[
  {
    "path": ".circleci/config.yml",
    "content": "version: 2.1\n\ncommands:\n  submodules:\n    steps:\n      - run:\n          name: \"Pull submodules\"\n          command: git submodule update --init\n  llvm-source-linux:\n    steps:\n      - restore_cache:\n          keys:\n            - llvm-source-19-v1\n      - run:\n          name: \"Fetch LLVM source\"\n          command: make llvm-source\n      - save_cache:\n          key: llvm-source-19-v1\n          paths:\n            - llvm-project/clang/lib/Headers\n            - llvm-project/clang/include\n            - llvm-project/compiler-rt\n            - llvm-project/lld/include\n            - llvm-project/llvm/include\n  hack-ninja-jobs:\n    steps:\n      - run:\n          name: \"Hack Ninja to use less jobs\"\n          command: |\n            echo -e '#!/bin/sh\\n/usr/bin/ninja -j3 \"$@\"' > /go/bin/ninja\n            chmod +x /go/bin/ninja\n  build-binaryen-linux:\n    steps:\n      - restore_cache:\n          keys:\n            - binaryen-linux-v3\n      - run:\n          name: \"Build Binaryen\"\n          command: |\n            make binaryen\n      - save_cache:\n          key: binaryen-linux-v3\n          paths:\n            - build/wasm-opt\n  test-linux:\n    parameters:\n      llvm:\n        type: string\n      fmt-check:\n        type: boolean\n        default: true\n    steps:\n      - checkout\n      - submodules\n      - run:\n          name: \"Install apt dependencies\"\n          command: |\n            echo 'deb https://apt.llvm.org/bullseye/ llvm-toolchain-bullseye-<<parameters.llvm>> main' > /etc/apt/sources.list.d/llvm.list\n            wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -\n            apt-get update\n            apt-get install --no-install-recommends -y \\\n                llvm-<<parameters.llvm>>-dev \\\n                clang-<<parameters.llvm>> \\\n                libclang-<<parameters.llvm>>-dev \\\n                lld-<<parameters.llvm>> \\\n                cmake \\\n                ninja-build\n      - hack-ninja-jobs\n      - build-binaryen-linux\n      - restore_cache:\n          keys:\n            - go-cache-v4-{{ checksum \"go.mod\" }}-{{ .Environment.CIRCLE_PREVIOUS_BUILD_NUM }}\n            - go-cache-v4-{{ checksum \"go.mod\" }}\n      - llvm-source-linux\n      - run: go install -tags=llvm<<parameters.llvm>> .\n      - when:\n          condition: <<parameters.fmt-check>>\n          steps:\n          - run:\n              # Do this before gen-device so that it doesn't check the\n              # formatting of generated files.\n              name: Check Go code formatting\n              command: make fmt-check lint\n      - run: make gen-device -j4\n      # TODO: change this to -skip='TestErrors|TestWasm' with Go 1.20\n      - run: go test -tags=llvm<<parameters.llvm>> -short -run='TestBuild|TestTest|TestGetList|TestTraceback'\n      - run: make smoketest XTENSA=0\n      - save_cache:\n          key: go-cache-v4-{{ checksum \"go.mod\" }}-{{ .Environment.CIRCLE_BUILD_NUM }}\n          paths:\n            - ~/.cache/go-build\n            - /go/pkg/mod\n\njobs:\n  test-oldest:\n    # This tests our lowest supported versions of Go and LLVM, to make sure at\n    # least the smoke tests still pass.\n    docker:\n      - image: golang:1.22-bullseye\n    steps:\n      - test-linux:\n          llvm: \"15\"\n    resource_class: large\n  test-newest:\n    # This tests the latest supported LLVM version when linking against system\n    # libraries.\n    docker:\n      - image: golang:1.25-bullseye\n    steps:\n      - test-linux:\n          llvm: \"20\"\n    resource_class: large\n\nworkflows:\n  test-all:\n    jobs:\n      - test-oldest\n      # disable this test, since CircleCI seems unable to download due to rate-limits on Dockerhub.\n      # - test-newest\n"
  },
  {
    "path": ".dockerignore",
    "content": "build/\nllvm-*/\n.github\n.circleci\n\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\nopen_collective: tinygo\n"
  },
  {
    "path": ".github/workflows/build-macos.yml",
    "content": "name: macOS\n\non:\n  pull_request:\n  push:\n    branches:\n      - dev\n      - release\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build-macos:\n    name: build-macos\n    strategy:\n      matrix:\n        # macos-14: arm64 (oldest supported version as of 18-11-2025)\n        # macos-15-intel: amd64 (last intel version to be supported by github runners)\n        # See https://github.com/actions/runner-images/issues/13046\n        os: [macos-14, macos-15-intel]\n        include:\n          - os: macos-14\n            goarch: arm64\n          - os: macos-15-intel\n            goarch: amd64\n    runs-on: ${{ matrix.os }}\n    steps:\n      - name: Install Dependencies\n        run: |\n          HOMEBREW_NO_AUTO_UPDATE=1 brew install qemu binaryen\n      - name: Checkout\n        uses: actions/checkout@v5\n        with:\n          submodules: true\n      - name: Extract TinyGo version\n        id: version\n        run: ./.github/workflows/tinygo-extract-version.sh | tee -a \"$GITHUB_OUTPUT\"\n      - name: Install Go\n        uses: actions/setup-go@v6\n        with:\n          go-version: '1.25.5'\n          cache: true\n      - name: Restore LLVM source cache\n        uses: actions/cache/restore@v4\n        id: cache-llvm-source\n        with:\n          key: llvm-source-20-${{ matrix.os }}-v1\n          path: |\n            llvm-project/clang/lib/Headers\n            llvm-project/clang/include\n            llvm-project/compiler-rt\n            llvm-project/lld/include\n            llvm-project/llvm/include\n      - name: Download LLVM source\n        if: steps.cache-llvm-source.outputs.cache-hit != 'true'\n        run: make llvm-source\n      - name: Save LLVM source cache\n        uses: actions/cache/save@v4\n        if: steps.cache-llvm-source.outputs.cache-hit != 'true'\n        with:\n          key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}\n          path: |\n            llvm-project/clang/lib/Headers\n            llvm-project/clang/include\n            llvm-project/compiler-rt\n            llvm-project/lld/include\n            llvm-project/llvm/include\n      - name: Restore LLVM build cache\n        uses: actions/cache/restore@v4\n        id: cache-llvm-build\n        with:\n          key: llvm-build-20-${{ matrix.os }}-v2\n          path: llvm-build\n      - name: Build LLVM\n        if: steps.cache-llvm-build.outputs.cache-hit != 'true'\n        run: |\n          # fetch LLVM source\n          rm -rf llvm-project\n          make llvm-source\n          # install dependencies\n          HOMEBREW_NO_AUTO_UPDATE=1 brew install ninja\n          # build!\n          make llvm-build\n          find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \\;\n      - name: Save LLVM build cache\n        uses: actions/cache/save@v4\n        if: steps.cache-llvm-build.outputs.cache-hit != 'true'\n        with:\n          key: ${{ steps.cache-llvm-build.outputs.cache-primary-key }}\n          path: llvm-build\n      - name: make gen-device\n        run: make -j3 gen-device\n      - name: Test TinyGo\n        run: make test GOTESTFLAGS=\"-only-current-os\"\n      - name: Build TinyGo release tarball\n        run: make release -j3\n      - name: Test stdlib packages\n        run: make tinygo-test\n      - name: Make release artifact\n        run: cp -p build/release.tar.gz build/tinygo${{ steps.version.outputs.version }}.darwin-${{ matrix.goarch }}.tar.gz\n      - name: Publish release artifact\n        # Note: this release artifact is double-zipped, see:\n        # https://github.com/actions/upload-artifact/issues/39\n        # We can essentially pick one of these:\n        # - have a double-zipped artifact when downloaded from the UI\n        # - have a very slow artifact upload\n        # We're doing the former here, to keep artifact uploads fast.\n        uses: actions/upload-artifact@v4\n        with:\n          name: darwin-${{ matrix.goarch }}-double-zipped-${{ steps.version.outputs.version }}\n          path: build/tinygo${{ steps.version.outputs.version }}.darwin-${{ matrix.goarch }}.tar.gz\n      - name: Smoke tests\n        run: make smoketest TINYGO=$(PWD)/build/tinygo\n  test-macos-homebrew:\n    name: homebrew-install\n    runs-on: macos-latest\n    strategy:\n      matrix:\n        version: [16, 17, 18, 19, 20]\n    steps:\n      - name: Set up Homebrew\n        uses: Homebrew/actions/setup-homebrew@master\n      - name: Fix Python symlinks\n        run: |\n          # Github runners have broken symlinks, so relink\n          # see: https://github.com/actions/setup-python/issues/577\n          brew list -1 | grep python | while read formula; do brew unlink $formula; brew link --overwrite $formula; done\n      - name: Install LLVM\n        run: |\n          brew install llvm@${{ matrix.version }}\n      - name: Checkout\n        uses: actions/checkout@v5\n      - name: Install Go\n        uses: actions/setup-go@v6\n        with:\n          go-version: '1.25.5'\n          cache: true\n      - name: Build TinyGo (LLVM ${{ matrix.version }})\n        run: go install -tags=llvm${{ matrix.version }}\n      - name: Check binary\n        run: tinygo version\n      - name: Build TinyGo (default LLVM)\n        if: matrix.version == 20\n        run: go install\n      - name: Check binary\n        if: matrix.version == 20\n        run: tinygo version\n"
  },
  {
    "path": ".github/workflows/docker.yml",
    "content": "# This is the Github action to build and push the tinygo/tinygo-dev Docker image.\n# If you are looking for the tinygo/tinygo \"release\" Docker image please see\n# https://github.com/tinygo-org/docker\n#\nname: Docker\non:\n  push:\n    branches: [ dev, fix-docker-llvm-build ]\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  push_to_registry:\n    name: build-push-dev\n    runs-on: ubuntu-latest\n    permissions:\n      packages: write\n      contents: read\n    steps:\n      - name: Free Disk space\n        shell: bash\n        run: |\n          df -h\n          sudo rm -rf /opt/hostedtoolcache\n          sudo rm -rf /usr/local/lib/android\n          sudo rm -rf /usr/share/dotnet\n          sudo rm -rf /opt/ghc\n          sudo rm -rf /usr/local/graalvm\n          sudo rm -rf /usr/local/share/boost\n          df -h\n      - name: Check out the repo\n        uses: actions/checkout@v5\n        with:\n          submodules: recursive\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n      - name: Docker meta\n        id: meta\n        uses: docker/metadata-action@v5\n        with:\n          images: |\n            tinygo/tinygo-dev\n            ghcr.io/${{ github.repository_owner }}/tinygo-dev\n          tags: |\n            type=sha,format=long\n            type=raw,value=latest\n      - name: Log in to Docker Hub\n        uses: docker/login-action@v3\n        with:\n          username: ${{ secrets.DOCKER_HUB_USERNAME }}\n          password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}\n      - name: Log in to Github Container Registry\n        uses: docker/login-action@v3\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n      - name: Build and push\n        uses: docker/build-push-action@v6\n        with:\n          context: .\n          push: true\n          tags: ${{ steps.meta.outputs.tags }}\n          labels: ${{ steps.meta.outputs.labels }}\n          cache-from: type=gha\n          cache-to: type=gha,mode=max\n"
  },
  {
    "path": ".github/workflows/linux.yml",
    "content": "name: Linux\n\non:\n  pull_request:\n  push:\n    branches:\n      - dev\n      - release\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build-linux:\n    # Build Linux binaries, ready for release.\n    # This runs inside an Alpine Linux container so we can more easily create a\n    # statically linked binary.\n    runs-on: ubuntu-latest\n    container:\n      image: golang:1.25-alpine\n    outputs:\n      version: ${{ steps.version.outputs.version }}\n    steps:\n      - name: Install apk dependencies\n        # tar: needed for actions/cache@v4\n        # git+openssh: needed for checkout (I think?)\n        # ruby: needed to install fpm\n        run: apk add tar git openssh make g++ ruby-dev mold\n      - name: Work around CVE-2022-24765\n        # We're not on a multi-user machine, so this is safe.\n        run: git config --global --add safe.directory \"$GITHUB_WORKSPACE\"\n      - name: Checkout\n        uses: actions/checkout@v5\n        with:\n          submodules: true\n      - name: Extract TinyGo version\n        id: version\n        run: ./.github/workflows/tinygo-extract-version.sh | tee -a \"$GITHUB_OUTPUT\"\n      - name: Cache Go\n        uses: actions/cache@v4\n        with:\n          key: go-cache-linux-alpine-v1-${{ hashFiles('go.mod') }}\n          path: |\n            ~/.cache/go-build\n            ~/go/pkg/mod\n      - name: Restore LLVM source cache\n        uses: actions/cache/restore@v4\n        id: cache-llvm-source\n        with:\n          key: llvm-source-20-linux-alpine-v1\n          path: |\n            llvm-project/clang/lib/Headers\n            llvm-project/clang/include\n            llvm-project/compiler-rt\n            llvm-project/lld/include\n            llvm-project/llvm/include\n      - name: Download LLVM source\n        if: steps.cache-llvm-source.outputs.cache-hit != 'true'\n        run: make llvm-source\n      - name: Save LLVM source cache\n        uses: actions/cache/save@v4\n        if: steps.cache-llvm-source.outputs.cache-hit != 'true'\n        with:\n          key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}\n          path: |\n            llvm-project/clang/lib/Headers\n            llvm-project/clang/include\n            llvm-project/compiler-rt\n            llvm-project/lld/include\n            llvm-project/llvm/include\n      - name: Restore LLVM build cache\n        uses: actions/cache/restore@v4\n        id: cache-llvm-build\n        with:\n          key: llvm-build-20-linux-alpine-v1\n          path: llvm-build\n      - name: Build LLVM\n        if: steps.cache-llvm-build.outputs.cache-hit != 'true'\n        run: |\n          # fetch LLVM source\n          rm -rf llvm-project\n          make llvm-source\n          # install dependencies\n          apk add cmake samurai python3\n          # build!\n          make llvm-build\n          # Remove unnecessary object files (to reduce cache size).\n          find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \\;\n      - name: Save LLVM build cache\n        uses: actions/cache/save@v4\n        if: steps.cache-llvm-build.outputs.cache-hit != 'true'\n        with:\n          key: ${{ steps.cache-llvm-build.outputs.cache-primary-key }}\n          path: llvm-build\n      - name: Cache Binaryen\n        uses: actions/cache@v4\n        id: cache-binaryen\n        with:\n          key: binaryen-linux-alpine-v1\n          path: build/wasm-opt\n      - name: Build Binaryen\n        if: steps.cache-binaryen.outputs.cache-hit != 'true'\n        run: |\n          apk add cmake samurai python3\n          make binaryen STATIC=1\n      - name: Install fpm\n        run: |\n          gem install --version 4.0.7 public_suffix\n          gem install --version 2.7.6 dotenv\n          gem install --no-document fpm\n      - name: Run linter\n        run: make lint\n      - name: Run spellcheck\n        run: make spell\n      - name: Build TinyGo release\n        run: |\n          make release deb -j3 STATIC=1\n          cp -p build/release.tar.gz /tmp/tinygo${{ steps.version.outputs.version }}.linux-amd64.tar.gz\n          cp -p build/release.deb    /tmp/tinygo_${{ steps.version.outputs.version }}_amd64.deb\n      - name: Publish release artifact\n        uses: actions/upload-artifact@v4\n        with:\n          name: linux-amd64-double-zipped-${{ steps.version.outputs.version }}\n          path: |\n            /tmp/tinygo${{ steps.version.outputs.version }}.linux-amd64.tar.gz\n            /tmp/tinygo_${{ steps.version.outputs.version }}_amd64.deb\n  test-linux-build:\n    # Test the binaries built in the build-linux job by running the smoke tests.\n    runs-on: ubuntu-latest\n    needs: build-linux\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v5\n        with:\n          submodules: true\n      - name: Install Go\n        uses: actions/setup-go@v6\n        with:\n          go-version: '1.25.5'\n          cache: true\n      - name: Install wasmtime\n        uses: bytecodealliance/actions/wasmtime/setup@v1\n        with:\n          version: \"29.0.1\"\n      - name: Install wasm-tools\n        uses: bytecodealliance/actions/wasm-tools/setup@v1\n      - name: Download release artifact\n        uses: actions/download-artifact@v4\n        with:\n          name: linux-amd64-double-zipped-${{ needs.build-linux.outputs.version }}\n      - name: Extract release tarball\n        run: |\n          mkdir -p ~/lib\n          tar -C ~/lib -xf tinygo${{ needs.build-linux.outputs.version }}.linux-amd64.tar.gz\n          ln -s ~/lib/tinygo/bin/tinygo ~/go/bin/tinygo\n      - run: make tinygo-test-wasip1-fast\n      - run: make tinygo-test-wasip2-fast\n      - run: make tinygo-test-wasm\n      - run: make smoketest\n  assert-test-linux:\n    # Run all tests that can run on Linux, with LLVM assertions enabled to catch\n    # potential bugs.\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v5\n        with:\n          submodules: true\n      - name: Install apt dependencies\n        run: |\n          echo \"Show cpuinfo; sometimes useful when troubleshooting\"\n          cat /proc/cpuinfo\n          sudo apt-get update\n          sudo apt-get install --no-install-recommends \\\n              qemu-system-arm \\\n              qemu-system-riscv32 \\\n              qemu-user \\\n              simavr \\\n              ninja-build\n      - name: Install Go\n        uses: actions/setup-go@v6\n        with:\n          go-version: '1.25.5'\n          cache: true\n      - name: Install Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: '18'\n      - name: Install wasmtime\n        uses: bytecodealliance/actions/wasmtime/setup@v1\n        with:\n          version: \"29.0.1\"\n      - name: Setup `wasm-tools`\n        uses: bytecodealliance/actions/wasm-tools/setup@v1\n      - name: Restore LLVM source cache\n        uses: actions/cache/restore@v4\n        id: cache-llvm-source\n        with:\n          key: llvm-source-20-linux-asserts-v1\n          path: |\n            llvm-project/clang/lib/Headers\n            llvm-project/clang/include\n            llvm-project/compiler-rt\n            llvm-project/lld/include\n            llvm-project/llvm/include\n      - name: Download LLVM source\n        if: steps.cache-llvm-source.outputs.cache-hit != 'true'\n        run: make llvm-source\n      - name: Save LLVM source cache\n        uses: actions/cache/save@v4\n        if: steps.cache-llvm-source.outputs.cache-hit != 'true'\n        with:\n          key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}\n          path: |\n            llvm-project/clang/lib/Headers\n            llvm-project/clang/include\n            llvm-project/compiler-rt\n            llvm-project/lld/include\n            llvm-project/llvm/include\n      - name: Restore LLVM build cache\n        uses: actions/cache/restore@v4\n        id: cache-llvm-build\n        with:\n          key: llvm-build-20-linux-asserts-v1\n          path: llvm-build\n      - name: Build LLVM\n        if: steps.cache-llvm-build.outputs.cache-hit != 'true'\n        run: |\n          # fetch LLVM source\n          rm -rf llvm-project\n          make llvm-source\n          # build!\n          make llvm-build ASSERT=1\n          # Remove unnecessary object files (to reduce cache size).\n          find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \\;\n      - name: Save LLVM build cache\n        uses: actions/cache/save@v4\n        if: steps.cache-llvm-build.outputs.cache-hit != 'true'\n        with:\n          key: ${{ steps.cache-llvm-build.outputs.cache-primary-key }}\n          path: llvm-build\n      - name: Cache Binaryen\n        uses: actions/cache@v4\n        id: cache-binaryen\n        with:\n          key: binaryen-linux-asserts-v1\n          path: build/wasm-opt\n      - name: Build Binaryen\n        if: steps.cache-binaryen.outputs.cache-hit != 'true'\n        run: make binaryen\n      - run: make gen-device -j4\n      - name: Test TinyGo\n        run: make ASSERT=1 test\n      - name: Build TinyGo\n        run: |\n          make ASSERT=1\n          echo \"$(pwd)/build\" >> $GITHUB_PATH\n      - name: Test stdlib packages\n        run: make tinygo-test\n      - run: make smoketest\n      - run: make wasmtest\n      - run: make tinygo-test-baremetal\n  build-linux-cross:\n    # Build ARM Linux binaries, ready for release.\n    # This intentionally uses an older Linux image, so that we compile against\n    # an older glibc version and therefore are compatible with a wide range of\n    # Linux distributions.\n    # It is set to \"needs: build-linux\" because it modifies the release created\n    # in that process to avoid doing lots of duplicate work and to avoid\n    # complications around precompiled libraries such as compiler-rt shipped as\n    # part of the release tarball.\n    strategy:\n      matrix:\n        goarch: [ arm, arm64 ]\n        include:\n          - goarch: arm64\n            toolchain: aarch64-linux-gnu\n            libc: arm64\n          - goarch: arm\n            toolchain: arm-linux-gnueabihf\n            libc: armhf\n    runs-on: ubuntu-22.04 # note: use the oldest image available! (see above)\n    needs: build-linux\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v5\n      - name: Get TinyGo version\n        id: version\n        run: ./.github/workflows/tinygo-extract-version.sh | tee -a \"$GITHUB_OUTPUT\"\n      - name: Install apt dependencies\n        run: |\n          sudo apt-get update\n          sudo apt-get install --no-install-recommends \\\n              qemu-user \\\n              g++-${{ matrix.toolchain }} \\\n              libc6-dev-${{ matrix.libc }}-cross\n      - name: Install Go\n        uses: actions/setup-go@v6\n        with:\n          go-version: '1.25.5'\n          cache: true\n      - name: Restore LLVM source cache\n        uses: actions/cache/restore@v4\n        id: cache-llvm-source\n        with:\n          key: llvm-source-20-linux-v1\n          path: |\n            llvm-project/clang/lib/Headers\n            llvm-project/clang/include\n            llvm-project/compiler-rt\n            llvm-project/lld/include\n            llvm-project/llvm/include\n      - name: Download LLVM source\n        if: steps.cache-llvm-source.outputs.cache-hit != 'true'\n        run: make llvm-source\n      - name: Save LLVM source cache\n        uses: actions/cache/save@v4\n        if: steps.cache-llvm-source.outputs.cache-hit != 'true'\n        with:\n          key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}\n          path: |\n            llvm-project/clang/lib/Headers\n            llvm-project/clang/include\n            llvm-project/compiler-rt\n            llvm-project/lld/include\n            llvm-project/llvm/include\n      - name: Restore LLVM build cache\n        uses: actions/cache/restore@v4\n        id: cache-llvm-build\n        with:\n          key: llvm-build-20-linux-${{ matrix.goarch }}-v1\n          path: llvm-build\n      - name: Build LLVM\n        if: steps.cache-llvm-build.outputs.cache-hit != 'true'\n        run: |\n          # fetch LLVM source\n          rm -rf llvm-project\n          make llvm-source\n          # Install build dependencies.\n          sudo apt-get install --no-install-recommends ninja-build\n          # build!\n          make llvm-build CROSS=${{ matrix.toolchain }}\n          # Remove unnecessary object files (to reduce cache size).\n          find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \\;\n      - name: Save LLVM build cache\n        uses: actions/cache/save@v4\n        if: steps.cache-llvm-build.outputs.cache-hit != 'true'\n        with:\n          key: ${{ steps.cache-llvm-build.outputs.cache-primary-key }}\n          path: llvm-build\n      - name: Cache Binaryen\n        uses: actions/cache@v4\n        id: cache-binaryen\n        with:\n          key: binaryen-linux-${{ matrix.goarch }}-v4\n          path: build/wasm-opt\n      - name: Build Binaryen\n        if: steps.cache-binaryen.outputs.cache-hit != 'true'\n        run: |\n          sudo apt-get install --no-install-recommends ninja-build\n          git submodule update --init lib/binaryen\n          make CROSS=${{ matrix.toolchain }} binaryen\n      - name: Install fpm\n        run: |\n          sudo gem install --version 4.0.7 public_suffix\n          sudo gem install --version 2.7.6 dotenv\n          sudo gem install --no-document fpm\n      - name: Build TinyGo binary\n        run: |\n          make CROSS=${{ matrix.toolchain }}\n      - name: Download amd64 release\n        uses: actions/download-artifact@v4\n        with:\n          name: linux-amd64-double-zipped-${{ needs.build-linux.outputs.version }}\n      - name: Extract amd64 release\n        run: |\n          mkdir -p build/release\n          tar -xf tinygo${{ needs.build-linux.outputs.version }}.linux-amd64.tar.gz -C build/release tinygo\n      - name: Modify release\n        run: |\n          cp -p build/tinygo   build/release/tinygo/bin\n          cp -p build/wasm-opt build/release/tinygo/bin\n      - name: Create ${{ matrix.goarch }} release\n        run: |\n          make release deb RELEASEONLY=1 DEB_ARCH=${{ matrix.libc }}\n          cp -p build/release.tar.gz /tmp/tinygo${{ steps.version.outputs.version }}.linux-${{ matrix.goarch }}.tar.gz\n          cp -p build/release.deb    /tmp/tinygo_${{ steps.version.outputs.version }}_${{ matrix.libc }}.deb\n      - name: Publish release artifact\n        uses: actions/upload-artifact@v4\n        with:\n          name: linux-${{ matrix.goarch }}-double-zipped-${{ steps.version.outputs.version }}\n          path: |\n            /tmp/tinygo${{ steps.version.outputs.version }}.linux-${{ matrix.goarch }}.tar.gz\n            /tmp/tinygo_${{ steps.version.outputs.version }}_${{ matrix.libc }}.deb\n"
  },
  {
    "path": ".github/workflows/llvm.yml",
    "content": "# This is the Github action to build and push the LLVM Docker image\n# used by the tinygo/tinygo-dev Docker image.\n#\n# It only needs to be rebuilt when updating the LLVM version.\n#\n# To update, make any needed changes to this file,\n# then push to the \"build-llvm-image\" branch.\n#\n# The needed image will be rebuilt, which will very likely take at least 1-2 hours.\nname: LLVM\non:\n  push:\n    branches: [ build-llvm-image ]\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build-push-llvm:\n    name: build-push-llvm\n    runs-on: ubuntu-latest\n    permissions:\n      packages: write\n      contents: read\n    steps:\n      - name: Check out the repo\n        uses: actions/checkout@v5\n        with:\n          submodules: recursive\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n      - name: Docker meta\n        id: meta\n        uses: docker/metadata-action@v5\n        with:\n          images: |\n            tinygo/llvm-20\n            ghcr.io/${{ github.repository_owner }}/llvm-20\n          tags: |\n            type=sha,format=long\n            type=raw,value=latest\n      - name: Log in to Docker Hub\n        uses: docker/login-action@v2\n        with:\n          username: ${{ secrets.DOCKER_HUB_USERNAME }}\n          password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}\n      - name: Log in to Github Container Registry\n        uses: docker/login-action@v3\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n      - name: Build and push\n        uses: docker/build-push-action@v6\n        with:\n          target: tinygo-llvm-build\n          context: .\n          push: true\n          tags: ${{ steps.meta.outputs.tags }}\n          labels: ${{ steps.meta.outputs.labels }}\n          cache-from: type=gha\n          cache-to: type=gha,mode=max\n"
  },
  {
    "path": ".github/workflows/nix.yml",
    "content": "name: Nix\n\non:\n  pull_request:\n  push:\n    branches:\n      - dev\n      - release\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  nix-test:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Uninstall system LLVM\n        # Hack to work around issue where we still include system headers for\n        # some reason.\n        # See: https://github.com/tinygo-org/tinygo/pull/4516#issuecomment-2416363668\n        run: sudo apt-get remove llvm-18\n      - name: Checkout\n        uses: actions/checkout@v5\n      - name: Pull musl, bdwgc\n        run: |\n            git submodule update --init lib/musl lib/bdwgc\n      - name: Restore LLVM source cache\n        uses: actions/cache/restore@v4\n        id: cache-llvm-source\n        with:\n          key: llvm-source-20-linux-nix-v1\n          path: |\n            llvm-project/compiler-rt\n      - name: Download LLVM source\n        if: steps.cache-llvm-source.outputs.cache-hit != 'true'\n        run: make llvm-source\n      - name: Save LLVM source cache\n        uses: actions/cache/save@v4\n        if: steps.cache-llvm-source.outputs.cache-hit != 'true'\n        with:\n          key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}\n          path: |\n            llvm-project/compiler-rt\n      - uses: cachix/install-nix-action@v22\n      - name: Test\n        run: |\n          nix develop --ignore-environment --keep HOME --command bash -c \"go install && ~/go/bin/tinygo version && ~/go/bin/tinygo build -o test ./testdata/cgo\"\n"
  },
  {
    "path": ".github/workflows/sizediff-install-pkgs.sh",
    "content": "# Command that's part of sizediff.yml. This is put in a separate file so that it\n# still works after checking out the dev branch (that is, when going from LLVM\n# 16 to LLVM 17 for example, both Clang 16 and Clang 17 are installed).\n\necho 'deb https://apt.llvm.org/noble/ llvm-toolchain-noble-20 main' | sudo tee /etc/apt/sources.list.d/llvm.list\nwget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -\nsudo apt-get update\nsudo apt-get install --no-install-recommends -y \\\n    llvm-20-dev \\\n    clang-20 \\\n    libclang-20-dev \\\n    lld-20\n"
  },
  {
    "path": ".github/workflows/sizediff.yml",
    "content": "name: Binary size difference\n\non:\n  pull_request:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  sizediff:\n    # Note: when updating the Ubuntu version, also update the Ubuntu version in\n    # sizediff-install-pkgs.sh\n    runs-on: ubuntu-24.04\n    permissions:\n      pull-requests: write\n    steps:\n      # Prepare, install tools\n      - name: Add GOBIN to $PATH\n        run: |\n          echo \"$HOME/go/bin\" >> $GITHUB_PATH\n      - name: Checkout\n        uses: actions/checkout@v5\n        with:\n          fetch-depth: 0 # fetch all history (no sparse checkout)\n          submodules: true\n      - name: Install apt dependencies\n        run: ./.github/workflows/sizediff-install-pkgs.sh\n      - name: Restore LLVM source cache\n        uses: actions/cache@v4\n        id: cache-llvm-source\n        with:\n          key: llvm-source-20-sizediff-v1\n          path: |\n            llvm-project/compiler-rt\n      - name: Download LLVM source\n        if: steps.cache-llvm-source.outputs.cache-hit != 'true'\n        run: make llvm-source\n      - name: Cache Go\n        uses: actions/cache@v4\n        with:\n          key: go-cache-linux-sizediff-v2-${{ hashFiles('go.mod') }}\n          path: |\n            ~/.cache/go-build\n            ~/go/pkg/mod\n      - run: make gen-device -j4\n      - name: Download drivers repo\n        run: git clone https://github.com/tinygo-org/drivers.git\n      - name: Save HEAD\n        run: git branch github-actions-saved-HEAD HEAD\n\n      # Compute sizes for the PR branch\n      - name: Build tinygo binary for the PR branch\n        run: go install\n      - name: Determine binary sizes on the PR branch\n        run: (cd drivers; make smoke-test XTENSA=0 | tee sizes-pr.txt)\n\n      # Compute sizes for the dev branch\n      - name: Checkout dev branch\n        run: |\n          git reset --hard origin/dev\n          git checkout --no-recurse-submodules `git merge-base HEAD origin/dev`\n      - name: Install apt dependencies on the dev branch\n        # this is only needed on a PR that changes the LLVM version\n        run: ./.github/workflows/sizediff-install-pkgs.sh\n      - name: Build tinygo binary for the dev branch\n        run: go install\n      - name: Determine binary sizes on the dev branch\n        run: (cd drivers; make smoke-test XTENSA=0 | tee sizes-dev.txt)\n\n      # Create comment\n      # TODO: add a summary, something like:\n      #  - overall size difference (percent)\n      #  - number of binaries that grew / shrank / remained the same\n      #  - don't show the full diff when no binaries changed\n      - name: Calculate size diff\n        run: ./tools/sizediff drivers/sizes-dev.txt drivers/sizes-pr.txt | tee sizediff.txt\n      - name: Create comment\n        run: |\n          echo \"Size difference with the dev branch:\" > comment.txt\n          echo \"<details><summary>Binary size difference</summary>\" >> comment.txt\n          echo \"<pre>\" >> comment.txt\n          cat sizediff.txt >> comment.txt\n          echo \"</pre></details>\" >> comment.txt\n      - name: Comment contents\n        run: cat comment.txt\n      - name: Add comment\n        if: ${{ github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name }}\n        uses: thollander/actions-comment-pull-request@v2.3.1\n        with:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          filePath: comment.txt\n          comment_tag: sizediff\n"
  },
  {
    "path": ".github/workflows/tinygo-extract-version.sh",
    "content": "#!/bin/sh\n\n# Extract the version string from the source code, to be stored in a variable.\ngrep 'const version' goenv/version.go | sed 's/^const version = \"\\(.*\\)\"$/version=\\1/g'\n"
  },
  {
    "path": ".github/workflows/windows.yml",
    "content": "name: Windows\n\non:\n  pull_request:\n  push:\n    branches:\n      - dev\n      - release\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build-windows:\n    runs-on: windows-2022\n    outputs:\n      version: ${{ steps.version.outputs.version }}\n    steps:\n      - name: Configure pagefile\n        uses: al-cheb/configure-pagefile-action@v1.4\n        with:\n          minimum-size: 8GB\n          maximum-size: 24GB\n          disk-root: \"C:\"\n      - uses: MinoruSekine/setup-scoop@v4\n        with:\n          scoop_update: 'false'\n      - name: Install Dependencies\n        shell: bash\n        run: |\n          scoop install ninja binaryen\n      - name: Checkout\n        uses: actions/checkout@v5\n        with:\n          submodules: true\n      - name: Extract TinyGo version\n        id: version\n        shell: bash\n        run: ./.github/workflows/tinygo-extract-version.sh | tee -a \"$GITHUB_OUTPUT\"\n      - name: Install Go\n        uses: actions/setup-go@v6\n        with:\n          go-version: '1.25.5'\n          cache: true\n      - name: Restore cached LLVM source\n        uses: actions/cache/restore@v4\n        id: cache-llvm-source\n        with:\n          key: llvm-source-20-windows-v1\n          path: |\n            llvm-project/clang/lib/Headers\n            llvm-project/clang/include\n            llvm-project/compiler-rt\n            llvm-project/lld/include\n            llvm-project/llvm/include\n      - name: Download LLVM source\n        if: steps.cache-llvm-source.outputs.cache-hit != 'true'\n        run: make llvm-source\n      - name: Save cached LLVM source\n        uses: actions/cache/save@v4\n        if: steps.cache-llvm-source.outputs.cache-hit != 'true'\n        with:\n          key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}\n          path: |\n            llvm-project/clang/lib/Headers\n            llvm-project/clang/include\n            llvm-project/compiler-rt\n            llvm-project/lld/include\n            llvm-project/llvm/include\n      - name: Restore cached LLVM build\n        uses: actions/cache/restore@v4\n        id: cache-llvm-build\n        with:\n          key: llvm-build-20-windows-v2\n          path: llvm-build\n      - name: Build LLVM\n        if: steps.cache-llvm-build.outputs.cache-hit != 'true'\n        shell: bash\n        run: |\n          # fetch LLVM source\n          rm -rf llvm-project\n          make llvm-source\n          # build!\n          make llvm-build CCACHE=OFF\n          # Remove unnecessary object files (to reduce cache size).\n          find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \\;\n      - name: Save cached LLVM build\n        uses: actions/cache/save@v4\n        if: steps.cache-llvm-build.outputs.cache-hit != 'true'\n        with:\n          key: ${{ steps.cache-llvm-build.outputs.cache-primary-key }}\n          path: llvm-build\n      - name: Cache Go cache\n        uses: actions/cache@v4\n        with:\n          key: go-cache-windows-v1-${{ hashFiles('go.mod') }}\n          path: |\n            C:/Users/runneradmin/AppData/Local/go-build\n            C:/Users/runneradmin/go/pkg/mod\n      - name: Install wasmtime\n        run: |\n          scoop install wasmtime@29.0.1\n      - name: make gen-device\n        run: make -j3 gen-device\n      - name: Test TinyGo\n        shell: bash\n        run: make test GOTESTFLAGS=\"-only-current-os\"\n      - name: Build TinyGo release tarball\n        shell: bash\n        run: make build/release -j4\n      - name: Make release artifact\n        shell: bash\n        working-directory: build/release\n        run: 7z -tzip a tinygo${{ steps.version.outputs.version }}.windows-amd64.zip tinygo\n      - name: Publish release artifact\n        # Note: this release artifact is double-zipped, see:\n        # https://github.com/actions/upload-artifact/issues/39\n        # We can essentially pick one of these:\n        # - have a dobule-zipped artifact when downloaded from the UI\n        # - have a very slow artifact upload\n        # We're doing the former here, to keep artifact uploads fast.\n        uses: actions/upload-artifact@v4\n        with:\n          name: windows-amd64-double-zipped-${{ steps.version.outputs.version }}\n          path: build/release/tinygo${{ steps.version.outputs.version }}.windows-amd64.zip\n\n  smoke-test-windows:\n    runs-on: windows-2022\n    needs: build-windows\n    steps:\n      - name: Configure pagefile\n        uses: al-cheb/configure-pagefile-action@v1.4\n        with:\n          minimum-size: 8GB\n          maximum-size: 24GB\n          disk-root: \"C:\"\n      - uses: MinoruSekine/setup-scoop@v4\n        with:\n          scoop_update: 'false'\n      - name: Install Dependencies\n        shell: bash\n        run: |\n          scoop install binaryen\n      - name: Checkout\n        uses: actions/checkout@v5\n      - name: Install Go\n        uses: actions/setup-go@v6\n        with:\n          go-version: '1.25.5'\n          cache: true\n      - name: Download TinyGo build\n        uses: actions/download-artifact@v4\n        with:\n          name: windows-amd64-double-zipped-${{ needs.build-windows.outputs.version }}\n          path: build/\n      - name: Unzip TinyGo build\n        shell: bash\n        working-directory: build\n        run: 7z x tinygo*.windows-amd64.zip -r\n      - name: Smoke tests\n        shell: bash\n        run: make smoketest TINYGO=$(PWD)/build/tinygo/bin/tinygo\n\n  stdlib-test-windows:\n    runs-on: windows-2022\n    needs: build-windows\n    steps:\n      - name: Configure pagefile\n        uses: al-cheb/configure-pagefile-action@v1.4\n        with:\n          minimum-size: 8GB\n          maximum-size: 24GB\n          disk-root: \"C:\"\n      - name: Checkout\n        uses: actions/checkout@v5\n      - name: Install Go\n        uses: actions/setup-go@v6\n        with:\n          go-version: '1.25.5'\n          cache: true\n      - name: Download TinyGo build\n        uses: actions/download-artifact@v4\n        with:\n          name: windows-amd64-double-zipped-${{ needs.build-windows.outputs.version }}\n          path: build/\n      - name: Unzip TinyGo build\n        shell: bash\n        working-directory: build\n        run: 7z x tinygo*.windows-amd64.zip -r\n      - name: Test stdlib packages\n        run: make tinygo-test TINYGO=$(PWD)/build/tinygo/bin/tinygo\n\n  stdlib-wasi-test-windows:\n    runs-on: windows-2022\n    needs: build-windows\n    steps:\n      - name: Configure pagefile\n        uses: al-cheb/configure-pagefile-action@v1.4\n        with:\n          minimum-size: 8GB\n          maximum-size: 24GB\n          disk-root: \"C:\"\n      - uses: MinoruSekine/setup-scoop@v4\n        with:\n          scoop_update: 'false'\n      - name: Install Dependencies\n        shell: bash\n        run: |\n          scoop install binaryen && scoop install wasmtime@29.0.1\n      - name: Checkout\n        uses: actions/checkout@v5\n      - name: Install Go\n        uses: actions/setup-go@v6\n        with:\n          go-version: '1.25.5'\n          cache: true\n      - name: Download TinyGo build\n        uses: actions/download-artifact@v4\n        with:\n          name: windows-amd64-double-zipped-${{ needs.build-windows.outputs.version }}\n          path: build/\n      - name: Unzip TinyGo build\n        shell: bash\n        working-directory: build\n        run: 7z x tinygo*.windows-amd64.zip -r\n      - name: Test stdlib packages on wasip1\n        run: make tinygo-test-wasip1-fast TINYGO=$(PWD)/build/tinygo/bin/tinygo\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\n.vscode\ngo.work\ngo.work.sum\n\ndocs/_build\nsrc/device/avr/*.go\nsrc/device/avr/*.ld\nsrc/device/avr/*.s\nsrc/device/esp/*.go\nsrc/device/nrf/*.go\nsrc/device/nrf/*.s\nsrc/device/nxp/*.go\nsrc/device/nxp/*.s\nsrc/device/sam/*.go\nsrc/device/sam/*.s\nsrc/device/sifive/*.go\nsrc/device/sifive/*.s\nsrc/device/stm32/*.go\nsrc/device/stm32/*.s\nsrc/device/kendryte/*.go\nsrc/device/kendryte/*.s\nsrc/device/renesas/*.go\nsrc/device/renesas/*.s\nsrc/device/rp/*.go\nsrc/device/rp/*.s\n./vendor\nllvm-build\nllvm-project\nbuild/*\n\n# Ignore files generated by smoketest\ntest\ntest.bin\ntest.elf\ntest.exe\ntest.gba\ntest.hex\ntest.nro\ntest.uf2\ntest.wasm\nwasm.wasm\n\n*.uf2\n*.elf"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"lib/nrfx\"]\n\tpath = lib/nrfx\n\turl = https://github.com/NordicSemiconductor/nrfx.git\n[submodule \"lib/CMSIS\"]\n\tpath = lib/CMSIS\n\turl = https://github.com/ARM-software/CMSIS.git\n[submodule \"lib/avr\"]\n\tpath = lib/avr\n\turl = https://github.com/avr-rust/avr-mcu.git\n[submodule \"lib/cmsis-svd\"]\n\tpath = lib/cmsis-svd\n\turl = https://github.com/cmsis-svd/cmsis-svd-data.git\n\tbranch = main\n[submodule \"lib/wasi-libc\"]\n\tpath = lib/wasi-libc\n\turl = https://github.com/WebAssembly/wasi-libc\n[submodule \"lib/picolibc\"]\n\tpath = lib/picolibc\n\turl = https://github.com/picolibc/picolibc.git\n[submodule \"lib/stm32-svd\"]\n\tpath = lib/stm32-svd\n\turl = https://github.com/tinygo-org/stm32-svd\n[submodule \"lib/musl\"]\n\tpath = lib/musl\n\turl = https://github.com/tinygo-org/musl-libc.git\n[submodule \"lib/binaryen\"]\n\tpath = lib/binaryen\n\turl = https://github.com/WebAssembly/binaryen.git\n[submodule \"lib/mingw-w64\"]\n\tpath = lib/mingw-w64\n\turl = https://github.com/mingw-w64/mingw-w64.git\n[submodule \"lib/macos-minimal-sdk\"]\n\tpath = lib/macos-minimal-sdk\n\turl = https://github.com/aykevl/macos-minimal-sdk.git\n[submodule \"src/net\"]\n\tpath = src/net\n\turl = https://github.com/tinygo-org/net.git\n[submodule \"lib/wasi-cli\"]\n\tpath = lib/wasi-cli\n\turl = https://github.com/WebAssembly/wasi-cli\n[submodule \"lib/bdwgc\"]\n\tpath = lib/bdwgc\n\turl = https://github.com/ivmai/bdwgc.git\n"
  },
  {
    "path": "BUILDING.md",
    "content": "# Building TinyGo\n\nTinyGo depends on LLVM and libclang, which are both big C++ libraries. It can\nalso optionally use a built-in lld to ease cross compiling. There are two ways\nthese can be linked: dynamically and statically. An install with `go install` is\ndynamic linking because it is fast and works almost out of the box on\nDebian-based systems with the right packages installed.\n\nThis guide describes how to statically link TinyGo against LLVM, libclang and\nlld so that the binary can be easily moved between systems. It also shows how to\nbuild a release tarball that includes this binary and all necessary extra files.\n\n**Note**: this documentation describes how to build a statically linked release\ntarball. If you want to help with development of TinyGo itself, you should follow the guide located at https://tinygo.org/docs/guides/build/\n\n## Dependencies\n\nLLVM, Clang and LLD are quite light on dependencies, requiring only standard\nbuild tools to be built. Go is of course necessary to build TinyGo itself.\n\n  * Go (1.19+)\n  * GNU Make\n  * Standard build tools (gcc/clang)\n  * git\n  * CMake\n  * [Ninja](https://ninja-build.org/)\n\nThe rest of this guide assumes you're running Linux, but it should be equivalent\non a different system like Mac.\n\n## Using GNU Make\n\nThe static build of TinyGo is driven by GNUmakefile, which provides a help target for quick reference:\n\n    % make help\n    clean                           Remove build directory\n    fmt                             Reformat source\n    fmt-check                       Warn if any source needs reformatting\n    gen-device                      Generate microcontroller-specific sources\n    llvm-source                     Get LLVM sources\n    llvm-build                      Build LLVM\n    tinygo                          Build the TinyGo compiler\n    lint                            Lint source tree\n    spell                           Spellcheck source tree\n\n## Download the source\n\nThe first step is to download the TinyGo sources (use `--recursive` if you clone\nthe git repository). Then, inside the directory, download the LLVM source:\n\n    make llvm-source\n\nYou can also store LLVM outside of the TinyGo root directory by setting the\n`LLVM_BUILDDIR`, `CLANG_SRC` and `LLD_SRC` make variables, but that is not\ncovered by this guide.\n\n## Build LLVM, Clang, LLD\n\nBefore starting the build, you may want to set the following environment\nvariables to speed up the build. Most Linux distributions ship with GCC as the\ndefault compiler, but Clang is significantly faster and uses much less memory\nwhile producing binaries that are about as fast.\n\n    export CC=clang\n    export CXX=clang++\n\nThe Makefile includes a default configuration that is good for most users. It\nbuilds a release version of LLVM (optimized, no asserts) and includes all\ntargets supported by TinyGo:\n\n    make llvm-build\n\nThis can take over an hour depending on the speed of your system.\n\n## Build TinyGo\n\nThe last step of course is to build TinyGo itself. This can again be done with\nmake:\n\n    make\n\n## Verify TinyGo\n\nTry running TinyGo:\n\n    ./build/tinygo help\n\nAlso, make sure the `tinygo` binary really is statically linked. The command to check for \ndynamic dependencies differs depending on your operating system.\n\nOn Linux, use `ldd` (not to be confused with `lld`):\n\n    ldd ./build/tinygo\n\nOn macOS, use otool -L:\n\n    otool -L ./build/tinygo\n\nThe result should not contain libclang or libLLVM.\n\n## Make a release tarball\n\nNow that we have a working static build, it's time to make a release tarball:\n\n    make release\n\nIf you did not clone the repository with the `--recursive` option, you will get errors until you initialize the project submodules:\n\n    git submodule update --init\n\nThe release tarball is stored in build/release.tar.gz, and can be extracted with\nthe following command (for example in ~/lib):\n\n    tar -xvf path/to/release.tar.gz\n\nTinyGo will get extracted to a `tinygo` directory. You can then call it with:\n\n    ./tinygo/bin/tinygo\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "0.40.1\n---\n* **machine**\n  - nrf: fix flash writes when SoftDevice is enabled\n* **runtime**\n  - runtime: avoid fixed math/rand sequence on RP2040/RP2350 (#5124)\n  - runtime: add calls to initRand() during run() for all schedulers\n  - runtime: call initRand() before initHeap() during initialization\n  - runtime: use rand_hwrng hardwareRand for RP2040/RP2350 (#5135)\n* **libs**\n  - picolibc: use updated location for git repo\n\n0.40.0\n---\n* **general**\n  - all: add full LLVM 20 support\n  - core: feat: enable //go:linkname pragma for globals\n  - core: feature: Add flag to ignore go compatibility matrix (#5078)\n  - chore: update version for 0.40 development cycle\n* **compiler**\n  - emit an error when the actual arch doesn't match GOARCH\n  - mark string parameters as readonly\n  - use Tarjan's SCC algorithm to detect loops for defer\n  - lower \"large stack\" limit to 16kb\n* **core**\n  - shrink bdwgc library\n  - Fix linker errors for runtime.vgetrandom and crypto/internal/sysrand.fatal\n  - fix: add TryLock to sync.RWMutex\n  - fix: correct linter issues exposed by the fix in #4679\n  - fix: don't hardcode success return state\n  - fix: expand RTT debugger compatibility\n  - internal/task (threads): save stack bounds instead of scanning under a lock\n  - internal/task: create detached threads and fix error handling\n  - interp: better errors when debugging interp\n  - transform (gc): create stack slots in callers of external functions\n  - internal/task: prevent semaphore resource leak for threads scheduler\n* **machine**\n  - cortexm: optimize code size for the HardFault_Handler\n  - fe310: add I2C pins for the HiFive1b\n  - clarify WriteAt semantics of BlockDevice\n  - fix deprecated AsmFull comment (#5005)\n  - make sure DMA buffers do not escape unnecessarily\n  - only enable USB-CDC when needed\n  - use larger SPI MAXCNT on nrf52833 and nrf52840\n  - fix: update m.queuedBytes when clamping output to avoid corrupting sentBytes\n  - fix: use int64 in ReadTemperature to avoid overflow\n  - fix(rp2): disable DBGPAUSE on startup\n  - fix(rp2): possible integer overflow while computing factors for SPI baudrate\n  - fix(rp2): reset spinlocks at startup\n  - fix(rp2): switch spinlock busy loop to wfe\n  - fix(rp2): use side-effect-free spinlocks\n  - nrf: add ADC_VDDH which is an ADC pin for VDDH\n  - nrf: don't block SPI transfer\n  - nrf: don't set PSELN, it's ignored in single ended mode anyway\n  - nrf: fix typo in ADC configuration\n  - nrf: refactor SoftDevice enabled check\n  - nrf: rename pwmPin to adcPin\n  - nrf: support flash operations while the SoftDevice is enabled\n  - rp2040: allow writing to the UART inside interrupts\n  - machine,nrf528: stop the bus only once on I2C bus error and ensures the first error is returned\n* **net**\n  - update submodule to latest commits\n* **runtime**\n  - (avr): fix infinite longjmp loop if stack is aligned to 256 bytes\n  - (gc_blocks.go): clear full size of allocation\n  - (gc_blocks.go): make sweep branchless\n  - (gc_blocks.go): simplify scanning logic\n  - (gc_blocks.go): use a linked stack to scan marked objects\n  - (gc_blocks.go): use best-fit allocation\n  - (gc_boehm.go): fix world already stopped check\n  - (wasm): scan the system stack\n  - fix sleep duration for long sleeps\n  - remove copied code for nrf52840\n  - src/syscall: update src buffer after write\n  - wasm: fix C realloc and optimize it a bit\n* **targets**\n  - add xiao-esp32s3 board target\n  - Add ESP32-S3 support (#5091)\n  - Added Gopher ARCADE board\n  - Create \"pico2-ice\" target board (#5062)\n* **build/test**\n  - Add testing.T.Context() and testing.B.Context()\n  - create separate go.mod file for testing dependencies for wasm tests that use Chromium headless browser to avoid use of older incompatible version.\n  - go back to normal scheduler instead of tasks scheduler for macos CI\n  - update CI to use Go 1.25.5\n  - update macOS GH actions builds to handle sunset of macOS 13\n  - use task scheduler on macOS builds to avoid test race condition lockups\n  - update all CI builds to use latest stable Go release. Also update some of the actions to their latest releases.\n  - update GH actions builds to use Go 1.25.4\n  - uninstall cmake before install\n  - fix: point the submodule for musl-lib to a mirror in the TinyGo GitHub org\n  - fix: remove macOS 15 from CI build matrix (conflicts with macOS 14 build)\n  - fix: separate host expected bytes from device intended bytes\n  - fix/typo: makeESPFirmwareImage\n  - make: GNUmakefile: shrink TinyGo binaries on Linux\n  - move the directory list into a variable\n  - several improvements to the macOS GH actions build\n  - Fix for #4678: top-level 'make lint' wasn't working\n  - fix: increase the timeout for chromedp to connect to the headless browser used for running the wasm tests.\n  - testdata: some more packages for the test corpus\n\n0.39.0\n---\n* **general**\n  - all: add Go 1.25 support\n  - net: update to latest tinygo net package\n  - docs: clarify build verification step for macOS users\n  - Add flag to skip Renesas SVD builds\n* **build**\n  - Makefile: install missing dlmalloc files\n  - flash: add -o flag support to save built binary (Fixes #4937) (#4942)\n  - fix: update version of clang to 17 to accommodate latest Go 1.25 docker base image\n* **ci**\n  - chore: update all CI builds to test Go 1.25 release\n  - fix: disable test-newest since CircleCI seems unable to download due to rate-limits on Dockerhub\n  - ci: rename some jobs to avoid churn on every Go/LLVM version bump\n  - ci: make the goroutines test less racy\n  - tests: de-flake goroutines test\n* **compiler**\n  - compiler: implement internal/abi.Escape\n* **main**\n  - main: show the compiler error (if any) for `tinygo test -c`\n  - chore: correct GOOS=js name in error messages for WASM\n* **machine**\n  - machine: add international keys\n  - machine: remove some unnecessary \"// peripherals:\" comments\n  - machine: add I2C pin comments\n  - machine: standardize I2C errors with \"i2c:\" prefix\n  - machine: make I2C usable in the simulator\n  - fix: add SPI and I2C to teensy 4.1 (#4943)\n  - `rp2`: use the correct channel mask for rp2350 ADC; hold lock during read (#4938)\n  - `rp2`: disable digital input for analog inputs\n* **runtime**\n  - runtime: ensure time.Sleep(d) sleeps at least d\n  - runtime: stub out weak pointer support\n  - runtime: implement dummy AddCleanup\n  - runtime: enable multi-core scheduler for rp2350\n  - `internal/task`: use -stack-size flag when starting a new thread\n  - `internal/task`: add SA_RESTART flag to GC interrupts\n  - `internal/task`: a few small correctness fixes\n  - `internal/gclayout`: make gclayout values constants\n  - darwin: add threading support and use it by default\n* **standard library**\n  - `sync`: implement sync.Swap\n  - `reflect`: implement Method.IsExported\n* **testing**\n  - testing: stub out testing.B.Loop\n* **targets**\n  - `stm32`: add support for the STM32L031G6U6\n  - add metro-rp2350 board definition (#4989)\n  - `rp2040/rp2350`: set the default stack size to 8k for rp2040/rp2350 based boards where this was not already the case\n\n\n0.38.0\n---\n* **general**\n  - `go.*`: upgrade `golang.org/x/tools` to v0.30.0\n  - `all`: add support for LLVM 20\n* **build**\n  - go back to using MinoruSekine/setup-scoop for Windows CI builds\n  - `flake.*`: upgrade to nixpkgs 25.05, LLVM 20\n  - `Makefile`: only detect ccache command when needed\n  - `Makefile`: create random filename inside rule\n  - `Makefile`: don't set GOROOT\n  - `Makefile`: call uname at most once\n  - `Makefile`: only read NodeJS version when it is needed\n* **compiler**\n  - add support for `GODEBUG=gotypesalias=1`\n  - `interp`: fix `copy()` from/to external buffers\n  - add `-nobounds` (similar to `-gcflags=-B`)\n  - `compileopts`: add library version to cached library path\n  - `builder`: build wasi-libc inside TinyGo\n  - `builder`: simplify bdwgc libc dependency\n  - `builder`: don't use precompiled libraries\n  - `compileopts`: enable support for `GOARCH=wasm` in `tinygo test`\n* **fixes**\n  - `rp2350`: Fix DMA to SPI transmits on RP2350 (#4903)\n  - `microbit v2`: use OpenOCD flash method on microbit v2 when using Nordic Semi SoftDevice\n  - `main`: display all of the current GC options for the `-gc` flag\n  - Remove duplicated error handling\n  - `sync`: fix `TestMutexConcurrent` test\n  - fix race condition in `testdata/goroutines.go`\n  - fix build warnings on Windows ARM\n* **machine**\n  - `usb`: add USB mass storage class support\n  - implement usb receive message throttling\n  - declare usb endpoints per-platform\n  - `samd21`: implement watchdog\n  - `samd51`: write to flash memory in 512 byte long chunks\n  - `samd21`: write to flash memory in 64 byte long chunks\n  - don't inline RTT `WriteByte` everywhere\n  - `rp2`: unexport machine-specific errors\n  - `rp2`: discount scheduling delays in I2C timeouts (#4876)\n  - use pointer receiver in simulated PWM peripherals\n  - add simulated PWM/timer peripherals\n  - `rp2`: expose usb endpoint stall handling\n  - `arm`: clear pending interrupts before enabling them\n  - `rp2`: merge common usb code (#4856)\n* **main**\n  - add \"cores\" and \"threads\" schedulers to help text\n  - add `StartPos` and `EndPos` to `-json` build output\n  - change `-json` flag to match upstream Go\n* **runtime**\n  - don't lock the print output inside interrupts\n  - don't try to interrupt other cores before they are started\n  - implement `NumCPU` for the multicore scheduler\n  - add support for multicore scheduler\n  - refactor obtaining the system stack\n  - `interrupt`: add `Checkpoint` type\n  - add `exportedFuncPtr`\n  - avoid an allocation in `(*time.Timer).Reset`\n  - stub runtime signal functions for `os/signal` on wasip1\n  - move `timeUnit` to a single place\n  - implement `NumCPU` for `-scheduler=threads`\n  - move `mainExited` boolean\n  - `internal/task`: rename `tinygo_pause` to `tinygo_task_exit`\n  - map every goroutine to a new OS thread\n  - refactor `timerQueue`\n  - make conservative and precise GC MT-safe\n  - `internal/task`: implement atomic primitives for preemptive scheduling\n  - Use diskutil on macOS to extract volume name and path for FAT mounts #4928\n* **standard library**\n  - `net`: update submodule to latest commits\n  - `runtime/debug`: add GC related stubs\n  - `metrics`: flesh out some of the metric types\n  - `reflect`: Chan related stubs\n  - `os`: handle relative and abs paths in `Executable()`\n  - `os`: add `os.Executable()` for Darwin\n  - `sync`: implement `RWMutex` using futexes\n  - `reflect`: Add `SliceOf`, `ArrayOf`, `StructOf`, `MapOf`, `FuncOf`\n* **targets**\n  - `rp2040`: add multicore support\n  - `riscv32`: use `gdb` binary as a fallback\n  - add target for Microbit v2 with SoftDevice S140 support for both peripheral and central\n  - `windows`: use MSVCRT.DLL instead of UCRT on i386\n  - `windows`: add windows/386 support\n  - `arm64`: remove unnecessary `.section` directive\n  - `riscv-qemu`: actually sleep in `time.Sleep()`\n  - `riscv`: define CSR constants and use them where possible\n  - `darwin`: support Boehm GC (and use by default)\n  - `windows`: add support for the Boehm-Demers-Weiser GC\n  - `windows`: fix wrong register for first parameter\n* **wasm**\n  - add Boehm GC support\n  - refactor/modify stub signal handling\n  - don't block `//go:wasmexport` because of running goroutines\n  - use `int64` instead of `float64` for the `timeUnit`\n* **boards**\n  - Add board support for BigTreeTech SKR Pico (#4842)\n\n\n0.37.0\n---\n* **general**\n  - add the Boehm-Demers-Weiser GC on Linux\n* **ci**\n  - add more tests for wasm and baremetal\n* **compiler**\n  - crypto/internal/sysrand is allowed to use unsafe signatures\n* **examples**\n  - add goroutine benchmark to examples\n* **fixes**\n  - ensure use of pointers for SPI interface on atsam21/atsam51 and other machines/boards that were missing implementation (#4798)\n  - replace loop counter with hw timer for USB SetAddressReq on rp2040 (#4796)\n* **internal**\n  - update to go.bytecodealliance.org@v0.6.2 in GNUmakefile and internal/wasm-tools\n  - exclude certain files when copying package in internal/cm\n  - update to go.bytecodealliance.org/cm@v0.2.2 in internal/cm\n  - remove old reflect.go in internal/reflectlite\n* **loader**\n  - use build tags for package iter and iter methods on reflect.Value in loader, iter, reflect\n  - add shim for go1.22 and earlier in loader, iter\n* **machine**\n  - bump rp2040 to 200MHz (#4768)\n  - correct register address for Pin.SetInterrupt for rp2350 (#4782)\n  - don't block the rp2xxx UART interrupt handler\n  - fix RP2040 Pico board on the playground\n  - add flash support for rp2350 (#4803)\n* **os**\n  - add stub Symlink for wasm\n* **refactor**\n  - use *SPI everywhere to make consistent for implementations. Fixes #4663 \"in reverse\" by making SPI a pointer everywhere, as discussed in the comments.\n* **reflect**\n  - add Value.SetIter{Key,Value} and MapIter.Reset in reflect, internal/reflectlite\n  - embed reflectlite types into reflect types in reflect, internal/reflectlite\n  - add Go 1.24 iter.Seq[2] methods\n  - copy reflect iter tests from upstream Go\n  - panic on Type.CanSeq[2] instead of returning false\n  - remove strconv.go\n  - remove unused go:linkname functions\n* **riscv-qemu**\n  - add VirtIO RNG device\n  - increase stack size\n* **runtime**\n  - only allocate heap memory when needed\n  - remove unused file func.go\n  - use package reflectlite\n* **transform**\n  - cherry-pick from #4774\n\n\n0.36.0\n---\n* **general**\n  - add initial Go 1.24 support\n  - add support for LLVM 19\n  - update license for 2025\n  - make small corrections for README regarding wasm\n  - use GOOS and GOARCH for building wasm simulated boards\n  - only infer target for wasm when GOOS and GOARCH are set correctly, not just based on file extension\n  - add test-corpus-wasip2\n  - use older image for cross-compiling builds\n  - update Linux builds to run on ubuntu-latest since 20.04 is being retired\n  - ensure build output directory is created\n  - add NoSandbox flag to chrome headless that is run during WASM tests, since this is now required for Ubuntu 23+ and we are using Ubuntu 24+ when running Github Actions\n  - update wasmtime used for CI to 29.0.1 to fix issue with install during CI tests\n  - update to use `Get-CimInstance` as `wmic` is being deprecated on WIndows\n  - remove unnecessary executable permissions\n  - `goenv`: update to new v0.36.0 development version\n* **compiler**\n  - `builder`: fix parsing of external ld.lld error messages\n  - `cgo`: mangle identifier names\n  - `interp`: correctly mark functions as modifying memory\n  - add buildmode=wasi-legacy to support existing base of users who expected the older behavior for wasi modules to not return an exit code as if they were reactors\n* **standard library**\n  - `crypto/tls`: add Dialer.DialContext() to fix websocket client\n  - `crypto/tls`: add VersionTLS constants and VersionName(version uint16) method that turns it into a string, copied from big go\n  - `internal/syscall/unix`: use our own version of this package\n  - `machine`: replace hard-coded cpu frequencies on rp2xxx\n  - `machine`: bump rp2350 CPUFrequency to 150 MHz\n  - `machine`: compute rp2 clock dividers from crystal and target frequency\n  - `machine`: remove bytes package dependency in flash code\n  - `machine/usb/descriptor`: avoid bytes package\n  - `net`: update to latest submodule with httptest subpackage and ResolveIPAddress implementation\n  - `os`: add File.Chdir support\n  - `os`: implement stub Chdir for non-OS systems\n  - `os/file`: add file.Chmod\n  - `reflect`: implement Value.Equal\n  - `runtime`: add FIPS helper functions\n  - `runtime`: manually initialize xorshift state\n  - `sync`: move Mutex to internal/task\n  - `syscall`: add wasip1 RandomGet\n  - `testing`: add Chdir\n  - `wasip2`: add stubs to get internal/syscall/unix to work\n* **fixes**\n  - correctly handle calls for GetRNG() when being made from nrf devices with SoftDevice enabled\n  - fix stm32f103 ADC\n  - `wasm`: correctly handle id lookup for finalizeRef call\n  - `wasm`: avoid total failure on wasm finalizer call\n  - `wasm`: convert offset as signed int into unsigned int in syscall/js.stringVal in wasm_exec.js\n* **targets**\n  - rp2350: add pll generalized solution; fix ADC handles; pwm period fix\n  - rp2350: extending support to include the rp2350b\n  - rp2350: cleanup: unexport internal USB and clock package variable, consts and types\n  - nrf: make ADC resolution changeable\n  - turn on GC for TKey1 device, since it does in fact work\n  - match Pico2 stack size to Pico\n* **boards**\n  - add support for Pimoroni Pico Plus2\n  - add target for pico2-w board\n  - add comboat_fw tag for elecrow W5 boards with Combo-AT Wifi firmware\n  - add support for Elecrow Pico rp2350 W5 boards\n  - add support for Elecrow Pico rp2040 W5 boards\n  - add support for NRF51 HW-651\n  - add support for esp32c3-supermini\n  - add support for waveshare-rp2040-tiny\n* **examples**\n  - add naive debouncing for pininterrupt example\n\n\n0.35.0\n---\n* **general**\n  - update cmsis-svd library\n  - use default UART settings in the echo example\n  - `goenv`: also show git hash with custom build of TinyGo\n  - `goenv`: support parsing development versions of Go\n  - `main`: parse extldflags early so we can report the error message\n* **compiler**\n  - `builder`: whitelist temporary directory env var for Clang invocation to fix Windows bug\n  - `builder`: fix cache paths in `-size=full` output\n  - `builder`: work around incorrectly escaped DWARF paths on Windows (Clang bug)\n  - `builder`: fix wasi-libc path names on Windows with `-size=full`\n  - `builder`: write HTML size report\n  - `cgo`: support C identifiers only referred to from within macros\n  - `cgo`: support function-like macros\n  - `cgo`: support errno value as second return parameter\n  - `cgo`: add support for `#cgo noescape` lines\n  - `compiler`: fix bug in interrupt lowering\n  - `compiler`: allow panic directly in `defer`\n  - `compiler`: fix wasmimport -> wasmexport in error message\n  - `compiler`: support `//go:noescape` pragma\n  - `compiler`: report error instead of crashing when instantiating a generic function without body\n  - `interp`: align created globals\n* **standard library**\n  - `machine`: modify i2s interface/implementation to better match specification\n  - `os`: implement `StartProcess`\n  - `reflect`: add `Value.Clear`\n  - `reflect`: add interface support to `NumMethods`\n  - `reflect`: fix `AssignableTo` for named + non-named types\n  - `reflect`: implement `CanConvert`\n  - `reflect`: handle more cases in `Convert`\n  - `reflect`: fix Copy of non-pointer array with size > 64bits\n  - `runtime`: don't call sleepTicks with a negative duration\n  - `runtime`: optimize GC scanning (findHead)\n  - `runtime`: move constants into shared package\n  - `runtime`: add `runtime.fcntl` function for internal/syscall/unix\n  - `runtime`: heapptr only needs to be initialized once\n  - `runtime`: refactor scheduler (this fixes a few bugs with `-scheduler=none`)\n  - `runtime`: rewrite channel implementation to be smaller and more flexible\n  - `runtime`: use `SA_RESTART` when registering a signal for os/signal\n  - `runtime`: implement race-free signals using futexes\n  - `runtime`: run deferred functions in `Goexit`\n  - `runtime`: remove `Cond` which seems to be unused\n  - `runtime`: properly handle unix read on directory\n  - `runtime/trace`: stub all public methods\n  - `sync`: don't use volatile in `Mutex`\n  - `sync`: implement `WaitGroup` using a (pseudo)futex\n  - `sync`: make `Cond` parallelism-safe\n  - `syscall`: use wasi-libc tables for wasm/js target\n* **targets**\n  - `mips`: fix a bug when scanning the stack\n  - `nintendoswitch`: get this target to compile again\n  - `rp2350`: add support for the new RP2350\n  - `rp2040/rp2350` : make I2C implementation shared for rp2040/rp2350\n  - `rp2040/rp2350` : make SPI implementation shared for rp2040/rp2350\n  - `rp2040/rp2350` : make RNG implementation shared for rp2040/rp2350\n  - `wasm`: revise and simplify wasmtime argument handling\n  - `wasm`: support `//go:wasmexport` functions after a call to `time.Sleep`\n  - `wasm`: correctly return from run() in wasm_exec.js\n  - `wasm`: call process.exit() when go.run() returns\n  - `windows`: don't return, exit via exit(0) instead to flush stdout buffer\n* **boards**\n  - add support for the Tillitis TKey\n  - add support for the Raspberry Pi Pico2 (based on the RP2040)\n  - add support for Pimoroni Tiny2350\n\n\n0.34.0\n---\n* **general**\n  - fix `GOOS=wasip1` for `tinygo test`\n  - add `-C DIR` flag\n  - add initial documentation for project governance\n  - add `-ldflags='-extldflags=...'` support\n  - improve usage message with `tinygo help` and when passing invalid parameters\n* **compiler**\n  - `builder`: remove environment variables when invoking Clang, to avoid the environment changing the behavior\n  - `builder`: check for the Go toolchain version used to compile TinyGo\n  - `cgo`: add `C.CBytes` implementation\n  - `compiler`: fix passing weirdly-padded structs as parameters to new goroutines\n  - `compiler`: support pragmas on generic functions\n  - `compiler`: do not let the slice buffer escape when casting a `[]byte` or `[]rune` to a string, to help escape analysis\n  - `compiler`: conform to the latest iteration of the wasm types proposal\n  - `loader`: don't panic when main package is not named 'main'\n  - `loader`: make sure we always return type checker errors even without type errors\n  - `transform`: optimize range over `[]byte(string)`\n* **standard library**\n  - `crypto/x509`: add package stub to build crypto/x509 on macOS\n  - `machine/usb/adc/midi`: fix `PitchBend`\n  - `os`: add `Truncate` stub for baremetal\n  - `os`: add stubs for `os.File` deadlines\n  - `os`: add internal `net.newUnixFile` for the net package\n  - `runtime`: stub runtime_{Before,After}Exec for linkage\n  - `runtime`: randomize map accesses\n  - `runtime`: support `maps.Clone`\n  - `runtime`: add more fields to `MemStats`\n  - `runtime`: implement newcoro, coroswitch to support package iter\n  - `runtime`: disallow defer in interrupts\n  - `runtime`: add support for os/signal on Linux and MacOS\n  - `runtime`: add gc layout info for some basic types to help the precise GC\n  - `runtime`: bump GC mark stack size to avoid excessive heap rescans\n* **targets**\n  - `darwin`: use Go standard library syscall package instead of a custom one\n  - `fe310`: support GPIO `PinInput`\n  - `mips`: fix compiler crash with GOMIPS=softfloat and defer\n  - `mips`: add big-endian (GOARCH=mips) support\n  - `mips`: use MIPS32 (instead of MIPS32R2) as the instruction set for wider compatibility\n  - `wasi`: add relative and absolute --dir options to wasmtime args\n  - `wasip2`: add wasmtime -S args to support network interfaces\n  - `wasm`: add `//go:wasmexport` support (for all WebAssembly targets)\n  - `wasm`: use precise instead of conservative GC for WebAssembly (including WASI)\n  - `wasm-unknown`: add bulk memory flags since basically every runtime has it now\n* **boards**\n  - add RAKwireless RAK4631\n  - add WaveShare ESP-C3-32S-Kit\n\n\n0.33.0\n---\n\n* **general**\n  - use latest version of x/tools\n  - add chromeos 9p support for flashing\n  - sort compiler error messages by source position in a package\n  - don't include prebuilt libraries in the release to simplify packaging and reduce the release tarball size\n  - show runtime panic addresses for `tinygo run`\n  - support Go 1.23 (including all new language features)\n  - `test`: support GOOS/GOARCH pairs in the `-target` flag\n  - `test`: remove message after test binary built\n* **compiler**\n  - remove unused registers for x86_64 linux syscalls\n  - remove old atomics workaround for AVR (not necessary in modern LLVM versions)\n  - support `golang.org/x/sys/unix` syscalls\n  - `builder`: remove workaround for generics race condition\n  - `builder`: add package ID to compiler and optimization error messages\n  - `builder`: show better error messages for some common linker errors\n  - `cgo`: support preprocessor macros passed on the command line\n  - `cgo`: use absolute paths for error messages\n  - `cgo`: add support for printf\n  - `loader`: handle `go list` errors inside TinyGo (for better error messages)\n  - `transform`: fix incorrect alignment of heap-to-stack transform\n  - `transform`: use thinlto-pre-link passes (instead of the full pipeline) to speed up compilation speed slightly\n* **standard library**\n  - `crypto/tls`: add CipherSuiteName and some extra fields to ConnectionSTate\n  - `internal/abi`: implement initial version of this package\n  - `machine`: use new `internal/binary` package\n  - `machine`: rewrite Reply() to fix sending long replies in I2C Target Mode\n  - `machine/usb/descriptor`: Reset joystick physical\n  - `machine/usb/descriptor`: Drop second joystick hat\n  - `machine/usb/descriptor`: Add more HID... functions\n  - `machine/usb/descriptor`: Fix encoding of values\n  - `machine/usb/hid/joystick`: Allow more hat switches\n  - `os`: add `Chown`, `Truncate`\n  - `os/user`: use stdlib version of this package\n  - `reflect`: return correct name for the `unsafe.Pointer` type\n  - `reflect`: implement `Type.Overflow*` functions\n  - `runtime`: implement dummy `getAuxv` to satisfy golang.org/x/sys/\n  - `runtime`: don't zero out new allocations for `-gc=leaking` when they are already zeroed\n  - `runtime`: simplify slice growing/appending code\n  - `runtime`: print a message when a fatal signal like SIGSEGV happens\n  - `runtime/debug`: add `GoVersion` to `debug.BuildInfo`\n  - `sync`: add `Map.Clear()`\n  - `sync/atomic`: add And* and Or* compiler intrinsics needed for Go 1.23\n  - `syscall`: add `Fork` and `Execve`\n  - `syscall`: add all MacOS errno values\n  - `testing`: stub out `T.Deadline`\n  - `unique`: implement custom (naive) version of the unique package\n* **targets**\n  - `arm`: support `GOARM=*,softfloat` (softfloat support for ARM v5, v6, and v7)\n  - `mips`: add linux/mipsle (and experimental linux/mips) support\n  - `mips`: add `GOMIPS=softfloat` support\n  - `wasip2`: add WASI preview 2 support\n  - `wasm/js`: add `node:` prefix in `require()` call of wasm_exec.js\n  - `wasm-unknown`: make sure the `os` package can be imported\n  - `wasm-unknown`: remove import-memory flag\n\n\n0.32.0\n---\n\n* **general**\n  - fix wasi-libc include headers on Nix\n  - apply OpenOCD commands after target configuration\n  - fix a minor race condition when determining the build tags\n  - support UF2 drives with a space in their name on Linux\n  - add LLVM 18 support\n  - drop support for Go 1.18 to be able to stay up to date\n\n* **compiler**\n  - move `-panic=trap` support to the compiler/runtime\n  - fix symbol table index for WebAssembly archives\n  - fix ed25519 build errors by adjusting the alias names\n  - add aliases to generic AES functions\n  - fix race condition by temporarily applying a proposed patch\n  - `builder`: keep un-wasm-opt'd .wasm if -work was passed\n  - `builder`: make sure wasm-opt command line is printed if asked\n  - `cgo`: implement shift operations in preprocessor macros\n  - `interp`: checking for methodset existence\n\n* **standard library**\n  - `machine`: add `__tinygo_spi_tx` function to simulator\n  - `machine`: fix simulator I2C support\n  - `machine`: add GetRNG support to simulator\n  - `machine`: add `TxFifoFreeLevel` for CAN\n  - `os`: add `Link`\n  - `os`: add `FindProcess` for posix\n  - `os`: add `Process.Release` for unix\n  - `os`: add `SetReadDeadline` stub\n  - `os`, `os/signal`: add signal stubs\n  - `os/user`: add stubs for `Lookup{,Group}` and `Group`\n  - `reflect`: use int in `StringHeader` and `SliceHeader` on non-AVR platforms\n  - `reflect`: fix `NumMethods` for Interface type\n  - `runtime`: skip negative sleep durations in sleepTicks\n\n* **targets**\n  - `esp32`: add I2C support\n  - `rp2040`: move UART0 and UART1 to common file\n  - `rp2040`: make all RP2040 boards available for simulation\n  - `rp2040`: fix timeUnit type\n  - `stm32`: add i2c `Frequency` and `SetBaudRate` function for chips that were missing implementation\n  - `wasm-unknown`: add math and memory builtins that LLVM needs\n  - `wasip1`: replace existing `-target=wasi` support with wasip1 as supported in Go 1.21+\n\n* **boards**\n  - `adafruit-esp32-feather-v2`: add the Adafruit ESP32 Feather V2\n  - `badger2040-w`: add support for the Badger2040 W\n  - `feather-nrf52840-sense`: fix lack of LXFO\n  - `m5paper`: add support for the M5 Paper\n  - `mksnanov3`: limit programming speed to 1800 kHz\n  - `nucleol476rg`: add stm32 nucleol476rg support\n  - `pico-w`: add the Pico W (which is near-idential to the pico target)\n  - `thingplus-rp2040`, `waveshare-rp2040-zero`: add WS2812 definition\n  - `pca10059-s140v7`: add this variant to the PCA10059 board\n\n\n0.31.2\n---\n\n* **general**\n  * update the `net` submodule to updated version with `Buffers` implementation\n\n* **compiler**\n  * `syscall`: add wasm_unknown tag to some additional files so it can compile more code\n\n* **standard library**\n  * `runtime`: add Frame.Entry field\n\n\n0.31.1\n---\n\n* **general**\n  * fix Binaryen build in make task\n  * update final build stage of Docker `dev` image to go1.22\n  * only use GHA cache for building Docker `dev` image\n  * update the `net` submodule to latest version\n\n* **compiler**\n  * `interp`: make getelementptr offsets signed\n  * `interp`: return a proper error message when indexing out of range\n\n\n0.31.0\n---\n\n* **general**\n  * remove LLVM 14 support\n  * add LLVM 17 support, and use it by default\n  * add Nix flake support\n  * update bundled Binaryen to version 116\n  * add `ports` subcommand that lists available serial ports for `-port` and `-monitor`\n  * support wasmtime version 14\n  * add `-serial=rtt` for serial output over SWD\n  * add Go 1.22 support and use it by default\n  * change minimum Node.js version from 16 to 18\n* **compiler**\n  * use the new LLVM pass manager\n  * allow systems with more stack space to allocate larger values on the stack\n  * `build`: fix a crash due to sharing GlobalValues between build instances\n  * `cgo`: add `C._Bool` type\n  * `cgo`: fix calling CGo callback inside generic function\n  * `compileopts`: set `purego` build tag by default so that more packages can be built\n  * `compileopts`: force-enable CGo to avoid build issues\n  * `compiler`: fix crash on type assert on interfaces with no methods\n  * `interp`: print LLVM instruction in traceback\n  * `interp`: support runtime times by running them at runtime\n  * `loader`: enforce Go language version in the type checker (this may break existing programs with an incorrect Go version in go.mod)\n  * `transform`: fix bug in StringToBytes optimization pass\n* **standard library**\n  * `crypto/tls`: stub out a lot of functions\n  * `internal/task`, `machine`: make TinyGo code usable with \"big Go\" CGo\n  * `machine`: implement `I2C.SetBaudRate` consistently across chips\n  * `machine`: implement `SPI.Configure` consistently across chips\n  * `machine`: add `DeviceID` for nrf, rp2040, sam, stm32\n  * `machine`: use smaller UART buffer size on atmega chips\n  * `machine/usb`: allow setting a serial number using a linker flag\n  * `math`: support more math functions on baremetal (picolibc) systems\n  * `net`: replace entire net package with a new one based on the netdev driver\n  * `os/user`: add bare-bones implementation of this package\n  * `reflect`: stub `CallSlice` and `FuncOf`\n  * `reflect`: add `TypeFor[T]`\n  * `reflect`: update `IsZero` to Go 1.22 semantics\n  * `reflect`: move indirect values into interface when setting interfaces\n  * `runtime`: stub `Breakpoint`\n  * `sync`: implement trylock\n* **targets**\n  * `atmega`: use UART double speed mode for fewer errors and higher throughput\n  * `atmega328pb`: refactor to enable extra uart\n  * `avr`: don't compile large parts of picolibc (math, stdio) for LLVM 17 support\n  * `esp32`: switch over to the official SVD file\n  * `esp32c3`: implement USB_SERIAL for USBCDC communication\n  * `esp32c3`: implement I2C\n  * `esp32c3`: implement RNG\n  * `esp32c3`: add more ROM functions and update linker script for the in-progress wifi support\n  * `esp32c3`: update to newer SVD files\n  * `rp2040`: add support for UART hardware flow control\n  * `rp2040`: add definition for `machine.PinToggle`\n  * `rp2040`: set XOSC startup delay multiplier\n  * `samd21`: add support for UART hardware flow control\n  * `samd51`: add support for UART hardware flow control\n  * `wasm`: increase default stack size to 64k for wasi/wasm targets\n  * `wasm`: bump wasi-libc version to SDK 20\n  * `wasm`: remove line of dead code in wasm_exec.js\n* **new targets/boards**\n  * `qtpy-esp32c3`: add Adafruit QT Py ESP32-C3 board\n  * `mksnanov3`: add support for the MKS Robin Nano V3.x\n  * `nrf52840-generic`: add generic nrf52840 chip support\n  * `thumby`: add support for Thumby\n  * `wasm`: add new `wasm-unknown` target that doesn't depend on WASI or a browser\n* **boards**\n  * `arduino-mkrwifi1010`, `arduino-nano33`, `nano-rp2040`, `matrixportal-m4`, `metro-m4-airlift`, `pybadge`, `pyportal`: add `ninafw` build tag and some constants for BLE support\n  * `gopher-badge`: fix typo in USB product name\n  * `nano-rp2040`: add UART1 and correct mappings for NINA via UART\n  * `pico`: bump default stack size from 2kB to 8kB\n  * `wioterminal`: expose UART4\n\n\n0.30.0\n---\n\n* **general**\n  - add LLVM 16 support, use it by default\n* **compiler**\n  - `build`: work around a race condition by building Go SSA serially\n  - `compiler`: fix a crash by not using the LLVM global context types\n  - `interp`: don't copy unknown values in `runtime.sliceCopy` to fix miscompile\n  - `interp`: fix crash in error report by not returning raw LLVM values\n* **standard library**\n  - `machine/usb/adc/midi`: various improvements and API changes\n  - `reflect`: add support for `[...]T` → `[]T` in reflect\n* **targets**\n  - `atsamd21`, `atsamd51`: add support for USB INTERRUPT OUT\n  - `rp2040`: always use the USB device enumeration fix, even in chips that supposedly have the HW fix\n  - `wasm`: increase default stack size to 32k for wasi/wasm\n* **boards**\n  - `gobadge`: add GoBadge target as alias for PyBadge :)\n  - `gemma-m0`: add support for the Adafruit Gemma M0\n\n\n0.29.0\n---\n\n* **general**\n  - Go 1.21 support\n  - use https for renesas submodule #3856\n  - ci: rename release-double-zipped to something more useful\n  - ci: update Node.js from version 14 to version 16\n  - ci: switch GH actions builds to use Go 1.21 final release\n  - docker: update clang to version 15\n  - docker: use Go 1.21 for Docker dev container build\n  - `main`: add target JSON file in `tinygo info` output\n  - `main`: improve detection of filesystems\n  - `main`: use `go env` instead of doing all detection manually\n  - make: add make task to generate Renesas device wrappers\n  - make: add task to check NodeJS version before running tests\n  - add submodule for Renesas SVD file mirror repo\n  - update to go-serial package v1.6.0\n  - `testing`: add Testing function\n  - `tools/gen-device-svd`: small changes needed for Renesas MCUs\n* **compiler**\n  - `builder`: update message for max supported Go version\n  - `compiler,reflect`: NumMethods reports exported methods only\n  - `compiler`: add compiler-rt and wasm symbols to table\n  - `compiler`: add compiler-rt to wasm.json\n  - `compiler`: add min and max builtin support\n  - `compiler`: implement clear builtin for maps\n  - `compiler`: implement clear builtin for slices\n  - `compiler`: improve panic message when a runtime call is unavailable\n  - `compiler`: update .ll test output\n  - `loader`: merge go.env file which is now required starting in Go 1.21 to correctly get required packages\n* **standard library**\n  - `os`: define ErrNoDeadline\n  - `reflect`: Add FieldByNameFunc\n  - `reflect`: add SetZero\n  - `reflect`: fix iterating over maps with interface{} keys\n  - `reflect`: implement Value.Grow\n  - `reflect`: remove unnecessary heap allocations\n  - `reflect`: use .key() instead of a type assert\n  - `sync`: add implementation from upstream Go for OnceFunc, OnceValue, and OnceValues\n* **targets**\n  - `machine`: UART refactor (#3832)\n  - `machine/avr`: pin change interrupt\n  - `machine/macropad_rp2040`: add machine.BUTTON\n  - `machine/nrf`: add I2C timeout\n  - `machine/nrf`: wait for stop condition after reading from the I2C bus\n  - `machine/nRF52`: set SPI TX/RX lengths even data is empty. Fixes #3868 (#3877)\n  - `machine/rp2040`: add missing suffix to CMD_READ_STATUS\n  - `machine/rp2040`: add NoPin support\n  - `machine/rp2040`: move flash related functions into separate file from C imports for correct  - LSP. Fixes #3852\n  - `machine/rp2040`: wait for 1000 us after flash reset to avoid issues with busy USB bus\n  - `machine/samd51,rp2040,nrf528xx,stm32`: implement watchdog\n  - `machine/samd51`: fix i2cTimeout was decreasing due to cache activation\n  - `machine/usb`: Add support for HID Keyboard LEDs\n  - `machine/usb`: allow USB Endpoint settings to be changed externally\n  - `machine/usb`: refactor endpoint configuration\n  - `machine/usb`: remove usbDescriptorConfig\n  - `machine/usb/hid,joystick`: fix hidreport (3) (#3802)\n  - `machine/usb/hid`: add RxHandler interface\n  - `machine/usb/hid`: rename Handler() to TxHandler()\n  - `wasi`: allow zero inodes when reading directories\n  - `wasm`: add support for GOOS=wasip1\n  - `wasm`: fix functions exported through //export\n  - `wasm`: remove i64 workaround, use BigInt instead\n  - `example`: adjust time offset\n  - `example`: simplify pininterrupt\n* **boards**\n  - `targets`: add AKIZUKI DENSHI AE-RP2040\n  - `targets`: adding new uf2 target for PCA10056 (#3765)\n\n\n0.28.0\n---\n\n* **general**\n  - fix parallelism in the compiler on Windows by building LLVM with thread support\n  - support qemu-user debugging\n  - make target JSON msd-volume-name an array\n  - print source location when a panic happens in -monitor\n  - `test`: don't print `ok` for a successful compile-only\n* **compiler**\n  - `builder`: remove non-ThinLTO build mode\n  - `builder`: fail earlier if Go is not available\n  - `builder`: improve `-size=full` in a number of ways\n  - `builder`: implement Nordic DFU file writer in Go\n  - `cgo`: allow `LDFLAGS: --export=...`\n  - `compiler`: support recursive slice types\n  - `compiler`: zero struct padding during map operations\n  - `compiler`: add llvm.ident metadata\n  - `compiler`: remove `unsafe.Pointer(uintptr(v) + idx)` optimization (use `unsafe.Add` instead)\n  - `compiler`: add debug info to `//go:embed` data structures for better `-size` output\n  - `compiler`: add debug info to string constants\n  - `compiler`: fix a minor race condition\n  - `compiler`: emit correct alignment in debug info for global variables\n  - `compiler`: correctly generate reflect data for local named types\n  - `compiler`: add alloc attributes to `runtime.alloc`, reducing flash usage slightly\n  - `compiler`: for interface maps, use the original named type if available\n  - `compiler`: implement most math/bits functions as LLVM intrinsics\n  - `compiler`: ensure all defers have been seen before creating rundefers\n* **standard library**\n  - `internal/task`: disallow blocking inside an interrupt\n  - `machine`: add `CPUReset`\n  - `machine/usb/hid`: add MediaKey support\n  - `machine/usb/hid/joystick`: move joystick under HID\n  - `machine/usb/hid/joystick`: allow joystick settings override\n  - `machine/usb/hid/joystick`: handle case where we cannot find the correct HID descriptor\n  - `machine/usb/hid/mouse`: add support for mouse back and forward\n  - `machine/usb`: add ability to override default VID, PID, manufacturer name, and product name\n  - `net`: added missing `TCPAddr` and `UDPAddr` implementations\n  - `os`: add IsTimeout function\n  - `os`: fix resource leak in `(*File).Close`\n  - `os`: add `(*File).Sync`\n  - `os`: implement `(*File).ReadDir` for wasi\n  - `os`: implement `(*File).WriteAt`\n  - `reflect`: make sure null bytes are supported in tags\n  - `reflect`: refactor this package to enable many new features\n  - `reflect`: add map type methods: `Elem` and `Key`\n  - `reflect`: add map methods: `MapIndex`, `MapRange`/`MapIter`, `SetMapIndex`, `MakeMap`, `MapKeys`\n  - `reflect`: add slice methods: `Append`, `MakeSlice`, `Slice`, `Slice3`, `Copy`, `Bytes`, `SetLen`\n  - `reflect`: add misc methods: `Zero`, `Addr`, `UnsafeAddr`, `OverflowFloat`, `OverflowInt`, `OverflowUint`, `SetBytes`, `Convert`, `CanInt`, `CanFloat`, `CanComplex`, `Comparable`\n  - `reflect`: add type methods: `String`, `PkgPath`, `FieldByName`, `FieldByIndex`, `NumMethod`\n  - `reflect`: add stubs for `Type.Method`, `CanConvert`, `ArrayOf`, `StructOf`, `MapOf`\n  - `reflect`: add stubs for channel select routines/types\n  - `reflect`: allow nil rawType to call Kind()\n  - `reflect`: ensure all ValueError panics have Kind fields\n  - `reflect`: add support for named types\n  - `reflect`: improve `Value.String()`\n  - `reflect`: set `Index` and `PkgPath` field in `Type.Field`\n  - `reflect`: `Type.AssignableTo`: you can assign anything to `interface{}`\n  - `reflect`: add type check to `Value.Field`\n  - `reflect`: let `TypeOf(nil)` return nil\n  - `reflect`: move `StructField.Anonymous` field to match upstream location\n  - `reflect`: add `UnsafePointer` for Func types\n  - `reflect`: `MapIter.Next` needs to allocate new keys/values every time\n  - `reflect`: fix `IsNil` for interfaces\n  - `reflect`: fix `Type.Name` to return an empty string for non-named types\n  - `reflect`: add `VisibleFields`\n  - `reflect`: properly handle embedded structs\n  - `reflect`: make sure `PointerTo` works for named types\n  - `reflect`: `Set`: convert non-interface to interface\n  - `reflect`: `Set`: fix direction of assignment check\n  - `reflect`: support channel directions\n  - `reflect`: print struct tags in Type.String()\n  - `reflect`: properly handle read-only values\n  - `runtime`: allow custom-gc SetFinalizer and clarify KeepAlive\n  - `runtime`: implement KeepAlive using inline assembly\n  - `runtime`: check for heap allocations inside interrupts\n  - `runtime`: properly turn pointer into empty interface when hashing\n  - `runtime`: improve map size hint usage\n  - `runtime`: zero map key/value on deletion to so GC doesn't see them\n  - `runtime`: print the address where a panic happened\n  - `runtime/debug`: stub `SetGCPercent`, `BuildInfo.Settings`\n  - `runtime/metrics`: add this package as a stub\n  - `syscall`: `Stat_t` timespec fields are Atimespec on darwin\n  - `syscall`: add `Timespec.Unix()` for wasi\n  - `syscall`: add fsync using libc\n  - `testing`: support -test.count\n  - `testing`: make test output unbuffered when verbose\n  - `testing`: add -test.skip\n  - `testing`: move runtime.GC() call to runN to match upstream\n  - `testing`: add -test.shuffle to order randomize test and benchmark order\n* **targets**\n  - `arm64`: fix register save/restore to include vector registers\n  - `attiny1616`: add support for this chip\n  - `cortexm`: refactor EnableInterrupts and DisableInterrupts to avoid `arm.AsmFull`\n  - `cortexm`: enable functions in RAM for go & cgo\n  - `cortexm`: convert SystemStack from `AsmFull` to C inline assembly\n  - `cortexm`: fix crash due to wrong stack size offset\n  - `nrf`: samd21, stm32: add flash API\n  - `nrf`: fix memory issue in ADC read\n  - `nrf`: new peripheral type for nrf528xx chips\n  - `nrf`: implement target mode\n  - `nrf`: improve ADC and add oversampling, longer sample time, and reference voltage\n  - `rp2040`: change calling order for device enumeration fix to do first\n  - `rp2040`: rtc delayed interrupt\n  - `rp2040`: provide better errors for invalid pins on I2C and SPI\n  - `rp2040`: change uart to allow for a single pin\n  - `rp2040`: implement Flash interface\n  - `rp2040`: remove SPI `DataBits` property\n  - `rp2040`: unify all linker scripts using LDFLAGS\n  - `rp2040`: remove SPI deadline for improved performance\n  - `rp2040`: use 4MHz as default frequency for SPI\n  - `rp2040`: implement target mode\n  - `rp2040`: use DMA for send-only SPI transfers\n  - `samd21`: rearrange switch case for get pin cfg\n  - `samd21`: fix issue with WS2812 driver by making pin accesses faster\n  - `samd51`: enable CMCC cache for greatly improved performance\n  - `samd51`: remove extra BK0RDY clear\n  - `samd51`: implement Flash interface\n  - `samd51`: use correct SPI frequency\n  - `samd51`: remove extra BK0RDY clear\n  - `samd51`: fix ADC multisampling\n  - `wasi`: allow users to set the `runtime_memhash_tsip` or `runtime_memhash_fnv` build tags\n  - `wasi`: set `WASMTIME_BACKTRACE_DETAILS` when running in wasmtime.\n  - `wasm`: implement the `//go:wasmimport` directive\n* **boards**\n  - `gameboy-advance`: switch to use register definitions in device/gba\n  - `gameboy-advance`: rename display and make pointer receivers\n  - `gopher-badge`: Added Gopher Badge support\n  - `lorae5`: add needed definition for UART2\n  - `lorae5`: correct mapping for I2C bus, add pin mapping to enable power\n  - `pinetime`: update the target file (rename from pinetime-devkit0)\n  - `qtpy`: fix bad pin assignment\n  - `wioterminal`: fix pin definition of BCM13\n  - `xiao`: Pins D4 & D5 are I2C1. Use pins D2 & D3 for I2C0.\n  - `xiao`: add DefaultUART\n\n\n0.27.0\n---\n\n* **general**\n  - all: update musl\n  - all: remove \"acm:\"` prefix for USB vid/pid pair\n  - all: add support for LLVM 15\n  - all: use DWARF version 4\n  - all: add initial (incomplete) support for Go 1.20\n  - all: add `-gc=custom` option\n  - `main`: print ldflags including ThinLTO flags with -x\n  - `main`: fix error message when a serial port can't be accessed\n  - `main`: add `-timeout` flag to allow setting how long TinyGo will try looking for a MSD volume for flashing\n  - `test`: print PASS on pass when running standalone test binaries\n  - `test`: fix printing of benchmark output\n  - `test`: print package name when compilation failed (not just when the test failed)\n* **compiler**\n  - refactor to support LLVM 15\n  - `builder`: print compiler commands while building a library\n  - `compiler`: fix stack overflow when creating recursive pointer types (fix for LLVM 15+ only)\n  - `compiler`: allow map keys and values of ≥256 bytes\n  - `cgo`: add support for `C.float` and `C.double`\n  - `cgo`: support anonymous enums included in multiple Go files\n  - `cgo`: add support for bitwise operators\n  - `interp`: add support for constant icmp instructions\n  - `transform`: fix memory corruption issues\n* **standard library**\n  - `machine/usb`: remove allocs in USB ISR\n  - `machine/usb`: add `Port()` and deprecate `New()` to have the API better match the singleton that is actually being returned\n  - `machine/usb`: change HID usage-maximum to 0xFF\n  - `machine/usb`: add USB HID joystick support\n  - `machine/usb`: change to not send before endpoint initialization\n  - `net`: implement `Pipe`\n  - `os`: add stub for `os.Chtimes`\n  - `reflect`: stub out `Type.FieldByIndex`\n  - `reflect`: add `Value.IsZero` method\n  - `reflect`: fix bug in `.Field` method when the field fits in a pointer but the parent doesn't\n  - `runtime`: switch some `panic()` calls in the gc to `runtimePanic()` for consistency\n  - `runtime`: add xorshift-based fastrand64\n  - `runtime`: fix alignment for arm64, arm, xtensa, riscv\n  - `runtime`: implement precise GC\n  - `runtime/debug`: stub `PrintStack`\n  - `sync`: implement simple pooling in `sync.Pool`\n  - `syscall`: stubbed `Setuid`, Exec and friends\n  - `syscall`: add more stubs as needed for Go 1.20 support\n  - `testing`: implement `t.Setenv`\n  - `unsafe`: add support for Go 1.20 slice/string functions\n* **targets**\n  - `all`: do not set stack size per board\n  - `all`: update picolibc to v1.7.9\n  - `atsame5x`: fix CAN extendedID handling\n  - `atsame5x`: reduce heap allocation\n  - `avr`: drop GNU toolchain dependency\n  - `avr`: fix .data initialization for binaries over 64kB\n  - `avr`: support ThinLTO\n  - `baremetal`: implements calloc\n  - `darwin`: fix `syscall.Open` on darwin/arm64\n  - `darwin`: fix error with `tinygo lldb`\n  - `esp`: use LLVM Xtensa linker instead of Espressif toolchain\n  - `esp`: use ThinLTO for Xtensa\n  - `esp32c3`: add SPI support\n  - `linux`: include musl `getpagesize` function in release\n  - `nrf51`: add ADC implementation\n  - `nrf52840`: add PDM support\n  - `riscv`: add \"target-abi\" metadata flag\n  - `rp2040`: remove mem allocation in GPIO ISR\n  - `rp2040`: avoid allocating clock on heap\n  - `rp2040`: add basic GPIO support for PIO\n  - `rp2040`: fix USB interrupt issue\n  - `rp2040`: fix RP2040-E5 USB errata\n  - `stm32`: always set ADC pins to pullups floating\n  - `stm32f1`, `stm32f4`: fix ADC by clearing the correct bit for rank after each read\n  - `stm32wl`: Fix incomplete RNG initialisation\n  - `stm32wlx`: change order for init so clock speeds are set before peripheral start\n  - `wasi`: makes wasmtime \"run\" explicit\n  - `wasm`: fix GC scanning of allocas\n  - `wasm`: allow custom malloc implementation\n  - `wasm`: remove `-wasm-abi=` flag (use `-target` instead)\n  - `wasm`: fix scanning of the stack\n  - `wasm`: fix panic when allocating 0 bytes using malloc\n  - `wasm`: always run wasm-opt even with `-scheduler=none`\n  - `wasm`: avoid miscompile with ThinLTO\n  - `wasm`: allow the emulator to expand `{tmpDir}`\n  - `wasm`: support ThinLTO\n  - `windows`: update mingw-w64 version to avoid linker warning\n  - `windows`: add ARM64 support\n* **boards**\n  - Add Waveshare RP2040 Zero\n  - Add Arduino Leonardo support\n  - Add Adafruit KB2040\n  - Add Adafruit Feather M0 Express\n  - Add Makerfabs ESP32C3SPI35 TFT Touchscreen board\n  - Add Espressif ESP32-C3-DevKit-RUST-1 board\n  - `lgt92`: fix OpenOCD configuration\n  - `xiao-rp2040`: fix D9 and D10 constants\n  - `xiao-rp2040`: add pin definitions\n\n0.26.0\n---\n\n* **general**\n  - remove support for LLVM 13\n  - remove calls to deprecated ioutil package\n  - move from `os.IsFoo` to `errors.Is(err, ErrFoo)`\n  - fix for builds using an Android host\n  - make interp timeout configurable from command line\n  - ignore ports with VID/PID if there is no candidates\n  - drop support for Go 1.16 and Go 1.17\n  - update serial package to v1.3.5 for latest bugfixes\n  - remove GOARM from `tinygo info`\n  - add flag for setting the goroutine stack size\n  - add serial port monitoring functionality\n* **compiler**\n  - `cgo`: implement support for static functions\n  - `cgo`: fix panic when FuncType.Results is nil\n  - `compiler`: add aliases for `edwards25519/field.feMul` and `field.feSquare`\n  - `compiler`: fix incorrect DWARF type in some generic parameters\n  - `compiler`: use LLVM math builtins everywhere\n  - `compiler`: replace some math operation bodies with LLVM intrinsics\n  - `compiler`: replace math aliases with intrinsics\n  - `compiler`: fix `unsafe.Sizeof` for chan and map values\n  - `compileopts`: use tags parser from buildutil\n  - `compileopts`: use backticks for regexp to avoid extra escapes\n  - `compileopts`: fail fast on duplicate values in target field slices\n  - `compileopts`: fix windows/arm target triple\n  - `compileopts`: improve error handling when loading target/*.json\n  - `compileopts`: add support for stlink-dap programmer\n  - `compileopts`: do not complain about `-no-debug` on MacOS\n  - `goenv`: support `GOOS=android`\n  - `interp`: fix reading from external global\n  - `loader`: fix link error for `crypto/internal/boring/sig.StandardCrypto`\n* **standard library**\n  - rename assembly files to .S extension\n  - `machine`: add PWM peripheral comments to pins\n  - `machine`: improve UARTParity slightly\n  - `machine`: do not export DFU_MAGIC_* constants on nrf52840\n  - `machine`: rename `PinInputPullUp`/`PinInputPullDown`\n  - `machine`: add `KHz`, `MHz`, `GHz` constants, deprecate `TWI_FREQ_*` constants\n  - `machine`: remove level triggered pin interrupts\n  - `machine`: do not expose `RESET_MAGIC_VALUE`\n  - `machine`: use `NoPin` constant where appropriate (instead of `0` for example)\n  - `net`: sync net.go with Go 1.18 stdlib\n  - `os`: add `SyscallError.Timeout`\n  - `os`: add `ErrProcessDone` error\n  - `reflect`: implement `CanInterface` and fix string `Index`\n  - `runtime`: make `MemStats` available to leaking collector\n  - `runtime`: add `MemStats.TotalAlloc`\n  - `runtime`: add `MemStats.Mallocs` and `Frees`\n  - `runtime`: add support for `time.NewTimer` and `time.NewTicker`\n  - `runtime`: implement `resetTimer`\n  - `runtime`: ensure some headroom for the GC to run\n  - `runtime`: make gc and scheduler asserts settable with build tags\n  - `runtime/pprof`: add `WriteHeapProfile`\n  - `runtime/pprof`: `runtime/trace`: stub some additional functions\n  - `sync`: implement `Map.LoadAndDelete`\n  - `syscall`: group WASI consts by purpose\n  - `syscall`: add WASI `{D,R}SYNC`, `NONBLOCK` FD flags\n  - `syscall`: add ENOTCONN on darwin\n  - `testing`: add support for -benchmem\n* **targets**\n  - remove USB vid/pid pair of bootloader\n  - `esp32c3`: remove unused `UARTStopBits` constants\n  - `nrf`: implement `GetRNG` function\n  - `nrf`: `rp2040`: add `machine.ReadTemperature`\n  - `nrf52`: cleanup s140v6 and s140v7 uf2 targets\n  - `rp2040`: implement semi-random RNG based on ROSC based on pico-sdk\n  - `wasm`: add summary of wasm examples and fix callback bug\n  - `wasm`: do not allow undefined symbols (`--allow-undefined`)\n  - `wasm`: make sure buffers returned by `malloc` are kept until `free` is called\n  - `windows`: save and restore xmm registers when switching goroutines\n* **boards**\n  - add Pimoroni's Tufty2040\n  - add XIAO ESP32C3\n  - add Adafruit QT2040\n  - add Adafruit QT Py RP2040\n  - `esp32c3-12f`: `matrixportal-m4`: `p1am-100`: remove duplicate build tags\n  - `hifive1-qemu`: remove this emulated board\n  - `wioterminal`: add UART3 for RTL8720DN\n  - `xiao-ble`: fix usbpid\n\n\n0.25.0\n---\n\n* **command line**\n  - change to ignore PortReset failures\n* **compiler**\n  - `compiler`: darwin/arm64 is aarch64, not arm\n  - `compiler`: don't clobber X18 and FP registers on darwin/arm64\n  - `compiler`: fix issue with methods on generic structs\n  - `compiler`: do not try to build generic functions\n  - `compiler`: fix type names for generic named structs\n  - `compiler`: fix multiple defined function issue for generic functions\n  - `compiler`: implement `unsafe.Alignof` and `unsafe.Sizeof` for generic code\n* **standard library**\n  - `machine`: add DTR and RTS to Serialer interface\n  - `machine`: reorder pin definitions to improve pin list on tinygo.org\n  - `machine/usb`: add support for MIDI\n  - `machine/usb`: adjust buffer alignment (samd21, samd51, nrf52840)\n  - `machine/usb/midi`: add `NoteOn`, `NoteOff`, and `SendCC` methods\n  - `machine/usb/midi`: add definition of MIDI note number\n  - `runtime`: add benchmarks for memhash\n  - `runtime`: add support for printing slices via print/println\n* **targets**\n  - `avr`: fix some apparent mistake in atmega1280/atmega2560 pin constants\n  - `esp32`: provide hardware pin constants\n  - `esp32`: fix WDT reset on the MCH2022 badge\n  - `esp32`: optimize SPI transmit\n  - `esp32c3`: provide hardware pin constants\n  - `esp8266`: provide hardware pin constants like `GPIO2`\n  - `nrf51`: define and use `P0_xx` constants\n  - `nrf52840`, `samd21`, `samd51`: unify bootloader entry process\n  - `nrf52840`, `samd21`, `samd51`: change usbSetup and sendZlp to public\n  - `nrf52840`, `samd21`, `samd51`: refactor handleStandardSetup and initEndpoint\n  - `nrf52840`, `samd21`, `samd51`: improve usb-device initialization\n  - `nrf52840`, `samd21`, `samd51`: move usbcdc to machine/usb/cdc\n  - `rp2040`: add usb serial vendor/product ID\n  - `rp2040`: add support for usb\n  - `rp2040`: change default for serial to usb\n  - `rp2040`: add support for `machine.EnterBootloader`\n  - `rp2040`: turn off pullup/down when input type is not specified\n  - `rp2040`: make picoprobe default openocd interface\n  - `samd51`: add support for `DAC1`\n  - `samd51`: improve TRNG\n  - `wasm`: stub `runtime.buffered`, `runtime.getchar`\n  - `wasi`: make leveldb runtime hash the default\n* **boards**\n  - add Challenger RP2040 LoRa\n  - add MCH2022 badge\n  - add XIAO RP2040\n  - `clue`: remove pins `D21`..`D28`\n  - `feather-rp2040`, `macropad-rp2040`: fix qspi-flash settings\n  - `xiao-ble`: add support for flash-1200-bps-reset\n  - `gopherbot`, `gopherbot2`: add these aliases to simplify for newer users\n\n\n0.24.0\n---\n\n* **command line**\n  - remove support for go 1.15\n  - remove support for LLVM 11 and LLVM 12\n  - add initial Go 1.19 beta support\n  - `test`: fix package/... syntax\n* **compiler**\n  - add support for the embed package\n  - `builder`: improve error message for \"command not found\"\n  - `builder`: add support for ThinLTO on MacOS and Windows\n  - `builder`: free LLVM objects after use, to reduce memory leaking\n  - `builder`: improve `-no-debug` error messages\n  - `cgo`: be more strict: CGo now requires every Go file to import the headers it needs\n  - `compiler`: alignof(func) is 1 pointer, not 2\n  - `compiler`: add support for type parameters (aka generics)\n  - `compiler`: implement `recover()` built-in function\n  - `compiler`: support atomic, volatile, and LLVM memcpy-like functions in defer\n  - `compiler`: drop support for macos syscalls via inline assembly\n  - `interp`: do not try to interpret past task.Pause()\n  - `interp`: fix some buggy localValue handling\n  - `interp`: do not unroll loops\n  - `transform`: fix MakeGCStackSlots that caused a possible GC bug on WebAssembly\n* **standard library**\n  - `os`: enable os.Stdin for baremetal target\n  - `reflect`: add `Value.UnsafePointer` method\n  - `runtime`: scan GC globals conservatively on Windows, MacOS, Linux and Nintendo Switch\n  - `runtime`: add per-map hash seeds\n  - `runtime`: handle nil map write panics\n  - `runtime`: add stronger hash functions\n  - `syscall`: implement `Getpagesize`\n* **targets**\n  - `atmega2560`: support UART1-3 + example for uart\n  - `avr`: use compiler-rt for improved float64 support\n  - `avr`: simplify timer-based time\n  - `avr`: fix race condition in stack write\n  - `darwin`: add support for `GOARCH=arm64` (aka Apple Silicon)\n  - `darwin`: support `-size=short` and `-size=full` flag\n  - `rp2040`: replace sleep 'busy loop' with timer alarm\n  - `rp2040`: align api for `PortMaskSet`, `PortMaskClear`\n  - `rp2040`: fix GPIO interrupts\n  - `samd21`, `samd51`, `nrf52840`: add support for USBHID (keyboard / mouse)\n  - `wasm`: update wasi-libc version\n  - `wasm`: use newer WebAssembly features\n* **boards**\n  - add Badger 2040\n  - `matrixportal-m4`: attach USB DP to the correct pin\n  - `teensy40`: add I2C support\n  - `wioterminal`: fix I2C definition\n\n\n0.23.0\n---\n\n* **command line**\n  - add `-work` flag\n  - add Go 1.18 support\n  - add LLVM 14 support\n  - `run`: add support for command-line parameters\n  - `build`: calculate default output path if `-o` is not specified\n  - `build`: add JSON output\n  - `test`: support multiple test binaries with `-c`\n  - `test`: support flags like `-v` on all targets (including emulated firmware)\n* **compiler**\n  - add support for ThinLTO\n  - use compiler-rt from LLVM\n  - `builder`: prefer GNU build ID over Go build ID for caching\n  - `builder`: add support for cross compiling to Darwin\n  - `builder`: support machine outlining pass in stacksize calculation\n  - `builder`: disable asynchronous unwind tables\n  - `compileopts`: fix emulator configuration on non-amd64 Linux architectures\n  - `compiler`: move allocations > 256  bytes to the heap\n  - `compiler`: fix incorrect `unsafe.Alignof` on some 32-bit architectures\n  - `compiler`: accept alias for slice `cap` builtin\n  - `compiler`: allow slices of empty structs\n  - `compiler`: fix difference in aliases in interface methods\n  - `compiler`: make `RawSyscall` an alias for `Syscall`\n  - `compiler`: remove support for memory references in `AsmFull`\n  - `loader`: only add Clang header path for CGo\n  - `transform`: fix poison value in heap-to-stack transform\n* **standard library**\n  - `internal/fuzz`: add this package as a shim\n  - `os`: implement readdir for darwin and linux\n  - `os`: add `DirFS`, which is used by many programs to access readdir.\n  - `os`: isWine: be compatible with older versions of wine, too\n  - `os`: implement `RemoveAll`\n  - `os`: Use a `uintptr` for `NewFile`\n  - `os`: add stubs for `exec.ExitError` and `ProcessState.ExitCode`\n  - `os`: export correct values for `DevNull` for each OS\n  - `os`: improve support for `Signal` by fixing various bugs\n  - `os`: implement `File.Fd` method\n  - `os`: implement `UserHomeDir`\n  - `os`: add `exec.ProcessState` stub\n  - `os`: implement `Pipe` for darwin\n  - `os`: define stub `ErrDeadlineExceeded`\n  - `reflect`: add stubs for more missing methods\n  - `reflect`: rename `reflect.Ptr` to `reflect.Pointer`\n  - `reflect`: add `Value.FieldByIndexErr` stub\n  - `runtime`: fix various small GC bugs\n  - `runtime`: use memzero for leaking collector instead of manually zeroing objects\n  - `runtime`: implement `memhash`\n  - `runtime`: implement `fastrand`\n  - `runtime`: add stub for `debug.ReadBuildInfo`\n  - `runtime`: add stub for `NumCPU`\n  - `runtime`: don't inline `runtime.alloc` with `-gc=leaking`\n  - `runtime`: add `Version`\n  - `runtime`: add stubs for `NumCgoCall` and `NumGoroutine`\n  - `runtime`: stub {Lock,Unlock}OSThread on Windows\n  - `runtime`: be able to deal with a very small heap\n  - `syscall`: make `Environ` return a copy of the environment\n  - `syscall`: implement getpagesize and munmap\n  - `syscall`: `wasi`: define `MAP_SHARED` and `PROT_READ`\n  - `syscall`: stub mmap(), munmap(), MAP_SHARED, PROT_READ, SIGBUS, etc. on nonhosted targets\n  - `syscall`: darwin: more complete list of signals\n  - `syscall`: `wasi`: more complete list of signals\n  - `syscall`: stub `WaitStatus`\n  - `syscall/js`: allow copyBytesTo(Go|JS) to use `Uint8ClampedArray`\n  - `testing`: implement `TempDir`\n  - `testing`: nudge type TB closer to upstream; should be a no-op change.\n  - `testing`: on baremetal platforms, use simpler test matcher\n* **targets**\n  - `atsamd`: fix usbcdc initialization when `-serial=uart`\n  - `atsamd51`: allow higher frequency when using SPI\n  - `esp`: support CGo\n  - `esp32c3`: add support for input pin\n  - `esp32c3`: add support for GPIO interrupts\n  - `esp32c3`: add support to receive UART data\n  - `rp2040`: fix PWM bug at high frequency\n  - `rp2040`: fix some minor I2C bugs\n  - `rp2040`: fix incorrect inline assembly\n  - `rp2040`: fix spurious i2c STOP during write+read transaction\n  - `rp2040`: improve ADC support\n  - `wasi`: remove `--export-dynamic` linker flag\n  - `wasm`: remove heap allocator from wasi-libc\n* **boards**\n  - `circuitplay-bluefruit`: move pin mappings so board can be compiled for WASM use in Playground\n  - `esp32-c3-12f`: add the ESP32-C3-12f Kit\n  - `m5stamp-c3`: add pin setting of UART\n  - `macropad-rp2040`: add the Adafruit MacroPad RP2040 board\n  - `nano-33-ble`: typo in LPS22HB peripheral definition and documentation (#2579)\n  - `teensy41`: add the Teensy 4.1 board\n  - `teensy40`: add ADC support\n  - `teensy40`: add SPI support\n  - `thingplus-rp2040`: add the SparkFun Thing Plus RP2040 board\n  - `wioterminal`: add DefaultUART\n  - `wioterminal`: verify written data when flashing through OpenOCD\n  - `xiao-ble`: add XIAO BLE nRF52840 support\n\n\n0.22.0\n---\n\n* **command line**\n  - add asyncify to scheduler flag help\n  - support -run for tests\n  - remove FreeBSD target support\n  - add LLVM 12 and LLVM 13 support, use LLVM 13 by default\n  - add support for ARM64 MacOS\n  - improve help\n  - check /run/media as well as /media on Linux for non-debian-based distros\n  - `test`: set cmd.Dir even when running emulators\n  - `info`: add JSON output using the `-json` flag\n* **compiler**\n  - `builder`: fix off-by-one in size calculation\n  - `builder`: handle concurrent library header rename\n  - `builder`: use flock to avoid double-compiles\n  - `builder`: use build ID as cache key\n  - `builder`: add -fno-stack-protector to musl build\n  - `builder`: update clang header search path to look in /usr/lib\n  - `builder`: explicitly disable unwind tables for ARM\n  - `cgo`: add support for `C.CString` and related functions\n  - `compiler`: fix ranging over maps with particular map types\n  - `compiler`: add correct debug location to init instructions\n  - `compiler`: fix emission of large object layouts\n  - `compiler`: work around AVR atomics bugs\n  - `compiler`: predeclare runtime.trackPointer\n  - `interp`: work around AVR function pointers in globals\n  - `interp`: run goroutine starts and checks at runtime\n  - `interp`: always run atomic and volatile loads/stores at runtime\n  - `interp`: bump timeout to 180 seconds\n  - `interp`: handle type assertions on nil interfaces\n  - `loader`: eliminate goroot cache inconsistency\n  - `loader`: respect $GOROOT when running `go list`\n  - `transform`: allocate the correct amount of bytes in an alloca\n  - `transform`: remove switched func lowering\n* **standard library**\n  - `crypto/rand`: show error if platform has no rng\n  - `device/*`: add `*_Msk` field for each bit field and avoid duplicates\n  - `device/*`: provide Set/Get for each register field described in the SVD files\n  - `internal/task`: swap stack chain when switching goroutines\n  - `internal/task`: remove `-scheduler=coroutines`\n  - `machine`: add `Device` string constant\n  - `net`: add bare Interface implementation\n  - `net`: add net.Buffers\n  - `os`: stub out support for some features\n  - `os`: obey TMPDIR on unix, TMP on Windows, etc\n  - `os`: implement `ReadAt`, `Mkdir`, `Remove`, `Stat`, `Lstat`, `CreateTemp`, `MkdirAll`, `Chdir`, `Chmod`, `Clearenv`, `Unsetenv`, `Setenv`, `MkdirTemp`, `Rename`, `Seek`, `ExpandEnv`, `Symlink`, `Readlink`\n  - `os`: implement `File.Stat`\n  - `os`: fix `IsNotExist` on nonexistent path\n  - `os`: fix opening files on WASI in read-only mode\n  - `os`: work around lack of `syscall.seek` on 386 and arm\n  - `reflect`: make sure indirect pointers are handled correctly\n  - `runtime`: allow comparing interfaces\n  - `runtime`: use LLVM intrinsic to read the stack pointer\n  - `runtime`: strengthen hashmap hash function for structs and arrays\n  - `runtime`: fix float/complex hashing\n  - `runtime`: fix nil map dereference\n  - `runtime`: add realloc implementation to GCs\n  - `runtime`: handle negative sleep times\n  - `runtime`: correct GC scan bounds\n  - `runtime`: remove extalloc GC\n  - `rumtime`: implement `__sync` libcalls as critical sections for most microcontrollers\n  - `runtime`: add stubs for `Func.FileLine` and `Frame.PC`\n  - `sync`: fix concurrent read-lock on write-locked RWMutex\n  - `sync`: add a package doc\n  - `sync`: add tests\n  - `syscall`: add support for `Mmap` and `Mprotect`\n  - `syscall`: fix array size for mmap slice creation\n  - `syscall`: enable `Getwd` in wasi\n  - `testing`: add a stub for `CoverMode`\n  - `testing`: support -bench option to run benchmarks matching the given pattern.\n  - `testing`: support b.SetBytes(); implement sub-benchmarks.\n  - `testing`: replace spaces with underscores in test/benchmark names, as upstream does\n  - `testing`: implement testing.Cleanup\n  - `testing`: allow filtering subbenchmarks with the `-bench` flag\n  - `testing`: implement `-benchtime` flag\n  - `testing`: print duration\n  - `testing`: allow filtering of subtests using `-run`\n* **targets**\n  - `all`: change LLVM features to match vanilla Clang\n  - `avr`: use interrupt-based timer which is much more accurate\n  - `nrf`: fix races in I2C\n  - `samd51`: implement TRNG for randomness\n  - `stm32`: pull-up on I2C lines\n  - `stm32`: fix timeout for i2c comms\n  - `stm32f4`, `stm32f103`: initial implementation for ADC\n  - `stm32f4`, `stm32f7`, `stm32l0x2`, `stm32l4`, `stm32l5`, `stm32wl`: TRNG implementation in crypto/rand\n  - `stm32wl`: add I2C support\n  - `windows`: add support for the `-size=` flag\n  - `wasm`: add support for `tinygo test`\n  - `wasi`, `wasm`: raise default stack size to 16 KiB\n* **boards**\n  - add M5Stack\n  - add lorae5 (stm32wle) support\n  - add Generic Node Sensor Edition\n  - add STM32F469 Discovery\n  - add M5Stamp C3\n  - add Blues Wireless Swan\n  - `bluepill`: add definitions for ADC pins\n  - `stm32f4disco`: add definitions for ADC pins\n  - `stm32l552ze`: use supported stlink interface\n  - `microbit-v2`: add some pin definitions\n\n\n0.21.0\n---\n\n* **command line**\n  - drop support for LLVM 10\n  - `build`: drop support for LLVM targets in the -target flag\n  - `build`: fix paths in error messages on Windows\n  - `build`: add -p flag to set parallelism\n  - `lldb`: implement `tinygo lldb` subcommand\n  - `test`: use emulator exit code instead of parsing test output\n  - `test`: pass testing arguments to wasmtime\n* **compiler**\n  - use -opt flag for optimization level in CFlags (-Os, etc)\n  - `builder`: improve accuracy of the -size=full flag\n  - `builder`: hardcode some more frame sizes for __aeabi_* functions\n  - `builder`: add support for -size= flag for WebAssembly\n  - `cgo`: fix line/column reporting in syntax error messages\n  - `cgo`: support function definitions in CGo headers\n  - `cgo`: implement rudimentary C array decaying\n  - `cgo`: add support for stdio in picolibc and wasi-libc\n  - `cgo`: run CGo parser per file, not per CGo fragment\n  - `compiler`: fix unintentionally exported math functions\n  - `compiler`: properly implement div and rem operations\n  - `compiler`: add support for recursive function types\n  - `compiler`: add support for the `go` keyword on interface methods\n  - `compiler`: add minsize attribute for -Oz\n  - `compiler`: add \"target-cpu\" and \"target-features\" attributes\n  - `compiler`: fix indices into strings and arrays\n  - `compiler`: fix string compare functions\n  - `interp`: simplify some code to avoid some errors\n  - `interp`: support recursive globals (like linked lists) in globals\n  - `interp`: support constant globals\n  - `interp`: fix reverting of extractvalue/insertvalue with multiple indices\n  - `transform`: work around renamed return type after merging LLVM modules\n* **standard library**\n  - `internal/bytealg`: fix indexing error in Compare()\n  - `machine`: support Pin.Get() function when the pin is configured as output\n  - `net`, `syscall`: Reduce code duplication by switching to internal/itoa.\n  - `os`: don't try to read executable path on baremetal\n  - `os`: implement Getwd\n  - `os`: add File.WriteString and File.WriteAt\n  - `reflect`: fix type.Size() to account for struct padding\n  - `reflect`: don't construct an interface-in-interface value\n  - `reflect`: implement Value.Elem() for interface values\n  - `reflect`: fix Value.Index() in a specific case\n  - `reflect`: add support for DeepEqual\n  - `runtime`: add another set of invalid unicode runes to encodeUTF8()\n  - `runtime`: only initialize os.runtime_args when needed\n  - `runtime`: only use CRLF on baremetal systems for println\n  - `runtime/debug`: stub `debug.SetMaxStack`\n  - `runtime/debug`: stub `debug.Stack`\n  - `testing`: add a stub for t.Parallel()\n  - `testing`: add support for -test.short flag\n  - `testing`: stub B.ReportAllocs()\n  - `testing`: add `testing.Verbose`\n  - `testing`: stub `testing.AllocsPerRun`\n* **targets**\n  - fix gen-device-svd to handle 64-bit values\n  - add CPU and Features property to all targets\n  - match LLVM triple to the one Clang uses\n  - `atsam`: simplify definition of SERCOM UART, I2C and SPI peripherals\n  - `atsam`: move I2S0 to machine file\n  - `esp32`: fix SPI configuration\n  - `esp32c3`: add support for GDB debugging\n  - `esp32c3`: add support for CPU interrupts\n  - `esp32c3`: use tasks scheduler by default\n  - `fe310`: increase CPU frequency from 16MHz to 320MHz\n  - `fe310`: add support for bit banging drivers\n  - `linux`: build static binaries using musl\n  - `linux`: reduce binary size by calling `write` instead of `putchar`\n  - `linux`: add support for GOARM\n  - `riscv`: implement 32-bit atomic operations\n  - `riscv`: align the heap to 16 bytes\n  - `riscv`: switch to tasks-based scheduler\n  - `rp2040`: add CPUFrequency()\n  - `rp2040`: improve I2C baud rate configuration\n  - `rp2040`: add pin interrupt API\n  - `rp2040`: refactor PWM code and fix Period calculation\n  - `stm32f103`: fix SPI\n  - `stm32f103`: make SPI frequency selection more flexible\n  - `qemu`: signal correct exit code to QEMU\n  - `wasi`: run C/C++ constructors at startup\n  - `wasm`: ensure heapptr is aligned\n  - `wasm`: update wasi-libc dependency\n  - `wasm`: wasi: use asyncify\n  - `wasm`: support `-scheduler=none`\n  - `windows`: add support for Windows (amd64 only for now)\n* **boards**\n  - `feather-stm32f405`, `feather-rp2040`: add I2C pin names\n  - `m5stack-core2`: add M5Stack Core2\n  - `nano-33-ble`: SoftDevice s140v7 support\n  - `nano-33-ble`: add constants for more on-board pins\n\n\n0.20.0\n---\n\n* **command line**\n  - add support for Go 1.17\n  - improve Go version detection\n  - add support for the Black Magic Probe (BMP)\n  - add a flag for creating cpu profiles\n* **compiler**\n  - `builder:` list libraries at the end of the linker command\n  - `builder:` strip debug information at link time instead of at compile time\n  - `builder:` add missing error check for `ioutil.TempFile()`\n  - `builder:` simplify running of jobs\n  - `compiler:` move LLVM math builtin support into the compiler\n  - `compiler:` move math aliases from the runtime to the compiler\n  - `compiler:` add aliases for many hashing packages\n  - `compiler:` add `*ssa.MakeSlice` bounds tests\n  - `compiler:` fix max possible slice\n  - `compiler:` add support for new language features of Go 1.17\n  - `compiler:` fix equally named structs in different scopes\n  - `compiler:` avoid zero-sized alloca in channel operations\n  - `interp:` don't ignore array indices for untyped objects\n  - `interp:` keep reverted package initializers in order\n  - `interp:` fix bug in compiler-time/run-time package initializers\n  - `loader:` fix panic in CGo files with syntax errors\n  - `transform:` improve GC stack slot pass to work around a bug\n* **standard library**\n  - `crypto/rand`: switch to `arc4random_buf`\n  - `math:` fix `math.Max` and `math.Min`\n  - `math/big`: fix undefined symbols error\n  - `net:` add MAC address implementation\n  - `os:` implement `os.Executable`\n  - `os:` add `SEEK_SET`, `SEEK_CUR`, and `SEEK_END`\n  - `reflect:` add StructField.IsExported method\n  - `runtime:` reset heapptr to heapStart after preinit()\n  - `runtime:` add `subsections_via_symbols` to assembly files on darwin\n  - `testing:` add subset implementation of Benchmark\n  - `testing:` test testing package using `tinygo test`\n  - `testing:` add support for the `-test.v` flag\n* **targets**\n  - `386:` bump minimum requirement to the Pentium 4\n  - `arm:` switch to Thumb instruction set on ARM\n  - `atsamd:` fix copy-paste error for atsamd21/51 calibTrim block\n  - `baremetal`,`wasm`: support command line params and environment variables\n  - `cortexm:` fix stack overflow because of unaligned stacks\n  - `esp32c3:` add support for the ESP32-C3 from Espressif\n  - `nrf52840:` fix ram size\n  - `nxpmk66f18:` fix a suspicious bitwise operation\n  - `rp2040:` add SPI support\n  - `rp2040:` add I2C support\n  - `rp2040:` add PWM implementation\n  - `rp2040:` add openocd configuration\n  - `stm32:` add support for PortMask* functions for WS2812 support\n  - `unix:` fix time base for time.Now()\n  - `unix:` check for mmap error and act accordingly\n  - `wasm:` override dlmalloc heap implementation from wasi-libc\n  - `wasm:` align heap to 16 bytes\n  - `wasm:` add support for the crypto/rand package\n* **boards**\n  - add `DefaultUART` to adafruit boards\n  - `arduino-mkrwifi1010:` add board definition for Arduino MKR WiFi 1010\n  - `arduino-mkrwifi1010:` fix pin definition of `NINA_RESETN`\n  - `feather-nrf52:` fix pin definition of uart\n  - `feather-rp2040:` add pin name definition\n  - `gameboy-advance:` fix ROM header\n  - `mdbt50qrx-uf2:` add Raytac MDBT50Q-RX Dongle with TinyUF2\n  - `nano-rp2040:` define `NINA_SPI` and fix wifinina pins\n  - `teensy40:` enable hardware UART reconfiguration, fix receive watermark interrupt\n\n\n0.19.0\n---\n\n* **command line**\n  - don't consider compile-only tests as failing\n  - add -test flag for `tinygo list`\n  - escape commands while printing them with the -x flag\n  - make flash-command portable and safer to use\n  - use `extended-remote` instead of `remote` in GDB\n  - detect specific serial port IDs based on USB vid/pid\n  - add a flag to the command line to select the serial implementation\n* **compiler**\n  - `cgo`: improve constant parser\n  - `compiler`: support chained interrupt handlers\n  - `compiler`: add support for running a builtin in a goroutine\n  - `compiler`: do not emit nil checks for loading closure variables\n  - `compiler`: skip context parameter when starting regular goroutine\n  - `compiler`: refactor method names\n  - `compiler`: add function and global section pragmas\n  - `compiler`: implement `syscall.rawSyscallNoError` in inline assembly\n  - `interp`: ignore inline assembly in markExternal\n  - `interp`: fix a bug in pointer cast workaround\n  - `loader`: fix testing a main package\n* **standard library**\n  - `crypto/rand`: replace this package with a TinyGo version\n  - `machine`: make USBCDC global a pointer\n  - `machine`: make UART objects pointer receivers\n  - `machine`: define Serial as the default output\n  - `net`: add initial support for net.IP\n  - `net`: add more net compatibility\n  - `os`: add stub for os.ReadDir\n  - `os`: add FileMode constants from Go 1.16\n  - `os`: add stubs required for net/http\n  - `os`: implement process related functions\n  - `reflect`: implement AppendSlice\n  - `reflect`: add stubs required for net/http\n  - `runtime`: make task.Data a 64-bit integer to avoid overflow\n  - `runtime`: expose memory stats\n  - `sync`: implement NewCond\n  - `syscall`: fix int type in libc version\n* **targets**\n  - `cortexm`: do not disable interrupts on abort\n  - `cortexm`: bump default stack size to 2048 bytes\n  - `nrf`: avoid heap allocation in waitForEvent\n  - `nrf`: don't trigger a heap allocation in SPI.Transfer\n  - `nrf52840`: add support for flashing with the BOSSA tool\n  - `rp2040`: add support for GPIO input\n  - `rp2040`: add basic support for ADC\n  - `rp2040`: gpio and adc pin definitions\n  - `rp2040`: implement UART\n  - `rp2040`: patch elf to checksum 2nd stage boot\n  - `stm32`: add PWM for most chips\n  - `stm32`: add support for pin interrupts\n  - `stm32f103`: add support for PinInputPullup / PinInputPulldown\n  - `wasi`: remove wasm build tag\n* **boards**\n  - `feather-rp2040`: add support for this board\n  - `feather-nrf52840-sense`: add board definition for this board\n  - `pca10059`: support flashing from Windows\n  - `nano-rp2040`: add this board\n  - `nano-33-ble`: add support for this board\n  - `pico`: add the Raspberry Pi Pico board with the new RP2040 chip\n  - `qtpy`: add pin for neopixels\n  - all: add definition for ws2812 for supported boards\n\n\n0.18.0\n---\n\n* **command line**\n  - drop support for Go 1.11 and 1.12\n  - throw an error when no target is specified on Windows\n  - improve error messages in `getDefaultPort()`, support for multiple ports\n  - remove `-cflags` and `-ldflags` flags\n  - implement `-ldflags=\"-X ...\"`\n  - add `-print-allocs` flag that lets you print all heap allocations\n  - openocd commands in tinygo command line\n  - add `-llvm-features` parameter\n  - match `go test` output\n  - discover USB ports only, this will ignore f.ex. bluetooth\n  - use physicmal path instead of cached GOROOT in function getGoroot\n  - add goroot for snap installs\n* **compiler**\n  - `builder`: add support for `-opt=0`\n  - `builder`, `compiler`: compile and cache packages in parallel\n  - `builder`: run interp per package\n  - `builder`: cache C and assembly file outputs\n  - `builder`: add support for `-x` flag to print commands\n  - `builder`: add optsize attribute while building the package\n  - `builder`: run function passes per package\n  - `builder`: hard code Clang compiler\n  - `compiler`: do not use `llvm.GlobalContext()`\n  - `compiler`: remove SimpleDCE pass\n  - `compiler`: do not emit nil checks for `*ssa.Alloc` instructions\n  - `compiler`: merge `runtime.typecodeID` and runtime.typeInInterface\n  - `compiler`: do not check for impossible type asserts\n  - `compiler`: fix use of global context: `llvm.Int32Type()`\n  - `compiler`: add interface IR test\n  - `compiler`: fix lack of method name in interface matching\n  - `compiler`: fix \"fragment covers entire variable\" bug\n  - `compiler`: optimize string literals and globals\n  - `compiler`: decouple func lowering from interface type codes\n  - `compiler`: add function attributes to some runtime calls\n  - `compiler`: improve position information in error messages\n  - `cgo`: add support for CFLAGS in .c files\n  - `interp`: support GEP on fixed (MMIO) addresses\n  - `interp`: handle `(reflect.Type).Elem()`\n  - `interp`: add support for runtime.interfaceMethod\n  - `interp`: make toLLVMValue return an error instead of panicking\n  - `interp`: add support for switch statement\n  - `interp`: fix phi instruction\n  - `interp`: remove map support\n  - `interp`: support extractvalue/insertvalue with multiple operands\n  - `transform`: optimize string comparisons against \"\"\n  - `transform`: optimize `reflect.Type` `Implements()` method\n  - `transform`: fix bug in interface lowering when signatures are renamed\n  - `transform`: don't rely on struct name of `runtime.typecodeID`\n  - `transform`: use IPSCCP pass instead of the constant propagation pass\n  - `transform`: fix func lowering assertion failure\n  - `transform`: do not lower zero-sized alloc to alloca\n  - `transform`: split interface and reflect lowering\n* **standard library**\n  - `runtime`: add dummy debug package\n  - `machine`: fix data shift/mask in newUSBSetup\n  - `machine`: make `machine.I2C0` and similar objects pointers\n  - `machine`: unify usbcdc code\n  - `machine`: refactor PWM support\n  - `machine`: avoid heap allocations in USB code\n  - `reflect`: let `reflect.Type` be of interface type\n  - `reflect`: implement a number of stub functions\n  - `reflect`: check for access in the `Interface` method call\n  - `reflect`: fix `AssignableTo` and `Implements` methods\n  - `reflect`: implement `Value.CanAddr`\n  - `reflect`: implement `Sizeof` and `Alignof` for func values\n  - `reflect`: implement `New` function\n  - `runtime`: implement command line arguments in hosted environments\n  - `runtime`: implement environment variables for Linux\n  - `runtime`: improve timers on nrf, and samd chips\n* **targets**\n  - all: use -Qunused-arguments only for assembly files\n  - `atmega1280`: add PWM support\n  - `attiny`: remove dummy UART\n  - `atsamd21`: improve SPI\n  - `atsamd51`: fix PWM support in atsamd51p20\n  - `atsamd5x`: improve SPI\n  - `atsamd51`, `atsame5x`: unify samd51 and same5x\n  - `atsamd51`, `atsamd21`: fix `ADC.Get()` value at 8bit and 10bit\n  - `atsame5x`: add support for CAN\n  - `avr`: remove I2C stubs from attiny support\n  - `cortexm`: check for `arm-none-eabi-gdb` and `gdb-multiarch` commands\n  - `cortexm`: add `__isr_vector` symbol\n  - `cortexm`: disable FPU on Cortex-M4\n  - `cortexm`: clean up Cortex-M target files\n  - `fe310`: fix SPI read\n  - `gameboy-advance`: Fix RGBA color interpretation\n  - `nrf52833`: add PWM support\n  - `stm32l0`: use unified UART logic\n  - `stm32`: move f103 (bluepill) to common i2c code\n  - `stm32`: separate altfunc selection for UART Tx/Rx\n  - `stm32`: i2c implementation for F7, L5 and L4 MCUs\n  - `stm32`: make SPI CLK fast to fix data issue\n  - `stm32`: support SPI on L4 series\n  - `unix`: avoid possible heap allocation with `-opt=0`\n  - `unix`: use conservative GC by default\n  - `unix`: use the tasks scheduler instead of coroutines\n  - `wasi`: upgrade WASI version to wasi_snapshot_preview1\n  - `wasi`: darwin: support basic file io based on libc\n  - `wasm`: only export explicitly exported functions\n  - `wasm`: use WASI ABI for exit function\n  - `wasm`: scan globals conservatively\n* **boards**\n  - `arduino-mega1280`: add support for the Arduino Mega 1280\n  - `arduino-nano-new`: Add Arduino Nano w/ New Bootloader target\n  - `atsame54-xpro`: add initial support this board\n  - `feather-m4-can`: add initial support for this board\n  - `grandcentral-m4`: add board support for Adafruit Grand Central M4 (SAMD51)\n  - `lgt92`: update to new UART structure\n  - `microbit`: remove LED constant\n  - `microbit-v2`: add support for S113 SoftDevice\n  - `nucleol432`: add support for this board\n  - `nucleo-l031k6`: add this board\n  - `pca10059`: initial support for this board\n  - `qtpy`: fix msd-volume-name\n  - `qtpy`: fix i2c setting\n  - `teensy40`: move txBuffer allocation to UART declaration\n  - `teensy40`: add UART0 as alias for UART1\n\n\n0.17.0\n\n---\n* **command line**\n  - switch to LLVM 11 for static builds\n  - support gdb debugging with AVR\n  - add support for additional openocd commands\n  - add `-x` flag to print commands\n  - use LLVM 11 by default when linking LLVM dynamically\n  - update go-llvm to use LLVM 11 on macOS\n  - bump go.bug.st/serial to version 1.1.2\n  - do not build LLVM with libxml to work around a bugo on macOS\n  - add support for Go 1.16\n  - support gdb daemonization on Windows\n  - remove support for LLVM 9, to fix CI\n  - kill OpenOCD if it does not exit with a regular quit signal\n  - support `-ocd-output` on Windows\n* **compiler**\n  - `builder`: parallelize most of the build\n  - `builder`: remove unused cacheKey parameter\n  - `builder`: add -mcpu flag while building libraries\n  - `builder`: wait for running jobs to finish\n  - `cgo`: add support for variadic functions\n  - `compiler`: fix undefined behavior in wordpack\n  - `compiler`: fix incorrect \"exported function\" panic\n  - `compiler`: fix non-int integer constants (fixing a crash)\n  - `compiler`: refactor and add tests\n  - `compiler`: emit a nil check when slicing an array pointer\n  - `compiler`: saturate float-to-int conversions\n  - `compiler`: test float to int conversions and fix upper-bound calculation\n  - `compiler`: support all kinds of deferred builtins\n  - `compiler`: remove ir package\n  - `compiler`: remove unnecessary main.main call workaround\n  - `compiler`: move the setting of attributes to getFunction\n  - `compiler`: create runtime types lazily when needed\n  - `compiler`: move settings to a separate Config struct\n  - `compiler`: work around an ARM backend bug in LLVM\n  - `interp`: rewrite entire package\n  - `interp`: fix alignment of untyped globals\n  - `loader`: use name \"main\" for the main package\n  - `loader`: support imports from vendor directories\n  - `stacksize`: add support for DW_CFA_offset_extended\n  - `transform`: show better error message in coroutines lowering\n* **standard library**\n  - `machine`: accept configuration struct for ADC parameters\n  - `machine`: make I2C.Configure signature consistent\n  - `reflect`: implement PtrTo\n  - `runtime`: refactor to simplify stack switching\n  - `runtime`: put metadata at the top end of the heap\n* **targets**\n  - `atsam`: add a length check to findPinPadMapping\n  - `atsam`: improve USBCDC\n  - `atsam`: avoid infinite loop when USBCDC is disconnected\n  - `avr`: add SPI support for Atmega based chips\n  - `avr`: use Clang for compiling C and assembly files\n  - `esp32`: implement task based scheduler\n  - `esp32`: enable the FPU\n  - `esp8266`: implement task based scheduler\n  - `esp`: add compiler-rt library\n  - `esp`: add picolibc\n  - `nrf`: refactor code a bit to reduce duplication\n  - `nrf`: use SPIM peripheral instead of the legacy SPI peripheral\n  - `nrf`: update nrfx submodule to latest commit\n  - `nrf52840`: ensure that USB CDC interface is only initialized once\n  - `nrf52840`: improve USBCDC\n  - `stm32`: use stm32-rs SVDs which are of much higher quality\n  - `stm32`: harmonization of UART logic\n  - `stm32`: replace I2C addressable interface with simpler type\n  - `stm32`: fix i2c and add stm32f407 i2c\n  - `stm32`: revert change that adds support for channels in interrupts\n  - `wasm`: implement a growable heap\n  - `wasm`: fix typo in wasm_exec.js, syscall/js.valueLoadString()\n  - `wasm`: Namespaced Wasm Imports so they don't conflict across modules, or reserved LLVM IR\n  - `wasi`: support env variables based on libc\n  - `wasi`: specify wasi-libc in a different way, to improve error message\n* **boards**\n  - `matrixportal-m4`: add support for board Adafruit Matrix Portal M4\n  - `mkr1000`: add this board\n  - `nucleo-f722ze`: add this board\n  - `clue`: correct volume name and add alias for release version of Adafruit Clue board\n  - `p1am-100`: add support for the P1AM-100 (similar to Arduino MKR)\n  - `microbit-v2`: add initial support based on work done by @alankrantas thank you!\n  - `lgt92`: support for STM32L0 MCUs and Dragino LGT92 device\n  - `nicenano`: nice!nano board support\n  - `circuitplay-bluefruit`: correct internal I2C pin mapping\n  - `clue`: correct for lack of low frequency crystal\n  - `digispark`: split off attiny85 target\n  - `nucleo-l552ze`: implementation with CLOCK, LED, and UART\n  - `nrf52840-mdk-usb-dongle`: add this board\n\n0.16.0\n---\n\n* **command-line**\n  - add initial support for LLVM 11\n  - make lib64 clang include path check more robust\n  - `build`: improve support for GOARCH=386 and add tests\n  - `gdb`: add support for qemu-user targets\n  - `test`: support non-host tests\n  - `test`: add support for -c and -o flags\n  - `test`: implement some benchmark stubs\n* **compiler**\n  - `builder`: improve detection of clang on Fedora\n  - `compiler`: fix floating point comparison bugs\n  - `compiler`: implement negate for complex numbers\n  - `loader`: fix linkname in test binaries\n  - `transform`: add missing return pointer restore for regular coroutine tail\n    calls\n* **standard library**\n  - `machine`: switch default frequency to 4MHz\n  - `machine`: clarify caller's responsibility in `SetInterrupt`\n  - `os`: add `LookupEnv()` stub\n  - `reflect`: implement `Swapper`\n  - `runtime`: fix UTF-8 decoding\n  - `runtime`: gc: use raw stack access whenever possible\n  - `runtime`: use dedicated printfloat32\n  - `runtime`: allow ranging over a nil map\n  - `runtime`: avoid device/nxp dependency in HardFault handler\n  - `testing`: implement dummy Helper method\n  - `testing`: add Run method\n* **targets**\n  - `arm64`: add support for SVCall intrinsic\n  - `atsamd51`: avoid panic when configuring SPI with SDI=NoPin\n  - `avr`: properly support the `.rodata` section\n  - `esp8266`: implement `Pin.Get` function\n  - `nintendoswitch`: fix crash when printing long lines (> 120)\n  - `nintendoswitch`: add env parser and removed unused stuff\n  - `nrf`: add I2C error checking\n  - `nrf`: give more flexibility in picking SPI speeds\n  - `nrf`: fix nrf52832 flash size\n  - `stm32f103`: support wakeups from interrupts\n  - `stm32f405`: add SPI support\n  - `stm32f405`: add I2C support\n  - `wasi`: add support for this target\n  - `wasi`: use 'generic' ABI by default\n  - `wasi`: remove --no-threads flag from wasm-ld\n  - `wasm`: add instanceof support for WebAssembly\n  - `wasm`: use fixed length buffer for putchar\n* **boards**\n  - `d1mini`: add this ESP8266 based board\n  - `esp32`: use board definitions instead of chip names\n  - `qtpy`: add board definition for Adafruit QTPy\n  - `teensy40`: add this board\n\n0.15.0\n---\n\n* **command-line**\n  - add cached GOROOT to info subcommand\n  - embed git-hash in tinygo-dev executable\n  - implement tinygo targets to list usable targets\n  - use simpler file copy instead of file renaming to avoid issues on nrf52840 UF2 bootloaders\n  - use ToSlash() to specify program path\n  - support flashing esp32/esp8266 directly from tinygo\n  - when flashing call PortReset only on other than openocd\n* **compiler**\n  - `compileopts`: add support for custom binary formats\n  - `compiler`: improve display of goroutine wrappers\n  - `interp`: don't panic in the Store method\n  - `interp`: replace some panics with error messages\n  - `interp`: show error line in first line of the traceback\n  - `loader`: be more robust when creating the cached GOROOT\n  - `loader`: rewrite/refactor much of the code to use go list directly\n  - `loader`: use ioutil.TempDir to create a temporary directory\n  - `stacksize`: deal with DW_CFA_advance_loc1\n* **standard library**\n  - `runtime`: use waitForEvents when appropriate\n* **wasm**\n  - `wasm`: Remove --no-threads from wasm-ld calls.\n  - `wasm`: update wasi-libc dependency\n* **targets**\n  - `arduino-mega2560`: fix flashing on Windows\n  - `arm`: automatically determine stack sizes\n  - `arm64`: make dynamic loader structs and constants private\n  - `avr`: configure emulator in board files\n  - `cortexm`: fix stack size calculation with interrupts\n  - `flash`: add openocd settings to atsamd21 / atsamd51\n  - `flash`: add openocd settings to nrf5\n  - `microbit`: reelboard: flash using OpenOCD when needed\n  - `nintendoswitch`: Add dynamic loader for runtime loading PIE sections\n  - `nintendoswitch`: fix import cycle on dynamic_arm64.go\n  - `nintendoswitch`: Fix invalid memory read / write in print calls\n  - `nintendoswitch`: simplified assembly code\n  - `nintendoswitch`: support outputting .nro files directly\n* **boards**\n  - `arduino-zero`: Adding support for the Arduino Zero (#1365)\n  - `atsamd2x`: fix BAUD value\n  - `atsamd5x`: fix BAUD value\n  - `bluepill`: Enable stm32's USART2 for the board and map it to UART1 tinygo's device\n  - `device/atsamd51x`: add all remaining bitfield values for PCHCTRLm Mapping\n  - `esp32`: add libgcc ROM functions to linker script\n  - `esp32`: add SPI support\n  - `esp32`: add support for basic GPIO\n  - `esp32`: add support for the Espressif ESP32 chip\n  - `esp32`: configure the I/O matrix for GPIO pins\n  - `esp32`: export machine.PortMask* for bitbanging implementations\n  - `esp8266`: add support for this chip\n  - `machine/atsamd51x,runtime/atsamd51x`: fixes needed for full support for all PWM pins. Also adds some useful constants to clarify peripheral clock usage\n  - `machine/itsybitsy-nrf52840`: add support for Adafruit Itsybitsy nrf52840 (#1243)\n  - `machine/stm32f4`: refactor common code and add new build tag stm32f4 (#1332)\n  - `nrf`: add SoftDevice support for the Circuit Playground Bluefruit\n  - `nrf`: call sd_app_evt_wait when the SoftDevice is enabled\n  - `nrf52840`: add build tags for SoftDevice support\n  - `nrf52840`: use higher priority for USB-CDC code\n  - `runtime/atsamd51x`: use PCHCTRL_GCLK_SERCOMX_SLOW for setting clocks on all SERCOM ports\n  - `stm32f405`: add basic UART handler\n  - `stm32f405`: add STM32F405 machine/runtime, and new board/target feather-stm32f405\n* **build**\n  - `all`: run test binaries in the correct directory\n  - `build`: Fix arch release job\n  - `ci`: run `tinygo test` for known-working packages\n  - `ci`: set git-fetch-depth to 1\n  - `docker`: fix the problem with the wasm build (#1357)\n  - `Makefile`: check whether submodules have been downloaded in some common cases\n* **docs**\n  - add ESP32, ESP8266, and Adafruit Feather STM32F405 to list of supported boards\n\n0.14.1\n---\n* **command-line**\n  - support for Go 1.15\n* **compiler**\n  - loader:  work around Windows symlink limitation\n\n0.14.0\n---\n* **command-line**\n  - fix `getDefaultPort()` on non-English Windows locales\n  - compileopts: improve error reporting of unsupported flags\n  - fix test subcommand\n  - use auto-retry to locate MSD for UF2 and HEX flashing\n  - fix touchSerialPortAt1200bps on Windows\n  - support package names with backslashes on Windows\n* **compiler**\n  - fix a few crashes due to named types\n  - add support for atomic operations\n  - move the channel blocked list onto the stack\n  - fix -gc=none\n  - fix named string to `[]byte` slice conversion\n  - implement func value and builtin defers\n  - add proper parameter names to runtime.initAll, to fix a panic\n  - builder: fix picolibc include path\n  - builder: use newer version of gohex\n  - builder: try to determine stack size information at compile time\n  - builder: remove -opt=0\n  - interp: fix sync/atomic.Value load/store methods\n  - loader: add Go module support\n  - transform: fix debug information in func lowering pass\n  - transform: do not special-case zero or one implementations of a method call\n  - transform: introduce check for method calls on nil interfaces\n  - transform: gc: track 0-index GEPs to fix miscompilation\n* **cgo**\n  - Add LDFlags support\n* **standard library**\n  - extend stdlib to allow import of more packages\n  - replace master/slave terminology with appropriate alternatives (MOSI->SDO\n    etc)\n  - `internal/bytealg`: reimplement bytealg in pure Go\n  - `internal/task`: fix nil panic in (*internal/task.Stack).Pop\n  - `os`: add Args and stub it with mock data\n  - `os`: implement virtual filesystem support\n  - `reflect`: add Cap and Len support for map and chan\n  - `runtime`: fix return address in scheduler on RISC-V\n  - `runtime`: avoid recursion in printuint64 function\n  - `runtime`: replace ReadRegister with AsmFull inline assembly\n  - `runtime`: fix compilation errors when using gc.extalloc\n  - `runtime`: add cap and len support for chans\n  - `runtime`: refactor time handling (improving accuracy)\n  - `runtime`: make channels work in interrupts\n  - `runtime/interrupt`: add cross-chip disable/restore interrupt support\n  - `sync`: implement `sync.Cond`\n  - `sync`: add WaitGroup\n* **targets**\n  - `arm`: allow nesting in DisableInterrupts and EnableInterrupts\n  - `arm`: make FPU configuration consistent\n  - `arm`: do not mask fault handlers in critical sections\n  - `atmega2560`: fix pin mapping for pins D2, D5 and the L port\n  - `atsamd`: return an error when an incorrect PWM pin is used\n  - `atsamd`: add support for pin change interrupts\n  - `atsamd`: add DAC support\n  - `atsamd21`: add more ADC pins\n  - `atsamd51`: fix ROM / RAM size on atsamd51j20\n  - `atsamd51`: add more pins\n  - `atsamd51`: add more ADC pins\n  - `atsamd51`: add pin change interrupt settings\n  - `atsamd51`: extend pinPadMapping\n  - `arduino-nano33`: use (U)SB flag to ensure that device can be found when\n     not on default port\n  - `arduino-nano33`: remove (d)ebug flag to reduce console noise when flashing\n  - `avr`: use standard pin numbering\n  - `avr`: unify GPIO pin/port code\n  - `avr`: add support for PinInputPullup\n  - `avr`: work around codegen bug in LLVM 10\n  - `avr`: fix target triple\n  - `fe310`: remove extra println left in by mistake\n  - `feather-nrf52840`: add support for the Feather nRF52840\n  - `maixbit`: add board definition and dummy runtime\n  - `nintendoswitch`: Add experimental Nintendo Switch support without CRT\n  - `nrf`: expose the RAM base address\n  - `nrf`: add support for pin change interrupts\n  - `nrf`: add microbit-s110v8 target\n  - `nrf`: fix bug in SPI.Tx\n  - `nrf`: support debugging the PCA10056\n  - `pygamer`: add Adafruit PyGamer support\n  - `riscv`: fix interrupt configuration bug\n  - `riscv`: disable linker relaxations during gp init\n  - `stm32f4disco`: add new target with ST-Link v2.1 debugger\n  - `teensy36`: add Teensy 3.6 support\n  - `wasm`: fix event handling\n  - `wasm`: add --no-demangle linker option\n  - `wioterminal`: add support for the Seeed Wio Terminal\n  - `xiao`: add support for the Seeed XIAO\n\n0.13.1\n---\n* **standard library**\n  - `runtime`: do not put scheduler and GC code in the same section\n  - `runtime`: copy stack scan assembly for GBA\n* **boards**\n  - `gameboy-advance`: always use ARM mode instead of Thumb mode\n\n\n0.13.0\n---\n* **command line**\n  - use `gdb-multiarch` for debugging Cortex-M chips\n  - support `tinygo run` with simavr\n  - support LLVM 10\n  - support Go 1.14\n  - retry 3 times when attempting to do a 1200-baud reset\n* **compiler**\n  - mark the `abort` function as noreturn\n  - fix deferred calls to exported functions\n  - add debug info for local variables\n  - check for channel size limit\n  - refactor coroutine lowering\n  - add `dereferenceable_or_null` attribute to pointer parameters\n  - do not perform nil checking when indexing slices and on `unsafe.Pointer`\n  - remove `runtime.isnil` hack\n  - use LLVM builtins for runtime `memcpy`/`memmove`/`memzero` functions\n  - implement spec-compliant shifts on negative/overflow\n  - support anonymous type asserts\n  - track pointer result of string concatenation for GC\n  - track PHI nodes for GC\n  - add debug info to goroutine start wrappers\n  - optimize comparing interface values against nil\n  - fix miscompilation when deferring an interface call\n  - builder: include picolibc for most baremetal targets\n  - builder: run tools (clang, lld) as separate processes\n  - builder: use `-fshort-enums` consistently\n  - interp: add support for constant type asserts\n  - interp: better support for interface operations\n  - interp: include backtrace with error\n  - transform: do not track const globals for GC\n  - transform: replace panics with source locations\n  - transform: fix error in interface lowering pass\n  - transform: make coroutine lowering deterministic\n  - transform: fix miscompilation in func lowering\n* **cgo**\n  - make `-I` and `-L` paths absolute\n* **standard library**\n  - `machine`: set the USB VID and PID to the manufacturer values\n  - `machine`: correct USB CDC composite descriptors\n  - `machine`: move `errors.New` calls to globals\n  - `runtime`: support operations on nil maps\n  - `runtime`: fix copy builtin return value on AVR\n  - `runtime`: refactor goroutines\n  - `runtime`: support `-scheduler=none` on most platforms\n  - `runtime`: run package initialization in the main goroutine\n  - `runtime`: export `malloc` / `free` for use from C\n  - `runtime`: add garbage collector that uses an external allocator\n  - `runtime`: scan callee-saved registers while marking the stack\n  - `runtime`: remove recursion from conservative GC\n  - `runtime`: fix blocking select on nil channel\n  - `runtime/volatile`: include `ReplaceBits` method\n  - `sync`: implement trivial `sync.Map`\n* **targets**\n  - `arm`: use `-fomit-frame-pointer`\n  - `atmega1284`: support this chip for testing purposes\n  - `atsamd51`: make QSPI available on all boards\n  - `atsamd51`: add support for ADC1\n  - `atsamd51`: use new interrupt registration in UART code\n  - `attiny`: clean up pin definitions\n  - `avr`: use the correct RAM start address\n  - `avr`: pass the correct `-mmcu` flag to the linker\n  - `avr`: add support for tasks scheduler (disabled by default)\n  - `avr`: fix linker problem with overlapping program/data areas\n  - `nrf`: fix typo in pin configuration options\n  - `nrf`: add lib/nrfx/mdk to include dirs\n  - `nrf52840`: implement USB-CDC\n  - `riscv`: implement VirtIO target and add RISC-V integration test\n  - `riscv`: add I2C support for the HiFive1 rev B board\n  - `stm32`: refactor GPIO pin handling\n  - `stm32`: refactor UART code\n  - `stm32f4`: add SPI\n  - `wasm`: support Go 1.14 (breaking previous versions)\n  - `wasm`: support `syscall/js.CopyBytesToJS`\n  - `wasm`: sync polyfills from Go 1.14.\n* **boards**\n  - `arduino-mega2560`: add the Arduino Mega 2560\n  - `clue-alpha`: add the Adafruit CLUE Alpha\n  - `gameboy-advance`: enable debugging with GDB\n  - `particle-argon`: add the Particle Argon board\n  - `particle-boron`: add the Particle Boron board\n  - `particle-xenon`: add the Particle Xenon board\n  - `reelboard`: add `reelboard-s140v7` SoftDevice target\n\n0.12.0\n---\n* **command line**\n  - add initial FreeBSD support\n  - remove getting a serial port in gdb subcommand\n  - add support for debugging through JLinkGDBServer\n  - fix CGo when cross compiling\n  - remove default port check for Digispark as micronucleus communicates directly using HID\n  - differentiate between various serial/USB error messages\n* **builder**\n  - improve detection of Clang headers\n* **compiler**\n  - fix assertion on empty interface\n  - don't crash when encountering `types.Invalid`\n  - revise defer to use heap allocations when running a variable number of times\n  - improve error messages for failed imports\n  - improve \"function redeclared\" error\n  - add globaldce pass to start of optimization pipeline\n  - add support for debugging globals\n  - implement RISC-V CSR operations as intrinsics\n  - add support for CGO_ENABLED environment variable\n  - do not emit debug info for extern globals (bugfix)\n  - add support for interrupts\n  - implement maps for arbitrary keys\n  - interp: error location for \"unknown GEP\" error\n  - wasm-abi: create temporary allocas in the entry block\n* **cgo**\n  - add support for symbols in `#define`\n  - fix a bug in number tokenization\n* **standard library**\n  - `machine`: avoid bytes package in USB logic\n  - `runtime`: fix external address declarations\n  - `runtime`: provide implementation for `internal/bytealg.IndexByte`\n* **targets**\n  - `atsamd51`: fix volatile usage\n  - `atsamd51`: fix ADC, updating to 12-bits precision\n  - `atsamd51`: refactor SPI pin configuration to only look at pin numbers\n  - `atsamd51`: switch UART to use new pin configuration\n  - `atsamd51`: fix obvious bug in I2C code\n  - `atsamd51`: use only the necessary UART interrupts\n  - `atsamd51`: refactor I2C pin handling to auto-detect pin mode\n  - `avr`: use a garbage collector\n  - `fe310`: use CLINT peripheral for timekeeping\n  - `fe310`: add support for PLIC interrupts\n  - `fe310`: implement UART receive interrupts\n  - `riscv`: support sleeping in QEMU\n  - `riscv`: add bare-bones interrupt support\n  - `riscv`: print exception PC and code\n  - `wasm`: implement memcpy and memset\n  - `wasm`: include wasi-libc\n  - `wasm`: use wasi ABI for basic startup/stdout\n* **boards**\n  - `arduino`: make avrdude command line compatible with Windows\n  - `arduino-nano`: add this board\n  - `arduino-nano33`: fix UART1 and UART2\n  - `circuitplay-bluefruit`: add this board\n  - `digispark`: add clock speed and pin mappings\n  - `gameboy-advance`: include compiler-rt in build\n  - `gameboy-advance`: implement interrupt handler\n  - `hifive1b`: add support for gdb subcommand\n  - `pyportal`: add this board\n  - `pyportal`: remove manual SPI pin mapping as now handled by default\n\n\n0.11.0\n---\n* **command line**\n  - add support for QEMU in `gdb` subcommand\n  - use builtin Clang when building statically, dropping the clang-9 dependency\n  - search for default serial port on both macOS and Linux\n  - windows: support `tinygo flash` directly by using win32 wmi\n* **compiler**\n  - add location information to the IR checker\n  - make reflection sidetables constant globals\n  - improve error locations in goroutine lowering\n  - interp: improve support for maps with string keys\n  - interp: add runtime fallback for mapassign operations\n* **standard library**\n  - `machine`: add support for `SPI.Tx()` on play.tinygo.org\n  - `machine`: rename `CPU_FREQUENCY` to `CPUFrequency()`\n* **targets**\n  - `adafruit-pybadge`: add Adafruit Pybadge\n  - `arduino-nano33`: allow simulation on play.tinygo.org\n  - `arduino-nano33`: fix default SPI pin numbers to be D13/D11/D12\n  - `circuitplay-express`: allow simulation on play.tinygo.org\n  - `hifive1-qemu`: add target for testing RISC-V bare metal in QEMU\n  - `riscv`: fix heap corruption due to changes in LLVM 9\n  - `riscv`: add support for compiler-rt\n  - `qemu`: rename to `cortex-m-qemu`\n\n0.10.0\n---\n* **command line**\n  - halt GDB after flashing with `gdb` subcommand\n  - fix a crash when using `-ocd-output`\n  - add `info` subcommand\n  - add `-programmer` flag\n* **builder**\n  - macos: use llvm@8 instead of just llvm in paths\n  - add `linkerscript` key to target JSON files\n  - write a symbol table when writing out the compiler-rt lib\n  - make Clang header detection more robust\n  - switch to LLVM 9\n* **compiler**\n  - fix interface miscompilation with reflect\n  - fix miscompile of static goroutine calls to closures\n  - fix `todo: store` panic\n  - fix incorrect starting value for optimized allocations in a loop\n  - optimize coroutines on non-Cortex-M targets\n  - fix crash for programs which have heap allocations but never hit the GC\n  - add support for async interface calls\n  - fix inserting non-const values in a const global\n  - interp: improve error reporting\n  - interp: implement comparing ptrtoint to 0\n* **cgo**\n  - improve diagnostics\n  - implement the constant parser (for `#define`) as a real parser\n  - rename reserved field names such as `type`\n  - avoid `\"unsafe\" imported but not used` error\n  - include all enums in the CGo Go AST\n  - add support for nested structs and unions\n  - implement `#cgo CFLAGS`\n* **standard library**\n  - `reflect`: add implementation of array alignment\n  - `runtime`: improve scheduler performance when no goroutines are queued\n  - `runtime`: add blocking select\n  - `runtime`: implement interface equality in non-trivial cases\n  - `runtime`: add AdjustTimeOffset to update current time\n  - `runtime`: only implement CountString for required platforms\n  - `runtime`: use MSP/PSP registers for scheduling on Cortex-M\n* **targets**\n  - `arm`: add system timer registers\n  - `atmega`: add port C GPIO support\n  - `atsamd21`: correct handling of pins >= 32\n  - `atsamd21`: i2s initialization fixes\n  - `atsamd51`: fix clock init code\n  - `atsamd51`: correct initialization for RTC\n  - `atsamd51`: fix pin function selection\n  - `atsamd51`: pin method cleanup\n  - `atsamd51`: allow setting pin mode for each of the SPI pins\n  - `atsamd51`: correct channel init and pin map for ADC based on ItsyBitsy-M4\n  - `feather-m4`: add Adafruit Feather M4 board\n  - `hifive1b`: add support for SPI1\n  - `hifive1b`: fix compiling in simulation\n  - `linux`: fix time on arm32\n  - `metro-m4`: add support for Adafruit Metro M4 Express Airlift board\n  - `metro-m4`: fixes for UART2\n  - `pinetime-devkit0`: add support for the PineTime dev kit\n  - `x9pro`: add support for this smartwatch\n  - `pca10040-s132v6`: add support for SoftDevice\n  - `pca10056-s140v7`: add support for SoftDevice\n  - `arduino-nano33`: added SPI1 connected to NINA-W102 chip on Arduino Nano 33 IOT\n\n0.9.0\n---\n* **command line**\n  - implement 1200-baud UART bootloader reset when flashing boards that support\n    it\n  - flash using mass-storage device for boards that support it\n  - implement `tinygo env`\n  - add support for Windows (but not yet producing Windows binaries)\n  - add Go version to `tinygo env`\n  - update SVD files for up-to-date peripheral interfaces\n* **compiler**\n  - add `//go:align` pragma\n  - fix bug related to type aliases\n  - add support for buffered channels\n  - remove incorrect reflect optimization\n  - implement copying slices in init interpretation\n  - add support for constant indices with a named type\n  - add support for recursive types like linked lists\n  - fix miscompile of function nil panics\n  - fix bug related to goroutines\n* **standard library**\n  - `machine`: do not check for nil slices in `SPI.Tx`\n  - `reflectlite`: add support for Go 1.13\n  - `runtime`: implement `internal/bytealg.CountString`\n  - `sync`: properly handle nil `New` func in `sync.Pool`\n* **targets**\n  - `arduino`: fix .bss section initialization\n  - `fe310`: implement `Pin.Get`\n  - `gameboy-advance`: support directly outputting .gba files\n  - `samd`: reduce code size by avoiding reflection\n  - `samd21`: do not hardcode pin numbers for peripherals\n  - `stm32f103`: avoid issue with `time.Sleep` less than 200µs\n\n0.8.0\n---\n* **command line**\n  - fix parsing of beta Go versions\n  - check the major/minor installed version of Go before compiling\n  - validate `-target` flag better to not panic on an invalid target\n* **compiler**\n  - implement full slice expression: `s[:2:4]`\n  - fix a crash when storing a linked list in an interface\n  - fix comparing struct types by making type IDs more unique\n  - fix some bugs in IR generation\n  - add support for linked lists in reflect data\n  - implement `[]rune` to string conversion\n  - implement support for `go` on func values\n* **standard library**\n  - `reflect`: add support for named types\n  - `reflect`: add support for `t.Bits()`\n  - `reflect`: add basic support for `t.AssignableTo()`\n  - `reflect`: implement `t.Align()`\n  - `reflect`: add support for struct types\n  - `reflect`: fix bug in `v.IsNil` and `v.Pointer` for addressable values\n  - `reflect`: implement support for array types\n  - `reflect`: implement `t.Comparable()`\n  - `runtime`: implement stack-based scheduler\n  - `runtime`: fix bug in the sleep queue of the scheduler\n  - `runtime`: implement `memcpy` for Cortex-M\n  - `testing`: implement stub `testing.B` struct\n  - `testing`: add common test logging methods such as Errorf/Fatalf/Printf\n* **targets**\n  - `386`: add support for linux/386 syscalls\n  - `atsamd21`: make SPI pins configurable so that multiple SPI ports can be\n    used\n  - `atsamd21`: correct issue with invalid first reading coming from ADC\n  - `atsamd21`: add support for reset-to-bootloader using 1200baud over USB-CDC\n  - `atsamd21`: make pin selection more flexible for peripherals\n  - `atsamd21`: fix minimum delay in `time.Sleep`\n  - `atsamd51`: fix minimum delay in `time.Sleep`\n  - `nrf`: improve SPI write-only speed, by making use of double buffering\n  - `stm32f103`: fix SPI frequency selection\n  - `stm32f103`: add machine.Pin.Get method for reading GPIO values\n  - `stm32f103`: allow board specific UART usage\n  - `nucleo-f103rb`: add support for NUCLEO-F103RB board\n  - `itsybitsy-m4`: add support for this board with a SAMD51 family chip\n  - `cortex-m`: add support for `arm.SystemReset()`\n  - `gameboy-advance`: add initial support for the GameBoy Advance\n  - `wasm`: add `//go:wasm-module` magic comment to set the wasm module name\n  - `wasm`: add syscall/js.valueSetIndex support\n  - `wasm`: add syscall/js.valueInvoke support\n\n0.7.1\n---\n* **targets**\n  - `atsamd21`: add support for the `-port` flag in the flash subcommand\n\n0.7.0\n---\n* **command line**\n  - try more locations to find Clang built-in headers\n  - add support for `tinygo test`\n  - build current directory if no package is specified\n  - support custom .json target spec with `-target` flag\n  - use zversion.go to detect version of GOROOT version\n  - make initial heap size configurable for some targets (currently WebAssembly\n    only)\n* **cgo**\n  - add support for bitfields using generated getters and setters\n  - add support for anonymous structs\n* **compiler**\n  - show an error instead of panicking on duplicate function definitions\n  - allow packages like github.com/tinygo-org/tinygo/src/\\* by aliasing it\n  - remove `//go:volatile` support  \n    It has been replaced with the runtime/volatile package.\n  - allow pointers in map keys\n  - support non-constant syscall numbers\n  - implement non-blocking selects\n  - add support for the `-tags` flag\n  - add support for `string` to `[]rune` conversion\n  - implement a portable conservative garbage collector (with support for wasm)\n  - add the `//go:noinline` pragma\n* **standard library**\n  - `os`: add `os.Exit` and `syscall.Exit`\n  - `os`: add several stubs\n  - `runtime`: fix heap corruption in conservative GC\n  - `runtime`: add support for math intrinsics where supported, massively\n    speeding up some benchmarks\n  - `testing`: add basic support for testing\n* **targets**\n  - add support for a generic target that calls `__tinygo_*` functions for\n    peripheral access\n  - `arduino-nano33`: add support for this board\n  - `hifive1`: add support for this RISC-V board\n  - `reelboard`: add e-paper pins\n  - `reelboard`: add `PowerSupplyActive` to enable voltage for on-board devices\n  - `wasm`: put the stack at the start of linear memory, to detect stack\n    overflows\n\n0.6.0\n---\n* **command line**\n  - some portability improvements\n  - make `$GOROOT` more robust and configurable\n  - check for Clang at the Homebrew install location as fallback\n* **compiler driver**\n  - support multiple variations of LLVM commands, for non-Debian distributions\n* **compiler**\n  - improve code quality in multiple ways\n  - make panic configurable, adding trap on panic\n  - refactor many internal parts of the compiler\n  - print all errors encountered during compilation\n  - implement calling function values of a named type\n  - implement returning values from blocking functions\n  - allow larger-than-int values to be sent across a channel\n  - implement complex arithmetic\n  - improve hashmap support\n  - add debuginfo for function arguments\n  - insert nil checks on stores (increasing code size)\n  - implement volatile operations as compiler builtins\n  - add `//go:inline` pragma\n  - add build tags for the Go stdlib version\n* **cgo**\n  - implement `char`, `enum` and `void*` types\n  - support `#include` for builtin headers\n  - improve typedef/struct/enum support\n  - only include symbols that are necessary, for broader support\n  - mark external function args as `nocapture`\n  - implement support for some `#define` constants\n  - implement support for multiple CGo files in a single package\n- **standard library**\n  - `machine`: remove microbit matrix (moved to drivers repository)\n  - `machine`: refactor pins to use `Pin` type instead of `GPIO`\n  - `runtime`: print more interface types on panic, including `error`\n* **targets**\n  - `arm`: print an error on HardFault (including stack overflows)\n  - `atsamd21`: fix a bug in the ADC peripheral\n  - `atsamd21`: add support for I2S\n  - `feather-m0`: add support for this board\n  - `nrf51`: fix a bug in I2C\n  - `stm32f103xx`: fix a bug in I2C\n  - `syscall`: implement `Exit` on unix\n  - `trinket-m0`: add support for this board\n  - `wasm`: make _main_ example smaller\n  - `wasm`: don't cache wasm file in the server, for ease of debugging\n  - `wasm`: work around bug #41508 that caused a deadlock while linking\n  - `wasm`: add support for `js.FuncOf`\n\n0.5.0\n---\n- **compiler driver**\n  - use `wasm-ld` instead of `wasm-ld-8` on macOS\n  - drop dependency on `llvm-ar`\n  - fix linker script includes when running outside `TINYGOROOT`\n- **compiler**\n  - switch to LLVM 8\n  - add support for the Go 1.12 standard library (Go 1.11 is still supported)\n  - work around lack of escape analysis due to nil checks\n  - implement casting named structs and pointers to them\n  - fix int casting to use the source signedness\n  - fix some bugs around `make([]T, …)` with uncommon index types\n  - some other optimizations\n  - support interface asserts in interp for \"math/rand\" support\n  - resolve all func value targets at compile time (wasm-only at the moment)\n- **cgo**\n  - improve diagnostics\n  - implement C `struct`, `union`, and arrays\n  - fix CGo-related crash in libclang\n  - implement `C.struct_` types\n- **targets**\n  - all baremetal: pretend to be linux/arm instead of js/wasm\n  - `avr`: improve `uintptr` support\n  - `cortexm`: implement memmove intrinsic generated by LLVM\n  - `cortexm`: use the lld linker instead of `arm-none-eabi-ld`\n  - `darwin`: use custom syscall package that links to libSystem.dylib\n  - `microbit`: add blink example\n  - `samd21`: support I2C1\n  - `samd21`: machine/atsamd21: correct pad/pin handling when using both UART\n     and USBCDC interfaces at same time\n  - `stm32f4discovery`: add support for this board\n  - `wasm`: support async func values\n  - `wasm`: improve documentation and add extra example\n\n0.4.1\n---\n- **compiler**\n  - fix `objcopy` replacement to include the .data section in the firmware image\n  - use `llvm-ar-7` on Linux to fix the Docker image\n\n0.4.0\n---\n- **compiler**\n  - switch to the hardfloat ABI on ARM, which is more widely used\n  - avoid a dependency on `objcopy` (`arm-none-eabi-objcopy` etc.)\n  - fix a bug in `make([]T, n)` where `n` is 64-bits on a 32-bit platform\n  - adapt to a change in the AVR backend in LLVM 8\n  - directly support the .uf2 firmware format as used on Adafruit boards\n  - fix a bug when calling `panic()` at init time outside of the main package\n  - implement nil checks, which results in a ~5% increase in code size\n  - inline slice bounds checking, which results in a ~1% decrease in code size\n- **targets**\n  - `samd21`: fix a bug in port B pins\n  - `samd21`: implement SPI peripheral\n  - `samd21`: implement ADC peripheral\n  - `stm32`: fix a bug in timekeeping\n  - `wasm`: fix a bug in `wasm_exec.js` that caused corruption in linear memory\n     when running on Node.js.\n\n0.3.0\n---\n- **compiler**\n  - remove old `-initinterp` flag\n  - add support for macOS\n- **cgo**\n  - add support for bool/float/complex types\n- **standard library**\n  - `device/arm`: add support to disable/enable hardware interrupts\n  - `machine`: add CPU frequency for nrf-based boards\n  - `syscall`: add support for darwin/amd64\n- **targets**\n  - `circuitplay_express`: add support for this board\n  - `microbit`: add regular pin constants\n  - `samd21`: fix time function for goroutine support\n  - `samd21`: add support for USB-CDC (serial over USB)\n  - `samd21`: add support for pins in port B\n  - `samd21`: add support for pullup and pulldown pins\n  - `wasm`: add support for Safari in example\n\n\n0.2.0\n---\n- **command line**\n  - add version subcommand\n- **compiler**\n  - fix a bug in floating point comparisons with NaN values\n  - fix a bug when calling `panic` in package initialization code\n  - add support for comparing `complex64` and `complex128`\n- **cgo**\n  - add support for external globals\n  - add support for pointers and function pointers\n- **standard library**\n  - `fmt`: initial support, `fmt.Println` works\n  - `math`: support for most/all functions\n  - `os`: initial support (only stdin/stdout/stderr)\n  - `reflect`: initial support\n  - `syscall`: add support for amd64, arm, and arm64\n"
  },
  {
    "path": "CODE-OF-CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to make participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, sex characteristics, gender identity and expression,\nlevel of experience, education, socio-economic status, nationality, personal\nappearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\n  advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n  address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies within all project spaces, and it also applies when\nan individual is representing the project or its community in public spaces.\nExamples of representing a project or community include using an official\nproject e-mail address, posting via an official social media account, or acting\nas an appointed representative at an online or offline event. Representation of\na project may be further defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project team at [conduct@tinygo.org](mailto:conduct@tinygo.org). All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see\nhttps://www.contributor-covenant.org/faq\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "Please take a look at our [Contributing](https://tinygo.org/docs/guides/contributing/) page on our web site for details. Thank you.\n"
  },
  {
    "path": "CONTRIBUTORS",
    "content": "# This is the official list of TinyGo authors for copyright purposes.\n#\n# This file is not actively maintained.\n# To be included, send a change adding the individual or\n# company who owns a contribution's copyright.\n#\n# Names should be added to this file as one of\n#     Organization's name\n#     Individual's name <submission email address>\n#     Individual's name <submission email address> <email2> <emailN>\n#\n# Please keep the list sorted.\n\nAyke van Laethem <aykevanlaethem@gmail.com>\nDaniel Esteban <conejo@conejo.me>\nLoon, LLC.\nRon Evans <ron@hybridgroup.com>\nNia Weiss <niaow1234@gmail.com>\n"
  },
  {
    "path": "Dockerfile",
    "content": "# tinygo-llvm stage obtains the llvm source for TinyGo\nFROM golang:1.25 AS tinygo-llvm\n\nRUN apt-get update && \\\n    apt-get install -y apt-utils make cmake clang-17 ninja-build && \\\n    rm -rf \\\n        /var/lib/apt/lists/* \\\n        /var/log/* \\\n        /var/tmp/* \\\n        /tmp/*\n\nCOPY ./GNUmakefile /tinygo/GNUmakefile\n\nRUN cd /tinygo/ && \\\n    make llvm-source\n\n# tinygo-llvm-build stage build the custom llvm with xtensa support\nFROM tinygo-llvm AS tinygo-llvm-build\n\nRUN cd /tinygo/ && \\\n    make llvm-build\n\n# tinygo-compiler-build stage builds the compiler itself\nFROM tinygo-llvm-build AS tinygo-compiler-build\n\nCOPY . /tinygo\n\n# build the compiler and tools\nRUN cd /tinygo/ && \\\n    git submodule update --init && \\\n    make gen-device -j4 && \\\n    make build/release\n\n# tinygo-compiler copies the compiler build over to a base Go container (without\n# all the build tools etc).\nFROM golang:1.25 AS tinygo-compiler\n\n# Copy tinygo build.\nCOPY --from=tinygo-compiler-build /tinygo/build/release/tinygo /tinygo\n\n# Configure the container.\nENV PATH=\"${PATH}:/tinygo/bin\"\nCMD [\"tinygo\"]\n"
  },
  {
    "path": "GNUmakefile",
    "content": "\n# aliases\nall: tinygo\n\n# Default build and source directories, as created by `make llvm-build`.\nLLVM_BUILDDIR ?= llvm-build\nLLVM_PROJECTDIR ?= llvm-project\nCLANG_SRC ?= $(LLVM_PROJECTDIR)/clang\nLLD_SRC ?= $(LLVM_PROJECTDIR)/lld\n\nifeq ($(OS),Windows_NT)\n    # avoid calling uname on Windows\n    uname := Windows_NT\nelse\n    uname := $(shell uname -s)\nendif\n\n# Try to autodetect LLVM build tools.\n# Versions are listed here in descending priority order.\nLLVM_VERSIONS = 19 18 17 16 15\nerrifempty = $(if $(1),$(1),$(error $(2)))\ndetect = $(shell which $(call errifempty,$(firstword $(foreach p,$(2),$(shell command -v $(p) 2> /dev/null && echo $(p)))),failed to locate $(1) at any of: $(2)))\ntoolSearchPathsVersion = $(1)-$(2)\nifeq ($(uname),Darwin)\n\t# Also explicitly search Brew's copy, which is not in PATH by default.\n\tBREW_PREFIX := $(shell brew --prefix)\n\ttoolSearchPathsVersion += $(BREW_PREFIX)/opt/llvm@$(2)/bin/$(1)-$(2) $(BREW_PREFIX)/opt/llvm@$(2)/bin/$(1)\nendif\n# First search for a custom built copy, then move on to explicitly version-tagged binaries, then just see if the tool is in path with its normal name.\nfindLLVMTool = $(call detect,$(1),$(abspath llvm-build/bin/$(1)) $(foreach ver,$(LLVM_VERSIONS),$(call toolSearchPathsVersion,$(1),$(ver))) $(1))\nCLANG ?= $(call findLLVMTool,clang)\nLLVM_AR ?= $(call findLLVMTool,llvm-ar)\nLLVM_NM ?= $(call findLLVMTool,llvm-nm)\n\n# Go binary and GOROOT to select\nGO ?= go\n\n# Flags to pass to go test.\nGOTESTFLAGS ?=\nGOTESTPKGS ?= ./builder ./cgo ./compileopts ./compiler ./interp ./transform .\n\n# tinygo binary for tests\nTINYGO ?= $(call detect,tinygo,tinygo $(CURDIR)/build/tinygo)\n\n# Check for ccache if the user hasn't set it to on or off.\nifeq (, $(CCACHE))\n    LLVM_OPTION += '-DLLVM_CCACHE_BUILD=$(if $(shell command -v ccache 2> /dev/null),ON,OFF)'\nelse\n    LLVM_OPTION += '-DLLVM_CCACHE_BUILD=$(CCACHE)'\nendif\n\n# Allow enabling LLVM assertions\nifeq (1, $(ASSERT))\n    LLVM_OPTION += '-DLLVM_ENABLE_ASSERTIONS=ON'\nelse\n    LLVM_OPTION += '-DLLVM_ENABLE_ASSERTIONS=OFF'\nendif\n\n# Enable AddressSanitizer\nifeq (1, $(ASAN))\n    LLVM_OPTION += -DLLVM_USE_SANITIZER=Address\n    CGO_LDFLAGS += -fsanitize=address\nendif\n\nifeq (1, $(STATIC))\n    # Build TinyGo as a fully statically linked binary (no dynamically loaded\n    # libraries such as a libc). This is not supported with glibc which is used\n    # on most major Linux distributions. However, it is supported in Alpine\n    # Linux with musl.\n    CGO_LDFLAGS += -static\n    # Also set the thread stack size to 1MB. This is necessary on musl as the\n    # default stack size is 128kB and LLVM uses more than that.\n    # For more information, see:\n    # https://wiki.musl-libc.org/functional-differences-from-glibc.html#Thread-stack-size\n    CGO_LDFLAGS += -Wl,-z,stack-size=1048576\n    # Build wasm-opt with static linking.\n    # For details, see:\n    # https://github.com/WebAssembly/binaryen/blob/version_102/.github/workflows/ci.yml#L181\n    BINARYEN_OPTION += -DCMAKE_CXX_FLAGS=\"-static\" -DCMAKE_C_FLAGS=\"-static\"\nendif\n\n# Optimize the binary size for Linux.\n# These flags may work on other platforms, but have only been tested on Linux.\nifeq ($(uname),Linux)\n    HAS_MOLD := $(shell command -v ld.mold 2> /dev/null)\n    HAS_LLD := $(shell command -v ld.lld 2> /dev/null)\n    LLVM_CFLAGS := -ffunction-sections -fdata-sections -fvisibility=hidden\n    LLVM_LDFLAGS := -Wl,--gc-sections\n    ifneq ($(HAS_MOLD),)\n        # Mold might be slightly faster.\n        LLVM_LDFLAGS += -fuse-ld=mold -Wl,--icf=all\n    else ifneq ($(HAS_LLD),)\n        # LLD is more commonly available.\n        LLVM_LDFLAGS += -fuse-ld=lld -Wl,--icf=all\n    endif\n    LLVM_OPTION += \\\n        -DCMAKE_C_FLAGS=\"$(LLVM_CFLAGS)\" \\\n        -DCMAKE_CXX_FLAGS=\"$(LLVM_CFLAGS)\"\n    CGO_LDFLAGS += $(LLVM_LDFLAGS)\nendif\n\n# Cross compiling support.\nifneq ($(CROSS),)\n    CC = $(CROSS)-gcc\n    CXX = $(CROSS)-g++\n    LLVM_OPTION += \\\n        -DCMAKE_C_COMPILER=$(CC) \\\n        -DCMAKE_CXX_COMPILER=$(CXX) \\\n        -DLLVM_DEFAULT_TARGET_TRIPLE=$(CROSS) \\\n        -DCROSS_TOOLCHAIN_FLAGS_NATIVE=\"-UCMAKE_C_COMPILER;-UCMAKE_CXX_COMPILER\"\n    ifeq ($(CROSS), arm-linux-gnueabihf)\n        # Assume we're building on a Debian-like distro, with QEMU installed.\n        LLVM_CONFIG_PREFIX = qemu-arm -L /usr/arm-linux-gnueabihf/\n        # The CMAKE_SYSTEM_NAME flag triggers cross compilation mode.\n        LLVM_OPTION += \\\n            -DCMAKE_SYSTEM_NAME=Linux \\\n            -DLLVM_TARGET_ARCH=ARM\n        GOENVFLAGS = GOARCH=arm CC=$(CC) CXX=$(CXX) CGO_ENABLED=1\n        BINARYEN_OPTION += -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX)\n    else ifeq ($(CROSS), aarch64-linux-gnu)\n        # Assume we're building on a Debian-like distro, with QEMU installed.\n        LLVM_CONFIG_PREFIX = qemu-aarch64 -L /usr/aarch64-linux-gnu/\n        # The CMAKE_SYSTEM_NAME flag triggers cross compilation mode.\n        LLVM_OPTION += \\\n            -DCMAKE_SYSTEM_NAME=Linux \\\n            -DLLVM_TARGET_ARCH=AArch64\n        GOENVFLAGS = GOARCH=arm64 CC=$(CC) CXX=$(CXX) CGO_ENABLED=1\n        BINARYEN_OPTION += -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX)\n    else\n        $(error Unknown cross compilation target: $(CROSS))\n    endif\nendif\n\n.PHONY: all tinygo test $(LLVM_BUILDDIR) llvm-source clean fmt gen-device gen-device-nrf gen-device-nxp gen-device-avr gen-device-rp\n\nLLVM_COMPONENTS = all-targets analysis asmparser asmprinter bitreader bitwriter codegen core coroutines coverage debuginfodwarf debuginfopdb executionengine frontenddriver frontendhlsl frontendopenmp instrumentation interpreter ipo irreader libdriver linker lto mc mcjit objcarcopts option profiledata scalaropts support target windowsdriver windowsmanifest\n\nifeq ($(OS),Windows_NT)\n    EXE = .exe\n    START_GROUP = -Wl,--start-group\n    END_GROUP = -Wl,--end-group\n\n    # PIC needs to be disabled for libclang to work.\n    LLVM_OPTION += -DLLVM_ENABLE_PIC=OFF\n\n    CGO_CPPFLAGS += -DCINDEX_NO_EXPORTS\n    CGO_LDFLAGS += -static -static-libgcc -static-libstdc++\n    CGO_LDFLAGS_EXTRA += -lversion\n\n    USE_SYSTEM_BINARYEN ?= 1\n\nelse ifeq ($(uname),Darwin)\n    MD5SUM ?= md5\n\n    CGO_LDFLAGS += -lxar\n\n    USE_SYSTEM_BINARYEN ?= 1\n\nelse ifeq ($(uname),FreeBSD)\n    MD5SUM ?= md5\n    START_GROUP = -Wl,--start-group\n    END_GROUP = -Wl,--end-group\nelse\n    START_GROUP = -Wl,--start-group\n    END_GROUP = -Wl,--end-group\nendif\n\n# md5sum binary default, can be overridden by an environment variable\nMD5SUM ?= md5sum\n\n# Libraries that should be linked in for the statically linked Clang.\nCLANG_LIB_NAMES = clangAnalysis clangAPINotes clangAST clangASTMatchers clangBasic clangCodeGen clangCrossTU clangDriver clangDynamicASTMatchers clangEdit clangExtractAPI clangFormat clangFrontend clangFrontendTool clangHandleCXX clangHandleLLVM clangIndex clangInstallAPI clangLex clangParse clangRewrite clangRewriteFrontend clangSema clangSerialization clangSupport clangTooling clangToolingASTDiff clangToolingCore clangToolingInclusions\nCLANG_LIBS = $(START_GROUP) $(addprefix -l,$(CLANG_LIB_NAMES)) $(END_GROUP) -lstdc++\n\n# Libraries that should be linked in for the statically linked LLD.\nLLD_LIB_NAMES = lldCOFF lldCommon lldELF lldMachO lldMinGW lldWasm\nLLD_LIBS = $(START_GROUP) $(addprefix -l,$(LLD_LIB_NAMES)) $(END_GROUP)\n\n# Other libraries that are needed to link TinyGo.\nEXTRA_LIB_NAMES = LLVMInterpreter LLVMMCA LLVMRISCVTargetMCA LLVMX86TargetMCA\n\n# All libraries to be built and linked with the tinygo binary (lib/lib*.a).\nLIB_NAMES = clang $(CLANG_LIB_NAMES) $(LLD_LIB_NAMES) $(EXTRA_LIB_NAMES)\n\n# These build targets appear to be the only ones necessary to build all TinyGo\n# dependencies. Only building a subset significantly speeds up rebuilding LLVM.\n# The Makefile rules convert a name like lldELF to lib/liblldELF.a to match the\n# library path (for ninja).\n# This list also includes a few tools that are necessary as part of the full\n# TinyGo build.\nNINJA_BUILD_TARGETS = clang llvm-config llvm-ar llvm-nm lld $(addprefix lib/lib,$(addsuffix .a,$(LIB_NAMES)))\n\n# For static linking.\nifneq (\"$(wildcard $(LLVM_BUILDDIR)/bin/llvm-config*)\",\"\")\n    CGO_CPPFLAGS+=$(shell $(LLVM_CONFIG_PREFIX) $(LLVM_BUILDDIR)/bin/llvm-config --cppflags) -I$(abspath $(LLVM_BUILDDIR))/tools/clang/include -I$(abspath $(CLANG_SRC))/include -I$(abspath $(LLD_SRC))/include\n    CGO_CXXFLAGS=-std=c++17\n    CGO_LDFLAGS+=-L$(abspath $(LLVM_BUILDDIR)/lib) -lclang $(CLANG_LIBS) $(LLD_LIBS) $(shell $(LLVM_CONFIG_PREFIX) $(LLVM_BUILDDIR)/bin/llvm-config --ldflags --libs --system-libs $(LLVM_COMPONENTS)) -lstdc++ $(CGO_LDFLAGS_EXTRA)\nendif\n\nclean: ## Remove build directory\n\t@rm -rf build\n\nFMT_PATHS = ./*.go builder cgo/*.go compiler interp loader src transform\nfmt: ## Reformat source\n\t@gofmt -l -w $(FMT_PATHS)\nfmt-check: ## Warn if any source needs reformatting\n\t@unformatted=$$(gofmt -l $(FMT_PATHS)); [ -z \"$$unformatted\" ] && exit 0; echo \"Unformatted:\"; for fn in $$unformatted; do echo \"  $$fn\"; done; exit 1\n\n\ngen-device: gen-device-avr gen-device-esp gen-device-nrf gen-device-sam gen-device-sifive gen-device-kendryte gen-device-nxp gen-device-rp ## Generate microcontroller-specific sources\nifneq ($(RENESAS), 0)\ngen-device: gen-device-renesas\nendif\nifneq ($(STM32), 0)\ngen-device: gen-device-stm32\nendif\n\ngen-device-avr:\n\t@if [ ! -e lib/avr/README.md ]; then echo \"Submodules have not been downloaded. Please download them using:\\n  git submodule update --init\"; exit 1; fi\n\t$(GO) build -o ./build/gen-device-avr ./tools/gen-device-avr/\n\t./build/gen-device-avr lib/avr/packs/atmega src/device/avr/\n\t./build/gen-device-avr lib/avr/packs/tiny src/device/avr/\n\t@GO111MODULE=off $(GO) fmt ./src/device/avr\n\nbuild/gen-device-svd: ./tools/gen-device-svd/*.go\n\t$(GO) build -o $@ ./tools/gen-device-svd/\n\ngen-device-esp: build/gen-device-svd\n\t./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/Espressif-Community -interrupts=software lib/cmsis-svd/data/Espressif-Community/ src/device/esp/\n\t./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/Espressif -interrupts=software lib/cmsis-svd/data/Espressif/ src/device/esp/\n\tGO111MODULE=off $(GO) fmt ./src/device/esp\n\ngen-device-nrf: build/gen-device-svd\n\t./build/gen-device-svd -source=https://github.com/NordicSemiconductor/nrfx/tree/master/mdk lib/nrfx/mdk/ src/device/nrf/\n\tGO111MODULE=off $(GO) fmt ./src/device/nrf\n\ngen-device-nxp: build/gen-device-svd\n\t./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/NXP lib/cmsis-svd/data/NXP/ src/device/nxp/\n\tGO111MODULE=off $(GO) fmt ./src/device/nxp\n\ngen-device-sam: build/gen-device-svd\n\t./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/Atmel lib/cmsis-svd/data/Atmel/ src/device/sam/\n\tGO111MODULE=off $(GO) fmt ./src/device/sam\n\ngen-device-sifive: build/gen-device-svd\n\t./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/SiFive-Community -interrupts=software lib/cmsis-svd/data/SiFive-Community/ src/device/sifive/\n\tGO111MODULE=off $(GO) fmt ./src/device/sifive\n\ngen-device-kendryte: build/gen-device-svd\n\t./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/Kendryte-Community -interrupts=software lib/cmsis-svd/data/Kendryte-Community/ src/device/kendryte/\n\tGO111MODULE=off $(GO) fmt ./src/device/kendryte\n\ngen-device-stm32: build/gen-device-svd\n\t./build/gen-device-svd -source=https://github.com/tinygo-org/stm32-svd lib/stm32-svd/svd src/device/stm32/\n\tGO111MODULE=off $(GO) fmt ./src/device/stm32\n\ngen-device-rp: build/gen-device-svd\n\t./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/RaspberryPi lib/cmsis-svd/data/RaspberryPi/ src/device/rp/\n\tGO111MODULE=off $(GO) fmt ./src/device/rp\n\ngen-device-renesas: build/gen-device-svd\n\t./build/gen-device-svd -source=https://github.com/cmsis-svd/cmsis-svd-data/tree/master/data/Renesas lib/cmsis-svd/data/Renesas/ src/device/renesas/\n\tGO111MODULE=off $(GO) fmt ./src/device/renesas\n\n$(LLVM_PROJECTDIR)/llvm:\n\tgit clone -b tinygo_20.x --depth=1 https://github.com/tinygo-org/llvm-project $(LLVM_PROJECTDIR)\nllvm-source: $(LLVM_PROJECTDIR)/llvm ## Get LLVM sources\n\n# Configure LLVM.\nTINYGO_SOURCE_DIR=$(shell pwd)\n$(LLVM_BUILDDIR)/build.ninja:\n\tmkdir -p $(LLVM_BUILDDIR) && cd $(LLVM_BUILDDIR) && cmake -G Ninja $(TINYGO_SOURCE_DIR)/$(LLVM_PROJECTDIR)/llvm \"-DLLVM_TARGETS_TO_BUILD=X86;ARM;AArch64;AVR;Mips;RISCV;WebAssembly\" \"-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=Xtensa\" -DCMAKE_BUILD_TYPE=Release -DLIBCLANG_BUILD_STATIC=ON -DLLVM_ENABLE_TERMINFO=OFF -DLLVM_ENABLE_ZLIB=OFF -DLLVM_ENABLE_ZSTD=OFF -DLLVM_ENABLE_LIBEDIT=OFF -DLLVM_ENABLE_Z3_SOLVER=OFF -DLLVM_ENABLE_OCAMLDOC=OFF -DLLVM_ENABLE_LIBXML2=OFF -DLLVM_ENABLE_PROJECTS=\"clang;lld\" -DLLVM_TOOL_CLANG_TOOLS_EXTRA_BUILD=OFF -DCLANG_ENABLE_STATIC_ANALYZER=OFF -DCLANG_ENABLE_ARCMT=OFF $(LLVM_OPTION)\n\n$(LLVM_BUILDDIR): $(LLVM_BUILDDIR)/build.ninja ## Build LLVM\n\tcd $(LLVM_BUILDDIR) && ninja $(NINJA_BUILD_TARGETS)\n\nifneq ($(USE_SYSTEM_BINARYEN),1)\n# Build Binaryen\n.PHONY: binaryen\nbinaryen: build/wasm-opt$(EXE)\nbuild/wasm-opt$(EXE):\n\tmkdir -p build\n\tcd lib/binaryen && cmake -G Ninja . -DBUILD_STATIC_LIB=ON -DBUILD_TESTS=OFF -DENABLE_WERROR=OFF $(BINARYEN_OPTION) && ninja bin/wasm-opt$(EXE)\n\tcp lib/binaryen/bin/wasm-opt$(EXE) build/wasm-opt$(EXE)\nendif\n\n# Generate WASI syscall bindings\nWASM_TOOLS_MODULE=go.bytecodealliance.org\n.PHONY: wasi-syscall\nwasi-syscall: wasi-cm\n\trm -rf ./src/internal/wasi/*\n\tgo run -modfile ./internal/wasm-tools/go.mod $(WASM_TOOLS_MODULE)/cmd/wit-bindgen-go generate --versioned -o ./src/internal -p internal --cm internal/cm ./lib/wasi-cli/wit\n\n# Copy package cm into src/internal/cm\n.PHONY: wasi-cm\nwasi-cm:\n\trm -rf ./src/internal/cm/*\n\trsync -rv --delete --exclude go.mod --exclude '*_test.go' --exclude '*_json.go' --exclude '*.md' --exclude LICENSE $(shell go list -modfile ./internal/wasm-tools/go.mod -m -f {{.Dir}} $(WASM_TOOLS_MODULE)/cm)/ ./src/internal/cm\n\n# Check for Node.js used during WASM tests.\nMIN_NODEJS_VERSION=18\n\n.PHONY: check-nodejs-version\ncheck-nodejs-version:\n\t@# Check whether NodeJS is available.\n\t@if ! command -v node 2>&1 >/dev/null; then echo \"Install NodeJS version ${MIN_NODEJS_VERSION}+ to run tests.\"; exit 1; fi\n\n\t@# Check whether the version is high enough.\n\t@if [ \"`node -v | sed 's/v\\([0-9]\\+\\).*/\\\\1/g'`\" -lt $(MIN_NODEJS_VERSION) ]; then echo \"Install NodeJS version $(MIN_NODEJS_VERSION)+ to run tests.\"; exit 1; fi\n\ntinygo: ## Build the TinyGo compiler\n\t@if [ ! -f \"$(LLVM_BUILDDIR)/bin/llvm-config\" ]; then echo \"Fetch and build LLVM first by running:\"; echo \"  $(MAKE) llvm-source\"; echo \"  $(MAKE) $(LLVM_BUILDDIR)\"; exit 1; fi\n\tCGO_CPPFLAGS=\"$(CGO_CPPFLAGS)\" CGO_CXXFLAGS=\"$(CGO_CXXFLAGS)\" CGO_LDFLAGS=\"$(CGO_LDFLAGS)\" $(GOENVFLAGS) $(GO) build -buildmode exe -o build/tinygo$(EXE) -tags \"byollvm osusergo\" .\ntest: check-nodejs-version\n\tCGO_CPPFLAGS=\"$(CGO_CPPFLAGS)\" CGO_CXXFLAGS=\"$(CGO_CXXFLAGS)\" CGO_LDFLAGS=\"$(CGO_LDFLAGS)\" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags \"byollvm osusergo\" $(GOTESTPKGS)\n\n# Standard library packages that pass tests on darwin, linux, wasi, and windows, but take over a minute in wasi\nTEST_PACKAGES_SLOW = \\\n\tcompress/bzip2 \\\n\tcrypto/dsa \\\n\tindex/suffixarray \\\n\n# Standard library packages that pass tests quickly on darwin, linux, wasi, and windows\nTEST_PACKAGES_FAST = \\\n\tcmp \\\n\tcompress/lzw \\\n\tcompress/zlib \\\n\tcontainer/heap \\\n\tcontainer/list \\\n\tcontainer/ring \\\n\tcrypto/ecdsa \\\n\tcrypto/elliptic \\\n\tcrypto/md5 \\\n\tcrypto/sha1 \\\n\tcrypto/sha256 \\\n\tcrypto/sha512 \\\n\tdatabase/sql/driver \\\n\tdebug/macho \\\n\tembed/internal/embedtest \\\n\tencoding \\\n\tencoding/ascii85 \\\n\tencoding/asn1 \\\n\tencoding/base32 \\\n\tencoding/base64 \\\n\tencoding/csv \\\n\tencoding/hex \\\n\tgo/ast \\\n\tgo/format \\\n\tgo/scanner \\\n\tgo/version \\\n\thash \\\n\thash/adler32 \\\n\thash/crc64 \\\n\thash/fnv \\\n\thtml \\\n\tinternal/itoa \\\n\tinternal/profile \\\n\tmath \\\n\tmath/cmplx \\\n\tnet/http/internal/ascii \\\n\tnet/mail \\\n\tos \\\n\tpath \\\n\treflect \\\n\tsync \\\n\ttesting \\\n\ttesting/iotest \\\n\ttext/scanner \\\n\tunicode \\\n\tunicode/utf16 \\\n\tunicode/utf8 \\\n\tunique \\\n\t$(nil)\n\n# archive/zip requires os.ReadAt, which is not yet supported on windows\n# bytes requires mmap\n# compress/flate appears to hang on wasi\n# crypto/aes fails on wasi, needs panic()/recover()\n# crypto/des fails on wasi, needs panic()/recover()\n# crypto/hmac fails on wasi, it exits with a \"slice out of range\" panic\n# debug/plan9obj requires os.ReadAt, which is not yet supported on windows\n# image requires recover(), which is not yet supported on wasi\n# io/ioutil requires os.ReadDir, which is not yet supported on windows or wasi\n# mime: fail on wasi; neds panic()/recover()\n# mime/multipart: needs wasip1 syscall.FDFLAG_NONBLOCK\n# mime/quotedprintable requires syscall.Faccessat\n# net/mail: needs wasip1  syscall.FDFLAG_NONBLOCK\n# net/ntextproto: needs wasip1 syscall.FDFLAG_NONBLOCK\n# regexp/syntax: fails on wasip1; needs panic()/recover()\n# strconv requires recover() which is not yet supported on wasi\n# text/tabwriter requires recover(), which is not yet supported on wasi\n# text/template/parse requires recover(), which is not yet supported on wasi\n# testing/fstest requires os.ReadDir, which is not yet supported on windows or wasi\n\n# Additional standard library packages that pass tests on individual platforms\nTEST_PACKAGES_LINUX := \\\n\tarchive/zip \\\n\tcompress/flate \\\n\tcrypto/aes \\\n\tcrypto/des \\\n\tcrypto/hmac \\\n\tdebug/dwarf \\\n\tdebug/plan9obj \\\n\timage \\\n\tio/ioutil \\\n\tmime \\\n\tmime/multipart \\\n\tmime/quotedprintable \\\n\tnet \\\n\tnet/mail \\\n\tnet/textproto \\\n\tos/user \\\n\tregexp/syntax \\\n\tstrconv \\\n\ttext/tabwriter \\\n\ttext/template/parse\n\nTEST_PACKAGES_DARWIN := $(TEST_PACKAGES_LINUX)\n\n# os/user requires t.Skip() support\nTEST_PACKAGES_WINDOWS := \\\n\tcompress/flate \\\n\tcrypto/des \\\n\tcrypto/hmac \\\n\tstrconv \\\n\ttext/template/parse \\\n\t$(nil)\n\n\n# These packages cannot be tested on wasm, mostly because these tests assume a\n# working filesystem. This could perhaps be fixed, by supporting filesystem\n# access when running inside Node.js.\nTEST_PACKAGES_WASM = $(filter-out $(TEST_PACKAGES_NONWASM), $(TEST_PACKAGES_FAST))\nTEST_PACKAGES_NONWASM = \\\n\tcompress/lzw \\\n\tcompress/zlib \\\n\tcrypto/ecdsa \\\n\tdebug/macho \\\n\tembed/internal/embedtest \\\n\tgo/format \\\n\tos \\\n\ttesting \\\n\t$(nil)\n\n# These packages cannot be tested on baremetal.\n#\n# Some reasons why the tests don't pass on baremetal:\n#\n#   * No filesystem is available, so packages like compress/zlib can't be tested\n#     (just like wasm).\n#   * picolibc math functions apparently are less precise, the math package\n#     fails on baremetal.\nTEST_PACKAGES_BAREMETAL = $(filter-out $(TEST_PACKAGES_NONBAREMETAL), $(TEST_PACKAGES_FAST))\nTEST_PACKAGES_NONBAREMETAL = \\\n\t$(TEST_PACKAGES_NONWASM) \\\n\tmath \\\n\t$(nil)\n\n# Report platforms on which each standard library package is known to pass tests\nreport-stdlib-tests-pass:\n\t$(eval jointmp := $(shell echo /tmp/join.$$$$))\n\t@for t in $(TEST_PACKAGES_DARWIN); do echo \"$$t darwin\"; done | sort > $(jointmp).darwin\n\t@for t in $(TEST_PACKAGES_LINUX); do echo \"$$t linux\"; done | sort > $(jointmp).linux\n\t@for t in $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW); do echo \"$$t darwin linux wasi windows\"; done | sort > $(jointmp).portable\n\t@join -a1 -a2 $(jointmp).darwin $(jointmp).linux | \\\n\tjoin -a1 -a2 - $(jointmp).portable\n\t@rm $(jointmp).*\n\n# Standard library packages that pass tests quickly on the current platform\nifeq ($(uname),Darwin)\nTEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_DARWIN)\nTEST_IOFS := true\nendif\nifeq ($(uname),Linux)\nTEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_LINUX)\nTEST_IOFS := true\nendif\nifeq ($(OS),Windows_NT)\nTEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_WINDOWS)\nTEST_IOFS := false\nendif\n\nTEST_SKIP_FLAG := -skip='TestExtraMethods|TestParseAndBytesRoundTrip/P256/Generic'\nTEST_ADDITIONAL_FLAGS ?=\n\n# Test known-working standard library packages.\n# TODO: parallelize, and only show failing tests (no implied -v flag).\n.PHONY: tinygo-test\ntinygo-test:\n\t@# TestExtraMethods: used by many crypto packages and uses reflect.Type.Method which is not implemented.\n\t@# TestParseAndBytesRoundTrip/P256/Generic: relies on t.Skip() which is not implemented\n\t$(TINYGO) test $(TEST_ADDITIONAL_FLAGS) $(TEST_SKIP_FLAG) $(TEST_PACKAGES_HOST) $(TEST_PACKAGES_SLOW)\n\t@# io/fs requires os.ReadDir, not yet supported on windows or wasi. It also\n\t@# requires a large stack-size. Hence, io/fs is only run conditionally.\n\t@# For more details, see the comments on issue #3143.\nifeq ($(TEST_IOFS),true)\n\t$(TINYGO) test -stack-size=6MB io/fs\nendif\ntinygo-test-fast:\n\t$(TINYGO) test $(TEST_SKIP_FLAG) $(TEST_PACKAGES_HOST)\ntinygo-bench:\n\t$(TINYGO) test -bench . $(TEST_PACKAGES_HOST) $(TEST_PACKAGES_SLOW)\ntinygo-bench-fast:\n\t$(TINYGO) test -bench . $(TEST_PACKAGES_HOST)\n\n# Same thing, except for wasi rather than the current platform.\ntinygo-test-wasm:\n\t$(TINYGO) test -target wasm $(TEST_SKIP_FLAG) $(TEST_PACKAGES_WASM)\ntinygo-test-wasi:\n\t$(TINYGO) test -target wasip1 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi\ntinygo-test-wasip1:\n\tGOOS=wasip1 GOARCH=wasm $(TINYGO) test $(TEST_SKIP_FLAG) $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi\ntinygo-test-wasip1-fast:\n\t$(TINYGO) test -target=wasip1 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_FAST) ./tests/runtime_wasi\n\ntinygo-test-wasip2-slow:\n\t$(TINYGO) test -target=wasip2 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_SLOW)\ntinygo-test-wasip2-fast:\n\t$(TINYGO) test -target=wasip2 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_FAST) ./tests/runtime_wasi\n\ntinygo-test-wasip2-sum-slow:\n\tTINYGO=$(TINYGO) \\\n\tTARGET=wasip2 \\\n\tTESTOPTS=\"-x -work\" \\\n\tPACKAGES=\"$(TEST_PACKAGES_SLOW)\" \\\n\tgotestsum --raw-command -- ./tools/tgtestjson.sh\ntinygo-test-wasip2-sum-fast:\n\tTINYGO=$(TINYGO) \\\n\tTARGET=wasip2 \\\n\tTESTOPTS=\"-x -work\" \\\n\tPACKAGES=\"$(TEST_PACKAGES_FAST)\" \\\n\tgotestsum --raw-command -- ./tools/tgtestjson.sh\ntinygo-bench-wasip1:\n\t$(TINYGO) test -target wasip1 -bench . $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW)\ntinygo-bench-wasip1-fast:\n\t$(TINYGO) test -target wasip1 -bench . $(TEST_PACKAGES_FAST)\n\ntinygo-bench-wasip2:\n\t$(TINYGO) test -target wasip2 -bench . $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW)\ntinygo-bench-wasip2-fast:\n\t$(TINYGO) test -target wasip2 -bench . $(TEST_PACKAGES_FAST)\n\n# Run tests on riscv-qemu since that one provides a large amount of memory.\ntinygo-test-baremetal:\n\t$(TINYGO) test -target riscv-qemu $(TEST_SKIP_FLAG) $(TEST_PACKAGES_BAREMETAL)\n\n# Test external packages in a large corpus.\ntest-corpus:\n\tCGO_CPPFLAGS=\"$(CGO_CPPFLAGS)\" CGO_CXXFLAGS=\"$(CGO_CXXFLAGS)\" CGO_LDFLAGS=\"$(CGO_LDFLAGS)\" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags byollvm -run TestCorpus . -corpus=testdata/corpus.yaml\ntest-corpus-fast:\n\tCGO_CPPFLAGS=\"$(CGO_CPPFLAGS)\" CGO_CXXFLAGS=\"$(CGO_CXXFLAGS)\" CGO_LDFLAGS=\"$(CGO_LDFLAGS)\" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags byollvm -run TestCorpus -short . -corpus=testdata/corpus.yaml\ntest-corpus-wasi:\n\tCGO_CPPFLAGS=\"$(CGO_CPPFLAGS)\" CGO_CXXFLAGS=\"$(CGO_CXXFLAGS)\" CGO_LDFLAGS=\"$(CGO_LDFLAGS)\" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags byollvm -run TestCorpus . -corpus=testdata/corpus.yaml -target=wasip1\ntest-corpus-wasip2:\n\tCGO_CPPFLAGS=\"$(CGO_CPPFLAGS)\" CGO_CXXFLAGS=\"$(CGO_CXXFLAGS)\" CGO_LDFLAGS=\"$(CGO_LDFLAGS)\" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags byollvm -run TestCorpus . -corpus=testdata/corpus.yaml -target=wasip2\n\n.PHONY: testchdir\ntestchdir:\n\t# test 'build' command with{,out} -C argument\n\t$(TINYGO) build -C tests/testing/chdir chdir.go && rm tests/testing/chdir/chdir\n\t$(TINYGO) build ./tests/testing/chdir/chdir.go && rm chdir\n\t# test 'run' command with{,out} -C argument\n\tEXPECT_DIR=$(PWD)/tests/testing/chdir $(TINYGO) run -C tests/testing/chdir chdir.go\n\tEXPECT_DIR=$(PWD) $(TINYGO) run ./tests/testing/chdir/chdir.go\n\n.PHONY: smoketest\nsmoketest: testchdir\n\t$(TINYGO) version\n\t$(TINYGO) targets > /dev/null\n\t# regression test for #2892\n\tcd tests/testing/recurse && ($(TINYGO) test ./... > recurse.log && cat recurse.log && test $$(wc -l < recurse.log) = 2 && rm recurse.log)\n\t# compile-only platform-independent examples\n\tcd tests/text/template/smoke && $(TINYGO) test -c && rm -f smoke.test\n\t# regression test for #2563\n\tcd tests/os/smoke && $(TINYGO) test -c -target=pybadge && rm smoke.test\n\t# test all examples (except pwm)\n\t$(TINYGO) build -size short -o test.hex -target=pga2350             examples/echo\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pca10040            examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pca10040            examples/adc\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pca10040            examples/blinkm\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pca10040            examples/blinky2\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pca10040            examples/button\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pca10040            examples/button2\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pca10040            examples/echo\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pca10040            examples/echo2\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=circuitplay-express examples/i2s\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pca10040            examples/mcp3008\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pca10040            examples/memstats\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=microbit            examples/microbit-blink\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pca10040            examples/pininterrupt\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=nano-rp2040         examples/rtcinterrupt\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pca10040            examples/machinetest\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pca10040            examples/systick\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pca10040            examples/test\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pca10040            examples/time-offset\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=wioterminal         examples/hid-mouse\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=wioterminal         examples/hid-keyboard\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=feather-rp2040      examples/i2c-target\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=feather-rp2040      examples/watchdog\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=feather-rp2040      examples/device-id\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pico2-ice           examples/blinky1\n\t@$(MD5SUM) test.hex\n\t# test simulated boards on play.tinygo.org\nifneq ($(WASM), 0)\n\tGOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=arduino              examples/blinky1\n\t@$(MD5SUM) test.wasm\n\tGOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=hifive1b             examples/blinky1\n\t@$(MD5SUM) test.wasm\n\tGOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=reelboard            examples/blinky1\n\t@$(MD5SUM) test.wasm\n\tGOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=microbit             examples/microbit-blink\n\t@$(MD5SUM) test.wasm\n\tGOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=circuitplay_express  examples/blinky1\n\t@$(MD5SUM) test.wasm\n\tGOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=circuitplay_bluefruit examples/blinky1\n\t@$(MD5SUM) test.wasm\n\tGOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=mch2022              examples/machinetest\n\t@$(MD5SUM) test.wasm\n\tGOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=gopher_badge         examples/blinky1\n\t@$(MD5SUM) test.wasm\n\tGOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=pico                 examples/blinky1\n\t@$(MD5SUM) test.wasm\nendif\n\t# test all targets/boards\n\t$(TINYGO) build -size short -o test.hex -target=pca10040-s132v6     examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=microbit            examples/echo\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=microbit-s110v8     examples/echo\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=microbit-v2         examples/microbit-blink\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=microbit-v2-s113v7  examples/microbit-blink\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=microbit-v2-s140v7  examples/microbit-blink\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=nrf52840-mdk        examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=btt-skr-pico        examples/uart\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pca10031            examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=reelboard           examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=reelboard           examples/blinky2\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pca10056            examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pca10056            examples/blinky2\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pca10059            examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pca10059            examples/blinky2\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=bluemicro840        examples/blinky2\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=itsybitsy-m0        examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=feather-m0          examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=trinket-m0          examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=gemma-m0            examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=circuitplay-express examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=circuitplay-bluefruit examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=circuitplay-express examples/i2s\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=clue-alpha          examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.gba -target=gameboy-advance     examples/gba-display\n\t@$(MD5SUM) test.gba\n\t$(TINYGO) build -size short -o test.hex -target=grandcentral-m4     examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=itsybitsy-m4        examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=feather-m4          examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=matrixportal-m4     examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pybadge             examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=metro-m4-airlift    examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pyportal            examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=particle-argon      examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=particle-boron      examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=particle-xenon      examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pinetime            examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=x9pro               examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pca10056-s140v7     examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pca10059-s140v7     examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=reelboard-s140v7    examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=wioterminal         examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pygamer             examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=xiao                examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=rak4631             examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=circuitplay-express examples/dac\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pyportal            examples/dac\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=feather-nrf52840  \texamples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=feather-nrf52840-sense examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=itsybitsy-nrf52840  examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=qtpy                examples/machinetest\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=teensy41            examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=teensy40            examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=teensy36            examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=p1am-100            examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=atsame54-xpro       examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=atsame54-xpro       examples/can\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=feather-m4-can      examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=feather-m4-can      examples/caninterrupt\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=arduino-nano33      examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=arduino-mkrwifi1010 examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pico                examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=nano-33-ble         examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=nano-rp2040         examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=feather-rp2040 \t\texamples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=qtpy-rp2040         examples/echo\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=kb2040              examples/echo\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=macropad-rp2040 \texamples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=badger2040          examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=badger2040-w        examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=tufty2040           examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=thingplus-rp2040    examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=xiao-rp2040         examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=waveshare-rp2040-zero examples/echo\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=challenger-rp2040    examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=trinkey-qt2040      examples/temp\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=gopher-badge      examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=gopher-arcade      examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=ae-rp2040           examples/echo\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=thumby              examples/echo\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pico2               examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=tiny2350            examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pico-plus2          examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=metro-rp2350        examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=waveshare-rp2040-tiny examples/echo\n\t@$(MD5SUM) test.hex\n\t# test pwm\n\t$(TINYGO) build -size short -o test.hex -target=itsybitsy-m0        examples/pwm\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=itsybitsy-m4        examples/pwm\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=feather-m4          examples/pwm\n\t@$(MD5SUM) test.hex\n\t# test usb\n\t$(TINYGO) build -size short -o test.hex -target=feather-nrf52840    examples/hid-keyboard\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=circuitplay-express examples/hid-keyboard\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=feather-nrf52840    examples/usb-midi\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pico    \t\t\texamples/usb-storage\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pico2    \t\t\texamples/usb-storage\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=nrf52840-s140v6-uf2-generic\texamples/machinetest\n\t@$(MD5SUM) test.hex\nifneq ($(STM32), 0)\n\t$(TINYGO) build -size short -o test.hex -target=bluepill            examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=feather-stm32f405   examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=lgt92               examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=nucleo-f103rb       examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=nucleo-f722ze       examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=nucleo-l031k6       examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=nucleo-l432kc       examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=nucleo-l476rg       examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=nucleo-l552ze       examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=nucleo-wl55jc       examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=stm32f4disco        examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=stm32f4disco        examples/blinky2\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=stm32f4disco-1      examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=stm32f4disco-1      examples/pwm\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=stm32f469disco      examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=lorae5              examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=swan                examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=mksnanov3           examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=stm32l0x1           examples/serial\n\t@$(MD5SUM) test.hex\nendif\n\t$(TINYGO) build -size short -o test.hex -target=atmega328pb         examples/blinkm\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=atmega1284p         examples/machinetest\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=arduino             examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=arduino-leonardo    examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=arduino             examples/pwm\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=arduino -scheduler=tasks  examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=arduino-mega1280    examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=arduino-mega1280    examples/pwm\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=arduino-nano        examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=attiny1616          examples/empty\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=digispark           examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=digispark -gc=leaking examples/blinky1\n\t@$(MD5SUM) test.hex\nifneq ($(XTENSA), 0)\n\t$(TINYGO) build -size short -o test.bin -target=esp32-mini32      \texamples/blinky1\n\t@$(MD5SUM) test.bin\n\t$(TINYGO) build -size short -o test.bin -target=esp32c3-supermini   examples/blinky1\n\t@$(MD5SUM) test.bin\n\t$(TINYGO) build -size short -o test.bin -target=nodemcu             examples/blinky1\n\t@$(MD5SUM) test.bin\n\t$(TINYGO) build -size short -o test.bin -target m5stack-core2       examples/machinetest\n\t@$(MD5SUM) test.bin\n\t$(TINYGO) build -size short -o test.bin -target m5stack             examples/machinetest\n\t@$(MD5SUM) test.bin\n\t$(TINYGO) build -size short -o test.bin -target m5stick-c           examples/machinetest\n\t@$(MD5SUM) test.bin\n\t$(TINYGO) build -size short -o test.bin -target m5paper             examples/machinetest\n\t@$(MD5SUM) test.bin\n\t$(TINYGO) build -size short -o test.bin -target mch2022             examples/machinetest\n\t@$(MD5SUM) test.bin\n\t$(TINYGO) build -size short -o test.bin -target=xiao-esp32s3   \t\texamples/blinky1\n\t@$(MD5SUM) test.bin\nendif\n\t$(TINYGO) build -size short -o test.bin -target=esp-c3-32s-kit      examples/blinky1\n\t@$(MD5SUM) test.bin\n\t$(TINYGO) build -size short -o test.bin -target=qtpy-esp32c3        examples/machinetest\n\t@$(MD5SUM) test.bin\n\t$(TINYGO) build -size short -o test.bin -target=m5stamp-c3          examples/machinetest\n\t@$(MD5SUM) test.bin\n\t$(TINYGO) build -size short -o test.bin -target=xiao-esp32c3        examples/machinetest\n\t@$(MD5SUM) test.bin\n\t$(TINYGO) build -size short -o test.bin -target=esp32-c3-devkit-rust-1 examples/blinky1\n\t@$(MD5SUM) test.bin\n\t$(TINYGO) build -size short -o test.bin -target=esp32c3-12f         examples/blinky1\n\t@$(MD5SUM) test.bin\n\t$(TINYGO) build -size short -o test.bin -target=makerfabs-esp32c3spi35 examples/machinetest\n\t@$(MD5SUM) test.bin\n\t$(TINYGO) build -size short -o test.hex -target=hifive1b            examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=maixbit             examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=tkey                examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=elecrow-rp2040      examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=elecrow-rp2350      examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=hw-651              examples/machinetest\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=hw-651-s110v8       examples/machinetest\n\t@$(MD5SUM) test.hex\nifneq ($(WASM), 0)\n\t$(TINYGO) build -size short -o wasm.wasm -target=wasm               examples/wasm/export\n\t$(TINYGO) build -size short -o wasm.wasm -target=wasm               examples/wasm/main\n\t$(TINYGO) build -size short -o wasm.wasm -target=wasm-unknown       examples/hello-wasm-unknown\nendif\n\t# test various compiler flags\n\t$(TINYGO) build -size short -o test.hex -target=pca10040 -gc=none -scheduler=none examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pca10040 -opt=1     examples/blinky1\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pca10040 -serial=none examples/echo\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build -size short -o test.hex -target=pca10040 -serial=rtt examples/echo\n\t@$(MD5SUM) test.hex\n\t$(TINYGO) build             -o test.nro -target=nintendoswitch      examples/echo2\n\t@$(MD5SUM) test.nro\n\t$(TINYGO) build -size short -o test.hex -target=pca10040 -opt=0     ./testdata/stdlib.go\n\t@$(MD5SUM) test.hex\n\tGOOS=linux GOARCH=arm $(TINYGO) build -size short -o test.elf       ./testdata/cgo\n\tGOOS=linux GOARCH=mips    $(TINYGO) build -size short -o test.elf   ./testdata/cgo\n\tGOOS=windows GOARCH=amd64 $(TINYGO) build -size short -o test.exe   ./testdata/cgo\n\tGOOS=windows GOARCH=arm64 $(TINYGO) build -size short -o test.exe   ./testdata/cgo\n\tGOOS=darwin GOARCH=amd64 $(TINYGO) build  -size short -o test       ./testdata/cgo\n\tGOOS=darwin GOARCH=arm64 $(TINYGO) build  -size short -o test       ./testdata/cgo\nifneq ($(OS),Windows_NT)\n\t# TODO: this does not yet work on Windows. Somehow, unused functions are\n\t# not garbage collected.\n\t$(TINYGO) build -o test.elf -gc=leaking -scheduler=none examples/serial\nendif\n\n\nwasmtest:\n\tcd ./tests/wasm && $(GO) test .\n\nbuild/release: tinygo gen-device $(if $(filter 1,$(USE_SYSTEM_BINARYEN)),,binaryen)\n\t@mkdir -p build/release/tinygo/bin\n\t@mkdir -p build/release/tinygo/lib/bdwgc\n\t@mkdir -p build/release/tinygo/lib/clang/include\n\t@mkdir -p build/release/tinygo/lib/CMSIS/CMSIS\n\t@mkdir -p build/release/tinygo/lib/macos-minimal-sdk\n\t@mkdir -p build/release/tinygo/lib/mingw-w64/mingw-w64-crt/crt\n\t@mkdir -p build/release/tinygo/lib/mingw-w64/mingw-w64-crt/math\n\t@mkdir -p build/release/tinygo/lib/mingw-w64/mingw-w64-crt/lib-common\n\t@mkdir -p build/release/tinygo/lib/mingw-w64/mingw-w64-headers/defaults\n\t@mkdir -p build/release/tinygo/lib/musl/arch\n\t@mkdir -p build/release/tinygo/lib/musl/crt\n\t@mkdir -p build/release/tinygo/lib/musl/src\n\t@mkdir -p build/release/tinygo/lib/nrfx\n\t@mkdir -p build/release/tinygo/lib/picolibc/newlib/libc\n\t@mkdir -p build/release/tinygo/lib/picolibc/newlib/libm\n\t@mkdir -p build/release/tinygo/lib/wasi-libc/dlmalloc\n\t@mkdir -p build/release/tinygo/lib/wasi-libc/libc-bottom-half\n\t@mkdir -p build/release/tinygo/lib/wasi-libc/libc-top-half/musl/arch\n\t@mkdir -p build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src\n\t@mkdir -p build/release/tinygo/lib/wasi-cli/\n\t@echo copying source files\n\t@cp -p  build/tinygo$(EXE)           build/release/tinygo/bin\nifneq ($(USE_SYSTEM_BINARYEN),1)\n\t@cp -p  build/wasm-opt$(EXE)         build/release/tinygo/bin\nendif\n\t@cp -rp lib/bdwgc/*                  build/release/tinygo/lib/bdwgc\n\t@cp -p $(abspath $(CLANG_SRC))/lib/Headers/*.h build/release/tinygo/lib/clang/include\n\t@cp -rp lib/CMSIS/CMSIS/Include      build/release/tinygo/lib/CMSIS/CMSIS\n\t@cp -rp lib/CMSIS/README.md          build/release/tinygo/lib/CMSIS\n\t@cp -rp lib/macos-minimal-sdk/*      build/release/tinygo/lib/macos-minimal-sdk\n\t@cp -rp lib/musl/arch/aarch64        build/release/tinygo/lib/musl/arch\n\t@cp -rp lib/musl/arch/arm            build/release/tinygo/lib/musl/arch\n\t@cp -rp lib/musl/arch/generic        build/release/tinygo/lib/musl/arch\n\t@cp -rp lib/musl/arch/i386           build/release/tinygo/lib/musl/arch\n\t@cp -rp lib/musl/arch/mips           build/release/tinygo/lib/musl/arch\n\t@cp -rp lib/musl/arch/x86_64         build/release/tinygo/lib/musl/arch\n\t@cp -rp lib/musl/crt/crt1.c          build/release/tinygo/lib/musl/crt\n\t@cp -rp lib/musl/COPYRIGHT           build/release/tinygo/lib/musl\n\t@cp -rp lib/musl/include             build/release/tinygo/lib/musl\n\t@cp -rp lib/musl/src/conf            build/release/tinygo/lib/musl/src\n\t@cp -rp lib/musl/src/ctype           build/release/tinygo/lib/musl/src\n\t@cp -rp lib/musl/src/env             build/release/tinygo/lib/musl/src\n\t@cp -rp lib/musl/src/errno           build/release/tinygo/lib/musl/src\n\t@cp -rp lib/musl/src/exit            build/release/tinygo/lib/musl/src\n\t@cp -rp lib/musl/src/fcntl           build/release/tinygo/lib/musl/src\n\t@cp -rp lib/musl/src/include         build/release/tinygo/lib/musl/src\n\t@cp -rp lib/musl/src/internal        build/release/tinygo/lib/musl/src\n\t@cp -rp lib/musl/src/legacy          build/release/tinygo/lib/musl/src\n\t@cp -rp lib/musl/src/locale          build/release/tinygo/lib/musl/src\n\t@cp -rp lib/musl/src/linux           build/release/tinygo/lib/musl/src\n\t@cp -rp lib/musl/src/malloc          build/release/tinygo/lib/musl/src\n\t@cp -rp lib/musl/src/mman            build/release/tinygo/lib/musl/src\n\t@cp -rp lib/musl/src/math            build/release/tinygo/lib/musl/src\n\t@cp -rp lib/musl/src/misc            build/release/tinygo/lib/musl/src\n\t@cp -rp lib/musl/src/multibyte       build/release/tinygo/lib/musl/src\n\t@cp -rp lib/musl/src/sched           build/release/tinygo/lib/musl/src\n\t@cp -rp lib/musl/src/signal          build/release/tinygo/lib/musl/src\n\t@cp -rp lib/musl/src/stdio           build/release/tinygo/lib/musl/src\n\t@cp -rp lib/musl/src/stdlib          build/release/tinygo/lib/musl/src\n\t@cp -rp lib/musl/src/string          build/release/tinygo/lib/musl/src\n\t@cp -rp lib/musl/src/thread          build/release/tinygo/lib/musl/src\n\t@cp -rp lib/musl/src/time            build/release/tinygo/lib/musl/src\n\t@cp -rp lib/musl/src/unistd          build/release/tinygo/lib/musl/src\n\t@cp -rp lib/musl/src/process         build/release/tinygo/lib/musl/src\n\t@cp -rp lib/mingw-w64/mingw-w64-crt/crt/pseudo-reloc.c          build/release/tinygo/lib/mingw-w64/mingw-w64-crt/crt\n\t@cp -rp lib/mingw-w64/mingw-w64-crt/def-include                 build/release/tinygo/lib/mingw-w64/mingw-w64-crt\n\t@cp -rp lib/mingw-w64/mingw-w64-crt/gdtoa                       build/release/tinygo/lib/mingw-w64/mingw-w64-crt\n\t@cp -rp lib/mingw-w64/mingw-w64-crt/include                     build/release/tinygo/lib/mingw-w64/mingw-w64-crt\n\t@cp -rp lib/mingw-w64/mingw-w64-crt/lib-common/api-ms-win-crt-* build/release/tinygo/lib/mingw-w64/mingw-w64-crt/lib-common\n\t@cp -rp lib/mingw-w64/mingw-w64-crt/lib-common/advapi32.def.in  build/release/tinygo/lib/mingw-w64/mingw-w64-crt/lib-common\n\t@cp -rp lib/mingw-w64/mingw-w64-crt/lib-common/kernel32.def.in  build/release/tinygo/lib/mingw-w64/mingw-w64-crt/lib-common\n\t@cp -rp lib/mingw-w64/mingw-w64-crt/lib-common/msvcrt.def.in    build/release/tinygo/lib/mingw-w64/mingw-w64-crt/lib-common\n\t@cp -rp lib/mingw-w64/mingw-w64-crt/math/x86                    build/release/tinygo/lib/mingw-w64/mingw-w64-crt/math\n\t@cp -rp lib/mingw-w64/mingw-w64-crt/misc                        build/release/tinygo/lib/mingw-w64/mingw-w64-crt\n\t@cp -rp lib/mingw-w64/mingw-w64-crt/stdio                       build/release/tinygo/lib/mingw-w64/mingw-w64-crt\n\t@cp -rp lib/mingw-w64/mingw-w64-headers/crt/                    build/release/tinygo/lib/mingw-w64/mingw-w64-headers\n\t@cp -rp lib/mingw-w64/mingw-w64-headers/defaults/include        build/release/tinygo/lib/mingw-w64/mingw-w64-headers/defaults\n\t@cp -rp lib/mingw-w64/mingw-w64-headers/include                 build/release/tinygo/lib/mingw-w64/mingw-w64-headers\n\t@cp -rp lib/nrfx/*                   build/release/tinygo/lib/nrfx\n\t@cp -rp lib/picolibc/newlib/libc/ctype       build/release/tinygo/lib/picolibc/newlib/libc\n\t@cp -rp lib/picolibc/newlib/libc/include     build/release/tinygo/lib/picolibc/newlib/libc\n\t@cp -rp lib/picolibc/newlib/libc/locale      build/release/tinygo/lib/picolibc/newlib/libc\n\t@cp -rp lib/picolibc/newlib/libc/string      build/release/tinygo/lib/picolibc/newlib/libc\n\t@cp -rp lib/picolibc/newlib/libc/tinystdio   build/release/tinygo/lib/picolibc/newlib/libc\n\t@cp -rp lib/picolibc/newlib/libm/common      build/release/tinygo/lib/picolibc/newlib/libm\n\t@cp -rp lib/picolibc/newlib/libm/math        build/release/tinygo/lib/picolibc/newlib/libm\n\t@cp -rp lib/picolibc-stdio.c         build/release/tinygo/lib\n\t@cp -rp lib/wasi-libc/dlmalloc/src                              build/release/tinygo/lib/wasi-libc/dlmalloc\n\t@cp -rp lib/wasi-libc/libc-bottom-half/cloudlibc                build/release/tinygo/lib/wasi-libc/libc-bottom-half\n\t@cp -rp lib/wasi-libc/libc-bottom-half/headers                  build/release/tinygo/lib/wasi-libc/libc-bottom-half\n\t@cp -rp lib/wasi-libc/libc-bottom-half/sources                  build/release/tinygo/lib/wasi-libc/libc-bottom-half\n\t@cp -rp lib/wasi-libc/libc-top-half/headers                     build/release/tinygo/lib/wasi-libc/libc-top-half\n\t@cp -rp lib/wasi-libc/libc-top-half/musl/arch/generic           build/release/tinygo/lib/wasi-libc/libc-top-half/musl/arch\n\t@cp -rp lib/wasi-libc/libc-top-half/musl/arch/wasm32            build/release/tinygo/lib/wasi-libc/libc-top-half/musl/arch\n\t@cp -rp lib/wasi-libc/libc-top-half/musl/include                build/release/tinygo/lib/wasi-libc/libc-top-half/musl\n\t@cp -rp lib/wasi-libc/libc-top-half/musl/src/conf               build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src\n\t@cp -rp lib/wasi-libc/libc-top-half/musl/src/dirent             build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src\n\t@cp -rp lib/wasi-libc/libc-top-half/musl/src/env                build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src\n\t@cp -rp lib/wasi-libc/libc-top-half/musl/src/errno              build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src\n\t@cp -rp lib/wasi-libc/libc-top-half/musl/src/exit               build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src\n\t@cp -rp lib/wasi-libc/libc-top-half/musl/src/fcntl              build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src\n\t@cp -rp lib/wasi-libc/libc-top-half/musl/src/fenv               build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src\n\t@cp -rp lib/wasi-libc/libc-top-half/musl/src/include            build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src\n\t@cp -rp lib/wasi-libc/libc-top-half/musl/src/internal           build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src\n\t@cp -rp lib/wasi-libc/libc-top-half/musl/src/legacy             build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src\n\t@cp -rp lib/wasi-libc/libc-top-half/musl/src/locale             build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src\n\t@cp -rp lib/wasi-libc/libc-top-half/musl/src/math               build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src\n\t@cp -rp lib/wasi-libc/libc-top-half/musl/src/misc               build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src\n\t@cp -rp lib/wasi-libc/libc-top-half/musl/src/multibyte          build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src\n\t@cp -rp lib/wasi-libc/libc-top-half/musl/src/network            build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src\n\t@cp -rp lib/wasi-libc/libc-top-half/musl/src/stat               build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src\n\t@cp -rp lib/wasi-libc/libc-top-half/musl/src/stdio              build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src\n\t@cp -rp lib/wasi-libc/libc-top-half/musl/src/stdlib             build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src\n\t@cp -rp lib/wasi-libc/libc-top-half/musl/src/string             build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src\n\t@cp -rp lib/wasi-libc/libc-top-half/musl/src/thread             build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src\n\t@cp -rp lib/wasi-libc/libc-top-half/musl/src/time               build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src\n\t@cp -rp lib/wasi-libc/libc-top-half/musl/src/unistd             build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src\n\t@cp -rp lib/wasi-libc/libc-top-half/sources                     build/release/tinygo/lib/wasi-libc/libc-top-half\n\t@cp -rp lib/wasi-cli/wit                                        build/release/tinygo/lib/wasi-cli/wit\n\t@cp -rp llvm-project/compiler-rt/lib/builtins build/release/tinygo/lib/compiler-rt-builtins\n\t@cp -rp llvm-project/compiler-rt/LICENSE.TXT  build/release/tinygo/lib/compiler-rt-builtins\n\t@cp -rp src                          build/release/tinygo/src\n\t@cp -rp targets                      build/release/tinygo/targets\n\nrelease:\n\ttar -czf build/release.tar.gz -C build/release tinygo\n\nDEB_ARCH ?= native\ndeb:\n\t@mkdir -p build/release-deb/usr/local/bin\n\t@mkdir -p build/release-deb/usr/local/lib\n\tcp -ar build/release/tinygo build/release-deb/usr/local/lib/tinygo\n\tln -sf ../lib/tinygo/bin/tinygo build/release-deb/usr/local/bin/tinygo\n\tfpm -f -s dir -t deb -n tinygo -a $(DEB_ARCH) -v $(shell grep \"const version = \" goenv/version.go | awk '{print $$NF}') -m '@tinygo-org' --description='TinyGo is a Go compiler for small places.' --license='BSD 3-Clause' --url=https://tinygo.org/ --deb-changelog CHANGELOG.md -p build/release.deb -C ./build/release-deb\n\nifneq ($(RELEASEONLY), 1)\nrelease: build/release\ndeb: build/release\nendif\n\n.PHONY: tools\ntools:\n\tcd internal/tools && go generate -tags tools ./\n\nLINTDIRS=src/os/ src/reflect/\n.PHONY: lint\nlint: tools ## Lint source tree\n\trevive -version\n\t# TODO: lint more directories!\n\t# revive.toml isn't flexible enough to filter out just one kind of error from a checker, so do it with grep here.\n\t# Can't use grep with friendly formatter.  Plain output isn't too bad, though.\n\t# Use 'grep .' to get rid of stray blank line\n\trevive -config revive.toml compiler/... $$( find $(LINTDIRS) -type f -name '*.go' ) \\\n\t\t| grep -v \"should have comment or be unexported\" \\\n\t\t| grep '.' \\\n\t\t| awk '{print}; END {exit NR>0}'\n\nSPELLDIRSCMD=find . -depth 1 -type d  | egrep -wv '.git|lib|llvm|src'; find src -depth 1 | egrep -wv 'device|internal|net|vendor'; find src/internal -depth 1 -type d | egrep -wv src/internal/wasi\n.PHONY: spell\nspell: tools ## Spellcheck source tree\n\tmisspell -error --dict misspell.csv -i 'ackward,devided,extint,rela' $$( $(SPELLDIRSCMD) ) *.go *.md\n\n.PHONY: spellfix\nspellfix: tools ## Same as spell, but fixes what it finds\n\tmisspell -w --dict misspell.csv -i 'ackward,devided,extint,rela' $$( $(SPELLDIRSCMD) ) *.go *.md\n\n# https://www.client9.com/self-documenting-makefiles/\n.PHONY: help\nhelp:\n\t@awk -F ':|##' '/^[^\\t].+?:.*?##/ {\\\n\tgsub(/\\$$\\(LLVM_BUILDDIR\\)/, \"$(LLVM_BUILDDIR)\"); \\\n        printf \"\\033[36m%-30s\\033[0m %s\\n\", $$1, $$NF \\\n        }' $(MAKEFILE_LIST)\n#.DEFAULT_GOAL=help\n"
  },
  {
    "path": "GOVERNANCE.md",
    "content": "TinyGo Team Members\n===================\n\nThe team of humans who maintain TinyGo.\n\n*   **Purpose**: To maintain the community, code, documentation, and tools for the TinyGo compiler.\n*   **Board**: The group of people who share responsibility for key decisions for the TinyGo organization.  \n    *   **Majority Voting**: The board makes decisions by majority vote.\n    *   **Membership**: The board elects its own members.\n*   **Do-ocracy**: Those who step forward to do a given task propose how it should be done. Then other interested people can make comments.\n*   **Proof of Work**: Power in decision-making is slightly weighted based on a participant's labor for the community.\n*   **Initiation**: We need to establish a procedure for how people join the team of maintainers.\n*   **Transparency**: Important information should be made publicly available, ideally in a way that allows for public comment.\n*   **Code of Conduct**: Participants agree to abide by the current project Code of Conduct.\n\n## Members\n\n* Ayke van Laethem (@aykevl)\n* Daniel Esteban (@conejoninja)\n* Ron Evans (@deadprogram)\n* Damian Gryski (@dgryski)\n* Masaaki Takasago (@sago35)\n* Patricio Whittingslow (@soypat)\n* Yurii Soldak (@ysoldak)\n\n## Experimental\n\n*   **Monthly Meeting**: A monthly meeting for the team and any other interested participants.  \n    Duration: 1 hour  \n    Facilitation: @deadprogram\n    Schedule: See https://github.com/tinygo-org/tinygo/wiki/Meetings for more information\n\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2018-2025 The TinyGo Authors. All rights reserved.\n\nTinyGo includes portions of the Go standard library.\nCopyright (c) 2009-2024 The Go Authors. All rights reserved.\n\nTinyGo includes portions of LLVM, which is under the Apache License v2.0 with\nLLVM Exceptions. See https://llvm.org/LICENSE.txt for license information.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n   * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n   * Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n   * Neither the name of the copyright holder nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "README.md",
    "content": "# TinyGo - Go compiler for small places\n\n[![Linux](https://github.com/tinygo-org/tinygo/actions/workflows/linux.yml/badge.svg?branch=dev)](https://github.com/tinygo-org/tinygo/actions/workflows/linux.yml) [![macOS](https://github.com/tinygo-org/tinygo/actions/workflows/build-macos.yml/badge.svg?branch=dev)](https://github.com/tinygo-org/tinygo/actions/workflows/build-macos.yml) [![Windows](https://github.com/tinygo-org/tinygo/actions/workflows/windows.yml/badge.svg?branch=dev)](https://github.com/tinygo-org/tinygo/actions/workflows/windows.yml) [![Docker](https://github.com/tinygo-org/tinygo/actions/workflows/docker.yml/badge.svg?branch=dev)](https://github.com/tinygo-org/tinygo/actions/workflows/docker.yml) [![Nix](https://github.com/tinygo-org/tinygo/actions/workflows/nix.yml/badge.svg?branch=dev)](https://github.com/tinygo-org/tinygo/actions/workflows/nix.yml) [![CircleCI](https://circleci.com/gh/tinygo-org/tinygo/tree/dev.svg?style=svg)](https://circleci.com/gh/tinygo-org/tinygo/tree/dev)\n\nTinyGo is a Go compiler intended for use in small places such as microcontrollers, WebAssembly (wasm/wasi), and command-line tools.\n\nIt reuses libraries used by the [Go language tools](https://golang.org/pkg/go/) alongside [LLVM](http://llvm.org) to provide an alternative way to compile programs written in the Go programming language.\n\n## Embedded\n\nHere is an example program that blinks the built-in LED when run directly on any supported board with onboard LED:\n\n```go\npackage main\n\nimport (\n    \"machine\"\n    \"time\"\n)\n\nfunc main() {\n    led := machine.LED\n    led.Configure(machine.PinConfig{Mode: machine.PinOutput})\n    for {\n        led.Low()\n        time.Sleep(time.Millisecond * 1000)\n\n        led.High()\n        time.Sleep(time.Millisecond * 1000)\n    }\n}\n```\n\nThe above program can be compiled and run without modification on an Arduino Uno, an Adafruit ItsyBitsy M0, or any of the supported boards that have a built-in LED, just by setting the correct TinyGo compiler target. For example, this compiles and flashes an Arduino Uno:\n\n```shell\ntinygo flash -target arduino examples/blinky1\n```\n\n## WebAssembly\n\nTinyGo is very useful for compiling programs both for use in browsers (WASM) as well as for use on servers and other edge devices (WASI).\n\nTinyGo programs can run in [Fastly Compute](https://www.fastly.com/documentation/guides/compute/go/), [Fermyon Spin](https://developer.fermyon.com/spin/go-components), [wazero](https://wazero.io/languages/tinygo/) and many other WebAssembly runtimes.\n\nHere is a small TinyGo program for use by a WASI host application:\n\n```go\npackage main\n\n//go:wasmexport add\nfunc add(x, y uint32) uint32 {\n\treturn x + y\n}\n```\n\nThis compiles the above TinyGo program for use on any WASI Preview 1 runtime:\n\n```shell\ntinygo build -buildmode=c-shared -o add.wasm -target=wasip1 add.go\n```\n\nYou can also use the same syntax as Go 1.24+:\n\n```shell\nGOARCH=wasip1 GOOS=wasm tinygo build -buildmode=c-shared -o add.wasm add.go\n```\n\n## Installation\n\nSee the [getting started instructions](https://tinygo.org/getting-started/) for information on how to install TinyGo, as well as how to run the TinyGo compiler using our Docker container.\n\n## Supported targets\n\n### Embedded\n\nYou can compile TinyGo programs for over 94 different microcontroller boards.\n\nFor more information, please see https://tinygo.org/docs/reference/microcontrollers/\n\n### WebAssembly\n\nTinyGo programs can be compiled for both WASM and WASI targets.\n\nFor more information, see https://tinygo.org/docs/guides/webassembly/\n\n### Operating Systems\n\nYou can also compile programs for Linux, macOS, and Windows targets.\n\nFor more information:\n\n- Linux https://tinygo.org/docs/guides/linux/\n\n- macOS https://tinygo.org/docs/guides/macos/\n\n- Windows https://tinygo.org/docs/guides/windows/\n\n## Currently supported features:\n\nFor a description of currently supported Go language features, please see [https://tinygo.org/lang-support/](https://tinygo.org/lang-support/).\n\n## Documentation\n\nDocumentation is located on our web site at [https://tinygo.org/](https://tinygo.org/).\n\nYou can find the web site code at [https://github.com/tinygo-org/tinygo-site](https://github.com/tinygo-org/tinygo-site).\n\n## Getting help\n\nIf you're looking for a more interactive way to discuss TinyGo usage or\ndevelopment, we have a [#TinyGo channel](https://gophers.slack.com/messages/CDJD3SUP6/)\non the [Gophers Slack](https://gophers.slack.com).\n\nIf you need an invitation for the Gophers Slack, you can generate one here which\nshould arrive fairly quickly (under 1 min): https://invite.slack.golangbridge.org\n\n## Contributing\n\nYour contributions are welcome!\n\nPlease take a look at our [Contributing](https://tinygo.org/docs/guides/contributing/) page on our web site for details.\n\n## Project Scope\n\nGoals:\n\n* Have very small binary sizes. Don't pay for what you don't use.\n* Support for most common microcontroller boards.\n* Be usable on the web using WebAssembly.\n* Good CGo support, with no more overhead than a regular function call.\n* Support most standard library packages and compile most Go code without modification.\n\nNon-goals:\n\n* Be efficient while using zillions of goroutines. However, good goroutine support is certainly a goal.\n* Be as fast as `gc`. However, LLVM will probably be better at optimizing certain things so TinyGo might actually turn out to be faster for number crunching.\n* Be able to compile every Go program out there.\n\n## Why this project exists\n\n> We never expected Go to be an embedded language and so its got serious problems...\n\n-- Rob Pike, [GopherCon 2014 Opening Keynote](https://www.youtube.com/watch?v=VoS7DsT1rdM&feature=youtu.be&t=2799)\n\nTinyGo is a project to bring Go to microcontrollers and small systems with a single processor core. It is similar to [emgo](https://github.com/ziutek/emgo) but a major difference is that we want to keep the Go memory model (which implies garbage collection of some sort). Another difference is that TinyGo uses LLVM internally instead of emitting C, which hopefully leads to smaller and more efficient code and certainly leads to more flexibility.\n\nThe original reasoning was: if [Python](https://micropython.org/) can run on microcontrollers, then certainly [Go](https://golang.org/) should be able to run on even lower level micros.\n\n## License\n\nThis project is licensed under the BSD 3-clause license, just like the [Go project](https://golang.org/LICENSE) itself.\n\nSome code has been copied from the LLVM project and is therefore licensed under [a variant of the Apache 2.0 license](http://releases.llvm.org/11.0.0/LICENSE.TXT). This has been clearly indicated in the header of these files.\n\nSome code has been copied and/or ported from Paul Stoffregen's Teensy libraries and is therefore licensed under PJRC's license. This has been clearly indicated in the header of these files.\n"
  },
  {
    "path": "bin/.keep",
    "content": ""
  },
  {
    "path": "builder/ar.go",
    "content": "package builder\n\nimport (\n\t\"bytes\"\n\t\"debug/elf\"\n\t\"debug/macho\"\n\t\"debug/pe\"\n\t\"encoding/binary\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"time\"\n\n\twasm \"github.com/aykevl/go-wasm\"\n\t\"github.com/blakesmith/ar\"\n)\n\n// makeArchive creates an archive for static linking from a list of object files\n// given as a parameter. It is equivalent to the following command:\n//\n//\tar -rcs <archivePath> <objs...>\nfunc makeArchive(arfile *os.File, objs []string) error {\n\t// Open the archive file.\n\tarwriter := ar.NewWriter(arfile)\n\terr := arwriter.WriteGlobalHeader()\n\tif err != nil {\n\t\treturn &os.PathError{Op: \"write ar header\", Path: arfile.Name(), Err: err}\n\t}\n\n\t// Open all object files and read the symbols for the symbol table.\n\tsymbolTable := []struct {\n\t\tname      string // symbol name\n\t\tfileIndex int    // index into objfiles\n\t}{}\n\tarchiveOffsets := make([]int32, len(objs))\n\tfor i, objpath := range objs {\n\t\tobjfile, err := os.Open(objpath)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// Read the symbols and add them to the symbol table.\n\t\tif dbg, err := elf.NewFile(objfile); err == nil {\n\t\t\tsymbols, err := dbg.Symbols()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tfor _, symbol := range symbols {\n\t\t\t\tbind := elf.ST_BIND(symbol.Info)\n\t\t\t\tif bind != elf.STB_GLOBAL && bind != elf.STB_WEAK {\n\t\t\t\t\t// Don't include local symbols (STB_LOCAL).\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif elf.ST_TYPE(symbol.Info) != elf.STT_FUNC && elf.ST_TYPE(symbol.Info) != elf.STT_OBJECT {\n\t\t\t\t\t// Not a function.\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t// Include in archive.\n\t\t\t\tsymbolTable = append(symbolTable, struct {\n\t\t\t\t\tname      string\n\t\t\t\t\tfileIndex int\n\t\t\t\t}{symbol.Name, i})\n\t\t\t}\n\t\t} else if dbg, err := macho.NewFile(objfile); err == nil {\n\t\t\tfor _, symbol := range dbg.Symtab.Syms {\n\t\t\t\t// See mach-o/nlist.h\n\t\t\t\tif symbol.Type&0x0e != 0xe { // (symbol.Type & N_TYPE) != N_SECT\n\t\t\t\t\tcontinue // undefined symbol\n\t\t\t\t}\n\t\t\t\tif symbol.Type&0x01 == 0 { // (symbol.Type & N_EXT) == 0\n\t\t\t\t\tcontinue // internal symbol (static, etc)\n\t\t\t\t}\n\t\t\t\tsymbolTable = append(symbolTable, struct {\n\t\t\t\t\tname      string\n\t\t\t\t\tfileIndex int\n\t\t\t\t}{symbol.Name, i})\n\t\t\t}\n\t\t} else if dbg, err := pe.NewFile(objfile); err == nil {\n\t\t\tfor _, symbol := range dbg.Symbols {\n\t\t\t\tif symbol.StorageClass != 2 {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif symbol.SectionNumber == 0 {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tsymbolTable = append(symbolTable, struct {\n\t\t\t\t\tname      string\n\t\t\t\t\tfileIndex int\n\t\t\t\t}{symbol.Name, i})\n\t\t\t}\n\t\t} else if dbg, err := wasm.Parse(objfile); err == nil {\n\t\t\tfor _, s := range dbg.Sections {\n\t\t\t\tswitch section := s.(type) {\n\t\t\t\tcase *wasm.SectionLinking:\n\t\t\t\t\tfor _, symbol := range section.Symbols {\n\t\t\t\t\t\tif symbol.Flags&wasm.LinkingSymbolFlagUndefined != 0 {\n\t\t\t\t\t\t\t// Don't list undefined functions.\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif symbol.Flags&wasm.LinkingSymbolFlagBindingLocal != 0 {\n\t\t\t\t\t\t\t// Don't include local symbols.\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif symbol.Kind != wasm.LinkingSymbolKindFunction && symbol.Kind != wasm.LinkingSymbolKindData {\n\t\t\t\t\t\t\t// Link functions and data symbols.\n\t\t\t\t\t\t\t// Some data symbols need to be included, such as\n\t\t\t\t\t\t\t// __log_data.\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Include in the archive.\n\t\t\t\t\t\tsymbolTable = append(symbolTable, struct {\n\t\t\t\t\t\t\tname      string\n\t\t\t\t\t\t\tfileIndex int\n\t\t\t\t\t\t}{symbol.Name, i})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\treturn fmt.Errorf(\"failed to open file %s as WASM, ELF or PE/COFF: %w\", objpath, err)\n\t\t}\n\n\t\t// Close file, to avoid issues with too many open files (especially on\n\t\t// MacOS X).\n\t\tobjfile.Close()\n\t}\n\n\t// Create the symbol table buffer.\n\t// For some (sparse) details on the file format:\n\t// https://en.wikipedia.org/wiki/Ar_(Unix)#System_V_(or_GNU)_variant\n\tbuf := &bytes.Buffer{}\n\tbinary.Write(buf, binary.BigEndian, int32(len(symbolTable)))\n\tfor range symbolTable {\n\t\t// This is a placeholder index, it will be updated after all files have\n\t\t// been written to the archive (see the end of this function).\n\t\terr = binary.Write(buf, binary.BigEndian, int32(0))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tfor _, sym := range symbolTable {\n\t\t_, err := buf.Write([]byte(sym.name + \"\\x00\"))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tfor buf.Len()%2 != 0 {\n\t\t// The symbol table must be aligned.\n\t\t// This appears to be required by lld.\n\t\tbuf.WriteByte(0)\n\t}\n\n\t// Write the symbol table.\n\terr = arwriter.WriteHeader(&ar.Header{\n\t\tName:    \"/\",\n\t\tModTime: time.Unix(0, 0),\n\t\tUid:     0,\n\t\tGid:     0,\n\t\tMode:    0,\n\t\tSize:    int64(buf.Len()),\n\t})\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Keep track of the start of the symbol table.\n\tsymbolTableStart, err := arfile.Seek(0, io.SeekCurrent)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Write symbol table contents.\n\t_, err = arfile.Write(buf.Bytes())\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Add all object files to the archive.\n\tvar copyBuf bytes.Buffer\n\tfor i, objpath := range objs {\n\t\tobjfile, err := os.Open(objpath)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdefer objfile.Close()\n\n\t\t// Store the start index, for when we'll update the symbol table with\n\t\t// the correct file start indices.\n\t\toffset, err := arfile.Seek(0, io.SeekCurrent)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif int64(int32(offset)) != offset {\n\t\t\treturn errors.New(\"large archives (4GB+) not supported: \" + arfile.Name())\n\t\t}\n\t\tarchiveOffsets[i] = int32(offset)\n\n\t\t// Write the file header.\n\t\tst, err := objfile.Stat()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\terr = arwriter.WriteHeader(&ar.Header{\n\t\t\tName:    filepath.Base(objfile.Name()),\n\t\t\tModTime: time.Unix(0, 0),\n\t\t\tUid:     0,\n\t\t\tGid:     0,\n\t\t\tMode:    0644,\n\t\t\tSize:    st.Size(),\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// Copy the file contents into the archive.\n\t\t// First load all contents into a buffer, then write it all in one go to\n\t\t// the archive file. This is a bit complicated, but is necessary because\n\t\t// io.Copy can't deal with files that are of an odd size.\n\t\tcopyBuf.Reset()\n\t\tn, err := io.Copy(&copyBuf, objfile)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"could not copy object file into ar file: %w\", err)\n\t\t}\n\t\tif n != st.Size() {\n\t\t\treturn errors.New(\"file modified during ar creation: \" + arfile.Name())\n\t\t}\n\t\t_, err = arwriter.Write(copyBuf.Bytes())\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"could not copy object file into ar file: %w\", err)\n\t\t}\n\n\t\t// File is not needed anymore.\n\t\tobjfile.Close()\n\t}\n\n\t// Create symbol indices.\n\tindicesBuf := &bytes.Buffer{}\n\tfor _, sym := range symbolTable {\n\t\terr = binary.Write(indicesBuf, binary.BigEndian, archiveOffsets[sym.fileIndex])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// Overwrite placeholder indices.\n\t_, err = arfile.WriteAt(indicesBuf.Bytes(), symbolTableStart+4)\n\treturn err\n}\n"
  },
  {
    "path": "builder/bdwgc.go",
    "content": "package builder\n\n// The well-known conservative Boehm-Demers-Weiser GC.\n// This file provides a way to compile this GC for use with TinyGo.\n\nimport (\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/tinygo-org/tinygo/goenv\"\n)\n\nvar BoehmGC = Library{\n\tname: \"bdwgc\",\n\tcflags: func(target, headerPath string) []string {\n\t\tlibdir := filepath.Join(goenv.Get(\"TINYGOROOT\"), \"lib/bdwgc\")\n\t\tflags := []string{\n\t\t\t// use a modern environment\n\t\t\t\"-DUSE_MMAP\",              // mmap is available\n\t\t\t\"-DUSE_MUNMAP\",            // return memory to the OS using munmap\n\t\t\t\"-DGC_BUILTIN_ATOMIC\",     // use compiler intrinsics for atomic operations\n\t\t\t\"-DNO_EXECUTE_PERMISSION\", // don't make the heap executable\n\n\t\t\t// specific flags for TinyGo\n\t\t\t\"-DALL_INTERIOR_POINTERS\",  // scan interior pointers (needed for Go)\n\t\t\t\"-DIGNORE_DYNAMIC_LOADING\", // we don't support dynamic loading at the moment\n\t\t\t\"-DNO_GETCONTEXT\",          // musl doesn't support getcontext()\n\t\t\t\"-DGC_DISABLE_INCREMENTAL\", // don't mess with SIGSEGV and such\n\n\t\t\t// Use a minimal environment.\n\t\t\t\"-DNO_MSGBOX_ON_ERROR\", // don't call MessageBoxA on Windows\n\t\t\t\"-DDONT_USE_ATEXIT\",\n\t\t\t\"-DNO_GETENV\",          // smaller binary, more predictable configuration\n\t\t\t\"-DNO_CLOCK\",           // don't use system clock\n\t\t\t\"-DNO_DEBUGGING\",       // reduce code size\n\t\t\t\"-DGC_NO_FINALIZATION\", // finalization is not used at the moment\n\n\t\t\t// Special flag to work around the lack of __data_start in ld.lld.\n\t\t\t// TODO: try to fix this in LLVM/lld directly so we don't have to\n\t\t\t// work around it anymore.\n\t\t\t\"-DGC_DONT_REGISTER_MAIN_STATIC_DATA\",\n\n\t\t\t// Do not scan the stack. We have our own mechanism to do this.\n\t\t\t\"-DSTACK_NOT_SCANNED\",\n\t\t\t\"-DNO_PROC_STAT\",  // we scan the stack manually (don't read /proc/self/stat on Linux)\n\t\t\t\"-DSTACKBOTTOM=0\", // dummy value, we scan the stack manually\n\n\t\t\t// Assertions can be enabled while debugging GC issues.\n\t\t\t//\"-DGC_ASSERTIONS\",\n\n\t\t\t// We use our own way of dealing with threads (that is a bit hacky).\n\t\t\t// See src/runtime/gc_boehm.go.\n\t\t\t//\"-DGC_THREADS\",\n\t\t\t//\"-DTHREAD_LOCAL_ALLOC\",\n\n\t\t\t\"-I\" + libdir + \"/include\",\n\t\t}\n\t\treturn flags\n\t},\n\tneedsLibc: true,\n\tsourceDir: func() string {\n\t\treturn filepath.Join(goenv.Get(\"TINYGOROOT\"), \"lib/bdwgc\")\n\t},\n\tlibrarySources: func(target string, _ bool) ([]string, error) {\n\t\tsources := []string{\n\t\t\t\"allchblk.c\",\n\t\t\t\"alloc.c\",\n\t\t\t\"blacklst.c\",\n\t\t\t\"dbg_mlc.c\",\n\t\t\t\"dyn_load.c\",\n\t\t\t\"headers.c\",\n\t\t\t\"mach_dep.c\",\n\t\t\t\"malloc.c\",\n\t\t\t\"mark.c\",\n\t\t\t\"mark_rts.c\",\n\t\t\t\"misc.c\",\n\t\t\t\"new_hblk.c\",\n\t\t\t\"os_dep.c\",\n\t\t\t\"reclaim.c\",\n\t\t}\n\t\tif strings.Split(target, \"-\")[2] == \"windows\" {\n\t\t\t// Due to how the linker on Windows works (that doesn't allow\n\t\t\t// undefined functions), we need to include these extra files.\n\t\t\tsources = append(sources,\n\t\t\t\t\"mallocx.c\",\n\t\t\t\t\"ptr_chck.c\",\n\t\t\t)\n\t\t}\n\t\treturn sources, nil\n\t},\n}\n"
  },
  {
    "path": "builder/build.go",
    "content": "// Package builder is the compiler driver of TinyGo. It takes in a package name\n// and an output path, and outputs an executable. It manages the entire\n// compilation pipeline in between.\npackage builder\n\nimport (\n\t\"crypto/sha256\"\n\t\"crypto/sha512\"\n\t\"debug/elf\"\n\t\"encoding/binary\"\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/types\"\n\t\"hash/crc32\"\n\t\"math/bits\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/gofrs/flock\"\n\t\"github.com/tinygo-org/tinygo/compileopts\"\n\t\"github.com/tinygo-org/tinygo/compiler\"\n\t\"github.com/tinygo-org/tinygo/goenv\"\n\t\"github.com/tinygo-org/tinygo/interp\"\n\t\"github.com/tinygo-org/tinygo/loader\"\n\t\"github.com/tinygo-org/tinygo/stacksize\"\n\t\"github.com/tinygo-org/tinygo/transform\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// BuildResult is the output of a build. This includes the binary itself and\n// some other metadata that is obtained while building the binary.\ntype BuildResult struct {\n\t// The executable directly from the linker, usually including debug\n\t// information. Used for GDB for example.\n\tExecutable string\n\n\t// A path to the output binary. It is stored in the tmpdir directory of the\n\t// Build function, so if it should be kept it must be copied or moved away.\n\t// It is often the same as Executable, but differs if the output format is\n\t// .hex for example (instead of the usual ELF).\n\tBinary string\n\n\t// The directory of the main package. This is useful for testing as the test\n\t// binary must be run in the directory of the tested package.\n\tMainDir string\n\n\t// The root of the Go module tree.  This is used for running tests in emulator\n\t// that restrict file system access to allow them to grant access to the entire\n\t// source tree they're likely to need to read testdata from.\n\tModuleRoot string\n\n\t// ImportPath is the import path of the main package. This is useful for\n\t// correctly printing test results: the import path isn't always the same as\n\t// the path listed on the command line.\n\tImportPath string\n\n\t// Map from path to package name. It is needed to attribute binary size to\n\t// the right Go package.\n\tPackagePathMap map[string]string\n}\n\n// packageAction is the struct that is serialized to JSON and hashed, to work as\n// a cache key of compiled packages. It should contain all the information that\n// goes into a compiled package to avoid using stale data.\n//\n// Right now it's still important to include a hash of every import, because a\n// dependency might have a public constant that this package uses and thus this\n// package will need to be recompiled if that constant changes. In the future,\n// the type data should be serialized to disk which can then be used as cache\n// key, avoiding the need for recompiling all dependencies when only the\n// implementation of an imported package changes.\ntype packageAction struct {\n\tImportPath       string\n\tCompilerBuildID  string\n\tTinyGoVersion    string\n\tLLVMVersion      string\n\tConfig           *compiler.Config\n\tCFlags           []string\n\tFileHashes       map[string]string // hash of every file that's part of the package\n\tEmbeddedFiles    map[string]string // hash of all the //go:embed files in the package\n\tImports          map[string]string // map from imported package to action ID hash\n\tOptLevel         string            // LLVM optimization level (O0, O1, O2, Os, Oz)\n\tUndefinedGlobals []string          // globals that are left as external globals (no initializer)\n}\n\n// Build performs a single package to executable Go build. It takes in a package\n// name, an output path, and set of compile options and from that it manages the\n// whole compilation process.\n//\n// The error value may be of type *MultiError. Callers will likely want to check\n// for this case and print such errors individually.\nfunc Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildResult, error) {\n\t// Read the build ID of the tinygo binary.\n\t// Used as a cache key for package builds.\n\tcompilerBuildID, err := ReadBuildID()\n\tif err != nil {\n\t\treturn BuildResult{}, err\n\t}\n\n\tif config.Options.Work {\n\t\tfmt.Printf(\"WORK=%s\\n\", tmpdir)\n\t}\n\n\t// Look up the build cache directory, which is used to speed up incremental\n\t// builds.\n\tcacheDir := goenv.Get(\"GOCACHE\")\n\tif cacheDir == \"off\" {\n\t\t// Use temporary build directory instead, effectively disabling the\n\t\t// build cache.\n\t\tcacheDir = tmpdir\n\t}\n\n\t// Create default global values.\n\tglobalValues := map[string]map[string]string{\n\t\t\"runtime\": {\n\t\t\t\"buildVersion\": goenv.Version(),\n\t\t},\n\t\t\"testing\": {},\n\t}\n\tif config.TestConfig.CompileTestBinary {\n\t\t// The testing.testBinary is set to \"1\" when in a test.\n\t\t// This is needed for testing.Testing() to work correctly.\n\t\tglobalValues[\"testing\"][\"testBinary\"] = \"1\"\n\t}\n\n\t// Copy over explicitly set global values, like\n\t// -ldflags=\"-X main.Version=\"1.0\"\n\tfor pkgPath, vals := range config.Options.GlobalValues {\n\t\tif _, ok := globalValues[pkgPath]; !ok {\n\t\t\tglobalValues[pkgPath] = map[string]string{}\n\t\t}\n\t\tfor k, v := range vals {\n\t\t\tglobalValues[pkgPath][k] = v\n\t\t}\n\t}\n\n\t// Check for a libc dependency.\n\t// As a side effect, this also creates the headers for the given libc, if\n\t// the libc needs them.\n\troot := goenv.Get(\"TINYGOROOT\")\n\tvar libcDependencies []*compileJob\n\tswitch config.Target.Libc {\n\tcase \"darwin-libSystem\":\n\t\tlibcJob := makeDarwinLibSystemJob(config, tmpdir)\n\t\tlibcDependencies = append(libcDependencies, libcJob)\n\tcase \"musl\":\n\t\tvar unlock func()\n\t\tlibcJob, unlock, err := libMusl.load(config, tmpdir)\n\t\tif err != nil {\n\t\t\treturn BuildResult{}, err\n\t\t}\n\t\tdefer unlock()\n\t\tlibcDependencies = append(libcDependencies, dummyCompileJob(filepath.Join(filepath.Dir(libcJob.result), \"crt1.o\")))\n\t\tlibcDependencies = append(libcDependencies, libcJob)\n\tcase \"picolibc\":\n\t\tlibcJob, unlock, err := libPicolibc.load(config, tmpdir)\n\t\tif err != nil {\n\t\t\treturn BuildResult{}, err\n\t\t}\n\t\tdefer unlock()\n\t\tlibcDependencies = append(libcDependencies, libcJob)\n\tcase \"wasi-libc\":\n\t\tlibcJob, unlock, err := libWasiLibc.load(config, tmpdir)\n\t\tif err != nil {\n\t\t\treturn BuildResult{}, err\n\t\t}\n\t\tdefer unlock()\n\t\tlibcDependencies = append(libcDependencies, libcJob)\n\tcase \"wasmbuiltins\":\n\t\tlibcJob, unlock, err := libWasmBuiltins.load(config, tmpdir)\n\t\tif err != nil {\n\t\t\treturn BuildResult{}, err\n\t\t}\n\t\tdefer unlock()\n\t\tlibcDependencies = append(libcDependencies, libcJob)\n\tcase \"mingw-w64\":\n\t\tlibcJob, unlock, err := libMinGW.load(config, tmpdir)\n\t\tif err != nil {\n\t\t\treturn BuildResult{}, err\n\t\t}\n\t\tdefer unlock()\n\t\tlibcDependencies = append(libcDependencies, libcJob)\n\t\tlibcDependencies = append(libcDependencies, makeMinGWExtraLibs(tmpdir, config.GOARCH())...)\n\tcase \"\":\n\t\t// no library specified, so nothing to do\n\tdefault:\n\t\treturn BuildResult{}, fmt.Errorf(\"unknown libc: %s\", config.Target.Libc)\n\t}\n\n\toptLevel, speedLevel, sizeLevel := config.OptLevel()\n\tcompilerConfig := &compiler.Config{\n\t\tTriple:          config.Triple(),\n\t\tCPU:             config.CPU(),\n\t\tFeatures:        config.Features(),\n\t\tABI:             config.ABI(),\n\t\tGOOS:            config.GOOS(),\n\t\tGOARCH:          config.GOARCH(),\n\t\tBuildMode:       config.BuildMode(),\n\t\tCodeModel:       config.CodeModel(),\n\t\tRelocationModel: config.RelocationModel(),\n\t\tSizeLevel:       sizeLevel,\n\t\tTinyGoVersion:   goenv.Version(),\n\n\t\tScheduler:          config.Scheduler(),\n\t\tAutomaticStackSize: config.AutomaticStackSize(),\n\t\tDefaultStackSize:   config.StackSize(),\n\t\tMaxStackAlloc:      config.MaxStackAlloc(),\n\t\tNeedsStackObjects:  config.NeedsStackObjects(),\n\t\tDebug:              !config.Options.SkipDWARF, // emit DWARF except when -internal-nodwarf is passed\n\t\tNobounds:           config.Options.Nobounds,\n\t\tPanicStrategy:      config.PanicStrategy(),\n\t}\n\n\t// Load the target machine, which is the LLVM object that contains all\n\t// details of a target (alignment restrictions, pointer size, default\n\t// address spaces, etc).\n\tmachine, err := compiler.NewTargetMachine(compilerConfig)\n\tif err != nil {\n\t\treturn BuildResult{}, err\n\t}\n\tdefer machine.Dispose()\n\n\t// Load entire program AST into memory.\n\tlprogram, err := loader.Load(config, pkgName, types.Config{\n\t\tSizes: compiler.Sizes(machine),\n\t})\n\tif err != nil {\n\t\treturn BuildResult{}, err\n\t}\n\tresult := BuildResult{\n\t\tModuleRoot: lprogram.MainPkg().Module.Dir,\n\t\tMainDir:    lprogram.MainPkg().Dir,\n\t\tImportPath: lprogram.MainPkg().ImportPath,\n\t}\n\tif result.ModuleRoot == \"\" {\n\t\t// If there is no module root, just the regular root.\n\t\tresult.ModuleRoot = lprogram.MainPkg().Root\n\t}\n\terr = lprogram.Parse()\n\tif err != nil {\n\t\treturn result, err\n\t}\n\n\t// Store which filesystem paths map to which package name.\n\tresult.PackagePathMap = make(map[string]string, len(lprogram.Packages))\n\tfor _, pkg := range lprogram.Sorted() {\n\t\tresult.PackagePathMap[pkg.OriginalDir()] = pkg.Pkg.Path()\n\t}\n\n\t// Create the *ssa.Program. This does not yet build the entire SSA of the\n\t// program so it's pretty fast and doesn't need to be parallelized.\n\tprogram := lprogram.LoadSSA()\n\n\t// Add jobs to compile each package.\n\t// Packages that have a cache hit will not be compiled again.\n\tvar packageJobs []*compileJob\n\tpackageActionIDJobs := make(map[string]*compileJob)\n\n\tvar embedFileObjects []*compileJob\n\tfor _, pkg := range lprogram.Sorted() {\n\t\tpkg := pkg // necessary to avoid a race condition\n\n\t\tvar undefinedGlobals []string\n\t\tfor name := range globalValues[pkg.Pkg.Path()] {\n\t\t\tundefinedGlobals = append(undefinedGlobals, name)\n\t\t}\n\t\tsort.Strings(undefinedGlobals)\n\n\t\t// Make compile jobs to load files to be embedded in the output binary.\n\t\tvar actionIDDependencies []*compileJob\n\t\tallFiles := map[string][]*loader.EmbedFile{}\n\t\tfor _, files := range pkg.EmbedGlobals {\n\t\t\tfor _, file := range files {\n\t\t\t\tallFiles[file.Name] = append(allFiles[file.Name], file)\n\t\t\t}\n\t\t}\n\t\tfor name, files := range allFiles {\n\t\t\tname := name\n\t\t\tfiles := files\n\t\t\tjob := &compileJob{\n\t\t\t\tdescription: \"make object file for \" + name,\n\t\t\t\trun: func(job *compileJob) error {\n\t\t\t\t\t// Read the file contents in memory.\n\t\t\t\t\tpath := filepath.Join(pkg.Dir, name)\n\t\t\t\t\tdata, err := os.ReadFile(path)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\n\t\t\t\t\t// Hash the file.\n\t\t\t\t\tsum := sha256.Sum256(data)\n\t\t\t\t\thexSum := hex.EncodeToString(sum[:16])\n\n\t\t\t\t\tfor _, file := range files {\n\t\t\t\t\t\tfile.Size = uint64(len(data))\n\t\t\t\t\t\tfile.Hash = hexSum\n\t\t\t\t\t\tif file.NeedsData {\n\t\t\t\t\t\t\tfile.Data = data\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tjob.result, err = createEmbedObjectFile(string(data), hexSum, name, pkg.OriginalDir(), tmpdir, compilerConfig)\n\t\t\t\t\treturn err\n\t\t\t\t},\n\t\t\t}\n\t\t\tactionIDDependencies = append(actionIDDependencies, job)\n\t\t\tembedFileObjects = append(embedFileObjects, job)\n\t\t}\n\n\t\t// Action ID jobs need to know the action ID of all the jobs the package\n\t\t// imports.\n\t\tvar importedPackages []*compileJob\n\t\tfor _, imported := range pkg.Pkg.Imports() {\n\t\t\tjob, ok := packageActionIDJobs[imported.Path()]\n\t\t\tif !ok {\n\t\t\t\treturn result, fmt.Errorf(\"package %s imports %s but couldn't find dependency\", pkg.ImportPath, imported.Path())\n\t\t\t}\n\t\t\timportedPackages = append(importedPackages, job)\n\t\t\tactionIDDependencies = append(actionIDDependencies, job)\n\t\t}\n\n\t\t// Create a job that will calculate the action ID for a package compile\n\t\t// job. The action ID is the cache key that is used for caching this\n\t\t// package.\n\t\tpackageActionIDJob := &compileJob{\n\t\t\tdescription:  \"calculate cache key for package \" + pkg.ImportPath,\n\t\t\tdependencies: actionIDDependencies,\n\t\t\trun: func(job *compileJob) error {\n\t\t\t\t// Create a cache key: a hash from the action ID below that contains all\n\t\t\t\t// the parameters for the build.\n\t\t\t\tactionID := packageAction{\n\t\t\t\t\tImportPath:       pkg.ImportPath,\n\t\t\t\t\tCompilerBuildID:  string(compilerBuildID),\n\t\t\t\t\tLLVMVersion:      llvm.Version,\n\t\t\t\t\tConfig:           compilerConfig,\n\t\t\t\t\tCFlags:           pkg.CFlags,\n\t\t\t\t\tFileHashes:       make(map[string]string, len(pkg.FileHashes)),\n\t\t\t\t\tEmbeddedFiles:    make(map[string]string, len(allFiles)),\n\t\t\t\t\tImports:          make(map[string]string, len(pkg.Pkg.Imports())),\n\t\t\t\t\tOptLevel:         optLevel,\n\t\t\t\t\tUndefinedGlobals: undefinedGlobals,\n\t\t\t\t}\n\t\t\t\tfor filePath, hash := range pkg.FileHashes {\n\t\t\t\t\tactionID.FileHashes[filePath] = hex.EncodeToString(hash)\n\t\t\t\t}\n\t\t\t\tfor name, files := range allFiles {\n\t\t\t\t\tactionID.EmbeddedFiles[name] = files[0].Hash\n\t\t\t\t}\n\t\t\t\tfor i, imported := range pkg.Pkg.Imports() {\n\t\t\t\t\tactionID.Imports[imported.Path()] = importedPackages[i].result\n\t\t\t\t}\n\t\t\t\tbuf, err := json.Marshal(actionID)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err // shouldn't happen\n\t\t\t\t}\n\t\t\t\thash := sha512.Sum512_224(buf)\n\t\t\t\tjob.result = hex.EncodeToString(hash[:])\n\t\t\t\treturn nil\n\t\t\t},\n\t\t}\n\t\tpackageActionIDJobs[pkg.ImportPath] = packageActionIDJob\n\n\t\t// Now create the job to actually build the package. It will exit early\n\t\t// if the package is already compiled.\n\t\tjob := &compileJob{\n\t\t\tdescription:  \"compile package \" + pkg.ImportPath,\n\t\t\tdependencies: []*compileJob{packageActionIDJob},\n\t\t\trun: func(job *compileJob) error {\n\t\t\t\tjob.result = filepath.Join(cacheDir, \"pkg-\"+packageActionIDJob.result+\".bc\")\n\t\t\t\t// Acquire a lock (if supported).\n\t\t\t\tunlock := lock(job.result + \".lock\")\n\t\t\t\tdefer unlock()\n\n\t\t\t\tif _, err := os.Stat(job.result); err == nil {\n\t\t\t\t\t// Already cached, don't recreate this package.\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\n\t\t\t\t// Compile AST to IR. The compiler.CompilePackage function will\n\t\t\t\t// build the SSA as needed.\n\t\t\t\tmod, errs := compiler.CompilePackage(pkg.ImportPath, pkg, program.Package(pkg.Pkg), machine, compilerConfig, config.DumpSSA())\n\t\t\t\tdefer mod.Context().Dispose()\n\t\t\t\tdefer mod.Dispose()\n\t\t\t\tif errs != nil {\n\t\t\t\t\treturn newMultiError(errs, pkg.ImportPath)\n\t\t\t\t}\n\t\t\t\tif err := llvm.VerifyModule(mod, llvm.PrintMessageAction); err != nil {\n\t\t\t\t\treturn errors.New(\"verification error after compiling package \" + pkg.ImportPath)\n\t\t\t\t}\n\n\t\t\t\t// Load bitcode of CGo headers and join the modules together.\n\t\t\t\t// This may seem vulnerable to cache problems, but this is not\n\t\t\t\t// the case: the Go code that was just compiled already tracks\n\t\t\t\t// all C files that are read and hashes them.\n\t\t\t\t// These headers could be compiled in parallel but the benefit\n\t\t\t\t// is so small that it's probably not worth parallelizing.\n\t\t\t\t// Packages are compiled independently anyway.\n\t\t\t\tfor _, cgoHeader := range pkg.CGoHeaders {\n\t\t\t\t\t// Store the header text in a temporary file.\n\t\t\t\t\tf, err := os.CreateTemp(tmpdir, \"cgosnippet-*.c\")\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t\t_, err = f.Write([]byte(cgoHeader))\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t\tf.Close()\n\n\t\t\t\t\t// Compile the code (if there is any) to bitcode.\n\t\t\t\t\tflags := append([]string{\"-c\", \"-emit-llvm\", \"-o\", f.Name() + \".bc\", f.Name()}, pkg.CFlags...)\n\t\t\t\t\tif config.Options.PrintCommands != nil {\n\t\t\t\t\t\tconfig.Options.PrintCommands(\"clang\", flags...)\n\t\t\t\t\t}\n\t\t\t\t\terr = runCCompiler(flags...)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn &commandError{\"failed to build CGo header\", \"\", err}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Load and link the bitcode.\n\t\t\t\t\t// This makes it possible to optimize the functions defined\n\t\t\t\t\t// in the header together with the Go code. In particular,\n\t\t\t\t\t// this allows inlining. It also ensures there is only one\n\t\t\t\t\t// file per package to cache.\n\t\t\t\t\theaderMod, err := mod.Context().ParseBitcodeFile(f.Name() + \".bc\")\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn fmt.Errorf(\"failed to load bitcode file: %w\", err)\n\t\t\t\t\t}\n\t\t\t\t\terr = llvm.LinkModules(mod, headerMod)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn fmt.Errorf(\"failed to link module: %w\", err)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Erase all globals that are part of the undefinedGlobals list.\n\t\t\t\t// This list comes from the -ldflags=\"-X pkg.foo=val\" option.\n\t\t\t\t// Instead of setting the value directly in the AST (which would\n\t\t\t\t// mean the value, which may be a secret, is stored in the build\n\t\t\t\t// cache), the global itself is left external (undefined) and is\n\t\t\t\t// only set at the end of the compilation.\n\t\t\t\tfor _, name := range undefinedGlobals {\n\t\t\t\t\tglobalName := pkg.Pkg.Path() + \".\" + name\n\t\t\t\t\tglobal := mod.NamedGlobal(globalName)\n\t\t\t\t\tif global.IsNil() {\n\t\t\t\t\t\treturn errors.New(\"global not found: \" + globalName)\n\t\t\t\t\t}\n\t\t\t\t\tglobalType := global.GlobalValueType()\n\t\t\t\t\tif globalType.TypeKind() != llvm.StructTypeKind || globalType.StructName() != \"runtime._string\" {\n\t\t\t\t\t\t// Verify this is indeed a string. This is needed so\n\t\t\t\t\t\t// that makeGlobalsModule can just create the right\n\t\t\t\t\t\t// globals of string type without checking.\n\t\t\t\t\t\treturn fmt.Errorf(\"%s: not a string\", globalName)\n\t\t\t\t\t}\n\t\t\t\t\tname := global.Name()\n\t\t\t\t\tnewGlobal := llvm.AddGlobal(mod, globalType, name+\".tmp\")\n\t\t\t\t\tglobal.ReplaceAllUsesWith(newGlobal)\n\t\t\t\t\tglobal.EraseFromParentAsGlobal()\n\t\t\t\t\tnewGlobal.SetName(name)\n\t\t\t\t}\n\n\t\t\t\t// Try to interpret package initializers at compile time.\n\t\t\t\t// It may only be possible to do this partially, in which case\n\t\t\t\t// it is completed after all IR files are linked.\n\t\t\t\tpkgInit := mod.NamedFunction(pkg.Pkg.Path() + \".init\")\n\t\t\t\tif pkgInit.IsNil() {\n\t\t\t\t\tpanic(\"init not found for \" + pkg.Pkg.Path())\n\t\t\t\t}\n\t\t\t\terr := interp.RunFunc(pkgInit, config.Options.InterpTimeout, config.DumpSSA())\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tif err := llvm.VerifyModule(mod, llvm.PrintMessageAction); err != nil {\n\t\t\t\t\treturn errors.New(\"verification error after interpreting \" + pkgInit.Name())\n\t\t\t\t}\n\n\t\t\t\ttransform.OptimizePackage(mod, config)\n\n\t\t\t\t// Serialize the LLVM module as a bitcode file.\n\t\t\t\t// Write to a temporary path that is renamed to the destination\n\t\t\t\t// file to avoid race conditions with other TinyGo invocatiosn\n\t\t\t\t// that might also be compiling this package at the same time.\n\t\t\t\tf, err := os.CreateTemp(filepath.Dir(job.result), filepath.Base(job.result))\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tif runtime.GOOS == \"windows\" {\n\t\t\t\t\t// Work around a problem on Windows.\n\t\t\t\t\t// For some reason, WriteBitcodeToFile causes TinyGo to\n\t\t\t\t\t// exit with the following message:\n\t\t\t\t\t//   LLVM ERROR: IO failure on output stream: Bad file descriptor\n\t\t\t\t\tbuf := llvm.WriteBitcodeToMemoryBuffer(mod)\n\t\t\t\t\tdefer buf.Dispose()\n\t\t\t\t\t_, err = f.Write(buf.Bytes())\n\t\t\t\t} else {\n\t\t\t\t\t// Otherwise, write bitcode directly to the file (probably\n\t\t\t\t\t// faster).\n\t\t\t\t\terr = llvm.WriteBitcodeToFile(mod, f)\n\t\t\t\t}\n\t\t\t\tif err != nil {\n\t\t\t\t\t// WriteBitcodeToFile doesn't produce a useful error on its\n\t\t\t\t\t// own, so create a somewhat useful error message here.\n\t\t\t\t\treturn fmt.Errorf(\"failed to write bitcode for package %s to file %s\", pkg.ImportPath, job.result)\n\t\t\t\t}\n\t\t\t\terr = f.Close()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\treturn os.Rename(f.Name(), job.result)\n\t\t\t},\n\t\t}\n\t\tpackageJobs = append(packageJobs, job)\n\t}\n\n\t// Add job that links and optimizes all packages together.\n\tvar mod llvm.Module\n\tdefer func() {\n\t\tif !mod.IsNil() {\n\t\t\tctx := mod.Context()\n\t\t\tmod.Dispose()\n\t\t\tctx.Dispose()\n\t\t}\n\t}()\n\tvar stackSizeLoads []string\n\tprogramJob := &compileJob{\n\t\tdescription:  \"link+optimize packages (LTO)\",\n\t\tdependencies: packageJobs,\n\t\trun: func(*compileJob) error {\n\t\t\t// Load and link all the bitcode files. This does not yet optimize\n\t\t\t// anything, it only links the bitcode files together.\n\t\t\tctx := llvm.NewContext()\n\t\t\tmod = ctx.NewModule(\"main\")\n\t\t\tfor _, pkgJob := range packageJobs {\n\t\t\t\tpkgMod, err := ctx.ParseBitcodeFile(pkgJob.result)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"failed to load bitcode file: %w\", err)\n\t\t\t\t}\n\t\t\t\terr = llvm.LinkModules(mod, pkgMod)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"failed to link module: %w\", err)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Insert values from -ldflags=\"-X ...\" into the IR.\n\t\t\t// This is a separate module, so that the \"runtime._string\" type\n\t\t\t// doesn't need to match precisely. LLVM tends to rename that type\n\t\t\t// sometimes, leading to errors. But linking in a separate module\n\t\t\t// works fine. See:\n\t\t\t// https://github.com/tinygo-org/tinygo/issues/4810\n\t\t\tglobalsMod := makeGlobalsModule(ctx, globalValues, machine)\n\t\t\tllvm.LinkModules(mod, globalsMod)\n\n\t\t\t// Create runtime.initAll function that calls the runtime\n\t\t\t// initializer of each package.\n\t\t\tllvmInitFn := mod.NamedFunction(\"runtime.initAll\")\n\t\t\tllvmInitFn.SetLinkage(llvm.InternalLinkage)\n\t\t\tllvmInitFn.SetUnnamedAddr(true)\n\t\t\ttransform.AddStandardAttributes(llvmInitFn, config)\n\t\t\tllvmInitFn.Param(0).SetName(\"context\")\n\t\t\tblock := mod.Context().AddBasicBlock(llvmInitFn, \"entry\")\n\t\t\tirbuilder := mod.Context().NewBuilder()\n\t\t\tdefer irbuilder.Dispose()\n\t\t\tirbuilder.SetInsertPointAtEnd(block)\n\t\t\tptrType := llvm.PointerType(mod.Context().Int8Type(), 0)\n\t\t\tfor _, pkg := range lprogram.Sorted() {\n\t\t\t\tpkgInit := mod.NamedFunction(pkg.Pkg.Path() + \".init\")\n\t\t\t\tif pkgInit.IsNil() {\n\t\t\t\t\tpanic(\"init not found for \" + pkg.Pkg.Path())\n\t\t\t\t}\n\t\t\t\tirbuilder.CreateCall(pkgInit.GlobalValueType(), pkgInit, []llvm.Value{llvm.Undef(ptrType)}, \"\")\n\t\t\t}\n\t\t\tirbuilder.CreateRetVoid()\n\n\t\t\t// After linking, functions should (as far as possible) be set to\n\t\t\t// private linkage or internal linkage. The compiler package marks\n\t\t\t// non-exported functions by setting the visibility to hidden or\n\t\t\t// (for thunks) to linkonce_odr linkage. Change the linkage here to\n\t\t\t// internal to benefit much more from interprocedural optimizations.\n\t\t\tfor fn := mod.FirstFunction(); !fn.IsNil(); fn = llvm.NextFunction(fn) {\n\t\t\t\tif fn.Visibility() == llvm.HiddenVisibility {\n\t\t\t\t\tfn.SetVisibility(llvm.DefaultVisibility)\n\t\t\t\t\tfn.SetLinkage(llvm.InternalLinkage)\n\t\t\t\t} else if fn.Linkage() == llvm.LinkOnceODRLinkage {\n\t\t\t\t\tfn.SetLinkage(llvm.InternalLinkage)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Do the same for globals.\n\t\t\tfor global := mod.FirstGlobal(); !global.IsNil(); global = llvm.NextGlobal(global) {\n\t\t\t\tif global.Visibility() == llvm.HiddenVisibility {\n\t\t\t\t\tglobal.SetVisibility(llvm.DefaultVisibility)\n\t\t\t\t\tglobal.SetLinkage(llvm.InternalLinkage)\n\t\t\t\t} else if global.Linkage() == llvm.LinkOnceODRLinkage {\n\t\t\t\t\tglobal.SetLinkage(llvm.InternalLinkage)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif config.Options.PrintIR {\n\t\t\t\tfmt.Println(\"; Generated LLVM IR:\")\n\t\t\t\tfmt.Println(mod.String())\n\t\t\t}\n\n\t\t\t// Run all optimization passes, which are much more effective now\n\t\t\t// that the optimizer can see the whole program at once.\n\t\t\terr := optimizeProgram(mod, config)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\t// Make sure stack sizes are loaded from a separate section so they can be\n\t\t\t// modified after linking.\n\t\t\tif config.AutomaticStackSize() {\n\t\t\t\tstackSizeLoads = transform.CreateStackSizeLoads(mod, config)\n\t\t\t}\n\t\t\treturn nil\n\t\t},\n\t}\n\n\t// Create the output directory, if needed\n\tif err := os.MkdirAll(filepath.Dir(outpath), 0777); err != nil {\n\t\treturn result, err\n\t}\n\n\t// Check whether we only need to create an object file.\n\t// If so, we don't need to link anything and will be finished quickly.\n\toutext := filepath.Ext(outpath)\n\tif outext == \".o\" || outext == \".bc\" || outext == \".ll\" {\n\t\t// Run jobs to produce the LLVM module.\n\t\terr := runJobs(programJob, config.Options.Semaphore)\n\t\tif err != nil {\n\t\t\treturn result, err\n\t\t}\n\t\t// Generate output.\n\t\tswitch outext {\n\t\tcase \".o\":\n\t\t\tllvmBuf, err := machine.EmitToMemoryBuffer(mod, llvm.ObjectFile)\n\t\t\tif err != nil {\n\t\t\t\treturn result, err\n\t\t\t}\n\t\t\tdefer llvmBuf.Dispose()\n\t\t\treturn result, os.WriteFile(outpath, llvmBuf.Bytes(), 0666)\n\t\tcase \".bc\":\n\t\t\tbuf := llvm.WriteThinLTOBitcodeToMemoryBuffer(mod)\n\t\t\tdefer buf.Dispose()\n\t\t\treturn result, os.WriteFile(outpath, buf.Bytes(), 0666)\n\t\tcase \".ll\":\n\t\t\tdata := []byte(mod.String())\n\t\t\treturn result, os.WriteFile(outpath, data, 0666)\n\t\tdefault:\n\t\t\tpanic(\"unreachable\")\n\t\t}\n\t}\n\n\t// Act as a compiler driver, as we need to produce a complete executable.\n\t// First add all jobs necessary to build this object file, then afterwards\n\t// run all jobs in parallel as far as possible.\n\n\t// Add job to write the output object file.\n\tobjfile := filepath.Join(tmpdir, \"main.o\")\n\toutputObjectFileJob := &compileJob{\n\t\tdescription:  \"generate output file\",\n\t\tdependencies: []*compileJob{programJob},\n\t\tresult:       objfile,\n\t\trun: func(*compileJob) error {\n\t\t\tllvmBuf := llvm.WriteThinLTOBitcodeToMemoryBuffer(mod)\n\t\t\tdefer llvmBuf.Dispose()\n\t\t\treturn os.WriteFile(objfile, llvmBuf.Bytes(), 0666)\n\t\t},\n\t}\n\n\t// Prepare link command.\n\tlinkerDependencies := []*compileJob{outputObjectFileJob}\n\tresult.Executable = filepath.Join(tmpdir, \"main\")\n\tif config.GOOS() == \"windows\" {\n\t\tresult.Executable += \".exe\"\n\t}\n\tresult.Binary = result.Executable // final file\n\tldflags := append(config.LDFlags(), \"-o\", result.Executable)\n\n\tif config.Options.BuildMode == \"c-shared\" {\n\t\tif !strings.HasPrefix(config.Triple(), \"wasm32-\") {\n\t\t\treturn result, fmt.Errorf(\"buildmode c-shared is only supported on wasm at the moment\")\n\t\t}\n\t\tldflags = append(ldflags, \"--no-entry\")\n\t}\n\n\tif config.Options.BuildMode == \"wasi-legacy\" {\n\t\tif !strings.HasPrefix(config.Triple(), \"wasm32-\") {\n\t\t\treturn result, fmt.Errorf(\"buildmode wasi-legacy is only supported on wasm\")\n\t\t}\n\n\t\tif config.Options.Scheduler != \"none\" {\n\t\t\treturn result, fmt.Errorf(\"buildmode wasi-legacy only supports scheduler=none\")\n\t\t}\n\t}\n\n\t// Add compiler-rt dependency if needed. Usually this is a simple load from\n\t// a cache.\n\tif config.Target.RTLib == \"compiler-rt\" {\n\t\tjob, unlock, err := libCompilerRT.load(config, tmpdir)\n\t\tif err != nil {\n\t\t\treturn result, err\n\t\t}\n\t\tdefer unlock()\n\t\tlinkerDependencies = append(linkerDependencies, job)\n\t}\n\n\t// The Boehm collector is stored in a separate C library.\n\tif config.GC() == \"boehm\" {\n\t\tjob, unlock, err := BoehmGC.load(config, tmpdir)\n\t\tif err != nil {\n\t\t\treturn BuildResult{}, err\n\t\t}\n\t\tdefer unlock()\n\t\tlinkerDependencies = append(linkerDependencies, job)\n\t}\n\n\t// Add jobs to compile extra files. These files are in C or assembly and\n\t// contain things like the interrupt vector table and low level operations\n\t// such as stack switching.\n\tfor _, path := range config.ExtraFiles() {\n\t\tabspath := filepath.Join(root, path)\n\t\tjob := &compileJob{\n\t\t\tdescription: \"compile extra file \" + path,\n\t\t\trun: func(job *compileJob) error {\n\t\t\t\tresult, err := compileAndCacheCFile(abspath, tmpdir, config.CFlags(false), config.Options.PrintCommands)\n\t\t\t\tjob.result = result\n\t\t\t\treturn err\n\t\t\t},\n\t\t}\n\t\tlinkerDependencies = append(linkerDependencies, job)\n\t}\n\n\t// Add jobs to compile C files in all packages. This is part of CGo.\n\t// TODO: do this as part of building the package to be able to link the\n\t// bitcode files together.\n\tfor _, pkg := range lprogram.Sorted() {\n\t\tpkg := pkg\n\t\tfor _, filename := range pkg.CFiles {\n\t\t\tabspath := filepath.Join(pkg.OriginalDir(), filename)\n\t\t\tjob := &compileJob{\n\t\t\t\tdescription: \"compile CGo file \" + abspath,\n\t\t\t\trun: func(job *compileJob) error {\n\t\t\t\t\tresult, err := compileAndCacheCFile(abspath, tmpdir, pkg.CFlags, config.Options.PrintCommands)\n\t\t\t\t\tjob.result = result\n\t\t\t\t\treturn err\n\t\t\t\t},\n\t\t\t}\n\t\t\tlinkerDependencies = append(linkerDependencies, job)\n\t\t}\n\t}\n\n\t// Linker flags from CGo lines:\n\t//     #cgo LDFLAGS: foo\n\tif len(lprogram.LDFlags) > 0 {\n\t\tldflags = append(ldflags, lprogram.LDFlags...)\n\t}\n\n\t// Add libc dependencies, if they exist.\n\tlinkerDependencies = append(linkerDependencies, libcDependencies...)\n\n\t// Add embedded files.\n\tlinkerDependencies = append(linkerDependencies, embedFileObjects...)\n\n\t// Determine whether the compilation configuration would result in debug\n\t// (DWARF) information in the object files.\n\tvar hasDebug = true\n\tif config.GOOS() == \"darwin\" {\n\t\t// Debug information isn't stored in the binary itself on MacOS but\n\t\t// is left in the object files by default. The binary does store the\n\t\t// path to these object files though.\n\t\thasDebug = false\n\t}\n\n\t// Strip debug information with -no-debug.\n\tif hasDebug && !config.Debug() {\n\t\tif config.Target.Linker == \"wasm-ld\" {\n\t\t\t// Don't just strip debug information, also compress relocations\n\t\t\t// while we're at it. Relocations can only be compressed when debug\n\t\t\t// information is stripped.\n\t\t\tldflags = append(ldflags, \"--strip-debug\", \"--compress-relocations\")\n\t\t} else if config.Target.Linker == \"ld.lld\" {\n\t\t\t// ld.lld is also used on Linux.\n\t\t\tldflags = append(ldflags, \"--strip-debug\")\n\t\t} else {\n\t\t\t// Other linkers may have different flags.\n\t\t\treturn result, errors.New(\"cannot remove debug information: unknown linker: \" + config.Target.Linker)\n\t\t}\n\t}\n\n\t// Create a linker job, which links all object files together and does some\n\t// extra stuff that can only be done after linking.\n\tlinkJob := &compileJob{\n\t\tdescription:  \"link\",\n\t\tdependencies: linkerDependencies,\n\t\trun: func(job *compileJob) error {\n\t\t\tfor _, dependency := range job.dependencies {\n\t\t\t\tif dependency.result == \"\" {\n\t\t\t\t\treturn errors.New(\"dependency without result: \" + dependency.description)\n\t\t\t\t}\n\t\t\t\tldflags = append(ldflags, dependency.result)\n\t\t\t}\n\t\t\tldflags = append(ldflags, \"-mllvm\", \"-mcpu=\"+config.CPU())\n\t\t\tldflags = append(ldflags, \"-mllvm\", \"-mattr=\"+config.Features()) // needed for MIPS softfloat\n\t\t\tif config.GOOS() == \"windows\" {\n\t\t\t\t// Options for the MinGW wrapper for the lld COFF linker.\n\t\t\t\tldflags = append(ldflags,\n\t\t\t\t\t\"-Xlink=/opt:lldlto=\"+strconv.Itoa(speedLevel),\n\t\t\t\t\t\"--thinlto-cache-dir=\"+filepath.Join(cacheDir, \"thinlto\"))\n\t\t\t} else if config.GOOS() == \"darwin\" {\n\t\t\t\t// Options for the ld64-compatible lld linker.\n\t\t\t\tldflags = append(ldflags,\n\t\t\t\t\t\"--lto-O\"+strconv.Itoa(speedLevel),\n\t\t\t\t\t\"-cache_path_lto\", filepath.Join(cacheDir, \"thinlto\"))\n\t\t\t} else {\n\t\t\t\t// Options for the ELF linker.\n\t\t\t\tldflags = append(ldflags,\n\t\t\t\t\t\"--lto-O\"+strconv.Itoa(speedLevel),\n\t\t\t\t\t\"--thinlto-cache-dir=\"+filepath.Join(cacheDir, \"thinlto\"),\n\t\t\t\t)\n\t\t\t}\n\t\t\tif config.CodeModel() != \"default\" {\n\t\t\t\tldflags = append(ldflags,\n\t\t\t\t\t\"-mllvm\", \"-code-model=\"+config.CodeModel())\n\t\t\t}\n\t\t\tif sizeLevel >= 2 {\n\t\t\t\t// Workaround with roughly the same effect as\n\t\t\t\t// https://reviews.llvm.org/D119342.\n\t\t\t\t// Can hopefully be removed in LLVM 19.\n\t\t\t\tldflags = append(ldflags,\n\t\t\t\t\t\"-mllvm\", \"--rotation-max-header-size=0\")\n\t\t\t}\n\t\t\tif config.Options.PrintCommands != nil {\n\t\t\t\tconfig.Options.PrintCommands(config.Target.Linker, ldflags...)\n\t\t\t}\n\t\t\terr = link(config.Target.Linker, ldflags...)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tvar calculatedStacks []string\n\t\t\tvar stackSizes map[string]functionStackSize\n\t\t\tif config.Options.PrintStacks || config.AutomaticStackSize() {\n\t\t\t\t// Try to determine stack sizes at compile time.\n\t\t\t\t// Don't do this by default as it usually doesn't work on\n\t\t\t\t// unsupported architectures.\n\t\t\t\tcalculatedStacks, stackSizes, err = determineStackSizes(mod, result.Executable)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Apply ELF patches\n\t\t\tif config.AutomaticStackSize() {\n\t\t\t\t// Modify the .tinygo_stacksizes section that contains a stack size\n\t\t\t\t// for each goroutine.\n\t\t\t\terr = modifyStackSizes(result.Executable, stackSizeLoads, stackSizes)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"could not modify stack sizes: %w\", err)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Apply patches of bootloader in the order they appear.\n\t\t\tif len(config.Target.BootPatches) > 0 {\n\t\t\t\terr = applyPatches(result.Executable, config.Target.BootPatches)\n\t\t\t}\n\n\t\t\tif config.RP2040BootPatch() {\n\t\t\t\t// Patch the second stage bootloader CRC into the .boot2 section\n\t\t\t\terr = patchRP2040BootCRC(result.Executable)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"could not patch RP2040 second stage boot loader: %w\", err)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Run wasm-opt for wasm binaries\n\t\t\tif arch := strings.Split(config.Triple(), \"-\")[0]; arch == \"wasm32\" {\n\t\t\t\toptLevel, _, _ := config.OptLevel()\n\t\t\t\topt := \"-\" + optLevel\n\n\t\t\t\tvar args []string\n\n\t\t\t\tif config.Scheduler() == \"asyncify\" {\n\t\t\t\t\targs = append(args, \"--asyncify\")\n\t\t\t\t}\n\n\t\t\t\tinputFile := result.Binary\n\t\t\t\tresult.Binary = result.Executable + \".wasmopt\"\n\t\t\t\targs = append(args,\n\t\t\t\t\topt,\n\t\t\t\t\t\"-g\",\n\t\t\t\t\tinputFile,\n\t\t\t\t\t\"--output\", result.Binary,\n\t\t\t\t)\n\n\t\t\t\twasmopt := goenv.Get(\"WASMOPT\")\n\t\t\t\tif config.Options.PrintCommands != nil {\n\t\t\t\t\tconfig.Options.PrintCommands(wasmopt, args...)\n\t\t\t\t}\n\t\t\t\tcmd := exec.Command(wasmopt, args...)\n\t\t\t\tcmd.Stdout = os.Stdout\n\t\t\t\tcmd.Stderr = os.Stderr\n\n\t\t\t\terr := cmd.Run()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"wasm-opt failed: %w\", err)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Run wasm-tools for component-model binaries\n\t\t\twitPackage := strings.ReplaceAll(config.Target.WITPackage, \"{root}\", goenv.Get(\"TINYGOROOT\"))\n\t\t\tif config.Options.WITPackage != \"\" {\n\t\t\t\twitPackage = config.Options.WITPackage\n\t\t\t}\n\t\t\twitWorld := config.Target.WITWorld\n\t\t\tif config.Options.WITWorld != \"\" {\n\t\t\t\twitWorld = config.Options.WITWorld\n\t\t\t}\n\t\t\tif witPackage != \"\" && witWorld != \"\" {\n\n\t\t\t\t// wasm-tools component embed -w wasi:cli/command\n\t\t\t\t// \t\t$$(tinygo env TINYGOROOT)/lib/wasi-cli/wit/ main.wasm -o embedded.wasm\n\t\t\t\tcomponentEmbedInputFile := result.Binary\n\t\t\t\tresult.Binary = result.Executable + \".wasm-component-embed\"\n\t\t\t\targs := []string{\n\t\t\t\t\t\"component\",\n\t\t\t\t\t\"embed\",\n\t\t\t\t\t\"-w\", witWorld,\n\t\t\t\t\twitPackage,\n\t\t\t\t\tcomponentEmbedInputFile,\n\t\t\t\t\t\"-o\", result.Binary,\n\t\t\t\t}\n\n\t\t\t\twasmtools := goenv.Get(\"WASMTOOLS\")\n\t\t\t\tif config.Options.PrintCommands != nil {\n\t\t\t\t\tconfig.Options.PrintCommands(wasmtools, args...)\n\t\t\t\t}\n\t\t\t\tcmd := exec.Command(wasmtools, args...)\n\t\t\t\tcmd.Stdout = os.Stdout\n\t\t\t\tcmd.Stderr = os.Stderr\n\n\t\t\t\terr := cmd.Run()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"`wasm-tools component embed` failed: %w\", err)\n\t\t\t\t}\n\n\t\t\t\t// wasm-tools component new embedded.wasm -o component.wasm\n\t\t\t\tcomponentNewInputFile := result.Binary\n\t\t\t\tresult.Binary = result.Executable + \".wasm-component-new\"\n\t\t\t\targs = []string{\n\t\t\t\t\t\"component\",\n\t\t\t\t\t\"new\",\n\t\t\t\t\tcomponentNewInputFile,\n\t\t\t\t\t\"-o\", result.Binary,\n\t\t\t\t}\n\n\t\t\t\tif config.Options.PrintCommands != nil {\n\t\t\t\t\tconfig.Options.PrintCommands(wasmtools, args...)\n\t\t\t\t}\n\t\t\t\tcmd = exec.Command(wasmtools, args...)\n\t\t\t\tcmd.Stdout = os.Stdout\n\t\t\t\tcmd.Stderr = os.Stderr\n\n\t\t\t\terr = cmd.Run()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"`wasm-tools component new` failed: %w\", err)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Print code size if requested.\n\t\t\tif config.Options.PrintSizes != \"\" {\n\t\t\t\tsizes, err := loadProgramSize(result.Executable, result.PackagePathMap)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tswitch config.Options.PrintSizes {\n\t\t\t\tcase \"short\":\n\t\t\t\t\tfmt.Printf(\"   code    data     bss |   flash     ram\\n\")\n\t\t\t\t\tfmt.Printf(\"%7d %7d %7d | %7d %7d\\n\", sizes.Code+sizes.ROData, sizes.Data, sizes.BSS, sizes.Flash(), sizes.RAM())\n\t\t\t\tcase \"full\":\n\t\t\t\t\tif !config.Debug() {\n\t\t\t\t\t\tfmt.Println(\"warning: data incomplete, remove the -no-debug flag for more detail\")\n\t\t\t\t\t}\n\t\t\t\t\tfmt.Printf(\"   code  rodata    data     bss |   flash     ram | package\\n\")\n\t\t\t\t\tfmt.Printf(\"------------------------------- | --------------- | -------\\n\")\n\t\t\t\t\tfor _, name := range sizes.sortedPackageNames() {\n\t\t\t\t\t\tpkgSize := sizes.Packages[name]\n\t\t\t\t\t\tfmt.Printf(\"%7d %7d %7d %7d | %7d %7d | %s\\n\", pkgSize.Code, pkgSize.ROData, pkgSize.Data, pkgSize.BSS, pkgSize.Flash(), pkgSize.RAM(), name)\n\t\t\t\t\t}\n\t\t\t\t\tfmt.Printf(\"------------------------------- | --------------- | -------\\n\")\n\t\t\t\t\tfmt.Printf(\"%7d %7d %7d %7d | %7d %7d | total\\n\", sizes.Code, sizes.ROData, sizes.Data, sizes.BSS, sizes.Code+sizes.ROData+sizes.Data, sizes.Data+sizes.BSS)\n\t\t\t\tcase \"html\":\n\t\t\t\t\tconst filename = \"size-report.html\"\n\t\t\t\t\terr := writeSizeReport(sizes, filename, pkgName)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t\tfmt.Println(\"Wrote size report to\", filename)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Print goroutine stack sizes, as far as possible.\n\t\t\tif config.Options.PrintStacks {\n\t\t\t\tprintStacks(calculatedStacks, stackSizes)\n\t\t\t}\n\n\t\t\treturn nil\n\t\t},\n\t}\n\n\t// Run all jobs to compile and link the program.\n\t// Do this now (instead of after elf-to-hex and similar conversions) as it\n\t// is simpler and cannot be parallelized.\n\terr = runJobs(linkJob, config.Options.Semaphore)\n\tif err != nil {\n\t\treturn result, err\n\t}\n\n\t// Get an Intel .hex file or .bin file from the .elf file.\n\toutputBinaryFormat := config.BinaryFormat(outext)\n\tswitch outputBinaryFormat {\n\tcase \"elf\":\n\t\t// do nothing, file is already in ELF format\n\tcase \"hex\", \"bin\":\n\t\t// Extract raw binary, either encoding it as a hex file or as a raw\n\t\t// firmware file.\n\t\tresult.Binary = filepath.Join(tmpdir, \"main\"+outext)\n\t\terr := objcopy(result.Executable, result.Binary, outputBinaryFormat)\n\t\tif err != nil {\n\t\t\treturn result, err\n\t\t}\n\tcase \"uf2\":\n\t\t// Get UF2 from the .elf file.\n\t\tresult.Binary = filepath.Join(tmpdir, \"main\"+outext)\n\t\terr := convertELFFileToUF2File(result.Executable, result.Binary, config.Target.UF2FamilyID)\n\t\tif err != nil {\n\t\t\treturn result, err\n\t\t}\n\tcase \"esp32\", \"esp32-img\", \"esp32c3\", \"esp32s3\", \"esp8266\":\n\t\t// Special format for the ESP family of chips (parsed by the ROM\n\t\t// bootloader).\n\t\tresult.Binary = filepath.Join(tmpdir, \"main\"+outext)\n\t\terr := makeESPFirmwareImage(result.Executable, result.Binary, outputBinaryFormat)\n\t\tif err != nil {\n\t\t\treturn result, err\n\t\t}\n\tcase \"nrf-dfu\":\n\t\t// special format for nrfutil for Nordic chips\n\t\tresult.Binary = filepath.Join(tmpdir, \"main\"+outext)\n\t\terr = makeDFUFirmwareImage(config.Options, result.Executable, result.Binary)\n\t\tif err != nil {\n\t\t\treturn result, err\n\t\t}\n\tdefault:\n\t\treturn result, fmt.Errorf(\"unknown output binary format: %s\", outputBinaryFormat)\n\t}\n\n\treturn result, nil\n}\n\n// createEmbedObjectFile creates a new object file with the given contents, for\n// the embed package.\nfunc createEmbedObjectFile(data, hexSum, sourceFile, sourceDir, tmpdir string, compilerConfig *compiler.Config) (string, error) {\n\t// TODO: this works for small files, but can be a problem for larger files.\n\t// For larger files, it seems more appropriate to generate the object file\n\t// manually without going through LLVM.\n\t// On the other hand, generating DWARF like we do here can be difficult\n\t// without assistance from LLVM.\n\n\t// Create new LLVM module just for this file.\n\tctx := llvm.NewContext()\n\tdefer ctx.Dispose()\n\tmod := ctx.NewModule(\"data\")\n\tdefer mod.Dispose()\n\n\t// Create data global.\n\tvalue := ctx.ConstString(data, false)\n\tglobalName := \"embed/file_\" + hexSum\n\tglobal := llvm.AddGlobal(mod, value.Type(), globalName)\n\tglobal.SetInitializer(value)\n\tglobal.SetLinkage(llvm.LinkOnceODRLinkage)\n\tglobal.SetGlobalConstant(true)\n\tglobal.SetUnnamedAddr(true)\n\tglobal.SetAlignment(1)\n\tif compilerConfig.GOOS != \"darwin\" {\n\t\t// MachO doesn't support COMDATs, while COFF requires it (to avoid\n\t\t// \"duplicate symbol\" errors). ELF works either way.\n\t\t// Therefore, only use a COMDAT on non-MachO systems (aka non-MacOS).\n\t\tglobal.SetComdat(mod.Comdat(globalName))\n\t}\n\n\t// Add DWARF debug information to this global, so that it is\n\t// correctly counted when compiling with the -size= flag.\n\tdibuilder := llvm.NewDIBuilder(mod)\n\tdibuilder.CreateCompileUnit(llvm.DICompileUnit{\n\t\tLanguage:  0xb, // DW_LANG_C99 (0xc, off-by-one?)\n\t\tFile:      sourceFile,\n\t\tDir:       sourceDir,\n\t\tProducer:  \"TinyGo\",\n\t\tOptimized: false,\n\t})\n\tditype := dibuilder.CreateArrayType(llvm.DIArrayType{\n\t\tSizeInBits:  uint64(len(data)) * 8,\n\t\tAlignInBits: 8,\n\t\tElementType: dibuilder.CreateBasicType(llvm.DIBasicType{\n\t\t\tName:       \"byte\",\n\t\t\tSizeInBits: 8,\n\t\t\tEncoding:   llvm.DW_ATE_unsigned_char,\n\t\t}),\n\t\tSubscripts: []llvm.DISubrange{\n\t\t\t{\n\t\t\t\tLo:    0,\n\t\t\t\tCount: int64(len(data)),\n\t\t\t},\n\t\t},\n\t})\n\tdifile := dibuilder.CreateFile(sourceFile, sourceDir)\n\tdiglobalexpr := dibuilder.CreateGlobalVariableExpression(difile, llvm.DIGlobalVariableExpression{\n\t\tName:        globalName,\n\t\tFile:        difile,\n\t\tLine:        1,\n\t\tType:        ditype,\n\t\tExpr:        dibuilder.CreateExpression(nil),\n\t\tAlignInBits: 8,\n\t})\n\tglobal.AddMetadata(0, diglobalexpr)\n\tmod.AddNamedMetadataOperand(\"llvm.module.flags\",\n\t\tctx.MDNode([]llvm.Metadata{\n\t\t\tllvm.ConstInt(ctx.Int32Type(), 2, false).ConstantAsMetadata(), // Warning on mismatch\n\t\t\tctx.MDString(\"Debug Info Version\"),\n\t\t\tllvm.ConstInt(ctx.Int32Type(), 3, false).ConstantAsMetadata(),\n\t\t}),\n\t)\n\tmod.AddNamedMetadataOperand(\"llvm.module.flags\",\n\t\tctx.MDNode([]llvm.Metadata{\n\t\t\tllvm.ConstInt(ctx.Int32Type(), 7, false).ConstantAsMetadata(), // Max on mismatch\n\t\t\tctx.MDString(\"Dwarf Version\"),\n\t\t\tllvm.ConstInt(ctx.Int32Type(), 4, false).ConstantAsMetadata(),\n\t\t}),\n\t)\n\tdibuilder.Finalize()\n\tdibuilder.Destroy()\n\n\t// Write this LLVM module out as an object file.\n\tmachine, err := compiler.NewTargetMachine(compilerConfig)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tdefer machine.Dispose()\n\toutfile, err := os.CreateTemp(tmpdir, \"embed-\"+hexSum+\"-*.o\")\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tdefer outfile.Close()\n\tbuf, err := machine.EmitToMemoryBuffer(mod, llvm.ObjectFile)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tdefer buf.Dispose()\n\t_, err = outfile.Write(buf.Bytes())\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn outfile.Name(), outfile.Close()\n}\n\n// optimizeProgram runs a series of optimizations and transformations that are\n// needed to convert a program to its final form. Some transformations are not\n// optional and must be run as the compiler expects them to run.\nfunc optimizeProgram(mod llvm.Module, config *compileopts.Config) error {\n\terr := interp.Run(mod, config.Options.InterpTimeout, config.DumpSSA())\n\tif err != nil {\n\t\treturn err\n\t}\n\tif config.VerifyIR() {\n\t\t// Only verify if we really need it.\n\t\t// The IR has already been verified before writing the bitcode to disk\n\t\t// and the interp function above doesn't need to do a lot as most of the\n\t\t// package initializers have already run. Additionally, verifying this\n\t\t// linked IR is _expensive_ because dead code hasn't been removed yet,\n\t\t// easily costing a few hundred milliseconds. Therefore, only do it when\n\t\t// specifically requested.\n\t\tif err := llvm.VerifyModule(mod, llvm.PrintMessageAction); err != nil {\n\t\t\treturn errors.New(\"verification error after interpreting runtime.initAll\")\n\t\t}\n\t}\n\n\t// Run most of the whole-program optimizations (including the whole\n\t// O0/O1/O2/Os/Oz optimization pipeline).\n\terrs := transform.Optimize(mod, config)\n\tif len(errs) > 0 {\n\t\treturn newMultiError(errs, \"\")\n\t}\n\tif err := llvm.VerifyModule(mod, llvm.PrintMessageAction); err != nil {\n\t\treturn errors.New(\"verification failure after LLVM optimization passes\")\n\t}\n\n\treturn nil\n}\n\nfunc makeGlobalsModule(ctx llvm.Context, globals map[string]map[string]string, machine llvm.TargetMachine) llvm.Module {\n\tmod := ctx.NewModule(\"cmdline-globals\")\n\ttargetData := machine.CreateTargetData()\n\tdefer targetData.Dispose()\n\tmod.SetDataLayout(targetData.String())\n\n\tstringType := ctx.StructCreateNamed(\"runtime._string\")\n\tuintptrType := ctx.IntType(targetData.PointerSize() * 8)\n\tstringType.StructSetBody([]llvm.Type{\n\t\tllvm.PointerType(ctx.Int8Type(), 0),\n\t\tuintptrType,\n\t}, false)\n\n\tvar pkgPaths []string\n\tfor pkgPath := range globals {\n\t\tpkgPaths = append(pkgPaths, pkgPath)\n\t}\n\tsort.Strings(pkgPaths)\n\tfor _, pkgPath := range pkgPaths {\n\t\tpkg := globals[pkgPath]\n\t\tvar names []string\n\t\tfor name := range pkg {\n\t\t\tnames = append(names, name)\n\t\t}\n\t\tsort.Strings(names)\n\t\tfor _, name := range names {\n\t\t\tvalue := pkg[name]\n\t\t\tglobalName := pkgPath + \".\" + name\n\n\t\t\t// Create a buffer for the string contents.\n\t\t\tbufInitializer := mod.Context().ConstString(value, false)\n\t\t\tbuf := llvm.AddGlobal(mod, bufInitializer.Type(), \".string\")\n\t\t\tbuf.SetInitializer(bufInitializer)\n\t\t\tbuf.SetAlignment(1)\n\t\t\tbuf.SetUnnamedAddr(true)\n\t\t\tbuf.SetLinkage(llvm.PrivateLinkage)\n\n\t\t\t// Create the string value, which is a {ptr, len} pair.\n\t\t\tlength := llvm.ConstInt(uintptrType, uint64(len(value)), false)\n\t\t\tinitializer := llvm.ConstNamedStruct(stringType, []llvm.Value{\n\t\t\t\tbuf,\n\t\t\t\tlength,\n\t\t\t})\n\n\t\t\t// Create the string global.\n\t\t\tglobal := llvm.AddGlobal(mod, stringType, globalName)\n\t\t\tglobal.SetInitializer(initializer)\n\t\t\tglobal.SetAlignment(targetData.PrefTypeAlignment(stringType))\n\t\t}\n\t}\n\n\treturn mod\n}\n\n// functionStackSizes keeps stack size information about a single function\n// (usually a goroutine).\ntype functionStackSize struct {\n\thumanName        string\n\tstackSize        uint64\n\tstackSizeType    stacksize.SizeType\n\tmissingStackSize *stacksize.CallNode\n}\n\n// determineStackSizes tries to determine the stack sizes of all started\n// goroutines and of the reset vector. The LLVM module is necessary to find\n// functions that call a function pointer.\nfunc determineStackSizes(mod llvm.Module, executable string) ([]string, map[string]functionStackSize, error) {\n\tvar callsIndirectFunction []string\n\tgowrappers := []string{}\n\tgowrapperNames := make(map[string]string)\n\tfor fn := mod.FirstFunction(); !fn.IsNil(); fn = llvm.NextFunction(fn) {\n\t\t// Determine which functions call a function pointer.\n\t\tfor bb := fn.FirstBasicBlock(); !bb.IsNil(); bb = llvm.NextBasicBlock(bb) {\n\t\t\tfor inst := bb.FirstInstruction(); !inst.IsNil(); inst = llvm.NextInstruction(inst) {\n\t\t\t\tif inst.IsACallInst().IsNil() {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif callee := inst.CalledValue(); callee.IsAFunction().IsNil() && callee.IsAInlineAsm().IsNil() {\n\t\t\t\t\tcallsIndirectFunction = append(callsIndirectFunction, fn.Name())\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Get a list of \"go wrappers\", small wrapper functions that decode\n\t\t// parameters when starting a new goroutine.\n\t\tattr := fn.GetStringAttributeAtIndex(-1, \"tinygo-gowrapper\")\n\t\tif !attr.IsNil() {\n\t\t\tgowrappers = append(gowrappers, fn.Name())\n\t\t\tgowrapperNames[fn.Name()] = attr.GetStringValue()\n\t\t}\n\t}\n\tsort.Strings(gowrappers)\n\n\t// Load the ELF binary.\n\tf, err := elf.Open(executable)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"could not load executable for stack size analysis: %w\", err)\n\t}\n\tdefer f.Close()\n\n\t// Determine the frame size of each function (if available) and the callgraph.\n\tfunctions, err := stacksize.CallGraph(f, callsIndirectFunction)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"could not parse executable for stack size analysis: %w\", err)\n\t}\n\n\t// Goroutines need to be started and finished and take up some stack space\n\t// that way. This can be measured by measuring the stack size of\n\t// tinygo_startTask.\n\tif numFuncs := len(functions[\"tinygo_startTask\"]); numFuncs != 1 {\n\t\treturn nil, nil, fmt.Errorf(\"expected exactly one definition of tinygo_startTask, got %d\", numFuncs)\n\t}\n\tbaseStackSize, baseStackSizeType, baseStackSizeFailedAt := functions[\"tinygo_startTask\"][0].StackSize()\n\n\tsizes := make(map[string]functionStackSize)\n\n\t// Add the reset handler function, for convenience. The reset handler runs\n\t// startup code and the scheduler. The listed stack size is not the full\n\t// stack size: interrupts are not counted.\n\tvar resetFunction string\n\tswitch f.Machine {\n\tcase elf.EM_ARM:\n\t\t// Note: all interrupts happen on this stack so the real size is bigger.\n\t\tresetFunction = \"Reset_Handler\"\n\t}\n\tif resetFunction != \"\" {\n\t\tfuncs := functions[resetFunction]\n\t\tif len(funcs) != 1 {\n\t\t\treturn nil, nil, fmt.Errorf(\"expected exactly one definition of %s in the callgraph, found %d\", resetFunction, len(funcs))\n\t\t}\n\t\tstackSize, stackSizeType, missingStackSize := funcs[0].StackSize()\n\t\tsizes[resetFunction] = functionStackSize{\n\t\t\tstackSize:        stackSize,\n\t\t\tstackSizeType:    stackSizeType,\n\t\t\tmissingStackSize: missingStackSize,\n\t\t\thumanName:        resetFunction,\n\t\t}\n\t}\n\n\t// Add all goroutine wrapper functions.\n\tfor _, name := range gowrappers {\n\t\tfuncs := functions[name]\n\t\tif len(funcs) != 1 {\n\t\t\treturn nil, nil, fmt.Errorf(\"expected exactly one definition of %s in the callgraph, found %d\", name, len(funcs))\n\t\t}\n\t\thumanName := gowrapperNames[name]\n\t\tif humanName == \"\" {\n\t\t\thumanName = name // fallback\n\t\t}\n\t\tstackSize, stackSizeType, missingStackSize := funcs[0].StackSize()\n\t\tif baseStackSizeType != stacksize.Bounded {\n\t\t\t// It was not possible to determine the stack size at compile time\n\t\t\t// because tinygo_startTask does not have a fixed stack size. This\n\t\t\t// can happen when using -opt=1.\n\t\t\tstackSizeType = baseStackSizeType\n\t\t\tmissingStackSize = baseStackSizeFailedAt\n\t\t} else if stackSize < baseStackSize {\n\t\t\t// This goroutine has a very small stack, but still needs to fit all\n\t\t\t// registers to start and suspend the goroutine. Otherwise a stack\n\t\t\t// overflow will occur even before the goroutine is started.\n\t\t\tstackSize = baseStackSize\n\t\t}\n\t\tsizes[name] = functionStackSize{\n\t\t\tstackSize:        stackSize,\n\t\t\tstackSizeType:    stackSizeType,\n\t\t\tmissingStackSize: missingStackSize,\n\t\t\thumanName:        humanName,\n\t\t}\n\t}\n\n\tif resetFunction != \"\" {\n\t\treturn append([]string{resetFunction}, gowrappers...), sizes, nil\n\t}\n\treturn gowrappers, sizes, nil\n}\n\n// modifyStackSizes modifies the .tinygo_stacksizes section with the updated\n// stack size information. Before this modification, all stack sizes in the\n// section assume the default stack size (which is relatively big).\nfunc modifyStackSizes(executable string, stackSizeLoads []string, stackSizes map[string]functionStackSize) error {\n\tdata, fileHeader, err := getElfSectionData(executable, \".tinygo_stacksizes\")\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif len(stackSizeLoads)*4 != len(data) {\n\t\t// Note: while AVR should use 2 byte stack sizes, even 64-bit platforms\n\t\t// should probably stick to 4 byte stack sizes as a larger than 4GB\n\t\t// stack doesn't make much sense.\n\t\treturn errors.New(\"expected 4 byte stack sizes\")\n\t}\n\n\t// Modify goroutine stack sizes with a compile-time known worst case stack\n\t// size.\n\tfor i, name := range stackSizeLoads {\n\t\tfn, ok := stackSizes[name]\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"could not find symbol %s in ELF file\", name)\n\t\t}\n\t\tif fn.stackSizeType == stacksize.Bounded {\n\t\t\tstackSize := uint32(fn.stackSize)\n\n\t\t\t// Add stack size used by interrupts.\n\t\t\tswitch fileHeader.Machine {\n\t\t\tcase elf.EM_ARM:\n\t\t\t\tif stackSize%8 != 0 {\n\t\t\t\t\t// If the stack isn't a multiple of 8, it means the leaf\n\t\t\t\t\t// function with the biggest stack depth doesn't have an aligned\n\t\t\t\t\t// stack. If the STKALIGN flag is set (which it is by default)\n\t\t\t\t\t// the interrupt controller will forcibly align the stack before\n\t\t\t\t\t// storing in-use registers. This will thus overwrite one word\n\t\t\t\t\t// past the end of the stack (off-by-one).\n\t\t\t\t\tstackSize += 4\n\t\t\t\t}\n\n\t\t\t\t// On Cortex-M (assumed here), this stack size is 8 words or 32\n\t\t\t\t// bytes. This is only to store the registers that the interrupt\n\t\t\t\t// may modify, the interrupt will switch to the interrupt stack\n\t\t\t\t// (MSP).\n\t\t\t\t// Some background:\n\t\t\t\t// https://interrupt.memfault.com/blog/cortex-m-rtos-context-switching\n\t\t\t\tstackSize += 32\n\n\t\t\t\t// Adding 4 for the stack canary, and another 4 to keep the\n\t\t\t\t// stack aligned. Even though the size may be automatically\n\t\t\t\t// determined, stack overflow checking is still important as the\n\t\t\t\t// stack size cannot be determined for all goroutines.\n\t\t\t\tstackSize += 8\n\t\t\tdefault:\n\t\t\t\treturn fmt.Errorf(\"unknown architecture: %s\", fileHeader.Machine.String())\n\t\t\t}\n\n\t\t\t// Finally write the stack size to the binary.\n\t\t\tbinary.LittleEndian.PutUint32(data[i*4:], stackSize)\n\t\t}\n\t}\n\n\treturn replaceElfSection(executable, \".tinygo_stacksizes\", data)\n}\n\n// printStacks prints the maximum stack depth for functions that are started as\n// goroutines. Stack sizes cannot always be determined statically, in particular\n// recursive functions and functions that call interface methods or function\n// pointers may have an unknown stack depth (depending on what the optimizer\n// manages to optimize away).\n//\n// It might print something like the following:\n//\n//\tfunction                         stack usage (in bytes)\n//\tReset_Handler                    316\n//\texamples/blinky2.led1            92\n//\truntime.run$1                    300\nfunc printStacks(calculatedStacks []string, stackSizes map[string]functionStackSize) {\n\t// Print the sizes of all stacks.\n\tfmt.Printf(\"%-32s %s\\n\", \"function\", \"stack usage (in bytes)\")\n\tfor _, name := range calculatedStacks {\n\t\tfn := stackSizes[name]\n\t\tswitch fn.stackSizeType {\n\t\tcase stacksize.Bounded:\n\t\t\tfmt.Printf(\"%-32s %d\\n\", fn.humanName, fn.stackSize)\n\t\tcase stacksize.Unknown:\n\t\t\tfmt.Printf(\"%-32s unknown, %s does not have stack frame information\\n\", fn.humanName, fn.missingStackSize)\n\t\tcase stacksize.Recursive:\n\t\t\tfmt.Printf(\"%-32s recursive, %s may call itself\\n\", fn.humanName, fn.missingStackSize)\n\t\tcase stacksize.IndirectCall:\n\t\t\tfmt.Printf(\"%-32s unknown, %s calls a function pointer\\n\", fn.humanName, fn.missingStackSize)\n\t\t}\n\t}\n}\n\nfunc applyPatches(executable string, bootPatches []string) (err error) {\n\tfor _, patch := range bootPatches {\n\t\tswitch patch {\n\t\tcase \"rp2040\":\n\t\t\terr = patchRP2040BootCRC(executable)\n\t\t// case \"rp2350\":\n\t\t// \terr = patchRP2350BootIMAGE_DEF(executable)\n\t\tdefault:\n\t\t\terr = errors.New(\"undefined boot patch name\")\n\t\t}\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"apply boot patch %q: %w\", patch, err)\n\t\t}\n\t}\n\treturn nil\n}\n\n// RP2040 second stage bootloader CRC32 calculation\n//\n// Spec: https://datasheets.raspberrypi.org/rp2040/rp2040-datasheet.pdf\n// Section: 2.8.1.3.1. Checksum\nfunc patchRP2040BootCRC(executable string) error {\n\tbytes, _, err := getElfSectionData(executable, \".boot2\")\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif len(bytes) != 256 {\n\t\treturn fmt.Errorf(\"rp2040 .boot2 section must be exactly 256 bytes, got %d\", len(bytes))\n\t}\n\n\t// From the 'official' RP2040 checksum script:\n\t//\n\t//  Our bootrom CRC32 is slightly bass-ackward but it's\n\t//  best to work around for now (FIXME)\n\t//  100% worth it to save two Thumb instructions\n\trevBytes := make([]byte, len(bytes))\n\tfor i := range bytes {\n\t\trevBytes[i] = bits.Reverse8(bytes[i])\n\t}\n\n\t// crc32.Update does an initial negate and negates the\n\t// result, so to meet RP2040 spec, pass 0x0 as initial\n\t// hash and negate returned value.\n\t//\n\t// Note: checksum is over 252 bytes (256 - 4)\n\thash := bits.Reverse32(crc32.Update(0x0, crc32.IEEETable, revBytes[:252]) ^ 0xFFFFFFFF)\n\n\t// Write the CRC to the end of the bootloader.\n\tbinary.LittleEndian.PutUint32(bytes[252:], hash)\n\n\t// Update the .boot2 section to included the CRC\n\treturn replaceElfSection(executable, \".boot2\", bytes)\n}\n\n// lock may acquire a lock at the specified path.\n// It returns a function to release the lock.\n// If flock is not supported, it does nothing.\nfunc lock(path string) func() {\n\tflock := flock.New(path)\n\terr := flock.Lock()\n\tif err != nil {\n\t\treturn func() {}\n\t}\n\n\treturn func() { flock.Close() }\n}\n\nfunc b2u8(b bool) uint8 {\n\tif b {\n\t\treturn 1\n\t}\n\treturn 0\n}\n"
  },
  {
    "path": "builder/builder_test.go",
    "content": "package builder\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"testing\"\n\n\t\"github.com/tinygo-org/tinygo/compileopts\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// Test whether the Clang generated \"target-cpu\" and \"target-features\"\n// attributes match the CPU and Features property in TinyGo target files.\nfunc TestClangAttributes(t *testing.T) {\n\tvar targetNames = []string{\n\t\t// Please keep this list sorted!\n\t\t\"atmega328p\",\n\t\t\"atmega1280\",\n\t\t\"atmega1284p\",\n\t\t\"atmega2560\",\n\t\t\"attiny85\",\n\t\t\"cortex-m0\",\n\t\t\"cortex-m0plus\",\n\t\t\"cortex-m3\",\n\t\t\"cortex-m33\",\n\t\t\"cortex-m4\",\n\t\t\"cortex-m7\",\n\t\t\"esp32c3\",\n\t\t\"esp32s3\",\n\t\t\"fe310\",\n\t\t\"gameboy-advance\",\n\t\t\"k210\",\n\t\t\"nintendoswitch\",\n\t\t\"riscv-qemu\",\n\t\t\"tkey\",\n\t\t\"wasip1\",\n\t\t\"wasip2\",\n\t\t\"wasm\",\n\t\t\"wasm-unknown\",\n\t}\n\tif hasBuiltinTools {\n\t\t// hasBuiltinTools is set when TinyGo is statically linked with LLVM,\n\t\t// which also implies it was built with Xtensa support.\n\t\ttargetNames = append(targetNames, \"esp32\", \"esp8266\")\n\t}\n\tfor _, targetName := range targetNames {\n\t\ttargetName := targetName\n\t\tt.Run(targetName, func(t *testing.T) {\n\t\t\ttestClangAttributes(t, &compileopts.Options{Target: targetName})\n\t\t})\n\t}\n\n\tfor _, options := range []*compileopts.Options{\n\t\t{GOOS: \"linux\", GOARCH: \"386\"},\n\t\t{GOOS: \"linux\", GOARCH: \"amd64\"},\n\t\t{GOOS: \"linux\", GOARCH: \"arm\", GOARM: \"5,softfloat\"},\n\t\t{GOOS: \"linux\", GOARCH: \"arm\", GOARM: \"6,softfloat\"},\n\t\t{GOOS: \"linux\", GOARCH: \"arm\", GOARM: \"7,softfloat\"},\n\t\t{GOOS: \"linux\", GOARCH: \"arm\", GOARM: \"5,hardfloat\"},\n\t\t{GOOS: \"linux\", GOARCH: \"arm\", GOARM: \"6,hardfloat\"},\n\t\t{GOOS: \"linux\", GOARCH: \"arm\", GOARM: \"7,hardfloat\"},\n\t\t{GOOS: \"linux\", GOARCH: \"arm64\"},\n\t\t{GOOS: \"linux\", GOARCH: \"mips\", GOMIPS: \"hardfloat\"},\n\t\t{GOOS: \"linux\", GOARCH: \"mipsle\", GOMIPS: \"hardfloat\"},\n\t\t{GOOS: \"linux\", GOARCH: \"mips\", GOMIPS: \"softfloat\"},\n\t\t{GOOS: \"linux\", GOARCH: \"mipsle\", GOMIPS: \"softfloat\"},\n\t\t{GOOS: \"darwin\", GOARCH: \"amd64\"},\n\t\t{GOOS: \"darwin\", GOARCH: \"arm64\"},\n\t\t{GOOS: \"windows\", GOARCH: \"386\"},\n\t\t{GOOS: \"windows\", GOARCH: \"amd64\"},\n\t\t{GOOS: \"windows\", GOARCH: \"arm64\"},\n\t} {\n\t\tname := \"GOOS=\" + options.GOOS + \",GOARCH=\" + options.GOARCH\n\t\tif options.GOARCH == \"arm\" {\n\t\t\tname += \",GOARM=\" + options.GOARM\n\t\t}\n\t\tif options.GOARCH == \"mips\" || options.GOARCH == \"mipsle\" {\n\t\t\tname += \",GOMIPS=\" + options.GOMIPS\n\t\t}\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\ttestClangAttributes(t, options)\n\t\t})\n\t}\n}\n\nfunc testClangAttributes(t *testing.T, options *compileopts.Options) {\n\ttestDir := t.TempDir()\n\n\tctx := llvm.NewContext()\n\tdefer ctx.Dispose()\n\n\ttarget, err := compileopts.LoadTarget(options)\n\tif err != nil {\n\t\tt.Fatalf(\"could not load target: %s\", err)\n\t}\n\tconfig := compileopts.Config{\n\t\tOptions: options,\n\t\tTarget:  target,\n\t}\n\n\t// Create a very simple C input file.\n\tsrcpath := filepath.Join(testDir, \"test.c\")\n\terr = os.WriteFile(srcpath, []byte(\"int add(int a, int b) { return a + b; }\"), 0o666)\n\tif err != nil {\n\t\tt.Fatalf(\"could not write target file %s: %s\", srcpath, err)\n\t}\n\n\t// Compile this file using Clang.\n\toutpath := filepath.Join(testDir, \"test.bc\")\n\tflags := append([]string{\"-c\", \"-emit-llvm\", \"-o\", outpath, srcpath}, config.CFlags(false)...)\n\tif config.GOOS() == \"darwin\" {\n\t\t// Silence some warnings that happen when testing GOOS=darwin on\n\t\t// something other than MacOS.\n\t\tflags = append(flags, \"-Wno-missing-sysroot\", \"-Wno-incompatible-sysroot\")\n\t}\n\terr = runCCompiler(flags...)\n\tif err != nil {\n\t\tt.Fatalf(\"failed to compile %s: %s\", srcpath, err)\n\t}\n\n\t// Read the resulting LLVM bitcode.\n\tmod, err := ctx.ParseBitcodeFile(outpath)\n\tif err != nil {\n\t\tt.Fatalf(\"could not parse bitcode file %s: %s\", outpath, err)\n\t}\n\tdefer mod.Dispose()\n\n\t// Check whether the LLVM target matches.\n\tif mod.Target() != config.Triple() {\n\t\tt.Errorf(\"target has LLVM triple %#v but Clang makes it LLVM triple %#v\", config.Triple(), mod.Target())\n\t}\n\n\t// Check the \"target-cpu\" and \"target-features\" string attribute of the add\n\t// function.\n\tadd := mod.NamedFunction(\"add\")\n\tvar cpu, features string\n\tcpuAttr := add.GetStringAttributeAtIndex(-1, \"target-cpu\")\n\tfeaturesAttr := add.GetStringAttributeAtIndex(-1, \"target-features\")\n\tif !cpuAttr.IsNil() {\n\t\tcpu = cpuAttr.GetStringValue()\n\t}\n\tif !featuresAttr.IsNil() {\n\t\tfeatures = featuresAttr.GetStringValue()\n\t}\n\tif cpu != config.CPU() {\n\t\tt.Errorf(\"target has CPU %#v but Clang makes it CPU %#v\", config.CPU(), cpu)\n\t}\n\tif features != config.Features() {\n\t\tif hasBuiltinTools || runtime.GOOS != \"linux\" {\n\t\t\t// Skip this step when using an external Clang invocation on Linux.\n\t\t\t// The reason is that Debian has patched Clang in a way that\n\t\t\t// modifies the LLVM features string, changing lots of FPU/float\n\t\t\t// related flags. We want to test vanilla Clang, not Debian Clang.\n\t\t\tt.Errorf(\"target has LLVM features\\n\\t%#v\\nbut Clang makes it\\n\\t%#v\", config.Features(), features)\n\t\t}\n\t}\n}\n\n// This TestMain is necessary because TinyGo may also be invoked to run certain\n// LLVM tools in a separate process. Not capturing these invocations would lead\n// to recursive tests.\nfunc TestMain(m *testing.M) {\n\tif len(os.Args) >= 2 {\n\t\tswitch os.Args[1] {\n\t\tcase \"clang\", \"ld.lld\", \"wasm-ld\":\n\t\t\t// Invoke a specific tool.\n\t\t\terr := RunTool(os.Args[1], os.Args[2:]...)\n\t\t\tif err != nil {\n\t\t\t\tfmt.Fprintln(os.Stderr, err)\n\t\t\t\tos.Exit(1)\n\t\t\t}\n\t\t\tos.Exit(0)\n\t\t}\n\t}\n\n\t// Run normal tests.\n\tos.Exit(m.Run())\n}\n"
  },
  {
    "path": "builder/buildid.go",
    "content": "package builder\n\nimport (\n\t\"bytes\"\n\t\"debug/elf\"\n\t\"debug/macho\"\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"runtime\"\n)\n\n// ReadBuildID reads the build ID from the currently running executable.\nfunc ReadBuildID() ([]byte, error) {\n\texecutable, err := os.Executable()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tf, err := os.Open(executable)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer f.Close()\n\n\tswitch runtime.GOOS {\n\tcase \"linux\", \"freebsd\", \"android\":\n\t\t// Read the GNU build id section. (Not sure about FreeBSD though...)\n\t\tfile, err := elf.NewFile(f)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tvar gnuID, goID []byte\n\t\tfor _, section := range file.Sections {\n\t\t\tif section.Type != elf.SHT_NOTE ||\n\t\t\t\t(section.Name != \".note.gnu.build-id\" && section.Name != \".note.go.buildid\") {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tbuf := make([]byte, section.Size)\n\t\t\tn, err := section.ReadAt(buf, 0)\n\t\t\tif uint64(n) != section.Size || err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"could not read build id: %w\", err)\n\t\t\t}\n\t\t\tif section.Name == \".note.gnu.build-id\" {\n\t\t\t\tgnuID = buf\n\t\t\t} else {\n\t\t\t\tgoID = buf\n\t\t\t}\n\t\t}\n\t\tif gnuID != nil {\n\t\t\treturn gnuID, nil\n\t\t} else if goID != nil {\n\t\t\treturn goID, nil\n\t\t}\n\tcase \"darwin\":\n\t\t// Read the LC_UUID load command, which contains the equivalent of a\n\t\t// build ID.\n\t\tfile, err := macho.NewFile(f)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tfor _, load := range file.Loads {\n\t\t\t// Unfortunately, the debug/macho package doesn't support the\n\t\t\t// LC_UUID command directly. So we have to read it from\n\t\t\t// macho.LoadBytes.\n\t\t\tload, ok := load.(macho.LoadBytes)\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\traw := load.Raw()\n\t\t\tcommand := binary.LittleEndian.Uint32(raw)\n\t\t\tif command != 0x1b {\n\t\t\t\t// Looking for the LC_UUID load command.\n\t\t\t\t// LC_UUID is defined here as 0x1b:\n\t\t\t\t// https://opensource.apple.com/source/xnu/xnu-4570.71.2/EXTERNAL_HEADERS/mach-o/loader.h.auto.html\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn raw[4:], nil\n\t\t}\n\n\t\t// Normally we would have found a build ID by now. But not on Nix,\n\t\t// unfortunately, because Nix adds -no_uuid for some reason:\n\t\t// https://github.com/NixOS/nixpkgs/issues/178366\n\t\t// Fall back to the same implementation that we use for Windows.\n\t\tid, err := readRawGoBuildID(f, 32*1024)\n\t\tif len(id) != 0 || err != nil {\n\t\t\treturn id, err\n\t\t}\n\tdefault:\n\t\t// On other platforms (such as Windows) there isn't such a convenient\n\t\t// build ID. Luckily, Go does have an equivalent of the build ID, which\n\t\t// is stored as a special symbol named go.buildid. You can read it\n\t\t// using `go tool buildid`, but the code below extracts it directly\n\t\t// from the binary.\n\t\t// Unfortunately, because of stripping with the -w flag, no symbol\n\t\t// table might be available. Therefore, we have to scan the binary\n\t\t// directly. Luckily the build ID is always at the start of the file.\n\t\t// For details, see:\n\t\t// https://github.com/golang/go/blob/master/src/cmd/internal/buildid/buildid.go\n\t\tid, err := readRawGoBuildID(f, 4096)\n\t\tif len(id) != 0 || err != nil {\n\t\t\treturn id, err\n\t\t}\n\t}\n\treturn nil, fmt.Errorf(\"could not find build ID in %v\", executable)\n}\n\n// The Go toolchain stores a build ID in the binary that we can use, as a\n// fallback if binary file specific build IDs can't be obtained.\n// This function reads that build ID from the binary.\nfunc readRawGoBuildID(f *os.File, prefixSize int) ([]byte, error) {\n\tfileStart := make([]byte, prefixSize)\n\t_, err := io.ReadFull(f, fileStart)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"could not read build id from %s: %v\", f.Name(), err)\n\t}\n\tindex := bytes.Index(fileStart, []byte(\"\\xff Go build ID: \\\"\"))\n\tif index < 0 || index > len(fileStart)-103 {\n\t\treturn nil, fmt.Errorf(\"could not find build id in %s\", f.Name())\n\t}\n\tbuf := fileStart[index : index+103]\n\tif bytes.HasPrefix(buf, []byte(\"\\xff Go build ID: \\\"\")) && bytes.HasSuffix(buf, []byte(\"\\\"\\n \\xff\")) {\n\t\treturn buf[len(\"\\xff Go build ID: \\\"\") : len(buf)-1], nil\n\t}\n\n\treturn nil, nil\n}\n"
  },
  {
    "path": "builder/builtins.go",
    "content": "package builder\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/tinygo-org/tinygo/compileopts\"\n\t\"github.com/tinygo-org/tinygo/goenv\"\n)\n\n// These are the GENERIC_SOURCES according to CMakeList.txt except for\n// divmodsi4.c and udivmodsi4.c.\nvar genericBuiltins = []string{\n\t\"absvdi2.c\",\n\t\"absvsi2.c\",\n\t\"absvti2.c\",\n\t\"adddf3.c\",\n\t\"addsf3.c\",\n\t\"addvdi3.c\",\n\t\"addvsi3.c\",\n\t\"addvti3.c\",\n\t\"apple_versioning.c\",\n\t\"ashldi3.c\",\n\t\"ashlti3.c\",\n\t\"ashrdi3.c\",\n\t\"ashrti3.c\",\n\t\"bswapdi2.c\",\n\t\"bswapsi2.c\",\n\t\"clzdi2.c\",\n\t\"clzsi2.c\",\n\t\"clzti2.c\",\n\t\"cmpdi2.c\",\n\t\"cmpti2.c\",\n\t\"comparedf2.c\",\n\t\"comparesf2.c\",\n\t\"ctzdi2.c\",\n\t\"ctzsi2.c\",\n\t\"ctzti2.c\",\n\t\"divdc3.c\",\n\t\"divdf3.c\",\n\t\"divdi3.c\",\n\t\"divmoddi4.c\",\n\t//\"divmodsi4.c\",\n\t\"divmodti4.c\",\n\t\"divsc3.c\",\n\t\"divsf3.c\",\n\t\"divsi3.c\",\n\t\"divti3.c\",\n\t\"extendsfdf2.c\",\n\t\"extendhfsf2.c\",\n\t\"ffsdi2.c\",\n\t\"ffssi2.c\",\n\t\"ffsti2.c\",\n\t\"fixdfdi.c\",\n\t\"fixdfsi.c\",\n\t\"fixdfti.c\",\n\t\"fixsfdi.c\",\n\t\"fixsfsi.c\",\n\t\"fixsfti.c\",\n\t\"fixunsdfdi.c\",\n\t\"fixunsdfsi.c\",\n\t\"fixunsdfti.c\",\n\t\"fixunssfdi.c\",\n\t\"fixunssfsi.c\",\n\t\"fixunssfti.c\",\n\t\"floatdidf.c\",\n\t\"floatdisf.c\",\n\t\"floatsidf.c\",\n\t\"floatsisf.c\",\n\t\"floattidf.c\",\n\t\"floattisf.c\",\n\t\"floatundidf.c\",\n\t\"floatundisf.c\",\n\t\"floatunsidf.c\",\n\t\"floatunsisf.c\",\n\t\"floatuntidf.c\",\n\t\"floatuntisf.c\",\n\t\"fp_mode.c\",\n\t//\"int_util.c\",\n\t\"lshrdi3.c\",\n\t\"lshrti3.c\",\n\t\"moddi3.c\",\n\t\"modsi3.c\",\n\t\"modti3.c\",\n\t\"muldc3.c\",\n\t\"muldf3.c\",\n\t\"muldi3.c\",\n\t\"mulodi4.c\",\n\t\"mulosi4.c\",\n\t\"muloti4.c\",\n\t\"mulsc3.c\",\n\t\"mulsf3.c\",\n\t\"multi3.c\",\n\t\"mulvdi3.c\",\n\t\"mulvsi3.c\",\n\t\"mulvti3.c\",\n\t\"negdf2.c\",\n\t\"negdi2.c\",\n\t\"negsf2.c\",\n\t\"negti2.c\",\n\t\"negvdi2.c\",\n\t\"negvsi2.c\",\n\t\"negvti2.c\",\n\t\"os_version_check.c\",\n\t\"paritydi2.c\",\n\t\"paritysi2.c\",\n\t\"parityti2.c\",\n\t\"popcountdi2.c\",\n\t\"popcountsi2.c\",\n\t\"popcountti2.c\",\n\t\"powidf2.c\",\n\t\"powisf2.c\",\n\t\"subdf3.c\",\n\t\"subsf3.c\",\n\t\"subvdi3.c\",\n\t\"subvsi3.c\",\n\t\"subvti3.c\",\n\t\"trampoline_setup.c\",\n\t\"truncdfhf2.c\",\n\t\"truncdfsf2.c\",\n\t\"truncsfhf2.c\",\n\t\"ucmpdi2.c\",\n\t\"ucmpti2.c\",\n\t\"udivdi3.c\",\n\t\"udivmoddi4.c\",\n\t//\"udivmodsi4.c\",\n\t\"udivmodti4.c\",\n\t\"udivsi3.c\",\n\t\"udivti3.c\",\n\t\"umoddi3.c\",\n\t\"umodsi3.c\",\n\t\"umodti3.c\",\n}\n\n// These are the GENERIC_TF_SOURCES as of LLVM 18.\n// They are not needed on all platforms (32-bit platforms usually don't need\n// these) but they seem to compile fine so it's easier to include them.\nvar genericBuiltins128 = []string{\n\t\"addtf3.c\",\n\t\"comparetf2.c\",\n\t\"divtc3.c\",\n\t\"divtf3.c\",\n\t\"extenddftf2.c\",\n\t\"extendhftf2.c\",\n\t\"extendsftf2.c\",\n\t\"fixtfdi.c\",\n\t\"fixtfsi.c\",\n\t\"fixtfti.c\",\n\t\"fixunstfdi.c\",\n\t\"fixunstfsi.c\",\n\t\"fixunstfti.c\",\n\t\"floatditf.c\",\n\t\"floatsitf.c\",\n\t\"floattitf.c\",\n\t\"floatunditf.c\",\n\t\"floatunsitf.c\",\n\t\"floatuntitf.c\",\n\t\"multc3.c\",\n\t\"multf3.c\",\n\t\"powitf2.c\",\n\t\"subtf3.c\",\n\t\"trunctfdf2.c\",\n\t\"trunctfhf2.c\",\n\t\"trunctfsf2.c\",\n}\n\nvar aeabiBuiltins = []string{\n\t\"arm/aeabi_cdcmp.S\",\n\t\"arm/aeabi_cdcmpeq_check_nan.c\",\n\t\"arm/aeabi_cfcmp.S\",\n\t\"arm/aeabi_cfcmpeq_check_nan.c\",\n\t\"arm/aeabi_dcmp.S\",\n\t\"arm/aeabi_div0.c\",\n\t\"arm/aeabi_drsub.c\",\n\t\"arm/aeabi_fcmp.S\",\n\t\"arm/aeabi_frsub.c\",\n\t\"arm/aeabi_idivmod.S\",\n\t\"arm/aeabi_ldivmod.S\",\n\t\"arm/aeabi_memcmp.S\",\n\t\"arm/aeabi_memcpy.S\",\n\t\"arm/aeabi_memmove.S\",\n\t\"arm/aeabi_memset.S\",\n\t\"arm/aeabi_uidivmod.S\",\n\t\"arm/aeabi_uldivmod.S\",\n\n\t// These two are not technically EABI builtins but are used by them and only\n\t// seem to be used on ARM. LLVM seems to use __divsi3 and __modsi3 on most\n\t// other architectures.\n\t// Most importantly, they have a different calling convention on AVR so\n\t// should not be used on AVR.\n\t\"divmodsi4.c\",\n\t\"udivmodsi4.c\",\n}\n\nvar avrBuiltins = []string{\n\t\"avr/divmodhi4.S\",\n\t\"avr/divmodqi4.S\",\n\t\"avr/mulhi3.S\",\n\t\"avr/mulqi3.S\",\n\t\"avr/udivmodhi4.S\",\n\t\"avr/udivmodqi4.S\",\n}\n\n// Builtins needed specifically for windows/386.\nvar windowsI386Builtins = []string{\n\t\"i386/chkstk.S\", // also _alloca\n}\n\n// libCompilerRT is a library with symbols required by programs compiled with\n// LLVM. These symbols are for operations that cannot be emitted with a single\n// instruction or a short sequence of instructions for that target.\n//\n// For more information, see: https://compiler-rt.llvm.org/\nvar libCompilerRT = Library{\n\tname: \"compiler-rt\",\n\tcflags: func(target, headerPath string) []string {\n\t\treturn []string{\"-Werror\", \"-Wall\", \"-std=c11\", \"-nostdlibinc\"}\n\t},\n\tsourceDir: func() string {\n\t\tllvmDir := filepath.Join(goenv.Get(\"TINYGOROOT\"), \"llvm-project/compiler-rt/lib/builtins\")\n\t\tif _, err := os.Stat(llvmDir); err == nil {\n\t\t\t// Release build.\n\t\t\treturn llvmDir\n\t\t}\n\t\t// Development build.\n\t\treturn filepath.Join(goenv.Get(\"TINYGOROOT\"), \"lib/compiler-rt-builtins\")\n\t},\n\tlibrarySources: func(target string, _ bool) ([]string, error) {\n\t\tbuiltins := append([]string{}, genericBuiltins...) // copy genericBuiltins\n\t\tswitch compileopts.CanonicalArchName(target) {\n\t\tcase \"arm\":\n\t\t\tbuiltins = append(builtins, aeabiBuiltins...)\n\t\tcase \"avr\":\n\t\t\tbuiltins = append(builtins, avrBuiltins...)\n\t\tcase \"x86_64\", \"aarch64\", \"riscv64\": // any 64-bit arch\n\t\t\tbuiltins = append(builtins, genericBuiltins128...)\n\t\tcase \"i386\":\n\t\t\tif strings.Split(target, \"-\")[2] == \"windows\" {\n\t\t\t\tbuiltins = append(builtins, windowsI386Builtins...)\n\t\t\t}\n\t\t}\n\t\treturn builtins, nil\n\t},\n}\n"
  },
  {
    "path": "builder/cc.go",
    "content": "package builder\n\n// This file implements a wrapper around the C compiler (Clang) which uses a\n// build cache.\n\nimport (\n\t\"crypto/sha512\"\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"io/fs\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n\t\"unicode\"\n\n\t\"github.com/tinygo-org/tinygo/goenv\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// compileAndCacheCFile compiles a C or assembly file using a build cache.\n// Compiling the same file again (if nothing changed, including included header\n// files) the output is loaded from the build cache instead.\n//\n// Its operation is a bit complex (more complex than Go package build caching)\n// because the list of file dependencies is only known after the file is\n// compiled. However, luckily compilers have a flag to write a list of file\n// dependencies in Makefile syntax which can be used for caching.\n//\n// Because of this complexity, every file has in fact two cached build outputs:\n// the file itself, and the list of dependencies. Its operation is as follows:\n//\n//\tdepfile = hash(path, compiler, cflags, ...)\n//\tif depfile exists:\n//\t  outfile = hash of all files and depfile name\n//\t  if outfile exists:\n//\t    # cache hit\n//\t    return outfile\n//\t# cache miss\n//\ttmpfile = compile file\n//\tread dependencies (side effect of compile)\n//\twrite depfile\n//\toutfile = hash of all files and depfile name\n//\trename tmpfile to outfile\n//\n// There are a few edge cases that are not handled:\n//   - If a file is added to an include path, that file may be included instead of\n//     some other file. This would be fixed by also including lookup failures in the\n//     dependencies file, but I'm not aware of a compiler which does that.\n//   - The Makefile syntax that compilers output has issues, see readDepFile for\n//     details.\n//   - A header file may be changed to add/remove an include. This invalidates the\n//     depfile but without invalidating its name. For this reason, the depfile is\n//     written on each new compilation (even when it seems unnecessary). However, it\n//     could in rare cases lead to a stale file fetched from the cache.\nfunc compileAndCacheCFile(abspath, tmpdir string, cflags []string, printCommands func(string, ...string)) (string, error) {\n\t// Hash input file.\n\tfileHash, err := hashFile(abspath)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\t// Acquire a lock (if supported).\n\tunlock := lock(filepath.Join(goenv.Get(\"GOCACHE\"), fileHash+\".c.lock\"))\n\tdefer unlock()\n\n\t// Create cache key for the dependencies file.\n\tbuf, err := json.Marshal(struct {\n\t\tPath        string\n\t\tHash        string\n\t\tFlags       []string\n\t\tLLVMVersion string\n\t}{\n\t\tPath:        abspath,\n\t\tHash:        fileHash,\n\t\tFlags:       cflags,\n\t\tLLVMVersion: llvm.Version,\n\t})\n\tif err != nil {\n\t\tpanic(err) // shouldn't happen\n\t}\n\tdepfileNameHashBuf := sha512.Sum512_224(buf)\n\tdepfileNameHash := hex.EncodeToString(depfileNameHashBuf[:])\n\n\t// Load dependencies file, if possible.\n\tdepfileName := \"dep-\" + depfileNameHash + \".json\"\n\tdepfileCachePath := filepath.Join(goenv.Get(\"GOCACHE\"), depfileName)\n\tdepfileBuf, err := os.ReadFile(depfileCachePath)\n\tvar dependencies []string // sorted list of dependency paths\n\tif err == nil {\n\t\t// There is a dependency file, that's great!\n\t\t// Parse it first.\n\t\terr := json.Unmarshal(depfileBuf, &dependencies)\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"could not parse dependencies JSON: %w\", err)\n\t\t}\n\n\t\t// Obtain hashes of all the files listed as a dependency.\n\t\toutpath, err := makeCFileCachePath(dependencies, depfileNameHash)\n\t\tif err == nil {\n\t\t\tif _, err := os.Stat(outpath); err == nil {\n\t\t\t\treturn outpath, nil\n\t\t\t} else if !errors.Is(err, fs.ErrNotExist) {\n\t\t\t\treturn \"\", err\n\t\t\t}\n\t\t}\n\t} else if !errors.Is(err, fs.ErrNotExist) {\n\t\t// expected either nil or IsNotExist\n\t\treturn \"\", err\n\t}\n\n\tobjTmpFile, err := os.CreateTemp(goenv.Get(\"GOCACHE\"), \"tmp-*.bc\")\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tobjTmpFile.Close()\n\tdepTmpFile, err := os.CreateTemp(tmpdir, \"dep-*.d\")\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tdepTmpFile.Close()\n\tflags := append([]string{}, cflags...)                                                 // copy cflags\n\tflags = append(flags, \"-MD\", \"-MV\", \"-MTdeps\", \"-MF\", depTmpFile.Name(), \"-flto=thin\") // autogenerate dependencies\n\tflags = append(flags, \"-c\", \"-o\", objTmpFile.Name(), abspath)\n\tif strings.ToLower(filepath.Ext(abspath)) == \".s\" {\n\t\t// If this is an assembly file (.s or .S, lowercase or uppercase), then\n\t\t// we'll need to add -Qunused-arguments because many parameters are\n\t\t// relevant to C, not assembly. And with -Werror, having meaningless\n\t\t// flags (for the assembler) is a compiler error.\n\t\tflags = append(flags, \"-Qunused-arguments\")\n\t}\n\tif printCommands != nil {\n\t\tprintCommands(\"clang\", flags...)\n\t}\n\terr = runCCompiler(flags...)\n\tif err != nil {\n\t\treturn \"\", &commandError{\"failed to build\", abspath, err}\n\t}\n\n\t// Create sorted and uniqued slice of dependencies.\n\tdependencyPaths, err := readDepFile(depTmpFile.Name())\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tdependencyPaths = append(dependencyPaths, abspath) // necessary for .s files\n\tdependencySet := make(map[string]struct{}, len(dependencyPaths))\n\tvar dependencySlice []string\n\tfor _, path := range dependencyPaths {\n\t\tif _, ok := dependencySet[path]; ok {\n\t\t\tcontinue\n\t\t}\n\t\tdependencySet[path] = struct{}{}\n\t\tdependencySlice = append(dependencySlice, path)\n\t}\n\tsort.Strings(dependencySlice)\n\n\t// Write dependencies file.\n\tf, err := os.CreateTemp(filepath.Dir(depfileCachePath), depfileName)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tbuf, err = json.MarshalIndent(dependencySlice, \"\", \"\\t\")\n\tif err != nil {\n\t\tpanic(err) // shouldn't happen\n\t}\n\t_, err = f.Write(buf)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\terr = f.Close()\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\terr = os.Rename(f.Name(), depfileCachePath)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\t// Move temporary object file to final location.\n\toutpath, err := makeCFileCachePath(dependencySlice, depfileNameHash)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\terr = os.Rename(objTmpFile.Name(), outpath)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\treturn outpath, nil\n}\n\n// Create a cache path (a path in GOCACHE) to store the output of a compiler\n// job. This path is based on the dep file name (which is a hash of metadata\n// including compiler flags) and the hash of all input files in the paths slice.\nfunc makeCFileCachePath(paths []string, depfileNameHash string) (string, error) {\n\t// Hash all input files.\n\tfileHashes := make(map[string]string, len(paths))\n\tfor _, path := range paths {\n\t\thash, err := hashFile(path)\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\tfileHashes[path] = hash\n\t}\n\n\t// Calculate a cache key based on the above hashes.\n\tbuf, err := json.Marshal(struct {\n\t\tDepfileHash string\n\t\tFileHashes  map[string]string\n\t}{\n\t\tDepfileHash: depfileNameHash,\n\t\tFileHashes:  fileHashes,\n\t})\n\tif err != nil {\n\t\tpanic(err) // shouldn't happen\n\t}\n\toutFileNameBuf := sha512.Sum512_224(buf)\n\tcacheKey := hex.EncodeToString(outFileNameBuf[:])\n\n\toutpath := filepath.Join(goenv.Get(\"GOCACHE\"), \"obj-\"+cacheKey+\".bc\")\n\treturn outpath, nil\n}\n\n// hashFile hashes the given file path and returns the hash as a hex string.\nfunc hashFile(path string) (string, error) {\n\tf, err := os.Open(path)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to hash file: %w\", err)\n\t}\n\tdefer f.Close()\n\tfileHasher := sha512.New512_224()\n\t_, err = io.Copy(fileHasher, f)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to hash file: %w\", err)\n\t}\n\treturn hex.EncodeToString(fileHasher.Sum(nil)), nil\n}\n\n// readDepFile reads a dependency file in NMake (Visual Studio make) format. The\n// file is assumed to have a single target named deps.\n//\n// There are roughly three make syntax variants:\n//   - BSD make, which doesn't support any escaping. This means that many special\n//     characters are not supported in file names.\n//   - GNU make, which supports escaping using a backslash but when it fails to\n//     find a file it tries to fall back with the literal path name (to match BSD\n//     make).\n//   - NMake (Visual Studio) and Jom, which simply quote the string if there are\n//     any weird characters.\n//\n// Clang supports two variants: a format that's a compromise between BSD and GNU\n// make (and is buggy to match GCC which is equally buggy), and NMake/Jom, which\n// is at least somewhat sane. This last format isn't perfect either: it does not\n// correctly handle filenames with quote marks in them. Those are generally not\n// allowed on Windows, but of course can be used on POSIX like systems. Still,\n// it's the most sane of any of the formats so readDepFile will use that format.\nfunc readDepFile(filename string) ([]string, error) {\n\tbuf, err := os.ReadFile(filename)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif len(buf) == 0 {\n\t\treturn nil, nil\n\t}\n\treturn parseDepFile(string(buf))\n}\n\nfunc parseDepFile(s string) ([]string, error) {\n\t// This function makes no attempt at parsing anything other than Clang -MD\n\t// -MV output.\n\n\t// For Windows: replace CRLF with LF to make the logic below simpler.\n\ts = strings.ReplaceAll(s, \"\\r\\n\", \"\\n\")\n\n\t// Collapse all lines ending in a backslash. These backslashes are really\n\t// just a way to continue a line without making very long lines.\n\ts = strings.ReplaceAll(s, \"\\\\\\n\", \" \")\n\n\t// Only use the first line, which is expected to begin with \"deps:\".\n\tline := strings.SplitN(s, \"\\n\", 2)[0]\n\tif !strings.HasPrefix(line, \"deps:\") {\n\t\treturn nil, errors.New(\"readDepFile: expected 'deps:' prefix\")\n\t}\n\tline = strings.TrimSpace(line[len(\"deps:\"):])\n\n\tvar deps []string\n\tfor line != \"\" {\n\t\tif line[0] == '\"' {\n\t\t\t// File path is quoted. Path ends with double quote.\n\t\t\t// This does not handle double quotes in path names, which is a\n\t\t\t// problem on non-Windows systems.\n\t\t\tline = line[1:]\n\t\t\tend := strings.IndexByte(line, '\"')\n\t\t\tif end < 0 {\n\t\t\t\treturn nil, errors.New(\"readDepFile: path is incorrectly quoted\")\n\t\t\t}\n\t\t\tdep := line[:end]\n\t\t\tline = strings.TrimSpace(line[end+1:])\n\t\t\tdeps = append(deps, dep)\n\t\t} else {\n\t\t\t// File path is not quoted. Path ends in space or EOL.\n\t\t\tend := strings.IndexFunc(line, unicode.IsSpace)\n\t\t\tif end < 0 {\n\t\t\t\t// last dependency\n\t\t\t\tdeps = append(deps, line)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tdep := line[:end]\n\t\t\tline = strings.TrimSpace(line[end:])\n\t\t\tdeps = append(deps, dep)\n\t\t}\n\t}\n\treturn deps, nil\n}\n"
  },
  {
    "path": "builder/cc1as.cpp",
    "content": "//go:build byollvm\n\n// Source: https://github.com/llvm/llvm-project/blob/main/clang/tools/driver/cc1as_main.cpp\n// This file needs to be updated each LLVM release.\n// There are a few small modifications to make, like:\n//   * ExecuteAssembler is made non-static.\n//   * The struct AssemblerImplementation is moved to cc1as.h so it can be\n//     included elsewhere.\n\n//===-- cc1as.cpp - Clang Assembler  --------------------------------------===//\n//\n// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.\n// See https://llvm.org/LICENSE.txt for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n//===----------------------------------------------------------------------===//\n//\n// This is the entry point to the clang -cc1as functionality, which implements\n// the direct interface to the LLVM MC based assembler.\n//\n//===----------------------------------------------------------------------===//\n\n#include \"clang/Basic/Diagnostic.h\"\n#include \"clang/Basic/DiagnosticOptions.h\"\n#include \"clang/Driver/DriverDiagnostic.h\"\n#include \"clang/Driver/Options.h\"\n#include \"clang/Frontend/FrontendDiagnostic.h\"\n#include \"clang/Frontend/TextDiagnosticPrinter.h\"\n#include \"clang/Frontend/Utils.h\"\n#include \"llvm/ADT/STLExtras.h\"\n#include \"llvm/ADT/StringExtras.h\"\n#include \"llvm/ADT/StringSwitch.h\"\n#include \"llvm/IR/DataLayout.h\"\n#include \"llvm/MC/MCAsmBackend.h\"\n#include \"llvm/MC/MCAsmInfo.h\"\n#include \"llvm/MC/MCCodeEmitter.h\"\n#include \"llvm/MC/MCContext.h\"\n#include \"llvm/MC/MCInstrInfo.h\"\n#include \"llvm/MC/MCObjectFileInfo.h\"\n#include \"llvm/MC/MCObjectWriter.h\"\n#include \"llvm/MC/MCParser/MCAsmParser.h\"\n#include \"llvm/MC/MCParser/MCTargetAsmParser.h\"\n#include \"llvm/MC/MCRegisterInfo.h\"\n#include \"llvm/MC/MCSectionMachO.h\"\n#include \"llvm/MC/MCStreamer.h\"\n#include \"llvm/MC/MCSubtargetInfo.h\"\n#include \"llvm/MC/MCTargetOptions.h\"\n#include \"llvm/MC/TargetRegistry.h\"\n#include \"llvm/Option/Arg.h\"\n#include \"llvm/Option/ArgList.h\"\n#include \"llvm/Option/OptTable.h\"\n#include \"llvm/Support/CommandLine.h\"\n#include \"llvm/Support/ErrorHandling.h\"\n#include \"llvm/Support/FileSystem.h\"\n#include \"llvm/Support/FormattedStream.h\"\n#include \"llvm/Support/MemoryBuffer.h\"\n#include \"llvm/Support/Path.h\"\n#include \"llvm/Support/Process.h\"\n#include \"llvm/Support/Signals.h\"\n#include \"llvm/Support/SourceMgr.h\"\n#include \"llvm/Support/TargetSelect.h\"\n#include \"llvm/Support/Timer.h\"\n#include \"llvm/Support/raw_ostream.h\"\n#include \"llvm/TargetParser/Host.h\"\n#include \"llvm/TargetParser/Triple.h\"\n#include <memory>\n#include <optional>\n#include <system_error>\nusing namespace clang;\nusing namespace clang::driver;\nusing namespace clang::driver::options;\nusing namespace llvm;\nusing namespace llvm::opt;\n\n#include \"cc1as.h\"\n\nbool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,\n                                         ArrayRef<const char *> Argv,\n                                         DiagnosticsEngine &Diags) {\n  bool Success = true;\n\n  // Parse the arguments.\n  const OptTable &OptTbl = getDriverOptTable();\n\n  llvm::opt::Visibility VisibilityMask(options::CC1AsOption);\n  unsigned MissingArgIndex, MissingArgCount;\n  InputArgList Args =\n      OptTbl.ParseArgs(Argv, MissingArgIndex, MissingArgCount, VisibilityMask);\n\n  // Check for missing argument error.\n  if (MissingArgCount) {\n    Diags.Report(diag::err_drv_missing_argument)\n        << Args.getArgString(MissingArgIndex) << MissingArgCount;\n    Success = false;\n  }\n\n  // Issue errors on unknown arguments.\n  for (const Arg *A : Args.filtered(OPT_UNKNOWN)) {\n    auto ArgString = A->getAsString(Args);\n    std::string Nearest;\n    if (OptTbl.findNearest(ArgString, Nearest, VisibilityMask) > 1)\n      Diags.Report(diag::err_drv_unknown_argument) << ArgString;\n    else\n      Diags.Report(diag::err_drv_unknown_argument_with_suggestion)\n          << ArgString << Nearest;\n    Success = false;\n  }\n\n  // Construct the invocation.\n\n  // Target Options\n  Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple));\n  if (Arg *A = Args.getLastArg(options::OPT_darwin_target_variant_triple))\n    Opts.DarwinTargetVariantTriple = llvm::Triple(A->getValue());\n  if (Arg *A = Args.getLastArg(OPT_darwin_target_variant_sdk_version_EQ)) {\n    VersionTuple Version;\n    if (Version.tryParse(A->getValue()))\n      Diags.Report(diag::err_drv_invalid_value)\n          << A->getAsString(Args) << A->getValue();\n    else\n      Opts.DarwinTargetVariantSDKVersion = Version;\n  }\n\n  Opts.CPU = std::string(Args.getLastArgValue(OPT_target_cpu));\n  Opts.Features = Args.getAllArgValues(OPT_target_feature);\n\n  // Use the default target triple if unspecified.\n  if (Opts.Triple.empty())\n    Opts.Triple = llvm::sys::getDefaultTargetTriple();\n\n  // Language Options\n  Opts.IncludePaths = Args.getAllArgValues(OPT_I);\n  Opts.NoInitialTextSection = Args.hasArg(OPT_n);\n  Opts.SaveTemporaryLabels = Args.hasArg(OPT_msave_temp_labels);\n  // Any DebugInfoKind implies GenDwarfForAssembly.\n  Opts.GenDwarfForAssembly = Args.hasArg(OPT_debug_info_kind_EQ);\n\n  if (const Arg *A = Args.getLastArg(OPT_compress_debug_sections_EQ)) {\n    Opts.CompressDebugSections =\n        llvm::StringSwitch<llvm::DebugCompressionType>(A->getValue())\n            .Case(\"none\", llvm::DebugCompressionType::None)\n            .Case(\"zlib\", llvm::DebugCompressionType::Zlib)\n            .Case(\"zstd\", llvm::DebugCompressionType::Zstd)\n            .Default(llvm::DebugCompressionType::None);\n  }\n\n  if (auto *DwarfFormatArg = Args.getLastArg(OPT_gdwarf64, OPT_gdwarf32))\n    Opts.Dwarf64 = DwarfFormatArg->getOption().matches(OPT_gdwarf64);\n  Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 2, Diags);\n  Opts.DwarfDebugFlags =\n      std::string(Args.getLastArgValue(OPT_dwarf_debug_flags));\n  Opts.DwarfDebugProducer =\n      std::string(Args.getLastArgValue(OPT_dwarf_debug_producer));\n  if (const Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ,\n                                     options::OPT_fdebug_compilation_dir_EQ))\n    Opts.DebugCompilationDir = A->getValue();\n  Opts.MainFileName = std::string(Args.getLastArgValue(OPT_main_file_name));\n\n  for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) {\n    auto Split = StringRef(Arg).split('=');\n    Opts.DebugPrefixMap.emplace_back(Split.first, Split.second);\n  }\n\n  // Frontend Options\n  if (Args.hasArg(OPT_INPUT)) {\n    bool First = true;\n    for (const Arg *A : Args.filtered(OPT_INPUT)) {\n      if (First) {\n        Opts.InputFile = A->getValue();\n        First = false;\n      } else {\n        Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(Args);\n        Success = false;\n      }\n    }\n  }\n  Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm);\n  Opts.OutputPath = std::string(Args.getLastArgValue(OPT_o));\n  Opts.SplitDwarfOutput =\n      std::string(Args.getLastArgValue(OPT_split_dwarf_output));\n  if (Arg *A = Args.getLastArg(OPT_filetype)) {\n    StringRef Name = A->getValue();\n    unsigned OutputType = StringSwitch<unsigned>(Name)\n      .Case(\"asm\", FT_Asm)\n      .Case(\"null\", FT_Null)\n      .Case(\"obj\", FT_Obj)\n      .Default(~0U);\n    if (OutputType == ~0U) {\n      Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;\n      Success = false;\n    } else\n      Opts.OutputType = FileType(OutputType);\n  }\n  Opts.ShowHelp = Args.hasArg(OPT_help);\n  Opts.ShowVersion = Args.hasArg(OPT_version);\n\n  // Transliterate Options\n  Opts.OutputAsmVariant =\n      getLastArgIntValue(Args, OPT_output_asm_variant, 0, Diags);\n  Opts.ShowEncoding = Args.hasArg(OPT_show_encoding);\n  Opts.ShowInst = Args.hasArg(OPT_show_inst);\n\n  // Assemble Options\n  Opts.RelaxAll = Args.hasArg(OPT_mrelax_all);\n  Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack);\n  Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings);\n  Opts.NoWarn = Args.hasArg(OPT_massembler_no_warn);\n  Opts.NoTypeCheck = Args.hasArg(OPT_mno_type_check);\n  Opts.RelocationModel =\n      std::string(Args.getLastArgValue(OPT_mrelocation_model, \"pic\"));\n  Opts.TargetABI = std::string(Args.getLastArgValue(OPT_target_abi));\n  Opts.IncrementalLinkerCompatible =\n      Args.hasArg(OPT_mincremental_linker_compatible);\n  Opts.SymbolDefs = Args.getAllArgValues(OPT_defsym);\n\n  // EmbedBitcode Option. If -fembed-bitcode is enabled, set the flag.\n  // EmbedBitcode behaves the same for all embed options for assembly files.\n  if (auto *A = Args.getLastArg(OPT_fembed_bitcode_EQ)) {\n    Opts.EmbedBitcode = llvm::StringSwitch<unsigned>(A->getValue())\n                            .Case(\"all\", 1)\n                            .Case(\"bitcode\", 1)\n                            .Case(\"marker\", 1)\n                            .Default(0);\n  }\n\n  if (auto *A = Args.getLastArg(OPT_femit_dwarf_unwind_EQ)) {\n    Opts.EmitDwarfUnwind =\n        llvm::StringSwitch<EmitDwarfUnwindType>(A->getValue())\n            .Case(\"always\", EmitDwarfUnwindType::Always)\n            .Case(\"no-compact-unwind\", EmitDwarfUnwindType::NoCompactUnwind)\n            .Case(\"default\", EmitDwarfUnwindType::Default);\n  }\n\n  Opts.EmitCompactUnwindNonCanonical =\n      Args.hasArg(OPT_femit_compact_unwind_non_canonical);\n  Opts.Crel = Args.hasArg(OPT_crel);\n  Opts.ImplicitMapsyms = Args.hasArg(OPT_mmapsyms_implicit);\n  Opts.X86RelaxRelocations = !Args.hasArg(OPT_mrelax_relocations_no);\n  Opts.X86Sse2Avx = Args.hasArg(OPT_msse2avx);\n\n  Opts.AsSecureLogFile = Args.getLastArgValue(OPT_as_secure_log_file);\n\n  return Success;\n}\n\nstatic std::unique_ptr<raw_fd_ostream>\ngetOutputStream(StringRef Path, DiagnosticsEngine &Diags, bool Binary) {\n  // Make sure that the Out file gets unlinked from the disk if we get a\n  // SIGINT.\n  if (Path != \"-\")\n    sys::RemoveFileOnSignal(Path);\n\n  std::error_code EC;\n  auto Out = std::make_unique<raw_fd_ostream>(\n      Path, EC, (Binary ? sys::fs::OF_None : sys::fs::OF_TextWithCRLF));\n  if (EC) {\n    Diags.Report(diag::err_fe_unable_to_open_output) << Path << EC.message();\n    return nullptr;\n  }\n\n  return Out;\n}\n\nstatic bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,\n                                 DiagnosticsEngine &Diags) {\n  // Get the target specific parser.\n  std::string Error;\n  const Target *TheTarget = TargetRegistry::lookupTarget(Opts.Triple, Error);\n  if (!TheTarget)\n    return Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;\n\n  ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer =\n      MemoryBuffer::getFileOrSTDIN(Opts.InputFile, /*IsText=*/true);\n\n  if (std::error_code EC = Buffer.getError()) {\n    return Diags.Report(diag::err_fe_error_reading)\n           << Opts.InputFile << EC.message();\n  }\n\n  SourceMgr SrcMgr;\n\n  // Tell SrcMgr about this buffer, which is what the parser will pick up.\n  unsigned BufferIndex = SrcMgr.AddNewSourceBuffer(std::move(*Buffer), SMLoc());\n\n  // Record the location of the include directories so that the lexer can find\n  // it later.\n  SrcMgr.setIncludeDirs(Opts.IncludePaths);\n\n  std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(Opts.Triple));\n  assert(MRI && \"Unable to create target register info!\");\n\n  MCTargetOptions MCOptions;\n  MCOptions.MCRelaxAll = Opts.RelaxAll;\n  MCOptions.EmitDwarfUnwind = Opts.EmitDwarfUnwind;\n  MCOptions.EmitCompactUnwindNonCanonical = Opts.EmitCompactUnwindNonCanonical;\n  MCOptions.MCSaveTempLabels = Opts.SaveTemporaryLabels;\n  MCOptions.Crel = Opts.Crel;\n  MCOptions.ImplicitMapSyms = Opts.ImplicitMapsyms;\n  MCOptions.X86RelaxRelocations = Opts.X86RelaxRelocations;\n  MCOptions.X86Sse2Avx = Opts.X86Sse2Avx;\n  MCOptions.CompressDebugSections = Opts.CompressDebugSections;\n  MCOptions.AsSecureLogFile = Opts.AsSecureLogFile;\n\n  std::unique_ptr<MCAsmInfo> MAI(\n      TheTarget->createMCAsmInfo(*MRI, Opts.Triple, MCOptions));\n  assert(MAI && \"Unable to create target asm info!\");\n\n  // Ensure MCAsmInfo initialization occurs before any use, otherwise sections\n  // may be created with a combination of default and explicit settings.\n\n\n  bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj;\n  if (Opts.OutputPath.empty())\n    Opts.OutputPath = \"-\";\n  std::unique_ptr<raw_fd_ostream> FDOS =\n      getOutputStream(Opts.OutputPath, Diags, IsBinary);\n  if (!FDOS)\n    return true;\n  std::unique_ptr<raw_fd_ostream> DwoOS;\n  if (!Opts.SplitDwarfOutput.empty())\n    DwoOS = getOutputStream(Opts.SplitDwarfOutput, Diags, IsBinary);\n\n  // Build up the feature string from the target feature list.\n  std::string FS = llvm::join(Opts.Features, \",\");\n\n  std::unique_ptr<MCSubtargetInfo> STI(\n      TheTarget->createMCSubtargetInfo(Opts.Triple, Opts.CPU, FS));\n  assert(STI && \"Unable to create subtarget info!\");\n\n  MCContext Ctx(Triple(Opts.Triple), MAI.get(), MRI.get(), STI.get(), &SrcMgr,\n                &MCOptions);\n\n  bool PIC = false;\n  if (Opts.RelocationModel == \"static\") {\n    PIC = false;\n  } else if (Opts.RelocationModel == \"pic\") {\n    PIC = true;\n  } else {\n    assert(Opts.RelocationModel == \"dynamic-no-pic\" &&\n           \"Invalid PIC model!\");\n    PIC = false;\n  }\n\n  // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and\n  // MCObjectFileInfo needs a MCContext reference in order to initialize itself.\n  std::unique_ptr<MCObjectFileInfo> MOFI(\n      TheTarget->createMCObjectFileInfo(Ctx, PIC));\n  Ctx.setObjectFileInfo(MOFI.get());\n\n  if (Opts.GenDwarfForAssembly)\n    Ctx.setGenDwarfForAssembly(true);\n  if (!Opts.DwarfDebugFlags.empty())\n    Ctx.setDwarfDebugFlags(StringRef(Opts.DwarfDebugFlags));\n  if (!Opts.DwarfDebugProducer.empty())\n    Ctx.setDwarfDebugProducer(StringRef(Opts.DwarfDebugProducer));\n  if (!Opts.DebugCompilationDir.empty())\n    Ctx.setCompilationDir(Opts.DebugCompilationDir);\n  else {\n    // If no compilation dir is set, try to use the current directory.\n    SmallString<128> CWD;\n    if (!sys::fs::current_path(CWD))\n      Ctx.setCompilationDir(CWD);\n  }\n  if (!Opts.DebugPrefixMap.empty())\n    for (const auto &KV : Opts.DebugPrefixMap)\n      Ctx.addDebugPrefixMapEntry(KV.first, KV.second);\n  if (!Opts.MainFileName.empty())\n    Ctx.setMainFileName(StringRef(Opts.MainFileName));\n  Ctx.setDwarfFormat(Opts.Dwarf64 ? dwarf::DWARF64 : dwarf::DWARF32);\n  Ctx.setDwarfVersion(Opts.DwarfVersion);\n  if (Opts.GenDwarfForAssembly)\n    Ctx.setGenDwarfRootFile(Opts.InputFile,\n                            SrcMgr.getMemoryBuffer(BufferIndex)->getBuffer());\n\n  std::unique_ptr<MCStreamer> Str;\n\n  std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());\n  assert(MCII && \"Unable to create instruction info!\");\n\n  raw_pwrite_stream *Out = FDOS.get();\n  std::unique_ptr<buffer_ostream> BOS;\n\n  MCOptions.MCNoWarn = Opts.NoWarn;\n  MCOptions.MCFatalWarnings = Opts.FatalWarnings;\n  MCOptions.MCNoTypeCheck = Opts.NoTypeCheck;\n  MCOptions.ShowMCInst = Opts.ShowInst;\n  MCOptions.AsmVerbose = true;\n  MCOptions.MCUseDwarfDirectory = MCTargetOptions::EnableDwarfDirectory;\n  MCOptions.ABIName = Opts.TargetABI;\n\n  // FIXME: There is a bit of code duplication with addPassesToEmitFile.\n  if (Opts.OutputType == AssemblerInvocation::FT_Asm) {\n    MCInstPrinter *IP = TheTarget->createMCInstPrinter(\n        llvm::Triple(Opts.Triple), Opts.OutputAsmVariant, *MAI, *MCII, *MRI);\n\n    std::unique_ptr<MCCodeEmitter> CE;\n    if (Opts.ShowEncoding)\n      CE.reset(TheTarget->createMCCodeEmitter(*MCII, Ctx));\n    std::unique_ptr<MCAsmBackend> MAB(\n        TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));\n\n    auto FOut = std::make_unique<formatted_raw_ostream>(*Out);\n    Str.reset(TheTarget->createAsmStreamer(Ctx, std::move(FOut), IP,\n                                           std::move(CE), std::move(MAB)));\n  } else if (Opts.OutputType == AssemblerInvocation::FT_Null) {\n    Str.reset(createNullStreamer(Ctx));\n  } else {\n    assert(Opts.OutputType == AssemblerInvocation::FT_Obj &&\n           \"Invalid file type!\");\n    if (!FDOS->supportsSeeking()) {\n      BOS = std::make_unique<buffer_ostream>(*FDOS);\n      Out = BOS.get();\n    }\n\n    std::unique_ptr<MCCodeEmitter> CE(\n        TheTarget->createMCCodeEmitter(*MCII, Ctx));\n    std::unique_ptr<MCAsmBackend> MAB(\n        TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));\n    assert(MAB && \"Unable to create asm backend!\");\n\n    std::unique_ptr<MCObjectWriter> OW =\n        DwoOS ? MAB->createDwoObjectWriter(*Out, *DwoOS)\n              : MAB->createObjectWriter(*Out);\n\n    Triple T(Opts.Triple);\n    Str.reset(TheTarget->createMCObjectStreamer(\n        T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI));\n    Str.get()->initSections(Opts.NoExecStack, *STI);\n    if (T.isOSBinFormatMachO() && T.isOSDarwin()) {\n      Triple *TVT = Opts.DarwinTargetVariantTriple\n                        ? &*Opts.DarwinTargetVariantTriple\n                        : nullptr;\n      Str->emitVersionForTarget(T, VersionTuple(), TVT,\n                                Opts.DarwinTargetVariantSDKVersion);\n    }\n  }\n\n  // When -fembed-bitcode is passed to clang_as, a 1-byte marker\n  // is emitted in __LLVM,__asm section if the object file is MachO format.\n  if (Opts.EmbedBitcode && Ctx.getObjectFileType() == MCContext::IsMachO) {\n    MCSection *AsmLabel = Ctx.getMachOSection(\n        \"__LLVM\", \"__asm\", MachO::S_REGULAR, 4, SectionKind::getReadOnly());\n    Str.get()->switchSection(AsmLabel);\n    Str.get()->emitZeros(1);\n  }\n\n  bool Failed = false;\n\n  std::unique_ptr<MCAsmParser> Parser(\n      createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI));\n\n  // FIXME: init MCTargetOptions from sanitizer flags here.\n  std::unique_ptr<MCTargetAsmParser> TAP(\n      TheTarget->createMCAsmParser(*STI, *Parser, *MCII, MCOptions));\n  if (!TAP)\n    Failed = Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;\n\n  // Set values for symbols, if any.\n  for (auto &S : Opts.SymbolDefs) {\n    auto Pair = StringRef(S).split('=');\n    auto Sym = Pair.first;\n    auto Val = Pair.second;\n    int64_t Value;\n    // We have already error checked this in the driver.\n    Val.getAsInteger(0, Value);\n    Ctx.setSymbolValue(Parser->getStreamer(), Sym, Value);\n  }\n\n  if (!Failed) {\n    Parser->setTargetParser(*TAP.get());\n    Failed = Parser->Run(Opts.NoInitialTextSection);\n  }\n\n  return Failed;\n}\n\nbool ExecuteAssembler(AssemblerInvocation &Opts,\n                             DiagnosticsEngine &Diags) {\n  bool Failed = ExecuteAssemblerImpl(Opts, Diags);\n\n  // Delete output file if there were errors.\n  if (Failed) {\n    if (Opts.OutputPath != \"-\")\n      sys::fs::remove(Opts.OutputPath);\n    if (!Opts.SplitDwarfOutput.empty() && Opts.SplitDwarfOutput != \"-\")\n      sys::fs::remove(Opts.SplitDwarfOutput);\n  }\n\n  return Failed;\n}\n\nstatic void LLVMErrorHandler(void *UserData, const char *Message,\n                             bool GenCrashDiag) {\n  DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData);\n\n  Diags.Report(diag::err_fe_error_backend) << Message;\n\n  // We cannot recover from llvm errors.\n  sys::Process::Exit(1);\n}\n\nint cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {\n  // Initialize targets and assembly printers/parsers.\n  InitializeAllTargetInfos();\n  InitializeAllTargetMCs();\n  InitializeAllAsmParsers();\n\n  // Construct our diagnostic client.\n  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();\n  TextDiagnosticPrinter *DiagClient\n    = new TextDiagnosticPrinter(errs(), &*DiagOpts);\n  DiagClient->setPrefix(\"clang -cc1as\");\n  IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());\n  DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient);\n\n  // Set an error handler, so that any LLVM backend diagnostics go through our\n  // error handler.\n  ScopedFatalErrorHandler FatalErrorHandler\n    (LLVMErrorHandler, static_cast<void*>(&Diags));\n\n  // Parse the arguments.\n  AssemblerInvocation Asm;\n  if (!AssemblerInvocation::CreateFromArgs(Asm, Argv, Diags))\n    return 1;\n\n  if (Asm.ShowHelp) {\n    getDriverOptTable().printHelp(\n        llvm::outs(), \"clang -cc1as [options] file...\",\n        \"Clang Integrated Assembler\", /*ShowHidden=*/false,\n        /*ShowAllAliases=*/false,\n        llvm::opt::Visibility(driver::options::CC1AsOption));\n\n    return 0;\n  }\n\n  // Honor -version.\n  //\n  // FIXME: Use a better -version message?\n  if (Asm.ShowVersion) {\n    llvm::cl::PrintVersionMessage();\n    return 0;\n  }\n\n  // Honor -mllvm.\n  //\n  // FIXME: Remove this, one day.\n  if (!Asm.LLVMArgs.empty()) {\n    unsigned NumArgs = Asm.LLVMArgs.size();\n    auto Args = std::make_unique<const char*[]>(NumArgs + 2);\n    Args[0] = \"clang (LLVM option parsing)\";\n    for (unsigned i = 0; i != NumArgs; ++i)\n      Args[i + 1] = Asm.LLVMArgs[i].c_str();\n    Args[NumArgs + 1] = nullptr;\n    llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get());\n  }\n\n  // Execute the invocation, unless there were parsing errors.\n  bool Failed = Diags.hasErrorOccurred() || ExecuteAssembler(Asm, Diags);\n\n  // If any timers were active but haven't been destroyed yet, print their\n  // results now.\n  TimerGroup::printAll(errs());\n  TimerGroup::clearAll();\n\n  return !!Failed;\n}\n"
  },
  {
    "path": "builder/cc1as.h",
    "content": "// Source: https://github.com/llvm/llvm-project/blob/main/clang/tools/driver/cc1as_main.cpp\n// See cc1as.cpp for details.\n\n//===-- cc1as.h - Clang Assembler  ----------------------------------------===//\n//\n// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.\n// See https://llvm.org/LICENSE.txt for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n//===----------------------------------------------------------------------===//\n//\n// This is the entry point to the clang -cc1as functionality, which implements\n// the direct interface to the LLVM MC based assembler.\n//\n//===----------------------------------------------------------------------===//\n\n/// Helper class for representing a single invocation of the assembler.\nstruct AssemblerInvocation {\n  /// @name Target Options\n  /// @{\n\n  /// The name of the target triple to assemble for.\n  std::string Triple;\n\n  /// If given, the name of the target CPU to determine which instructions\n  /// are legal.\n  std::string CPU;\n\n  /// The list of target specific features to enable or disable -- this should\n  /// be a list of strings starting with '+' or '-'.\n  std::vector<std::string> Features;\n\n  /// The list of symbol definitions.\n  std::vector<std::string> SymbolDefs;\n\n  /// @}\n  /// @name Language Options\n  /// @{\n\n  std::vector<std::string> IncludePaths;\n  LLVM_PREFERRED_TYPE(bool)\n  unsigned NoInitialTextSection : 1;\n  LLVM_PREFERRED_TYPE(bool)\n  unsigned SaveTemporaryLabels : 1;\n  LLVM_PREFERRED_TYPE(bool)\n  unsigned GenDwarfForAssembly : 1;\n  LLVM_PREFERRED_TYPE(bool)\n  unsigned Dwarf64 : 1;\n  unsigned DwarfVersion;\n  std::string DwarfDebugFlags;\n  std::string DwarfDebugProducer;\n  std::string DebugCompilationDir;\n  llvm::SmallVector<std::pair<std::string, std::string>, 0> DebugPrefixMap;\n  llvm::DebugCompressionType CompressDebugSections =\n      llvm::DebugCompressionType::None;\n  std::string MainFileName;\n  std::string SplitDwarfOutput;\n\n  /// @}\n  /// @name Frontend Options\n  /// @{\n\n  std::string InputFile;\n  std::vector<std::string> LLVMArgs;\n  std::string OutputPath;\n  enum FileType {\n    FT_Asm,  ///< Assembly (.s) output, transliterate mode.\n    FT_Null, ///< No output, for timing purposes.\n    FT_Obj   ///< Object file output.\n  };\n  FileType OutputType;\n  LLVM_PREFERRED_TYPE(bool)\n  unsigned ShowHelp : 1;\n  LLVM_PREFERRED_TYPE(bool)\n  unsigned ShowVersion : 1;\n\n  /// @}\n  /// @name Transliterate Options\n  /// @{\n\n  unsigned OutputAsmVariant;\n  LLVM_PREFERRED_TYPE(bool)\n  unsigned ShowEncoding : 1;\n  LLVM_PREFERRED_TYPE(bool)\n  unsigned ShowInst : 1;\n\n  /// @}\n  /// @name Assembler Options\n  /// @{\n\n  LLVM_PREFERRED_TYPE(bool)\n  unsigned RelaxAll : 1;\n  LLVM_PREFERRED_TYPE(bool)\n  unsigned NoExecStack : 1;\n  LLVM_PREFERRED_TYPE(bool)\n  unsigned FatalWarnings : 1;\n  LLVM_PREFERRED_TYPE(bool)\n  unsigned NoWarn : 1;\n  LLVM_PREFERRED_TYPE(bool)\n  unsigned NoTypeCheck : 1;\n  LLVM_PREFERRED_TYPE(bool)\n  unsigned IncrementalLinkerCompatible : 1;\n  LLVM_PREFERRED_TYPE(bool)\n  unsigned EmbedBitcode : 1;\n\n  /// Whether to emit DWARF unwind info.\n  EmitDwarfUnwindType EmitDwarfUnwind;\n\n  // Whether to emit compact-unwind for non-canonical entries.\n  // Note: maybe overriden by other constraints.\n  LLVM_PREFERRED_TYPE(bool)\n  unsigned EmitCompactUnwindNonCanonical : 1;\n\n  LLVM_PREFERRED_TYPE(bool)\n  unsigned Crel : 1;\n  LLVM_PREFERRED_TYPE(bool)\n  unsigned ImplicitMapsyms : 1;\n\n  LLVM_PREFERRED_TYPE(bool)\n  unsigned X86RelaxRelocations : 1;\n  LLVM_PREFERRED_TYPE(bool)\n  unsigned X86Sse2Avx : 1;\n\n  /// The name of the relocation model to use.\n  std::string RelocationModel;\n\n  /// The ABI targeted by the backend. Specified using -target-abi. Empty\n  /// otherwise.\n  std::string TargetABI;\n\n  /// Darwin target variant triple, the variant of the deployment target\n  /// for which the code is being compiled.\n  std::optional<llvm::Triple> DarwinTargetVariantTriple;\n\n  /// The version of the darwin target variant SDK which was used during the\n  /// compilation\n  llvm::VersionTuple DarwinTargetVariantSDKVersion;\n\n  /// The name of a file to use with \\c .secure_log_unique directives.\n  std::string AsSecureLogFile;\n  /// @}\n\npublic:\n  AssemblerInvocation() {\n    Triple = \"\";\n    NoInitialTextSection = 0;\n    InputFile = \"-\";\n    OutputPath = \"-\";\n    OutputType = FT_Asm;\n    OutputAsmVariant = 0;\n    ShowInst = 0;\n    ShowEncoding = 0;\n    RelaxAll = 0;\n    NoExecStack = 0;\n    FatalWarnings = 0;\n    NoWarn = 0;\n    NoTypeCheck = 0;\n    IncrementalLinkerCompatible = 0;\n    Dwarf64 = 0;\n    DwarfVersion = 0;\n    EmbedBitcode = 0;\n    EmitDwarfUnwind = EmitDwarfUnwindType::Default;\n    EmitCompactUnwindNonCanonical = false;\n    Crel = false;\n    ImplicitMapsyms = 0;\n    X86RelaxRelocations = 0;\n    X86Sse2Avx = 0;\n  }\n\n  static bool CreateFromArgs(AssemblerInvocation &Res,\n                             ArrayRef<const char *> Argv,\n                             DiagnosticsEngine &Diags);\n};\n\nbool ExecuteAssembler(AssemblerInvocation &Opts, DiagnosticsEngine &Diags);\n"
  },
  {
    "path": "builder/cc_test.go",
    "content": "package builder\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n)\n\nfunc TestSplitDepFile(t *testing.T) {\n\tfor i, tc := range []struct {\n\t\tin  string\n\t\tout []string\n\t}{\n\t\t{`deps: foo bar`, []string{\"foo\", \"bar\"}},\n\t\t{`deps: foo \"bar\"`, []string{\"foo\", \"bar\"}},\n\t\t{`deps: \"foo\" bar`, []string{\"foo\", \"bar\"}},\n\t\t{`deps: \"foo bar\"`, []string{\"foo bar\"}},\n\t\t{`deps: \"foo bar\" `, []string{\"foo bar\"}},\n\t\t{\"deps: foo\\nbar\", []string{\"foo\"}},\n\t\t{\"deps: foo \\\\\\nbar\", []string{\"foo\", \"bar\"}},\n\t\t{\"deps: foo\\\\bar \\\\\\nbaz\", []string{\"foo\\\\bar\", \"baz\"}},\n\t\t{\"deps: foo\\\\bar \\\\\\r\\n baz\", []string{\"foo\\\\bar\", \"baz\"}}, // Windows uses CRLF line endings\n\t} {\n\t\tout, err := parseDepFile(tc.in)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"test #%d failed: %v\", i, err)\n\t\t\tcontinue\n\t\t}\n\t\tif !reflect.DeepEqual(out, tc.out) {\n\t\t\tt.Errorf(\"test #%d failed: expected %#v but got %#v\", i, tc.out, out)\n\t\t\tcontinue\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "builder/clang.cpp",
    "content": "//go:build byollvm\n\n#include <clang/Basic/DiagnosticOptions.h>\n#include <clang/CodeGen/CodeGenAction.h>\n#include <clang/Driver/Compilation.h>\n#include <clang/Driver/Driver.h>\n#include <clang/Frontend/CompilerInstance.h>\n#include <clang/Frontend/CompilerInvocation.h>\n#include <clang/Frontend/FrontendDiagnostic.h>\n#include <clang/Frontend/TextDiagnosticPrinter.h>\n#include <clang/FrontendTool/Utils.h>\n#include <llvm/ADT/IntrusiveRefCntPtr.h>\n#include <llvm/Option/Option.h>\n#include <llvm/TargetParser/Host.h>\n\nusing namespace llvm;\nusing namespace clang;\n\n#include \"cc1as.h\"\n\n// This file provides C wrappers for the builtin tools cc1 and cc1as\n// provided by Clang, and calls them as the driver would call them.\n\nextern \"C\" {\n\nbool tinygo_clang_driver(int argc, char **argv) {\n\tstd::vector<const char*> args(argv, argv + argc);\n\n\t// The compiler invocation needs a DiagnosticsEngine so it can report problems\n\tllvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts = new clang::DiagnosticOptions();\n\tclang::TextDiagnosticPrinter DiagnosticPrinter(llvm::errs(), &*DiagOpts);\n\tclang::DiagnosticsEngine Diags(llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs>(new clang::DiagnosticIDs()), &*DiagOpts, &DiagnosticPrinter, false);\n\n\t// Create the clang driver\n\tclang::driver::Driver TheDriver(args[0], llvm::sys::getDefaultTargetTriple(), Diags);\n\n\t// Create the set of actions to perform\n\tstd::unique_ptr<clang::driver::Compilation> C(TheDriver.BuildCompilation(args));\n\tif (!C) {\n\t\treturn false;\n\t}\n\tconst clang::driver::JobList &Jobs = C->getJobs();\n\n\t// There may be more than one job, for example for .S files\n\t// (preprocessor + assembler).\n\tfor (auto Cmd : Jobs) {\n\t\t// Select the tool: cc1 or cc1as.\n\t\tconst llvm::opt::ArgStringList &CCArgs = Cmd.getArguments();\n\n\t\tif (strcmp(*CCArgs.data(), \"-cc1\") == 0) {\n\t\t\t// This is the C frontend.\n\t\t\t// Initialize a compiler invocation object from the clang (-cc1) arguments.\n\t\t\tstd::unique_ptr<clang::CompilerInstance> Clang(new clang::CompilerInstance());\n\t\t\tbool success = clang::CompilerInvocation::CreateFromArgs(\n\t\t\t\t\tClang->getInvocation(),\n\t\t\t\t\tCCArgs,\n\t\t\t\t\tDiags);\n\t\t\tif (!success) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Create the actual diagnostics engine.\n\t\t\tClang->createDiagnostics(*llvm::vfs::getRealFileSystem());\n\t\t\tif (!Clang->hasDiagnostics()) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Execute the frontend actions.\n\t\t\tsuccess = ExecuteCompilerInvocation(Clang.get());\n\t\t\tif (!success) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t} else if (strcmp(*CCArgs.data(), \"-cc1as\") == 0) {\n\t\t\t// This is the assembler frontend. Parse the arguments.\n\t\t\tAssemblerInvocation Asm;\n\t\t\tArrayRef<const char *> Argv = llvm::ArrayRef<const char*>(CCArgs);\n\t\t\tif (!AssemblerInvocation::CreateFromArgs(Asm, Argv.slice(1), Diags))\n\t\t\t\treturn false;\n\n\t\t\t// Execute the invocation, unless there were parsing errors.\n\t\t\tbool failed = Diags.hasErrorOccurred() || ExecuteAssembler(Asm, Diags);\n\t\t\tif (failed) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t} else {\n\t\t\t// Unknown tool, print the tool and exit.\n\t\t\tfprintf(stderr, \"unknown tool: %s\\n\", *CCArgs.data());\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// Commands executed successfully.\n\treturn true;\n}\n\n} // extern \"C\"\n"
  },
  {
    "path": "builder/commands.go",
    "content": "package builder\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"os/exec\"\n\t\"runtime\"\n\t\"strings\"\n\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// Commands lists command alternatives for various operating systems. These\n// commands may have a slightly different name across operating systems and\n// distributions or may not even exist in $PATH, in which case absolute paths\n// may be used.\nvar commands = map[string][]string{}\n\nfunc init() {\n\tllvmMajor := strings.Split(llvm.Version, \".\")[0]\n\tcommands[\"clang\"] = []string{\"clang-\" + llvmMajor}\n\tcommands[\"ld.lld\"] = []string{\"ld.lld-\" + llvmMajor, \"ld.lld\"}\n\tcommands[\"wasm-ld\"] = []string{\"wasm-ld-\" + llvmMajor, \"wasm-ld\"}\n\tcommands[\"lldb\"] = []string{\"lldb-\" + llvmMajor, \"lldb\"}\n\t// Add the path to a Homebrew-installed LLVM for ease of use (no need to\n\t// manually set $PATH).\n\tif runtime.GOOS == \"darwin\" {\n\t\tvar prefix string\n\t\tswitch runtime.GOARCH {\n\t\tcase \"amd64\":\n\t\t\tprefix = \"/usr/local/opt/llvm@\" + llvmMajor + \"/bin/\"\n\t\tcase \"arm64\":\n\t\t\tprefix = \"/opt/homebrew/opt/llvm@\" + llvmMajor + \"/bin/\"\n\t\tdefault:\n\t\t\t// unknown GOARCH\n\t\t\tpanic(fmt.Sprintf(\"unknown GOARCH: %s on darwin\", runtime.GOARCH))\n\t\t}\n\t\tcommands[\"clang\"] = append(commands[\"clang\"], prefix+\"clang-\"+llvmMajor)\n\t\tcommands[\"ld.lld\"] = append(commands[\"ld.lld\"], prefix+\"ld.lld\")\n\t\tcommands[\"wasm-ld\"] = append(commands[\"wasm-ld\"], prefix+\"wasm-ld\")\n\t\tcommands[\"lldb\"] = append(commands[\"lldb\"], prefix+\"lldb\")\n\t}\n\t// Add the path for when LLVM was installed with the installer from\n\t// llvm.org, which by default doesn't add LLVM to the $PATH environment\n\t// variable.\n\tif runtime.GOOS == \"windows\" {\n\t\tcommands[\"clang\"] = append(commands[\"clang\"], \"clang\", \"C:\\\\Program Files\\\\LLVM\\\\bin\\\\clang.exe\")\n\t\tcommands[\"ld.lld\"] = append(commands[\"ld.lld\"], \"lld\", \"C:\\\\Program Files\\\\LLVM\\\\bin\\\\lld.exe\")\n\t\tcommands[\"wasm-ld\"] = append(commands[\"wasm-ld\"], \"C:\\\\Program Files\\\\LLVM\\\\bin\\\\wasm-ld.exe\")\n\t\tcommands[\"lldb\"] = append(commands[\"lldb\"], \"C:\\\\Program Files\\\\LLVM\\\\bin\\\\lldb.exe\")\n\t}\n\t// Add the path to LLVM installed from ports.\n\tif runtime.GOOS == \"freebsd\" {\n\t\tprefix := \"/usr/local/llvm\" + llvmMajor + \"/bin/\"\n\t\tcommands[\"clang\"] = append(commands[\"clang\"], prefix+\"clang-\"+llvmMajor)\n\t\tcommands[\"ld.lld\"] = append(commands[\"ld.lld\"], prefix+\"ld.lld\")\n\t\tcommands[\"wasm-ld\"] = append(commands[\"wasm-ld\"], prefix+\"wasm-ld\")\n\t\tcommands[\"lldb\"] = append(commands[\"lldb\"], prefix+\"lldb\")\n\t}\n}\n\n// LookupCommand looks up the executable name for a given LLVM tool such as\n// clang or wasm-ld. It returns the (relative) command that can be used to\n// invoke the tool or an error if it could not be found.\nfunc LookupCommand(name string) (string, error) {\n\tfor _, cmdName := range commands[name] {\n\t\t_, err := exec.LookPath(cmdName)\n\t\tif err != nil {\n\t\t\tif errors.Unwrap(err) == exec.ErrNotFound {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn cmdName, err\n\t\t}\n\t\treturn cmdName, nil\n\t}\n\treturn \"\", errors.New(\"none of these commands were found in your $PATH: \" + strings.Join(commands[name], \" \"))\n}\n"
  },
  {
    "path": "builder/config.go",
    "content": "package builder\n\nimport (\n\t\"fmt\"\n\t\"runtime\"\n\n\t\"github.com/tinygo-org/tinygo/compileopts\"\n\t\"github.com/tinygo-org/tinygo/goenv\"\n)\n\n// NewConfig builds a new Config object from a set of compiler options. It also\n// loads some information from the environment while doing that. For example, it\n// uses the currently active GOPATH (from the goenv package) to determine the Go\n// version to use.\nfunc NewConfig(options *compileopts.Options) (*compileopts.Config, error) {\n\tspec, err := compileopts.LoadTarget(options)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif options.OpenOCDCommands != nil {\n\t\t// Override the OpenOCDCommands from the target spec if specified on\n\t\t// the command-line\n\t\tspec.OpenOCDCommands = options.OpenOCDCommands\n\t}\n\n\t// Version range supported by TinyGo.\n\tconst minorMin = 19\n\tconst minorMax = 25\n\n\t// Check that we support this Go toolchain version.\n\tgorootMajor, gorootMinor, err := goenv.GetGorootVersion()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif options.GoCompatibility {\n\t\tif gorootMajor != 1 || gorootMinor < minorMin || gorootMinor > minorMax {\n\t\t\t// Note: when this gets updated, also update the Go compatibility matrix:\n\t\t\t// https://github.com/tinygo-org/tinygo-site/blob/dev/content/docs/reference/go-compat-matrix.md\n\t\t\treturn nil, fmt.Errorf(\"requires go version 1.%d through 1.%d, got go%d.%d\", minorMin, minorMax, gorootMajor, gorootMinor)\n\t\t}\n\t}\n\n\t// Check that the Go toolchain version isn't too new, if we haven't been\n\t// compiled with the latest Go version.\n\t// This may be a bit too aggressive: if the newer version doesn't change the\n\t// Go language we will most likely be able to compile it.\n\tbuildMajor, buildMinor, _, err := goenv.Parse(runtime.Version())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif buildMajor != 1 || buildMinor < gorootMinor {\n\t\treturn nil, fmt.Errorf(\"cannot compile with Go toolchain version go%d.%d (TinyGo was built using toolchain version %s)\", gorootMajor, gorootMinor, runtime.Version())\n\t}\n\n\treturn &compileopts.Config{\n\t\tOptions:        options,\n\t\tTarget:         spec,\n\t\tGoMinorVersion: gorootMinor,\n\t\tTestConfig:     options.TestConfig,\n\t}, nil\n}\n"
  },
  {
    "path": "builder/darwin-libsystem.go",
    "content": "package builder\n\nimport (\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/tinygo-org/tinygo/compileopts\"\n\t\"github.com/tinygo-org/tinygo/goenv\"\n)\n\n// Create a job that builds a Darwin libSystem.dylib stub library. This library\n// contains all the symbols needed so that we can link against it, but it\n// doesn't contain any real symbol implementations.\nfunc makeDarwinLibSystemJob(config *compileopts.Config, tmpdir string) *compileJob {\n\treturn &compileJob{\n\t\tdescription: \"compile Darwin libSystem.dylib\",\n\t\trun: func(job *compileJob) (err error) {\n\t\t\tarch := strings.Split(config.Triple(), \"-\")[0]\n\t\t\tjob.result = filepath.Join(tmpdir, \"libSystem.dylib\")\n\t\t\tobjpath := filepath.Join(tmpdir, \"libSystem.o\")\n\t\t\tinpath := filepath.Join(goenv.Get(\"TINYGOROOT\"), \"lib/macos-minimal-sdk/src\", arch, \"libSystem.s\")\n\n\t\t\t// Compile assembly file to object file.\n\t\t\tflags := []string{\n\t\t\t\t\"-nostdlib\",\n\t\t\t\t\"--target=\" + config.Triple(),\n\t\t\t\t\"-c\",\n\t\t\t\t\"-o\", objpath,\n\t\t\t\tinpath,\n\t\t\t}\n\t\t\tif config.Options.PrintCommands != nil {\n\t\t\t\tconfig.Options.PrintCommands(\"clang\", flags...)\n\t\t\t}\n\t\t\terr = runCCompiler(flags...)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\t// Link object file to dynamic library.\n\t\t\tplatformVersion := strings.TrimPrefix(strings.Split(config.Triple(), \"-\")[2], \"macosx\")\n\t\t\tflags = []string{\n\t\t\t\t\"-flavor\", \"darwin\",\n\t\t\t\t\"-demangle\",\n\t\t\t\t\"-dynamic\",\n\t\t\t\t\"-dylib\",\n\t\t\t\t\"-arch\", arch,\n\t\t\t\t\"-platform_version\", \"macos\", platformVersion, platformVersion,\n\t\t\t\t\"-install_name\", \"/usr/lib/libSystem.B.dylib\",\n\t\t\t\t\"-o\", job.result,\n\t\t\t\tobjpath,\n\t\t\t}\n\t\t\tif config.Options.PrintCommands != nil {\n\t\t\t\tconfig.Options.PrintCommands(\"ld.lld\", flags...)\n\t\t\t}\n\t\t\treturn link(\"ld.lld\", flags...)\n\t\t},\n\t}\n}\n"
  },
  {
    "path": "builder/elfpatch.go",
    "content": "package builder\n\nimport (\n\t\"debug/elf\"\n\t\"fmt\"\n\t\"os\"\n)\n\nfunc getElfSectionData(executable string, sectionName string) ([]byte, elf.FileHeader, error) {\n\telfFile, err := elf.Open(executable)\n\tif err != nil {\n\t\treturn nil, elf.FileHeader{}, err\n\t}\n\tdefer elfFile.Close()\n\n\tsection := elfFile.Section(sectionName)\n\tif section == nil {\n\t\treturn nil, elf.FileHeader{}, fmt.Errorf(\"could not find %s section\", sectionName)\n\t}\n\n\tdata, err := section.Data()\n\n\treturn data, elfFile.FileHeader, err\n}\n\nfunc replaceElfSection(executable string, sectionName string, data []byte) error {\n\tfp, err := os.OpenFile(executable, os.O_RDWR, 0)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer fp.Close()\n\n\telfFile, err := elf.Open(executable)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer elfFile.Close()\n\n\tsection := elfFile.Section(sectionName)\n\tif section == nil {\n\t\treturn fmt.Errorf(\"could not find %s section\", sectionName)\n\t}\n\n\t// Implicitly check for compressed sections\n\tif section.Size != section.FileSize {\n\t\treturn fmt.Errorf(\"expected section %s to have identical size and file size, got %d and %d\", sectionName, section.Size, section.FileSize)\n\t}\n\n\t// Only permit complete replacement of section\n\tif section.Size != uint64(len(data)) {\n\t\treturn fmt.Errorf(\"expected section %s to have size %d, was actually %d\", sectionName, len(data), section.Size)\n\t}\n\n\t// Write the replacement section data\n\t_, err = fp.WriteAt(data, int64(section.Offset))\n\treturn err\n}\n"
  },
  {
    "path": "builder/error.go",
    "content": "package builder\n\n// MultiError is a list of multiple errors (actually: diagnostics) returned\n// during LLVM IR generation.\ntype MultiError struct {\n\tImportPath string\n\tErrs       []error\n}\n\nfunc (e *MultiError) Error() string {\n\t// Return the first error, to conform to the error interface. Clients should\n\t// really do a type-assertion on *MultiError.\n\treturn e.Errs[0].Error()\n}\n\n// newMultiError returns a *MultiError if there is more than one error, or\n// returns that error directly when there is only one. Passing an empty slice\n// will return nil (because there is no error).\n// The importPath may be passed if this error is for a single package.\nfunc newMultiError(errs []error, importPath string) error {\n\tswitch len(errs) {\n\tcase 0:\n\t\treturn nil\n\tcase 1:\n\t\treturn errs[0]\n\tdefault:\n\t\treturn &MultiError{importPath, errs}\n\t}\n}\n\n// commandError is an error type to wrap os/exec.Command errors. This provides\n// some more information regarding what went wrong while running a command.\ntype commandError struct {\n\tMsg  string\n\tFile string\n\tErr  error\n}\n\nfunc (e *commandError) Error() string {\n\treturn e.Msg + \" \" + e.File + \": \" + e.Err.Error()\n}\n"
  },
  {
    "path": "builder/esp.go",
    "content": "package builder\n\n// This file implements support for writing ESP image files. These image files\n// are read by the ROM bootloader so have to be in a particular format.\n//\n// In the future, it may be necessary to implement support for other image\n// formats, such as the ESP8266 image formats (again, used by the ROM bootloader\n// to load the firmware).\n\nimport (\n\t\"bytes\"\n\t\"crypto/sha256\"\n\t\"debug/elf\"\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"os\"\n\t\"sort\"\n\t\"strings\"\n)\n\ntype espImageSegment struct {\n\taddr uint32\n\tdata []byte\n}\n\n// makeESPFirmwareImage converts an input ELF file to an image file for an ESP32 or\n// ESP8266 chip. This is a special purpose image format just for the ESP chip\n// family, and is parsed by the on-chip mask ROM bootloader.\n//\n// The following documentation has been used:\n// https://github.com/espressif/esptool/wiki/Firmware-Image-Format\n// https://github.com/espressif/esp-idf/blob/8fbb63c2a701c22ccf4ce249f43aded73e134a34/components/bootloader_support/include/esp_image_format.h#L58\n// https://github.com/espressif/esptool/blob/master/esptool.py\nfunc makeESPFirmwareImage(infile, outfile, format string) error {\n\tinf, err := elf.Open(infile)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer inf.Close()\n\n\t// Load all segments to be written to the image. These are actually ELF\n\t// sections, not true ELF segments (similar to how esptool does it).\n\tvar segments []*espImageSegment\n\tfor _, section := range inf.Sections {\n\t\tif section.Type != elf.SHT_PROGBITS || section.Size == 0 || section.Flags&elf.SHF_ALLOC == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tdata, err := section.Data()\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to read section data: %w\", err)\n\t\t}\n\t\tfor len(data)%4 != 0 {\n\t\t\t// Align segment to 4 bytes.\n\t\t\tdata = append(data, 0)\n\t\t}\n\t\tif uint64(uint32(section.Addr)) != section.Addr {\n\t\t\treturn fmt.Errorf(\"section address too big: 0x%x\", section.Addr)\n\t\t}\n\t\tsegments = append(segments, &espImageSegment{\n\t\t\taddr: uint32(section.Addr),\n\t\t\tdata: data,\n\t\t})\n\t}\n\n\t// Sort the segments by address. This is what esptool does too.\n\tsort.SliceStable(segments, func(i, j int) bool { return segments[i].addr < segments[j].addr })\n\n\t// Calculate checksum over the segment data. This is used in the image\n\t// footer.\n\tchecksum := uint8(0xef)\n\tfor _, segment := range segments {\n\t\tfor _, b := range segment.data {\n\t\t\tchecksum ^= b\n\t\t}\n\t}\n\n\t// Write first to an in-memory buffer, primarily so that we can easily\n\t// calculate a hash over the entire image.\n\t// An added benefit is that we don't need to check for errors all the time.\n\toutf := &bytes.Buffer{}\n\n\t// Separate esp32 and esp32-img. The -img suffix indicates we should make an\n\t// image, not just a binary to be flashed at 0x1000 for example.\n\tchip := format\n\tmakeImage := false\n\tif strings.HasSuffix(format, \"-img\") {\n\t\tmakeImage = true\n\t\tchip = format[:len(format)-len(\"-img\")]\n\t}\n\n\tif makeImage {\n\t\t// The bootloader starts at 0x1000, or 4096.\n\t\t// TinyGo doesn't use a separate bootloader and runs the entire\n\t\t// application in the bootloader location.\n\t\toutf.Write(make([]byte, 4096))\n\t}\n\n\t// Chip IDs. Source:\n\t// https://github.com/espressif/esp-idf/blob/v4.3/components/bootloader_support/include/esp_app_format.h#L22\n\tchip_id := map[string]uint16{\n\t\t\"esp32\":   0x0000,\n\t\t\"esp32c3\": 0x0005,\n\t\t\"esp32s3\": 0x0009,\n\t}[chip]\n\n\t// Image header.\n\tswitch chip {\n\tcase \"esp32\", \"esp32c3\", \"esp32s3\":\n\t\t// Header format:\n\t\t// https://github.com/espressif/esp-idf/blob/v4.3/components/bootloader_support/include/esp_app_format.h#L71\n\t\t// Note: not adding a SHA256 hash as the binary is modified by\n\t\t// esptool.py while flashing and therefore the hash won't be valid\n\t\t// anymore.\n\t\tbinary.Write(outf, binary.LittleEndian, struct {\n\t\t\tmagic          uint8\n\t\t\tsegment_count  uint8\n\t\t\tspi_mode       uint8\n\t\t\tspi_speed_size uint8\n\t\t\tentry_addr     uint32\n\t\t\twp_pin         uint8\n\t\t\tspi_pin_drv    [3]uint8\n\t\t\tchip_id        uint16\n\t\t\tmin_chip_rev   uint8\n\t\t\treserved       [8]uint8\n\t\t\thash_appended  bool\n\t\t}{\n\t\t\tmagic:          0xE9,\n\t\t\tsegment_count:  byte(len(segments)),\n\t\t\tspi_mode:       2,    // ESP_IMAGE_SPI_MODE_DIO\n\t\t\tspi_speed_size: 0x1f, // ESP_IMAGE_SPI_SPEED_80M, ESP_IMAGE_FLASH_SIZE_2MB\n\t\t\tentry_addr:     uint32(inf.Entry),\n\t\t\twp_pin:         0xEE, // disable WP pin\n\t\t\tchip_id:        chip_id,\n\t\t\thash_appended:  true, // add a SHA256 hash\n\t\t})\n\tcase \"esp8266\":\n\t\t// Header format:\n\t\t// https://github.com/espressif/esptool/wiki/Firmware-Image-Format\n\t\t// Basically a truncated version of the ESP32 header.\n\t\tbinary.Write(outf, binary.LittleEndian, struct {\n\t\t\tmagic          uint8\n\t\t\tsegment_count  uint8\n\t\t\tspi_mode       uint8\n\t\t\tspi_speed_size uint8\n\t\t\tentry_addr     uint32\n\t\t}{\n\t\t\tmagic:          0xE9,\n\t\t\tsegment_count:  byte(len(segments)),\n\t\t\tspi_mode:       0,    // irrelevant, replaced by esptool when flashing\n\t\t\tspi_speed_size: 0x20, // spi_speed, spi_size: replaced by esptool when flashing\n\t\t\tentry_addr:     uint32(inf.Entry),\n\t\t})\n\tdefault:\n\t\treturn fmt.Errorf(\"builder: unknown binary format %#v, expected esp32 or esp8266\", format)\n\t}\n\n\t// Write all segments to the image.\n\t// https://github.com/espressif/esptool/wiki/Firmware-Image-Format#segment\n\tfor _, segment := range segments {\n\t\tbinary.Write(outf, binary.LittleEndian, struct {\n\t\t\taddr   uint32\n\t\t\tlength uint32\n\t\t}{\n\t\t\taddr:   segment.addr,\n\t\t\tlength: uint32(len(segment.data)),\n\t\t})\n\t\toutf.Write(segment.data)\n\t}\n\n\t// Footer, including checksum.\n\t// The entire image size must be a multiple of 16, so pad the image to one\n\t// byte less than that before writing the checksum.\n\toutf.Write(make([]byte, 15-outf.Len()%16))\n\toutf.WriteByte(checksum)\n\n\tif chip != \"esp8266\" {\n\t\t// SHA256 hash (to protect against image corruption, not for security).\n\t\thash := sha256.Sum256(outf.Bytes())\n\t\toutf.Write(hash[:])\n\t}\n\n\t// QEMU (or more precisely, qemu-system-xtensa from Espressif) expects the\n\t// image to be a certain size.\n\tif makeImage {\n\t\t// Use a default image size of 4MB.\n\t\tgrow := 4096*1024 - outf.Len()\n\t\tif grow > 0 {\n\t\t\toutf.Write(make([]byte, grow))\n\t\t}\n\t}\n\n\t// Write the image to the output file.\n\treturn os.WriteFile(outfile, outf.Bytes(), 0666)\n}\n"
  },
  {
    "path": "builder/jobs.go",
    "content": "package builder\n\n// This file implements a job runner for the compiler, which runs jobs in\n// parallel while taking care of dependencies.\n\nimport (\n\t\"container/heap\"\n\t\"errors\"\n\t\"fmt\"\n\t\"runtime\"\n\t\"sort\"\n\t\"strings\"\n\t\"time\"\n)\n\n// Set to true to enable logging in the job runner. This may help to debug\n// concurrency or performance issues.\nconst jobRunnerDebug = false\n\n// compileJob is a single compiler job, comparable to a single Makefile target.\n// It is used to orchestrate various compiler tasks that can be run in parallel\n// but that have dependencies and thus have limitations in how they can be run.\ntype compileJob struct {\n\tdescription  string // description, only used for logging\n\tdependencies []*compileJob\n\tresult       string // result (path)\n\trun          func(*compileJob) (err error)\n\terr          error         // error if finished\n\tduration     time.Duration // how long it took to run this job (only set after finishing)\n}\n\n// dummyCompileJob returns a new *compileJob that produces an output without\n// doing anything. This can be useful where a *compileJob producing an output is\n// expected but nothing needs to be done, for example for a load from a cache.\nfunc dummyCompileJob(result string) *compileJob {\n\treturn &compileJob{\n\t\tdescription: \"<dummy>\",\n\t\tresult:      result,\n\t}\n}\n\n// runJobs runs the indicated job and all its dependencies. For every job, all\n// the dependencies are run first. It returns the error of the first job that\n// fails.\n// It runs all jobs in the order of the dependencies slice, depth-first.\n// Therefore, if some jobs are preferred to run before others, they should be\n// ordered as such in the job dependencies.\nfunc runJobs(job *compileJob, sema chan struct{}) error {\n\tif sema == nil {\n\t\t// Have a default, if the semaphore isn't set. This is useful for tests.\n\t\tsema = make(chan struct{}, runtime.NumCPU())\n\t}\n\tif cap(sema) == 0 {\n\t\treturn errors.New(\"cannot run 0 jobs at a time\")\n\t}\n\n\t// Create a slice of jobs to run, where all dependencies are run in order.\n\tjobs := []*compileJob{}\n\taddedJobs := map[*compileJob]struct{}{}\n\tvar addJobs func(*compileJob)\n\taddJobs = func(job *compileJob) {\n\t\tif _, ok := addedJobs[job]; ok {\n\t\t\treturn\n\t\t}\n\t\tfor _, dep := range job.dependencies {\n\t\t\taddJobs(dep)\n\t\t}\n\t\tjobs = append(jobs, job)\n\t\taddedJobs[job] = struct{}{}\n\t}\n\taddJobs(job)\n\n\twaiting := make(map[*compileJob]map[*compileJob]struct{}, len(jobs))\n\tdependents := make(map[*compileJob][]*compileJob, len(jobs))\n\tcompileJobs := make(map[*compileJob]int)\n\tvar ready intHeap\n\tfor i, job := range jobs {\n\t\tcompileJobs[job] = i\n\t\tif len(job.dependencies) == 0 {\n\t\t\t// This job is ready to run.\n\t\t\tready.Push(i)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Construct a map for dependencies which the job is currently waiting on.\n\t\twaitDeps := make(map[*compileJob]struct{})\n\t\twaiting[job] = waitDeps\n\n\t\t// Add the job to the dependents list of each dependency.\n\t\tfor _, dep := range job.dependencies {\n\t\t\tdependents[dep] = append(dependents[dep], job)\n\t\t\twaitDeps[dep] = struct{}{}\n\t\t}\n\t}\n\n\t// Create a channel to accept notifications of completion.\n\tdoneChan := make(chan *compileJob)\n\n\t// Send each job in the jobs slice to a worker, taking care of job dependencies.\n\tnumRunningJobs := 0\n\tvar totalTime time.Duration\n\tstart := time.Now()\n\tfor len(ready.IntSlice) > 0 || numRunningJobs != 0 {\n\t\tvar completed *compileJob\n\t\tif len(ready.IntSlice) > 0 {\n\t\t\tselect {\n\t\t\tcase sema <- struct{}{}:\n\t\t\t\t// Start a job.\n\t\t\t\tjob := jobs[heap.Pop(&ready).(int)]\n\t\t\t\tif jobRunnerDebug {\n\t\t\t\t\tfmt.Println(\"## start:   \", job.description)\n\t\t\t\t}\n\t\t\t\tgo runJob(job, doneChan)\n\t\t\t\tnumRunningJobs++\n\t\t\t\tcontinue\n\n\t\t\tcase completed = <-doneChan:\n\t\t\t\t// A job completed.\n\t\t\t}\n\t\t} else {\n\t\t\t// Wait for a job to complete.\n\t\t\tcompleted = <-doneChan\n\t\t}\n\t\tnumRunningJobs--\n\t\t<-sema\n\t\tif jobRunnerDebug {\n\t\t\tfmt.Println(\"## finished:\", completed.description, \"(time \"+completed.duration.String()+\")\")\n\t\t}\n\t\tif completed.err != nil {\n\t\t\t// Wait for any current jobs to finish.\n\t\t\tfor numRunningJobs != 0 {\n\t\t\t\t<-doneChan\n\t\t\t\tnumRunningJobs--\n\t\t\t}\n\n\t\t\t// The build failed.\n\t\t\treturn completed.err\n\t\t}\n\n\t\t// Update total run time.\n\t\ttotalTime += completed.duration\n\n\t\t// Update dependent jobs.\n\t\tfor _, j := range dependents[completed] {\n\t\t\twait := waiting[j]\n\t\t\tdelete(wait, completed)\n\t\t\tif len(wait) == 0 {\n\t\t\t\t// This job is now ready to run.\n\t\t\t\tready.Push(compileJobs[j])\n\t\t\t\tdelete(waiting, j)\n\t\t\t}\n\t\t}\n\t}\n\tif len(waiting) != 0 {\n\t\t// There is a dependency cycle preventing some jobs from running.\n\t\treturn errDependencyCycle{waiting}\n\t}\n\n\t// Some statistics, if debugging.\n\tif jobRunnerDebug {\n\t\t// Total duration of running all jobs.\n\t\tduration := time.Since(start)\n\t\tfmt.Println(\"## total:   \", duration)\n\n\t\t// The individual time of each job combined. On a multicore system, this\n\t\t// should be lower than the total above.\n\t\tfmt.Println(\"## job sum: \", totalTime)\n\t}\n\n\treturn nil\n}\n\ntype errDependencyCycle struct {\n\twaiting map[*compileJob]map[*compileJob]struct{}\n}\n\nfunc (err errDependencyCycle) Error() string {\n\twaits := make([]string, 0, len(err.waiting))\n\tfor j, wait := range err.waiting {\n\t\tdeps := make([]string, 0, len(wait))\n\t\tfor dep := range wait {\n\t\t\tdeps = append(deps, dep.description)\n\t\t}\n\t\tsort.Strings(deps)\n\n\t\twaits = append(waits, fmt.Sprintf(\"\\t%s is waiting for [%s]\",\n\t\t\tj.description, strings.Join(deps, \", \"),\n\t\t))\n\t}\n\tsort.Strings(waits)\n\treturn \"deadlock:\\n\" + strings.Join(waits, \"\\n\")\n}\n\ntype intHeap struct {\n\tsort.IntSlice\n}\n\nfunc (h *intHeap) Push(x interface{}) {\n\th.IntSlice = append(h.IntSlice, x.(int))\n}\n\nfunc (h *intHeap) Pop() interface{} {\n\tx := h.IntSlice[len(h.IntSlice)-1]\n\th.IntSlice = h.IntSlice[:len(h.IntSlice)-1]\n\treturn x\n}\n\n// runJob runs a compile job and notifies doneChan of completion.\nfunc runJob(job *compileJob, doneChan chan *compileJob) {\n\tstart := time.Now()\n\tif job.run != nil {\n\t\terr := job.run(job)\n\t\tif err != nil {\n\t\t\tjob.err = err\n\t\t}\n\t}\n\tjob.duration = time.Since(start)\n\tdoneChan <- job\n}\n"
  },
  {
    "path": "builder/library.go",
    "content": "package builder\n\nimport (\n\t\"errors\"\n\t\"io/fs\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/tinygo-org/tinygo/compileopts\"\n\t\"github.com/tinygo-org/tinygo/goenv\"\n)\n\n// Library is a container for information about a single C library, such as a\n// compiler runtime or libc.\n//\n// Note: whenever a library gets changed, the version in compileopts/config.go\n// probably also needs to be incremented.\ntype Library struct {\n\t// The library name, such as compiler-rt or picolibc.\n\tname string\n\n\t// makeHeaders creates a header include dir for the library\n\tmakeHeaders func(target, includeDir string) error\n\n\t// cflags returns the C flags specific to this library\n\tcflags func(target, headerPath string) []string\n\n\t// cflagsForFile returns additional C flags for a particular source file.\n\tcflagsForFile func(path string) []string\n\n\t// needsLibc is set to true if this library needs libc headers.\n\tneedsLibc bool\n\n\t// The source directory.\n\tsourceDir func() string\n\n\t// The source files, relative to sourceDir.\n\tlibrarySources func(target string, libcNeedsMalloc bool) ([]string, error)\n\n\t// The source code for the crt1.o file, relative to sourceDir.\n\tcrt1Source string\n}\n\n// load returns a compile job to build this library file for the given target\n// and CPU. It may return a dummy compileJob if the library build is already\n// cached. The path is stored as job.result but is only valid after the job has\n// been run.\n// The provided tmpdir will be used to store intermediary files and possibly the\n// output archive file, it is expected to be removed after use.\n// As a side effect, this call creates the library header files if they didn't\n// exist yet.\nfunc (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJob, abortLock func(), err error) {\n\toutdir := config.LibraryPath(l.name)\n\tarchiveFilePath := filepath.Join(outdir, \"lib.a\")\n\n\t// Create a lock on the output (if supported).\n\t// This is a bit messy, but avoids a deadlock because it is ordered consistently with other library loads within a build.\n\toutname := filepath.Base(outdir)\n\tunlock := lock(filepath.Join(goenv.Get(\"GOCACHE\"), outname+\".lock\"))\n\tvar ok bool\n\tdefer func() {\n\t\tif !ok {\n\t\t\tunlock()\n\t\t}\n\t}()\n\n\t// Try to fetch this library from the cache.\n\tif _, err := os.Stat(archiveFilePath); err == nil {\n\t\treturn dummyCompileJob(archiveFilePath), func() {}, nil\n\t}\n\t// Cache miss, build it now.\n\n\t// Create the destination directory where the components of this library\n\t// (lib.a file, include directory) are placed.\n\terr = os.MkdirAll(filepath.Join(goenv.Get(\"GOCACHE\"), outname), 0o777)\n\tif err != nil {\n\t\t// Could not create directory (and not because it already exists).\n\t\treturn nil, nil, err\n\t}\n\n\t// Make headers if needed.\n\theaderPath := filepath.Join(outdir, \"include\")\n\ttarget := config.Triple()\n\tif l.makeHeaders != nil {\n\t\tif _, err = os.Stat(headerPath); err != nil {\n\t\t\ttemporaryHeaderPath, err := os.MkdirTemp(outdir, \"include.tmp*\")\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, err\n\t\t\t}\n\t\t\tdefer os.RemoveAll(temporaryHeaderPath)\n\t\t\terr = l.makeHeaders(target, temporaryHeaderPath)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, err\n\t\t\t}\n\t\t\terr = os.Chmod(temporaryHeaderPath, 0o755) // TempDir uses 0o700 by default\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, err\n\t\t\t}\n\t\t\terr = os.Rename(temporaryHeaderPath, headerPath)\n\t\t\tif err != nil {\n\t\t\t\tswitch {\n\t\t\t\tcase errors.Is(err, fs.ErrExist):\n\t\t\t\t\t// Another invocation of TinyGo also seems to have already created the headers.\n\n\t\t\t\tcase runtime.GOOS == \"windows\" && errors.Is(err, fs.ErrPermission):\n\t\t\t\t\t// On Windows, a rename with a destination directory that already\n\t\t\t\t\t// exists does not result in an IsExist error, but rather in an\n\t\t\t\t\t// access denied error. To be sure, check for this case by checking\n\t\t\t\t\t// whether the target directory exists.\n\t\t\t\t\tif _, err := os.Stat(headerPath); err == nil {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tfallthrough\n\n\t\t\t\tdefault:\n\t\t\t\t\treturn nil, nil, err\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tremapDir := filepath.Join(os.TempDir(), \"tinygo-\"+l.name)\n\tdir := filepath.Join(tmpdir, \"build-lib-\"+l.name)\n\terr = os.Mkdir(dir, 0777)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\t// Precalculate the flags to the compiler invocation.\n\t// Note: -fdebug-prefix-map is necessary to make the output archive\n\t// reproducible. Otherwise the temporary directory is stored in the archive\n\t// itself, which varies each run.\n\targs := append(l.cflags(target, headerPath), \"-c\", \"-Oz\", \"-gdwarf-4\", \"-ffunction-sections\", \"-fdata-sections\", \"-Wno-macro-redefined\", \"--target=\"+target, \"-fdebug-prefix-map=\"+dir+\"=\"+remapDir)\n\tresourceDir := goenv.ClangResourceDir(false)\n\tif resourceDir != \"\" {\n\t\targs = append(args, \"-resource-dir=\"+resourceDir)\n\t}\n\tcpu := config.CPU()\n\tif cpu != \"\" {\n\t\t// X86 has deprecated the -mcpu flag, so we need to use -march instead.\n\t\t// However, ARM has not done this.\n\t\tif strings.HasPrefix(target, \"i386\") || strings.HasPrefix(target, \"x86_64\") {\n\t\t\targs = append(args, \"-march=\"+cpu)\n\t\t} else if strings.HasPrefix(target, \"avr\") {\n\t\t\targs = append(args, \"-mmcu=\"+cpu)\n\t\t} else {\n\t\t\targs = append(args, \"-mcpu=\"+cpu)\n\t\t}\n\t}\n\tif config.ABI() != \"\" {\n\t\targs = append(args, \"-mabi=\"+config.ABI())\n\t}\n\tswitch compileopts.CanonicalArchName(target) {\n\tcase \"arm\":\n\t\tif strings.Split(target, \"-\")[2] == \"linux\" {\n\t\t\targs = append(args, \"-fno-unwind-tables\", \"-fno-asynchronous-unwind-tables\")\n\t\t} else {\n\t\t\targs = append(args, \"-fshort-enums\", \"-fomit-frame-pointer\", \"-mfloat-abi=soft\", \"-fno-unwind-tables\", \"-fno-asynchronous-unwind-tables\")\n\t\t}\n\tcase \"avr\":\n\t\t// AVR defaults to C float and double both being 32-bit. This deviates\n\t\t// from what most code (and certainly compiler-rt) expects. So we need\n\t\t// to force the compiler to use 64-bit floating point numbers for\n\t\t// double.\n\t\targs = append(args, \"-mdouble=64\")\n\tcase \"riscv32\":\n\t\targs = append(args, \"-march=rv32imac\", \"-fforce-enable-int128\")\n\tcase \"riscv64\":\n\t\targs = append(args, \"-march=rv64gc\")\n\tcase \"mips\":\n\t\targs = append(args, \"-fno-pic\")\n\t}\n\tif config.Target.SoftFloat {\n\t\t// Use softfloat instead of floating point instructions. This is\n\t\t// supported on many architectures.\n\t\targs = append(args, \"-msoft-float\")\n\t} else {\n\t\tif strings.HasPrefix(target, \"armv5\") {\n\t\t\t// On ARMv5 we need to explicitly enable hardware floating point\n\t\t\t// instructions: Clang appears to assume the hardware doesn't have a\n\t\t\t// FPU otherwise.\n\t\t\targs = append(args, \"-mfpu=vfpv2\")\n\t\t}\n\t}\n\tif l.needsLibc {\n\t\targs = append(args, config.LibcCFlags()...)\n\t}\n\n\tvar once sync.Once\n\n\t// Create job to put all the object files in a single archive. This archive\n\t// file is the (static) library file.\n\tvar objs []string\n\tjob = &compileJob{\n\t\tdescription: \"ar \" + l.name + \"/lib.a\",\n\t\tresult:      filepath.Join(goenv.Get(\"GOCACHE\"), outname, \"lib.a\"),\n\t\trun: func(*compileJob) error {\n\t\t\tdefer once.Do(unlock)\n\n\t\t\t// Create an archive of all object files.\n\t\t\tf, err := os.CreateTemp(outdir, \"libc.a.tmp*\")\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\terr = makeArchive(f, objs)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\terr = f.Close()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\terr = os.Chmod(f.Name(), 0o644) // TempFile uses 0o600 by default\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\t// Store this archive in the cache.\n\t\t\treturn os.Rename(f.Name(), archiveFilePath)\n\t\t},\n\t}\n\n\tsourceDir := l.sourceDir()\n\n\t// Create jobs to compile all sources. These jobs are depended upon by the\n\t// archive job above, so must be run first.\n\tpaths, err := l.librarySources(target, config.LibcNeedsMalloc())\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tfor _, path := range paths {\n\t\t// Strip leading \"../\" parts off the path.\n\t\tpath := path\n\t\tcleanpath := path\n\t\tfor strings.HasPrefix(cleanpath, \"../\") {\n\t\t\tcleanpath = cleanpath[3:]\n\t\t}\n\t\tsrcpath := filepath.Join(sourceDir, path)\n\t\tobjpath := filepath.Join(dir, cleanpath+\".o\")\n\t\tos.MkdirAll(filepath.Dir(objpath), 0o777)\n\t\tobjs = append(objs, objpath)\n\t\tobjfile := &compileJob{\n\t\t\tdescription: \"compile \" + srcpath,\n\t\t\trun: func(*compileJob) error {\n\t\t\t\tvar compileArgs []string\n\t\t\t\tcompileArgs = append(compileArgs, args...)\n\t\t\t\tif l.cflagsForFile != nil {\n\t\t\t\t\tcompileArgs = append(compileArgs, l.cflagsForFile(path)...)\n\t\t\t\t}\n\t\t\t\tcompileArgs = append(compileArgs, \"-o\", objpath, srcpath)\n\t\t\t\tif config.Options.PrintCommands != nil {\n\t\t\t\t\tconfig.Options.PrintCommands(\"clang\", compileArgs...)\n\t\t\t\t}\n\t\t\t\terr := runCCompiler(compileArgs...)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn &commandError{\"failed to build\", srcpath, err}\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t},\n\t\t}\n\t\tjob.dependencies = append(job.dependencies, objfile)\n\t}\n\n\t// Create crt1.o job, if needed.\n\t// Add this as a (fake) dependency to the ar file so it gets compiled.\n\t// (It could be done in parallel with creating the ar file, but it probably\n\t// won't make much of a difference in speed).\n\tif l.crt1Source != \"\" {\n\t\tsrcpath := filepath.Join(sourceDir, l.crt1Source)\n\t\tcrt1Job := &compileJob{\n\t\t\tdescription: \"compile \" + srcpath,\n\t\t\trun: func(*compileJob) error {\n\t\t\t\tvar compileArgs []string\n\t\t\t\tcompileArgs = append(compileArgs, args...)\n\t\t\t\ttmpfile, err := os.CreateTemp(outdir, \"crt1.o.tmp*\")\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\ttmpfile.Close()\n\t\t\t\tcompileArgs = append(compileArgs, \"-o\", tmpfile.Name(), srcpath)\n\t\t\t\tif config.Options.PrintCommands != nil {\n\t\t\t\t\tconfig.Options.PrintCommands(\"clang\", compileArgs...)\n\t\t\t\t}\n\t\t\t\terr = runCCompiler(compileArgs...)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn &commandError{\"failed to build\", srcpath, err}\n\t\t\t\t}\n\t\t\t\treturn os.Rename(tmpfile.Name(), filepath.Join(outdir, \"crt1.o\"))\n\t\t\t},\n\t\t}\n\t\tjob.dependencies = append(job.dependencies, crt1Job)\n\t}\n\n\tok = true\n\treturn job, func() {\n\t\tonce.Do(unlock)\n\t}, nil\n}\n"
  },
  {
    "path": "builder/lld.cpp",
    "content": "//go:build byollvm\n\n// This file provides C wrappers for liblld.\n\n#include <lld/Common/Driver.h>\n#include <llvm/Support/Parallel.h>\n\nLLD_HAS_DRIVER(coff)\nLLD_HAS_DRIVER(elf)\nLLD_HAS_DRIVER(mingw)\nLLD_HAS_DRIVER(macho)\nLLD_HAS_DRIVER(wasm)\n\nstatic void configure() {\n#if _WIN64\n\t// This is a hack to work around a hang in the LLD linker on Windows, with\n\t// -DLLVM_ENABLE_THREADS=ON. It has a similar effect as the -threads=1\n\t// linker flag, but with support for the COFF linker.\n\tllvm::parallel::strategy = llvm::hardware_concurrency(1);\n#endif\n}\n\nextern \"C\" {\n\nbool tinygo_link(int argc, char **argv) {\n\tconfigure();\n\tstd::vector<const char*> args(argv, argv + argc);\n\tlld::Result r = lld::lldMain(args, llvm::outs(), llvm::errs(), LLD_ALL_DRIVERS);\n\treturn !r.retCode;\n}\n\n} // external \"C\"\n"
  },
  {
    "path": "builder/mingw-w64.go",
    "content": "package builder\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/tinygo-org/tinygo/goenv\"\n)\n\nvar libMinGW = Library{\n\tname: \"mingw-w64\",\n\tmakeHeaders: func(target, includeDir string) error {\n\t\t// copy _mingw.h\n\t\tsrcDir := filepath.Join(goenv.Get(\"TINYGOROOT\"), \"lib\", \"mingw-w64\")\n\t\toutf, err := os.Create(includeDir + \"/_mingw.h\")\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdefer outf.Close()\n\t\tinf, err := os.Open(srcDir + \"/mingw-w64-headers/crt/_mingw.h.in\")\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\t_, err = io.Copy(outf, inf)\n\t\treturn err\n\t},\n\tsourceDir: func() string { return filepath.Join(goenv.Get(\"TINYGOROOT\"), \"lib/mingw-w64\") },\n\tcflags: func(target, headerPath string) []string {\n\t\tmingwDir := filepath.Join(goenv.Get(\"TINYGOROOT\"), \"lib/mingw-w64\")\n\t\tflags := []string{\n\t\t\t\"-nostdlibinc\",\n\t\t\t\"-isystem\", mingwDir + \"/mingw-w64-crt/include\",\n\t\t\t\"-isystem\", mingwDir + \"/mingw-w64-headers/crt\",\n\t\t\t\"-isystem\", mingwDir + \"/mingw-w64-headers/include\",\n\t\t\t\"-I\", mingwDir + \"/mingw-w64-headers/defaults/include\",\n\t\t\t\"-I\" + headerPath,\n\t\t}\n\t\tif strings.Split(target, \"-\")[0] == \"i386\" {\n\t\t\tflags = append(flags,\n\t\t\t\t\"-D__MSVCRT_VERSION__=0x700\", // Microsoft Visual C++ .NET 2002\n\t\t\t\t\"-D_WIN32_WINNT=0x0501\",      // target Windows XP\n\t\t\t\t\"-D_CRTBLD\",\n\t\t\t\t\"-Wno-pragma-pack\",\n\t\t\t)\n\t\t}\n\t\treturn flags\n\t},\n\tlibrarySources: func(target string, _ bool) ([]string, error) {\n\t\t// These files are needed so that printf and the like are supported.\n\t\tvar sources []string\n\t\tif strings.Split(target, \"-\")[0] == \"i386\" {\n\t\t\t// Old 32-bit x86 systems use msvcrt.dll.\n\t\t\tsources = []string{\n\t\t\t\t\"mingw-w64-crt/crt/pseudo-reloc.c\",\n\t\t\t\t\"mingw-w64-crt/gdtoa/dmisc.c\",\n\t\t\t\t\"mingw-w64-crt/gdtoa/gdtoa.c\",\n\t\t\t\t\"mingw-w64-crt/gdtoa/gmisc.c\",\n\t\t\t\t\"mingw-w64-crt/gdtoa/misc.c\",\n\t\t\t\t\"mingw-w64-crt/math/x86/exp2.S\",\n\t\t\t\t\"mingw-w64-crt/math/x86/trunc.S\",\n\t\t\t\t\"mingw-w64-crt/misc/___mb_cur_max_func.c\",\n\t\t\t\t\"mingw-w64-crt/misc/lc_locale_func.c\",\n\t\t\t\t\"mingw-w64-crt/misc/mbrtowc.c\",\n\t\t\t\t\"mingw-w64-crt/misc/strnlen.c\",\n\t\t\t\t\"mingw-w64-crt/misc/wcrtomb.c\",\n\t\t\t\t\"mingw-w64-crt/misc/wcsnlen.c\",\n\t\t\t\t\"mingw-w64-crt/stdio/acrt_iob_func.c\",\n\t\t\t\t\"mingw-w64-crt/stdio/mingw_lock.c\",\n\t\t\t\t\"mingw-w64-crt/stdio/mingw_pformat.c\",\n\t\t\t\t\"mingw-w64-crt/stdio/mingw_vfprintf.c\",\n\t\t\t\t\"mingw-w64-crt/stdio/mingw_vsnprintf.c\",\n\t\t\t}\n\t\t} else {\n\t\t\t// Anything somewhat modern (amd64, arm64) uses UCRT.\n\t\t\tsources = []string{\n\t\t\t\t\"mingw-w64-crt/stdio/ucrt_fprintf.c\",\n\t\t\t\t\"mingw-w64-crt/stdio/ucrt_fwprintf.c\",\n\t\t\t\t\"mingw-w64-crt/stdio/ucrt_printf.c\",\n\t\t\t\t\"mingw-w64-crt/stdio/ucrt_snprintf.c\",\n\t\t\t\t\"mingw-w64-crt/stdio/ucrt_sprintf.c\",\n\t\t\t\t\"mingw-w64-crt/stdio/ucrt_vfprintf.c\",\n\t\t\t\t\"mingw-w64-crt/stdio/ucrt_vprintf.c\",\n\t\t\t\t\"mingw-w64-crt/stdio/ucrt_vsnprintf.c\",\n\t\t\t\t\"mingw-w64-crt/stdio/ucrt_vsprintf.c\",\n\t\t\t}\n\t\t}\n\t\treturn sources, nil\n\t},\n}\n\n// makeMinGWExtraLibs returns a slice of jobs to import the correct .dll\n// libraries. This is done by converting input .def files to .lib files which\n// can then be linked as usual.\n//\n// TODO: cache the result. At the moment, it costs a few hundred milliseconds to\n// compile these files.\nfunc makeMinGWExtraLibs(tmpdir, goarch string) []*compileJob {\n\tvar jobs []*compileJob\n\troot := goenv.Get(\"TINYGOROOT\")\n\tvar libs []string\n\tif goarch == \"386\" {\n\t\tlibs = []string{\n\t\t\t// x86 uses msvcrt.dll instead of UCRT for compatibility with old\n\t\t\t// Windows versions.\n\t\t\t\"advapi32.def.in\",\n\t\t\t\"kernel32.def.in\",\n\t\t\t\"msvcrt.def.in\",\n\t\t}\n\t} else {\n\t\t// Use the modernized UCRT on new systems.\n\t\t// Normally all the api-ms-win-crt-*.def files are all compiled to a\n\t\t// single .lib file. But to simplify things, we're going to leave them\n\t\t// as separate files.\n\t\tlibs = []string{\n\t\t\t\"advapi32.def.in\",\n\t\t\t\"kernel32.def.in\",\n\t\t\t\"api-ms-win-crt-conio-l1-1-0.def\",\n\t\t\t\"api-ms-win-crt-convert-l1-1-0.def.in\",\n\t\t\t\"api-ms-win-crt-environment-l1-1-0.def\",\n\t\t\t\"api-ms-win-crt-filesystem-l1-1-0.def\",\n\t\t\t\"api-ms-win-crt-heap-l1-1-0.def\",\n\t\t\t\"api-ms-win-crt-locale-l1-1-0.def\",\n\t\t\t\"api-ms-win-crt-math-l1-1-0.def.in\",\n\t\t\t\"api-ms-win-crt-multibyte-l1-1-0.def\",\n\t\t\t\"api-ms-win-crt-private-l1-1-0.def.in\",\n\t\t\t\"api-ms-win-crt-process-l1-1-0.def\",\n\t\t\t\"api-ms-win-crt-runtime-l1-1-0.def.in\",\n\t\t\t\"api-ms-win-crt-stdio-l1-1-0.def\",\n\t\t\t\"api-ms-win-crt-string-l1-1-0.def\",\n\t\t\t\"api-ms-win-crt-time-l1-1-0.def\",\n\t\t\t\"api-ms-win-crt-utility-l1-1-0.def\",\n\t\t}\n\t}\n\tfor _, name := range libs {\n\t\toutpath := filepath.Join(tmpdir, filepath.Base(name)+\".lib\")\n\t\tinpath := filepath.Join(root, \"lib/mingw-w64/mingw-w64-crt/lib-common/\"+name)\n\t\tjob := &compileJob{\n\t\t\tdescription: \"create lib file \" + inpath,\n\t\t\tresult:      outpath,\n\t\t\trun: func(job *compileJob) error {\n\t\t\t\tdefpath := inpath\n\t\t\t\tvar archDef, emulation string\n\t\t\t\tswitch goarch {\n\t\t\t\tcase \"386\":\n\t\t\t\t\tarchDef = \"-DDEF_I386\"\n\t\t\t\t\temulation = \"i386pe\"\n\t\t\t\tcase \"amd64\":\n\t\t\t\t\tarchDef = \"-DDEF_X64\"\n\t\t\t\t\temulation = \"i386pep\"\n\t\t\t\tcase \"arm64\":\n\t\t\t\t\tarchDef = \"-DDEF_ARM64\"\n\t\t\t\t\temulation = \"arm64pe\"\n\t\t\t\tdefault:\n\t\t\t\t\treturn fmt.Errorf(\"unsupported architecture for mingw-w64: %s\", goarch)\n\t\t\t\t}\n\t\t\t\tif strings.HasSuffix(inpath, \".in\") {\n\t\t\t\t\t// .in files need to be preprocessed by a preprocessor (-E)\n\t\t\t\t\t// first.\n\t\t\t\t\tdefpath = outpath + \".def\"\n\t\t\t\t\terr := runCCompiler(\"-E\", \"-x\", \"c\", \"-Wp,-w\", \"-P\", archDef, \"-DDATA\", \"-o\", defpath, inpath, \"-I\"+goenv.Get(\"TINYGOROOT\")+\"/lib/mingw-w64/mingw-w64-crt/def-include/\")\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn link(\"ld.lld\", \"-m\", emulation, \"-o\", outpath, defpath)\n\t\t\t},\n\t\t}\n\t\tjobs = append(jobs, job)\n\t}\n\treturn jobs\n}\n"
  },
  {
    "path": "builder/musl.go",
    "content": "package builder\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"github.com/tinygo-org/tinygo/compileopts\"\n\t\"github.com/tinygo-org/tinygo/goenv\"\n)\n\n// Create the alltypes.h file from the appropriate alltypes.h.in files.\nfunc buildMuslAllTypes(arch, muslDir, outputBitsDir string) error {\n\t// Create the file alltypes.h.\n\tf, err := os.Create(filepath.Join(outputBitsDir, \"alltypes.h\"))\n\tif err != nil {\n\t\treturn err\n\t}\n\tinfiles := []string{\n\t\tfilepath.Join(muslDir, \"arch\", arch, \"bits\", \"alltypes.h.in\"),\n\t\tfilepath.Join(muslDir, \"include\", \"alltypes.h.in\"),\n\t}\n\tfor _, infile := range infiles {\n\t\tdata, err := os.ReadFile(infile)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tlines := strings.Split(string(data), \"\\n\")\n\t\tfor _, line := range lines {\n\t\t\tif strings.HasPrefix(line, \"TYPEDEF \") {\n\t\t\t\tmatches := regexp.MustCompile(`TYPEDEF (.*) ([^ ]*);`).FindStringSubmatch(line)\n\t\t\t\tvalue := matches[1]\n\t\t\t\tname := matches[2]\n\t\t\t\tline = fmt.Sprintf(\"#if defined(__NEED_%s) && !defined(__DEFINED_%s)\\ntypedef %s %s;\\n#define __DEFINED_%s\\n#endif\\n\", name, name, value, name, name)\n\t\t\t}\n\t\t\tif strings.HasPrefix(line, \"STRUCT \") {\n\t\t\t\tmatches := regexp.MustCompile(`STRUCT * ([^ ]*) (.*);`).FindStringSubmatch(line)\n\t\t\t\tname := matches[1]\n\t\t\t\tvalue := matches[2]\n\t\t\t\tline = fmt.Sprintf(\"#if defined(__NEED_struct_%s) && !defined(__DEFINED_struct_%s)\\nstruct %s %s;\\n#define __DEFINED_struct_%s\\n#endif\\n\", name, name, name, value, name)\n\t\t\t}\n\t\t\t_, err := f.WriteString(line + \"\\n\")\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\treturn f.Close()\n}\n\nvar libMusl = Library{\n\tname: \"musl\",\n\tmakeHeaders: func(target, includeDir string) error {\n\t\tbits := filepath.Join(includeDir, \"bits\")\n\t\terr := os.Mkdir(bits, 0777)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tarch := compileopts.MuslArchitecture(target)\n\t\tmuslDir := filepath.Join(goenv.Get(\"TINYGOROOT\"), \"lib\", \"musl\")\n\n\t\terr = buildMuslAllTypes(arch, muslDir, bits)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// Create the file syscall.h.\n\t\tf, err := os.Create(filepath.Join(bits, \"syscall.h\"))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdata, err := os.ReadFile(filepath.Join(muslDir, \"arch\", arch, \"bits\", \"syscall.h.in\"))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\t_, err = f.Write(bytes.ReplaceAll(data, []byte(\"__NR_\"), []byte(\"SYS_\")))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tf.Close()\n\n\t\treturn nil\n\t},\n\tcflags: func(target, headerPath string) []string {\n\t\tarch := compileopts.MuslArchitecture(target)\n\t\tmuslDir := filepath.Join(goenv.Get(\"TINYGOROOT\"), \"lib/musl\")\n\t\tcflags := []string{\n\t\t\t\"-std=c99\",            // same as in musl\n\t\t\t\"-D_XOPEN_SOURCE=700\", // same as in musl\n\t\t\t// Musl triggers some warnings and we don't want to show any\n\t\t\t// warnings while compiling (only errors or silence), so disable\n\t\t\t// specific warnings that are triggered in musl.\n\t\t\t\"-Werror\",\n\t\t\t\"-Wno-logical-op-parentheses\",\n\t\t\t\"-Wno-bitwise-op-parentheses\",\n\t\t\t\"-Wno-shift-op-parentheses\",\n\t\t\t\"-Wno-ignored-attributes\",\n\t\t\t\"-Wno-string-plus-int\",\n\t\t\t\"-Wno-ignored-pragmas\",\n\t\t\t\"-Wno-tautological-constant-out-of-range-compare\",\n\t\t\t\"-Wno-deprecated-non-prototype\",\n\t\t\t\"-Wno-format\",\n\t\t\t\"-Wno-parentheses\",\n\t\t\t\"-Qunused-arguments\",\n\t\t\t// Select include dirs. Don't include standard library includes\n\t\t\t// (that would introduce host dependencies and other complications),\n\t\t\t// but do include all the include directories expected by musl.\n\t\t\t\"-nostdlibinc\",\n\t\t\t\"-I\" + muslDir + \"/arch/\" + arch,\n\t\t\t\"-I\" + muslDir + \"/arch/generic\",\n\t\t\t\"-I\" + muslDir + \"/src/include\",\n\t\t\t\"-I\" + muslDir + \"/src/internal\",\n\t\t\t\"-I\" + headerPath,\n\t\t\t\"-I\" + muslDir + \"/include\",\n\t\t\t\"-fno-stack-protector\",\n\t\t}\n\t\treturn cflags\n\t},\n\tsourceDir: func() string { return filepath.Join(goenv.Get(\"TINYGOROOT\"), \"lib/musl/src\") },\n\tlibrarySources: func(target string, _ bool) ([]string, error) {\n\t\tarch := compileopts.MuslArchitecture(target)\n\t\tglobs := []string{\n\t\t\t\"conf/*.c\",\n\t\t\t\"ctype/*.c\",\n\t\t\t\"env/*.c\",\n\t\t\t\"errno/*.c\",\n\t\t\t\"exit/*.c\",\n\t\t\t\"fcntl/*.c\",\n\t\t\t\"internal/defsysinfo.c\",\n\t\t\t\"internal/intscan.c\",\n\t\t\t\"internal/libc.c\",\n\t\t\t\"internal/shgetc.c\",\n\t\t\t\"internal/syscall_ret.c\",\n\t\t\t\"internal/vdso.c\",\n\t\t\t\"legacy/*.c\",\n\t\t\t\"locale/*.c\",\n\t\t\t\"linux/*.c\",\n\t\t\t\"locale/*.c\",\n\t\t\t\"malloc/*.c\",\n\t\t\t\"malloc/mallocng/*.c\",\n\t\t\t\"mman/*.c\",\n\t\t\t\"math/*.c\",\n\t\t\t\"misc/*.c\",\n\t\t\t\"multibyte/*.c\",\n\t\t\t\"sched/*.c\",\n\t\t\t\"signal/\" + arch + \"/*.s\",\n\t\t\t\"signal/*.c\",\n\t\t\t\"stdio/*.c\",\n\t\t\t\"stdlib/*.c\",\n\t\t\t\"string/*.c\",\n\t\t\t\"thread/\" + arch + \"/*.s\",\n\t\t\t\"thread/*.c\",\n\t\t\t\"time/*.c\",\n\t\t\t\"unistd/*.c\",\n\t\t\t\"process/*.c\",\n\t\t}\n\n\t\tif arch == \"arm\" {\n\t\t\t// These files need to be added to the start for some reason.\n\t\t\tglobs = append([]string{\"thread/arm/*.c\"}, globs...)\n\t\t}\n\n\t\tif arch != \"aarch64\" && arch != \"mips\" {\n\t\t\t//aarch64 and mips have no architecture specific code, either they\n\t\t\t// are not supported or don't need any?\n\t\t\tglobs = append([]string{\"process/\" + arch + \"/*.s\"}, globs...)\n\t\t}\n\n\t\tvar sources []string\n\t\tseenSources := map[string]struct{}{}\n\t\tbasepath := goenv.Get(\"TINYGOROOT\") + \"/lib/musl/src/\"\n\t\tfor _, pattern := range globs {\n\t\t\tmatches, err := filepath.Glob(basepath + pattern)\n\t\t\tif err != nil {\n\t\t\t\t// From the documentation:\n\t\t\t\t// > Glob ignores file system errors such as I/O errors reading\n\t\t\t\t// > directories. The only possible returned error is\n\t\t\t\t// > ErrBadPattern, when pattern is malformed.\n\t\t\t\t// So the only possible error is when the (statically defined)\n\t\t\t\t// pattern is wrong. In other words, a programming bug.\n\t\t\t\treturn nil, fmt.Errorf(\"musl: could not glob source dirs: %w\", err)\n\t\t\t}\n\t\t\tif len(matches) == 0 {\n\t\t\t\treturn nil, fmt.Errorf(\"musl: did not find any files for pattern %#v\", pattern)\n\t\t\t}\n\t\t\tfor _, match := range matches {\n\t\t\t\trelpath, err := filepath.Rel(basepath, match)\n\t\t\t\tif err != nil {\n\t\t\t\t\t// Not sure if this is even possible.\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\t// Make sure architecture specific files override generic files.\n\t\t\t\tid := strings.ReplaceAll(relpath, \"/\"+arch+\"/\", \"/\")\n\t\t\t\tif _, ok := seenSources[id]; ok {\n\t\t\t\t\t// Already seen this file, skipping this (generic) file.\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tseenSources[id] = struct{}{}\n\t\t\t\tsources = append(sources, relpath)\n\t\t\t}\n\t\t}\n\t\treturn sources, nil\n\t},\n\tcrt1Source: \"../crt/crt1.c\", // lib/musl/crt/crt1.c\n}\n"
  },
  {
    "path": "builder/nrfutil.go",
    "content": "package builder\n\nimport (\n\t\"archive/zip\"\n\t\"bytes\"\n\t\"encoding/binary\"\n\t\"encoding/json\"\n\t\"os\"\n\n\t\"github.com/sigurn/crc16\"\n\t\"github.com/tinygo-org/tinygo/compileopts\"\n)\n\n// Structure of the manifest.json file.\ntype jsonManifest struct {\n\tManifest struct {\n\t\tApplication struct {\n\t\t\tBinaryFile     string        `json:\"bin_file\"`\n\t\t\tDataFile       string        `json:\"dat_file\"`\n\t\t\tInitPacketData nrfInitPacket `json:\"init_packet_data\"`\n\t\t} `json:\"application\"`\n\t\tDFUVersion float64 `json:\"dfu_version\"` // yes, this is a JSON number, not a string\n\t} `json:\"manifest\"`\n}\n\n// Structure of the init packet.\n// Source:\n// https://github.com/adafruit/Adafruit_nRF52_Bootloader/blob/master/lib/sdk11/components/libraries/bootloader_dfu/dfu_init.h#L47-L57\ntype nrfInitPacket struct {\n\tApplicationVersion uint32   `json:\"application_version\"`\n\tDeviceRevision     uint16   `json:\"device_revision\"`\n\tDeviceType         uint16   `json:\"device_type\"`\n\tFirmwareCRC16      uint16   `json:\"firmware_crc16\"`\n\tSoftDeviceRequired []uint16 `json:\"softdevice_req\"` // this is actually a variable length array\n}\n\n// Create the init packet (the contents of application.dat).\nfunc (p nrfInitPacket) createInitPacket() []byte {\n\tbuf := &bytes.Buffer{}\n\tbinary.Write(buf, binary.LittleEndian, p.DeviceType)                      // uint16_t device_type;\n\tbinary.Write(buf, binary.LittleEndian, p.DeviceRevision)                  // uint16_t device_rev;\n\tbinary.Write(buf, binary.LittleEndian, p.ApplicationVersion)              // uint32_t app_version;\n\tbinary.Write(buf, binary.LittleEndian, uint16(len(p.SoftDeviceRequired))) // uint16_t softdevice_len;\n\tbinary.Write(buf, binary.LittleEndian, p.SoftDeviceRequired)              // uint16_t softdevice[1];\n\tbinary.Write(buf, binary.LittleEndian, p.FirmwareCRC16)\n\treturn buf.Bytes()\n}\n\n// Make a Nordic DFU firmware image from an ELF file.\nfunc makeDFUFirmwareImage(options *compileopts.Options, infile, outfile string) error {\n\t// Read ELF file as input and convert it to a binary image file.\n\t_, data, err := extractROM(infile)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Create the zip file in memory.\n\t// It won't be very large anyway.\n\tbuf := &bytes.Buffer{}\n\tw := zip.NewWriter(buf)\n\n\t// Write the application binary to the zip file.\n\tbinw, err := w.Create(\"application.bin\")\n\tif err != nil {\n\t\treturn err\n\t}\n\t_, err = binw.Write(data)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Create the init packet.\n\tinitPacket := nrfInitPacket{\n\t\tApplicationVersion: 0xffff_ffff, // appears to be unused by the Adafruit bootloader\n\t\tDeviceRevision:     0xffff,      // DFU_DEVICE_REVISION_EMPTY\n\t\tDeviceType:         0x0052,      // ADAFRUIT_DEVICE_TYPE\n\t\tFirmwareCRC16:      crc16.Checksum(data, crc16.MakeTable(crc16.CRC16_CCITT_FALSE)),\n\t\tSoftDeviceRequired: []uint16{0xfffe}, // DFU_SOFTDEVICE_ANY\n\t}\n\n\t// Write the init packet to the zip file.\n\tdatw, err := w.Create(\"application.dat\")\n\tif err != nil {\n\t\treturn err\n\t}\n\t_, err = datw.Write(initPacket.createInitPacket())\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Create the JSON manifest.\n\tmanifest := &jsonManifest{}\n\tmanifest.Manifest.Application.BinaryFile = \"application.bin\"\n\tmanifest.Manifest.Application.DataFile = \"application.dat\"\n\tmanifest.Manifest.Application.InitPacketData = initPacket\n\tmanifest.Manifest.DFUVersion = 0.5\n\n\t// Write the JSON manifest to the file.\n\tjsonw, err := w.Create(\"manifest.json\")\n\tif err != nil {\n\t\treturn err\n\t}\n\tenc := json.NewEncoder(jsonw)\n\tenc.SetIndent(\"\", \"    \")\n\terr = enc.Encode(manifest)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Finish the zip file.\n\terr = w.Close()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn os.WriteFile(outfile, buf.Bytes(), 0o666)\n}\n"
  },
  {
    "path": "builder/objcopy.go",
    "content": "package builder\n\nimport (\n\t\"debug/elf\"\n\t\"io\"\n\t\"os\"\n\t\"sort\"\n\n\t\"github.com/marcinbor85/gohex\"\n)\n\n// maxPadBytes is the maximum allowed bytes to be padded in a rom extraction\n// this value is currently defined by Nintendo Switch Page Alignment (4096 bytes)\nconst maxPadBytes = 4095\n\n// objcopyError is an error returned by functions that act like objcopy.\ntype objcopyError struct {\n\tOp  string\n\tErr error\n}\n\nfunc (e objcopyError) Error() string {\n\tif e.Err == nil {\n\t\treturn e.Op\n\t}\n\treturn e.Op + \": \" + e.Err.Error()\n}\n\ntype progSlice []*elf.Prog\n\nfunc (s progSlice) Len() int           { return len(s) }\nfunc (s progSlice) Less(i, j int) bool { return s[i].Paddr < s[j].Paddr }\nfunc (s progSlice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }\n\n// extractROM extracts a firmware image and the first load address from the\n// given ELF file. It tries to emulate the behavior of objcopy.\nfunc extractROM(path string) (uint64, []byte, error) {\n\tf, err := elf.Open(path)\n\tif err != nil {\n\t\treturn 0, nil, objcopyError{\"failed to open ELF file to extract text segment\", err}\n\t}\n\tdefer f.Close()\n\n\t// The GNU objcopy command does the following for firmware extraction (from\n\t// the man page):\n\t// > When objcopy generates a raw binary file, it will essentially produce a\n\t// > memory dump of the contents of the input object file. All symbols and\n\t// > relocation information will be discarded. The memory dump will start at\n\t// > the load address of the lowest section copied into the output file.\n\n\t// Find the lowest section address.\n\tstartAddr := ^uint64(0)\n\tfor _, section := range f.Sections {\n\t\tif section.Type != elf.SHT_PROGBITS || section.Flags&elf.SHF_ALLOC == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tif section.Addr < startAddr {\n\t\t\tstartAddr = section.Addr\n\t\t}\n\t}\n\n\tprogs := make(progSlice, 0, 2)\n\tfor _, prog := range f.Progs {\n\t\tif prog.Type != elf.PT_LOAD || prog.Filesz == 0 || prog.Off == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tprogs = append(progs, prog)\n\t}\n\tif len(progs) == 0 {\n\t\treturn 0, nil, objcopyError{\"file does not contain ROM segments: \" + path, nil}\n\t}\n\tsort.Sort(progs)\n\n\tvar rom []byte\n\tfor _, prog := range progs {\n\t\tromEnd := progs[0].Paddr + uint64(len(rom))\n\t\tif prog.Paddr > romEnd && prog.Paddr < romEnd+16 {\n\t\t\t// Sometimes, the linker seems to insert a bit of padding between\n\t\t\t// segments. Simply zero-fill these parts.\n\t\t\trom = append(rom, make([]byte, prog.Paddr-romEnd)...)\n\t\t}\n\t\tif prog.Paddr != progs[0].Paddr+uint64(len(rom)) {\n\t\t\tdiff := prog.Paddr - (progs[0].Paddr + uint64(len(rom)))\n\t\t\tif diff > maxPadBytes {\n\t\t\t\treturn 0, nil, objcopyError{\"ROM segments are non-contiguous: \" + path, nil}\n\t\t\t}\n\t\t\t// Pad the difference\n\t\t\trom = append(rom, make([]byte, diff)...)\n\t\t}\n\t\tdata, err := io.ReadAll(prog.Open())\n\t\tif err != nil {\n\t\t\treturn 0, nil, objcopyError{\"failed to extract segment from ELF file: \" + path, err}\n\t\t}\n\t\trom = append(rom, data...)\n\t}\n\tif progs[0].Paddr < startAddr {\n\t\t// The lowest memory address is before the first section. This means\n\t\t// that there is some extra data loaded at the start of the image that\n\t\t// should be discarded.\n\t\t// Example: ELF files where .text doesn't start at address 0 because\n\t\t// there is a bootloader at the start.\n\t\treturn startAddr, rom[startAddr-progs[0].Paddr:], nil\n\t} else {\n\t\treturn progs[0].Paddr, rom, nil\n\t}\n}\n\n// objcopy converts an ELF file to a different (simpler) output file format:\n// .bin or .hex. It extracts only the .text section.\nfunc objcopy(infile, outfile, binaryFormat string) error {\n\tf, err := os.OpenFile(outfile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer f.Close()\n\n\t// Read the .text segment.\n\taddr, data, err := extractROM(infile)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Write to the file, in the correct format.\n\tswitch binaryFormat {\n\tcase \"hex\":\n\t\t// Intel hex file, includes the firmware start address.\n\t\tmem := gohex.NewMemory()\n\t\terr := mem.AddBinary(uint32(addr), data)\n\t\tif err != nil {\n\t\t\treturn objcopyError{\"failed to create .hex file\", err}\n\t\t}\n\t\treturn mem.DumpIntelHex(f, 16)\n\tcase \"bin\":\n\t\t// The start address is not stored in raw firmware files (therefore you\n\t\t// should use .hex files in most cases).\n\t\t_, err := f.Write(data)\n\t\treturn err\n\tdefault:\n\t\tpanic(\"unreachable\")\n\t}\n}\n"
  },
  {
    "path": "builder/picolibc.go",
    "content": "package builder\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/tinygo-org/tinygo/goenv\"\n)\n\n// libPicolibc is a C library for bare metal embedded devices. It was originally\n// based on newlib.\nvar libPicolibc = Library{\n\tname: \"picolibc\",\n\tmakeHeaders: func(target, includeDir string) error {\n\t\tf, err := os.Create(filepath.Join(includeDir, \"picolibc.h\"))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn f.Close()\n\t},\n\tcflags: func(target, headerPath string) []string {\n\t\tnewlibDir := filepath.Join(goenv.Get(\"TINYGOROOT\"), \"lib/picolibc/newlib\")\n\t\treturn []string{\n\t\t\t\"-Werror\",\n\t\t\t\"-Wall\",\n\t\t\t\"-std=gnu11\",\n\t\t\t\"-D_COMPILING_NEWLIB\",\n\t\t\t\"-D_HAVE_ALIAS_ATTRIBUTE\",\n\t\t\t\"-DTINY_STDIO\",\n\t\t\t\"-DPOSIX_IO\",\n\t\t\t\"-DFORMAT_DEFAULT_INTEGER\", // use __i_vfprintf and __i_vfscanf by default\n\t\t\t\"-D_IEEE_LIBM\",\n\t\t\t\"-D__OBSOLETE_MATH_FLOAT=1\", // use old math code that doesn't expect a FPU\n\t\t\t\"-D__OBSOLETE_MATH_DOUBLE=0\",\n\t\t\t\"-D_WANT_IO_C99_FORMATS\",\n\t\t\t\"-D__PICOLIBC_ERRNO_FUNCTION=__errno_location\",\n\t\t\t\"-nostdlibinc\",\n\t\t\t\"-isystem\", newlibDir + \"/libc/include\",\n\t\t\t\"-I\" + newlibDir + \"/libc/tinystdio\",\n\t\t\t\"-I\" + newlibDir + \"/libm/common\",\n\t\t\t\"-I\" + headerPath,\n\t\t}\n\t},\n\tsourceDir: func() string { return filepath.Join(goenv.Get(\"TINYGOROOT\"), \"lib/picolibc/newlib\") },\n\tlibrarySources: func(target string, _ bool) ([]string, error) {\n\t\tsources := append([]string(nil), picolibcSources...)\n\t\tif !strings.HasPrefix(target, \"avr\") {\n\t\t\t// Small chips without long jumps can't compile many files (printf,\n\t\t\t// pow, etc). Therefore exclude those source files for those chips.\n\t\t\t// Unfortunately it's difficult to exclude only some chips, so this\n\t\t\t// excludes those files on all AVR chips for now.\n\t\t\t// More information:\n\t\t\t// https://github.com/llvm/llvm-project/issues/67042\n\t\t\tsources = append(sources, picolibcSourcesLarge...)\n\t\t}\n\t\treturn sources, nil\n\t},\n}\n\nvar picolibcSources = []string{\n\t\"../../picolibc-stdio.c\",\n\n\t\"libc/string/bcmp.c\",\n\t\"libc/string/bcopy.c\",\n\t\"libc/string/bzero.c\",\n\t\"libc/string/explicit_bzero.c\",\n\t\"libc/string/ffsl.c\",\n\t\"libc/string/ffsll.c\",\n\t\"libc/string/fls.c\",\n\t\"libc/string/flsl.c\",\n\t\"libc/string/flsll.c\",\n\t\"libc/string/gnu_basename.c\",\n\t\"libc/string/index.c\",\n\t\"libc/string/memccpy.c\",\n\t\"libc/string/memchr.c\",\n\t\"libc/string/memcmp.c\",\n\t\"libc/string/memcpy.c\",\n\t\"libc/string/memmem.c\",\n\t\"libc/string/memmove.c\",\n\t\"libc/string/mempcpy.c\",\n\t\"libc/string/memrchr.c\",\n\t\"libc/string/memset.c\",\n\t\"libc/string/rawmemchr.c\",\n\t\"libc/string/rindex.c\",\n\t\"libc/string/stpcpy.c\",\n\t\"libc/string/stpncpy.c\",\n\t\"libc/string/strcasecmp.c\",\n\t\"libc/string/strcasecmp_l.c\",\n\t\"libc/string/strcasestr.c\",\n\t\"libc/string/strcat.c\",\n\t\"libc/string/strchr.c\",\n\t\"libc/string/strchrnul.c\",\n\t\"libc/string/strcmp.c\",\n\t\"libc/string/strcoll.c\",\n\t\"libc/string/strcoll_l.c\",\n\t\"libc/string/strcpy.c\",\n\t\"libc/string/strcspn.c\",\n\t\"libc/string/strdup.c\",\n\t\"libc/string/strerror.c\",\n\t\"libc/string/strerror_r.c\",\n\t\"libc/string/strlcat.c\",\n\t\"libc/string/strlcpy.c\",\n\t\"libc/string/strlen.c\",\n\t\"libc/string/strlwr.c\",\n\t\"libc/string/strncasecmp.c\",\n\t\"libc/string/strncasecmp_l.c\",\n\t\"libc/string/strncat.c\",\n\t\"libc/string/strncmp.c\",\n\t\"libc/string/strncpy.c\",\n\t\"libc/string/strndup.c\",\n\t\"libc/string/strnlen.c\",\n\t\"libc/string/strnstr.c\",\n\t\"libc/string/strpbrk.c\",\n\t\"libc/string/strrchr.c\",\n\t\"libc/string/strsep.c\",\n\t\"libc/string/strsignal.c\",\n\t\"libc/string/strspn.c\",\n\t\"libc/string/strstr.c\",\n\t\"libc/string/strtok.c\",\n\t\"libc/string/strtok_r.c\",\n\t\"libc/string/strupr.c\",\n\t\"libc/string/strverscmp.c\",\n\t\"libc/string/strxfrm.c\",\n\t\"libc/string/strxfrm_l.c\",\n\t\"libc/string/swab.c\",\n\t\"libc/string/timingsafe_bcmp.c\",\n\t\"libc/string/timingsafe_memcmp.c\",\n\t\"libc/string/u_strerr.c\",\n\t\"libc/string/wcpcpy.c\",\n\t\"libc/string/wcpncpy.c\",\n\t\"libc/string/wcscasecmp.c\",\n\t\"libc/string/wcscasecmp_l.c\",\n\t\"libc/string/wcscat.c\",\n\t\"libc/string/wcschr.c\",\n\t\"libc/string/wcscmp.c\",\n\t\"libc/string/wcscoll.c\",\n\t\"libc/string/wcscoll_l.c\",\n\t\"libc/string/wcscpy.c\",\n\t\"libc/string/wcscspn.c\",\n\t\"libc/string/wcsdup.c\",\n\t\"libc/string/wcslcat.c\",\n\t\"libc/string/wcslcpy.c\",\n\t\"libc/string/wcslen.c\",\n\t\"libc/string/wcsncasecmp.c\",\n\t\"libc/string/wcsncasecmp_l.c\",\n\t\"libc/string/wcsncat.c\",\n\t\"libc/string/wcsncmp.c\",\n\t\"libc/string/wcsncpy.c\",\n\t\"libc/string/wcsnlen.c\",\n\t\"libc/string/wcspbrk.c\",\n\t\"libc/string/wcsrchr.c\",\n\t\"libc/string/wcsspn.c\",\n\t\"libc/string/wcsstr.c\",\n\t\"libc/string/wcstok.c\",\n\t\"libc/string/wcswidth.c\",\n\t\"libc/string/wcsxfrm.c\",\n\t\"libc/string/wcsxfrm_l.c\",\n\t\"libc/string/wcwidth.c\",\n\t\"libc/string/wmemchr.c\",\n\t\"libc/string/wmemcmp.c\",\n\t\"libc/string/wmemcpy.c\",\n\t\"libc/string/wmemmove.c\",\n\t\"libc/string/wmempcpy.c\",\n\t\"libc/string/wmemset.c\",\n\t\"libc/string/xpg_strerror_r.c\",\n}\n\n// Parts of picolibc that are too large for small AVRs.\nvar picolibcSourcesLarge = []string{\n\t// srcs_tinystdio\n\t\"libc/tinystdio/asprintf.c\",\n\t\"libc/tinystdio/bufio.c\",\n\t\"libc/tinystdio/clearerr.c\",\n\t\"libc/tinystdio/ecvt_r.c\",\n\t\"libc/tinystdio/ecvt.c\",\n\t\"libc/tinystdio/ecvtf_r.c\",\n\t\"libc/tinystdio/ecvtf.c\",\n\t\"libc/tinystdio/fcvt.c\",\n\t\"libc/tinystdio/fcvt_r.c\",\n\t\"libc/tinystdio/fcvtf.c\",\n\t\"libc/tinystdio/fcvtf_r.c\",\n\t\"libc/tinystdio/gcvt.c\",\n\t\"libc/tinystdio/gcvtf.c\",\n\t\"libc/tinystdio/fclose.c\",\n\t\"libc/tinystdio/fdevopen.c\",\n\t\"libc/tinystdio/feof.c\",\n\t\"libc/tinystdio/ferror.c\",\n\t\"libc/tinystdio/fflush.c\",\n\t\"libc/tinystdio/fgetc.c\",\n\t\"libc/tinystdio/fgets.c\",\n\t\"libc/tinystdio/fileno.c\",\n\t\"libc/tinystdio/filestrget.c\",\n\t\"libc/tinystdio/filestrput.c\",\n\t\"libc/tinystdio/filestrputalloc.c\",\n\t\"libc/tinystdio/fmemopen.c\",\n\t\"libc/tinystdio/fprintf.c\",\n\t\"libc/tinystdio/fputc.c\",\n\t\"libc/tinystdio/fputs.c\",\n\t\"libc/tinystdio/fread.c\",\n\t//\"libc/tinystdio/freopen.c\", // crashes with AVR, see: https://github.com/picolibc/picolibc/pull/369\n\t\"libc/tinystdio/fscanf.c\",\n\t\"libc/tinystdio/fseek.c\",\n\t\"libc/tinystdio/fseeko.c\",\n\t\"libc/tinystdio/ftell.c\",\n\t\"libc/tinystdio/ftello.c\",\n\t\"libc/tinystdio/fwrite.c\",\n\t\"libc/tinystdio/getchar.c\",\n\t\"libc/tinystdio/gets.c\",\n\t\"libc/tinystdio/matchcaseprefix.c\",\n\t\"libc/tinystdio/mktemp.c\",\n\t\"libc/tinystdio/perror.c\",\n\t\"libc/tinystdio/printf.c\",\n\t\"libc/tinystdio/putchar.c\",\n\t\"libc/tinystdio/puts.c\",\n\t\"libc/tinystdio/rewind.c\",\n\t\"libc/tinystdio/scanf.c\",\n\t\"libc/tinystdio/setbuf.c\",\n\t\"libc/tinystdio/setbuffer.c\",\n\t\"libc/tinystdio/setlinebuf.c\",\n\t\"libc/tinystdio/setvbuf.c\",\n\t\"libc/tinystdio/snprintf.c\",\n\t\"libc/tinystdio/sprintf.c\",\n\t\"libc/tinystdio/snprintfd.c\",\n\t\"libc/tinystdio/snprintff.c\",\n\t\"libc/tinystdio/sprintff.c\",\n\t\"libc/tinystdio/sprintfd.c\",\n\t\"libc/tinystdio/sscanf.c\",\n\t\"libc/tinystdio/strfromf.c\",\n\t\"libc/tinystdio/strfromd.c\",\n\t\"libc/tinystdio/strtof.c\",\n\t\"libc/tinystdio/strtof_l.c\",\n\t\"libc/tinystdio/strtod.c\",\n\t\"libc/tinystdio/strtod_l.c\",\n\t\"libc/tinystdio/ungetc.c\",\n\t\"libc/tinystdio/vasprintf.c\",\n\t\"libc/tinystdio/vfiprintf.c\",\n\t\"libc/tinystdio/vfprintf.c\",\n\t\"libc/tinystdio/vfprintff.c\",\n\t\"libc/tinystdio/vfscanf.c\",\n\t\"libc/tinystdio/vfiscanf.c\",\n\t\"libc/tinystdio/vfscanff.c\",\n\t\"libc/tinystdio/vprintf.c\",\n\t\"libc/tinystdio/vscanf.c\",\n\t\"libc/tinystdio/vsscanf.c\",\n\t\"libc/tinystdio/vsnprintf.c\",\n\t\"libc/tinystdio/vsprintf.c\",\n\n\t\"libm/common/sf_finite.c\",\n\t\"libm/common/sf_copysign.c\",\n\t\"libm/common/sf_modf.c\",\n\t\"libm/common/sf_scalbn.c\",\n\t\"libm/common/sf_cbrt.c\",\n\t\"libm/common/sf_exp10.c\",\n\t\"libm/common/sf_expm1.c\",\n\t\"libm/common/sf_ilogb.c\",\n\t\"libm/common/sf_infinity.c\",\n\t\"libm/common/sf_isinf.c\",\n\t\"libm/common/sf_isinff.c\",\n\t\"libm/common/sf_isnan.c\",\n\t\"libm/common/sf_isnanf.c\",\n\t\"libm/common/sf_issignaling.c\",\n\t\"libm/common/sf_log1p.c\",\n\t\"libm/common/sf_nan.c\",\n\t\"libm/common/sf_nextafter.c\",\n\t\"libm/common/sf_pow10.c\",\n\t\"libm/common/sf_rint.c\",\n\t\"libm/common/sf_logb.c\",\n\t\"libm/common/sf_fdim.c\",\n\t\"libm/common/sf_fma.c\",\n\t\"libm/common/sf_fmax.c\",\n\t\"libm/common/sf_fmin.c\",\n\t\"libm/common/sf_fpclassify.c\",\n\t\"libm/common/sf_lrint.c\",\n\t\"libm/common/sf_llrint.c\",\n\t\"libm/common/sf_lround.c\",\n\t\"libm/common/sf_llround.c\",\n\t\"libm/common/sf_nearbyint.c\",\n\t\"libm/common/sf_remquo.c\",\n\t\"libm/common/sf_round.c\",\n\t\"libm/common/sf_scalbln.c\",\n\t\"libm/common/sf_trunc.c\",\n\t\"libm/common/sf_exp.c\",\n\t\"libm/common/sf_exp2.c\",\n\t\"libm/common/sf_exp2_data.c\",\n\t\"libm/common/sf_log.c\",\n\t\"libm/common/sf_log_data.c\",\n\t\"libm/common/sf_log2.c\",\n\t\"libm/common/sf_log2_data.c\",\n\t\"libm/common/sf_pow_log2_data.c\",\n\t\"libm/common/sf_pow.c\",\n\n\t\"libm/common/s_finite.c\",\n\t\"libm/common/s_copysign.c\",\n\t\"libm/common/s_modf.c\",\n\t\"libm/common/s_scalbn.c\",\n\t\"libm/common/s_cbrt.c\",\n\t\"libm/common/s_exp10.c\",\n\t\"libm/common/s_expm1.c\",\n\t\"libm/common/s_ilogb.c\",\n\t\"libm/common/s_infinity.c\",\n\t\"libm/common/s_iseqsig.c\",\n\t\"libm/common/s_isinf.c\",\n\t\"libm/common/s_isinfd.c\",\n\t\"libm/common/s_isnan.c\",\n\t\"libm/common/s_isnand.c\",\n\t\"libm/common/s_issignaling.c\",\n\t\"libm/common/s_log1p.c\",\n\t\"libm/common/s_nan.c\",\n\t\"libm/common/s_nextafter.c\",\n\t\"libm/common/s_pow10.c\",\n\t\"libm/common/s_rint.c\",\n\t\"libm/common/s_logb.c\",\n\t\"libm/common/s_log2.c\",\n\t\"libm/common/s_fdim.c\",\n\t\"libm/common/s_fma.c\",\n\t\"libm/common/s_fmax.c\",\n\t\"libm/common/s_fmin.c\",\n\t\"libm/common/s_fpclassify.c\",\n\t\"libm/common/s_getpayload.c\",\n\t\"libm/common/s_lrint.c\",\n\t\"libm/common/s_llrint.c\",\n\t\"libm/common/s_lround.c\",\n\t\"libm/common/s_llround.c\",\n\t\"libm/common/s_nearbyint.c\",\n\t\"libm/common/s_remquo.c\",\n\t\"libm/common/s_round.c\",\n\t\"libm/common/s_scalbln.c\",\n\t\"libm/common/s_signbit.c\",\n\t\"libm/common/s_trunc.c\",\n\t\"libm/common/exp.c\",\n\t\"libm/common/exp2.c\",\n\t\"libm/common/exp_data.c\",\n\t\"libm/common/math_err_with_errno.c\",\n\t\"libm/common/math_err_uflow.c\",\n\t\"libm/common/math_err_oflow.c\",\n\t\"libm/common/math_err_divzero.c\",\n\t\"libm/common/math_err_invalid.c\",\n\t\"libm/common/math_err_may_uflow.c\",\n\t\"libm/common/math_err_check_uflow.c\",\n\t\"libm/common/math_err_check_oflow.c\",\n\t\"libm/common/math_errf_divzerof.c\",\n\t\"libm/common/math_errf_invalidf.c\",\n\t\"libm/common/math_errf_may_uflowf.c\",\n\t\"libm/common/math_errf_oflowf.c\",\n\t\"libm/common/math_errf_uflowf.c\",\n\t\"libm/common/math_errf_with_errnof.c\",\n\t\"libm/common/math_inexact.c\",\n\t\"libm/common/math_inexactf.c\",\n\t\"libm/common/log.c\",\n\t\"libm/common/log_data.c\",\n\t\"libm/common/log2.c\",\n\t\"libm/common/log2_data.c\",\n\t\"libm/common/pow.c\",\n\t\"libm/common/pow_log_data.c\",\n\n\t\"libm/math/k_cos.c\",\n\t\"libm/math/k_rem_pio2.c\",\n\t\"libm/math/k_sin.c\",\n\t\"libm/math/k_tan.c\",\n\t\"libm/math/kf_cos.c\",\n\t\"libm/math/kf_rem_pio2.c\",\n\t\"libm/math/kf_sin.c\",\n\t\"libm/math/kf_tan.c\",\n\t\"libm/math/s_acos.c\",\n\t\"libm/math/s_acosh.c\",\n\t\"libm/math/s_asin.c\",\n\t\"libm/math/s_asinh.c\",\n\t\"libm/math/s_atan.c\",\n\t\"libm/math/s_atan2.c\",\n\t\"libm/math/s_atanh.c\",\n\t\"libm/math/s_ceil.c\",\n\t\"libm/math/s_cos.c\",\n\t\"libm/math/s_cosh.c\",\n\t\"libm/math/s_drem.c\",\n\t\"libm/math/s_erf.c\",\n\t\"libm/math/s_exp.c\",\n\t\"libm/math/s_exp2.c\",\n\t\"libm/math/s_fabs.c\",\n\t\"libm/math/s_floor.c\",\n\t\"libm/math/s_fmod.c\",\n\t\"libm/math/s_frexp.c\",\n\t\"libm/math/s_gamma.c\",\n\t\"libm/math/s_hypot.c\",\n\t\"libm/math/s_j0.c\",\n\t\"libm/math/s_j1.c\",\n\t\"libm/math/s_jn.c\",\n\t\"libm/math/s_lgamma.c\",\n\t\"libm/math/s_log.c\",\n\t\"libm/math/s_log10.c\",\n\t\"libm/math/s_pow.c\",\n\t\"libm/math/s_rem_pio2.c\",\n\t\"libm/math/s_remainder.c\",\n\t\"libm/math/s_scalb.c\",\n\t\"libm/math/s_signif.c\",\n\t\"libm/math/s_sin.c\",\n\t\"libm/math/s_sincos.c\",\n\t\"libm/math/s_sinh.c\",\n\t\"libm/math/s_sqrt.c\",\n\t\"libm/math/s_tan.c\",\n\t\"libm/math/s_tanh.c\",\n\t\"libm/math/s_tgamma.c\",\n\t\"libm/math/sf_acos.c\",\n\t\"libm/math/sf_acosh.c\",\n\t\"libm/math/sf_asin.c\",\n\t\"libm/math/sf_asinh.c\",\n\t\"libm/math/sf_atan.c\",\n\t\"libm/math/sf_atan2.c\",\n\t\"libm/math/sf_atanh.c\",\n\t\"libm/math/sf_ceil.c\",\n\t\"libm/math/sf_cos.c\",\n\t\"libm/math/sf_cosh.c\",\n\t\"libm/math/sf_drem.c\",\n\t\"libm/math/sf_erf.c\",\n\t\"libm/math/sf_exp.c\",\n\t\"libm/math/sf_exp2.c\",\n\t\"libm/math/sf_fabs.c\",\n\t\"libm/math/sf_floor.c\",\n\t\"libm/math/sf_fmod.c\",\n\t\"libm/math/sf_frexp.c\",\n\t\"libm/math/sf_gamma.c\",\n\t\"libm/math/sf_hypot.c\",\n\t\"libm/math/sf_j0.c\",\n\t\"libm/math/sf_j1.c\",\n\t\"libm/math/sf_jn.c\",\n\t\"libm/math/sf_lgamma.c\",\n\t\"libm/math/sf_log.c\",\n\t\"libm/math/sf_log10.c\",\n\t\"libm/math/sf_log2.c\",\n\t\"libm/math/sf_pow.c\",\n\t\"libm/math/sf_rem_pio2.c\",\n\t\"libm/math/sf_remainder.c\",\n\t\"libm/math/sf_scalb.c\",\n\t\"libm/math/sf_signif.c\",\n\t\"libm/math/sf_sin.c\",\n\t\"libm/math/sf_sincos.c\",\n\t\"libm/math/sf_sinh.c\",\n\t\"libm/math/sf_sqrt.c\",\n\t\"libm/math/sf_tan.c\",\n\t\"libm/math/sf_tanh.c\",\n\t\"libm/math/sf_tgamma.c\",\n\t\"libm/math/sr_lgamma.c\",\n\t\"libm/math/srf_lgamma.c\",\n}\n"
  },
  {
    "path": "builder/size-report.go",
    "content": "package builder\n\nimport (\n\t_ \"embed\"\n\t\"fmt\"\n\t\"html/template\"\n\t\"os\"\n)\n\n//go:embed size-report.html\nvar sizeReportBase string\n\nfunc writeSizeReport(sizes *programSize, filename, pkgName string) error {\n\ttmpl, err := template.New(\"report\").Parse(sizeReportBase)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tf, err := os.Create(filename)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"could not open report file: %w\", err)\n\t}\n\tdefer f.Close()\n\n\t// Prepare data for the report.\n\ttype sizeLine struct {\n\t\tName string\n\t\tSize *packageSize\n\t}\n\tprogramData := []sizeLine{}\n\tfor _, name := range sizes.sortedPackageNames() {\n\t\tpkgSize := sizes.Packages[name]\n\t\tprogramData = append(programData, sizeLine{\n\t\t\tName: name,\n\t\t\tSize: pkgSize,\n\t\t})\n\t}\n\tsizeTotal := map[string]uint64{\n\t\t\"code\":   sizes.Code,\n\t\t\"rodata\": sizes.ROData,\n\t\t\"data\":   sizes.Data,\n\t\t\"bss\":    sizes.BSS,\n\t\t\"flash\":  sizes.Flash(),\n\t}\n\n\t// Write the report.\n\terr = tmpl.Execute(f, map[string]any{\n\t\t\"pkgName\":   pkgName,\n\t\t\"sizes\":     programData,\n\t\t\"sizeTotal\": sizeTotal,\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"could not create report file: %w\", err)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "builder/size-report.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <title>Size Report for {{.pkgName}}</title>\n    <meta charset=\"utf-8\"/>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n    <link href=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH\" crossorigin=\"anonymous\">\n    <style>\n\n.table-vertical-border {\n  border-left: calc(var(--bs-border-width) * 2) solid currentcolor;\n}\n\n/* Hover on only the rows that are clickable. */\n.row-package:hover > * {\n  --bs-table-color-state: var(--bs-table-hover-color);\n  --bs-table-bg-state: var(--bs-table-hover-bg);\n}\n\n    </style>\n  </head>\n  <body>\n    <div class=\"container-xxl\">\n      <h1>Size Report for {{.pkgName}}</h1>\n\n      <p>How much space is used by Go packages, C libraries, and other bits to set up the program environment.</p>\n\n      <ul>\n        <li><strong>Code</strong> is the actual program code (machine code instructions).</li>\n        <li><strong>Read-only data</strong> are read-only global variables. On most microcontrollers, these are stored in flash and do not take up any RAM.</li>\n        <li><strong>Data</strong> are writable global variables with a non-zero initializer. On microcontrollers, they are copied from flash to RAM on reset.</li>\n        <li><strong>BSS</strong> are writable global variables that are zero initialized. They do not take up any space in the binary, but do take up RAM. On microcontrollers, this area is zeroed on reset.</li>\n      </ul>\n\n      <p>The binary size consists of code, read-only data, and data. On microcontrollers, this is exactly the size of the firmware image. On other systems, there is some extra overhead: binary metadata (headers of the ELF/MachO/COFF file), debug information, exception tables, symbol names, etc. Using <code>-no-debug</code> strips most of those.</p>\n\n      <h2>Program breakdown</h2>\n\n      <p>You can click on the rows below to see which files contribute to the binary size.</p>\n\n      <div class=\"table-responsive\">\n        <table class=\"table w-auto\">\n          <thead>\n            <tr>\n              <th>Package</th>\n              <th class=\"table-vertical-border\">Code</th>\n              <th>Read-only data</th>\n              <th>Data</th>\n              <th title=\"zero-initialized data\">BSS</th>\n              <th class=\"table-vertical-border\" style=\"min-width: 16em\">Binary size</th>\n            </tr>\n          </thead>\n          <tbody class=\"table-group-divider\">\n            {{range $i, $pkg := .sizes}}\n            <tr class=\"row-package\" data-collapse=\".collapse-row-{{$i}}\">\n              <td>{{.Name}}</td>\n              <td class=\"table-vertical-border\">{{.Size.Code}}</td>\n              <td>{{.Size.ROData}}</td>\n              <td>{{.Size.Data}}</td>\n              <td>{{.Size.BSS}}</td>\n              <td class=\"table-vertical-border\" style=\"background: linear-gradient(to right, var(--bs-info-bg-subtle) {{.Size.FlashPercent}}%, var(--bs-table-bg) {{.Size.FlashPercent}}%)\">\n                {{.Size.Flash}}\n              </td>\n            </tr>\n            {{range $filename, $sizes := .Size.Sub}}\n            <tr class=\"table-secondary collapse collapse-row-{{$i}}\">\n              <td class=\"ps-4\">\n                {{if eq $filename \"\"}}\n                  (unknown file)\n                {{else}}\n                  {{$filename}}\n                {{end}}\n              </td>\n              <td class=\"table-vertical-border\">{{$sizes.Code}}</td>\n              <td>{{$sizes.ROData}}</td>\n              <td>{{$sizes.Data}}</td>\n              <td>{{$sizes.BSS}}</td>\n              <td class=\"table-vertical-border\" style=\"background: linear-gradient(to right, var(--bs-info-bg-subtle) {{$sizes.FlashPercent}}%, var(--bs-table-bg) {{$sizes.FlashPercent}}%)\">\n                {{$sizes.Flash}}\n              </td>\n            </tr>\n            {{end}}\n            {{end}}\n          </tbody>\n          <tfoot class=\"table-group-divider\">\n            <tr>\n              <th>Total</th>\n              <td class=\"table-vertical-border\">{{.sizeTotal.code}}</td>\n              <td>{{.sizeTotal.rodata}}</td>\n              <td>{{.sizeTotal.data}}</td>\n              <td>{{.sizeTotal.bss}}</td>\n              <td class=\"table-vertical-border\">{{.sizeTotal.flash}}</td>\n            </tr>\n          </tfoot>\n        </table>\n      </div>\n    </div>\n    <script>\n// Make table rows toggleable to show filenames.\nfor (let clickable of document.querySelectorAll('.row-package')) {\n  clickable.addEventListener('click', e => {\n    for (let row of document.querySelectorAll(clickable.dataset.collapse)) {\n      row.classList.toggle('show');\n    }\n  });\n}\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "builder/sizes.go",
    "content": "package builder\n\nimport (\n\t\"bytes\"\n\t\"debug/dwarf\"\n\t\"debug/elf\"\n\t\"debug/macho\"\n\t\"debug/pe\"\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"runtime\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"github.com/aykevl/go-wasm\"\n\t\"github.com/tinygo-org/tinygo/goenv\"\n)\n\n// Set to true to print extra debug logs.\nconst sizesDebug = false\n\n// programSize contains size statistics per package of a compiled program.\ntype programSize struct {\n\tPackages map[string]*packageSize\n\tCode     uint64\n\tROData   uint64\n\tData     uint64\n\tBSS      uint64\n}\n\n// sortedPackageNames returns the list of package names (ProgramSize.Packages)\n// sorted alphabetically.\nfunc (ps *programSize) sortedPackageNames() []string {\n\tnames := make([]string, 0, len(ps.Packages))\n\tfor name := range ps.Packages {\n\t\tnames = append(names, name)\n\t}\n\tsort.Strings(names)\n\treturn names\n}\n\n// Flash usage in regular microcontrollers.\nfunc (ps *programSize) Flash() uint64 {\n\treturn ps.Code + ps.ROData + ps.Data\n}\n\n// Static RAM usage in regular microcontrollers.\nfunc (ps *programSize) RAM() uint64 {\n\treturn ps.Data + ps.BSS\n}\n\n// Return the package size information for a given package path, creating it if\n// it doesn't exist yet.\nfunc (ps *programSize) getPackage(path string) *packageSize {\n\tif field, ok := ps.Packages[path]; ok {\n\t\treturn field\n\t}\n\tfield := &packageSize{\n\t\tProgram: ps,\n\t\tSub:     map[string]*packageSize{},\n\t}\n\tps.Packages[path] = field\n\treturn field\n}\n\n// packageSize contains the size of a package, calculated from the linked object\n// file.\ntype packageSize struct {\n\tProgram *programSize\n\tCode    uint64\n\tROData  uint64\n\tData    uint64\n\tBSS     uint64\n\tSub     map[string]*packageSize\n}\n\n// Flash usage in regular microcontrollers.\nfunc (ps *packageSize) Flash() uint64 {\n\treturn ps.Code + ps.ROData + ps.Data\n}\n\n// Static RAM usage in regular microcontrollers.\nfunc (ps *packageSize) RAM() uint64 {\n\treturn ps.Data + ps.BSS\n}\n\n// Flash usage in regular microcontrollers, as a percentage of the total flash\n// usage of the program.\nfunc (ps *packageSize) FlashPercent() float64 {\n\treturn float64(ps.Flash()) / float64(ps.Program.Flash()) * 100\n}\n\n// Add a single size data point to this package.\n// This must only be called while calculating package size, not afterwards.\nfunc (ps *packageSize) addSize(getField func(*packageSize, bool) *uint64, filename string, size uint64, isVariable bool) {\n\tif size == 0 {\n\t\treturn\n\t}\n\n\t// Add size for the package.\n\t*getField(ps, isVariable) += size\n\n\t// Add size for file inside package.\n\tsub, ok := ps.Sub[filename]\n\tif !ok {\n\t\tsub = &packageSize{Program: ps.Program}\n\t\tps.Sub[filename] = sub\n\t}\n\t*getField(sub, isVariable) += size\n}\n\n// A mapping of a single chunk of code or data to a file path.\ntype addressLine struct {\n\tAddress    uint64\n\tLength     uint64 // length of this chunk\n\tAlign      uint64 // (maximum) alignment of this line\n\tFile       string // file path as stored in DWARF\n\tIsVariable bool   // true if this is a variable (or constant), false if it is code\n}\n\n// Sections defined in the input file. This struct defines them in a\n// filetype-agnostic way but roughly follow the ELF types (.text, .data, .bss,\n// etc).\ntype memorySection struct {\n\tType    memoryType\n\tAddress uint64\n\tSize    uint64\n\tAlign   uint64\n}\n\ntype memoryType int\n\nconst (\n\tmemoryCode memoryType = iota + 1\n\tmemoryData\n\tmemoryROData\n\tmemoryBSS\n\tmemoryStack\n)\n\nfunc (t memoryType) String() string {\n\treturn [...]string{\n\t\t0:            \"-\",\n\t\tmemoryCode:   \"code\",\n\t\tmemoryData:   \"data\",\n\t\tmemoryROData: \"rodata\",\n\t\tmemoryBSS:    \"bss\",\n\t\tmemoryStack:  \"stack\",\n\t}[t]\n}\n\n// Regular expressions to match particular symbol names. These are not stored as\n// DWARF variables because they have no mapping to source code global variables.\nvar (\n\t// Various globals that aren't a variable but nonetheless need to be stored\n\t// somewhere:\n\t//   alloc:  heap allocations during init interpretation\n\t//   pack:   data created when storing a constant in an interface for example\n\t//   string: buffer behind strings\n\tpackageSymbolRegexp = regexp.MustCompile(`\\$(alloc|pack|string)(\\.[0-9]+)?$`)\n)\n\n// readProgramSizeFromDWARF reads the source location for each line of code and\n// each variable in the program, as far as this is stored in the DWARF debug\n// information.\nfunc readProgramSizeFromDWARF(data *dwarf.Data, codeOffset, codeAlignment uint64, skipTombstone bool) ([]addressLine, error) {\n\tr := data.Reader()\n\tvar lines []*dwarf.LineFile\n\tvar addresses []addressLine\n\tfor {\n\t\te, err := r.Next()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif e == nil {\n\t\t\tbreak\n\t\t}\n\t\tswitch e.Tag {\n\t\tcase dwarf.TagCompileUnit:\n\t\t\t// Found a compile unit.\n\t\t\t// We can read the .debug_line section using it, which contains a\n\t\t\t// mapping for most instructions to their file/line/column - even\n\t\t\t// for inlined functions!\n\t\t\tlr, err := data.LineReader(e)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tlines = lr.Files()\n\t\t\tvar lineEntry = dwarf.LineEntry{\n\t\t\t\tEndSequence: true,\n\t\t\t}\n\n\t\t\t// Line tables are organized as sequences of line entries until an\n\t\t\t// end sequence. A single line table can contain multiple such\n\t\t\t// sequences. The last line entry is an EndSequence to indicate the\n\t\t\t// end.\n\t\t\tfor {\n\t\t\t\t// Read the next .debug_line entry.\n\t\t\t\tprevLineEntry := lineEntry\n\t\t\t\terr := lr.Next(&lineEntry)\n\t\t\t\tif err != nil {\n\t\t\t\t\tif err == io.EOF {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\n\t\t\t\tif prevLineEntry.EndSequence && lineEntry.Address == 0 && skipTombstone {\n\t\t\t\t\t// Tombstone value. This symbol has been removed, for\n\t\t\t\t\t// example by the --gc-sections linker flag. It is still\n\t\t\t\t\t// here in the debug information because the linker can't\n\t\t\t\t\t// just remove this reference.\n\t\t\t\t\t// Read until the next EndSequence so that this sequence is\n\t\t\t\t\t// skipped.\n\t\t\t\t\t// For more details, see (among others):\n\t\t\t\t\t// https://reviews.llvm.org/D84825\n\t\t\t\t\t// The value 0 can however really occur in object files,\n\t\t\t\t\t// that typically start at address 0. So don't skip\n\t\t\t\t\t// tombstone values in object files (like when parsing MachO\n\t\t\t\t\t// files).\n\t\t\t\t\tfor {\n\t\t\t\t\t\terr := lr.Next(&lineEntry)\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn nil, err\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif lineEntry.EndSequence {\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif !prevLineEntry.EndSequence {\n\t\t\t\t\t// The chunk describes the code from prevLineEntry to\n\t\t\t\t\t// lineEntry.\n\t\t\t\t\tpath := prevLineEntry.File.Name\n\t\t\t\t\tif runtime.GOOS == \"windows\" {\n\t\t\t\t\t\t// Work around a Clang bug on Windows:\n\t\t\t\t\t\t// https://github.com/llvm/llvm-project/issues/117317\n\t\t\t\t\t\tpath = strings.ReplaceAll(path, \"\\\\\\\\\", \"\\\\\")\n\n\t\t\t\t\t\t// wasi-libc likes to use forward slashes, but we\n\t\t\t\t\t\t// canonicalize everything to use backwards slashes as\n\t\t\t\t\t\t// is common on Windows.\n\t\t\t\t\t\tpath = strings.ReplaceAll(path, \"/\", \"\\\\\")\n\t\t\t\t\t}\n\t\t\t\t\tline := addressLine{\n\t\t\t\t\t\tAddress: prevLineEntry.Address + codeOffset,\n\t\t\t\t\t\tLength:  lineEntry.Address - prevLineEntry.Address,\n\t\t\t\t\t\tAlign:   codeAlignment,\n\t\t\t\t\t\tFile:    path,\n\t\t\t\t\t}\n\t\t\t\t\tif line.Length != 0 {\n\t\t\t\t\t\taddresses = append(addresses, line)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\tcase dwarf.TagVariable:\n\t\t\t// Global variable (or constant). Most of these are not actually\n\t\t\t// stored in the binary, because they have been optimized out. Only\n\t\t\t// the ones with a location are still present.\n\t\t\tr.SkipChildren()\n\n\t\t\tfile := e.AttrField(dwarf.AttrDeclFile)\n\t\t\tlocation := e.AttrField(dwarf.AttrLocation)\n\t\t\tglobalType := e.AttrField(dwarf.AttrType)\n\t\t\tif file == nil || location == nil || globalType == nil {\n\t\t\t\t// Doesn't contain the requested information.\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Try to parse the location. While this could in theory be a very\n\t\t\t// complex expression, usually it's just a DW_OP_addr opcode\n\t\t\t// followed by an address.\n\t\t\taddr, err := readDWARFConstant(r.AddressSize(), location.Val.([]uint8))\n\t\t\tif err != nil {\n\t\t\t\tcontinue // ignore the error, we don't know what to do with it\n\t\t\t}\n\n\t\t\t// Parse the type of the global variable, which (importantly)\n\t\t\t// contains the variable size. We're not interested in the type,\n\t\t\t// only in the size.\n\t\t\ttyp, err := data.Type(globalType.Val.(dwarf.Offset))\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\t// Read alignment, if it's stored as part of the debug information.\n\t\t\tvar alignment uint64\n\t\t\tif attr := e.AttrField(dwarf.AttrAlignment); attr != nil {\n\t\t\t\talignment = uint64(attr.Val.(int64))\n\t\t\t}\n\n\t\t\taddresses = append(addresses, addressLine{\n\t\t\t\tAddress:    addr,\n\t\t\t\tLength:     uint64(typ.Size()),\n\t\t\t\tAlign:      alignment,\n\t\t\t\tFile:       lines[file.Val.(int64)].Name,\n\t\t\t\tIsVariable: true,\n\t\t\t})\n\t\tdefault:\n\t\t\tr.SkipChildren()\n\t\t}\n\t}\n\treturn addresses, nil\n}\n\n// Parse a DWARF constant. For addresses, this is usually a very simple\n// expression.\nfunc readDWARFConstant(addressSize int, bytecode []byte) (uint64, error) {\n\tvar addr uint64\n\tfor len(bytecode) != 0 {\n\t\top := bytecode[0]\n\t\tbytecode = bytecode[1:]\n\t\tswitch op {\n\t\tcase 0x03: // DW_OP_addr\n\t\t\tswitch addressSize {\n\t\t\tcase 2:\n\t\t\t\taddr = uint64(binary.LittleEndian.Uint16(bytecode))\n\t\t\tcase 4:\n\t\t\t\taddr = uint64(binary.LittleEndian.Uint32(bytecode))\n\t\t\tcase 8:\n\t\t\t\taddr = binary.LittleEndian.Uint64(bytecode)\n\t\t\tdefault:\n\t\t\t\tpanic(\"unexpected address size\")\n\t\t\t}\n\t\t\tbytecode = bytecode[addressSize:]\n\t\tcase 0x23: // DW_OP_plus_uconst\n\t\t\toffset, n := readULEB128(bytecode)\n\t\t\taddr += offset\n\t\t\tbytecode = bytecode[n:]\n\t\tdefault:\n\t\t\treturn 0, fmt.Errorf(\"unknown DWARF opcode: 0x%x\", op)\n\t\t}\n\t}\n\treturn addr, nil\n}\n\n// Source: https://en.wikipedia.org/wiki/LEB128#Decode_unsigned_integer\nfunc readULEB128(buf []byte) (result uint64, n int) {\n\tvar shift uint8\n\tfor {\n\t\tb := buf[n]\n\t\tn++\n\t\tresult |= uint64(b&0x7f) << shift\n\t\tif b&0x80 == 0 {\n\t\t\tbreak\n\t\t}\n\t\tshift += 7\n\t}\n\treturn\n}\n\n// Read a MachO object file and return a line table.\n// Also return an index from symbol name to start address in the line table.\nfunc readMachOSymbolAddresses(path string) (map[string]int, []addressLine, error) {\n\t// Some constants from mach-o/nlist.h\n\t// See: https://opensource.apple.com/source/xnu/xnu-7195.141.2/EXTERNAL_HEADERS/mach-o/nlist.h.auto.html\n\tconst (\n\t\tN_STAB = 0xe0\n\t\tN_TYPE = 0x0e // bitmask for N_TYPE field\n\t\tN_SECT = 0xe  // one of the possible type in the N_TYPE field\n\t)\n\n\t// Read DWARF from the given object file.\n\tfile, err := macho.Open(path)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tdefer file.Close()\n\tdwarf, err := file.DWARF()\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tlines, err := readProgramSizeFromDWARF(dwarf, 0, 0, false)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\t// Make a map from start addresses to indices in the line table (because the\n\t// line table is a slice, not a map).\n\taddressToLine := make(map[uint64]int, len(lines))\n\tfor i, line := range lines {\n\t\tif _, ok := addressToLine[line.Address]; ok {\n\t\t\taddressToLine[line.Address] = -1\n\t\t\tcontinue\n\t\t}\n\t\taddressToLine[line.Address] = i\n\t}\n\n\t// Make a map that for each symbol gives the start index in the line table.\n\taddresses := make(map[string]int, len(addressToLine))\n\tfor _, symbol := range file.Symtab.Syms {\n\t\tif symbol.Type&N_STAB != 0 {\n\t\t\tcontinue // STABS entry, ignore\n\t\t}\n\t\tif symbol.Type&0x0e != N_SECT {\n\t\t\tcontinue // undefined symbol\n\t\t}\n\t\tif index, ok := addressToLine[symbol.Value]; ok && index >= 0 {\n\t\t\tif _, ok := addresses[symbol.Name]; ok {\n\t\t\t\t// There is a duplicate. Mark it as unavailable.\n\t\t\t\taddresses[symbol.Name] = -1\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\taddresses[symbol.Name] = index\n\t\t}\n\t}\n\n\treturn addresses, lines, nil\n}\n\n// loadProgramSize calculate a program/data size breakdown of each package for a\n// given ELF file.\n// If the file doesn't contain DWARF debug information, the returned program\n// size will still have valid summaries but won't have complete size information\n// per package.\nfunc loadProgramSize(path string, packagePathMap map[string]string) (*programSize, error) {\n\t// Open the binary file.\n\tf, err := os.Open(path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer f.Close()\n\n\t// This stores all chunks of addresses found in the binary.\n\tvar addresses []addressLine\n\n\t// Load the binary file, which could be in a number of file formats.\n\tvar sections []memorySection\n\tif file, err := elf.NewFile(f); err == nil {\n\t\tvar codeAlignment uint64\n\t\tswitch file.Machine {\n\t\tcase elf.EM_ARM:\n\t\t\tcodeAlignment = 4 // usually 2, but can be 4\n\t\t}\n\t\t// Read DWARF information. The error is intentionally ignored.\n\t\tdata, _ := file.DWARF()\n\t\tif data != nil {\n\t\t\taddresses, err = readProgramSizeFromDWARF(data, 0, codeAlignment, true)\n\t\t\tif err != nil {\n\t\t\t\t// However, _do_ report an error here. Something must have gone\n\t\t\t\t// wrong while trying to parse DWARF data.\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\n\t\t// Read the ELF symbols for some more chunks of location information.\n\t\t// Some globals (such as strings) aren't stored in the DWARF debug\n\t\t// information and therefore need to be obtained in a different way.\n\t\tallSymbols, err := file.Symbols()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tfor _, symbol := range allSymbols {\n\t\t\tsymType := elf.ST_TYPE(symbol.Info)\n\t\t\tif symbol.Size == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif symType != elf.STT_FUNC && symType != elf.STT_OBJECT && symType != elf.STT_NOTYPE {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif symbol.Section >= elf.SHN_LORESERVE {\n\t\t\t\t// Not a regular section, so skip it.\n\t\t\t\t// One example is elf.SHN_ABS, which is used for symbols\n\t\t\t\t// declared with an absolute value such as the memset function\n\t\t\t\t// on the ESP32 which is defined in the mask ROM.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tsection := file.Sections[symbol.Section]\n\t\t\tif section.Flags&elf.SHF_ALLOC == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif packageSymbolRegexp.MatchString(symbol.Name) || symbol.Name == \"__isr_vector\" {\n\t\t\t\taddresses = append(addresses, addressLine{\n\t\t\t\t\tAddress:    symbol.Value,\n\t\t\t\t\tLength:     symbol.Size,\n\t\t\t\t\tFile:       symbol.Name,\n\t\t\t\t\tIsVariable: true,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\t// Load allocated sections.\n\t\tfor _, section := range file.Sections {\n\t\t\tif section.Flags&elf.SHF_ALLOC == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif section.Type == elf.SHT_NOBITS {\n\t\t\t\tif strings.HasPrefix(section.Name, \".stack\") {\n\t\t\t\t\t// TinyGo emits stack sections on microcontroller using the\n\t\t\t\t\t// \".stack\" name.\n\t\t\t\t\t// This is a bit ugly, but I don't think there is a way to\n\t\t\t\t\t// mark the stack section in a linker script.\n\t\t\t\t\tsections = append(sections, memorySection{\n\t\t\t\t\t\tAddress: section.Addr,\n\t\t\t\t\t\tSize:    section.Size,\n\t\t\t\t\t\tAlign:   section.Addralign,\n\t\t\t\t\t\tType:    memoryStack,\n\t\t\t\t\t})\n\t\t\t\t} else {\n\t\t\t\t\t// Regular .bss section.\n\t\t\t\t\tsections = append(sections, memorySection{\n\t\t\t\t\t\tAddress: section.Addr,\n\t\t\t\t\t\tSize:    section.Size,\n\t\t\t\t\t\tAlign:   section.Addralign,\n\t\t\t\t\t\tType:    memoryBSS,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t} else if section.Type == elf.SHT_PROGBITS && section.Flags&elf.SHF_EXECINSTR != 0 {\n\t\t\t\t// .text\n\t\t\t\tsections = append(sections, memorySection{\n\t\t\t\t\tAddress: section.Addr,\n\t\t\t\t\tSize:    section.Size,\n\t\t\t\t\tAlign:   section.Addralign,\n\t\t\t\t\tType:    memoryCode,\n\t\t\t\t})\n\t\t\t} else if section.Type == elf.SHT_PROGBITS && section.Flags&elf.SHF_WRITE != 0 {\n\t\t\t\t// .data\n\t\t\t\tsections = append(sections, memorySection{\n\t\t\t\t\tAddress: section.Addr,\n\t\t\t\t\tSize:    section.Size,\n\t\t\t\t\tAlign:   section.Addralign,\n\t\t\t\t\tType:    memoryData,\n\t\t\t\t})\n\t\t\t} else if section.Type == elf.SHT_PROGBITS {\n\t\t\t\t// .rodata\n\t\t\t\tsections = append(sections, memorySection{\n\t\t\t\t\tAddress: section.Addr,\n\t\t\t\t\tSize:    section.Size,\n\t\t\t\t\tAlign:   section.Addralign,\n\t\t\t\t\tType:    memoryROData,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t} else if file, err := macho.NewFile(f); err == nil {\n\t\t// Read segments, for use while reading through sections.\n\t\tsegments := map[string]*macho.Segment{}\n\t\tfor _, load := range file.Loads {\n\t\t\tswitch load := load.(type) {\n\t\t\tcase *macho.Segment:\n\t\t\t\tsegments[load.Name] = load\n\t\t\t}\n\t\t}\n\n\t\t// Read MachO sections.\n\t\tfor _, section := range file.Sections {\n\t\t\tsectionType := section.Flags & 0xff\n\t\t\tsectionFlags := section.Flags >> 8\n\t\t\tsegment := segments[section.Seg]\n\t\t\t// For the constants used here, see:\n\t\t\t// https://github.com/llvm/llvm-project/blob/release/14.x/llvm/include/llvm/BinaryFormat/MachO.h\n\t\t\tif sectionFlags&0x800000 != 0 { // S_ATTR_PURE_INSTRUCTIONS\n\t\t\t\t// Section containing only instructions.\n\t\t\t\tsections = append(sections, memorySection{\n\t\t\t\t\tAddress: section.Addr,\n\t\t\t\t\tSize:    uint64(section.Size),\n\t\t\t\t\tAlign:   uint64(section.Align),\n\t\t\t\t\tType:    memoryCode,\n\t\t\t\t})\n\t\t\t} else if sectionType == 1 { // S_ZEROFILL\n\t\t\t\t// Section filled with zeroes on demand.\n\t\t\t\tsections = append(sections, memorySection{\n\t\t\t\t\tAddress: section.Addr,\n\t\t\t\t\tSize:    uint64(section.Size),\n\t\t\t\t\tAlign:   uint64(section.Align),\n\t\t\t\t\tType:    memoryBSS,\n\t\t\t\t})\n\t\t\t} else if segment.Maxprot&0b011 == 0b001 { // --r (read-only data)\n\t\t\t\t// Protection doesn't allow writes, so mark this section read-only.\n\t\t\t\tsections = append(sections, memorySection{\n\t\t\t\t\tAddress: section.Addr,\n\t\t\t\t\tSize:    uint64(section.Size),\n\t\t\t\t\tAlign:   uint64(section.Align),\n\t\t\t\t\tType:    memoryROData,\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\t// The rest is assumed to be regular data.\n\t\t\t\tsections = append(sections, memorySection{\n\t\t\t\t\tAddress: section.Addr,\n\t\t\t\t\tSize:    uint64(section.Size),\n\t\t\t\t\tAlign:   uint64(section.Align),\n\t\t\t\t\tType:    memoryData,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\t// Read DWARF information.\n\t\t// The data isn't stored directly in the binary as in most executable\n\t\t// formats. Instead, it is left in the object files that were used as a\n\t\t// basis for linking. The executable does however contain STABS debug\n\t\t// information that points to the source object file and is used by\n\t\t// debuggers.\n\t\t// For more information:\n\t\t// http://wiki.dwarfstd.org/index.php?title=Apple%27s_%22Lazy%22_DWARF_Scheme\n\t\tvar objSymbolNames map[string]int\n\t\tvar objAddresses []addressLine\n\t\tvar previousSymbol macho.Symbol\n\t\tfor _, symbol := range file.Symtab.Syms {\n\t\t\t// STABS constants, from mach-o/stab.h:\n\t\t\t// https://opensource.apple.com/source/xnu/xnu-7195.141.2/EXTERNAL_HEADERS/mach-o/stab.h.auto.html\n\t\t\tconst (\n\t\t\t\tN_GSYM  = 0x20\n\t\t\t\tN_FUN   = 0x24\n\t\t\t\tN_STSYM = 0x26\n\t\t\t\tN_SO    = 0x64\n\t\t\t\tN_OSO   = 0x66\n\t\t\t)\n\t\t\tif symbol.Type == N_OSO {\n\t\t\t\t// Found an object file. Now try to parse it.\n\t\t\t\tobjSymbolNames, objAddresses, err = readMachOSymbolAddresses(symbol.Name)\n\t\t\t\tif err != nil && sizesDebug {\n\t\t\t\t\t// Errors are normally ignored. If there is an error, it's\n\t\t\t\t\t// simply treated as that the DWARF is not available.\n\t\t\t\t\tfmt.Fprintf(os.Stderr, \"could not read DWARF from file %s: %s\\n\", symbol.Name, err)\n\t\t\t\t}\n\t\t\t} else if symbol.Type == N_FUN {\n\t\t\t\t// Found a function.\n\t\t\t\t// The way this is encoded is a bit weird. MachO symbols don't\n\t\t\t\t// have a length. What I've found is that the length is encoded\n\t\t\t\t// by first having a N_FUN symbol as usual, and then having a\n\t\t\t\t// symbol with a zero-length name that has the value not set to\n\t\t\t\t// the address of the symbol but to the length. So in order to\n\t\t\t\t// get both the address and the length, we look for a symbol\n\t\t\t\t// with a name followed by a symbol without a name.\n\t\t\t\tif symbol.Name == \"\" && previousSymbol.Type == N_FUN && previousSymbol.Name != \"\" {\n\t\t\t\t\t// Functions are encoded as many small chunks in the line\n\t\t\t\t\t// table (one or a few instructions per source line). But\n\t\t\t\t\t// the symbol length covers the whole symbols, over many\n\t\t\t\t\t// lines and possibly including inlined functions. So we\n\t\t\t\t\t// continue to iterate through the objAddresses slice until\n\t\t\t\t\t// we've found all the source lines that are part of this\n\t\t\t\t\t// symbol.\n\t\t\t\t\taddress := previousSymbol.Value\n\t\t\t\t\tlength := symbol.Value\n\t\t\t\t\tif index, ok := objSymbolNames[previousSymbol.Name]; ok && index >= 0 {\n\t\t\t\t\t\tfor length > 0 {\n\t\t\t\t\t\t\tline := objAddresses[index]\n\t\t\t\t\t\t\tline.Address = address\n\t\t\t\t\t\t\tif line.Length > length {\n\t\t\t\t\t\t\t\t// Line extends beyond the end of te symbol?\n\t\t\t\t\t\t\t\t// Weird, shouldn't happen.\n\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\taddresses = append(addresses, line)\n\t\t\t\t\t\t\tindex++\n\t\t\t\t\t\t\tlength -= line.Length\n\t\t\t\t\t\t\taddress += line.Length\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if symbol.Type == N_GSYM || symbol.Type == N_STSYM {\n\t\t\t\t// Global variables.\n\t\t\t\tif index, ok := objSymbolNames[symbol.Name]; ok {\n\t\t\t\t\taddress := objAddresses[index]\n\t\t\t\t\taddress.Address = symbol.Value\n\t\t\t\t\taddresses = append(addresses, address)\n\t\t\t\t}\n\t\t\t}\n\t\t\tpreviousSymbol = symbol\n\t\t}\n\t} else if file, err := pe.NewFile(f); err == nil {\n\t\t// Read DWARF information. The error is intentionally ignored.\n\t\tdata, _ := file.DWARF()\n\t\tif data != nil {\n\t\t\taddresses, err = readProgramSizeFromDWARF(data, 0, 0, true)\n\t\t\tif err != nil {\n\t\t\t\t// However, _do_ report an error here. Something must have gone\n\t\t\t\t// wrong while trying to parse DWARF data.\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\n\t\t// Read COFF sections.\n\t\toptionalHeader := file.OptionalHeader.(*pe.OptionalHeader64)\n\t\tfor _, section := range file.Sections {\n\t\t\t// For more information:\n\t\t\t// https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_section_header\n\t\t\tconst (\n\t\t\t\tIMAGE_SCN_CNT_CODE             = 0x00000020\n\t\t\t\tIMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040\n\t\t\t\tIMAGE_SCN_MEM_DISCARDABLE      = 0x02000000\n\t\t\t\tIMAGE_SCN_MEM_READ             = 0x40000000\n\t\t\t\tIMAGE_SCN_MEM_WRITE            = 0x80000000\n\t\t\t)\n\t\t\tif section.Characteristics&IMAGE_SCN_MEM_DISCARDABLE != 0 {\n\t\t\t\t// Debug sections, etc.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\taddress := uint64(section.VirtualAddress) + optionalHeader.ImageBase\n\t\t\tif section.Characteristics&IMAGE_SCN_CNT_CODE != 0 {\n\t\t\t\t// .text\n\t\t\t\tsections = append(sections, memorySection{\n\t\t\t\t\tAddress: address,\n\t\t\t\t\tSize:    uint64(section.VirtualSize),\n\t\t\t\t\tType:    memoryCode,\n\t\t\t\t})\n\t\t\t} else if section.Characteristics&IMAGE_SCN_CNT_INITIALIZED_DATA != 0 {\n\t\t\t\tif section.Characteristics&IMAGE_SCN_MEM_WRITE != 0 {\n\t\t\t\t\t// .data\n\t\t\t\t\tsections = append(sections, memorySection{\n\t\t\t\t\t\tAddress: address,\n\t\t\t\t\t\tSize:    uint64(section.Size),\n\t\t\t\t\t\tType:    memoryData,\n\t\t\t\t\t})\n\t\t\t\t\tif section.Size < section.VirtualSize {\n\t\t\t\t\t\t// Equivalent of a .bss section.\n\t\t\t\t\t\t// Note: because of how the PE/COFF format is\n\t\t\t\t\t\t// structured, not all zero-initialized data is marked\n\t\t\t\t\t\t// as such. A portion may be at the end of the .data\n\t\t\t\t\t\t// section and is thus marked as initialized data.\n\t\t\t\t\t\tsections = append(sections, memorySection{\n\t\t\t\t\t\t\tAddress: address + uint64(section.Size),\n\t\t\t\t\t\t\tSize:    uint64(section.VirtualSize) - uint64(section.Size),\n\t\t\t\t\t\t\tType:    memoryBSS,\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t} else if section.Characteristics&IMAGE_SCN_MEM_READ != 0 {\n\t\t\t\t\t// .rdata, .buildid, .pdata\n\t\t\t\t\tsections = append(sections, memorySection{\n\t\t\t\t\t\tAddress: address,\n\t\t\t\t\t\tSize:    uint64(section.VirtualSize),\n\t\t\t\t\t\tType:    memoryROData,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else if file, err := wasm.Parse(f); err == nil {\n\t\t// File is in WebAssembly format.\n\n\t\t// Put code at a very high address, so that it won't conflict with the\n\t\t// data in the memory section.\n\t\tconst codeOffset = 0x8000_0000_0000_0000\n\n\t\t// Read DWARF information. The error is intentionally ignored.\n\t\tdata, _ := file.DWARF()\n\t\tif data != nil {\n\t\t\taddresses, err = readProgramSizeFromDWARF(data, codeOffset, 0, true)\n\t\t\tif err != nil {\n\t\t\t\t// However, _do_ report an error here. Something must have gone\n\t\t\t\t// wrong while trying to parse DWARF data.\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\n\t\tvar linearMemorySize uint64\n\t\tfor _, section := range file.Sections {\n\t\t\tswitch section := section.(type) {\n\t\t\tcase *wasm.SectionCode:\n\t\t\t\tsections = append(sections, memorySection{\n\t\t\t\t\tAddress: codeOffset,\n\t\t\t\t\tSize:    uint64(section.Size()),\n\t\t\t\t\tType:    memoryCode,\n\t\t\t\t})\n\t\t\tcase *wasm.SectionMemory:\n\t\t\t\t// This value is used when processing *wasm.SectionData (which\n\t\t\t\t// always comes after *wasm.SectionMemory).\n\t\t\t\tlinearMemorySize = uint64(section.Entries[0].Limits.Initial) * 64 * 1024\n\t\t\tcase *wasm.SectionData:\n\t\t\t\t// Data sections contain initial values for linear memory.\n\t\t\t\t// First load the list of data sections, and sort them by\n\t\t\t\t// address for easier processing.\n\t\t\t\tvar dataSections []memorySection\n\t\t\t\tfor _, entry := range section.Entries {\n\t\t\t\t\taddress, err := wasm.Eval(bytes.NewBuffer(entry.Offset))\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn nil, fmt.Errorf(\"could not parse data section address: %w\", err)\n\t\t\t\t\t}\n\t\t\t\t\tdataSections = append(dataSections, memorySection{\n\t\t\t\t\t\tAddress: uint64(address[0].(int32)),\n\t\t\t\t\t\tSize:    uint64(len(entry.Data)),\n\t\t\t\t\t\tType:    memoryData,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tsort.Slice(dataSections, func(i, j int) bool {\n\t\t\t\t\treturn dataSections[i].Address < dataSections[j].Address\n\t\t\t\t})\n\n\t\t\t\t// And now add all data sections for linear memory.\n\t\t\t\t// Parts that are in the slice of data sections are added as\n\t\t\t\t// memoryData, and parts that are not are added as memoryBSS.\n\t\t\t\taddr := uint64(0)\n\t\t\t\tfor _, section := range dataSections {\n\t\t\t\t\tif addr < section.Address {\n\t\t\t\t\t\tsections = append(sections, memorySection{\n\t\t\t\t\t\t\tAddress: addr,\n\t\t\t\t\t\t\tSize:    section.Address - addr,\n\t\t\t\t\t\t\tType:    memoryBSS,\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t\tif addr > section.Address {\n\t\t\t\t\t\t// This might be allowed, I'm not sure.\n\t\t\t\t\t\t// It certainly doesn't make a lot of sense.\n\t\t\t\t\t\treturn nil, fmt.Errorf(\"overlapping data section\")\n\t\t\t\t\t}\n\t\t\t\t\t// addr == section.Address\n\t\t\t\t\tsections = append(sections, section)\n\t\t\t\t\taddr = section.Address + section.Size\n\t\t\t\t}\n\t\t\t\tif addr < linearMemorySize {\n\t\t\t\t\tsections = append(sections, memorySection{\n\t\t\t\t\t\tAddress: addr,\n\t\t\t\t\t\tSize:    linearMemorySize - addr,\n\t\t\t\t\t\tType:    memoryBSS,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\treturn nil, fmt.Errorf(\"could not parse file: %w\", err)\n\t}\n\n\t// Sort the slice of address chunks by address, so that we can iterate\n\t// through it to calculate section sizes.\n\tsort.Slice(addresses, func(i, j int) bool {\n\t\tif addresses[i].Address == addresses[j].Address {\n\t\t\t// Very rarely, there might be duplicate addresses.\n\t\t\t// If that happens, sort the largest chunks first.\n\t\t\treturn addresses[i].Length > addresses[j].Length\n\t\t}\n\t\treturn addresses[i].Address < addresses[j].Address\n\t})\n\n\t// Now finally determine the binary/RAM size usage per package by going\n\t// through each allocated section.\n\tsizes := make(map[string]*packageSize)\n\tprogram := &programSize{\n\t\tPackages: sizes,\n\t}\n\tfor _, section := range sections {\n\t\tswitch section.Type {\n\t\tcase memoryCode:\n\t\t\treadSection(section, addresses, program, func(ps *packageSize, isVariable bool) *uint64 {\n\t\t\t\tif isVariable {\n\t\t\t\t\treturn &ps.ROData\n\t\t\t\t}\n\t\t\t\treturn &ps.Code\n\t\t\t}, packagePathMap)\n\t\tcase memoryROData:\n\t\t\treadSection(section, addresses, program, func(ps *packageSize, isVariable bool) *uint64 {\n\t\t\t\treturn &ps.ROData\n\t\t\t}, packagePathMap)\n\t\tcase memoryData:\n\t\t\treadSection(section, addresses, program, func(ps *packageSize, isVariable bool) *uint64 {\n\t\t\t\treturn &ps.Data\n\t\t\t}, packagePathMap)\n\t\tcase memoryBSS:\n\t\t\treadSection(section, addresses, program, func(ps *packageSize, isVariable bool) *uint64 {\n\t\t\t\treturn &ps.BSS\n\t\t\t}, packagePathMap)\n\t\tcase memoryStack:\n\t\t\t// We store the C stack as a pseudo-package.\n\t\t\tprogram.getPackage(\"C stack\").addSize(func(ps *packageSize, isVariable bool) *uint64 {\n\t\t\t\treturn &ps.BSS\n\t\t\t}, \"\", section.Size, false)\n\t\t}\n\t}\n\n\t// ...and summarize the results.\n\tfor _, pkg := range sizes {\n\t\tprogram.Code += pkg.Code\n\t\tprogram.ROData += pkg.ROData\n\t\tprogram.Data += pkg.Data\n\t\tprogram.BSS += pkg.BSS\n\t}\n\treturn program, nil\n}\n\n// readSection determines for each byte in this section to which package it\n// belongs.\nfunc readSection(section memorySection, addresses []addressLine, program *programSize, getField func(*packageSize, bool) *uint64, packagePathMap map[string]string) {\n\t// The addr variable tracks at which address we are while going through this\n\t// section. We start at the beginning.\n\taddr := section.Address\n\tsectionEnd := section.Address + section.Size\n\tif sizesDebug {\n\t\tfmt.Printf(\"%08x..%08x %5d: %s\\n\", addr, sectionEnd, section.Size, section.Type)\n\t}\n\tfor _, line := range addresses {\n\t\tif line.Address < section.Address || line.Address+line.Length > sectionEnd {\n\t\t\t// Check that this line is entirely within the section.\n\t\t\t// Don't bother dealing with line entries that cross sections (that\n\t\t\t// seems rather unlikely anyway).\n\t\t\tcontinue\n\t\t}\n\t\tif addr < line.Address {\n\t\t\t// There is a gap: there is a space between the current and the\n\t\t\t// previous line entry.\n\t\t\t// Check whether this is caused by alignment requirements.\n\t\t\taddrAligned := (addr + line.Align - 1) &^ (line.Align - 1)\n\t\t\tif line.Align > 1 && addrAligned >= line.Address {\n\t\t\t\t// It is, assume that's what causes the gap.\n\t\t\t\tprogram.getPackage(\"(padding)\").addSize(getField, \"\", line.Address-addr, true)\n\t\t\t} else {\n\t\t\t\tprogram.getPackage(\"(unknown)\").addSize(getField, \"\", line.Address-addr, false)\n\t\t\t\tif sizesDebug {\n\t\t\t\t\tfmt.Printf(\"%08x..%08x %5d:  unknown (gap), alignment=%d\\n\", addr, line.Address, line.Address-addr, line.Align)\n\t\t\t\t}\n\t\t\t}\n\t\t\taddr = line.Address\n\t\t}\n\t\tif addr > line.Address+line.Length {\n\t\t\t// The current line is already covered by a previous line entry.\n\t\t\t// Simply skip it.\n\t\t\tcontinue\n\t\t}\n\t\t// At this point, addr falls within the current line (probably at the\n\t\t// start).\n\t\tlength := line.Length\n\t\tif addr > line.Address {\n\t\t\t// There is some overlap: the previous line entry already covered\n\t\t\t// part of this line entry. So reduce the length to add to the\n\t\t\t// remaining bit of the line entry.\n\t\t\tlength = line.Length - (addr - line.Address)\n\t\t}\n\t\t// Finally, mark this chunk of memory as used by the given package.\n\t\tpackagePath, filename := findPackagePath(line.File, packagePathMap)\n\t\tprogram.getPackage(packagePath).addSize(getField, filename, length, line.IsVariable)\n\t\taddr = line.Address + line.Length\n\t}\n\tif addr < sectionEnd {\n\t\t// There is a gap at the end of the section.\n\t\taddrAligned := (addr + section.Align - 1) &^ (section.Align - 1)\n\t\tif section.Align > 1 && addrAligned >= sectionEnd {\n\t\t\t// The gap is caused by the section alignment.\n\t\t\t// For example, if a .rodata section ends with a non-aligned string.\n\t\t\tprogram.getPackage(\"(padding)\").addSize(getField, \"\", sectionEnd-addr, true)\n\t\t} else {\n\t\t\tprogram.getPackage(\"(unknown)\").addSize(getField, \"\", sectionEnd-addr, false)\n\t\t\tif sizesDebug {\n\t\t\t\tfmt.Printf(\"%08x..%08x %5d:  unknown (end), alignment=%d\\n\", addr, sectionEnd, sectionEnd-addr, section.Align)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// findPackagePath returns the Go package (or a pseudo package) for the given\n// path. It uses some heuristics, for example for some C libraries.\nfunc findPackagePath(path string, packagePathMap map[string]string) (packagePath, filename string) {\n\t// Check whether this path is part of one of the compiled packages.\n\tpackagePath, ok := packagePathMap[filepath.Dir(path)]\n\tif ok {\n\t\t// Directory is known as a Go package.\n\t\t// Add the file itself as well.\n\t\tfilename = filepath.Base(path)\n\t} else {\n\t\tif strings.HasPrefix(path, filepath.Join(goenv.Get(\"TINYGOROOT\"), \"lib\")) {\n\t\t\t// Emit C libraries (in the lib subdirectory of TinyGo) as a single\n\t\t\t// package, with a \"C\" prefix. For example: \"C picolibc\" for the\n\t\t\t// baremetal libc.\n\t\t\tlibPath := strings.TrimPrefix(path, filepath.Join(goenv.Get(\"TINYGOROOT\"), \"lib\")+string(os.PathSeparator))\n\t\t\tparts := strings.SplitN(libPath, string(os.PathSeparator), 2)\n\t\t\tpackagePath = \"C \" + parts[0]\n\t\t\tfilename = parts[1]\n\t\t} else if prefix := filepath.Join(goenv.Get(\"TINYGOROOT\"), \"llvm-project\", \"compiler-rt\"); strings.HasPrefix(path, prefix) {\n\t\t\tpackagePath = \"C compiler-rt\"\n\t\t\tfilename = strings.TrimPrefix(path, prefix+string(os.PathSeparator))\n\t\t} else if packageSymbolRegexp.MatchString(path) {\n\t\t\t// Parse symbol names like main$alloc or runtime$string.\n\t\t\tpackagePath = path[:strings.LastIndex(path, \"$\")]\n\t\t} else if path == \"__isr_vector\" {\n\t\t\tpackagePath = \"C interrupt vector\"\n\t\t} else if path == \"<Go type>\" {\n\t\t\tpackagePath = \"Go types\"\n\t\t} else if path == \"<Go interface assert>\" {\n\t\t\t// Interface type assert, generated by the interface lowering pass.\n\t\t\tpackagePath = \"Go interface assert\"\n\t\t} else if path == \"<Go interface method>\" {\n\t\t\t// Interface method wrapper (switch over all concrete types),\n\t\t\t// generated by the interface lowering pass.\n\t\t\tpackagePath = \"Go interface method\"\n\t\t} else if path == \"<stdin>\" {\n\t\t\t// This can happen when the source code (in Go) doesn't have a\n\t\t\t// source file and uses \"-\" as the location. Somewhere this is\n\t\t\t// converted to \"<stdin>\".\n\t\t\t// Convert this back to the \"-\" string. Eventually, this should be\n\t\t\t// fixed in the compiler.\n\t\t\tpackagePath = \"-\"\n\t\t} else {\n\t\t\t// This is some other path. Not sure what it is, so just emit its\n\t\t\t// directory as a fallback.\n\t\t\tpackagePath = filepath.Dir(path)\n\t\t\tfilename = filepath.Base(path)\n\t\t}\n\t}\n\treturn\n}\n"
  },
  {
    "path": "builder/sizes_test.go",
    "content": "package builder\n\nimport (\n\t\"regexp\"\n\t\"runtime\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/tinygo-org/tinygo/compileopts\"\n)\n\nvar sema = make(chan struct{}, runtime.NumCPU())\n\ntype sizeTest struct {\n\ttarget     string\n\tpath       string\n\tcodeSize   uint64\n\trodataSize uint64\n\tdataSize   uint64\n\tbssSize    uint64\n}\n\n// Test whether code and data size is as expected for the given targets.\n// This tests both the logic of loadProgramSize and checks that code size\n// doesn't change unintentionally.\n//\n// If you find that code or data size is reduced, then great! You can reduce the\n// number in this test.\n// If you find that the code or data size is increased, take a look as to why\n// this is. It could be due to an update (LLVM version, Go version, etc) which\n// is fine, but it could also mean that a recent change introduced this size\n// increase. If so, please consider whether this new feature is indeed worth the\n// size increase for all users.\nfunc TestBinarySize(t *testing.T) {\n\tif runtime.GOOS == \"linux\" && !hasBuiltinTools {\n\t\t// Debian LLVM packages are modified a bit and tend to produce\n\t\t// different machine code. Ideally we'd fix this (with some attributes\n\t\t// or something?), but for now skip it.\n\t\tt.Skip(\"Skip: using external LLVM version so binary size might differ\")\n\t}\n\n\t// This is a small number of very diverse targets that we want to test.\n\ttests := []sizeTest{\n\t\t// microcontrollers\n\t\t{\"hifive1b\", \"examples/echo\", 3668, 280, 0, 2244},\n\t\t{\"microbit\", \"examples/serial\", 2694, 342, 8, 2248},\n\t\t{\"wioterminal\", \"examples/pininterrupt\", 7187, 1489, 116, 6888},\n\n\t\t// TODO: also check wasm. Right now this is difficult, because\n\t\t// wasm binaries are run through wasm-opt and therefore the\n\t\t// output varies by binaryen version.\n\t}\n\tfor _, tc := range tests {\n\t\ttc := tc\n\t\tt.Run(tc.target+\"/\"+tc.path, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\t// Build the binary.\n\t\t\tresult := buildBinary(t, tc.target, tc.path)\n\n\t\t\t// Check whether the size of the binary matches the expected size.\n\t\t\tsizes, err := loadProgramSize(result.Executable, nil)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(\"could not read program size:\", err)\n\t\t\t}\n\t\t\tif sizes.Code != tc.codeSize || sizes.ROData != tc.rodataSize || sizes.Data != tc.dataSize || sizes.BSS != tc.bssSize {\n\t\t\t\tt.Errorf(\"Unexpected code size when compiling: -target=%s %s\", tc.target, tc.path)\n\t\t\t\tt.Errorf(\"            code rodata   data    bss\")\n\t\t\t\tt.Errorf(\"expected: %6d %6d %6d %6d\", tc.codeSize, tc.rodataSize, tc.dataSize, tc.bssSize)\n\t\t\t\tt.Errorf(\"actual:   %6d %6d %6d %6d\", sizes.Code, sizes.ROData, sizes.Data, sizes.BSS)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Check that the -size=full flag attributes binary size to the correct package\n// without filesystem paths and things like that.\nfunc TestSizeFull(t *testing.T) {\n\ttests := []string{\n\t\t\"microbit\",\n\t\t\"wasip1\",\n\t}\n\n\tlibMatch := regexp.MustCompile(`^C [a-z -]+$`) // example: \"C interrupt vector\"\n\tpkgMatch := regexp.MustCompile(`^[a-z/]+$`)    // example: \"internal/task\"\n\n\tfor _, target := range tests {\n\t\ttarget := target\n\t\tt.Run(target, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\t// Build the binary.\n\t\t\tresult := buildBinary(t, target, \"examples/serial\")\n\n\t\t\t// Check whether the binary doesn't contain any unexpected package\n\t\t\t// names.\n\t\t\tsizes, err := loadProgramSize(result.Executable, result.PackagePathMap)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(\"could not read program size:\", err)\n\t\t\t}\n\t\t\tfor _, pkg := range sizes.sortedPackageNames() {\n\t\t\t\tif pkg == \"(padding)\" || pkg == \"(unknown)\" {\n\t\t\t\t\t// TODO: correctly attribute all unknown binary size.\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif libMatch.MatchString(pkg) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif pkgMatch.MatchString(pkg) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tt.Error(\"unexpected package name in size output:\", pkg)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc buildBinary(t *testing.T, targetString, pkgName string) BuildResult {\n\toptions := compileopts.Options{\n\t\tTarget:        targetString,\n\t\tOpt:           \"z\",\n\t\tSemaphore:     sema,\n\t\tInterpTimeout: 60 * time.Second,\n\t\tDebug:         true,\n\t\tVerifyIR:      true,\n\t}\n\ttarget, err := compileopts.LoadTarget(&options)\n\tif err != nil {\n\t\tt.Fatal(\"could not load target:\", err)\n\t}\n\tconfig := &compileopts.Config{\n\t\tOptions: &options,\n\t\tTarget:  target,\n\t}\n\tresult, err := Build(pkgName, \"\", t.TempDir(), config)\n\tif err != nil {\n\t\tt.Fatal(\"could not build:\", err)\n\t}\n\treturn result\n}\n"
  },
  {
    "path": "builder/tools-builtin.go",
    "content": "//go:build byollvm\n\npackage builder\n\nimport (\n\t\"errors\"\n\t\"unsafe\"\n)\n\n/*\n#cgo CXXFLAGS: -fno-rtti\n#include <stdbool.h>\n#include <stdlib.h>\nbool tinygo_clang_driver(int argc, char **argv);\nbool tinygo_link(int argc, char **argv);\n*/\nimport \"C\"\n\nconst hasBuiltinTools = true\n\n// RunTool runs the given tool (such as clang).\n//\n// This version actually runs the tools because TinyGo was compiled while\n// linking statically with LLVM (with the byollvm build tag).\nfunc RunTool(tool string, args ...string) error {\n\targs = append([]string{tool}, args...)\n\n\tvar cflag *C.char\n\tbuf := C.calloc(C.size_t(len(args)), C.size_t(unsafe.Sizeof(cflag)))\n\tdefer C.free(buf)\n\tcflags := (*[1 << 10]*C.char)(unsafe.Pointer(buf))[:len(args):len(args)]\n\tfor i, flag := range args {\n\t\tcflag := C.CString(flag)\n\t\tcflags[i] = cflag\n\t\tdefer C.free(unsafe.Pointer(cflag))\n\t}\n\n\tvar ok C.bool\n\tswitch tool {\n\tcase \"clang\":\n\t\tok = C.tinygo_clang_driver(C.int(len(args)), (**C.char)(buf))\n\tcase \"ld.lld\", \"wasm-ld\":\n\t\tok = C.tinygo_link(C.int(len(args)), (**C.char)(buf))\n\tdefault:\n\t\treturn errors.New(\"unknown tool: \" + tool)\n\t}\n\tif !ok {\n\t\treturn errors.New(\"failed to run tool: \" + tool)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "builder/tools-external.go",
    "content": "//go:build !byollvm\n\npackage builder\n\nimport \"errors\"\n\nconst hasBuiltinTools = false\n\n// RunTool runs the given tool (such as clang).\n//\n// This version doesn't actually run the tool: TinyGo has not been compiled by\n// statically linking to LLVM.\nfunc RunTool(tool string, args ...string) error {\n\treturn errors.New(\"cannot run tool: \" + tool)\n}\n"
  },
  {
    "path": "builder/tools.go",
    "content": "package builder\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/scanner\"\n\t\"go/token\"\n\t\"os\"\n\t\"os/exec\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// runCCompiler invokes a C compiler with the given arguments.\nfunc runCCompiler(flags ...string) error {\n\t// Find the right command to run Clang.\n\tvar cmd *exec.Cmd\n\tif hasBuiltinTools {\n\t\t// Compile this with the internal Clang compiler.\n\t\tcmd = exec.Command(os.Args[0], append([]string{\"clang\"}, flags...)...)\n\t} else {\n\t\t// Compile this with an external invocation of the Clang compiler.\n\t\tname, err := LookupCommand(\"clang\")\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tcmd = exec.Command(name, flags...)\n\t}\n\n\tcmd.Stdout = os.Stdout\n\tcmd.Stderr = os.Stderr\n\n\t// Make sure the command doesn't use any environmental variables.\n\t// Most importantly, it should not use C_INCLUDE_PATH and the like.\n\tcmd.Env = []string{}\n\n\t// Let some environment variables through. One important one is the\n\t// temporary directory, especially on Windows it looks like Clang breaks if\n\t// the temporary directory has not been set.\n\t// See: https://github.com/tinygo-org/tinygo/issues/4557\n\t// Also see: https://github.com/llvm/llvm-project/blob/release/18.x/llvm/lib/Support/Unix/Path.inc#L1435\n\tfor _, env := range os.Environ() {\n\t\t// We could parse the key and look it up in a map, but since there are\n\t\t// only a few keys iterating through them is easier and maybe even\n\t\t// faster.\n\t\tfor _, prefix := range []string{\"TMPDIR=\", \"TMP=\", \"TEMP=\", \"TEMPDIR=\"} {\n\t\t\tif strings.HasPrefix(env, prefix) {\n\t\t\t\tcmd.Env = append(cmd.Env, env)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\treturn cmd.Run()\n}\n\n// link invokes a linker with the given name and flags.\nfunc link(linker string, flags ...string) error {\n\t// We only support LLD.\n\tif linker != \"ld.lld\" && linker != \"wasm-ld\" {\n\t\treturn fmt.Errorf(\"unexpected: linker %s should be ld.lld or wasm-ld\", linker)\n\t}\n\n\tvar cmd *exec.Cmd\n\tif hasBuiltinTools {\n\t\tcmd = exec.Command(os.Args[0], append([]string{linker}, flags...)...)\n\t} else {\n\t\tname, err := LookupCommand(linker)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tcmd = exec.Command(name, flags...)\n\t}\n\tvar buf bytes.Buffer\n\tcmd.Stdout = os.Stdout\n\tcmd.Stderr = &buf\n\terr := cmd.Run()\n\tif err != nil {\n\t\tif buf.Len() == 0 {\n\t\t\t// The linker failed but there was no output.\n\t\t\t// Therefore, show some output anyway.\n\t\t\treturn fmt.Errorf(\"failed to run linker: %w\", err)\n\t\t}\n\t\treturn parseLLDErrors(buf.String())\n\t}\n\treturn nil\n}\n\n// Split LLD errors into individual erros (including errors that continue on the\n// next line, using a \">>>\" prefix). If possible, replace the raw errors with a\n// more user-friendly version (and one that's more in a Go style).\nfunc parseLLDErrors(text string) error {\n\t// Split linker output in separate error messages.\n\tlines := strings.Split(text, \"\\n\")\n\tvar errorLines []string // one or more line (belonging to a single error) per line\n\tfor _, line := range lines {\n\t\tline = strings.TrimRight(line, \"\\r\") // needed for Windows\n\t\tif len(errorLines) != 0 && strings.HasPrefix(line, \">>> \") {\n\t\t\terrorLines[len(errorLines)-1] += \"\\n\" + line\n\t\t\tcontinue\n\t\t}\n\t\tif line == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\terrorLines = append(errorLines, line)\n\t}\n\n\t// Parse error messages.\n\tvar linkErrors []error\n\tvar flashOverflow, ramOverflow uint64\n\tfor _, message := range errorLines {\n\t\tparsedError := false\n\n\t\t// Check for undefined symbols.\n\t\t// This can happen in some cases like with CGo and //go:linkname tricker.\n\t\tif matches := regexp.MustCompile(`^ld.lld(-[0-9]+)?: error: undefined symbol: (.*)\\n`).FindStringSubmatch(message); matches != nil {\n\t\t\tsymbolName := matches[2]\n\t\t\tfor _, line := range strings.Split(message, \"\\n\") {\n\t\t\t\tmatches := regexp.MustCompile(`referenced by .* \\(((.*):([0-9]+))\\)`).FindStringSubmatch(line)\n\t\t\t\tif matches != nil {\n\t\t\t\t\tparsedError = true\n\t\t\t\t\tline, _ := strconv.Atoi(matches[3])\n\t\t\t\t\t// TODO: detect common mistakes like -gc=none?\n\t\t\t\t\tlinkErrors = append(linkErrors, scanner.Error{\n\t\t\t\t\t\tPos: token.Position{\n\t\t\t\t\t\t\tFilename: matches[2],\n\t\t\t\t\t\t\tLine:     line,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tMsg: \"linker could not find symbol \" + symbolName,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check for flash/RAM overflow.\n\t\tif matches := regexp.MustCompile(`^ld.lld(-[0-9]+)?: error: section '(.*?)' will not fit in region '(.*?)': overflowed by ([0-9]+) bytes$`).FindStringSubmatch(message); matches != nil {\n\t\t\tregion := matches[3]\n\t\t\tn, err := strconv.ParseUint(matches[4], 10, 64)\n\t\t\tif err != nil {\n\t\t\t\t// Should not happen at all (unless it overflows an uint64 for some reason).\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Check which area overflowed.\n\t\t\t// Some chips use differently named memory areas, but these are by\n\t\t\t// far the most common.\n\t\t\tswitch region {\n\t\t\tcase \"FLASH_TEXT\":\n\t\t\t\tif n > flashOverflow {\n\t\t\t\t\tflashOverflow = n\n\t\t\t\t}\n\t\t\t\tparsedError = true\n\t\t\tcase \"RAM\":\n\t\t\t\tif n > ramOverflow {\n\t\t\t\t\tramOverflow = n\n\t\t\t\t}\n\t\t\t\tparsedError = true\n\t\t\t}\n\t\t}\n\n\t\t// If we couldn't parse the linker error: show the error as-is to\n\t\t// the user.\n\t\tif !parsedError {\n\t\t\tlinkErrors = append(linkErrors, LinkerError{message})\n\t\t}\n\t}\n\n\tif flashOverflow > 0 {\n\t\tlinkErrors = append(linkErrors, LinkerError{\n\t\t\tMsg: fmt.Sprintf(\"program too large for this chip (flash overflowed by %d bytes)\\n\\toptimization guide: https://tinygo.org/docs/guides/optimizing-binaries/\", flashOverflow),\n\t\t})\n\t}\n\tif ramOverflow > 0 {\n\t\tlinkErrors = append(linkErrors, LinkerError{\n\t\t\tMsg: fmt.Sprintf(\"program uses too much static RAM on this chip (RAM overflowed by %d bytes)\", ramOverflow),\n\t\t})\n\t}\n\n\treturn newMultiError(linkErrors, \"\")\n}\n\n// LLD linker error that could not be parsed or doesn't refer to a source\n// location.\ntype LinkerError struct {\n\tMsg string\n}\n\nfunc (e LinkerError) Error() string {\n\treturn e.Msg\n}\n"
  },
  {
    "path": "builder/uf2.go",
    "content": "package builder\n\n// This file converts firmware files from BIN to UF2 format before flashing.\n//\n// For more information about the UF2 firmware file format, please see:\n// https://github.com/Microsoft/uf2\n//\n//\n\nimport (\n\t\"bytes\"\n\t\"encoding/binary\"\n\t\"os\"\n\t\"strconv\"\n)\n\n// convertELFFileToUF2File converts an ELF file to a UF2 file.\nfunc convertELFFileToUF2File(infile, outfile string, uf2FamilyID string) error {\n\t// Read the .text segment.\n\ttargetAddress, data, err := extractROM(infile)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\toutput, _, err := convertBinToUF2(data, uint32(targetAddress), uf2FamilyID)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn os.WriteFile(outfile, output, 0644)\n}\n\n// convertBinToUF2 converts the binary bytes in input to UF2 formatted data.\nfunc convertBinToUF2(input []byte, targetAddr uint32, uf2FamilyID string) ([]byte, int, error) {\n\tblocks := split(input, 256)\n\toutput := make([]byte, 0)\n\n\tbl, err := newUF2Block(targetAddr, uf2FamilyID)\n\tif err != nil {\n\t\treturn nil, 0, err\n\t}\n\tbl.SetNumBlocks(len(blocks))\n\n\tfor i := 0; i < len(blocks); i++ {\n\t\tbl.SetBlockNo(i)\n\t\tbl.SetData(blocks[i])\n\n\t\toutput = append(output, bl.Bytes()...)\n\t\tbl.IncrementAddress(bl.payloadSize)\n\t}\n\n\treturn output, len(blocks), nil\n}\n\nconst (\n\tuf2MagicStart0 = 0x0A324655 // \"UF2\\n\"\n\tuf2MagicStart1 = 0x9E5D5157 // Randomly selected\n\tuf2MagicEnd    = 0x0AB16F30 // Ditto\n)\n\n// uf2Block is the structure used for each UF2 code block sent to device.\ntype uf2Block struct {\n\tmagicStart0 uint32\n\tmagicStart1 uint32\n\tflags       uint32\n\ttargetAddr  uint32\n\tpayloadSize uint32\n\tblockNo     uint32\n\tnumBlocks   uint32\n\tfamilyID    uint32\n\tdata        []uint8\n\tmagicEnd    uint32\n}\n\n// newUF2Block returns a new uf2Block struct that has been correctly populated\nfunc newUF2Block(targetAddr uint32, uf2FamilyID string) (*uf2Block, error) {\n\tvar flags uint32\n\tvar familyID uint32\n\tif uf2FamilyID != \"\" {\n\t\tflags |= flagFamilyIDPresent\n\t\tv, err := strconv.ParseUint(uf2FamilyID, 0, 32)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tfamilyID = uint32(v)\n\t}\n\treturn &uf2Block{magicStart0: uf2MagicStart0,\n\t\tmagicStart1: uf2MagicStart1,\n\t\tmagicEnd:    uf2MagicEnd,\n\t\ttargetAddr:  targetAddr,\n\t\tflags:       flags,\n\t\tfamilyID:    familyID,\n\t\tpayloadSize: 256,\n\t\tdata:        make([]byte, 476),\n\t}, nil\n}\n\nconst (\n\tflagFamilyIDPresent = 0x00002000\n)\n\n// Bytes converts the uf2Block to a slice of bytes that can be written to file.\nfunc (b *uf2Block) Bytes() []byte {\n\tbuf := bytes.NewBuffer(make([]byte, 0, 512))\n\tbinary.Write(buf, binary.LittleEndian, b.magicStart0)\n\tbinary.Write(buf, binary.LittleEndian, b.magicStart1)\n\tbinary.Write(buf, binary.LittleEndian, b.flags)\n\tbinary.Write(buf, binary.LittleEndian, b.targetAddr)\n\tbinary.Write(buf, binary.LittleEndian, b.payloadSize)\n\tbinary.Write(buf, binary.LittleEndian, b.blockNo)\n\tbinary.Write(buf, binary.LittleEndian, b.numBlocks)\n\tbinary.Write(buf, binary.LittleEndian, b.familyID)\n\tbinary.Write(buf, binary.LittleEndian, b.data)\n\tbinary.Write(buf, binary.LittleEndian, b.magicEnd)\n\n\treturn buf.Bytes()\n}\n\n// IncrementAddress moves the target address pointer forward by count bytes.\nfunc (b *uf2Block) IncrementAddress(count uint32) {\n\tb.targetAddr += b.payloadSize\n}\n\n// SetData sets the data to be used for the current block.\nfunc (b *uf2Block) SetData(d []byte) {\n\tb.data = make([]byte, 476)\n\tcopy(b.data[:], d)\n}\n\n// SetBlockNo sets the current block number to be used.\nfunc (b *uf2Block) SetBlockNo(bn int) {\n\tb.blockNo = uint32(bn)\n}\n\n// SetNumBlocks sets the total number of blocks for this UF2 file.\nfunc (b *uf2Block) SetNumBlocks(total int) {\n\tb.numBlocks = uint32(total)\n}\n\n// split splits a slice of bytes into a slice of byte slices of a specific size limit.\nfunc split(input []byte, limit int) [][]byte {\n\tvar block []byte\n\toutput := make([][]byte, 0, len(input)/limit+1)\n\tfor len(input) >= limit {\n\t\t// add all blocks\n\t\tblock, input = input[:limit], input[limit:]\n\t\toutput = append(output, block)\n\t}\n\tif len(input) > 0 {\n\t\t// add remaining block (that isn't full sized)\n\t\toutput = append(output, input)\n\t}\n\treturn output\n}\n"
  },
  {
    "path": "builder/wasilibc.go",
    "content": "package builder\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/tinygo-org/tinygo/goenv\"\n)\n\nvar libWasiLibc = Library{\n\tname: \"wasi-libc\",\n\tmakeHeaders: func(target, includeDir string) error {\n\t\tbits := filepath.Join(includeDir, \"bits\")\n\t\terr := os.Mkdir(bits, 0777)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tmuslDir := filepath.Join(goenv.Get(\"TINYGOROOT\"), \"lib\", \"wasi-libc/libc-top-half/musl\")\n\t\terr = buildMuslAllTypes(\"wasm32\", muslDir, bits)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// See MUSL_OMIT_HEADERS in the Makefile.\n\t\tomitHeaders := map[string]struct{}{\n\t\t\t\"syslog.h\":   {},\n\t\t\t\"wait.h\":     {},\n\t\t\t\"ucontext.h\": {},\n\t\t\t\"paths.h\":    {},\n\t\t\t\"utmp.h\":     {},\n\t\t\t\"utmpx.h\":    {},\n\t\t\t\"lastlog.h\":  {},\n\t\t\t\"elf.h\":      {},\n\t\t\t\"link.h\":     {},\n\t\t\t\"pwd.h\":      {},\n\t\t\t\"shadow.h\":   {},\n\t\t\t\"grp.h\":      {},\n\t\t\t\"mntent.h\":   {},\n\t\t\t\"netdb.h\":    {},\n\t\t\t\"resolv.h\":   {},\n\t\t\t\"pty.h\":      {},\n\t\t\t\"dlfcn.h\":    {},\n\t\t\t\"setjmp.h\":   {},\n\t\t\t\"ulimit.h\":   {},\n\t\t\t\"wordexp.h\":  {},\n\t\t\t\"spawn.h\":    {},\n\t\t\t\"termios.h\":  {},\n\t\t\t\"libintl.h\":  {},\n\t\t\t\"aio.h\":      {},\n\n\t\t\t\"stdarg.h\": {},\n\t\t\t\"stddef.h\": {},\n\n\t\t\t\"pthread.h\": {},\n\t\t}\n\n\t\tfor _, glob := range [][2]string{\n\t\t\t{\"libc-bottom-half/headers/public/*.h\", \"\"},\n\t\t\t{\"libc-bottom-half/headers/public/wasi/*.h\", \"wasi\"},\n\t\t\t{\"libc-top-half/musl/arch/wasm32/bits/*.h\", \"bits\"},\n\t\t\t{\"libc-top-half/musl/include/*.h\", \"\"},\n\t\t\t{\"libc-top-half/musl/include/netinet/*.h\", \"netinet\"},\n\t\t\t{\"libc-top-half/musl/include/sys/*.h\", \"sys\"},\n\t\t} {\n\t\t\tmatches, _ := filepath.Glob(filepath.Join(goenv.Get(\"TINYGOROOT\"), \"lib/wasi-libc\", glob[0]))\n\t\t\toutDir := filepath.Join(includeDir, glob[1])\n\t\t\tos.MkdirAll(outDir, 0o777)\n\t\t\tfor _, match := range matches {\n\t\t\t\tname := filepath.Base(match)\n\t\t\t\tif _, ok := omitHeaders[name]; ok {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tdata, err := os.ReadFile(match)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\terr = os.WriteFile(filepath.Join(outDir, name), data, 0o666)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn nil\n\t},\n\tcflags: func(target, headerPath string) []string {\n\t\tlibcDir := filepath.Join(goenv.Get(\"TINYGOROOT\"), \"lib/wasi-libc\")\n\t\treturn []string{\n\t\t\t\"-Werror\",\n\t\t\t\"-Wall\",\n\t\t\t\"-std=gnu11\",\n\t\t\t\"-nostdlibinc\",\n\t\t\t\"-mnontrapping-fptoint\", \"-msign-ext\", \"-mbulk-memory\",\n\t\t\t\"-Wno-null-pointer-arithmetic\", \"-Wno-unused-parameter\", \"-Wno-sign-compare\", \"-Wno-unused-variable\", \"-Wno-unused-function\", \"-Wno-ignored-attributes\", \"-Wno-missing-braces\", \"-Wno-ignored-pragmas\", \"-Wno-unused-but-set-variable\", \"-Wno-unknown-warning-option\",\n\t\t\t\"-Wno-parentheses\", \"-Wno-shift-op-parentheses\", \"-Wno-bitwise-op-parentheses\", \"-Wno-logical-op-parentheses\", \"-Wno-string-plus-int\", \"-Wno-dangling-else\", \"-Wno-unknown-pragmas\",\n\t\t\t\"-DNDEBUG\",\n\t\t\t\"-D__wasilibc_printscan_no_long_double\",\n\t\t\t\"-D__wasilibc_printscan_full_support_option=\\\"long double support is disabled\\\"\",\n\t\t\t\"-DBULK_MEMORY_THRESHOLD=32\", // default threshold in wasi-libc\n\t\t\t\"-isystem\", headerPath,\n\t\t\t\"-I\" + libcDir + \"/libc-top-half/musl/src/include\",\n\t\t\t\"-I\" + libcDir + \"/libc-top-half/musl/src/internal\",\n\t\t\t\"-I\" + libcDir + \"/libc-top-half/musl/arch/wasm32\",\n\t\t\t\"-I\" + libcDir + \"/libc-top-half/musl/arch/generic\",\n\t\t\t\"-I\" + libcDir + \"/libc-top-half/headers/private\",\n\t\t}\n\t},\n\tcflagsForFile: func(path string) []string {\n\t\tif strings.HasPrefix(path, \"libc-bottom-half\"+string(os.PathSeparator)) {\n\t\t\tlibcDir := filepath.Join(goenv.Get(\"TINYGOROOT\"), \"lib/wasi-libc\")\n\t\t\treturn []string{\n\t\t\t\t\"-I\" + libcDir + \"/libc-bottom-half/headers/private\",\n\t\t\t\t\"-I\" + libcDir + \"/libc-bottom-half/cloudlibc/src/include\",\n\t\t\t\t\"-I\" + libcDir + \"/libc-bottom-half/cloudlibc/src\",\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t},\n\tsourceDir: func() string { return filepath.Join(goenv.Get(\"TINYGOROOT\"), \"lib/wasi-libc\") },\n\tlibrarySources: func(target string, libcNeedsMalloc bool) ([]string, error) {\n\t\ttype filePattern struct {\n\t\t\tglob    string\n\t\t\texclude []string\n\t\t}\n\n\t\t// See: LIBC_TOP_HALF_MUSL_SOURCES in the Makefile\n\t\tglobs := []filePattern{\n\t\t\t// Top half: mostly musl sources.\n\t\t\t{glob: \"libc-top-half/sources/*.c\"},\n\t\t\t{glob: \"libc-top-half/musl/src/conf/*.c\"},\n\t\t\t{glob: \"libc-top-half/musl/src/internal/*.c\", exclude: []string{\n\t\t\t\t\"procfdname.c\", \"syscall.c\", \"syscall_ret.c\", \"vdso.c\", \"version.c\",\n\t\t\t}},\n\t\t\t{glob: \"libc-top-half/musl/src/locale/*.c\", exclude: []string{\n\t\t\t\t\"dcngettext.c\", \"textdomain.c\", \"bind_textdomain_codeset.c\"}},\n\t\t\t{glob: \"libc-top-half/musl/src/math/*.c\", exclude: []string{\n\t\t\t\t\"__signbit.c\", \"__signbitf.c\", \"__signbitl.c\",\n\t\t\t\t\"__fpclassify.c\", \"__fpclassifyf.c\", \"__fpclassifyl.c\",\n\t\t\t\t\"ceilf.c\", \"ceil.c\",\n\t\t\t\t\"floorf.c\", \"floor.c\",\n\t\t\t\t\"truncf.c\", \"trunc.c\",\n\t\t\t\t\"rintf.c\", \"rint.c\",\n\t\t\t\t\"nearbyintf.c\", \"nearbyint.c\",\n\t\t\t\t\"sqrtf.c\", \"sqrt.c\",\n\t\t\t\t\"fabsf.c\", \"fabs.c\",\n\t\t\t\t\"copysignf.c\", \"copysign.c\",\n\t\t\t\t\"fminf.c\", \"fmaxf.c\",\n\t\t\t\t\"fmin.c\", \"fmax.c,\",\n\t\t\t}},\n\t\t\t{glob: \"libc-top-half/musl/src/multibyte/*.c\"},\n\t\t\t{glob: \"libc-top-half/musl/src/stdio/*.c\", exclude: []string{\n\t\t\t\t\"vfwscanf.c\", \"vfwprintf.c\", // long double is unsupported\n\t\t\t\t\"__lockfile.c\", \"flockfile.c\", \"funlockfile.c\", \"ftrylockfile.c\",\n\t\t\t\t\"rename.c\",\n\t\t\t\t\"tmpnam.c\", \"tmpfile.c\", \"tempnam.c\",\n\t\t\t\t\"popen.c\", \"pclose.c\",\n\t\t\t\t\"remove.c\",\n\t\t\t\t\"gets.c\"}},\n\t\t\t{glob: \"libc-top-half/musl/src/stdlib/*.c\"},\n\t\t\t{glob: \"libc-top-half/musl/src/string/*.c\", exclude: []string{\n\t\t\t\t\"strsignal.c\"}},\n\n\t\t\t// Bottom half: connect top half to WASI equivalents.\n\t\t\t{glob: \"libc-bottom-half/cloudlibc/src/libc/*/*.c\"},\n\t\t\t{glob: \"libc-bottom-half/cloudlibc/src/libc/sys/*/*.c\"},\n\t\t\t{glob: \"libc-bottom-half/sources/*.c\"},\n\t\t}\n\n\t\t// We're using the Boehm GC, so we need a heap implementation in the libc.\n\t\tif libcNeedsMalloc {\n\t\t\tglobs = append(globs, filePattern{glob: \"dlmalloc/src/dlmalloc.c\"})\n\t\t}\n\n\t\t// See: LIBC_TOP_HALF_MUSL_SOURCES in the Makefile\n\t\tsources := []string{\n\t\t\t\"libc-top-half/musl/src/misc/a64l.c\",\n\t\t\t\"libc-top-half/musl/src/misc/basename.c\",\n\t\t\t\"libc-top-half/musl/src/misc/dirname.c\",\n\t\t\t\"libc-top-half/musl/src/misc/ffs.c\",\n\t\t\t\"libc-top-half/musl/src/misc/ffsl.c\",\n\t\t\t\"libc-top-half/musl/src/misc/ffsll.c\",\n\t\t\t\"libc-top-half/musl/src/misc/fmtmsg.c\",\n\t\t\t\"libc-top-half/musl/src/misc/getdomainname.c\",\n\t\t\t\"libc-top-half/musl/src/misc/gethostid.c\",\n\t\t\t\"libc-top-half/musl/src/misc/getopt.c\",\n\t\t\t\"libc-top-half/musl/src/misc/getopt_long.c\",\n\t\t\t\"libc-top-half/musl/src/misc/getsubopt.c\",\n\t\t\t\"libc-top-half/musl/src/misc/uname.c\",\n\t\t\t\"libc-top-half/musl/src/misc/nftw.c\",\n\t\t\t\"libc-top-half/musl/src/errno/strerror.c\",\n\t\t\t\"libc-top-half/musl/src/network/htonl.c\",\n\t\t\t\"libc-top-half/musl/src/network/htons.c\",\n\t\t\t\"libc-top-half/musl/src/network/ntohl.c\",\n\t\t\t\"libc-top-half/musl/src/network/ntohs.c\",\n\t\t\t\"libc-top-half/musl/src/network/inet_ntop.c\",\n\t\t\t\"libc-top-half/musl/src/network/inet_pton.c\",\n\t\t\t\"libc-top-half/musl/src/network/inet_aton.c\",\n\t\t\t\"libc-top-half/musl/src/network/in6addr_any.c\",\n\t\t\t\"libc-top-half/musl/src/network/in6addr_loopback.c\",\n\t\t\t\"libc-top-half/musl/src/fenv/fenv.c\",\n\t\t\t\"libc-top-half/musl/src/fenv/fesetround.c\",\n\t\t\t\"libc-top-half/musl/src/fenv/feupdateenv.c\",\n\t\t\t\"libc-top-half/musl/src/fenv/fesetexceptflag.c\",\n\t\t\t\"libc-top-half/musl/src/fenv/fegetexceptflag.c\",\n\t\t\t\"libc-top-half/musl/src/fenv/feholdexcept.c\",\n\t\t\t\"libc-top-half/musl/src/exit/exit.c\",\n\t\t\t\"libc-top-half/musl/src/exit/atexit.c\",\n\t\t\t\"libc-top-half/musl/src/exit/assert.c\",\n\t\t\t\"libc-top-half/musl/src/exit/quick_exit.c\",\n\t\t\t\"libc-top-half/musl/src/exit/at_quick_exit.c\",\n\t\t\t\"libc-top-half/musl/src/time/strftime.c\",\n\t\t\t\"libc-top-half/musl/src/time/asctime.c\",\n\t\t\t\"libc-top-half/musl/src/time/asctime_r.c\",\n\t\t\t\"libc-top-half/musl/src/time/ctime.c\",\n\t\t\t\"libc-top-half/musl/src/time/ctime_r.c\",\n\t\t\t\"libc-top-half/musl/src/time/wcsftime.c\",\n\t\t\t\"libc-top-half/musl/src/time/strptime.c\",\n\t\t\t\"libc-top-half/musl/src/time/difftime.c\",\n\t\t\t\"libc-top-half/musl/src/time/timegm.c\",\n\t\t\t\"libc-top-half/musl/src/time/ftime.c\",\n\t\t\t\"libc-top-half/musl/src/time/gmtime.c\",\n\t\t\t\"libc-top-half/musl/src/time/gmtime_r.c\",\n\t\t\t\"libc-top-half/musl/src/time/timespec_get.c\",\n\t\t\t\"libc-top-half/musl/src/time/getdate.c\",\n\t\t\t\"libc-top-half/musl/src/time/localtime.c\",\n\t\t\t\"libc-top-half/musl/src/time/localtime_r.c\",\n\t\t\t\"libc-top-half/musl/src/time/mktime.c\",\n\t\t\t\"libc-top-half/musl/src/time/__tm_to_secs.c\",\n\t\t\t\"libc-top-half/musl/src/time/__month_to_secs.c\",\n\t\t\t\"libc-top-half/musl/src/time/__secs_to_tm.c\",\n\t\t\t\"libc-top-half/musl/src/time/__year_to_secs.c\",\n\t\t\t\"libc-top-half/musl/src/time/__tz.c\",\n\t\t\t\"libc-top-half/musl/src/fcntl/creat.c\",\n\t\t\t\"libc-top-half/musl/src/dirent/alphasort.c\",\n\t\t\t\"libc-top-half/musl/src/dirent/versionsort.c\",\n\t\t\t\"libc-top-half/musl/src/env/__stack_chk_fail.c\",\n\t\t\t\"libc-top-half/musl/src/env/clearenv.c\",\n\t\t\t\"libc-top-half/musl/src/env/getenv.c\",\n\t\t\t\"libc-top-half/musl/src/env/putenv.c\",\n\t\t\t\"libc-top-half/musl/src/env/setenv.c\",\n\t\t\t\"libc-top-half/musl/src/env/unsetenv.c\",\n\t\t\t\"libc-top-half/musl/src/unistd/posix_close.c\",\n\t\t\t\"libc-top-half/musl/src/stat/futimesat.c\",\n\t\t\t\"libc-top-half/musl/src/legacy/getpagesize.c\",\n\t\t\t\"libc-top-half/musl/src/thread/thrd_sleep.c\",\n\t\t}\n\n\t\tbasepath := goenv.Get(\"TINYGOROOT\") + \"/lib/wasi-libc/\"\n\t\tfor _, pattern := range globs {\n\t\t\tmatches, err := filepath.Glob(basepath + pattern.glob)\n\t\t\tif err != nil {\n\t\t\t\t// From the documentation:\n\t\t\t\t// > Glob ignores file system errors such as I/O errors reading\n\t\t\t\t// > directories. The only possible returned error is\n\t\t\t\t// > ErrBadPattern, when pattern is malformed.\n\t\t\t\t// So the only possible error is when the (statically defined)\n\t\t\t\t// pattern is wrong. In other words, a programming bug.\n\t\t\t\treturn nil, fmt.Errorf(\"wasi-libc: could not glob source dirs: %w\", err)\n\t\t\t}\n\t\t\tif len(matches) == 0 {\n\t\t\t\treturn nil, fmt.Errorf(\"wasi-libc: did not find any files for pattern %#v\", pattern)\n\t\t\t}\n\t\t\texcludeSet := map[string]struct{}{}\n\t\t\tfor _, exclude := range pattern.exclude {\n\t\t\t\texcludeSet[exclude] = struct{}{}\n\t\t\t}\n\t\t\tfor _, match := range matches {\n\t\t\t\tif _, ok := excludeSet[filepath.Base(match)]; ok {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\trelpath, err := filepath.Rel(basepath, match)\n\t\t\t\tif err != nil {\n\t\t\t\t\t// Not sure if this is even possible.\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tsources = append(sources, relpath)\n\t\t\t}\n\t\t}\n\t\treturn sources, nil\n\t},\n}\n"
  },
  {
    "path": "builder/wasmbuiltins.go",
    "content": "package builder\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"github.com/tinygo-org/tinygo/goenv\"\n)\n\nvar libWasmBuiltins = Library{\n\tname: \"wasmbuiltins\",\n\tmakeHeaders: func(target, includeDir string) error {\n\t\tif err := os.Mkdir(includeDir+\"/bits\", 0o777); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tf, err := os.Create(includeDir + \"/bits/alltypes.h\")\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif _, err := f.Write([]byte(wasmAllTypes)); err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn f.Close()\n\t},\n\tcflags: func(target, headerPath string) []string {\n\t\tlibcDir := filepath.Join(goenv.Get(\"TINYGOROOT\"), \"lib/wasi-libc\")\n\t\treturn []string{\n\t\t\t\"-Werror\",\n\t\t\t\"-Wall\",\n\t\t\t\"-std=gnu11\",\n\t\t\t\"-nostdlibinc\",\n\t\t\t\"-mnontrapping-fptoint\", // match wasm-unknown (default on in LLVM 20)\n\t\t\t\"-mno-bulk-memory\",      // same here\n\t\t\t\"-isystem\", libcDir + \"/libc-top-half/musl/arch/wasm32\",\n\t\t\t\"-isystem\", libcDir + \"/libc-top-half/musl/arch/generic\",\n\t\t\t\"-isystem\", libcDir + \"/libc-top-half/musl/src/internal\",\n\t\t\t\"-isystem\", libcDir + \"/libc-top-half/musl/src/include\",\n\t\t\t\"-isystem\", libcDir + \"/libc-top-half/musl/include\",\n\t\t\t\"-isystem\", libcDir + \"/libc-bottom-half/headers/public\",\n\t\t\t\"-I\" + headerPath,\n\t\t}\n\t},\n\tsourceDir: func() string { return filepath.Join(goenv.Get(\"TINYGOROOT\"), \"lib/wasi-libc\") },\n\tlibrarySources: func(target string, _ bool) ([]string, error) {\n\t\treturn []string{\n\t\t\t// memory builtins needed for llvm.memcpy.*, llvm.memmove.*, and\n\t\t\t// llvm.memset.* LLVM intrinsics.\n\t\t\t\"libc-top-half/musl/src/string/memcpy.c\",\n\t\t\t\"libc-top-half/musl/src/string/memmove.c\",\n\t\t\t\"libc-top-half/musl/src/string/memset.c\",\n\n\t\t\t// exp, exp2, and log are needed for LLVM math builtin functions\n\t\t\t// like llvm.exp.*.\n\t\t\t\"libc-top-half/musl/src/math/__math_divzero.c\",\n\t\t\t\"libc-top-half/musl/src/math/__math_invalid.c\",\n\t\t\t\"libc-top-half/musl/src/math/__math_oflow.c\",\n\t\t\t\"libc-top-half/musl/src/math/__math_uflow.c\",\n\t\t\t\"libc-top-half/musl/src/math/__math_xflow.c\",\n\t\t\t\"libc-top-half/musl/src/math/exp.c\",\n\t\t\t\"libc-top-half/musl/src/math/exp_data.c\",\n\t\t\t\"libc-top-half/musl/src/math/exp2.c\",\n\t\t\t\"libc-top-half/musl/src/math/log.c\",\n\t\t\t\"libc-top-half/musl/src/math/log_data.c\",\n\t\t}, nil\n\t},\n}\n\n// alltypes.h for wasm-libc, using the types as defined inside Clang.\nconst wasmAllTypes = `\ntypedef __SIZE_TYPE__    size_t;\ntypedef __INT8_TYPE__    int8_t;\ntypedef __INT16_TYPE__   int16_t;\ntypedef __INT32_TYPE__   int32_t;\ntypedef __INT64_TYPE__   int64_t;\ntypedef __UINT8_TYPE__   uint8_t;\ntypedef __UINT16_TYPE__  uint16_t;\ntypedef __UINT32_TYPE__  uint32_t;\ntypedef __UINT64_TYPE__  uint64_t;\ntypedef __UINTPTR_TYPE__ uintptr_t;\n\n// This type is used internally in wasi-libc.\ntypedef double double_t;\n`\n"
  },
  {
    "path": "cgo/cgo.go",
    "content": "// Package cgo implements CGo by modifying a loaded AST. It does this by parsing\n// the `import \"C\"` statements found in the source code with libclang and\n// generating stub function and global declarations.\n//\n// There are a few advantages to modifying the AST directly instead of doing CGo\n// as a preprocessing step, with the main advantage being that debug information\n// is kept intact as much as possible.\npackage cgo\n\n// This file extracts the `import \"C\"` statement from the source and modifies\n// the AST for CGo. It does not use libclang directly: see libclang.go for the C\n// source file parsing.\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/parser\"\n\t\"go/scanner\"\n\t\"go/token\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/google/shlex\"\n\t\"golang.org/x/tools/go/ast/astutil\"\n)\n\n// Function that's only defined in Go 1.22.\nvar setASTFileFields = func(f *ast.File, start, end token.Pos) {\n}\n\n// cgoPackage holds all CGo-related information of a package.\ntype cgoPackage struct {\n\tgenerated       *ast.File\n\tpackageName     string\n\tcgoFiles        []*ast.File\n\tgeneratedPos    token.Pos\n\terrors          []error\n\tcurrentDir      string // current working directory\n\tpackageDir      string // full path to the package to process\n\timportPath      string\n\tfset            *token.FileSet\n\ttokenFiles      map[string]*token.File\n\tdefinedGlobally map[string]ast.Node\n\tnoescapingFuncs map[string]*noescapingFunc // #cgo noescape lines\n\tanonDecls       map[interface{}]string\n\tcflags          []string // CFlags from #cgo lines\n\tldflags         []string // LDFlags from #cgo lines\n\tvisitedFiles    map[string][]byte\n\tcgoHeaders      []string\n}\n\n// cgoFile holds information only for a single Go file (with one or more\n// `import \"C\"` statements).\ntype cgoFile struct {\n\t*cgoPackage\n\tfile    *ast.File\n\tindex   int\n\tdefined map[string]ast.Node\n\tnames   map[string]clangCursor\n}\n\n// elaboratedTypeInfo contains some information about an elaborated type\n// (struct, union) found in the C AST.\ntype elaboratedTypeInfo struct {\n\ttypeExpr   *ast.StructType\n\tpos        token.Pos\n\tbitfields  []bitfieldInfo\n\tunionSize  int64 // union size in bytes, nonzero when union getters/setters should be created\n\tunionAlign int64 // union alignment in bytes\n}\n\n// bitfieldInfo contains information about a single bitfield in a struct. It\n// keeps information about the start, end, and the special (renamed) base field\n// of this bitfield.\ntype bitfieldInfo struct {\n\tfield    *ast.Field\n\tname     string\n\tpos      token.Pos\n\tstartBit int64\n\tendBit   int64 // may be 0 meaning \"until the end of the field\"\n}\n\n// Information about a #cgo noescape line in the source code.\ntype noescapingFunc struct {\n\tname string\n\tpos  token.Pos\n\tused bool // true if used somewhere in the source (for proper error reporting)\n}\n\n// cgoAliases list type aliases between Go and C, for types that are equivalent\n// in both languages. See addTypeAliases.\nvar cgoAliases = map[string]string{\n\t\"_Cgo_int8_t\":    \"int8\",\n\t\"_Cgo_int16_t\":   \"int16\",\n\t\"_Cgo_int32_t\":   \"int32\",\n\t\"_Cgo_int64_t\":   \"int64\",\n\t\"_Cgo_uint8_t\":   \"uint8\",\n\t\"_Cgo_uint16_t\":  \"uint16\",\n\t\"_Cgo_uint32_t\":  \"uint32\",\n\t\"_Cgo_uint64_t\":  \"uint64\",\n\t\"_Cgo_uintptr_t\": \"uintptr\",\n\t\"_Cgo_float\":     \"float32\",\n\t\"_Cgo_double\":    \"float64\",\n\t\"_Cgo__Bool\":     \"bool\",\n}\n\n// builtinAliases are handled specially because they only exist on the Go side\n// of CGo, not on the CGo side (they're prefixed with \"_Cgo_\" there).\nvar builtinAliases = []string{\n\t\"char\",\n\t\"schar\",\n\t\"uchar\",\n\t\"short\",\n\t\"ushort\",\n\t\"int\",\n\t\"uint\",\n\t\"long\",\n\t\"ulong\",\n\t\"longlong\",\n\t\"ulonglong\",\n}\n\n// builtinAliasTypedefs lists some C types with ambiguous sizes that must be\n// retrieved somehow from C. This is done by adding some typedefs to get the\n// size of each type.\nconst builtinAliasTypedefs = `\n# 1 \"<cgo>\"\ntypedef char                _Cgo_char;\ntypedef signed char         _Cgo_schar;\ntypedef unsigned char       _Cgo_uchar;\ntypedef short               _Cgo_short;\ntypedef unsigned short      _Cgo_ushort;\ntypedef int                 _Cgo_int;\ntypedef unsigned int        _Cgo_uint;\ntypedef long                _Cgo_long;\ntypedef unsigned long       _Cgo_ulong;\ntypedef long long           _Cgo_longlong;\ntypedef unsigned long long  _Cgo_ulonglong;\n`\n\n// First part of the generated Go file. Written here as Go because that's much\n// easier than constructing the entire AST in memory.\n// The string/bytes functions below implement C.CString etc. To make sure the\n// runtime doesn't need to know the C int type, lengths are converted to uintptr\n// first.\nconst generatedGoFilePrefixBase = `\nimport \"syscall\"\nimport \"unsafe\"\n\nvar _ unsafe.Pointer\n\n//go:linkname _Cgo_CString runtime.cgo_CString\nfunc _Cgo_CString(string) *_Cgo_char\n\n//go:linkname _Cgo_GoString runtime.cgo_GoString\nfunc _Cgo_GoString(*_Cgo_char) string\n\n//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN\nfunc _Cgo___GoStringN(*_Cgo_char, uintptr) string\n\nfunc _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {\n\treturn _Cgo___GoStringN(cstr, uintptr(length))\n}\n\n//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes\nfunc _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte\n\nfunc _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {\n\treturn _Cgo___GoBytes(ptr, uintptr(length))\n}\n\n//go:linkname _Cgo___CBytes runtime.cgo_CBytes\nfunc _Cgo___CBytes([]byte) unsafe.Pointer\n\nfunc _Cgo_CBytes(b []byte) unsafe.Pointer {\n\treturn _Cgo___CBytes(b)\n}\n\n//go:linkname _Cgo___get_errno_num runtime.cgo_errno\nfunc _Cgo___get_errno_num() uintptr\n`\n\nconst generatedGoFilePrefixOther = generatedGoFilePrefixBase + `\nfunc _Cgo___get_errno() error {\n\treturn syscall.Errno(_Cgo___get_errno_num())\n}\n`\n\n// Windows uses fake errno values in the syscall package.\n// See for example: https://github.com/golang/go/issues/23468\n// TinyGo uses mingw-w64 though, which does have defined errno values. Since the\n// syscall package is the standard library one we can't change it, but we can\n// map the errno values to match the values in the syscall package.\n// Source of the errno values: lib/mingw-w64/mingw-w64-headers/crt/errno.h\nconst generatedGoFilePrefixWindows = generatedGoFilePrefixBase + `\nvar _Cgo___errno_mapping = [...]syscall.Errno{\n\t1:  syscall.EPERM,\n\t2:  syscall.ENOENT,\n\t3:  syscall.ESRCH,\n\t4:  syscall.EINTR,\n\t5:  syscall.EIO,\n\t6:  syscall.ENXIO,\n\t7:  syscall.E2BIG,\n\t8:  syscall.ENOEXEC,\n\t9:  syscall.EBADF,\n\t10: syscall.ECHILD,\n\t11: syscall.EAGAIN,\n\t12: syscall.ENOMEM,\n\t13: syscall.EACCES,\n\t14: syscall.EFAULT,\n\t16: syscall.EBUSY,\n\t17: syscall.EEXIST,\n\t18: syscall.EXDEV,\n\t19: syscall.ENODEV,\n\t20: syscall.ENOTDIR,\n\t21: syscall.EISDIR,\n\t22: syscall.EINVAL,\n\t23: syscall.ENFILE,\n\t24: syscall.EMFILE,\n\t25: syscall.ENOTTY,\n\t27: syscall.EFBIG,\n\t28: syscall.ENOSPC,\n\t29: syscall.ESPIPE,\n\t30: syscall.EROFS,\n\t31: syscall.EMLINK,\n\t32: syscall.EPIPE,\n\t33: syscall.EDOM,\n\t34: syscall.ERANGE,\n\t36: syscall.EDEADLK,\n\t38: syscall.ENAMETOOLONG,\n\t39: syscall.ENOLCK,\n\t40: syscall.ENOSYS,\n\t41: syscall.ENOTEMPTY,\n\t42: syscall.EILSEQ,\n}\n\nfunc _Cgo___get_errno() error {\n\tnum := _Cgo___get_errno_num()\n\tif num < uintptr(len(_Cgo___errno_mapping)) {\n\t\tif mapped := _Cgo___errno_mapping[num]; mapped != 0 {\n\t\t\treturn mapped\n\t\t}\n\t}\n\treturn syscall.Errno(num)\n}\n`\n\n// Process extracts `import \"C\"` statements from the AST, parses the comment\n// with libclang, and modifies the AST to use this information. It returns a\n// newly created *ast.File that should be added to the list of to-be-parsed\n// files, the CGo header snippets that should be compiled (for inline\n// functions), the CFLAGS and LDFLAGS found in #cgo lines, and a map of file\n// hashes of the accessed C header files. If there is one or more error, it\n// returns these in the []error slice but still modifies the AST.\nfunc Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cflags []string, goos string) ([]*ast.File, []string, []string, []string, map[string][]byte, []error) {\n\tp := &cgoPackage{\n\t\tpackageName:     files[0].Name.Name,\n\t\tcurrentDir:      dir,\n\t\timportPath:      importPath,\n\t\tfset:            fset,\n\t\ttokenFiles:      map[string]*token.File{},\n\t\tdefinedGlobally: map[string]ast.Node{},\n\t\tnoescapingFuncs: map[string]*noescapingFunc{},\n\t\tanonDecls:       map[interface{}]string{},\n\t\tvisitedFiles:    map[string][]byte{},\n\t}\n\n\t// Add a new location for the following file.\n\tgeneratedTokenPos := p.fset.AddFile(dir+\"/!cgo.go\", -1, 0)\n\tgeneratedTokenPos.SetLines([]int{0})\n\tp.generatedPos = generatedTokenPos.Pos(0)\n\n\t// Find the absolute path for this package.\n\tpackagePath, err := filepath.Abs(fset.File(files[0].Pos()).Name())\n\tif err != nil {\n\t\treturn nil, nil, nil, nil, nil, []error{\n\t\t\tscanner.Error{\n\t\t\t\tPos: fset.Position(files[0].Pos()),\n\t\t\t\tMsg: \"cgo: cannot find absolute path: \" + err.Error(), // TODO: wrap this error\n\t\t\t},\n\t\t}\n\t}\n\tp.packageDir = filepath.Dir(packagePath)\n\n\t// Construct a new in-memory AST for CGo declarations of this package.\n\t// The first part is written as Go code that is then parsed, but more code\n\t// is added later to the AST to declare functions, globals, etc.\n\tgoCode := \"package \" + files[0].Name.Name + \"\\n\\n\"\n\tif goos == \"windows\" {\n\t\tgoCode += generatedGoFilePrefixWindows\n\t} else {\n\t\tgoCode += generatedGoFilePrefixOther\n\t}\n\tp.generated, err = parser.ParseFile(fset, dir+\"/!cgo.go\", goCode, parser.ParseComments)\n\tif err != nil {\n\t\t// This is always a bug in the cgo package.\n\t\tpanic(\"unexpected error: \" + err.Error())\n\t}\n\tp.cgoFiles = append(p.cgoFiles, p.generated)\n\t// If the Comments field is not set to nil, the go/format package will get\n\t// confused about where comments should go.\n\tp.generated.Comments = nil\n\n\t// Find `import \"C\"` C fragments in the file.\n\tp.cgoHeaders = make([]string, len(files)) // combined CGo header fragment for each file\n\tfor i, f := range files {\n\t\tvar cgoHeader string\n\t\tfor i := 0; i < len(f.Decls); i++ {\n\t\t\tdecl := f.Decls[i]\n\t\t\tgenDecl, ok := decl.(*ast.GenDecl)\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif len(genDecl.Specs) != 1 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tspec, ok := genDecl.Specs[0].(*ast.ImportSpec)\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, err := strconv.Unquote(spec.Path.Value)\n\t\t\tif err != nil {\n\t\t\t\t// This should not happen. An import path that is not properly\n\t\t\t\t// quoted should not exist in a correct AST.\n\t\t\t\tpanic(\"could not parse import path: \" + err.Error())\n\t\t\t}\n\t\t\tif path != \"C\" {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Remove this import declaration.\n\t\t\tf.Decls = append(f.Decls[:i], f.Decls[i+1:]...)\n\t\t\ti--\n\n\t\t\tif genDecl.Doc == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Iterate through all parts of the CGo header. Note that every //\n\t\t\t// line is a new comment.\n\t\t\tposition := fset.Position(genDecl.Doc.Pos())\n\t\t\tfragment := fmt.Sprintf(\"# %d %#v\\n\", position.Line, position.Filename)\n\t\t\tfor _, comment := range genDecl.Doc.List {\n\t\t\t\t// Find all #cgo lines, extract and use their contents, and\n\t\t\t\t// replace the lines with spaces (to preserve locations).\n\t\t\t\tc := p.parseCGoPreprocessorLines(comment.Text, comment.Slash)\n\n\t\t\t\t// Change the comment (which is still in Go syntax, with // and\n\t\t\t\t// /* */ ) to a regular string by replacing the start/end\n\t\t\t\t// markers of comments with spaces.\n\t\t\t\t// It is similar to the Text() method but differs in that it\n\t\t\t\t// doesn't strip anything and tries to keep all offsets correct\n\t\t\t\t// by adding spaces and newlines where necessary.\n\t\t\t\tif c[1] == '/' { /* comment */\n\t\t\t\t\tc = \"  \" + c[2:]\n\t\t\t\t} else { // comment\n\t\t\t\t\tc = \"  \" + c[2:len(c)-2]\n\t\t\t\t}\n\t\t\t\tfragment += c + \"\\n\"\n\t\t\t}\n\t\t\tcgoHeader += fragment\n\t\t}\n\n\t\tp.cgoHeaders[i] = cgoHeader\n\t}\n\n\t// Define CFlags that will be used while parsing the package.\n\t// Disable _FORTIFY_SOURCE as it causes problems on macOS.\n\t// Note that it is only disabled for memcpy (etc) calls made from Go, which\n\t// have better alternatives anyway.\n\tcflagsForCGo := append([]string{\"-D_FORTIFY_SOURCE=0\"}, cflags...)\n\tcflagsForCGo = append(cflagsForCGo, p.cflags...)\n\n\t// Retrieve types such as C.int, C.longlong, etc from C.\n\tp.newCGoFile(nil, -1).readNames(builtinAliasTypedefs, cflagsForCGo, \"\", func(names map[string]clangCursor) {\n\t\tgen := &ast.GenDecl{\n\t\t\tTokPos: token.NoPos,\n\t\t\tTok:    token.TYPE,\n\t\t}\n\t\tfor _, name := range builtinAliases {\n\t\t\ttypeSpec := p.getIntegerType(\"_Cgo_\"+name, names[\"_Cgo_\"+name])\n\t\t\tgen.Specs = append(gen.Specs, typeSpec)\n\t\t}\n\t\tp.generated.Decls = append(p.generated.Decls, gen)\n\t})\n\n\t// Process CGo imports for each file.\n\tfor i, f := range files {\n\t\tcf := p.newCGoFile(f, i)\n\t\t// These types are aliased with the corresponding types in C. For\n\t\t// example, float in C is always float32 in Go.\n\t\tcf.names[\"float\"] = clangCursor{}\n\t\tcf.names[\"double\"] = clangCursor{}\n\t\tcf.names[\"_Bool\"] = clangCursor{}\n\t\t// Now read all the names (identifies) that C defines in the header\n\t\t// snippet.\n\t\tcf.readNames(p.cgoHeaders[i], cflagsForCGo, filepath.Base(fset.File(f.Pos()).Name()), func(names map[string]clangCursor) {\n\t\t\tfor _, name := range builtinAliases {\n\t\t\t\t// Names such as C.int should not be obtained from C.\n\t\t\t\t// This works around an issue in picolibc that has `#define int`\n\t\t\t\t// in a header file.\n\t\t\t\tdelete(names, name)\n\t\t\t}\n\t\t\tastutil.Apply(f, func(cursor *astutil.Cursor) bool {\n\t\t\t\treturn cf.walker(cursor, names)\n\t\t\t}, nil)\n\t\t})\n\t}\n\n\t// Show an error when a #cgo noescape line isn't used in practice.\n\t// This matches upstream Go. I think the goal is to avoid issues with\n\t// misspelled function names, which seems very useful.\n\tvar unusedNoescapeLines []*noescapingFunc\n\tfor _, value := range p.noescapingFuncs {\n\t\tif !value.used {\n\t\t\tunusedNoescapeLines = append(unusedNoescapeLines, value)\n\t\t}\n\t}\n\tsort.SliceStable(unusedNoescapeLines, func(i, j int) bool {\n\t\treturn unusedNoescapeLines[i].pos < unusedNoescapeLines[j].pos\n\t})\n\tfor _, value := range unusedNoescapeLines {\n\t\tp.addError(value.pos, fmt.Sprintf(\"function %#v in #cgo noescape line is not used\", value.name))\n\t}\n\n\t// Print the newly generated in-memory AST, for debugging.\n\t//ast.Print(fset, p.generated)\n\n\treturn p.cgoFiles, p.cgoHeaders, p.cflags, p.ldflags, p.visitedFiles, p.errors\n}\n\nfunc (p *cgoPackage) newCGoFile(file *ast.File, index int) *cgoFile {\n\treturn &cgoFile{\n\t\tcgoPackage: p,\n\t\tfile:       file,\n\t\tindex:      index,\n\t\tdefined:    make(map[string]ast.Node),\n\t\tnames:      make(map[string]clangCursor),\n\t}\n}\n\n// makePathsAbsolute converts some common path compiler flags (-I, -L) from\n// relative flags into absolute flags, if they are relative. This is necessary\n// because the C compiler is usually not invoked from the package path.\nfunc (p *cgoPackage) makePathsAbsolute(args []string) {\n\tnextIsPath := false\n\tfor i, arg := range args {\n\t\tif nextIsPath {\n\t\t\tif !filepath.IsAbs(arg) {\n\t\t\t\targs[i] = filepath.Join(p.packageDir, arg)\n\t\t\t}\n\t\t}\n\t\tif arg == \"-I\" || arg == \"-L\" {\n\t\t\tnextIsPath = true\n\t\t\tcontinue\n\t\t}\n\t\tif strings.HasPrefix(arg, \"-I\") || strings.HasPrefix(arg, \"-L\") {\n\t\t\tpath := arg[2:]\n\t\t\tif !filepath.IsAbs(path) {\n\t\t\t\targs[i] = arg[:2] + filepath.Join(p.packageDir, path)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// parseCGoPreprocessorLines reads #cgo pseudo-preprocessor lines in the source\n// text (import \"C\" fragment), stores their information such as CFLAGS, and\n// returns the same text but with those #cgo lines replaced by spaces (to keep\n// position offsets the same).\nfunc (p *cgoPackage) parseCGoPreprocessorLines(text string, pos token.Pos) string {\n\tfor {\n\t\t// Extract the #cgo line, and replace it with spaces.\n\t\t// Replacing with spaces makes sure that error locations are\n\t\t// still correct, while not interfering with parsing in any way.\n\t\tlineStart := strings.Index(text, \"#cgo \")\n\t\tif lineStart < 0 {\n\t\t\tbreak\n\t\t}\n\t\tlineLen := strings.IndexByte(text[lineStart:], '\\n')\n\t\tif lineLen < 0 {\n\t\t\tlineLen = len(text) - lineStart\n\t\t}\n\t\tlineEnd := lineStart + lineLen\n\t\tline := text[lineStart:lineEnd]\n\t\tspaces := make([]byte, len(line))\n\t\tfor i := range spaces {\n\t\t\tspaces[i] = ' '\n\t\t}\n\t\ttext = text[:lineStart] + string(spaces) + text[lineEnd:]\n\n\t\tallFields := strings.Fields(line[4:])\n\t\tswitch allFields[0] {\n\t\tcase \"noescape\":\n\t\t\t// The code indicates that pointer parameters will not be captured\n\t\t\t// by the called C function.\n\t\t\tif len(allFields) < 2 {\n\t\t\t\tp.addErrorAfter(pos, text[:lineStart], \"missing function name in #cgo noescape line\")\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif len(allFields) > 2 {\n\t\t\t\tp.addErrorAfter(pos, text[:lineStart], \"multiple function names in #cgo noescape line\")\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tname := allFields[1]\n\t\t\tp.noescapingFuncs[name] = &noescapingFunc{\n\t\t\t\tname: name,\n\t\t\t\tpos:  pos,\n\t\t\t\tused: false,\n\t\t\t}\n\t\t\tcontinue\n\t\tcase \"nocallback\":\n\t\t\t// We don't do anything special when calling a C function, so there\n\t\t\t// appears to be no optimization that we can do here.\n\t\t\t// Accept, but ignore the parameter for compatibility.\n\t\t\tcontinue\n\t\t}\n\n\t\t// Get the text before the colon in the #cgo directive.\n\t\tcolon := strings.IndexByte(line, ':')\n\t\tif colon < 0 {\n\t\t\tp.addErrorAfter(pos, text[:lineStart], \"missing colon in #cgo line\")\n\t\t\tcontinue\n\t\t}\n\n\t\t// Extract the fields before the colon. These fields are a list\n\t\t// of build tags and the C environment variable.\n\t\tfields := strings.Fields(line[4:colon])\n\t\tif len(fields) == 0 {\n\t\t\tp.addErrorAfter(pos, text[:lineStart+colon-1], \"invalid #cgo line\")\n\t\t\tcontinue\n\t\t}\n\n\t\tif len(fields) > 1 {\n\t\t\tp.addErrorAfter(pos, text[:lineStart+5], \"not implemented: build constraints in #cgo line\")\n\t\t\tcontinue\n\t\t}\n\n\t\tname := fields[len(fields)-1]\n\t\tvalue := line[colon+1:]\n\t\tswitch name {\n\t\tcase \"CFLAGS\":\n\t\t\tflags, err := shlex.Split(value)\n\t\t\tif err != nil {\n\t\t\t\t// TODO: find the exact location where the error happened.\n\t\t\t\tp.addErrorAfter(pos, text[:lineStart+colon+1], \"failed to parse flags in #cgo line: \"+err.Error())\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif err := checkCompilerFlags(name, flags); err != nil {\n\t\t\t\tp.addErrorAfter(pos, text[:lineStart+colon+1], err.Error())\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tp.makePathsAbsolute(flags)\n\t\t\tp.cflags = append(p.cflags, flags...)\n\t\tcase \"LDFLAGS\":\n\t\t\tflags, err := shlex.Split(value)\n\t\t\tif err != nil {\n\t\t\t\t// TODO: find the exact location where the error happened.\n\t\t\t\tp.addErrorAfter(pos, text[:lineStart+colon+1], \"failed to parse flags in #cgo line: \"+err.Error())\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif err := checkLinkerFlags(name, flags); err != nil {\n\t\t\t\tp.addErrorAfter(pos, text[:lineStart+colon+1], err.Error())\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tp.makePathsAbsolute(flags)\n\t\t\tp.ldflags = append(p.ldflags, flags...)\n\t\tdefault:\n\t\t\tstartPos := strings.LastIndex(line[4:colon], name) + 4\n\t\t\tp.addErrorAfter(pos, text[:lineStart+startPos], \"invalid #cgo line: \"+name)\n\t\t\tcontinue\n\t\t}\n\t}\n\treturn text\n}\n\n// makeUnionField creates a new struct from an existing *elaboratedTypeInfo,\n// that has just a single field that must be accessed through special accessors.\n// It returns nil when there is an error. In case of an error, that error has\n// already been added to the list of errors using p.addError.\nfunc (p *cgoPackage) makeUnionField(typ *elaboratedTypeInfo) *ast.StructType {\n\tunionFieldTypeName, ok := map[int64]string{\n\t\t1: \"uint8\",\n\t\t2: \"uint16\",\n\t\t4: \"uint32\",\n\t\t8: \"uint64\",\n\t}[typ.unionAlign]\n\tif !ok {\n\t\tp.addError(typ.typeExpr.Struct, fmt.Sprintf(\"expected union alignment to be one of 1, 2, 4, or 8, but got %d\", typ.unionAlign))\n\t\treturn nil\n\t}\n\tvar unionFieldType ast.Expr = &ast.Ident{\n\t\tNamePos: token.NoPos,\n\t\tName:    unionFieldTypeName,\n\t}\n\tif typ.unionSize != typ.unionAlign {\n\t\t// A plain struct{uintX} isn't enough, we have to make a\n\t\t// struct{[N]uintX} to make the union big enough.\n\t\tif typ.unionSize/typ.unionAlign*typ.unionAlign != typ.unionSize {\n\t\t\tp.addError(typ.typeExpr.Struct, fmt.Sprintf(\"union alignment (%d) must be a multiple of union alignment (%d)\", typ.unionSize, typ.unionAlign))\n\t\t\treturn nil\n\t\t}\n\t\tunionFieldType = &ast.ArrayType{\n\t\t\tLen: &ast.BasicLit{\n\t\t\t\tKind:  token.INT,\n\t\t\t\tValue: strconv.FormatInt(typ.unionSize/typ.unionAlign, 10),\n\t\t\t},\n\t\t\tElt: unionFieldType,\n\t\t}\n\t}\n\treturn &ast.StructType{\n\t\tStruct: typ.typeExpr.Struct,\n\t\tFields: &ast.FieldList{\n\t\t\tOpening: typ.typeExpr.Fields.Opening,\n\t\t\tList: []*ast.Field{{\n\t\t\t\tNames: []*ast.Ident{\n\t\t\t\t\t{\n\t\t\t\t\t\tNamePos: typ.typeExpr.Fields.Opening,\n\t\t\t\t\t\tName:    \"$union\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tType: unionFieldType,\n\t\t\t}},\n\t\t\tClosing: typ.typeExpr.Fields.Closing,\n\t\t},\n\t}\n}\n\n// createUnionAccessor creates a function that returns a typed pointer to a\n// union field for each field in a union. For example:\n//\n//\tfunc (union *C.union_1) unionfield_d() *float64 {\n//\t    return (*float64)(unsafe.Pointer(&union.$union))\n//\t}\n//\n// Where C.union_1 is defined as:\n//\n//\ttype C.union_1 struct{\n//\t    $union uint64\n//\t}\n//\n// The returned pointer can be used to get or set the field, or get the pointer\n// to a subfield.\nfunc (p *cgoPackage) createUnionAccessor(field *ast.Field, typeName string) {\n\tif len(field.Names) != 1 {\n\t\tpanic(\"number of names in union field must be exactly 1\")\n\t}\n\tfieldName := field.Names[0]\n\tpos := fieldName.NamePos\n\n\t// The method receiver.\n\treceiver := &ast.SelectorExpr{\n\t\tX: &ast.Ident{\n\t\t\tNamePos: pos,\n\t\t\tName:    \"union\",\n\t\t\tObj:     nil,\n\t\t},\n\t\tSel: &ast.Ident{\n\t\t\tNamePos: pos,\n\t\t\tName:    \"$union\",\n\t\t},\n\t}\n\n\t// Get the address of the $union field.\n\treceiverPtr := &ast.UnaryExpr{\n\t\tOp: token.AND,\n\t\tX:  receiver,\n\t}\n\n\t// Cast to unsafe.Pointer.\n\tsourcePointer := &ast.CallExpr{\n\t\tFun: &ast.SelectorExpr{\n\t\t\tX:   &ast.Ident{Name: \"unsafe\"},\n\t\t\tSel: &ast.Ident{Name: \"Pointer\"},\n\t\t},\n\t\tArgs: []ast.Expr{receiverPtr},\n\t}\n\n\t// Cast to the target pointer type.\n\ttargetPointer := &ast.CallExpr{\n\t\tLparen: pos,\n\t\tFun: &ast.ParenExpr{\n\t\t\tLparen: pos,\n\t\t\tX: &ast.StarExpr{\n\t\t\t\tX: field.Type,\n\t\t\t},\n\t\t\tRparen: pos,\n\t\t},\n\t\tArgs:   []ast.Expr{sourcePointer},\n\t\tRparen: pos,\n\t}\n\n\t// Create the accessor function.\n\taccessor := &ast.FuncDecl{\n\t\tRecv: &ast.FieldList{\n\t\t\tOpening: pos,\n\t\t\tList: []*ast.Field{\n\t\t\t\t{\n\t\t\t\t\tNames: []*ast.Ident{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tNamePos: pos,\n\t\t\t\t\t\t\tName:    \"union\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tType: &ast.StarExpr{\n\t\t\t\t\t\tStar: pos,\n\t\t\t\t\t\tX: &ast.Ident{\n\t\t\t\t\t\t\tNamePos: pos,\n\t\t\t\t\t\t\tName:    typeName,\n\t\t\t\t\t\t\tObj:     nil,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tClosing: pos,\n\t\t},\n\t\tName: &ast.Ident{\n\t\t\tNamePos: pos,\n\t\t\tName:    \"unionfield_\" + fieldName.Name,\n\t\t},\n\t\tType: &ast.FuncType{\n\t\t\tFunc: pos,\n\t\t\tParams: &ast.FieldList{\n\t\t\t\tOpening: pos,\n\t\t\t\tClosing: pos,\n\t\t\t},\n\t\t\tResults: &ast.FieldList{\n\t\t\t\tList: []*ast.Field{\n\t\t\t\t\t{\n\t\t\t\t\t\tType: &ast.StarExpr{\n\t\t\t\t\t\t\tStar: pos,\n\t\t\t\t\t\t\tX:    field.Type,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tBody: &ast.BlockStmt{\n\t\t\tLbrace: pos,\n\t\t\tList: []ast.Stmt{\n\t\t\t\t&ast.ReturnStmt{\n\t\t\t\t\tReturn: pos,\n\t\t\t\t\tResults: []ast.Expr{\n\t\t\t\t\t\ttargetPointer,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tRbrace: pos,\n\t\t},\n\t}\n\tp.generated.Decls = append(p.generated.Decls, accessor)\n}\n\n// createBitfieldGetter creates a bitfield getter function like the following:\n//\n//\tfunc (s *C.struct_foo) bitfield_b() byte {\n//\t    return (s.__bitfield_1 >> 5) & 0x1\n//\t}\nfunc (p *cgoPackage) createBitfieldGetter(bitfield bitfieldInfo, typeName string) {\n\t// The value to return from the getter.\n\t// Not complete: this is just an expression to get the complete field.\n\tvar result ast.Expr = &ast.SelectorExpr{\n\t\tX: &ast.Ident{\n\t\t\tNamePos: bitfield.pos,\n\t\t\tName:    \"s\",\n\t\t\tObj:     nil,\n\t\t},\n\t\tSel: &ast.Ident{\n\t\t\tNamePos: bitfield.pos,\n\t\t\tName:    bitfield.field.Names[0].Name,\n\t\t},\n\t}\n\tif bitfield.startBit != 0 {\n\t\t// Shift to the right by .startBit so that fields that come before are\n\t\t// shifted off.\n\t\tresult = &ast.BinaryExpr{\n\t\t\tX:     result,\n\t\t\tOpPos: bitfield.pos,\n\t\t\tOp:    token.SHR,\n\t\t\tY: &ast.BasicLit{\n\t\t\t\tValuePos: bitfield.pos,\n\t\t\t\tKind:     token.INT,\n\t\t\t\tValue:    strconv.FormatInt(bitfield.startBit, 10),\n\t\t\t},\n\t\t}\n\t}\n\tif bitfield.endBit != 0 {\n\t\t// Mask off the high bits so that fields that come after this field are\n\t\t// masked off.\n\t\tand := (uint64(1) << uint64(bitfield.endBit-bitfield.startBit)) - 1\n\t\tresult = &ast.BinaryExpr{\n\t\t\tX:     result,\n\t\t\tOpPos: bitfield.pos,\n\t\t\tOp:    token.AND,\n\t\t\tY: &ast.BasicLit{\n\t\t\t\tValuePos: bitfield.pos,\n\t\t\t\tKind:     token.INT,\n\t\t\t\tValue:    \"0x\" + strconv.FormatUint(and, 16),\n\t\t\t},\n\t\t}\n\t}\n\n\t// Create the getter function.\n\tgetter := &ast.FuncDecl{\n\t\tRecv: &ast.FieldList{\n\t\t\tOpening: bitfield.pos,\n\t\t\tList: []*ast.Field{\n\t\t\t\t{\n\t\t\t\t\tNames: []*ast.Ident{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tNamePos: bitfield.pos,\n\t\t\t\t\t\t\tName:    \"s\",\n\t\t\t\t\t\t\tObj: &ast.Object{\n\t\t\t\t\t\t\t\tKind: ast.Var,\n\t\t\t\t\t\t\t\tName: \"s\",\n\t\t\t\t\t\t\t\tDecl: nil,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tType: &ast.StarExpr{\n\t\t\t\t\t\tStar: bitfield.pos,\n\t\t\t\t\t\tX: &ast.Ident{\n\t\t\t\t\t\t\tNamePos: bitfield.pos,\n\t\t\t\t\t\t\tName:    typeName,\n\t\t\t\t\t\t\tObj:     nil,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tClosing: bitfield.pos,\n\t\t},\n\t\tName: &ast.Ident{\n\t\t\tNamePos: bitfield.pos,\n\t\t\tName:    \"bitfield_\" + bitfield.name,\n\t\t},\n\t\tType: &ast.FuncType{\n\t\t\tFunc: bitfield.pos,\n\t\t\tParams: &ast.FieldList{\n\t\t\t\tOpening: bitfield.pos,\n\t\t\t\tClosing: bitfield.pos,\n\t\t\t},\n\t\t\tResults: &ast.FieldList{\n\t\t\t\tList: []*ast.Field{\n\t\t\t\t\t{\n\t\t\t\t\t\tType: bitfield.field.Type,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tBody: &ast.BlockStmt{\n\t\t\tLbrace: bitfield.pos,\n\t\t\tList: []ast.Stmt{\n\t\t\t\t&ast.ReturnStmt{\n\t\t\t\t\tReturn: bitfield.pos,\n\t\t\t\t\tResults: []ast.Expr{\n\t\t\t\t\t\tresult,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tRbrace: bitfield.pos,\n\t\t},\n\t}\n\tp.generated.Decls = append(p.generated.Decls, getter)\n}\n\n// createBitfieldSetter creates a bitfield setter function like the following:\n//\n//\tfunc (s *C.struct_foo) set_bitfield_b(value byte) {\n//\t    s.__bitfield_1 = s.__bitfield_1 ^ 0x60 | ((value & 1) << 5)\n//\t}\n//\n// Or the following:\n//\n//\tfunc (s *C.struct_foo) set_bitfield_c(value byte) {\n//\t    s.__bitfield_1 = s.__bitfield_1 & 0x3f | (value << 6)\n//\t}\nfunc (p *cgoPackage) createBitfieldSetter(bitfield bitfieldInfo, typeName string) {\n\t// The full field with all bitfields.\n\tvar field ast.Expr = &ast.SelectorExpr{\n\t\tX: &ast.Ident{\n\t\t\tNamePos: bitfield.pos,\n\t\t\tName:    \"s\",\n\t\t\tObj:     nil,\n\t\t},\n\t\tSel: &ast.Ident{\n\t\t\tNamePos: bitfield.pos,\n\t\t\tName:    bitfield.field.Names[0].Name,\n\t\t},\n\t}\n\t// The value to insert into the field.\n\tvar valueToInsert ast.Expr = &ast.Ident{\n\t\tNamePos: bitfield.pos,\n\t\tName:    \"value\",\n\t}\n\n\tif bitfield.endBit != 0 {\n\t\t// Make sure the value is in range with a mask.\n\t\tvalueToInsert = &ast.BinaryExpr{\n\t\t\tX:     valueToInsert,\n\t\t\tOpPos: bitfield.pos,\n\t\t\tOp:    token.AND,\n\t\t\tY: &ast.BasicLit{\n\t\t\t\tValuePos: bitfield.pos,\n\t\t\t\tKind:     token.INT,\n\t\t\t\tValue:    \"0x\" + strconv.FormatUint((uint64(1)<<uint64(bitfield.endBit-bitfield.startBit))-1, 16),\n\t\t\t},\n\t\t}\n\t\t// Create a mask for the AND NOT operation.\n\t\tmask := ((uint64(1) << uint64(bitfield.endBit-bitfield.startBit)) - 1) << uint64(bitfield.startBit)\n\t\t// Zero the bits in the field that will soon be inserted.\n\t\tfield = &ast.BinaryExpr{\n\t\t\tX:     field,\n\t\t\tOpPos: bitfield.pos,\n\t\t\tOp:    token.AND_NOT,\n\t\t\tY: &ast.BasicLit{\n\t\t\t\tValuePos: bitfield.pos,\n\t\t\t\tKind:     token.INT,\n\t\t\t\tValue:    \"0x\" + strconv.FormatUint(mask, 16),\n\t\t\t},\n\t\t}\n\t} else { // bitfield.endBit == 0\n\t\t// We don't know exactly how many high bits should be zeroed. So we do\n\t\t// something different: keep the low bits with a mask and OR the new\n\t\t// value with it.\n\t\tmask := (uint64(1) << uint64(bitfield.startBit)) - 1\n\t\t// Extract the lower bits.\n\t\tfield = &ast.BinaryExpr{\n\t\t\tX:     field,\n\t\t\tOpPos: bitfield.pos,\n\t\t\tOp:    token.AND,\n\t\t\tY: &ast.BasicLit{\n\t\t\t\tValuePos: bitfield.pos,\n\t\t\t\tKind:     token.INT,\n\t\t\t\tValue:    \"0x\" + strconv.FormatUint(mask, 16),\n\t\t\t},\n\t\t}\n\t}\n\n\t// Bitwise OR with the new value (after the new value has been shifted).\n\tfield = &ast.BinaryExpr{\n\t\tX:     field,\n\t\tOpPos: bitfield.pos,\n\t\tOp:    token.OR,\n\t\tY: &ast.BinaryExpr{\n\t\t\tX:     valueToInsert,\n\t\t\tOpPos: bitfield.pos,\n\t\t\tOp:    token.SHL,\n\t\t\tY: &ast.BasicLit{\n\t\t\t\tValuePos: bitfield.pos,\n\t\t\t\tKind:     token.INT,\n\t\t\t\tValue:    strconv.FormatInt(bitfield.startBit, 10),\n\t\t\t},\n\t\t},\n\t}\n\n\t// Create the setter function.\n\tsetter := &ast.FuncDecl{\n\t\tRecv: &ast.FieldList{\n\t\t\tOpening: bitfield.pos,\n\t\t\tList: []*ast.Field{\n\t\t\t\t{\n\t\t\t\t\tNames: []*ast.Ident{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tNamePos: bitfield.pos,\n\t\t\t\t\t\t\tName:    \"s\",\n\t\t\t\t\t\t\tObj: &ast.Object{\n\t\t\t\t\t\t\t\tKind: ast.Var,\n\t\t\t\t\t\t\t\tName: \"s\",\n\t\t\t\t\t\t\t\tDecl: nil,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tType: &ast.StarExpr{\n\t\t\t\t\t\tStar: bitfield.pos,\n\t\t\t\t\t\tX: &ast.Ident{\n\t\t\t\t\t\t\tNamePos: bitfield.pos,\n\t\t\t\t\t\t\tName:    typeName,\n\t\t\t\t\t\t\tObj:     nil,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tClosing: bitfield.pos,\n\t\t},\n\t\tName: &ast.Ident{\n\t\t\tNamePos: bitfield.pos,\n\t\t\tName:    \"set_bitfield_\" + bitfield.name,\n\t\t},\n\t\tType: &ast.FuncType{\n\t\t\tFunc: bitfield.pos,\n\t\t\tParams: &ast.FieldList{\n\t\t\t\tOpening: bitfield.pos,\n\t\t\t\tList: []*ast.Field{\n\t\t\t\t\t{\n\t\t\t\t\t\tNames: []*ast.Ident{\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tNamePos: bitfield.pos,\n\t\t\t\t\t\t\t\tName:    \"value\",\n\t\t\t\t\t\t\t\tObj:     nil,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tType: bitfield.field.Type,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tClosing: bitfield.pos,\n\t\t\t},\n\t\t},\n\t\tBody: &ast.BlockStmt{\n\t\t\tLbrace: bitfield.pos,\n\t\t\tList: []ast.Stmt{\n\t\t\t\t&ast.AssignStmt{\n\t\t\t\t\tLhs: []ast.Expr{\n\t\t\t\t\t\t&ast.SelectorExpr{\n\t\t\t\t\t\t\tX: &ast.Ident{\n\t\t\t\t\t\t\t\tNamePos: bitfield.pos,\n\t\t\t\t\t\t\t\tName:    \"s\",\n\t\t\t\t\t\t\t\tObj:     nil,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tSel: &ast.Ident{\n\t\t\t\t\t\t\t\tNamePos: bitfield.pos,\n\t\t\t\t\t\t\t\tName:    bitfield.field.Names[0].Name,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tTokPos: bitfield.pos,\n\t\t\t\t\tTok:    token.ASSIGN,\n\t\t\t\t\tRhs: []ast.Expr{\n\t\t\t\t\t\tfield,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tRbrace: bitfield.pos,\n\t\t},\n\t}\n\tp.generated.Decls = append(p.generated.Decls, setter)\n}\n\n// isEquivalentAST returns whether the given two AST nodes are equivalent as far\n// as CGo is concerned. This is used to check that C types, globals, etc defined\n// in different CGo header snippets are actually the same type (and probably\n// even defined in the same header file, just in different translation units).\nfunc (p *cgoPackage) isEquivalentAST(a, b ast.Node) bool {\n\tswitch node := a.(type) {\n\tcase *ast.ArrayType:\n\t\tb, ok := b.(*ast.ArrayType)\n\t\tif !ok {\n\t\t\treturn false\n\t\t}\n\t\tif !p.isEquivalentAST(node.Len, b.Len) {\n\t\t\treturn false\n\t\t}\n\t\treturn p.isEquivalentAST(node.Elt, b.Elt)\n\tcase *ast.BasicLit:\n\t\tb, ok := b.(*ast.BasicLit)\n\t\tif !ok {\n\t\t\treturn false\n\t\t}\n\t\t// Note: this comparison is not correct in general (\"1e2\" equals \"100\"),\n\t\t// but is correct for its use in the cgo package.\n\t\treturn node.Value == b.Value\n\tcase *ast.CommentGroup:\n\t\tb, ok := b.(*ast.CommentGroup)\n\t\tif !ok {\n\t\t\treturn false\n\t\t}\n\t\tif len(node.List) != len(b.List) {\n\t\t\treturn false\n\t\t}\n\t\tfor i, c := range node.List {\n\t\t\tif c.Text != b.List[i].Text {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\tcase *ast.FieldList:\n\t\tb, ok := b.(*ast.FieldList)\n\t\tif !ok {\n\t\t\treturn false\n\t\t}\n\t\tif node == nil || b == nil {\n\t\t\treturn node == b\n\t\t}\n\t\tif len(node.List) != len(b.List) {\n\t\t\treturn false\n\t\t}\n\t\tfor i, f := range node.List {\n\t\t\tif !p.isEquivalentAST(f, b.List[i]) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\tcase *ast.Field:\n\t\tb, ok := b.(*ast.Field)\n\t\tif !ok {\n\t\t\treturn false\n\t\t}\n\t\tif !p.isEquivalentAST(node.Type, b.Type) {\n\t\t\treturn false\n\t\t}\n\t\tif len(node.Names) != len(b.Names) {\n\t\t\treturn false\n\t\t}\n\t\tfor i, name := range node.Names {\n\t\t\tif name.Name != b.Names[i].Name {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\tcase *ast.FuncDecl:\n\t\tb, ok := b.(*ast.FuncDecl)\n\t\tif !ok {\n\t\t\treturn false\n\t\t}\n\t\tif node.Name.Name != b.Name.Name {\n\t\t\treturn false\n\t\t}\n\t\tif node.Doc != b.Doc {\n\t\t\tif !p.isEquivalentAST(node.Doc, b.Doc) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\tif node.Recv != b.Recv {\n\t\t\tif !p.isEquivalentAST(node.Recv, b.Recv) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\tif !p.isEquivalentAST(node.Type.Params, b.Type.Params) {\n\t\t\treturn false\n\t\t}\n\t\treturn p.isEquivalentAST(node.Type.Results, b.Type.Results)\n\tcase *ast.GenDecl:\n\t\tb, ok := b.(*ast.GenDecl)\n\t\tif !ok {\n\t\t\treturn false\n\t\t}\n\t\tif node.Doc != b.Doc {\n\t\t\tif !p.isEquivalentAST(node.Doc, b.Doc) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\tif len(node.Specs) != len(b.Specs) {\n\t\t\treturn false\n\t\t}\n\t\tfor i, s := range node.Specs {\n\t\t\tif !p.isEquivalentAST(s, b.Specs[i]) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\tcase *ast.Ident:\n\t\tb, ok := b.(*ast.Ident)\n\t\tif !ok {\n\t\t\treturn false\n\t\t}\n\t\treturn node.Name == b.Name\n\tcase *ast.SelectorExpr:\n\t\tb, ok := b.(*ast.SelectorExpr)\n\t\tif !ok {\n\t\t\treturn false\n\t\t}\n\t\tif !p.isEquivalentAST(node.Sel, b.Sel) {\n\t\t\treturn false\n\t\t}\n\t\treturn p.isEquivalentAST(node.X, b.X)\n\tcase *ast.StarExpr:\n\t\tb, ok := b.(*ast.StarExpr)\n\t\tif !ok {\n\t\t\treturn false\n\t\t}\n\t\treturn p.isEquivalentAST(node.X, b.X)\n\tcase *ast.StructType:\n\t\tb, ok := b.(*ast.StructType)\n\t\tif !ok {\n\t\t\treturn false\n\t\t}\n\t\treturn p.isEquivalentAST(node.Fields, b.Fields)\n\tcase *ast.TypeSpec:\n\t\tb, ok := b.(*ast.TypeSpec)\n\t\tif !ok {\n\t\t\treturn false\n\t\t}\n\t\tif node.Name.Name != b.Name.Name {\n\t\t\treturn false\n\t\t}\n\t\tif node.Assign.IsValid() != b.Assign.IsValid() {\n\t\t\treturn false\n\t\t}\n\t\treturn p.isEquivalentAST(node.Type, b.Type)\n\tcase *ast.ValueSpec:\n\t\tb, ok := b.(*ast.ValueSpec)\n\t\tif !ok {\n\t\t\treturn false\n\t\t}\n\t\tif len(node.Names) != len(b.Names) {\n\t\t\treturn false\n\t\t}\n\t\tfor i, name := range node.Names {\n\t\t\tif name.Name != b.Names[i].Name {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\tif node.Type != b.Type && !p.isEquivalentAST(node.Type, b.Type) {\n\t\t\treturn false\n\t\t}\n\t\tif len(node.Values) != len(b.Values) {\n\t\t\treturn false\n\t\t}\n\t\tfor i, value := range node.Values {\n\t\t\tif !p.isEquivalentAST(value, b.Values[i]) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\tcase nil:\n\t\tp.addError(token.NoPos, \"internal error: AST node is nil\")\n\t\treturn true\n\tdefault:\n\t\tp.addError(a.Pos(), fmt.Sprintf(\"internal error: unknown AST node: %T\", a))\n\t\treturn true\n\t}\n}\n\n// getPos returns node.Pos(), and tries to obtain a closely related position if\n// that fails.\nfunc getPos(node ast.Node) token.Pos {\n\tpos := node.Pos()\n\tif pos.IsValid() {\n\t\treturn pos\n\t}\n\tif decl, ok := node.(*ast.GenDecl); ok {\n\t\t// *ast.GenDecl often doesn't have TokPos defined, so look at the first\n\t\t// spec.\n\t\treturn getPos(decl.Specs[0])\n\t}\n\treturn token.NoPos\n}\n\n// getUnnamedDeclName creates a name (with the given prefix) for the given C\n// declaration. This is used for structs, unions, and enums that are often\n// defined without a name and used in a typedef.\nfunc (p *cgoPackage) getUnnamedDeclName(prefix string, itf interface{}) string {\n\tif name, ok := p.anonDecls[itf]; ok {\n\t\treturn name\n\t}\n\tname := prefix + strconv.Itoa(len(p.anonDecls))\n\tp.anonDecls[itf] = name\n\treturn name\n}\n\n// getASTDeclName will declare the given C AST node (if not already defined) and\n// will return its name, in the form of C.foo.\nfunc (f *cgoFile) getASTDeclName(name string, found clangCursor, iscall bool) string {\n\t// Some types are defined in stdint.h and map directly to a particular Go\n\t// type.\n\tif alias := cgoAliases[\"_Cgo_\"+name]; alias != \"\" {\n\t\treturn alias\n\t}\n\tnode := f.getASTDeclNode(name, found)\n\tif node, ok := node.(*ast.FuncDecl); ok {\n\t\tif !iscall {\n\t\t\treturn node.Name.Name + \"$funcaddr\"\n\t\t}\n\t\treturn node.Name.Name\n\t}\n\treturn \"_Cgo_\" + name\n}\n\n// getASTDeclNode will declare the given C AST node (if not already defined) and\n// returns it.\nfunc (f *cgoFile) getASTDeclNode(name string, found clangCursor) ast.Node {\n\tif node, ok := f.defined[name]; ok {\n\t\t// Declaration was found in the current file, so return it immediately.\n\t\treturn node\n\t}\n\n\tif node, ok := f.definedGlobally[name]; ok {\n\t\t// Declaration was previously created, but not for the current file. It\n\t\t// may be different (because it comes from a different CGo snippet), so\n\t\t// we need to check whether the AST for this definition is equivalent.\n\t\tf.defined[name] = nil\n\t\tnewNode, _ := f.createASTNode(name, found)\n\t\tif !f.isEquivalentAST(node, newNode) {\n\t\t\t// It's not. Return a nice error with both locations.\n\t\t\t// Original cgo reports an error like\n\t\t\t//   cgo: inconsistent definitions for C.myint\n\t\t\t// which is far less helpful.\n\t\t\tf.addError(getPos(node), name+\" defined previously at \"+f.fset.Position(getPos(newNode)).String()+\" with a different type\")\n\t\t}\n\t\tf.defined[name] = node\n\t\treturn node\n\t}\n\n\t// The declaration has no AST node. Create it now.\n\tf.defined[name] = nil\n\tnode, extra := f.createASTNode(name, found)\n\tf.defined[name] = node\n\tswitch node := node.(type) {\n\tcase *ast.FuncDecl:\n\t\tif strings.HasPrefix(node.Doc.List[0].Text, \"//export _Cgo_static_\") {\n\t\t\t// Static function. Only accessible in the current Go file.\n\t\t\tglobalName := strings.TrimPrefix(node.Doc.List[0].Text, \"//export \")\n\t\t\t// Make an alias. Normally this is done using the alias function\n\t\t\t// attribute, but MacOS for some reason doesn't support this (even\n\t\t\t// though the linker has support for aliases in the form of N_INDR).\n\t\t\t// Therefore, create an actual function for MacOS.\n\t\t\tvar params []string\n\t\t\tfor _, param := range node.Type.Params.List {\n\t\t\t\tparams = append(params, param.Names[0].Name)\n\t\t\t}\n\t\t\tcallInst := fmt.Sprintf(\"%s(%s);\", name, strings.Join(params, \", \"))\n\t\t\tif node.Type.Results != nil {\n\t\t\t\tcallInst = \"return \" + callInst\n\t\t\t}\n\t\t\taliasDeclaration := fmt.Sprintf(`\n#ifdef __APPLE__\n%s {\n\t%s\n}\n#else\nextern __typeof(%s) %s __attribute__((alias(%#v)));\n#endif\n`, extra.(string), callInst, name, globalName, name)\n\t\t\tf.cgoHeaders[f.index] += \"\\n\\n\" + aliasDeclaration\n\t\t} else {\n\t\t\t// Regular (non-static) function.\n\t\t\tf.definedGlobally[name] = node\n\t\t}\n\t\tf.generated.Decls = append(f.generated.Decls, node)\n\t\t// Also add a declaration like the following:\n\t\t//   var C.foo$funcaddr unsafe.Pointer\n\t\tf.generated.Decls = append(f.generated.Decls, &ast.GenDecl{\n\t\t\tTok: token.VAR,\n\t\t\tSpecs: []ast.Spec{\n\t\t\t\t&ast.ValueSpec{\n\t\t\t\t\tNames: []*ast.Ident{{Name: node.Name.Name + \"$funcaddr\"}},\n\t\t\t\t\tType: &ast.SelectorExpr{\n\t\t\t\t\t\tX:   &ast.Ident{Name: \"unsafe\"},\n\t\t\t\t\t\tSel: &ast.Ident{Name: \"Pointer\"},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t})\n\tcase *ast.GenDecl:\n\t\tf.definedGlobally[name] = node\n\t\tf.generated.Decls = append(f.generated.Decls, node)\n\tcase *ast.TypeSpec:\n\t\tf.definedGlobally[name] = node\n\t\tf.generated.Decls = append(f.generated.Decls, &ast.GenDecl{\n\t\t\tTok:   token.TYPE,\n\t\t\tSpecs: []ast.Spec{node},\n\t\t})\n\tcase nil:\n\t\t// Node may be nil in case of an error. In that case, just don't add it\n\t\t// as a declaration.\n\tdefault:\n\t\tpanic(\"unexpected AST node\")\n\t}\n\n\t// If this is a struct or union it may need bitfields or union accessor\n\t// methods.\n\tswitch elaboratedType := extra.(type) {\n\tcase *elaboratedTypeInfo:\n\t\t// Add struct bitfields.\n\t\tfor _, bitfield := range elaboratedType.bitfields {\n\t\t\tf.createBitfieldGetter(bitfield, \"_Cgo_\"+name)\n\t\t\tf.createBitfieldSetter(bitfield, \"_Cgo_\"+name)\n\t\t}\n\t\tif elaboratedType.unionSize != 0 {\n\t\t\t// Create union getters/setters.\n\t\t\tfor _, field := range elaboratedType.typeExpr.Fields.List {\n\t\t\t\tif len(field.Names) != 1 {\n\t\t\t\t\tf.addError(elaboratedType.pos, fmt.Sprintf(\"union must have field with a single name, it has %d names\", len(field.Names)))\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tf.createUnionAccessor(field, \"_Cgo_\"+name)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn node\n}\n\n// walker replaces all \"C\".<something> expressions to literal \"C.<something>\"\n// expressions. Such expressions are impossible to write in Go (a dot cannot be\n// used in the middle of a name) so in practice all C identifiers live in a\n// separate namespace (no _Cgo_ hacks like in gc).\nfunc (f *cgoFile) walker(cursor *astutil.Cursor, names map[string]clangCursor) bool {\n\tswitch node := cursor.Node().(type) {\n\tcase *ast.AssignStmt:\n\t\t// An assign statement could be something like this:\n\t\t//\n\t\t//   val, errno := C.some_func()\n\t\t//\n\t\t// Check whether it looks like that, and if so, read the errno value and\n\t\t// return it as the second return value. The call will be transformed\n\t\t// into something like this:\n\t\t//\n\t\t//   val, errno := C.some_func(), C.__get_errno()\n\t\tif len(node.Lhs) != 2 || len(node.Rhs) != 1 {\n\t\t\treturn true\n\t\t}\n\t\trhs, ok := node.Rhs[0].(*ast.CallExpr)\n\t\tif !ok {\n\t\t\treturn true\n\t\t}\n\t\tfun, ok := rhs.Fun.(*ast.SelectorExpr)\n\t\tif !ok {\n\t\t\treturn true\n\t\t}\n\t\tx, ok := fun.X.(*ast.Ident)\n\t\tif !ok {\n\t\t\treturn true\n\t\t}\n\t\tif found, ok := names[fun.Sel.Name]; ok && x.Name == \"C\" {\n\t\t\t// Replace \"C\".\"some_func\" into \"C.somefunc\".\n\t\t\trhs.Fun = &ast.Ident{\n\t\t\t\tNamePos: x.NamePos,\n\t\t\t\tName:    f.getASTDeclName(fun.Sel.Name, found, true),\n\t\t\t}\n\t\t\t// Add the errno value as the second value in the statement.\n\t\t\tnode.Rhs = append(node.Rhs, &ast.CallExpr{\n\t\t\t\tFun: &ast.Ident{\n\t\t\t\t\tNamePos: node.Lhs[1].End(),\n\t\t\t\t\tName:    \"_Cgo___get_errno\",\n\t\t\t\t},\n\t\t\t})\n\t\t}\n\tcase *ast.CallExpr:\n\t\tfun, ok := node.Fun.(*ast.SelectorExpr)\n\t\tif !ok {\n\t\t\treturn true\n\t\t}\n\t\tx, ok := fun.X.(*ast.Ident)\n\t\tif !ok {\n\t\t\treturn true\n\t\t}\n\t\tif found, ok := names[fun.Sel.Name]; ok && x.Name == \"C\" {\n\t\t\tnode.Fun = &ast.Ident{\n\t\t\t\tNamePos: x.NamePos,\n\t\t\t\tName:    f.getASTDeclName(fun.Sel.Name, found, true),\n\t\t\t}\n\t\t}\n\tcase *ast.SelectorExpr:\n\t\tx, ok := node.X.(*ast.Ident)\n\t\tif !ok {\n\t\t\treturn true\n\t\t}\n\t\tif x.Name == \"C\" {\n\t\t\tname := \"_Cgo_\" + node.Sel.Name\n\t\t\tif found, ok := names[node.Sel.Name]; ok {\n\t\t\t\tname = f.getASTDeclName(node.Sel.Name, found, false)\n\t\t\t}\n\t\t\tcursor.Replace(&ast.Ident{\n\t\t\t\tNamePos: x.NamePos,\n\t\t\t\tName:    name,\n\t\t\t})\n\t\t}\n\t}\n\treturn true\n}\n\n// renameFieldKeywords renames all reserved words in Go to some other field name\n// with a \"_\" prefix. For example, it renames `type` to `_type`.\n//\n// See: https://golang.org/cmd/cgo/#hdr-Go_references_to_C\nfunc renameFieldKeywords(fieldList *ast.FieldList) {\n\trenameFieldName(fieldList, \"type\")\n}\n\n// renameFieldName renames a given field name to a name with a \"_\" prepended. It\n// makes sure to do the same thing for any field sharing the same name.\nfunc renameFieldName(fieldList *ast.FieldList, name string) {\n\tvar ident *ast.Ident\n\tfor _, f := range fieldList.List {\n\t\tfor _, n := range f.Names {\n\t\t\tif n.Name == name {\n\t\t\t\tident = n\n\t\t\t}\n\t\t}\n\t}\n\tif ident == nil {\n\t\treturn\n\t}\n\trenameFieldName(fieldList, \"_\"+name)\n\tident.Name = \"_\" + ident.Name\n}\n"
  },
  {
    "path": "cgo/cgo_go122.go",
    "content": "//go:build go1.22\n\npackage cgo\n\n// Code specifically for Go 1.22.\n\nimport (\n\t\"go/ast\"\n\t\"go/token\"\n)\n\nfunc init() {\n\tsetASTFileFields = func(f *ast.File, start, end token.Pos) {\n\t\tf.FileStart = start\n\t\tf.FileEnd = end\n\t}\n}\n"
  },
  {
    "path": "cgo/cgo_test.go",
    "content": "package cgo\n\nimport (\n\t\"bytes\"\n\t\"flag\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/format\"\n\t\"go/parser\"\n\t\"go/scanner\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n)\n\n// Pass -update to go test to update the output of the test files.\nvar flagUpdate = flag.Bool(\"update\", false, \"Update images based on test output.\")\n\n// normalizeResult normalizes Go source code that comes out of tests across\n// platforms and Go versions.\nfunc normalizeResult(t *testing.T, result string) string {\n\tresult = strings.ReplaceAll(result, \"\\r\\n\", \"\\n\")\n\n\t// This changed to 'undefined:', in Go 1.20.\n\tresult = strings.ReplaceAll(result, \": undeclared name:\", \": undefined:\")\n\t// Go 1.20 added a bit more detail\n\tresult = regexp.MustCompile(`(unknown field z in struct literal).*`).ReplaceAllString(result, \"$1\")\n\n\treturn result\n}\n\nfunc TestCGo(t *testing.T) {\n\tvar cflags = []string{\"--target=armv6m-unknown-unknown-eabi\"}\n\n\tfor _, name := range []string{\n\t\t\"basic\",\n\t\t\"errors\",\n\t\t\"types\",\n\t\t\"symbols\",\n\t\t\"flags\",\n\t\t\"const\",\n\t} {\n\t\tname := name // avoid a race condition\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\t// Read the AST in memory.\n\t\t\tpath := filepath.Join(\"testdata\", name+\".go\")\n\t\t\tfset := token.NewFileSet()\n\t\t\tf, err := parser.ParseFile(fset, path, nil, parser.ParseComments)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(\"could not parse Go source file:\", err)\n\t\t\t}\n\n\t\t\t// Process the AST with CGo.\n\t\t\tcgoFiles, _, _, _, _, cgoErrors := Process([]*ast.File{f}, \"testdata\", \"main\", fset, cflags, \"linux\")\n\n\t\t\t// Check the AST for type errors.\n\t\t\tvar typecheckErrors []error\n\t\t\tconfig := types.Config{\n\t\t\t\tError: func(err error) {\n\t\t\t\t\ttypecheckErrors = append(typecheckErrors, err)\n\t\t\t\t},\n\t\t\t\tImporter: newSimpleImporter(),\n\t\t\t\tSizes:    types.SizesFor(\"gccgo\", \"arm\"),\n\t\t\t}\n\t\t\t_, err = config.Check(\"\", fset, append([]*ast.File{f}, cgoFiles...), nil)\n\t\t\tif err != nil && len(typecheckErrors) == 0 {\n\t\t\t\t// Only report errors when no type errors are found (an\n\t\t\t\t// unexpected condition).\n\t\t\t\tt.Error(err)\n\t\t\t}\n\n\t\t\t// Store the (formatted) output in a buffer. Format it, so it\n\t\t\t// becomes easier to read (and will hopefully change less with CGo\n\t\t\t// changes).\n\t\t\tbuf := &bytes.Buffer{}\n\t\t\tif len(cgoErrors) != 0 {\n\t\t\t\tbuf.WriteString(\"// CGo errors:\\n\")\n\t\t\t\tfor _, err := range cgoErrors {\n\t\t\t\t\tbuf.WriteString(formatDiagnostic(err))\n\t\t\t\t}\n\t\t\t\tbuf.WriteString(\"\\n\")\n\t\t\t}\n\t\t\tif len(typecheckErrors) != 0 {\n\t\t\t\tbuf.WriteString(\"// Type checking errors after CGo processing:\\n\")\n\t\t\t\tfor _, err := range typecheckErrors {\n\t\t\t\t\tbuf.WriteString(formatDiagnostic(err))\n\t\t\t\t}\n\t\t\t\tbuf.WriteString(\"\\n\")\n\t\t\t}\n\t\t\terr = format.Node(buf, fset, cgoFiles[0])\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"could not write out CGo AST: %v\", err)\n\t\t\t}\n\t\t\tactual := normalizeResult(t, buf.String())\n\n\t\t\t// Read the file with the expected output, to compare against.\n\t\t\toutfile := filepath.Join(\"testdata\", name+\".out.go\")\n\t\t\texpectedBytes, err := os.ReadFile(outfile)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"could not read expected output: %v\", err)\n\t\t\t}\n\t\t\texpected := strings.ReplaceAll(string(expectedBytes), \"\\r\\n\", \"\\n\")\n\n\t\t\t// Check whether the output is as expected.\n\t\t\tif expected != actual {\n\t\t\t\t// It is not. Test failed.\n\t\t\t\tif *flagUpdate {\n\t\t\t\t\t// Update the file with the expected data.\n\t\t\t\t\terr := os.WriteFile(outfile, []byte(actual), 0666)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tt.Error(\"could not write updated output file:\", err)\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tt.Errorf(\"output did not match:\\n%s\", string(actual))\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc Test_cgoPackage_isEquivalentAST(t *testing.T) {\n\tfieldA := &ast.Field{Type: &ast.BasicLit{Kind: token.STRING, Value: \"a\"}}\n\tfieldB := &ast.Field{Type: &ast.BasicLit{Kind: token.STRING, Value: \"b\"}}\n\tlistOfFieldA := &ast.FieldList{List: []*ast.Field{fieldA}}\n\tlistOfFieldB := &ast.FieldList{List: []*ast.Field{fieldB}}\n\tfuncDeclA := &ast.FuncDecl{Name: &ast.Ident{Name: \"a\"}, Type: &ast.FuncType{Params: &ast.FieldList{}, Results: listOfFieldA}}\n\tfuncDeclB := &ast.FuncDecl{Name: &ast.Ident{Name: \"b\"}, Type: &ast.FuncType{Params: &ast.FieldList{}, Results: listOfFieldB}}\n\tfuncDeclNoResults := &ast.FuncDecl{Name: &ast.Ident{Name: \"C\"}, Type: &ast.FuncType{Params: &ast.FieldList{}}}\n\n\ttestCases := []struct {\n\t\tname     string\n\t\ta, b     ast.Node\n\t\texpected bool\n\t}{\n\t\t{\n\t\t\tname:     \"both nil\",\n\t\t\texpected: true,\n\t\t},\n\t\t{\n\t\t\tname:     \"not same type\",\n\t\t\ta:        fieldA,\n\t\t\tb:        &ast.FuncDecl{},\n\t\t\texpected: false,\n\t\t},\n\t\t{\n\t\t\tname:     \"Field same\",\n\t\t\ta:        fieldA,\n\t\t\tb:        fieldA,\n\t\t\texpected: true,\n\t\t},\n\t\t{\n\t\t\tname:     \"Field different\",\n\t\t\ta:        fieldA,\n\t\t\tb:        fieldB,\n\t\t\texpected: false,\n\t\t},\n\t\t{\n\t\t\tname:     \"FuncDecl Type Results nil\",\n\t\t\ta:        funcDeclNoResults,\n\t\t\tb:        funcDeclNoResults,\n\t\t\texpected: true,\n\t\t},\n\t\t{\n\t\t\tname:     \"FuncDecl Type Results same\",\n\t\t\ta:        funcDeclA,\n\t\t\tb:        funcDeclA,\n\t\t\texpected: true,\n\t\t},\n\t\t{\n\t\t\tname:     \"FuncDecl Type Results different\",\n\t\t\ta:        funcDeclA,\n\t\t\tb:        funcDeclB,\n\t\t\texpected: false,\n\t\t},\n\t\t{\n\t\t\tname:     \"FuncDecl Type Results a nil\",\n\t\t\ta:        funcDeclNoResults,\n\t\t\tb:        funcDeclB,\n\t\t\texpected: false,\n\t\t},\n\t\t{\n\t\t\tname:     \"FuncDecl Type Results b nil\",\n\t\t\ta:        funcDeclA,\n\t\t\tb:        funcDeclNoResults,\n\t\t\texpected: false,\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tp := &cgoPackage{}\n\t\t\tif got := p.isEquivalentAST(tc.a, tc.b); tc.expected != got {\n\t\t\t\tt.Errorf(\"expected %v, got %v\", tc.expected, got)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// simpleImporter implements the types.Importer interface, but only allows\n// importing the syscall and unsafe packages.\ntype simpleImporter struct {\n\tsyscallPkg *types.Package\n}\n\nfunc newSimpleImporter() *simpleImporter {\n\ti := &simpleImporter{}\n\n\t// Implement a dummy syscall package with the Errno type.\n\ti.syscallPkg = types.NewPackage(\"syscall\", \"syscall\")\n\tobj := types.NewTypeName(token.NoPos, i.syscallPkg, \"Errno\", nil)\n\tnamed := types.NewNamed(obj, nil, nil)\n\ti.syscallPkg.Scope().Insert(obj)\n\tnamed.SetUnderlying(types.Typ[types.Uintptr])\n\tsig := types.NewSignatureType(nil, nil, nil, types.NewTuple(), types.NewTuple(types.NewParam(token.NoPos, i.syscallPkg, \"\", types.Typ[types.String])), false)\n\tnamed.AddMethod(types.NewFunc(token.NoPos, i.syscallPkg, \"Error\", sig))\n\ti.syscallPkg.MarkComplete()\n\n\treturn i\n}\n\n// Import implements the Importer interface. For testing usage only: it only\n// supports importing the unsafe package.\nfunc (i *simpleImporter) Import(path string) (*types.Package, error) {\n\tswitch path {\n\tcase \"syscall\":\n\t\treturn i.syscallPkg, nil\n\tcase \"unsafe\":\n\t\treturn types.Unsafe, nil\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"importer not implemented for package %s\", path)\n\t}\n}\n\n// formatDiagnostic formats the error message to be an indented comment. It\n// also fixes Windows path name issues (backward slashes).\nfunc formatDiagnostic(err error) string {\n\tvar msg string\n\tswitch err := err.(type) {\n\tcase scanner.Error:\n\t\tmsg = err.Pos.String() + \": \" + err.Msg\n\tdefault:\n\t\tmsg = err.Error()\n\t}\n\tif runtime.GOOS == \"windows\" {\n\t\t// Fix Windows path slashes.\n\t\tmsg = strings.ReplaceAll(msg, \"testdata\\\\\", \"testdata/\")\n\t}\n\treturn \"//     \" + msg + \"\\n\"\n}\n"
  },
  {
    "path": "cgo/const.go",
    "content": "package cgo\n\n// This file implements a parser of a subset of the C language, just enough to\n// parse common #define statements to Go constant expressions.\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/scanner\"\n\t\"go/token\"\n\t\"strings\"\n)\n\nvar (\n\tprefixParseFns map[token.Token]func(*tokenizer) (ast.Expr, *scanner.Error)\n\tprecedences    = map[token.Token]int{\n\t\ttoken.OR:  precedenceOr,\n\t\ttoken.XOR: precedenceXor,\n\t\ttoken.AND: precedenceAnd,\n\t\ttoken.SHL: precedenceShift,\n\t\ttoken.SHR: precedenceShift,\n\t\ttoken.ADD: precedenceAdd,\n\t\ttoken.SUB: precedenceAdd,\n\t\ttoken.MUL: precedenceMul,\n\t\ttoken.QUO: precedenceMul,\n\t\ttoken.REM: precedenceMul,\n\t}\n)\n\n// See: https://en.cppreference.com/w/c/language/operator_precedence\nconst (\n\tprecedenceLowest = iota + 1\n\tprecedenceOr\n\tprecedenceXor\n\tprecedenceAnd\n\tprecedenceShift\n\tprecedenceAdd\n\tprecedenceMul\n\tprecedencePrefix\n)\n\nfunc init() {\n\t// This must be done in an init function to avoid an initialization order\n\t// failure.\n\tprefixParseFns = map[token.Token]func(*tokenizer) (ast.Expr, *scanner.Error){\n\t\ttoken.IDENT:  parseIdent,\n\t\ttoken.INT:    parseBasicLit,\n\t\ttoken.FLOAT:  parseBasicLit,\n\t\ttoken.STRING: parseBasicLit,\n\t\ttoken.CHAR:   parseBasicLit,\n\t\ttoken.LPAREN: parseParenExpr,\n\t\ttoken.SUB:    parseUnaryExpr,\n\t}\n}\n\n// parseConst parses the given string as a C constant.\nfunc parseConst(pos token.Pos, fset *token.FileSet, value string, params []ast.Expr, callerPos token.Pos, f *cgoFile) (ast.Expr, *scanner.Error) {\n\tt := newTokenizer(pos, fset, value, f)\n\n\t// If params is non-nil (could be a zero length slice), this const is\n\t// actually a function-call like expression from another macro.\n\t// This means we have to parse a string like \"(a, b) (a+b)\".\n\t// We do this by parsing the parameters at the start and then treating the\n\t// following like a normal constant expression.\n\tif params != nil {\n\t\t// Parse opening paren.\n\t\tif t.curToken != token.LPAREN {\n\t\t\treturn nil, unexpectedToken(t, token.LPAREN)\n\t\t}\n\t\tt.Next()\n\n\t\t// Parse parameters (identifiers) and closing paren.\n\t\tvar paramIdents []string\n\t\tfor i := 0; ; i++ {\n\t\t\tif i == 0 && t.curToken == token.RPAREN {\n\t\t\t\t// No parameters, break early.\n\t\t\t\tt.Next()\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\t// Read the parameter name.\n\t\t\tif t.curToken != token.IDENT {\n\t\t\t\treturn nil, unexpectedToken(t, token.IDENT)\n\t\t\t}\n\t\t\tparamIdents = append(paramIdents, t.curValue)\n\t\t\tt.Next()\n\n\t\t\t// Read the next token: either a continuation (comma) or end of list\n\t\t\t// (rparen).\n\t\t\tif t.curToken == token.RPAREN {\n\t\t\t\t// End of parameter list.\n\t\t\t\tt.Next()\n\t\t\t\tbreak\n\t\t\t} else if t.curToken == token.COMMA {\n\t\t\t\t// Comma, so there will be another parameter name.\n\t\t\t\tt.Next()\n\t\t\t} else {\n\t\t\t\treturn nil, &scanner.Error{\n\t\t\t\t\tPos: t.fset.Position(t.curPos),\n\t\t\t\t\tMsg: \"unexpected token \" + t.curToken.String() + \" inside macro parameters, expected ',' or ')'\",\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Report an error if there is a mismatch in parameter length.\n\t\t// The error is reported at the location of the closing paren from the\n\t\t// caller location.\n\t\tif len(params) != len(paramIdents) {\n\t\t\treturn nil, &scanner.Error{\n\t\t\t\tPos: t.fset.Position(callerPos),\n\t\t\t\tMsg: fmt.Sprintf(\"unexpected number of parameters: expected %d, got %d\", len(paramIdents), len(params)),\n\t\t\t}\n\t\t}\n\n\t\t// Assign values to the parameters.\n\t\t// These parameter names are closer in 'scope' than other identifiers so\n\t\t// will be used first when parsing an identifier.\n\t\tfor i, name := range paramIdents {\n\t\t\tt.params[name] = params[i]\n\t\t}\n\t}\n\n\texpr, err := parseConstExpr(t, precedenceLowest)\n\tt.Next()\n\tif t.curToken != token.EOF {\n\t\treturn nil, &scanner.Error{\n\t\t\tPos: t.fset.Position(t.curPos),\n\t\t\tMsg: \"unexpected token \" + t.curToken.String() + \", expected end of expression\",\n\t\t}\n\t}\n\treturn expr, err\n}\n\n// parseConstExpr parses a stream of C tokens to a Go expression.\nfunc parseConstExpr(t *tokenizer, precedence int) (ast.Expr, *scanner.Error) {\n\tif t.curToken == token.EOF {\n\t\treturn nil, &scanner.Error{\n\t\t\tPos: t.fset.Position(t.curPos),\n\t\t\tMsg: \"empty constant\",\n\t\t}\n\t}\n\tprefix := prefixParseFns[t.curToken]\n\tif prefix == nil {\n\t\treturn nil, &scanner.Error{\n\t\t\tPos: t.fset.Position(t.curPos),\n\t\t\tMsg: fmt.Sprintf(\"unexpected token %s\", t.curToken),\n\t\t}\n\t}\n\tleftExpr, err := prefix(t)\n\n\tfor t.peekToken != token.EOF && precedence < precedences[t.peekToken] {\n\t\tswitch t.peekToken {\n\t\tcase token.OR, token.XOR, token.AND, token.SHL, token.SHR, token.ADD, token.SUB, token.MUL, token.QUO, token.REM:\n\t\t\tt.Next()\n\t\t\tleftExpr, err = parseBinaryExpr(t, leftExpr)\n\t\t}\n\t}\n\n\treturn leftExpr, err\n}\n\nfunc parseIdent(t *tokenizer) (ast.Expr, *scanner.Error) {\n\t// If the identifier is one of the parameters of this function-like macro,\n\t// use the parameter value.\n\tif val, ok := t.params[t.curValue]; ok {\n\t\treturn val, nil\n\t}\n\n\tif t.f != nil {\n\t\t// Check whether this identifier is actually a macro \"call\" with\n\t\t// parameters. In that case, we should parse the parameters and pass it\n\t\t// on to a new invocation of parseConst.\n\t\tif t.peekToken == token.LPAREN {\n\t\t\tif cursor, ok := t.f.names[t.curValue]; ok && t.f.isFunctionLikeMacro(cursor) {\n\t\t\t\t// We know the current and peek tokens (the peek one is the '('\n\t\t\t\t// token). So skip ahead until the current token is the first\n\t\t\t\t// unknown token.\n\t\t\t\tt.Next()\n\t\t\t\tt.Next()\n\n\t\t\t\t// Parse the list of parameters until ')' (rparen) is found.\n\t\t\t\tparams := []ast.Expr{}\n\t\t\t\tfor i := 0; ; i++ {\n\t\t\t\t\tif i == 0 && t.curToken == token.RPAREN {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tx, err := parseConstExpr(t, precedenceLowest)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn nil, err\n\t\t\t\t\t}\n\t\t\t\t\tparams = append(params, x)\n\t\t\t\t\tt.Next()\n\t\t\t\t\tif t.curToken == token.COMMA {\n\t\t\t\t\t\tt.Next()\n\t\t\t\t\t} else if t.curToken == token.RPAREN {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn nil, &scanner.Error{\n\t\t\t\t\t\t\tPos: t.fset.Position(t.curPos),\n\t\t\t\t\t\t\tMsg: \"unexpected token \" + t.curToken.String() + \", ',' or ')'\",\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Evaluate the macro value and use it as the identifier value.\n\t\t\t\trparen := t.curPos\n\t\t\t\tpos, text := t.f.getMacro(cursor)\n\t\t\t\treturn parseConst(pos, t.fset, text, params, rparen, t.f)\n\t\t\t}\n\t\t}\n\n\t\t// Normally the name is something defined in the file (like another\n\t\t// macro) which we get the declaration from using getASTDeclName.\n\t\t// This ensures that names that are only referenced inside a macro are\n\t\t// still getting defined.\n\t\tif cursor, ok := t.f.names[t.curValue]; ok {\n\t\t\treturn &ast.Ident{\n\t\t\t\tNamePos: t.curPos,\n\t\t\t\tName:    t.f.getASTDeclName(t.curValue, cursor, false),\n\t\t\t}, nil\n\t\t}\n\t}\n\n\t// t.f is nil during testing. This is a fallback.\n\treturn &ast.Ident{\n\t\tNamePos: t.curPos,\n\t\tName:    \"C.\" + t.curValue,\n\t}, nil\n}\n\nfunc parseBasicLit(t *tokenizer) (ast.Expr, *scanner.Error) {\n\treturn &ast.BasicLit{\n\t\tValuePos: t.curPos,\n\t\tKind:     t.curToken,\n\t\tValue:    t.curValue,\n\t}, nil\n}\n\nfunc parseParenExpr(t *tokenizer) (ast.Expr, *scanner.Error) {\n\tlparen := t.curPos\n\tt.Next()\n\tx, err := parseConstExpr(t, precedenceLowest)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tt.Next()\n\tif t.curToken != token.RPAREN {\n\t\treturn nil, unexpectedToken(t, token.RPAREN)\n\t}\n\texpr := &ast.ParenExpr{\n\t\tLparen: lparen,\n\t\tX:      x,\n\t\tRparen: t.curPos,\n\t}\n\treturn expr, nil\n}\n\nfunc parseBinaryExpr(t *tokenizer, left ast.Expr) (ast.Expr, *scanner.Error) {\n\texpression := &ast.BinaryExpr{\n\t\tX:     left,\n\t\tOp:    t.curToken,\n\t\tOpPos: t.curPos,\n\t}\n\tprecedence := precedences[t.curToken]\n\tt.Next()\n\tright, err := parseConstExpr(t, precedence)\n\texpression.Y = right\n\treturn expression, err\n}\n\nfunc parseUnaryExpr(t *tokenizer) (ast.Expr, *scanner.Error) {\n\texpression := &ast.UnaryExpr{\n\t\tOpPos: t.curPos,\n\t\tOp:    t.curToken,\n\t}\n\tt.Next()\n\tx, err := parseConstExpr(t, precedencePrefix)\n\texpression.X = x\n\treturn expression, err\n}\n\n// unexpectedToken returns an error of the form \"unexpected token FOO, expected\n// BAR\".\nfunc unexpectedToken(t *tokenizer, expected token.Token) *scanner.Error {\n\treturn &scanner.Error{\n\t\tPos: t.fset.Position(t.curPos),\n\t\tMsg: fmt.Sprintf(\"unexpected token %s, expected %s\", t.curToken, expected),\n\t}\n}\n\n// tokenizer reads C source code and converts it to Go tokens.\ntype tokenizer struct {\n\tf                   *cgoFile\n\tcurPos, peekPos     token.Pos\n\tfset                *token.FileSet\n\tcurToken, peekToken token.Token\n\tcurValue, peekValue string\n\tbuf                 string\n\tparams              map[string]ast.Expr\n}\n\n// newTokenizer initializes a new tokenizer, positioned at the first token in\n// the string.\nfunc newTokenizer(start token.Pos, fset *token.FileSet, buf string, f *cgoFile) *tokenizer {\n\tt := &tokenizer{\n\t\tf:         f,\n\t\tpeekPos:   start,\n\t\tfset:      fset,\n\t\tbuf:       buf,\n\t\tpeekToken: token.ILLEGAL,\n\t\tparams:    make(map[string]ast.Expr),\n\t}\n\t// Parse the first two tokens (cur and peek).\n\tt.Next()\n\tt.Next()\n\treturn t\n}\n\n// Next consumes the next token in the stream. There is no return value, read\n// the next token from the pos, token and value properties.\nfunc (t *tokenizer) Next() {\n\t// The previous peek is now the current token.\n\tt.curPos = t.peekPos\n\tt.curToken = t.peekToken\n\tt.curValue = t.peekValue\n\n\t// Parse the next peek token.\n\tif t.peekPos != token.NoPos {\n\t\tt.peekPos += token.Pos(len(t.curValue))\n\t}\n\tfor {\n\t\tif len(t.buf) == 0 {\n\t\t\tt.peekToken = token.EOF\n\t\t\treturn\n\t\t}\n\t\tc := t.buf[0]\n\t\tswitch {\n\t\tcase c == ' ' || c == '\\f' || c == '\\n' || c == '\\r' || c == '\\t' || c == '\\v':\n\t\t\t// Skip whitespace.\n\t\t\t// Based on this source, not sure whether it represents C whitespace:\n\t\t\t// https://en.cppreference.com/w/cpp/string/byte/isspace\n\t\t\tif t.peekPos != token.NoPos {\n\t\t\t\tt.peekPos++\n\t\t\t}\n\t\t\tt.buf = t.buf[1:]\n\t\tcase len(t.buf) >= 2 && (string(t.buf[:2]) == \"||\" || string(t.buf[:2]) == \"&&\" || string(t.buf[:2]) == \"<<\" || string(t.buf[:2]) == \">>\"):\n\t\t\t// Two-character tokens.\n\t\t\tswitch c {\n\t\t\tcase '&':\n\t\t\t\tt.peekToken = token.LAND\n\t\t\tcase '|':\n\t\t\t\tt.peekToken = token.LOR\n\t\t\tcase '<':\n\t\t\t\tt.peekToken = token.SHL\n\t\t\tcase '>':\n\t\t\t\tt.peekToken = token.SHR\n\t\t\tdefault:\n\t\t\t\tpanic(\"unreachable\")\n\t\t\t}\n\t\t\tt.peekValue = t.buf[:2]\n\t\t\tt.buf = t.buf[2:]\n\t\t\treturn\n\t\tcase c == '(' || c == ')' || c == ',' || c == '+' || c == '-' || c == '*' || c == '/' || c == '%' || c == '&' || c == '|' || c == '^':\n\t\t\t// Single-character tokens.\n\t\t\t// TODO: ++ (increment) and -- (decrement) operators.\n\t\t\tswitch c {\n\t\t\tcase '(':\n\t\t\t\tt.peekToken = token.LPAREN\n\t\t\tcase ')':\n\t\t\t\tt.peekToken = token.RPAREN\n\t\t\tcase ',':\n\t\t\t\tt.peekToken = token.COMMA\n\t\t\tcase '+':\n\t\t\t\tt.peekToken = token.ADD\n\t\t\tcase '-':\n\t\t\t\tt.peekToken = token.SUB\n\t\t\tcase '*':\n\t\t\t\tt.peekToken = token.MUL\n\t\t\tcase '/':\n\t\t\t\tt.peekToken = token.QUO\n\t\t\tcase '%':\n\t\t\t\tt.peekToken = token.REM\n\t\t\tcase '&':\n\t\t\t\tt.peekToken = token.AND\n\t\t\tcase '|':\n\t\t\t\tt.peekToken = token.OR\n\t\t\tcase '^':\n\t\t\t\tt.peekToken = token.XOR\n\t\t\t}\n\t\t\tt.peekValue = t.buf[:1]\n\t\t\tt.buf = t.buf[1:]\n\t\t\treturn\n\t\tcase c >= '0' && c <= '9':\n\t\t\t// Numeric constant (int, float, etc.).\n\t\t\t// Find the last non-numeric character.\n\t\t\ttokenLen := len(t.buf)\n\t\t\thasDot := false\n\t\t\tfor i, c := range t.buf {\n\t\t\t\tif c == '.' {\n\t\t\t\t\thasDot = true\n\t\t\t\t}\n\t\t\t\tif c >= '0' && c <= '9' || c == '.' || c == '_' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' {\n\t\t\t\t\ttokenLen = i + 1\n\t\t\t\t} else {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tt.peekValue = t.buf[:tokenLen]\n\t\t\tt.buf = t.buf[tokenLen:]\n\t\t\tif hasDot {\n\t\t\t\t// Integer constants are more complicated than this but this is\n\t\t\t\t// a close approximation.\n\t\t\t\t// https://en.cppreference.com/w/cpp/language/integer_literal\n\t\t\t\tt.peekToken = token.FLOAT\n\t\t\t\tt.peekValue = strings.TrimRight(t.peekValue, \"f\")\n\t\t\t} else {\n\t\t\t\tt.peekToken = token.INT\n\t\t\t\tt.peekValue = strings.TrimRight(t.peekValue, \"uUlL\")\n\t\t\t}\n\t\t\treturn\n\t\tcase c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || c == '_':\n\t\t\t// Identifier. Find all remaining tokens that are part of this\n\t\t\t// identifier.\n\t\t\ttokenLen := len(t.buf)\n\t\t\tfor i, c := range t.buf {\n\t\t\t\tif c >= '0' && c <= '9' || c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || c == '_' {\n\t\t\t\t\ttokenLen = i + 1\n\t\t\t\t} else {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tt.peekValue = t.buf[:tokenLen]\n\t\t\tt.buf = t.buf[tokenLen:]\n\t\t\tt.peekToken = token.IDENT\n\t\t\treturn\n\t\tcase c == '\"':\n\t\t\t// String constant. Find the first '\"' character that is not\n\t\t\t// preceded by a backslash.\n\t\t\tescape := false\n\t\t\ttokenLen := len(t.buf)\n\t\t\tfor i, c := range t.buf {\n\t\t\t\tif i != 0 && c == '\"' && !escape {\n\t\t\t\t\ttokenLen = i + 1\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tif !escape {\n\t\t\t\t\tescape = c == '\\\\'\n\t\t\t\t}\n\t\t\t}\n\t\t\tt.peekToken = token.STRING\n\t\t\tt.peekValue = t.buf[:tokenLen]\n\t\t\tt.buf = t.buf[tokenLen:]\n\t\t\treturn\n\t\tcase c == '\\'':\n\t\t\t// Char (rune) constant. Find the first '\\'' character that is not\n\t\t\t// preceded by a backslash.\n\t\t\tescape := false\n\t\t\ttokenLen := len(t.buf)\n\t\t\tfor i, c := range t.buf {\n\t\t\t\tif i != 0 && c == '\\'' && !escape {\n\t\t\t\t\ttokenLen = i + 1\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tif !escape {\n\t\t\t\t\tescape = c == '\\\\'\n\t\t\t\t}\n\t\t\t}\n\t\t\tt.peekToken = token.CHAR\n\t\t\tt.peekValue = t.buf[:tokenLen]\n\t\t\tt.buf = t.buf[tokenLen:]\n\t\t\treturn\n\t\tdefault:\n\t\t\tt.peekToken = token.ILLEGAL\n\t\t\treturn\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cgo/const_test.go",
    "content": "package cgo\n\nimport (\n\t\"bytes\"\n\t\"go/format\"\n\t\"go/token\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestParseConst(t *testing.T) {\n\t// Test converting a C constant to a Go constant.\n\tfor _, tc := range []struct {\n\t\tC  string\n\t\tGo string\n\t}{\n\t\t{`5`, `5`},\n\t\t{`(5)`, `(5)`},\n\t\t{`(((5)))`, `(5)`},\n\t\t{`)`, `error: 1:1: unexpected token )`},\n\t\t{`5)`, `error: 1:2: unexpected token ), expected end of expression`},\n\t\t{\"  \\t)\", `error: 1:4: unexpected token )`},\n\t\t{`5.8f`, `5.8`},\n\t\t{`foo`, `C.foo`},\n\t\t{``, `error: 1:1: empty constant`}, // empty constants not allowed in Go\n\t\t{`\"foo\"`, `\"foo\"`},\n\t\t{`\"a\\\\n\"`, `\"a\\\\n\"`},\n\t\t{`\"a\\n\"`, `\"a\\n\"`},\n\t\t{`\"a\\\"\"`, `\"a\\\"\"`},\n\t\t{`'a'`, `'a'`},\n\t\t{`0b10`, `0b10`},\n\t\t{`0x1234_5678`, `0x1234_5678`},\n\t\t{`5 5`, `error: 1:3: unexpected token INT, expected end of expression`}, // test for a bugfix\n\t\t// Binary operators.\n\t\t{`5+5`, `5 + 5`},\n\t\t{`5-5`, `5 - 5`},\n\t\t{`5*5`, `5 * 5`},\n\t\t{`5/5`, `5 / 5`},\n\t\t{`5%5`, `5 % 5`},\n\t\t{`5&5`, `5 & 5`},\n\t\t{`5|5`, `5 | 5`},\n\t\t{`5^5`, `5 ^ 5`},\n\t\t{`5<<5`, `5 << 5`},\n\t\t{`5>>5`, `5 >> 5`},\n\t\t{`5>>5 + 3`, `5 >> (5 + 3)`},\n\t\t{`5>>5 ^ 3`, `5>>5 ^ 3`},\n\t\t{`5||5`, `error: 1:2: unexpected token ||, expected end of expression`}, // logical binops aren't supported yet\n\t\t{`(5/5)`, `(5 / 5)`},\n\t\t{`1 - 2`, `1 - 2`},\n\t\t{`1 - 2 + 3`, `1 - 2 + 3`},\n\t\t{`1 - 2 * 3`, `1 - 2*3`},\n\t\t{`(1 - 2) * 3`, `(1 - 2) * 3`},\n\t\t{`1 * 2 - 3`, `1*2 - 3`},\n\t\t{`1 * (2 - 3)`, `1 * (2 - 3)`},\n\t\t// Unary operators.\n\t\t{`-5`, `-5`},\n\t\t{`-5-2`, `-5 - 2`},\n\t\t{`5 - - 2`, `5 - -2`},\n\t} {\n\t\tfset := token.NewFileSet()\n\t\tstartPos := fset.AddFile(\"\", -1, 1000).Pos(0)\n\t\texpr, err := parseConst(startPos, fset, tc.C, nil, token.NoPos, nil)\n\t\ts := \"<invalid>\"\n\t\tif err != nil {\n\t\t\tif !strings.HasPrefix(tc.Go, \"error: \") {\n\t\t\t\tt.Errorf(\"expected value %#v for C constant %#v but got error %#v\", tc.Go, tc.C, err.Error())\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\ts = \"error: \" + err.Error()\n\t\t} else if expr != nil {\n\t\t\t// Serialize the Go constant to a string, for more readable test\n\t\t\t// cases.\n\t\t\tbuf := &bytes.Buffer{}\n\t\t\terr := format.Node(buf, fset, expr)\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"could not format expr from C constant %#v: %v\", tc.C, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\ts = buf.String()\n\t\t}\n\t\tif s != tc.Go {\n\t\t\tt.Errorf(\"C constant %#v was parsed to %#v while expecting %#v\", tc.C, s, tc.Go)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cgo/libclang.go",
    "content": "package cgo\n\n// This file parses a fragment of C with libclang and stores the result for AST\n// modification. It does not touch the AST itself.\n\nimport (\n\t\"bytes\"\n\t\"crypto/sha256\"\n\t\"crypto/sha512\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/scanner\"\n\t\"go/token\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"strings\"\n\t\"unsafe\"\n\n\t\"tinygo.org/x/go-llvm\"\n)\n\n/*\n#include <clang-c/Index.h> // If this fails, libclang headers aren't available. Please take a look here: https://tinygo.org/docs/guides/build/\n#include <llvm/Config/llvm-config.h>\n#include <stdlib.h>\n#include <stdint.h>\n\n// This struct should be ABI-compatible on all platforms (uintptr_t has the same\n// alignment etc. as void*) but does not include void* pointers that are not\n// always real pointers.\n// The Go garbage collector assumes that all non-nil pointer-typed integers are\n// actually pointers. This is not always true, as data[1] often contains 0x1,\n// which is clearly not a valid pointer. Usually the GC won't catch this issue,\n// but occasionally it will leading to a crash with a vague error message.\ntypedef struct {\n\tenum CXCursorKind kind;\n\tint xdata;\n\tuintptr_t data[3];\n} GoCXCursor;\n\n// Forwarding functions. They are implemented in libclang_stubs.c and forward to\n// the real functions without doing anything else, thus they are entirely\n// compatible with the versions without tinygo_ prefix. The only difference is\n// the CXCursor type, which has been replaced with GoCXCursor.\nGoCXCursor tinygo_clang_getTranslationUnitCursor(CXTranslationUnit tu);\nunsigned tinygo_clang_visitChildren(GoCXCursor parent, CXCursorVisitor visitor, CXClientData client_data);\nCXString tinygo_clang_getCursorSpelling(GoCXCursor c);\nCXString tinygo_clang_getCursorPrettyPrinted(GoCXCursor c, CXPrintingPolicy Policy);\nCXPrintingPolicy tinygo_clang_getCursorPrintingPolicy(GoCXCursor c);\nenum CXCursorKind tinygo_clang_getCursorKind(GoCXCursor c);\nCXType tinygo_clang_getCursorType(GoCXCursor c);\nGoCXCursor tinygo_clang_getTypeDeclaration(CXType t);\nCXType tinygo_clang_getTypedefDeclUnderlyingType(GoCXCursor c);\nCXType tinygo_clang_getCursorResultType(GoCXCursor c);\nint tinygo_clang_Cursor_getNumArguments(GoCXCursor c);\nGoCXCursor tinygo_clang_Cursor_getArgument(GoCXCursor c, unsigned i);\nenum CX_StorageClass tinygo_clang_Cursor_getStorageClass(GoCXCursor c);\nCXSourceLocation tinygo_clang_getCursorLocation(GoCXCursor c);\nCXSourceRange tinygo_clang_getCursorExtent(GoCXCursor c);\nCXTranslationUnit tinygo_clang_Cursor_getTranslationUnit(GoCXCursor c);\nlong long tinygo_clang_getEnumConstantDeclValue(GoCXCursor c);\nCXType tinygo_clang_getEnumDeclIntegerType(GoCXCursor c);\nunsigned tinygo_clang_Cursor_isAnonymous(GoCXCursor c);\nunsigned tinygo_clang_Cursor_isBitField(GoCXCursor c);\nunsigned tinygo_clang_Cursor_isMacroFunctionLike(GoCXCursor c);\n\n// Fix some warnings on Windows ARM. Without the __declspec(dllexport), it gives warnings like this:\n//     In file included from _cgo_export.c:4:\n//     cgo-gcc-export-header-prolog:49:34: warning: redeclaration of 'tinygo_clang_globals_visitor' should not add 'dllexport' attribute [-Wdll-attribute-on-redeclaration]\n//     libclang.go:68:5: note: previous declaration is here\n// See: https://github.com/golang/go/issues/49721\n#if defined(_WIN32)\n#define CGO_DECL __declspec(dllexport)\n#else\n#define CGO_DECL\n#endif\n\nCGO_DECL\nint tinygo_clang_globals_visitor(GoCXCursor c, GoCXCursor parent, CXClientData client_data);\nCGO_DECL\nint tinygo_clang_struct_visitor(GoCXCursor c, GoCXCursor parent, CXClientData client_data);\nCGO_DECL\nvoid tinygo_clang_inclusion_visitor(CXFile included_file, CXSourceLocation *inclusion_stack, unsigned include_len, CXClientData client_data);\n*/\nimport \"C\"\n\n// storedRefs stores references to types, used for clang_visitChildren.\nvar storedRefs refMap\n\nvar diagnosticSeverity = [...]string{\n\tC.CXDiagnostic_Ignored: \"ignored\",\n\tC.CXDiagnostic_Note:    \"note\",\n\tC.CXDiagnostic_Warning: \"warning\",\n\tC.CXDiagnostic_Error:   \"error\",\n\tC.CXDiagnostic_Fatal:   \"fatal\",\n}\n\n// Alias so that cgo.go (which doesn't import Clang related stuff and is in\n// theory decoupled from Clang) can also use this type.\ntype clangCursor = C.GoCXCursor\n\nfunc init() {\n\t// Check that we haven't messed up LLVM versioning.\n\t// This can happen when llvm_config_*.go files in either this or the\n\t// tinygo.org/x/go-llvm packages is incorrect. It should not ever happen\n\t// with byollvm.\n\tif C.LLVM_VERSION_STRING != llvm.Version {\n\t\tpanic(\"incorrect build: using LLVM version \" + llvm.Version + \" in the tinygo.org/x/llvm package, and version \" + C.LLVM_VERSION_STRING + \" in the ./cgo package\")\n\t}\n}\n\nfunc (f *cgoFile) readNames(fragment string, cflags []string, filename string, callback func(map[string]clangCursor)) {\n\tindex := C.clang_createIndex(0, 0)\n\tdefer C.clang_disposeIndex(index)\n\n\t// pretend to be a .c file\n\tfilenameC := C.CString(filename + \"!cgo.c\")\n\tdefer C.free(unsafe.Pointer(filenameC))\n\n\tfragmentC := C.CString(fragment)\n\tdefer C.free(unsafe.Pointer(fragmentC))\n\n\tunsavedFile := C.struct_CXUnsavedFile{\n\t\tFilename: filenameC,\n\t\tLength:   C.ulong(len(fragment)),\n\t\tContents: fragmentC,\n\t}\n\n\t// convert Go slice of strings to C array of strings.\n\tcmdargsC := C.malloc(C.size_t(len(cflags)) * C.size_t(unsafe.Sizeof(uintptr(0))))\n\tdefer C.free(cmdargsC)\n\tcmdargs := (*[1 << 16]*C.char)(cmdargsC)\n\tfor i, cflag := range cflags {\n\t\ts := C.CString(cflag)\n\t\tcmdargs[i] = s\n\t\tdefer C.free(unsafe.Pointer(s))\n\t}\n\n\tvar unit C.CXTranslationUnit\n\terrCode := C.clang_parseTranslationUnit2(\n\t\tindex,\n\t\tfilenameC,\n\t\t(**C.char)(cmdargsC), C.int(len(cflags)), // command line args\n\t\t&unsavedFile, 1, // unsaved files\n\t\tC.CXTranslationUnit_DetailedPreprocessingRecord,\n\t\t&unit)\n\tif errCode != 0 {\n\t\t// This is probably a bug in the usage of libclang.\n\t\tpanic(\"cgo: failed to parse source with libclang\")\n\t}\n\tdefer C.clang_disposeTranslationUnit(unit)\n\n\t// Report parser and type errors.\n\tif numDiagnostics := int(C.clang_getNumDiagnostics(unit)); numDiagnostics != 0 {\n\t\taddDiagnostic := func(diagnostic C.CXDiagnostic) {\n\t\t\tspelling := getString(C.clang_getDiagnosticSpelling(diagnostic))\n\t\t\tseverity := diagnosticSeverity[C.clang_getDiagnosticSeverity(diagnostic)]\n\t\t\tlocation := C.clang_getDiagnosticLocation(diagnostic)\n\t\t\tpos := f.getClangLocationPosition(location, unit)\n\t\t\tf.addError(pos, severity+\": \"+spelling)\n\t\t}\n\t\tfor i := 0; i < numDiagnostics; i++ {\n\t\t\tdiagnostic := C.clang_getDiagnostic(unit, C.uint(i))\n\t\t\taddDiagnostic(diagnostic)\n\n\t\t\t// Child diagnostics (like notes on redefinitions).\n\t\t\tdiagnostics := C.clang_getChildDiagnostics(diagnostic)\n\t\t\tfor j := 0; j < int(C.clang_getNumDiagnosticsInSet(diagnostics)); j++ {\n\t\t\t\taddDiagnostic(C.clang_getDiagnosticInSet(diagnostics, C.uint(j)))\n\t\t\t}\n\t\t}\n\t}\n\n\t// Extract information required by CGo.\n\tref := storedRefs.Put(f)\n\tdefer storedRefs.Remove(ref)\n\tcursor := C.tinygo_clang_getTranslationUnitCursor(unit)\n\tC.tinygo_clang_visitChildren(cursor, C.CXCursorVisitor(C.tinygo_clang_globals_visitor), C.CXClientData(ref))\n\n\t// Determine files read during CGo processing, for caching.\n\tinclusionCallback := func(includedFile C.CXFile) {\n\t\t// Get full file path.\n\t\tpath := getString(C.clang_getFileName(includedFile))\n\n\t\t// Get contents of file (that should be in-memory).\n\t\tsize := C.size_t(0)\n\t\trawData := C.clang_getFileContents(unit, includedFile, &size)\n\t\tif rawData == nil {\n\t\t\t// Sanity check. This should (hopefully) never trigger.\n\t\t\tpanic(\"libclang: file contents was not loaded\")\n\t\t}\n\t\tdata := (*[1 << 24]byte)(unsafe.Pointer(rawData))[:size]\n\n\t\t// Hash the contents if it isn't hashed yet.\n\t\tif _, ok := f.visitedFiles[path]; !ok {\n\t\t\t// already stored\n\t\t\tsum := sha512.Sum512_224(data)\n\t\t\tf.visitedFiles[path] = sum[:]\n\t\t}\n\t}\n\tinclusionCallbackRef := storedRefs.Put(inclusionCallback)\n\tdefer storedRefs.Remove(inclusionCallbackRef)\n\tC.clang_getInclusions(unit, C.CXInclusionVisitor(C.tinygo_clang_inclusion_visitor), C.CXClientData(inclusionCallbackRef))\n\n\t// Do all the C AST operations inside a callback. This makes sure that\n\t// libclang related memory is only freed after it is not necessary anymore.\n\tcallback(f.names)\n}\n\n// Convert the AST node under the given Clang cursor to a Go AST node and return\n// it.\nfunc (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {\n\tkind := C.tinygo_clang_getCursorKind(c)\n\tpos := f.getCursorPosition(c)\n\tswitch kind {\n\tcase C.CXCursor_FunctionDecl:\n\t\tcursorType := C.tinygo_clang_getCursorType(c)\n\t\tnumArgs := int(C.tinygo_clang_Cursor_getNumArguments(c))\n\t\tobj := &ast.Object{\n\t\t\tKind: ast.Fun,\n\t\t\tName: \"_Cgo_\" + name,\n\t\t}\n\t\texportName := name\n\t\tlocalName := name\n\t\tvar stringSignature string\n\t\tif C.tinygo_clang_Cursor_getStorageClass(c) == C.CX_SC_Static {\n\t\t\t// A static function is assigned a globally unique symbol name based\n\t\t\t// on the file path (like _Cgo_static_2d09198adbf58f4f4655_foo) and\n\t\t\t// has a different Go name in the form of C.foo!symbols.go instead\n\t\t\t// of just C.foo.\n\t\t\tpath := f.importPath + \"/\" + filepath.Base(f.fset.File(f.file.Pos()).Name())\n\t\t\tstaticIDBuf := sha256.Sum256([]byte(path))\n\t\t\tstaticID := hex.EncodeToString(staticIDBuf[:10])\n\t\t\texportName = \"_Cgo_static_\" + staticID + \"_\" + name\n\t\t\tlocalName = name + \"!\" + filepath.Base(path)\n\n\t\t\t// Create a signature. This is necessary for MacOS to forward the\n\t\t\t// call, because MacOS doesn't support aliases like ELF and PE do.\n\t\t\t// (There is N_INDR but __attribute__((alias(\"...\"))) doesn't work).\n\t\t\tpolicy := C.tinygo_clang_getCursorPrintingPolicy(c)\n\t\t\tdefer C.clang_PrintingPolicy_dispose(policy)\n\t\t\tC.clang_PrintingPolicy_setProperty(policy, C.CXPrintingPolicy_TerseOutput, 1)\n\t\t\tstringSignature = getString(C.tinygo_clang_getCursorPrettyPrinted(c, policy))\n\t\t\tstringSignature = strings.Replace(stringSignature, \" \"+name+\"(\", \" \"+exportName+\"(\", 1)\n\t\t\tstringSignature = strings.TrimPrefix(stringSignature, \"static \")\n\t\t}\n\t\targs := make([]*ast.Field, numArgs)\n\t\tdecl := &ast.FuncDecl{\n\t\t\tDoc: &ast.CommentGroup{\n\t\t\t\tList: []*ast.Comment{\n\t\t\t\t\t{\n\t\t\t\t\t\tSlash: pos - 1,\n\t\t\t\t\t\tText:  \"//export \" + exportName,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tName: &ast.Ident{\n\t\t\t\tNamePos: pos,\n\t\t\t\tName:    \"_Cgo_\" + localName,\n\t\t\t\tObj:     obj,\n\t\t\t},\n\t\t\tType: &ast.FuncType{\n\t\t\t\tFunc: pos,\n\t\t\t\tParams: &ast.FieldList{\n\t\t\t\t\tOpening: pos,\n\t\t\t\t\tList:    args,\n\t\t\t\t\tClosing: pos,\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\t\tvar doc []string\n\t\tif C.clang_isFunctionTypeVariadic(cursorType) != 0 {\n\t\t\tdoc = append(doc, \"//go:variadic\")\n\t\t}\n\t\tif _, ok := f.noescapingFuncs[name]; ok {\n\t\t\tdoc = append(doc, \"//go:noescape\")\n\t\t\tf.noescapingFuncs[name].used = true\n\t\t}\n\t\tif len(doc) != 0 {\n\t\t\tdecl.Doc.List = append(decl.Doc.List, &ast.Comment{\n\t\t\t\tSlash: pos - 1,\n\t\t\t\tText:  strings.Join(doc, \"\\n\"),\n\t\t\t})\n\t\t}\n\t\tfor i := 0; i < numArgs; i++ {\n\t\t\targ := C.tinygo_clang_Cursor_getArgument(c, C.uint(i))\n\t\t\targName := getString(C.tinygo_clang_getCursorSpelling(arg))\n\t\t\targType := C.clang_getArgType(cursorType, C.uint(i))\n\t\t\tif argName == \"\" {\n\t\t\t\targName = \"$\" + strconv.Itoa(i)\n\t\t\t}\n\t\t\targs[i] = &ast.Field{\n\t\t\t\tNames: []*ast.Ident{\n\t\t\t\t\t{\n\t\t\t\t\t\tNamePos: pos,\n\t\t\t\t\t\tName:    argName,\n\t\t\t\t\t\tObj: &ast.Object{\n\t\t\t\t\t\t\tKind: ast.Var,\n\t\t\t\t\t\t\tName: argName,\n\t\t\t\t\t\t\tDecl: decl,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tType: f.makeDecayingASTType(argType, pos),\n\t\t\t}\n\t\t}\n\t\tresultType := C.tinygo_clang_getCursorResultType(c)\n\t\tif resultType.kind != C.CXType_Void {\n\t\t\tdecl.Type.Results = &ast.FieldList{\n\t\t\t\tList: []*ast.Field{\n\t\t\t\t\t{\n\t\t\t\t\t\tType: f.makeASTType(resultType, pos),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\t\tobj.Decl = decl\n\t\treturn decl, stringSignature\n\tcase C.CXCursor_StructDecl, C.CXCursor_UnionDecl:\n\t\ttyp := f.makeASTRecordType(c, pos)\n\t\ttypeName := \"_Cgo_\" + name\n\t\ttypeExpr := typ.typeExpr\n\t\tif typ.unionSize != 0 {\n\t\t\t// Convert to a single-field struct type.\n\t\t\ttypeExpr = f.makeUnionField(typ)\n\t\t}\n\t\tobj := &ast.Object{\n\t\t\tKind: ast.Typ,\n\t\t\tName: typeName,\n\t\t}\n\t\ttypeSpec := &ast.TypeSpec{\n\t\t\tName: &ast.Ident{\n\t\t\t\tNamePos: typ.pos,\n\t\t\t\tName:    typeName,\n\t\t\t\tObj:     obj,\n\t\t\t},\n\t\t\tType: typeExpr,\n\t\t}\n\t\tobj.Decl = typeSpec\n\t\treturn typeSpec, typ\n\tcase C.CXCursor_TypedefDecl:\n\t\ttypeName := \"_Cgo_\" + name\n\t\tunderlyingType := C.tinygo_clang_getTypedefDeclUnderlyingType(c)\n\t\tobj := &ast.Object{\n\t\t\tKind: ast.Typ,\n\t\t\tName: typeName,\n\t\t}\n\t\ttypeSpec := &ast.TypeSpec{\n\t\t\tName: &ast.Ident{\n\t\t\t\tNamePos: pos,\n\t\t\t\tName:    typeName,\n\t\t\t\tObj:     obj,\n\t\t\t},\n\t\t\tType: f.makeASTType(underlyingType, pos),\n\t\t}\n\t\tif underlyingType.kind != C.CXType_Enum {\n\t\t\ttypeSpec.Assign = pos\n\t\t}\n\t\tobj.Decl = typeSpec\n\t\treturn typeSpec, nil\n\tcase C.CXCursor_VarDecl:\n\t\tcursorType := C.tinygo_clang_getCursorType(c)\n\t\ttypeExpr := f.makeASTType(cursorType, pos)\n\t\tgen := &ast.GenDecl{\n\t\t\tTokPos: pos,\n\t\t\tTok:    token.VAR,\n\t\t\tLparen: token.NoPos,\n\t\t\tRparen: token.NoPos,\n\t\t\tDoc: &ast.CommentGroup{\n\t\t\t\tList: []*ast.Comment{\n\t\t\t\t\t{\n\t\t\t\t\t\tSlash: pos - 1,\n\t\t\t\t\t\tText:  \"//go:extern \" + name,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\t\tobj := &ast.Object{\n\t\t\tKind: ast.Var,\n\t\t\tName: \"_Cgo_\" + name,\n\t\t}\n\t\tvalueSpec := &ast.ValueSpec{\n\t\t\tNames: []*ast.Ident{{\n\t\t\t\tNamePos: pos,\n\t\t\t\tName:    \"_Cgo_\" + name,\n\t\t\t\tObj:     obj,\n\t\t\t}},\n\t\t\tType: typeExpr,\n\t\t}\n\t\tobj.Decl = valueSpec\n\t\tgen.Specs = append(gen.Specs, valueSpec)\n\t\treturn gen, nil\n\tcase C.CXCursor_MacroDefinition:\n\t\ttokenPos, value := f.getMacro(c)\n\t\texpr, scannerError := parseConst(tokenPos, f.fset, value, nil, token.NoPos, f)\n\t\tif scannerError != nil {\n\t\t\tf.errors = append(f.errors, *scannerError)\n\t\t\treturn nil, nil\n\t\t}\n\n\t\tgen := &ast.GenDecl{\n\t\t\tTokPos: token.NoPos,\n\t\t\tTok:    token.CONST,\n\t\t\tLparen: token.NoPos,\n\t\t\tRparen: token.NoPos,\n\t\t}\n\t\tobj := &ast.Object{\n\t\t\tKind: ast.Con,\n\t\t\tName: \"_Cgo_\" + name,\n\t\t}\n\t\tvalueSpec := &ast.ValueSpec{\n\t\t\tNames: []*ast.Ident{{\n\t\t\t\tNamePos: pos,\n\t\t\t\tName:    \"_Cgo_\" + name,\n\t\t\t\tObj:     obj,\n\t\t\t}},\n\t\t\tValues: []ast.Expr{expr},\n\t\t}\n\t\tobj.Decl = valueSpec\n\t\tgen.Specs = append(gen.Specs, valueSpec)\n\t\treturn gen, nil\n\tcase C.CXCursor_EnumDecl:\n\t\tobj := &ast.Object{\n\t\t\tKind: ast.Typ,\n\t\t\tName: \"_Cgo_\" + name,\n\t\t}\n\t\tunderlying := C.tinygo_clang_getEnumDeclIntegerType(c)\n\t\t// TODO: gc's CGo implementation uses types such as `uint32` for enums\n\t\t// instead of types such as C.int, which are used here.\n\t\ttypeSpec := &ast.TypeSpec{\n\t\t\tName: &ast.Ident{\n\t\t\t\tNamePos: pos,\n\t\t\t\tName:    \"_Cgo_\" + name,\n\t\t\t\tObj:     obj,\n\t\t\t},\n\t\t\tAssign: pos,\n\t\t\tType:   f.makeASTType(underlying, pos),\n\t\t}\n\t\tobj.Decl = typeSpec\n\t\treturn typeSpec, nil\n\tcase C.CXCursor_EnumConstantDecl:\n\t\tvalue := C.tinygo_clang_getEnumConstantDeclValue(c)\n\t\texpr := &ast.BasicLit{\n\t\t\tValuePos: pos,\n\t\t\tKind:     token.INT,\n\t\t\tValue:    strconv.FormatInt(int64(value), 10),\n\t\t}\n\t\tgen := &ast.GenDecl{\n\t\t\tTokPos: token.NoPos,\n\t\t\tTok:    token.CONST,\n\t\t\tLparen: token.NoPos,\n\t\t\tRparen: token.NoPos,\n\t\t}\n\t\tobj := &ast.Object{\n\t\t\tKind: ast.Con,\n\t\t\tName: \"_Cgo_\" + name,\n\t\t}\n\t\tvalueSpec := &ast.ValueSpec{\n\t\t\tNames: []*ast.Ident{{\n\t\t\t\tNamePos: pos,\n\t\t\t\tName:    \"_Cgo_\" + name,\n\t\t\t\tObj:     obj,\n\t\t\t}},\n\t\t\tValues: []ast.Expr{expr},\n\t\t}\n\t\tobj.Decl = valueSpec\n\t\tgen.Specs = append(gen.Specs, valueSpec)\n\t\treturn gen, nil\n\tdefault:\n\t\tf.addError(pos, fmt.Sprintf(\"internal error: unknown cursor type: %d\", kind))\n\t\treturn nil, nil\n\t}\n}\n\n// Return whether this is a macro that's also function-like, like this:\n//\n//\t#define add(a, b) (a+b)\nfunc (f *cgoFile) isFunctionLikeMacro(c clangCursor) bool {\n\tif C.tinygo_clang_getCursorKind(c) != C.CXCursor_MacroDefinition {\n\t\treturn false\n\t}\n\treturn C.tinygo_clang_Cursor_isMacroFunctionLike(c) != 0\n}\n\n// Get the macro value: the position in the source file and the string value of\n// the macro.\nfunc (f *cgoFile) getMacro(c clangCursor) (pos token.Pos, value string) {\n\t// Extract tokens from the Clang tokenizer.\n\t// See: https://stackoverflow.com/a/19074846/559350\n\tsourceRange := C.tinygo_clang_getCursorExtent(c)\n\ttu := C.tinygo_clang_Cursor_getTranslationUnit(c)\n\tvar rawTokens *C.CXToken\n\tvar numTokens C.unsigned\n\tC.clang_tokenize(tu, sourceRange, &rawTokens, &numTokens)\n\ttokens := unsafe.Slice(rawTokens, numTokens)\n\tdefer C.clang_disposeTokens(tu, rawTokens, numTokens)\n\n\t// Convert this range of tokens back to source text.\n\t// Ugly, but it works well enough.\n\tsourceBuf := &bytes.Buffer{}\n\tvar startOffset int\n\tfor i, token := range tokens {\n\t\tspelling := getString(C.clang_getTokenSpelling(tu, token))\n\t\tlocation := C.clang_getTokenLocation(tu, token)\n\t\tvar tokenOffset C.unsigned\n\t\tC.clang_getExpansionLocation(location, nil, nil, nil, &tokenOffset)\n\t\tif i == 0 {\n\t\t\t// The first token is the macro name itself.\n\t\t\t// Skip it (after using its location).\n\t\t\tstartOffset = int(tokenOffset)\n\t\t} else {\n\t\t\t// Later tokens are the macro contents.\n\t\t\tfor int(tokenOffset) > (startOffset + sourceBuf.Len()) {\n\t\t\t\t// Pad the source text with whitespace (that must have been\n\t\t\t\t// present in the original source as well).\n\t\t\t\tsourceBuf.WriteByte(' ')\n\t\t\t}\n\t\t\tsourceBuf.WriteString(spelling)\n\t\t}\n\t}\n\tvalue = sourceBuf.String()\n\n\t// Obtain the position of this token. This is the position of the first\n\t// character in the 'value' string and is used to report errors at the\n\t// correct location in the source file.\n\tpos = f.getCursorPosition(c)\n\n\treturn\n}\n\nfunc getString(clangString C.CXString) (s string) {\n\trawString := C.clang_getCString(clangString)\n\ts = C.GoString(rawString)\n\tC.clang_disposeString(clangString)\n\treturn\n}\n\n//export tinygo_clang_globals_visitor\nfunc tinygo_clang_globals_visitor(c, parent C.GoCXCursor, client_data C.CXClientData) C.int {\n\tf := storedRefs.Get(unsafe.Pointer(client_data)).(*cgoFile)\n\tswitch C.tinygo_clang_getCursorKind(c) {\n\tcase C.CXCursor_FunctionDecl:\n\t\tname := getString(C.tinygo_clang_getCursorSpelling(c))\n\t\tf.names[name] = c\n\tcase C.CXCursor_StructDecl:\n\t\tname := getString(C.tinygo_clang_getCursorSpelling(c))\n\t\tif name != \"\" {\n\t\t\tf.names[\"struct_\"+name] = c\n\t\t}\n\tcase C.CXCursor_UnionDecl:\n\t\tname := getString(C.tinygo_clang_getCursorSpelling(c))\n\t\tif name != \"\" {\n\t\t\tf.names[\"union_\"+name] = c\n\t\t}\n\tcase C.CXCursor_TypedefDecl:\n\t\ttypedefType := C.tinygo_clang_getCursorType(c)\n\t\tname := getString(C.clang_getTypedefName(typedefType))\n\t\tf.names[name] = c\n\tcase C.CXCursor_VarDecl:\n\t\tname := getString(C.tinygo_clang_getCursorSpelling(c))\n\t\tf.names[name] = c\n\tcase C.CXCursor_MacroDefinition:\n\t\tname := getString(C.tinygo_clang_getCursorSpelling(c))\n\t\tf.names[name] = c\n\tcase C.CXCursor_EnumDecl:\n\t\tname := getString(C.tinygo_clang_getCursorSpelling(c))\n\t\tif name != \"\" {\n\t\t\t// Named enum, which can be referenced from Go using C.enum_foo.\n\t\t\tf.names[\"enum_\"+name] = c\n\t\t}\n\t\t// The enum fields are in global scope, so recurse to visit them.\n\t\treturn C.CXChildVisit_Recurse\n\tcase C.CXCursor_EnumConstantDecl:\n\t\t// We arrive here because of the \"Recurse\" above.\n\t\tname := getString(C.tinygo_clang_getCursorSpelling(c))\n\t\tf.names[name] = c\n\t}\n\treturn C.CXChildVisit_Continue\n}\n\n// Get the precise location in the source code. Used for uniquely identifying\n// source locations.\nfunc (f *cgoFile) getUniqueLocationID(pos token.Pos, cursor C.GoCXCursor) interface{} {\n\tclangLocation := C.tinygo_clang_getCursorLocation(cursor)\n\tvar file C.CXFile\n\tvar line C.unsigned\n\tvar column C.unsigned\n\tC.clang_getFileLocation(clangLocation, &file, &line, &column, nil)\n\tlocation := token.Position{\n\t\tFilename: getString(C.clang_getFileName(file)),\n\t\tLine:     int(line),\n\t\tColumn:   int(column),\n\t}\n\tif location.Filename == \"\" || location.Line == 0 {\n\t\t// Not sure when this would happen, but protect from it anyway.\n\t\tf.addError(pos, \"could not find file/line information\")\n\t}\n\treturn location\n}\n\n// getCursorPosition returns a usable token.Pos from a libclang cursor.\nfunc (p *cgoPackage) getCursorPosition(cursor C.GoCXCursor) token.Pos {\n\treturn p.getClangLocationPosition(C.tinygo_clang_getCursorLocation(cursor), C.tinygo_clang_Cursor_getTranslationUnit(cursor))\n}\n\n// getClangLocationPosition returns a usable token.Pos based on a libclang\n// location and translation unit. If the file for this cursor has not been seen\n// before, it is read from libclang (which already has the file in memory) and\n// added to the token.FileSet.\nfunc (p *cgoPackage) getClangLocationPosition(location C.CXSourceLocation, tu C.CXTranslationUnit) token.Pos {\n\tvar file C.CXFile\n\tvar line C.unsigned\n\tvar column C.unsigned\n\tvar offset C.unsigned\n\tC.clang_getExpansionLocation(location, &file, &line, &column, &offset)\n\tif line == 0 || file == nil {\n\t\t// Invalid token.\n\t\treturn token.NoPos\n\t}\n\tfilename := getString(C.clang_getFileName(file))\n\tif _, ok := p.tokenFiles[filename]; !ok {\n\t\t// File has not been seen before in this package, add line information\n\t\t// now by reading the file from libclang.\n\t\tvar size C.size_t\n\t\tsourcePtr := C.clang_getFileContents(tu, file, &size)\n\t\tsource := ((*[1 << 28]byte)(unsafe.Pointer(sourcePtr)))[:size:size]\n\t\tlines := []int{0}\n\t\tfor i := 0; i < len(source)-1; i++ {\n\t\t\tif source[i] == '\\n' {\n\t\t\t\tlines = append(lines, i+1)\n\t\t\t}\n\t\t}\n\t\tf := p.fset.AddFile(filename, -1, int(size))\n\t\tf.SetLines(lines)\n\t\tp.tokenFiles[filename] = f\n\t\t// Add dummy file AST, to satisfy the type checker.\n\t\tastFile := &ast.File{\n\t\t\tPackage: f.Pos(0),\n\t\t\tName:    ast.NewIdent(p.packageName),\n\t\t}\n\t\tsetASTFileFields(astFile, f.Pos(0), f.Pos(int(size)))\n\t\tp.cgoFiles = append(p.cgoFiles, astFile)\n\t}\n\tpositionFile := p.tokenFiles[filename]\n\n\t// Check for alternative line/column information (set with a line directive).\n\tvar filename2String C.CXString\n\tvar line2 C.unsigned\n\tvar column2 C.unsigned\n\tC.clang_getPresumedLocation(location, &filename2String, &line2, &column2)\n\tfilename2 := getString(filename2String)\n\tif filename2 != filename || line2 != line || column2 != column {\n\t\t// The location was changed with a preprocessor directive.\n\t\t// TODO: this only works for locations that are added in order. Adding\n\t\t// line/column info to a file that already has line/column info after\n\t\t// the given offset is ignored.\n\t\tpositionFile.AddLineColumnInfo(int(offset), filename2, int(line2), int(column2))\n\t}\n\n\treturn positionFile.Pos(int(offset))\n}\n\n// addError is a utility function to add an error to the list of errors. It will\n// convert the token position to a line/column position first, and call\n// addErrorAt.\nfunc (p *cgoPackage) addError(pos token.Pos, msg string) {\n\tp.addErrorAt(p.fset.PositionFor(pos, true), msg)\n}\n\n// addErrorAfter is like addError, but adds the text `after` to the source\n// location.\nfunc (p *cgoPackage) addErrorAfter(pos token.Pos, after, msg string) {\n\tposition := p.fset.PositionFor(pos, true)\n\tlines := strings.Split(after, \"\\n\")\n\tif len(lines) != 1 {\n\t\t// Adjust lines.\n\t\t// For why we can't just do pos+token.Pos(len(after)), see:\n\t\t// https://github.com/golang/go/issues/35803\n\t\tposition.Line += len(lines) - 1\n\t\tposition.Column = len(lines[len(lines)-1]) + 1\n\t} else {\n\t\tposition.Column += len(after)\n\t}\n\tp.addErrorAt(position, msg)\n}\n\n// addErrorAt is a utility function to add an error to the list of errors.\nfunc (p *cgoPackage) addErrorAt(position token.Position, msg string) {\n\tp.errors = append(p.errors, scanner.Error{\n\t\tPos: position,\n\t\tMsg: msg,\n\t})\n}\n\n// makeDecayingASTType does the same as makeASTType but takes care of decaying\n// types (arrays in function parameters, etc). It is otherwise identical to\n// makeASTType.\nfunc (f *cgoFile) makeDecayingASTType(typ C.CXType, pos token.Pos) ast.Expr {\n\t// Strip typedefs, if any.\n\tunderlyingType := typ\n\tif underlyingType.kind == C.CXType_Elaborated {\n\t\t// Starting with LLVM 16, the elaborated type is used for more types.\n\t\t// According to the Clang documentation, the elaborated type has no\n\t\t// semantic meaning so can be stripped (it is used to better convey type\n\t\t// name information).\n\t\t// Source:\n\t\t// https://clang.llvm.org/doxygen/classclang_1_1ElaboratedType.html#details\n\t\t// > The type itself is always \"sugar\", used to express what was written\n\t\t// > in the source code but containing no additional semantic information.\n\t\tunderlyingType = C.clang_Type_getNamedType(underlyingType)\n\t}\n\tif underlyingType.kind == C.CXType_Typedef {\n\t\tc := C.tinygo_clang_getTypeDeclaration(underlyingType)\n\t\tunderlyingType = C.tinygo_clang_getTypedefDeclUnderlyingType(c)\n\t\t// TODO: support a chain of typedefs. At the moment, it seems to get\n\t\t// stuck in an endless loop when trying to get to the most underlying\n\t\t// type.\n\t}\n\t// Check for decaying type. An example would be an array type in a\n\t// parameter. This declaration:\n\t//   void foo(char buf[6]);\n\t// is the same as this one:\n\t//   void foo(char *buf);\n\t// But this one:\n\t//   void bar(char buf[6][4]);\n\t// equals this:\n\t//   void bar(char *buf[4]);\n\t// so not all array dimensions should be stripped, just the first one.\n\t// TODO: there are more kinds of decaying types.\n\tif underlyingType.kind == C.CXType_ConstantArray {\n\t\t// Apply type decaying.\n\t\tpointeeType := C.clang_getElementType(underlyingType)\n\t\treturn &ast.StarExpr{\n\t\t\tStar: pos,\n\t\t\tX:    f.makeASTType(pointeeType, pos),\n\t\t}\n\t}\n\treturn f.makeASTType(typ, pos)\n}\n\n// makeASTType return the ast.Expr for the given libclang type. In other words,\n// it converts a libclang type to a type in the Go AST.\nfunc (f *cgoFile) makeASTType(typ C.CXType, pos token.Pos) ast.Expr {\n\tvar typeName string\n\tswitch typ.kind {\n\tcase C.CXType_Char_S, C.CXType_Char_U:\n\t\ttypeName = \"_Cgo_char\"\n\tcase C.CXType_SChar:\n\t\ttypeName = \"_Cgo_schar\"\n\tcase C.CXType_UChar:\n\t\ttypeName = \"_Cgo_uchar\"\n\tcase C.CXType_Short:\n\t\ttypeName = \"_Cgo_short\"\n\tcase C.CXType_UShort:\n\t\ttypeName = \"_Cgo_ushort\"\n\tcase C.CXType_Int:\n\t\ttypeName = \"_Cgo_int\"\n\tcase C.CXType_UInt:\n\t\ttypeName = \"_Cgo_uint\"\n\tcase C.CXType_Long:\n\t\ttypeName = \"_Cgo_long\"\n\tcase C.CXType_ULong:\n\t\ttypeName = \"_Cgo_ulong\"\n\tcase C.CXType_LongLong:\n\t\ttypeName = \"_Cgo_longlong\"\n\tcase C.CXType_ULongLong:\n\t\ttypeName = \"_Cgo_ulonglong\"\n\tcase C.CXType_Bool:\n\t\ttypeName = \"bool\"\n\tcase C.CXType_Float, C.CXType_Double, C.CXType_LongDouble:\n\t\tswitch C.clang_Type_getSizeOf(typ) {\n\t\tcase 4:\n\t\t\ttypeName = \"float32\"\n\t\tcase 8:\n\t\t\ttypeName = \"float64\"\n\t\tdefault:\n\t\t\t// Don't do anything, rely on the fallback code to show a somewhat\n\t\t\t// sensible error message like \"undeclared name: C.long double\".\n\t\t}\n\tcase C.CXType_Complex:\n\t\tswitch C.clang_Type_getSizeOf(typ) {\n\t\tcase 8:\n\t\t\ttypeName = \"complex64\"\n\t\tcase 16:\n\t\t\ttypeName = \"complex128\"\n\t\t}\n\tcase C.CXType_Pointer:\n\t\tpointeeType := C.clang_getPointeeType(typ)\n\t\tif pointeeType.kind == C.CXType_Void {\n\t\t\t// void* type is translated to Go as unsafe.Pointer\n\t\t\treturn &ast.SelectorExpr{\n\t\t\t\tX: &ast.Ident{\n\t\t\t\t\tNamePos: pos,\n\t\t\t\t\tName:    \"unsafe\",\n\t\t\t\t},\n\t\t\t\tSel: &ast.Ident{\n\t\t\t\t\tNamePos: pos,\n\t\t\t\t\tName:    \"Pointer\",\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\t\treturn &ast.StarExpr{\n\t\t\tStar: pos,\n\t\t\tX:    f.makeASTType(pointeeType, pos),\n\t\t}\n\tcase C.CXType_ConstantArray:\n\t\treturn &ast.ArrayType{\n\t\t\tLbrack: pos,\n\t\t\tLen: &ast.BasicLit{\n\t\t\t\tValuePos: pos,\n\t\t\t\tKind:     token.INT,\n\t\t\t\tValue:    strconv.FormatInt(int64(C.clang_getArraySize(typ)), 10),\n\t\t\t},\n\t\t\tElt: f.makeASTType(C.clang_getElementType(typ), pos),\n\t\t}\n\tcase C.CXType_FunctionProto:\n\t\t// Be compatible with gc, which uses the *[0]byte type for function\n\t\t// pointer types.\n\t\t// Return type [0]byte because this is a function type, not a pointer to\n\t\t// this function type.\n\t\treturn &ast.ArrayType{\n\t\t\tLbrack: pos,\n\t\t\tLen: &ast.BasicLit{\n\t\t\t\tValuePos: pos,\n\t\t\t\tKind:     token.INT,\n\t\t\t\tValue:    \"0\",\n\t\t\t},\n\t\t\tElt: &ast.Ident{\n\t\t\t\tNamePos: pos,\n\t\t\t\tName:    \"byte\",\n\t\t\t},\n\t\t}\n\tcase C.CXType_Typedef:\n\t\tname := getString(C.clang_getTypedefName(typ))\n\t\tc := C.tinygo_clang_getTypeDeclaration(typ)\n\t\treturn &ast.Ident{\n\t\t\tNamePos: pos,\n\t\t\tName:    f.getASTDeclName(name, c, false),\n\t\t}\n\tcase C.CXType_Elaborated:\n\t\tunderlying := C.clang_Type_getNamedType(typ)\n\t\tswitch underlying.kind {\n\t\tcase C.CXType_Record:\n\t\t\treturn f.makeASTType(underlying, pos)\n\t\tcase C.CXType_Enum:\n\t\t\treturn f.makeASTType(underlying, pos)\n\t\tcase C.CXType_Typedef:\n\t\t\treturn f.makeASTType(underlying, pos)\n\t\tdefault:\n\t\t\ttypeKindSpelling := getString(C.clang_getTypeKindSpelling(underlying.kind))\n\t\t\tf.addError(pos, fmt.Sprintf(\"unknown elaborated type (libclang type kind %s)\", typeKindSpelling))\n\t\t\ttypeName = \"<unknown>\"\n\t\t}\n\tcase C.CXType_Record:\n\t\tcursor := C.tinygo_clang_getTypeDeclaration(typ)\n\t\tname := getString(C.tinygo_clang_getCursorSpelling(cursor))\n\t\tvar cgoRecordPrefix string\n\t\tswitch C.tinygo_clang_getCursorKind(cursor) {\n\t\tcase C.CXCursor_StructDecl:\n\t\t\tcgoRecordPrefix = \"struct_\"\n\t\tcase C.CXCursor_UnionDecl:\n\t\t\tcgoRecordPrefix = \"union_\"\n\t\tdefault:\n\t\t\t// makeASTRecordType will create an appropriate error.\n\t\t\tcgoRecordPrefix = \"record_\"\n\t\t}\n\t\tif name == \"\" || C.tinygo_clang_Cursor_isAnonymous(cursor) != 0 {\n\t\t\t// Anonymous record, probably inside a typedef.\n\t\t\tlocation := f.getUniqueLocationID(pos, cursor)\n\t\t\tname = f.getUnnamedDeclName(\"_Ctype_\"+cgoRecordPrefix+\"__\", location)\n\t\t} else {\n\t\t\tname = cgoRecordPrefix + name\n\t\t}\n\t\treturn &ast.Ident{\n\t\t\tNamePos: pos,\n\t\t\tName:    f.getASTDeclName(name, cursor, false),\n\t\t}\n\tcase C.CXType_Enum:\n\t\tcursor := C.tinygo_clang_getTypeDeclaration(typ)\n\t\tname := getString(C.tinygo_clang_getCursorSpelling(cursor))\n\t\tif name == \"\" {\n\t\t\t// Anonymous enum, probably inside a typedef.\n\t\t\tlocation := f.getUniqueLocationID(pos, cursor)\n\t\t\tname = f.getUnnamedDeclName(\"_Ctype_enum___\", location)\n\t\t} else {\n\t\t\tname = \"enum_\" + name\n\t\t}\n\t\treturn &ast.Ident{\n\t\t\tNamePos: pos,\n\t\t\tName:    f.getASTDeclName(name, cursor, false),\n\t\t}\n\t}\n\tif typeName == \"\" {\n\t\t// Report this as an error.\n\t\ttypeSpelling := getString(C.clang_getTypeSpelling(typ))\n\t\ttypeKindSpelling := getString(C.clang_getTypeKindSpelling(typ.kind))\n\t\tf.addError(pos, fmt.Sprintf(\"unknown C type: %v (libclang type kind %s)\", typeSpelling, typeKindSpelling))\n\t\ttypeName = \"_Cgo_<unknown>\"\n\t}\n\treturn &ast.Ident{\n\t\tNamePos: pos,\n\t\tName:    typeName,\n\t}\n}\n\n// getIntegerType returns an AST node that defines types such as C.int.\nfunc (p *cgoPackage) getIntegerType(name string, cursor clangCursor) *ast.TypeSpec {\n\tpos := p.getCursorPosition(cursor)\n\n\t// Find a Go type that matches the size and signedness of the given C type.\n\tunderlyingType := C.tinygo_clang_getTypedefDeclUnderlyingType(cursor)\n\tvar goName string\n\ttypeSize := C.clang_Type_getSizeOf(underlyingType)\n\tswitch name {\n\tcase \"_Cgo_char\":\n\t\tif typeSize != 1 {\n\t\t\t// This happens for some very special purpose architectures\n\t\t\t// (DSPs etc.) that are not currently targeted.\n\t\t\t// https://www.embecosm.com/2017/04/18/non-8-bit-char-support-in-clang-and-llvm/\n\t\t\tp.addError(pos, fmt.Sprintf(\"unknown char width: %d\", typeSize))\n\t\t}\n\t\tswitch underlyingType.kind {\n\t\tcase C.CXType_Char_S:\n\t\t\tgoName = \"int8\"\n\t\tcase C.CXType_Char_U:\n\t\t\tgoName = \"uint8\"\n\t\t}\n\tcase \"_Cgo_schar\", \"_Cgo_short\", \"_Cgo_int\", \"_Cgo_long\", \"_Cgo_longlong\":\n\t\tswitch typeSize {\n\t\tcase 1:\n\t\t\tgoName = \"int8\"\n\t\tcase 2:\n\t\t\tgoName = \"int16\"\n\t\tcase 4:\n\t\t\tgoName = \"int32\"\n\t\tcase 8:\n\t\t\tgoName = \"int64\"\n\t\t}\n\tcase \"_Cgo_uchar\", \"_Cgo_ushort\", \"_Cgo_uint\", \"_Cgo_ulong\", \"_Cgo_ulonglong\":\n\t\tswitch typeSize {\n\t\tcase 1:\n\t\t\tgoName = \"uint8\"\n\t\tcase 2:\n\t\t\tgoName = \"uint16\"\n\t\tcase 4:\n\t\t\tgoName = \"uint32\"\n\t\tcase 8:\n\t\t\tgoName = \"uint64\"\n\t\t}\n\t}\n\n\tif goName == \"\" { // should not happen\n\t\tp.addError(pos, \"internal error: did not find Go type for C type \"+name)\n\t\tgoName = \"int\"\n\t}\n\n\t// Construct an *ast.TypeSpec for this type.\n\tobj := &ast.Object{\n\t\tKind: ast.Typ,\n\t\tName: name,\n\t}\n\tspec := &ast.TypeSpec{\n\t\tName: &ast.Ident{\n\t\t\tNamePos: pos,\n\t\t\tName:    name,\n\t\t\tObj:     obj,\n\t\t},\n\t\tType: &ast.Ident{\n\t\t\tNamePos: pos,\n\t\t\tName:    goName,\n\t\t},\n\t}\n\tobj.Decl = spec\n\treturn spec\n}\n\n// makeASTRecordType parses a C record (struct or union) and translates it into\n// a Go struct type.\nfunc (f *cgoFile) makeASTRecordType(cursor C.GoCXCursor, pos token.Pos) *elaboratedTypeInfo {\n\tfieldList := &ast.FieldList{\n\t\tOpening: pos,\n\t\tClosing: pos,\n\t}\n\tvar bitfieldList []bitfieldInfo\n\tinBitfield := false\n\tbitfieldNum := 0\n\tref := storedRefs.Put(struct {\n\t\tfieldList    *ast.FieldList\n\t\tfile         *cgoFile\n\t\tinBitfield   *bool\n\t\tbitfieldNum  *int\n\t\tbitfieldList *[]bitfieldInfo\n\t}{fieldList, f, &inBitfield, &bitfieldNum, &bitfieldList})\n\tdefer storedRefs.Remove(ref)\n\tC.tinygo_clang_visitChildren(cursor, C.CXCursorVisitor(C.tinygo_clang_struct_visitor), C.CXClientData(ref))\n\trenameFieldKeywords(fieldList)\n\tswitch C.tinygo_clang_getCursorKind(cursor) {\n\tcase C.CXCursor_StructDecl:\n\t\treturn &elaboratedTypeInfo{\n\t\t\ttypeExpr: &ast.StructType{\n\t\t\t\tStruct: pos,\n\t\t\t\tFields: fieldList,\n\t\t\t},\n\t\t\tpos:       pos,\n\t\t\tbitfields: bitfieldList,\n\t\t}\n\tcase C.CXCursor_UnionDecl:\n\t\ttypeInfo := &elaboratedTypeInfo{\n\t\t\ttypeExpr: &ast.StructType{\n\t\t\t\tStruct: pos,\n\t\t\t\tFields: fieldList,\n\t\t\t},\n\t\t\tpos:       pos,\n\t\t\tbitfields: bitfieldList,\n\t\t}\n\t\tif len(fieldList.List) <= 1 {\n\t\t\t// Useless union, treat it as a regular struct.\n\t\t\treturn typeInfo\n\t\t}\n\t\tif bitfieldList != nil {\n\t\t\t// This is valid C... but please don't do this.\n\t\t\tf.addError(pos, \"bitfield in a union is not supported\")\n\t\t}\n\t\ttyp := C.tinygo_clang_getCursorType(cursor)\n\t\talignInBytes := int64(C.clang_Type_getAlignOf(typ))\n\t\tsizeInBytes := int64(C.clang_Type_getSizeOf(typ))\n\t\tif sizeInBytes == 0 {\n\t\t\tf.addError(pos, \"zero-length union is not supported\")\n\t\t}\n\t\ttypeInfo.unionSize = sizeInBytes\n\t\ttypeInfo.unionAlign = alignInBytes\n\t\treturn typeInfo\n\tdefault:\n\t\tcursorKind := C.tinygo_clang_getCursorKind(cursor)\n\t\tcursorKindSpelling := getString(C.clang_getCursorKindSpelling(cursorKind))\n\t\tf.addError(pos, fmt.Sprintf(\"expected StructDecl or UnionDecl, not %s\", cursorKindSpelling))\n\t\treturn &elaboratedTypeInfo{\n\t\t\ttypeExpr: &ast.StructType{\n\t\t\t\tStruct: pos,\n\t\t\t},\n\t\t\tpos: pos,\n\t\t}\n\t}\n}\n\n//export tinygo_clang_struct_visitor\nfunc tinygo_clang_struct_visitor(c, parent C.GoCXCursor, client_data C.CXClientData) C.int {\n\tpassed := storedRefs.Get(unsafe.Pointer(client_data)).(struct {\n\t\tfieldList    *ast.FieldList\n\t\tfile         *cgoFile\n\t\tinBitfield   *bool\n\t\tbitfieldNum  *int\n\t\tbitfieldList *[]bitfieldInfo\n\t})\n\tfieldList := passed.fieldList\n\tf := passed.file\n\tinBitfield := passed.inBitfield\n\tbitfieldNum := passed.bitfieldNum\n\tbitfieldList := passed.bitfieldList\n\tpos := f.getCursorPosition(c)\n\tswitch cursorKind := C.tinygo_clang_getCursorKind(c); cursorKind {\n\tcase C.CXCursor_FieldDecl:\n\t\t// Expected. This is a regular field.\n\tcase C.CXCursor_StructDecl, C.CXCursor_UnionDecl:\n\t\t// Ignore. The next field will be the struct/union itself.\n\t\treturn C.CXChildVisit_Continue\n\tdefault:\n\t\tcursorKindSpelling := getString(C.clang_getCursorKindSpelling(cursorKind))\n\t\tf.addError(pos, fmt.Sprintf(\"expected FieldDecl in struct or union, not %s\", cursorKindSpelling))\n\t\treturn C.CXChildVisit_Continue\n\t}\n\tname := getString(C.tinygo_clang_getCursorSpelling(c))\n\tif name == \"\" {\n\t\t// Assume this is a bitfield of 0 bits.\n\t\t// Warning: this is not necessarily true!\n\t\treturn C.CXChildVisit_Continue\n\t}\n\ttyp := C.tinygo_clang_getCursorType(c)\n\tfield := &ast.Field{\n\t\tType: f.makeASTType(typ, f.getCursorPosition(c)),\n\t}\n\toffsetof := int64(C.clang_Type_getOffsetOf(C.tinygo_clang_getCursorType(parent), C.CString(name)))\n\talignOf := int64(C.clang_Type_getAlignOf(typ) * 8)\n\tbitfieldOffset := offsetof % alignOf\n\tif bitfieldOffset != 0 {\n\t\tif C.tinygo_clang_Cursor_isBitField(c) != 1 {\n\t\t\tf.addError(pos, \"expected a bitfield\")\n\t\t\treturn C.CXChildVisit_Continue\n\t\t}\n\t\tif !*inBitfield {\n\t\t\t*bitfieldNum++\n\t\t}\n\t\tbitfieldName := \"__bitfield_\" + strconv.Itoa(*bitfieldNum)\n\t\tprevField := fieldList.List[len(fieldList.List)-1]\n\t\tif !*inBitfield {\n\t\t\t// The previous element also was a bitfield, but wasn't noticed\n\t\t\t// then. Add it now.\n\t\t\t*inBitfield = true\n\t\t\t*bitfieldList = append(*bitfieldList, bitfieldInfo{\n\t\t\t\tfield:    prevField,\n\t\t\t\tname:     prevField.Names[0].Name,\n\t\t\t\tstartBit: 0,\n\t\t\t\tpos:      prevField.Names[0].NamePos,\n\t\t\t})\n\t\t\tprevField.Names[0].Name = bitfieldName\n\t\t\tprevField.Names[0].Obj.Name = bitfieldName\n\t\t}\n\t\tprevBitfield := &(*bitfieldList)[len(*bitfieldList)-1]\n\t\tprevBitfield.endBit = bitfieldOffset\n\t\t*bitfieldList = append(*bitfieldList, bitfieldInfo{\n\t\t\tfield:    prevField,\n\t\t\tname:     name,\n\t\t\tstartBit: bitfieldOffset,\n\t\t\tpos:      pos,\n\t\t})\n\t\treturn C.CXChildVisit_Continue\n\t}\n\t*inBitfield = false\n\tfield.Names = []*ast.Ident{\n\t\t{\n\t\t\tNamePos: pos,\n\t\t\tName:    name,\n\t\t\tObj: &ast.Object{\n\t\t\t\tKind: ast.Var,\n\t\t\t\tName: name,\n\t\t\t\tDecl: field,\n\t\t\t},\n\t\t},\n\t}\n\tfieldList.List = append(fieldList.List, field)\n\treturn C.CXChildVisit_Continue\n}\n\n//export tinygo_clang_inclusion_visitor\nfunc tinygo_clang_inclusion_visitor(includedFile C.CXFile, inclusionStack *C.CXSourceLocation, includeLen C.unsigned, clientData C.CXClientData) {\n\tcallback := storedRefs.Get(unsafe.Pointer(clientData)).(func(C.CXFile))\n\tcallback(includedFile)\n}\n"
  },
  {
    "path": "cgo/libclang_config_llvm15.go",
    "content": "//go:build !byollvm && llvm15\n\npackage cgo\n\n/*\n#cgo linux        CFLAGS:  -I/usr/lib/llvm-15/include\n#cgo darwin,amd64 CFLAGS:  -I/usr/local/opt/llvm@15/include\n#cgo darwin,arm64 CFLAGS:  -I/opt/homebrew/opt/llvm@15/include\n#cgo freebsd      CFLAGS:  -I/usr/local/llvm15/include\n#cgo linux        LDFLAGS: -L/usr/lib/llvm-15/lib -lclang\n#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@15/lib -lclang\n#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@15/lib -lclang\n#cgo freebsd      LDFLAGS: -L/usr/local/llvm15/lib -lclang\n*/\nimport \"C\"\n"
  },
  {
    "path": "cgo/libclang_config_llvm16.go",
    "content": "//go:build !byollvm && llvm16\n\npackage cgo\n\n// As of 2023-05-05, there is a packaging issue with LLVM 16 on Debian:\n// https://github.com/llvm/llvm-project/issues/62199\n// A workaround is to fix this locally, using something like this:\n//\n//   ln -sf ../../x86_64-linux-gnu/libclang-16.so.1 /usr/lib/llvm-16/lib/libclang.so\n\n/*\n#cgo linux        CFLAGS:  -I/usr/lib/llvm-16/include\n#cgo darwin,amd64 CFLAGS:  -I/usr/local/opt/llvm@16/include\n#cgo darwin,arm64 CFLAGS:  -I/opt/homebrew/opt/llvm@16/include\n#cgo freebsd      CFLAGS:  -I/usr/local/llvm16/include\n#cgo linux        LDFLAGS: -L/usr/lib/llvm-16/lib -lclang\n#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@16/lib -lclang\n#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@16/lib -lclang\n#cgo freebsd      LDFLAGS: -L/usr/local/llvm16/lib -lclang\n*/\nimport \"C\"\n"
  },
  {
    "path": "cgo/libclang_config_llvm17.go",
    "content": "//go:build !byollvm && llvm17\n\npackage cgo\n\n/*\n#cgo linux        CFLAGS:  -I/usr/include/llvm-17 -I/usr/include/llvm-c-17 -I/usr/lib/llvm-17/include\n#cgo darwin,amd64 CFLAGS:  -I/usr/local/opt/llvm@17/include\n#cgo darwin,arm64 CFLAGS:  -I/opt/homebrew/opt/llvm@17/include\n#cgo freebsd      CFLAGS:  -I/usr/local/llvm17/include\n#cgo linux        LDFLAGS: -L/usr/lib/llvm-17/lib -lclang\n#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@17/lib -lclang\n#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@17/lib -lclang\n#cgo freebsd      LDFLAGS: -L/usr/local/llvm17/lib -lclang\n*/\nimport \"C\"\n"
  },
  {
    "path": "cgo/libclang_config_llvm18.go",
    "content": "//go:build !byollvm && llvm18\n\npackage cgo\n\n/*\n#cgo linux        CFLAGS:  -I/usr/include/llvm-18 -I/usr/include/llvm-c-18 -I/usr/lib/llvm-18/include\n#cgo darwin,amd64 CFLAGS:  -I/usr/local/opt/llvm@18/include\n#cgo darwin,arm64 CFLAGS:  -I/opt/homebrew/opt/llvm@18/include\n#cgo freebsd      CFLAGS:  -I/usr/local/llvm18/include\n#cgo linux        LDFLAGS: -L/usr/lib/llvm-18/lib -lclang\n#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@18/lib -lclang\n#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@18/lib -lclang\n#cgo freebsd      LDFLAGS: -L/usr/local/llvm18/lib -lclang\n*/\nimport \"C\"\n"
  },
  {
    "path": "cgo/libclang_config_llvm19.go",
    "content": "//go:build !byollvm && llvm19\n\npackage cgo\n\n/*\n#cgo linux        CFLAGS:  -I/usr/include/llvm-19 -I/usr/include/llvm-c-19 -I/usr/lib/llvm-19/include\n#cgo darwin,amd64 CFLAGS:  -I/usr/local/opt/llvm@19/include\n#cgo darwin,arm64 CFLAGS:  -I/opt/homebrew/opt/llvm@19/include\n#cgo freebsd      CFLAGS:  -I/usr/local/llvm19/include\n#cgo linux        LDFLAGS: -L/usr/lib/llvm-19/lib -lclang\n#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@19/lib -lclang\n#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@19/lib -lclang\n#cgo freebsd      LDFLAGS: -L/usr/local/llvm19/lib -lclang\n*/\nimport \"C\"\n"
  },
  {
    "path": "cgo/libclang_config_llvm20.go",
    "content": "//go:build !byollvm && !llvm15 && !llvm16 && !llvm17 && !llvm18 && !llvm19\n\npackage cgo\n\n/*\n#cgo linux        CFLAGS:  -I/usr/include/llvm-20 -I/usr/include/llvm-c-20 -I/usr/lib/llvm-20/include\n#cgo darwin,amd64 CFLAGS:  -I/usr/local/opt/llvm@20/include\n#cgo darwin,arm64 CFLAGS:  -I/opt/homebrew/opt/llvm@20/include\n#cgo freebsd      CFLAGS:  -I/usr/local/llvm20/include\n#cgo linux        LDFLAGS: -L/usr/lib/llvm-20/lib -lclang\n#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@20/lib -lclang\n#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@20/lib -lclang\n#cgo freebsd      LDFLAGS: -L/usr/local/llvm20/lib -lclang\n*/\nimport \"C\"\n"
  },
  {
    "path": "cgo/libclang_stubs.c",
    "content": "\n// This file implements some small trampoline functions. The signatures\n// are slightly different from the ones defined in libclang.go, but they\n// should be ABI compatible.\n\n#include <clang-c/Index.h> // If this fails, libclang headers aren't available. Please take a look here: https://tinygo.org/docs/guides/build/\n\nCXCursor tinygo_clang_getTranslationUnitCursor(CXTranslationUnit tu) {\n\treturn clang_getTranslationUnitCursor(tu);\n}\n\nunsigned tinygo_clang_visitChildren(CXCursor parent, CXCursorVisitor visitor, CXClientData client_data) {\n\treturn clang_visitChildren(parent, visitor, client_data);\n}\n\nCXString tinygo_clang_getCursorSpelling(CXCursor c) {\n\treturn clang_getCursorSpelling(c);\n}\n\nCXString tinygo_clang_getCursorPrettyPrinted(CXCursor c, CXPrintingPolicy policy) {\n\treturn clang_getCursorPrettyPrinted(c, policy);\n}\n\nCXPrintingPolicy tinygo_clang_getCursorPrintingPolicy(CXCursor c) {\n\treturn clang_getCursorPrintingPolicy(c);\n}\n\nenum CXCursorKind tinygo_clang_getCursorKind(CXCursor c) {\n\treturn clang_getCursorKind(c);\n}\n\nCXType tinygo_clang_getCursorType(CXCursor c) {\n\treturn clang_getCursorType(c);\n}\n\nCXCursor tinygo_clang_getTypeDeclaration(CXType t) {\n\treturn clang_getTypeDeclaration(t);\n}\n\nCXType tinygo_clang_getTypedefDeclUnderlyingType(CXCursor c) {\n\treturn clang_getTypedefDeclUnderlyingType(c);\n}\n\nCXType tinygo_clang_getCursorResultType(CXCursor c) {\n\treturn clang_getCursorResultType(c);\n}\n\nint tinygo_clang_Cursor_getNumArguments(CXCursor c) {\n\treturn clang_Cursor_getNumArguments(c);\n}\n\nCXCursor tinygo_clang_Cursor_getArgument(CXCursor c, unsigned i) {\n\treturn clang_Cursor_getArgument(c, i);\n}\n\nenum CX_StorageClass tinygo_clang_Cursor_getStorageClass(CXCursor c) {\n\treturn clang_Cursor_getStorageClass(c);\n}\n\nCXSourceLocation tinygo_clang_getCursorLocation(CXCursor c) {\n\treturn clang_getCursorLocation(c);\n}\n\nCXSourceRange tinygo_clang_getCursorExtent(CXCursor c) {\n\treturn clang_getCursorExtent(c);\n}\n\nCXTranslationUnit tinygo_clang_Cursor_getTranslationUnit(CXCursor c) {\n\treturn clang_Cursor_getTranslationUnit(c);\n}\n\nlong long tinygo_clang_getEnumConstantDeclValue(CXCursor c) {\n\treturn clang_getEnumConstantDeclValue(c);\n}\n\nCXType tinygo_clang_getEnumDeclIntegerType(CXCursor c) {\n\treturn clang_getEnumDeclIntegerType(c);\n}\n\nunsigned tinygo_clang_Cursor_isAnonymous(CXCursor c) {\n\treturn clang_Cursor_isAnonymous(c);\n}\n\nunsigned tinygo_clang_Cursor_isBitField(CXCursor c) {\n\treturn clang_Cursor_isBitField(c);\n}\n\nunsigned tinygo_clang_Cursor_isMacroFunctionLike(CXCursor c) {\n\treturn clang_Cursor_isMacroFunctionLike(c);\n}\n"
  },
  {
    "path": "cgo/security.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file has been copied from the Go 1.13 release tree.\n\n// Checking of compiler and linker flags.\n// We must avoid flags like -fplugin=, which can allow\n// arbitrary code execution during the build.\n// Do not make changes here without carefully\n// considering the implications.\n// (That's why the code is isolated in a file named security.go.)\n//\n// Note that -Wl,foo means split foo on commas and pass to\n// the linker, so that -Wl,-foo,bar means pass -foo bar to\n// the linker. Similarly -Wa,foo for the assembler and so on.\n// If any of these are permitted, the wildcard portion must\n// disallow commas.\n//\n// Note also that GNU binutils accept any argument @foo\n// as meaning \"read more flags from the file foo\", so we must\n// guard against any command-line argument beginning with @,\n// even things like \"-I @foo\".\n// We use safeArg (which is even more conservative)\n// to reject these.\n//\n// Even worse, gcc -I@foo (one arg) turns into cc1 -I @foo (two args),\n// so although gcc doesn't expand the @foo, cc1 will.\n// So out of paranoia, we reject @ at the beginning of every\n// flag argument that might be split into its own argument.\n\npackage cgo\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"regexp\"\n\t\"strings\"\n\t\"unicode/utf8\"\n)\n\nvar re = regexp.MustCompile\n\nvar validCompilerFlags = []*regexp.Regexp{\n\tre(`-D([A-Za-z_].*)`),\n\tre(`-F([^@\\-].*)`),\n\tre(`-I([^@\\-].*)`),\n\tre(`-O`),\n\tre(`-O([^@\\-].*)`),\n\tre(`-W`),\n\tre(`-W([^@,]+)`), // -Wall but not -Wa,-foo.\n\tre(`-Wa,-mbig-obj`),\n\tre(`-Wp,-D([A-Za-z_].*)`),\n\tre(`-ansi`),\n\tre(`-f(no-)?asynchronous-unwind-tables`),\n\tre(`-f(no-)?blocks`),\n\tre(`-f(no-)builtin-[a-zA-Z0-9_]*`),\n\tre(`-f(no-)?common`),\n\tre(`-f(no-)?constant-cfstrings`),\n\tre(`-fdiagnostics-show-note-include-stack`),\n\tre(`-f(no-)?eliminate-unused-debug-types`),\n\tre(`-f(no-)?exceptions`),\n\tre(`-f(no-)?fast-math`),\n\tre(`-f(no-)?inline-functions`),\n\tre(`-finput-charset=([^@\\-].*)`),\n\tre(`-f(no-)?fat-lto-objects`),\n\tre(`-f(no-)?keep-inline-dllexport`),\n\tre(`-f(no-)?lto`),\n\tre(`-fmacro-backtrace-limit=(.+)`),\n\tre(`-fmessage-length=(.+)`),\n\tre(`-f(no-)?modules`),\n\tre(`-f(no-)?objc-arc`),\n\tre(`-f(no-)?objc-nonfragile-abi`),\n\tre(`-f(no-)?objc-legacy-dispatch`),\n\tre(`-f(no-)?omit-frame-pointer`),\n\tre(`-f(no-)?openmp(-simd)?`),\n\tre(`-f(no-)?permissive`),\n\tre(`-f(no-)?(pic|PIC|pie|PIE)`),\n\tre(`-f(no-)?plt`),\n\tre(`-f(no-)?rtti`),\n\tre(`-f(no-)?split-stack`),\n\tre(`-f(no-)?stack-(.+)`),\n\tre(`-f(no-)?strict-aliasing`),\n\tre(`-f(un)signed-char`),\n\tre(`-f(no-)?use-linker-plugin`), // safe if -B is not used; we don't permit -B\n\tre(`-f(no-)?visibility-inlines-hidden`),\n\tre(`-fsanitize=(.+)`),\n\tre(`-ftemplate-depth-(.+)`),\n\tre(`-fvisibility=(.+)`),\n\tre(`-g([^@\\-].*)?`),\n\tre(`-m32`),\n\tre(`-m64`),\n\tre(`-m(abi|arch|cpu|fpu|tune)=([^@\\-].*)`),\n\tre(`-m(no-)?v?aes`),\n\tre(`-marm`),\n\tre(`-m(no-)?avx[0-9a-z]*`),\n\tre(`-mfloat-abi=([^@\\-].*)`),\n\tre(`-mfpmath=[0-9a-z,+]*`),\n\tre(`-m(no-)?avx[0-9a-z.]*`),\n\tre(`-m(no-)?ms-bitfields`),\n\tre(`-m(no-)?stack-(.+)`),\n\tre(`-mmacosx-(.+)`),\n\tre(`-mios-simulator-version-min=(.+)`),\n\tre(`-miphoneos-version-min=(.+)`),\n\tre(`-mtvos-simulator-version-min=(.+)`),\n\tre(`-mtvos-version-min=(.+)`),\n\tre(`-mwatchos-simulator-version-min=(.+)`),\n\tre(`-mwatchos-version-min=(.+)`),\n\tre(`-mnop-fun-dllimport`),\n\tre(`-m(no-)?sse[0-9.]*`),\n\tre(`-m(no-)?ssse3`),\n\tre(`-mthumb(-interwork)?`),\n\tre(`-mthreads`),\n\tre(`-mwindows`),\n\tre(`--param=ssp-buffer-size=[0-9]*`),\n\tre(`-pedantic(-errors)?`),\n\tre(`-pipe`),\n\tre(`-pthread`),\n\tre(`-?-std=([^@\\-].*)`),\n\tre(`-?-stdlib=([^@\\-].*)`),\n\tre(`--sysroot=([^@\\-].*)`),\n\tre(`-w`),\n\tre(`-x([^@\\-].*)`),\n\tre(`-v`),\n}\n\nvar validCompilerFlagsWithNextArg = []string{\n\t\"-arch\",\n\t\"-D\",\n\t\"-I\",\n\t\"-framework\",\n\t\"-isysroot\",\n\t\"-isystem\",\n\t\"--sysroot\",\n\t\"-target\",\n\t\"-x\",\n}\n\nvar validLinkerFlags = []*regexp.Regexp{\n\tre(`-F([^@\\-].*)`),\n\tre(`-l([^@\\-].*)`),\n\tre(`-L([^@\\-].*)`),\n\tre(`-O`),\n\tre(`-O([^@\\-].*)`),\n\tre(`--export=([^@\\-].*)`),\n\tre(`-f(no-)?(pic|PIC|pie|PIE)`),\n\tre(`-f(no-)?openmp(-simd)?`),\n\tre(`-fsanitize=([^@\\-].*)`),\n\tre(`-flat_namespace`),\n\tre(`-g([^@\\-].*)?`),\n\tre(`-headerpad_max_install_names`),\n\tre(`-m(abi|arch|cpu|fpu|tune)=([^@\\-].*)`),\n\tre(`-mfloat-abi=([^@\\-].*)`),\n\tre(`-mmacosx-(.+)`),\n\tre(`-mios-simulator-version-min=(.+)`),\n\tre(`-miphoneos-version-min=(.+)`),\n\tre(`-mthreads`),\n\tre(`-mwindows`),\n\tre(`-(pic|PIC|pie|PIE)`),\n\tre(`-pthread`),\n\tre(`-rdynamic`),\n\tre(`-shared`),\n\tre(`-?-static([-a-z0-9+]*)`),\n\tre(`-?-stdlib=([^@\\-].*)`),\n\tre(`-v`),\n\n\t// Note that any wildcards in -Wl need to exclude comma,\n\t// since -Wl splits its argument at commas and passes\n\t// them all to the linker uninterpreted. Allowing comma\n\t// in a wildcard would allow tunnelling arbitrary additional\n\t// linker arguments through one of these.\n\tre(`-Wl,--(no-)?allow-multiple-definition`),\n\tre(`-Wl,--(no-)?allow-shlib-undefined`),\n\tre(`-Wl,--(no-)?as-needed`),\n\tre(`-Wl,-Bdynamic`),\n\tre(`-Wl,-berok`),\n\tre(`-Wl,-Bstatic`),\n\tre(`-WL,-O([^@,\\-][^,]*)?`),\n\tre(`-Wl,-d[ny]`),\n\tre(`-Wl,--disable-new-dtags`),\n\tre(`-Wl,-e[=,][a-zA-Z0-9]*`),\n\tre(`-Wl,--enable-new-dtags`),\n\tre(`-Wl,--end-group`),\n\tre(`-Wl,--(no-)?export-dynamic`),\n\tre(`-Wl,-framework,[^,@\\-][^,]+`),\n\tre(`-Wl,-headerpad_max_install_names`),\n\tre(`-Wl,--no-undefined`),\n\tre(`-Wl,-R([^@\\-][^,@]*$)`),\n\tre(`-Wl,--just-symbols[=,]([^,@\\-][^,@]+)`),\n\tre(`-Wl,-rpath(-link)?[=,]([^,@\\-][^,]+)`),\n\tre(`-Wl,-s`),\n\tre(`-Wl,-search_paths_first`),\n\tre(`-Wl,-sectcreate,([^,@\\-][^,]+),([^,@\\-][^,]+),([^,@\\-][^,]+)`),\n\tre(`-Wl,--start-group`),\n\tre(`-Wl,-?-static`),\n\tre(`-Wl,-?-subsystem,(native|windows|console|posix|xbox)`),\n\tre(`-Wl,-syslibroot[=,]([^,@\\-][^,]+)`),\n\tre(`-Wl,-undefined[=,]([^,@\\-][^,]+)`),\n\tre(`-Wl,-?-unresolved-symbols=[^,]+`),\n\tre(`-Wl,--(no-)?warn-([^,]+)`),\n\tre(`-Wl,-z,(no)?execstack`),\n\tre(`-Wl,-z,relro`),\n\n\tre(`[a-zA-Z0-9_/].*\\.(a|o|obj|dll|dylib|so)`), // direct linker inputs: x.o or libfoo.so (but not -foo.o or @foo.o)\n\tre(`\\./.*\\.(a|o|obj|dll|dylib|so)`),\n}\n\nvar validLinkerFlagsWithNextArg = []string{\n\t\"-arch\",\n\t\"-F\",\n\t\"-l\",\n\t\"-L\",\n\t\"-framework\",\n\t\"-isysroot\",\n\t\"--sysroot\",\n\t\"-target\",\n\t\"-Wl,-framework\",\n\t\"-Wl,-rpath\",\n\t\"-Wl,-R\",\n\t\"-Wl,--just-symbols\",\n\t\"-Wl,-undefined\",\n}\n\nfunc checkCompilerFlags(name string, list []string) error {\n\treturn checkFlags(name, list, validCompilerFlags, validCompilerFlagsWithNextArg)\n}\n\nfunc checkLinkerFlags(name string, list []string) error {\n\treturn checkFlags(name, list, validLinkerFlags, validLinkerFlagsWithNextArg)\n}\n\nfunc checkFlags(name string, list []string, valid []*regexp.Regexp, validNext []string) error {\n\t// Let users override rules with $CGO_CFLAGS_ALLOW, $CGO_CFLAGS_DISALLOW, etc.\n\tvar (\n\t\tallow    *regexp.Regexp\n\t\tdisallow *regexp.Regexp\n\t)\n\tif env := os.Getenv(\"CGO_\" + name + \"_ALLOW\"); env != \"\" {\n\t\tr, err := regexp.Compile(env)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"parsing $CGO_%s_ALLOW: %v\", name, err)\n\t\t}\n\t\tallow = r\n\t}\n\tif env := os.Getenv(\"CGO_\" + name + \"_DISALLOW\"); env != \"\" {\n\t\tr, err := regexp.Compile(env)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"parsing $CGO_%s_DISALLOW: %v\", name, err)\n\t\t}\n\t\tdisallow = r\n\t}\n\nArgs:\n\tfor i := 0; i < len(list); i++ {\n\t\targ := list[i]\n\t\tif disallow != nil && disallow.FindString(arg) == arg {\n\t\t\tgoto Bad\n\t\t}\n\t\tif allow != nil && allow.FindString(arg) == arg {\n\t\t\tcontinue Args\n\t\t}\n\t\tfor _, re := range valid {\n\t\t\tif re.FindString(arg) == arg { // must be complete match\n\t\t\t\tcontinue Args\n\t\t\t}\n\t\t}\n\t\tfor _, x := range validNext {\n\t\t\tif arg == x {\n\t\t\t\tif i+1 < len(list) && safeArg(list[i+1]) {\n\t\t\t\t\ti++\n\t\t\t\t\tcontinue Args\n\t\t\t\t}\n\n\t\t\t\t// Permit -Wl,-framework -Wl,name.\n\t\t\t\tif i+1 < len(list) &&\n\t\t\t\t\tstrings.HasPrefix(arg, \"-Wl,\") &&\n\t\t\t\t\tstrings.HasPrefix(list[i+1], \"-Wl,\") &&\n\t\t\t\t\tsafeArg(list[i+1][4:]) &&\n\t\t\t\t\t!strings.Contains(list[i+1][4:], \",\") {\n\t\t\t\t\ti++\n\t\t\t\t\tcontinue Args\n\t\t\t\t}\n\n\t\t\t\tif i+1 < len(list) {\n\t\t\t\t\treturn fmt.Errorf(\"invalid flag: %s %s (see https://golang.org/s/invalidflag)\", arg, list[i+1])\n\t\t\t\t}\n\t\t\t\treturn fmt.Errorf(\"invalid flag: %s without argument (see https://golang.org/s/invalidflag)\", arg)\n\t\t\t}\n\t\t}\n\tBad:\n\t\treturn fmt.Errorf(\"invalid flag: %s\", arg)\n\t}\n\treturn nil\n}\n\nfunc safeArg(name string) bool {\n\tif name == \"\" {\n\t\treturn false\n\t}\n\tc := name[0]\n\treturn '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || c == '.' || c == '_' || c == '/' || c >= utf8.RuneSelf\n}\n"
  },
  {
    "path": "cgo/security_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file has been copied from the Go 1.13 release tree.\n\npackage cgo\n\nimport (\n\t\"os\"\n\t\"testing\"\n)\n\nvar goodCompilerFlags = [][]string{\n\t{\"-DFOO\"},\n\t{\"-Dfoo=bar\"},\n\t{\"-F/Qt\"},\n\t{\"-I/\"},\n\t{\"-I/etc/passwd\"},\n\t{\"-I.\"},\n\t{\"-O\"},\n\t{\"-O2\"},\n\t{\"-Osmall\"},\n\t{\"-W\"},\n\t{\"-Wall\"},\n\t{\"-fobjc-arc\"},\n\t{\"-fno-objc-arc\"},\n\t{\"-fomit-frame-pointer\"},\n\t{\"-fno-omit-frame-pointer\"},\n\t{\"-fpic\"},\n\t{\"-fno-pic\"},\n\t{\"-fPIC\"},\n\t{\"-fno-PIC\"},\n\t{\"-fpie\"},\n\t{\"-fno-pie\"},\n\t{\"-fPIE\"},\n\t{\"-fno-PIE\"},\n\t{\"-fsplit-stack\"},\n\t{\"-fno-split-stack\"},\n\t{\"-fstack-xxx\"},\n\t{\"-fno-stack-xxx\"},\n\t{\"-fsanitize=hands\"},\n\t{\"-g\"},\n\t{\"-ggdb\"},\n\t{\"-march=souza\"},\n\t{\"-mcpu=123\"},\n\t{\"-mfpu=123\"},\n\t{\"-mtune=happybirthday\"},\n\t{\"-mstack-overflow\"},\n\t{\"-mno-stack-overflow\"},\n\t{\"-mmacosx-version\"},\n\t{\"-mnop-fun-dllimport\"},\n\t{\"-pthread\"},\n\t{\"-std=c99\"},\n\t{\"-xc\"},\n\t{\"-D\", \"FOO\"},\n\t{\"-D\", \"foo=bar\"},\n\t{\"-I\", \".\"},\n\t{\"-I\", \"/etc/passwd\"},\n\t{\"-I\", \"世界\"},\n\t{\"-framework\", \"Chocolate\"},\n\t{\"-x\", \"c\"},\n\t{\"-v\"},\n}\n\nvar badCompilerFlags = [][]string{\n\t{\"-D@X\"},\n\t{\"-D-X\"},\n\t{\"-F@dir\"},\n\t{\"-F-dir\"},\n\t{\"-I@dir\"},\n\t{\"-I-dir\"},\n\t{\"-O@1\"},\n\t{\"-Wa,-foo\"},\n\t{\"-W@foo\"},\n\t{\"-g@gdb\"},\n\t{\"-g-gdb\"},\n\t{\"-march=@dawn\"},\n\t{\"-march=-dawn\"},\n\t{\"-std=@c99\"},\n\t{\"-std=-c99\"},\n\t{\"-x@c\"},\n\t{\"-x-c\"},\n\t{\"-D\", \"@foo\"},\n\t{\"-D\", \"-foo\"},\n\t{\"-I\", \"@foo\"},\n\t{\"-I\", \"-foo\"},\n\t{\"-framework\", \"-Caffeine\"},\n\t{\"-framework\", \"@Home\"},\n\t{\"-x\", \"--c\"},\n\t{\"-x\", \"@obj\"},\n}\n\nfunc TestCheckCompilerFlags(t *testing.T) {\n\tfor _, f := range goodCompilerFlags {\n\t\tif err := checkCompilerFlags(\"test\", f); err != nil {\n\t\t\tt.Errorf(\"unexpected error for %q: %v\", f, err)\n\t\t}\n\t}\n\tfor _, f := range badCompilerFlags {\n\t\tif err := checkCompilerFlags(\"test\", f); err == nil {\n\t\t\tt.Errorf(\"missing error for %q\", f)\n\t\t}\n\t}\n}\n\nvar goodLinkerFlags = [][]string{\n\t{\"-Fbar\"},\n\t{\"-lbar\"},\n\t{\"-Lbar\"},\n\t{\"--export=my_symbol\"},\n\t{\"-fpic\"},\n\t{\"-fno-pic\"},\n\t{\"-fPIC\"},\n\t{\"-fno-PIC\"},\n\t{\"-fpie\"},\n\t{\"-fno-pie\"},\n\t{\"-fPIE\"},\n\t{\"-fno-PIE\"},\n\t{\"-fsanitize=hands\"},\n\t{\"-g\"},\n\t{\"-ggdb\"},\n\t{\"-march=souza\"},\n\t{\"-mcpu=123\"},\n\t{\"-mfpu=123\"},\n\t{\"-mtune=happybirthday\"},\n\t{\"-pic\"},\n\t{\"-pthread\"},\n\t{\"-Wl,-rpath,foo\"},\n\t{\"-Wl,-rpath,$ORIGIN/foo\"},\n\t{\"-Wl,-R\", \"/foo\"},\n\t{\"-Wl,-R\", \"foo\"},\n\t{\"-Wl,-R,foo\"},\n\t{\"-Wl,--just-symbols=foo\"},\n\t{\"-Wl,--just-symbols,foo\"},\n\t{\"-Wl,--warn-error\"},\n\t{\"-Wl,--no-warn-error\"},\n\t{\"foo.so\"},\n\t{\"_世界.dll\"},\n\t{\"./x.o\"},\n\t{\"libcgosotest.dylib\"},\n\t{\"-F\", \"framework\"},\n\t{\"-l\", \".\"},\n\t{\"-l\", \"/etc/passwd\"},\n\t{\"-l\", \"世界\"},\n\t{\"-L\", \"framework\"},\n\t{\"-framework\", \"Chocolate\"},\n\t{\"-v\"},\n\t{\"-Wl,-framework\", \"-Wl,Chocolate\"},\n\t{\"-Wl,-framework,Chocolate\"},\n\t{\"-Wl,-unresolved-symbols=ignore-all\"},\n}\n\nvar badLinkerFlags = [][]string{\n\t{\"-DFOO\"},\n\t{\"-Dfoo=bar\"},\n\t{\"-W\"},\n\t{\"-Wall\"},\n\t{\"-fobjc-arc\"},\n\t{\"-fno-objc-arc\"},\n\t{\"-fomit-frame-pointer\"},\n\t{\"-fno-omit-frame-pointer\"},\n\t{\"-fsplit-stack\"},\n\t{\"-fno-split-stack\"},\n\t{\"-fstack-xxx\"},\n\t{\"-fno-stack-xxx\"},\n\t{\"-mstack-overflow\"},\n\t{\"-mno-stack-overflow\"},\n\t{\"-mnop-fun-dllimport\"},\n\t{\"-std=c99\"},\n\t{\"-xc\"},\n\t{\"-D\", \"FOO\"},\n\t{\"-D\", \"foo=bar\"},\n\t{\"-I\", \"FOO\"},\n\t{\"-L\", \"@foo\"},\n\t{\"-L\", \"-foo\"},\n\t{\"-x\", \"c\"},\n\t{\"-D@X\"},\n\t{\"-D-X\"},\n\t{\"-I@dir\"},\n\t{\"-I-dir\"},\n\t{\"-O@1\"},\n\t{\"-Wa,-foo\"},\n\t{\"-W@foo\"},\n\t{\"-g@gdb\"},\n\t{\"-g-gdb\"},\n\t{\"-march=@dawn\"},\n\t{\"-march=-dawn\"},\n\t{\"-std=@c99\"},\n\t{\"-std=-c99\"},\n\t{\"-x@c\"},\n\t{\"-x-c\"},\n\t{\"-D\", \"@foo\"},\n\t{\"-D\", \"-foo\"},\n\t{\"-I\", \"@foo\"},\n\t{\"-I\", \"-foo\"},\n\t{\"-l\", \"@foo\"},\n\t{\"-l\", \"-foo\"},\n\t{\"-framework\", \"-Caffeine\"},\n\t{\"-framework\", \"@Home\"},\n\t{\"-Wl,-framework,-Caffeine\"},\n\t{\"-Wl,-framework\", \"-Wl,@Home\"},\n\t{\"-Wl,-framework\", \"@Home\"},\n\t{\"-Wl,-framework,Chocolate,@Home\"},\n\t{\"-x\", \"--c\"},\n\t{\"-x\", \"@obj\"},\n\t{\"-Wl,-rpath,@foo\"},\n\t{\"-Wl,-R,foo,bar\"},\n\t{\"-Wl,-R,@foo\"},\n\t{\"-Wl,--just-symbols,@foo\"},\n\t{\"../x.o\"},\n}\n\nfunc TestCheckLinkerFlags(t *testing.T) {\n\tfor _, f := range goodLinkerFlags {\n\t\tif err := checkLinkerFlags(\"test\", f); err != nil {\n\t\t\tt.Errorf(\"unexpected error for %q: %v\", f, err)\n\t\t}\n\t}\n\tfor _, f := range badLinkerFlags {\n\t\tif err := checkLinkerFlags(\"test\", f); err == nil {\n\t\t\tt.Errorf(\"missing error for %q\", f)\n\t\t}\n\t}\n}\n\nfunc TestCheckFlagAllowDisallow(t *testing.T) {\n\tif err := checkCompilerFlags(\"TEST\", []string{\"-disallow\"}); err == nil {\n\t\tt.Fatalf(\"missing error for -disallow\")\n\t}\n\tos.Setenv(\"CGO_TEST_ALLOW\", \"-disallo\")\n\tif err := checkCompilerFlags(\"TEST\", []string{\"-disallow\"}); err == nil {\n\t\tt.Fatalf(\"missing error for -disallow with CGO_TEST_ALLOW=-disallo\")\n\t}\n\tos.Setenv(\"CGO_TEST_ALLOW\", \"-disallow\")\n\tif err := checkCompilerFlags(\"TEST\", []string{\"-disallow\"}); err != nil {\n\t\tt.Fatalf(\"unexpected error for -disallow with CGO_TEST_ALLOW=-disallow: %v\", err)\n\t}\n\tos.Unsetenv(\"CGO_TEST_ALLOW\")\n\n\tif err := checkCompilerFlags(\"TEST\", []string{\"-Wall\"}); err != nil {\n\t\tt.Fatalf(\"unexpected error for -Wall: %v\", err)\n\t}\n\tos.Setenv(\"CGO_TEST_DISALLOW\", \"-Wall\")\n\tif err := checkCompilerFlags(\"TEST\", []string{\"-Wall\"}); err == nil {\n\t\tt.Fatalf(\"missing error for -Wall with CGO_TEST_DISALLOW=-Wall\")\n\t}\n\tos.Setenv(\"CGO_TEST_ALLOW\", \"-Wall\") // disallow wins\n\tif err := checkCompilerFlags(\"TEST\", []string{\"-Wall\"}); err == nil {\n\t\tt.Fatalf(\"missing error for -Wall with CGO_TEST_DISALLOW=-Wall and CGO_TEST_ALLOW=-Wall\")\n\t}\n\n\tos.Setenv(\"CGO_TEST_ALLOW\", \"-fplugin.*\")\n\tos.Setenv(\"CGO_TEST_DISALLOW\", \"-fplugin=lint.so\")\n\tif err := checkCompilerFlags(\"TEST\", []string{\"-fplugin=faster.so\"}); err != nil {\n\t\tt.Fatalf(\"unexpected error for -fplugin=faster.so: %v\", err)\n\t}\n\tif err := checkCompilerFlags(\"TEST\", []string{\"-fplugin=lint.so\"}); err == nil {\n\t\tt.Fatalf(\"missing error for -fplugin=lint.so: %v\", err)\n\t}\n}\n"
  },
  {
    "path": "cgo/sync.go",
    "content": "package cgo\n\nimport (\n\t\"sync\"\n\t\"unsafe\"\n)\n\n// #include <stdlib.h>\nimport \"C\"\n\n// refMap is a convenient way to store opaque references that can be passed to\n// C. It is useful if an API uses function pointers and you cannot pass a Go\n// pointer but only a C pointer.\ntype refMap struct {\n\trefs map[unsafe.Pointer]interface{}\n\tlock sync.Mutex\n}\n\n// Put stores a value in the map. It can later be retrieved using Get. It must\n// be removed using Remove to avoid memory leaks.\nfunc (m *refMap) Put(v interface{}) unsafe.Pointer {\n\tm.lock.Lock()\n\tdefer m.lock.Unlock()\n\tif m.refs == nil {\n\t\tm.refs = make(map[unsafe.Pointer]interface{}, 1)\n\t}\n\tref := C.malloc(1)\n\tm.refs[ref] = v\n\treturn ref\n}\n\n// Get returns a stored value previously inserted with Put. Use the same\n// reference as you got from Put.\nfunc (m *refMap) Get(ref unsafe.Pointer) interface{} {\n\tm.lock.Lock()\n\tdefer m.lock.Unlock()\n\treturn m.refs[ref]\n}\n\n// Remove deletes a single reference from the map.\nfunc (m *refMap) Remove(ref unsafe.Pointer) {\n\tm.lock.Lock()\n\tdefer m.lock.Unlock()\n\tdelete(m.refs, ref)\n\tC.free(ref)\n}\n"
  },
  {
    "path": "cgo/testdata/basic.go",
    "content": "package main\n\nimport \"C\"\n"
  },
  {
    "path": "cgo/testdata/basic.out.go",
    "content": "package main\n\nimport \"syscall\"\nimport \"unsafe\"\n\nvar _ unsafe.Pointer\n\n//go:linkname _Cgo_CString runtime.cgo_CString\nfunc _Cgo_CString(string) *_Cgo_char\n\n//go:linkname _Cgo_GoString runtime.cgo_GoString\nfunc _Cgo_GoString(*_Cgo_char) string\n\n//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN\nfunc _Cgo___GoStringN(*_Cgo_char, uintptr) string\n\nfunc _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {\n\treturn _Cgo___GoStringN(cstr, uintptr(length))\n}\n\n//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes\nfunc _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte\n\nfunc _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {\n\treturn _Cgo___GoBytes(ptr, uintptr(length))\n}\n\n//go:linkname _Cgo___CBytes runtime.cgo_CBytes\nfunc _Cgo___CBytes([]byte) unsafe.Pointer\n\nfunc _Cgo_CBytes(b []byte) unsafe.Pointer {\n\treturn _Cgo___CBytes(b)\n}\n\n//go:linkname _Cgo___get_errno_num runtime.cgo_errno\nfunc _Cgo___get_errno_num() uintptr\n\nfunc _Cgo___get_errno() error {\n\treturn syscall.Errno(_Cgo___get_errno_num())\n}\n\ntype (\n\t_Cgo_char      uint8\n\t_Cgo_schar     int8\n\t_Cgo_uchar     uint8\n\t_Cgo_short     int16\n\t_Cgo_ushort    uint16\n\t_Cgo_int       int32\n\t_Cgo_uint      uint32\n\t_Cgo_long      int32\n\t_Cgo_ulong     uint32\n\t_Cgo_longlong  int64\n\t_Cgo_ulonglong uint64\n)\n"
  },
  {
    "path": "cgo/testdata/const.go",
    "content": "package main\n\n/*\n#define foo 3\n#define bar foo\n\n#define unreferenced 4\n#define referenced unreferenced\n\n#define fnlike() 5\n#define fnlike_val fnlike()\n#define square(n) (n*n)\n#define square_val square(20)\n#define add(a, b) (a + b)\n#define add_val add(3, 5)\n*/\nimport \"C\"\n\nconst (\n\tFoo = C.foo\n\tBar = C.bar\n\n\tBaz = C.referenced\n\n\tfnlike = C.fnlike_val\n\tsquare = C.square_val\n\tadd    = C.add_val\n)\n"
  },
  {
    "path": "cgo/testdata/const.out.go",
    "content": "package main\n\nimport \"syscall\"\nimport \"unsafe\"\n\nvar _ unsafe.Pointer\n\n//go:linkname _Cgo_CString runtime.cgo_CString\nfunc _Cgo_CString(string) *_Cgo_char\n\n//go:linkname _Cgo_GoString runtime.cgo_GoString\nfunc _Cgo_GoString(*_Cgo_char) string\n\n//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN\nfunc _Cgo___GoStringN(*_Cgo_char, uintptr) string\n\nfunc _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {\n\treturn _Cgo___GoStringN(cstr, uintptr(length))\n}\n\n//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes\nfunc _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte\n\nfunc _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {\n\treturn _Cgo___GoBytes(ptr, uintptr(length))\n}\n\n//go:linkname _Cgo___CBytes runtime.cgo_CBytes\nfunc _Cgo___CBytes([]byte) unsafe.Pointer\n\nfunc _Cgo_CBytes(b []byte) unsafe.Pointer {\n\treturn _Cgo___CBytes(b)\n}\n\n//go:linkname _Cgo___get_errno_num runtime.cgo_errno\nfunc _Cgo___get_errno_num() uintptr\n\nfunc _Cgo___get_errno() error {\n\treturn syscall.Errno(_Cgo___get_errno_num())\n}\n\ntype (\n\t_Cgo_char      uint8\n\t_Cgo_schar     int8\n\t_Cgo_uchar     uint8\n\t_Cgo_short     int16\n\t_Cgo_ushort    uint16\n\t_Cgo_int       int32\n\t_Cgo_uint      uint32\n\t_Cgo_long      int32\n\t_Cgo_ulong     uint32\n\t_Cgo_longlong  int64\n\t_Cgo_ulonglong uint64\n)\n\nconst _Cgo_foo = 3\nconst _Cgo_bar = _Cgo_foo\nconst _Cgo_unreferenced = 4\nconst _Cgo_referenced = _Cgo_unreferenced\nconst _Cgo_fnlike_val = 5\nconst _Cgo_square_val = (20 * 20)\nconst _Cgo_add_val = (3 + 5)\n"
  },
  {
    "path": "cgo/testdata/errors.go",
    "content": "package main\n\n/*\n#warning some warning\n\ntypedef struct {\n\tint x;\n\tint y;\n} point_t;\n\ntypedef someType noType; // undefined type\n\n// Some invalid noescape lines\n#cgo noescape\n#cgo noescape foo bar\n#cgo noescape unusedFunction\n\n#define SOME_CONST_1 5) // invalid const syntax\n#define SOME_CONST_2 6) // const not used (so no error)\n#define SOME_CONST_3 1234 // const too large for byte\n#define   SOME_CONST_b      3   ) // const with lots of weird whitespace (to test error locations)\n#  define SOME_CONST_startspace 3)\n*/\n//\n//\n// #define SOME_CONST_4 8) // after some empty lines\n// #cgo CFLAGS: -DSOME_PARAM_CONST_invalid=3/+3\n// #cgo CFLAGS: -DSOME_PARAM_CONST_valid=3+4\nimport \"C\"\n\n// #warning another warning\nimport \"C\"\n\n// #define add(a, b) (a+b)\n// #define add_toomuch add(1, 2, 3)\n// #define add_toolittle add(1)\nimport \"C\"\n\n// Make sure that errors for the following lines won't change with future\n// additions to the CGo preamble.\n//\n//line errors.go:100\nvar (\n\t// constant too large\n\t_ C.char = 2 << 10\n\n\t// z member does not exist\n\t_ C.point_t = C.point_t{z: 3}\n\n\t// constant has syntax error\n\t_ = C.SOME_CONST_1\n\n\t_ byte = C.SOME_CONST_3\n\n\t_ = C.SOME_CONST_4\n\n\t_ = C.SOME_CONST_b\n\n\t_ = C.SOME_CONST_startspace\n\n\t// constants passed by a command line parameter\n\t_ = C.SOME_PARAM_CONST_invalid\n\t_ = C.SOME_PARAM_CONST_valid\n\n\t_ = C.add_toomuch\n\t_ = C.add_toolittle\n)\n"
  },
  {
    "path": "cgo/testdata/errors.out.go",
    "content": "// CGo errors:\n//     testdata/errors.go:14:1: missing function name in #cgo noescape line\n//     testdata/errors.go:15:1: multiple function names in #cgo noescape line\n//     testdata/errors.go:4:2: warning: some warning\n//     testdata/errors.go:11:9: error: unknown type name 'someType'\n//     testdata/errors.go:31:5: warning: another warning\n//     testdata/errors.go:18:23: unexpected token ), expected end of expression\n//     testdata/errors.go:26:26: unexpected token ), expected end of expression\n//     testdata/errors.go:21:33: unexpected token ), expected end of expression\n//     testdata/errors.go:22:34: unexpected token ), expected end of expression\n//     -: unexpected token INT, expected end of expression\n//     testdata/errors.go:35:35: unexpected number of parameters: expected 2, got 3\n//     testdata/errors.go:36:31: unexpected number of parameters: expected 2, got 1\n//     testdata/errors.go:3:1: function \"unusedFunction\" in #cgo noescape line is not used\n\n// Type checking errors after CGo processing:\n//     testdata/errors.go:102: cannot use 2 << 10 (untyped int constant 2048) as _Cgo_char value in variable declaration (overflows)\n//     testdata/errors.go:105: unknown field z in struct literal\n//     testdata/errors.go:108: undefined: _Cgo_SOME_CONST_1\n//     testdata/errors.go:110: cannot use _Cgo_SOME_CONST_3 (untyped int constant 1234) as byte value in variable declaration (overflows)\n//     testdata/errors.go:112: undefined: _Cgo_SOME_CONST_4\n//     testdata/errors.go:114: undefined: _Cgo_SOME_CONST_b\n//     testdata/errors.go:116: undefined: _Cgo_SOME_CONST_startspace\n//     testdata/errors.go:119: undefined: _Cgo_SOME_PARAM_CONST_invalid\n//     testdata/errors.go:122: undefined: _Cgo_add_toomuch\n//     testdata/errors.go:123: undefined: _Cgo_add_toolittle\n\npackage main\n\nimport \"syscall\"\nimport \"unsafe\"\n\nvar _ unsafe.Pointer\n\n//go:linkname _Cgo_CString runtime.cgo_CString\nfunc _Cgo_CString(string) *_Cgo_char\n\n//go:linkname _Cgo_GoString runtime.cgo_GoString\nfunc _Cgo_GoString(*_Cgo_char) string\n\n//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN\nfunc _Cgo___GoStringN(*_Cgo_char, uintptr) string\n\nfunc _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {\n\treturn _Cgo___GoStringN(cstr, uintptr(length))\n}\n\n//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes\nfunc _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte\n\nfunc _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {\n\treturn _Cgo___GoBytes(ptr, uintptr(length))\n}\n\n//go:linkname _Cgo___CBytes runtime.cgo_CBytes\nfunc _Cgo___CBytes([]byte) unsafe.Pointer\n\nfunc _Cgo_CBytes(b []byte) unsafe.Pointer {\n\treturn _Cgo___CBytes(b)\n}\n\n//go:linkname _Cgo___get_errno_num runtime.cgo_errno\nfunc _Cgo___get_errno_num() uintptr\n\nfunc _Cgo___get_errno() error {\n\treturn syscall.Errno(_Cgo___get_errno_num())\n}\n\ntype (\n\t_Cgo_char      uint8\n\t_Cgo_schar     int8\n\t_Cgo_uchar     uint8\n\t_Cgo_short     int16\n\t_Cgo_ushort    uint16\n\t_Cgo_int       int32\n\t_Cgo_uint      uint32\n\t_Cgo_long      int32\n\t_Cgo_ulong     uint32\n\t_Cgo_longlong  int64\n\t_Cgo_ulonglong uint64\n)\ntype _Cgo_struct_point_t struct {\n\tx _Cgo_int\n\ty _Cgo_int\n}\ntype _Cgo_point_t = _Cgo_struct_point_t\n\nconst _Cgo_SOME_CONST_3 = 1234\nconst _Cgo_SOME_PARAM_CONST_valid = 3 + 4\n"
  },
  {
    "path": "cgo/testdata/flags.go",
    "content": "package main\n\n/*\n// this name doesn't exist\n#cgo  NOFLAGS: -foo\n\n// unknown flag\n#cgo CFLAGS: -fdoes-not-exist -DNOTDEFINED\n\n#cgo CFLAGS: -DFOO\n\n#cgo CFLAGS: -Iinclude\n#include \"foo.h\"\n\n#if defined(FOO)\n#define BAR 3\n#else\n#define BAR 5\n#endif\n\n#if defined(NOTDEFINED)\n#warning flag must not be defined\n#endif\n\n// Check Compiler flags\n#cgo LDFLAGS: -lc\n\n// This flag is not valid ldflags\n#cgo LDFLAGS: -does-not-exists\n\n*/\nimport \"C\"\n\nvar (\n\t_ = C.BAR\n\t_ = C.FOO_H\n)\n"
  },
  {
    "path": "cgo/testdata/flags.out.go",
    "content": "// CGo errors:\n//     testdata/flags.go:5:7: invalid #cgo line: NOFLAGS\n//     testdata/flags.go:8:13: invalid flag: -fdoes-not-exist\n//     testdata/flags.go:29:14: invalid flag: -does-not-exists\n\npackage main\n\nimport \"syscall\"\nimport \"unsafe\"\n\nvar _ unsafe.Pointer\n\n//go:linkname _Cgo_CString runtime.cgo_CString\nfunc _Cgo_CString(string) *_Cgo_char\n\n//go:linkname _Cgo_GoString runtime.cgo_GoString\nfunc _Cgo_GoString(*_Cgo_char) string\n\n//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN\nfunc _Cgo___GoStringN(*_Cgo_char, uintptr) string\n\nfunc _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {\n\treturn _Cgo___GoStringN(cstr, uintptr(length))\n}\n\n//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes\nfunc _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte\n\nfunc _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {\n\treturn _Cgo___GoBytes(ptr, uintptr(length))\n}\n\n//go:linkname _Cgo___CBytes runtime.cgo_CBytes\nfunc _Cgo___CBytes([]byte) unsafe.Pointer\n\nfunc _Cgo_CBytes(b []byte) unsafe.Pointer {\n\treturn _Cgo___CBytes(b)\n}\n\n//go:linkname _Cgo___get_errno_num runtime.cgo_errno\nfunc _Cgo___get_errno_num() uintptr\n\nfunc _Cgo___get_errno() error {\n\treturn syscall.Errno(_Cgo___get_errno_num())\n}\n\ntype (\n\t_Cgo_char      uint8\n\t_Cgo_schar     int8\n\t_Cgo_uchar     uint8\n\t_Cgo_short     int16\n\t_Cgo_ushort    uint16\n\t_Cgo_int       int32\n\t_Cgo_uint      uint32\n\t_Cgo_long      int32\n\t_Cgo_ulong     uint32\n\t_Cgo_longlong  int64\n\t_Cgo_ulonglong uint64\n)\n\nconst _Cgo_BAR = 3\nconst _Cgo_FOO_H = 1\n"
  },
  {
    "path": "cgo/testdata/include/foo.h",
    "content": "#define FOO_H 1\n"
  },
  {
    "path": "cgo/testdata/symbols.go",
    "content": "package main\n\n/*\n// Function signatures.\nint foo(int a, int b);\nvoid variadic0();\nvoid variadic2(int x, int y, ...);\nstatic void staticfunc(int x);\n\n// Global variable signatures.\nextern int someValue;\n\nvoid notEscapingFunction(int *a);\n\n#cgo noescape notEscapingFunction\n*/\nimport \"C\"\n\n// Test function signatures.\nfunc accessFunctions() {\n\tC.foo(3, 4)\n\tC.variadic0()\n\tC.variadic2(3, 5)\n\tC.staticfunc(3)\n\tC.notEscapingFunction(nil)\n}\n\nfunc accessGlobals() {\n\t_ = C.someValue\n}\n"
  },
  {
    "path": "cgo/testdata/symbols.out.go",
    "content": "package main\n\nimport \"syscall\"\nimport \"unsafe\"\n\nvar _ unsafe.Pointer\n\n//go:linkname _Cgo_CString runtime.cgo_CString\nfunc _Cgo_CString(string) *_Cgo_char\n\n//go:linkname _Cgo_GoString runtime.cgo_GoString\nfunc _Cgo_GoString(*_Cgo_char) string\n\n//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN\nfunc _Cgo___GoStringN(*_Cgo_char, uintptr) string\n\nfunc _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {\n\treturn _Cgo___GoStringN(cstr, uintptr(length))\n}\n\n//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes\nfunc _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte\n\nfunc _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {\n\treturn _Cgo___GoBytes(ptr, uintptr(length))\n}\n\n//go:linkname _Cgo___CBytes runtime.cgo_CBytes\nfunc _Cgo___CBytes([]byte) unsafe.Pointer\n\nfunc _Cgo_CBytes(b []byte) unsafe.Pointer {\n\treturn _Cgo___CBytes(b)\n}\n\n//go:linkname _Cgo___get_errno_num runtime.cgo_errno\nfunc _Cgo___get_errno_num() uintptr\n\nfunc _Cgo___get_errno() error {\n\treturn syscall.Errno(_Cgo___get_errno_num())\n}\n\ntype (\n\t_Cgo_char      uint8\n\t_Cgo_schar     int8\n\t_Cgo_uchar     uint8\n\t_Cgo_short     int16\n\t_Cgo_ushort    uint16\n\t_Cgo_int       int32\n\t_Cgo_uint      uint32\n\t_Cgo_long      int32\n\t_Cgo_ulong     uint32\n\t_Cgo_longlong  int64\n\t_Cgo_ulonglong uint64\n)\n\n//export foo\nfunc _Cgo_foo(a _Cgo_int, b _Cgo_int) _Cgo_int\n\nvar _Cgo_foo$funcaddr unsafe.Pointer\n\n//export variadic0\n//go:variadic\nfunc _Cgo_variadic0()\n\nvar _Cgo_variadic0$funcaddr unsafe.Pointer\n\n//export variadic2\n//go:variadic\nfunc _Cgo_variadic2(x _Cgo_int, y _Cgo_int)\n\nvar _Cgo_variadic2$funcaddr unsafe.Pointer\n\n//export _Cgo_static_173c95a79b6df1980521_staticfunc\nfunc _Cgo_staticfunc!symbols.go(x _Cgo_int)\n\nvar _Cgo_staticfunc!symbols.go$funcaddr unsafe.Pointer\n\n//export notEscapingFunction\n//go:noescape\nfunc _Cgo_notEscapingFunction(a *_Cgo_int)\n\nvar _Cgo_notEscapingFunction$funcaddr unsafe.Pointer\n//go:extern someValue\nvar _Cgo_someValue _Cgo_int\n"
  },
  {
    "path": "cgo/testdata/types.go",
    "content": "package main\n\n/*\n// Simple typedef.\ntypedef int myint;\n\n// Structs, with or without name.\ntypedef struct {\n\tint x;\n\tint y;\n} point2d_t;\ntypedef struct point3d {\n\tint x;\n\tint y;\n\tint z;\n} point3d_t;\n\n// Structs with reserved field names.\nstruct type1 {\n\t// All these fields should be renamed.\n\tint type;\n\tint _type;\n\tint __type;\n};\nstruct type2 {\n\t// This field should not be renamed.\n\tint _type;\n};\n\n// Unions.\ntypedef union {\n\t// Union should be treated as a struct.\n\tint i;\n} union1_t;\ntypedef union {\n\t// Union must contain a single field and have special getters/setters.\n\tint    i;\n\tdouble d;\n\tshort  s;\n} union3_t;\ntypedef union union2d {\n\tint i;\n\tdouble d[2];\n} union2d_t;\ntypedef union {\n\tunsigned char arr[10];\n} unionarray_t;\n\n// Nested structs and unions.\ntypedef struct {\n\tpoint2d_t begin;\n\tpoint2d_t end;\n\tint       tag;\n\tunion {\n\t\tpoint2d_t area;\n\t\tpoint3d_t solid;\n\t} coord;\n} struct_nested_t;\ntypedef union {\n\tpoint3d_t    point;\n\tunionarray_t array;\n\tunion3_t     thing;\n} union_nested_t;\n\n// Enums. These define constant numbers. All these constants must be given the\n// correct number.\ntypedef enum option {\n\toptionA,\n\toptionB,\n\toptionC = -5,\n\toptionD,\n\toptionE = 10,\n\toptionF,\n\toptionG,\n} option_t;\nenum unused {\n\tunused1 = 5,\n};\n\n// Anonymous enum.\ntypedef enum {\n\toption2A = 20,\n} option2_t;\n\n// Various types that are usually translated directly to Go types, but storing\n// them in a struct reveals them.\ntypedef struct {\n\tfloat  f;\n\tdouble d;\n\tint    *ptr;\n} types_t;\n\n// Arrays.\ntypedef int myIntArray[10];\n\n// Bitfields.\ntypedef struct {\n\tunsigned char start;\n\tunsigned char a : 5;\n\tunsigned char b : 1;\n\tunsigned char c : 2;\n\tunsigned char :0; // new field\n\tunsigned char d : 6;\n\tunsigned char e : 3;\n\t// Note that C++ allows bitfields bigger than the underlying type.\n} bitfield_t;\n*/\nimport \"C\"\n\n// // Test that we can refer from this CGo fragment to the fragment above.\n// typedef myint myint2;\nimport \"C\"\n\nvar (\n\t// aliases\n\t_ C.float\n\t_ C.double\n\n\t// Simple typedefs.\n\t_ C.myint\n\n\t// Structs.\n\t_ C.point2d_t\n\t_ C.point3d_t\n\t_ C.struct_point3d\n\n\t// Structs with reserved field names.\n\t_ C.struct_type1\n\t_ C.struct_type2\n\n\t// Unions.\n\t_ C.union1_t\n\t_ C.union3_t\n\t_ C.union2d_t\n\t_ C.unionarray_t\n\n\t// Nested structs and unions.\n\t_ C.struct_nested_t\n\t_ C.union_nested_t\n\n\t// Enums (anonymous and named).\n\t_ C.option_t\n\t_ C.enum_option\n\t_ C.option2_t\n\n\t// Various types.\n\t_ C.types_t\n\n\t// Arrays.\n\t_ C.myIntArray\n)\n\n// Test bitfield accesses.\nfunc accessBitfields() {\n\tvar x C.bitfield_t\n\tx.start = 3\n\tx.set_bitfield_a(4)\n\tx.set_bitfield_b(1)\n\tx.set_bitfield_c(2)\n\tx.d = 10\n\tx.e = 5\n\tvar _ C.uchar = x.bitfield_a()\n}\n\n// Test union accesses.\nfunc accessUnion() {\n\tvar union1 C.union1_t\n\tunion1.i = 5\n\n\tvar union2d C.union2d_t\n\tvar _ *C.int = union2d.unionfield_i()\n\tvar _ *[2]float64 = union2d.unionfield_d()\n}\n"
  },
  {
    "path": "cgo/testdata/types.out.go",
    "content": "package main\n\nimport \"syscall\"\nimport \"unsafe\"\n\nvar _ unsafe.Pointer\n\n//go:linkname _Cgo_CString runtime.cgo_CString\nfunc _Cgo_CString(string) *_Cgo_char\n\n//go:linkname _Cgo_GoString runtime.cgo_GoString\nfunc _Cgo_GoString(*_Cgo_char) string\n\n//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN\nfunc _Cgo___GoStringN(*_Cgo_char, uintptr) string\n\nfunc _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {\n\treturn _Cgo___GoStringN(cstr, uintptr(length))\n}\n\n//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes\nfunc _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte\n\nfunc _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {\n\treturn _Cgo___GoBytes(ptr, uintptr(length))\n}\n\n//go:linkname _Cgo___CBytes runtime.cgo_CBytes\nfunc _Cgo___CBytes([]byte) unsafe.Pointer\n\nfunc _Cgo_CBytes(b []byte) unsafe.Pointer {\n\treturn _Cgo___CBytes(b)\n}\n\n//go:linkname _Cgo___get_errno_num runtime.cgo_errno\nfunc _Cgo___get_errno_num() uintptr\n\nfunc _Cgo___get_errno() error {\n\treturn syscall.Errno(_Cgo___get_errno_num())\n}\n\ntype (\n\t_Cgo_char      uint8\n\t_Cgo_schar     int8\n\t_Cgo_uchar     uint8\n\t_Cgo_short     int16\n\t_Cgo_ushort    uint16\n\t_Cgo_int       int32\n\t_Cgo_uint      uint32\n\t_Cgo_long      int32\n\t_Cgo_ulong     uint32\n\t_Cgo_longlong  int64\n\t_Cgo_ulonglong uint64\n)\ntype _Cgo_myint = _Cgo_int\ntype _Cgo_struct_point2d_t struct {\n\tx _Cgo_int\n\ty _Cgo_int\n}\ntype _Cgo_point2d_t = _Cgo_struct_point2d_t\ntype _Cgo_struct_point3d struct {\n\tx _Cgo_int\n\ty _Cgo_int\n\tz _Cgo_int\n}\ntype _Cgo_point3d_t = _Cgo_struct_point3d\ntype _Cgo_struct_type1 struct {\n\t_type   _Cgo_int\n\t__type  _Cgo_int\n\t___type _Cgo_int\n}\ntype _Cgo_struct_type2 struct{ _type _Cgo_int }\ntype _Cgo_union_union1_t struct{ i _Cgo_int }\ntype _Cgo_union1_t = _Cgo_union_union1_t\ntype _Cgo_union_union3_t struct{ $union uint64 }\n\nfunc (union *_Cgo_union_union3_t) unionfield_i() *_Cgo_int {\n\treturn (*_Cgo_int)(unsafe.Pointer(&union.$union))\n}\nfunc (union *_Cgo_union_union3_t) unionfield_d() *float64 {\n\treturn (*float64)(unsafe.Pointer(&union.$union))\n}\nfunc (union *_Cgo_union_union3_t) unionfield_s() *_Cgo_short {\n\treturn (*_Cgo_short)(unsafe.Pointer(&union.$union))\n}\n\ntype _Cgo_union3_t = _Cgo_union_union3_t\ntype _Cgo_union_union2d struct{ $union [2]uint64 }\n\nfunc (union *_Cgo_union_union2d) unionfield_i() *_Cgo_int {\n\treturn (*_Cgo_int)(unsafe.Pointer(&union.$union))\n}\nfunc (union *_Cgo_union_union2d) unionfield_d() *[2]float64 {\n\treturn (*[2]float64)(unsafe.Pointer(&union.$union))\n}\n\ntype _Cgo_union2d_t = _Cgo_union_union2d\ntype _Cgo_union_unionarray_t struct{ arr [10]_Cgo_uchar }\ntype _Cgo_unionarray_t = _Cgo_union_unionarray_t\ntype _Cgo__Ctype_union___0 struct{ $union [3]uint32 }\n\nfunc (union *_Cgo__Ctype_union___0) unionfield_area() *_Cgo_point2d_t {\n\treturn (*_Cgo_point2d_t)(unsafe.Pointer(&union.$union))\n}\nfunc (union *_Cgo__Ctype_union___0) unionfield_solid() *_Cgo_point3d_t {\n\treturn (*_Cgo_point3d_t)(unsafe.Pointer(&union.$union))\n}\n\ntype _Cgo_struct_struct_nested_t struct {\n\tbegin _Cgo_point2d_t\n\tend   _Cgo_point2d_t\n\ttag   _Cgo_int\n\n\tcoord _Cgo__Ctype_union___0\n}\ntype _Cgo_struct_nested_t = _Cgo_struct_struct_nested_t\ntype _Cgo_union_union_nested_t struct{ $union [2]uint64 }\n\nfunc (union *_Cgo_union_union_nested_t) unionfield_point() *_Cgo_point3d_t {\n\treturn (*_Cgo_point3d_t)(unsafe.Pointer(&union.$union))\n}\nfunc (union *_Cgo_union_union_nested_t) unionfield_array() *_Cgo_unionarray_t {\n\treturn (*_Cgo_unionarray_t)(unsafe.Pointer(&union.$union))\n}\nfunc (union *_Cgo_union_union_nested_t) unionfield_thing() *_Cgo_union3_t {\n\treturn (*_Cgo_union3_t)(unsafe.Pointer(&union.$union))\n}\n\ntype _Cgo_union_nested_t = _Cgo_union_union_nested_t\ntype _Cgo_enum_option = _Cgo_int\ntype _Cgo_option_t = _Cgo_enum_option\ntype _Cgo_enum_option2_t = _Cgo_uint\ntype _Cgo_option2_t = _Cgo_enum_option2_t\ntype _Cgo_struct_types_t struct {\n\tf   float32\n\td   float64\n\tptr *_Cgo_int\n}\ntype _Cgo_types_t = _Cgo_struct_types_t\ntype _Cgo_myIntArray = [10]_Cgo_int\ntype _Cgo_struct_bitfield_t struct {\n\tstart        _Cgo_uchar\n\t__bitfield_1 _Cgo_uchar\n\n\td _Cgo_uchar\n\te _Cgo_uchar\n}\n\nfunc (s *_Cgo_struct_bitfield_t) bitfield_a() _Cgo_uchar { return s.__bitfield_1 & 0x1f }\nfunc (s *_Cgo_struct_bitfield_t) set_bitfield_a(value _Cgo_uchar) {\n\ts.__bitfield_1 = s.__bitfield_1&^0x1f | value&0x1f<<0\n}\nfunc (s *_Cgo_struct_bitfield_t) bitfield_b() _Cgo_uchar {\n\treturn s.__bitfield_1 >> 5 & 0x1\n}\nfunc (s *_Cgo_struct_bitfield_t) set_bitfield_b(value _Cgo_uchar) {\n\ts.__bitfield_1 = s.__bitfield_1&^0x20 | value&0x1<<5\n}\nfunc (s *_Cgo_struct_bitfield_t) bitfield_c() _Cgo_uchar {\n\treturn s.__bitfield_1 >> 6\n}\nfunc (s *_Cgo_struct_bitfield_t) set_bitfield_c(value _Cgo_uchar,\n\n) { s.__bitfield_1 = s.__bitfield_1&0x3f | value<<6 }\n\ntype _Cgo_bitfield_t = _Cgo_struct_bitfield_t\n"
  },
  {
    "path": "colorwriter.go",
    "content": "package main\n\nimport (\n\t\"io\"\n)\n\n// ANSI escape codes for terminal colors.\nconst (\n\tTermColorReset  = \"\\x1b[0m\"\n\tTermColorYellow = \"\\x1b[93m\"\n)\n\n// ColorWriter wraps an io.Writer but adds a prefix and a terminal color.\ntype ColorWriter struct {\n\tOut    io.Writer\n\tColor  string\n\tPrefix string\n\tline   []byte\n}\n\n// Write implements io.Writer, but with an added prefix and terminal color.\nfunc (w *ColorWriter) Write(p []byte) (n int, err error) {\n\tfor _, c := range p {\n\t\tif c == '\\n' {\n\t\t\tw.line = append(w.line, []byte(TermColorReset)...)\n\t\t\tw.line = append(w.line, '\\n')\n\t\t\t// Write this line.\n\t\t\t_, err := w.Out.Write(w.line)\n\t\t\tw.line = w.line[:0]\n\t\t\tw.line = append(w.line, []byte(w.Color+w.Prefix)...)\n\t\t\tif err != nil {\n\t\t\t\treturn 0, err\n\t\t\t}\n\t\t} else {\n\t\t\tw.line = append(w.line, c)\n\t\t}\n\t}\n\treturn len(p), nil\n}\n"
  },
  {
    "path": "compileopts/config.go",
    "content": "// Package compileopts contains the configuration for a single to-be-built\n// binary.\npackage compileopts\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/google/shlex\"\n\t\"github.com/tinygo-org/tinygo/goenv\"\n)\n\n// Library versions. Whenever an existing library is changed, this number should\n// be added/increased so that existing caches are invalidated.\n//\n// (This is a bit of a layering violation, this should really be part of the\n// builder.Library struct but that's hard to do since we want to know the\n// library path in advance in several places).\nvar libVersions = map[string]int{\n\t\"musl\":  3,\n\t\"bdwgc\": 2,\n}\n\n// Config keeps all configuration affecting the build in a single struct.\ntype Config struct {\n\tOptions        *Options\n\tTarget         *TargetSpec\n\tGoMinorVersion int\n\tTestConfig     TestConfig\n}\n\n// Triple returns the LLVM target triple, like armv6m-unknown-unknown-eabi.\nfunc (c *Config) Triple() string {\n\treturn c.Target.Triple\n}\n\n// CPU returns the LLVM CPU name, like atmega328p or arm7tdmi. It may return an\n// empty string if the CPU name is not known.\nfunc (c *Config) CPU() string {\n\treturn c.Target.CPU\n}\n\n// The current build mode (like the `-buildmode` command line flag).\nfunc (c *Config) BuildMode() string {\n\tif c.Options.BuildMode != \"\" {\n\t\treturn c.Options.BuildMode\n\t}\n\tif c.Target.BuildMode != \"\" {\n\t\treturn c.Target.BuildMode\n\t}\n\treturn \"default\"\n}\n\n// Features returns a list of features this CPU supports. For example, for a\n// RISC-V processor, that could be \"+a,+c,+m\". For many targets, an empty list\n// will be returned.\nfunc (c *Config) Features() string {\n\tif c.Target.Features == \"\" {\n\t\treturn c.Options.LLVMFeatures\n\t}\n\tif c.Options.LLVMFeatures == \"\" {\n\t\treturn c.Target.Features\n\t}\n\treturn c.Target.Features + \",\" + c.Options.LLVMFeatures\n}\n\n// ABI returns the -mabi= flag for this target (like -mabi=lp64). A zero-length\n// string is returned if the target doesn't specify an ABI.\nfunc (c *Config) ABI() string {\n\treturn c.Target.ABI\n}\n\n// GOOS returns the GOOS of the target. This might not always be the actual OS:\n// for example, bare-metal targets will usually pretend to be linux to get the\n// standard library to compile.\nfunc (c *Config) GOOS() string {\n\treturn c.Target.GOOS\n}\n\n// GOARCH returns the GOARCH of the target. This might not always be the actual\n// architecture: for example, the AVR target is not supported by the Go standard\n// library so such targets will usually pretend to be linux/arm.\nfunc (c *Config) GOARCH() string {\n\treturn c.Target.GOARCH\n}\n\n// GOARM will return the GOARM environment variable given to the compiler when\n// building a program.\nfunc (c *Config) GOARM() string {\n\treturn c.Options.GOARM\n}\n\n// GOMIPS will return the GOMIPS environment variable given to the compiler when\n// building a program.\nfunc (c *Config) GOMIPS() string {\n\treturn c.Options.GOMIPS\n}\n\n// BuildTags returns the complete list of build tags used during this build.\nfunc (c *Config) BuildTags() []string {\n\ttags := append([]string(nil), c.Target.BuildTags...) // copy slice (avoid a race)\n\ttags = append(tags, []string{\n\t\t\"tinygo\",                                     // that's the compiler\n\t\t\"purego\",                                     // to get various crypto packages to work\n\t\t\"osusergo\",                                   // to get os/user to work\n\t\t\"math_big_pure_go\",                           // to get math/big to work\n\t\t\"gc.\" + c.GC(), \"scheduler.\" + c.Scheduler(), // used inside the runtime package\n\t\t\"serial.\" + c.Serial()}...) // used inside the machine package\n\tswitch c.Scheduler() {\n\tcase \"threads\", \"cores\":\n\tdefault:\n\t\ttags = append(tags, \"tinygo.unicore\")\n\t}\n\tfor i := 1; i <= c.GoMinorVersion; i++ {\n\t\ttags = append(tags, fmt.Sprintf(\"go1.%d\", i))\n\t}\n\ttags = append(tags, c.Options.Tags...)\n\treturn tags\n}\n\n// GC returns the garbage collection strategy in use on this platform. Valid\n// values are \"none\", \"leaking\", \"conservative\" and \"precise\".\nfunc (c *Config) GC() string {\n\tif c.Options.GC != \"\" {\n\t\treturn c.Options.GC\n\t}\n\tif c.Target.GC != \"\" {\n\t\treturn c.Target.GC\n\t}\n\treturn \"conservative\"\n}\n\n// NeedsStackObjects returns true if the compiler should insert stack objects\n// that can be traced by the garbage collector.\nfunc (c *Config) NeedsStackObjects() bool {\n\tswitch c.GC() {\n\tcase \"conservative\", \"custom\", \"precise\", \"boehm\":\n\t\tfor _, tag := range c.BuildTags() {\n\t\t\tif tag == \"tinygo.wasm\" {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\n\t\treturn false\n\tdefault:\n\t\treturn false\n\t}\n}\n\n// Scheduler returns the scheduler implementation. Valid values are \"none\",\n// \"asyncify\" and \"tasks\".\nfunc (c *Config) Scheduler() string {\n\tif c.Options.Scheduler != \"\" {\n\t\treturn c.Options.Scheduler\n\t}\n\tif c.Target.Scheduler != \"\" {\n\t\treturn c.Target.Scheduler\n\t}\n\t// Fall back to none.\n\treturn \"none\"\n}\n\n// Serial returns the serial implementation for this build configuration: uart,\n// usb (meaning USB-CDC), or none.\nfunc (c *Config) Serial() string {\n\tif c.Options.Serial != \"\" {\n\t\treturn c.Options.Serial\n\t}\n\tif c.Target.Serial != \"\" {\n\t\treturn c.Target.Serial\n\t}\n\treturn \"none\"\n}\n\n// OptLevels returns the optimization level (0-2), size level (0-2), and inliner\n// threshold as used in the LLVM optimization pipeline.\nfunc (c *Config) OptLevel() (level string, speedLevel, sizeLevel int) {\n\tswitch c.Options.Opt {\n\tcase \"none\", \"0\":\n\t\treturn \"O0\", 0, 0\n\tcase \"1\":\n\t\treturn \"O1\", 1, 0\n\tcase \"2\":\n\t\treturn \"O2\", 2, 0\n\tcase \"s\":\n\t\treturn \"Os\", 2, 1\n\tcase \"z\":\n\t\treturn \"Oz\", 2, 2 // default\n\tdefault:\n\t\t// This is not shown to the user: valid choices are already checked as\n\t\t// part of Options.Verify(). It is here as a sanity check.\n\t\tpanic(\"unknown optimization level: -opt=\" + c.Options.Opt)\n\t}\n}\n\n// PanicStrategy returns the panic strategy selected for this target. Valid\n// values are \"print\" (print the panic value, then exit) or \"trap\" (issue a trap\n// instruction).\nfunc (c *Config) PanicStrategy() string {\n\treturn c.Options.PanicStrategy\n}\n\n// AutomaticStackSize returns whether goroutine stack sizes should be determined\n// automatically at compile time, if possible. If it is false, no attempt is\n// made.\nfunc (c *Config) AutomaticStackSize() bool {\n\tif c.Target.AutoStackSize != nil && c.Scheduler() == \"tasks\" {\n\t\treturn *c.Target.AutoStackSize\n\t}\n\treturn false\n}\n\n// StackSize returns the default stack size to be used for goroutines, if the\n// stack size could not be determined automatically at compile time.\nfunc (c *Config) StackSize() uint64 {\n\tif c.Options.StackSize != 0 {\n\t\treturn c.Options.StackSize\n\t}\n\treturn c.Target.DefaultStackSize\n}\n\n// MaxStackAlloc returns the size of the maximum allocation to put on the stack vs heap.\nfunc (c *Config) MaxStackAlloc() uint64 {\n\tif c.StackSize() >= 16*1024 {\n\t\treturn 1024\n\t}\n\n\treturn 256\n}\n\n// RP2040BootPatch returns whether the RP2040 boot patch should be applied that\n// calculates and patches in the checksum for the 2nd stage bootloader.\nfunc (c *Config) RP2040BootPatch() bool {\n\tif c.Target.RP2040BootPatch != nil {\n\t\treturn *c.Target.RP2040BootPatch\n\t}\n\treturn false\n}\n\n// Return a canonicalized architecture name, so we don't have to deal with arm*\n// vs thumb* vs arm64.\nfunc CanonicalArchName(triple string) string {\n\tarch := strings.Split(triple, \"-\")[0]\n\tif arch == \"arm64\" {\n\t\treturn \"aarch64\"\n\t}\n\tif strings.HasPrefix(arch, \"arm\") || strings.HasPrefix(arch, \"thumb\") {\n\t\treturn \"arm\"\n\t}\n\tif arch == \"mipsel\" {\n\t\treturn \"mips\"\n\t}\n\treturn arch\n}\n\n// MuslArchitecture returns the architecture name as used in musl libc. It is\n// usually the same as the first part of the LLVM triple, but not always.\nfunc MuslArchitecture(triple string) string {\n\treturn CanonicalArchName(triple)\n}\n\n// Returns true if the libc needs to include malloc, for the libcs where this\n// matters.\nfunc (c *Config) LibcNeedsMalloc() bool {\n\tif c.GC() == \"boehm\" && c.Target.Libc == \"wasi-libc\" {\n\t\treturn true\n\t}\n\treturn false\n}\n\n// LibraryPath returns the path to the library build directory. The path will be\n// a library path in the cache directory (which might not yet be built).\nfunc (c *Config) LibraryPath(name string) string {\n\tarchname := c.Triple()\n\tif c.CPU() != \"\" {\n\t\tarchname += \"-\" + c.CPU()\n\t}\n\tif c.ABI() != \"\" {\n\t\tarchname += \"-\" + c.ABI()\n\t}\n\tif c.Target.SoftFloat {\n\t\tarchname += \"-softfloat\"\n\t}\n\tif name == \"bdwgc\" {\n\t\t// Boehm GC is compiled against a particular libc.\n\t\tarchname += \"-\" + c.Target.Libc\n\t}\n\n\t// Append a version string, if this library has a version.\n\tif v, ok := libVersions[name]; ok {\n\t\tarchname += \"-v\" + strconv.Itoa(v)\n\t}\n\n\toptions := \"\"\n\tif c.LibcNeedsMalloc() {\n\t\toptions += \"+malloc\"\n\t}\n\n\t// No precompiled library found. Determine the path name that will be used\n\t// in the build cache.\n\treturn filepath.Join(goenv.Get(\"GOCACHE\"), name+options+\"-\"+archname)\n}\n\n// DefaultBinaryExtension returns the default extension for binaries, such as\n// .exe, .wasm, or no extension (depending on the target).\nfunc (c *Config) DefaultBinaryExtension() string {\n\tparts := strings.Split(c.Triple(), \"-\")\n\tif parts[0] == \"wasm32\" {\n\t\t// WebAssembly files always have the .wasm file extension.\n\t\treturn \".wasm\"\n\t}\n\tif len(parts) >= 3 && parts[2] == \"windows\" {\n\t\t// Windows uses .exe.\n\t\treturn \".exe\"\n\t}\n\tif len(parts) >= 3 && parts[2] == \"unknown\" {\n\t\t// There appears to be a convention to use the .elf file extension for\n\t\t// ELF files intended for microcontrollers. I'm not aware of the origin\n\t\t// of this, it's just something that is used by many projects.\n\t\t// I think it's a good tradition, so let's keep it.\n\t\treturn \".elf\"\n\t}\n\t// Linux, MacOS, etc, don't use a file extension. Use it as a fallback.\n\treturn \"\"\n}\n\n// CFlags returns the flags to pass to the C compiler. This is necessary for CGo\n// preprocessing.\nfunc (c *Config) CFlags(libclang bool) []string {\n\tvar cflags []string\n\tfor _, flag := range c.Target.CFlags {\n\t\tcflags = append(cflags, strings.ReplaceAll(flag, \"{root}\", goenv.Get(\"TINYGOROOT\")))\n\t}\n\tresourceDir := goenv.ClangResourceDir(libclang)\n\tif resourceDir != \"\" {\n\t\t// The resource directory contains the built-in clang headers like\n\t\t// stdbool.h, stdint.h, float.h, etc.\n\t\t// It is left empty if we're using an external compiler (that already\n\t\t// knows these headers).\n\t\tcflags = append(cflags,\n\t\t\t\"-resource-dir=\"+resourceDir,\n\t\t)\n\t}\n\tcflags = append(cflags, c.LibcCFlags()...)\n\t// Always emit debug information. It is optionally stripped at link time.\n\tcflags = append(cflags, \"-gdwarf-4\")\n\t// Use the same optimization level as TinyGo.\n\tcflags = append(cflags, \"-O\"+c.Options.Opt)\n\t// Set the LLVM target triple.\n\tcflags = append(cflags, \"--target=\"+c.Triple())\n\t// Set the -mcpu (or similar) flag.\n\tif c.Target.CPU != \"\" {\n\t\tif c.GOARCH() == \"amd64\" || c.GOARCH() == \"386\" {\n\t\t\t// x86 prefers the -march flag (-mcpu is deprecated there).\n\t\t\tcflags = append(cflags, \"-march=\"+c.Target.CPU)\n\t\t} else if strings.HasPrefix(c.Triple(), \"avr\") {\n\t\t\t// AVR MCUs use -mmcu instead of -mcpu.\n\t\t\tcflags = append(cflags, \"-mmcu=\"+c.Target.CPU)\n\t\t} else {\n\t\t\t// The rest just uses -mcpu.\n\t\t\tcflags = append(cflags, \"-mcpu=\"+c.Target.CPU)\n\t\t}\n\t}\n\t// Set the -mabi flag, if needed.\n\tif c.ABI() != \"\" {\n\t\tcflags = append(cflags, \"-mabi=\"+c.ABI())\n\t}\n\treturn cflags\n}\n\n// LibcCFlags returns the C compiler flags for the configured libc.\n// It only uses flags that are part of the libc path (triple, cpu, abi, libc\n// name) so it can safely be used to compile another C library.\nfunc (c *Config) LibcCFlags() []string {\n\tswitch c.Target.Libc {\n\tcase \"darwin-libSystem\":\n\t\troot := goenv.Get(\"TINYGOROOT\")\n\t\treturn []string{\n\t\t\t\"-nostdlibinc\",\n\t\t\t\"-isystem\", filepath.Join(root, \"lib/macos-minimal-sdk/src/usr/include\"),\n\t\t}\n\tcase \"picolibc\":\n\t\troot := goenv.Get(\"TINYGOROOT\")\n\t\tpicolibcDir := filepath.Join(root, \"lib\", \"picolibc\", \"newlib\", \"libc\")\n\t\tpath := c.LibraryPath(\"picolibc\")\n\t\treturn []string{\n\t\t\t\"-nostdlibinc\",\n\t\t\t\"-isystem\", filepath.Join(path, \"include\"),\n\t\t\t\"-isystem\", filepath.Join(picolibcDir, \"include\"),\n\t\t\t\"-isystem\", filepath.Join(picolibcDir, \"tinystdio\"),\n\t\t\t\"-D__PICOLIBC_ERRNO_FUNCTION=__errno_location\",\n\t\t}\n\tcase \"musl\":\n\t\troot := goenv.Get(\"TINYGOROOT\")\n\t\tpath := c.LibraryPath(\"musl\")\n\t\tarch := MuslArchitecture(c.Triple())\n\t\treturn []string{\n\t\t\t\"-nostdlibinc\",\n\t\t\t\"-isystem\", filepath.Join(path, \"include\"),\n\t\t\t\"-isystem\", filepath.Join(root, \"lib\", \"musl\", \"arch\", arch),\n\t\t\t\"-isystem\", filepath.Join(root, \"lib\", \"musl\", \"arch\", \"generic\"),\n\t\t\t\"-isystem\", filepath.Join(root, \"lib\", \"musl\", \"include\"),\n\t\t}\n\tcase \"wasi-libc\":\n\t\tpath := c.LibraryPath(\"wasi-libc\")\n\t\treturn []string{\n\t\t\t\"-nostdlibinc\",\n\t\t\t\"-isystem\", filepath.Join(path, \"include\"),\n\t\t}\n\tcase \"wasmbuiltins\":\n\t\t// nothing to add (library is purely for builtins)\n\t\treturn nil\n\tcase \"mingw-w64\":\n\t\troot := goenv.Get(\"TINYGOROOT\")\n\t\tpath := c.LibraryPath(\"mingw-w64\")\n\t\tcflags := []string{\n\t\t\t\"-nostdlibinc\",\n\t\t\t\"-isystem\", filepath.Join(path, \"include\"),\n\t\t\t\"-isystem\", filepath.Join(root, \"lib\", \"mingw-w64\", \"mingw-w64-headers\", \"crt\"),\n\t\t\t\"-isystem\", filepath.Join(root, \"lib\", \"mingw-w64\", \"mingw-w64-headers\", \"include\"),\n\t\t\t\"-isystem\", filepath.Join(root, \"lib\", \"mingw-w64\", \"mingw-w64-headers\", \"defaults\", \"include\"),\n\t\t}\n\t\tif c.GOARCH() == \"386\" {\n\t\t\tcflags = append(cflags,\n\t\t\t\t\"-D__MSVCRT_VERSION__=0x700\", // Microsoft Visual C++ .NET 2002\n\t\t\t\t\"-D_WIN32_WINNT=0x0501\",      // target Windows XP\n\t\t\t)\n\t\t} else {\n\t\t\tcflags = append(cflags,\n\t\t\t\t\"-D_UCRT\",\n\t\t\t\t\"-D_WIN32_WINNT=0x0a00\", // target Windows 10\n\t\t\t)\n\t\t}\n\t\treturn cflags\n\tcase \"\":\n\t\t// No libc specified, nothing to add.\n\t\treturn nil\n\tdefault:\n\t\t// Incorrect configuration. This could be handled in a better way, but\n\t\t// usually this will be found by developers (not by TinyGo users).\n\t\tpanic(\"unknown libc: \" + c.Target.Libc)\n\t}\n}\n\n// LDFlags returns the flags to pass to the linker. A few more flags are needed\n// (like the one for the compiler runtime), but this represents the majority of\n// the flags.\nfunc (c *Config) LDFlags() []string {\n\troot := goenv.Get(\"TINYGOROOT\")\n\t// Merge and adjust LDFlags.\n\tvar ldflags []string\n\tfor _, flag := range c.Target.LDFlags {\n\t\tldflags = append(ldflags, strings.ReplaceAll(flag, \"{root}\", root))\n\t}\n\tldflags = append(ldflags, \"-L\", root)\n\tif c.Target.LinkerScript != \"\" {\n\t\tldflags = append(ldflags, \"-T\", c.Target.LinkerScript)\n\t}\n\tldflags = append(ldflags, c.Options.ExtLDFlags...)\n\n\treturn ldflags\n}\n\n// ExtraFiles returns the list of extra files to be built and linked with the\n// executable. This can include extra C and assembly files.\nfunc (c *Config) ExtraFiles() []string {\n\treturn c.Target.ExtraFiles\n}\n\n// DumpSSA returns whether to dump Go SSA while compiling (-dumpssa flag). Only\n// enable this for debugging.\nfunc (c *Config) DumpSSA() bool {\n\treturn c.Options.DumpSSA\n}\n\n// VerifyIR returns whether to run extra checks on the IR. This is normally\n// disabled but enabled during testing.\nfunc (c *Config) VerifyIR() bool {\n\treturn c.Options.VerifyIR\n}\n\n// Debug returns whether debug (DWARF) information should be retained by the\n// linker. By default, debug information is retained, but it can be removed\n// with the -no-debug flag.\nfunc (c *Config) Debug() bool {\n\treturn c.Options.Debug\n}\n\n// BinaryFormat returns an appropriate binary format, based on the file\n// extension and the configured binary format in the target JSON file.\nfunc (c *Config) BinaryFormat(ext string) string {\n\tswitch ext {\n\tcase \".bin\", \".gba\", \".nro\":\n\t\t// The simplest format possible: dump everything in a raw binary file.\n\t\tif c.Target.BinaryFormat != \"\" {\n\t\t\treturn c.Target.BinaryFormat\n\t\t}\n\t\treturn \"bin\"\n\tcase \".img\":\n\t\t// Image file. Only defined for the ESP32 at the moment, where it is a\n\t\t// full (runnable) image that can be used in the Espressif QEMU fork.\n\t\tif c.Target.BinaryFormat != \"\" {\n\t\t\treturn c.Target.BinaryFormat + \"-img\"\n\t\t}\n\t\treturn \"bin\"\n\tcase \".hex\":\n\t\t// Similar to bin, but includes the start address and is thus usually a\n\t\t// better format.\n\t\treturn \"hex\"\n\tcase \".uf2\":\n\t\t// Special purpose firmware format, mainly used on Adafruit boards.\n\t\t// More information:\n\t\t// https://github.com/Microsoft/uf2\n\t\treturn \"uf2\"\n\tcase \".zip\":\n\t\tif c.Target.BinaryFormat != \"\" {\n\t\t\treturn c.Target.BinaryFormat\n\t\t}\n\t\treturn \"zip\"\n\tdefault:\n\t\t// Use the ELF format for unrecognized file formats.\n\t\treturn \"elf\"\n\t}\n}\n\n// Programmer returns the flash method and OpenOCD interface name given a\n// particular configuration. It may either be all configured in the target JSON\n// file or be modified using the -programmer command-line option.\nfunc (c *Config) Programmer() (method, openocdInterface string) {\n\tswitch c.Options.Programmer {\n\tcase \"\":\n\t\t// No configuration supplied.\n\t\treturn c.Target.FlashMethod, c.Target.OpenOCDInterface\n\tcase \"openocd\", \"msd\", \"command\":\n\t\t// The -programmer flag only specifies the flash method.\n\t\treturn c.Options.Programmer, c.Target.OpenOCDInterface\n\tcase \"bmp\":\n\t\t// The -programmer flag only specifies the flash method.\n\t\treturn c.Options.Programmer, \"\"\n\tdefault:\n\t\t// The -programmer flag specifies something else, assume it specifies\n\t\t// the OpenOCD interface name.\n\t\treturn \"openocd\", c.Options.Programmer\n\t}\n}\n\n// OpenOCDConfiguration returns a list of command line arguments to OpenOCD.\n// This list of command-line arguments is based on the various OpenOCD-related\n// flags in the target specification.\nfunc (c *Config) OpenOCDConfiguration() (args []string, err error) {\n\t_, openocdInterface := c.Programmer()\n\tif openocdInterface == \"\" {\n\t\treturn nil, errors.New(\"OpenOCD programmer not set\")\n\t}\n\tif !regexp.MustCompile(`^[\\p{L}0-9_-]+$`).MatchString(openocdInterface) {\n\t\treturn nil, fmt.Errorf(\"OpenOCD programmer has an invalid name: %#v\", openocdInterface)\n\t}\n\tif c.Target.OpenOCDTarget == \"\" {\n\t\treturn nil, errors.New(\"OpenOCD chip not set\")\n\t}\n\tif !regexp.MustCompile(`^[\\p{L}0-9_-]+$`).MatchString(c.Target.OpenOCDTarget) {\n\t\treturn nil, fmt.Errorf(\"OpenOCD target has an invalid name: %#v\", c.Target.OpenOCDTarget)\n\t}\n\tif c.Target.OpenOCDTransport != \"\" && c.Target.OpenOCDTransport != \"swd\" {\n\t\treturn nil, fmt.Errorf(\"unknown OpenOCD transport: %#v\", c.Target.OpenOCDTransport)\n\t}\n\targs = []string{\"-f\", \"interface/\" + openocdInterface + \".cfg\"}\n\tif c.Target.OpenOCDTransport != \"\" {\n\t\ttransport := c.Target.OpenOCDTransport\n\t\tif transport == \"swd\" {\n\t\t\tswitch openocdInterface {\n\t\t\tcase \"stlink-dap\":\n\t\t\t\ttransport = \"dapdirect_swd\"\n\t\t\t}\n\t\t}\n\t\targs = append(args, \"-c\", \"transport select \"+transport)\n\t}\n\targs = append(args, \"-f\", \"target/\"+c.Target.OpenOCDTarget+\".cfg\")\n\tfor _, cmd := range c.Target.OpenOCDCommands {\n\t\targs = append(args, \"-c\", cmd)\n\t}\n\treturn args, nil\n}\n\n// CodeModel returns the code model used on this platform.\nfunc (c *Config) CodeModel() string {\n\tif c.Target.CodeModel != \"\" {\n\t\treturn c.Target.CodeModel\n\t}\n\n\treturn \"default\"\n}\n\n// RelocationModel returns the relocation model in use on this platform. Valid\n// values are \"static\", \"pic\", \"dynamicnopic\".\nfunc (c *Config) RelocationModel() string {\n\tif c.Target.RelocationModel != \"\" {\n\t\treturn c.Target.RelocationModel\n\t}\n\n\treturn \"static\"\n}\n\n// EmulatorName is a shorthand to get the command for this emulator, something\n// like qemu-system-arm or simavr.\nfunc (c *Config) EmulatorName() string {\n\tparts := strings.SplitN(c.Target.Emulator, \" \", 2)\n\tif len(parts) > 1 {\n\t\treturn parts[0]\n\t}\n\treturn \"\"\n}\n\n// EmulatorFormat returns the binary format for the emulator and the associated\n// file extension. An empty string means to pass directly whatever the linker\n// produces directly without conversion (usually ELF format).\nfunc (c *Config) EmulatorFormat() (format, fileExt string) {\n\tswitch {\n\tcase strings.Contains(c.Target.Emulator, \"{img}\"):\n\t\treturn \"img\", \".img\"\n\tdefault:\n\t\treturn \"\", \"\"\n\t}\n}\n\n// Emulator returns a ready-to-run command to run the given binary in an\n// emulator. Give it the format (returned by EmulatorFormat()) and the path to\n// the compiled binary.\nfunc (c *Config) Emulator(format, binary string) ([]string, error) {\n\tparts, err := shlex.Split(c.Target.Emulator)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"could not parse emulator command: %w\", err)\n\t}\n\tvar emulator []string\n\tfor _, s := range parts {\n\t\ts = strings.ReplaceAll(s, \"{root}\", goenv.Get(\"TINYGOROOT\"))\n\t\t// Allow replacement of what's usually /tmp except notably Windows.\n\t\ts = strings.ReplaceAll(s, \"{tmpDir}\", os.TempDir())\n\t\ts = strings.ReplaceAll(s, \"{\"+format+\"}\", binary)\n\t\temulator = append(emulator, s)\n\t}\n\treturn emulator, nil\n}\n\ntype TestConfig struct {\n\tCompileTestBinary bool\n\tCompileOnly       bool\n\tVerbose           bool\n\tShort             bool\n\tRunRegexp         string\n\tSkipRegexp        string\n\tCount             *int\n\tBenchRegexp       string\n\tBenchTime         string\n\tBenchMem          bool\n\tShuffle           string\n}\n"
  },
  {
    "path": "compileopts/options.go",
    "content": "package compileopts\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strings\"\n\t\"time\"\n)\n\nvar (\n\tvalidBuildModeOptions     = []string{\"default\", \"c-shared\", \"wasi-legacy\"}\n\tvalidGCOptions            = []string{\"none\", \"leaking\", \"conservative\", \"custom\", \"precise\", \"boehm\"}\n\tvalidSchedulerOptions     = []string{\"none\", \"tasks\", \"asyncify\", \"threads\", \"cores\"}\n\tvalidSerialOptions        = []string{\"none\", \"uart\", \"usb\", \"rtt\"}\n\tvalidPrintSizeOptions     = []string{\"none\", \"short\", \"full\", \"html\"}\n\tvalidPanicStrategyOptions = []string{\"print\", \"trap\"}\n\tvalidOptOptions           = []string{\"none\", \"0\", \"1\", \"2\", \"s\", \"z\"}\n)\n\n// Options contains extra options to give to the compiler. These options are\n// usually passed from the command line, but can also be passed in environment\n// variables for example.\ntype Options struct {\n\tGOOS            string // environment variable\n\tGOARCH          string // environment variable\n\tGOARM           string // environment variable (only used with GOARCH=arm)\n\tGOMIPS          string // environment variable (only used with GOARCH=mips and GOARCH=mipsle)\n\tDirectory       string // working dir, leave it unset to use the current working dir\n\tTarget          string\n\tBuildMode       string // -buildmode flag\n\tOpt             string\n\tGC              string\n\tPanicStrategy   string\n\tScheduler       string\n\tStackSize       uint64 // goroutine stack size (if none could be automatically determined)\n\tSerial          string\n\tWork            bool // -work flag to print temporary build directory\n\tInterpTimeout   time.Duration\n\tPrintIR         bool\n\tDumpSSA         bool\n\tVerifyIR        bool\n\tSkipDWARF       bool\n\tPrintCommands   func(cmd string, args ...string) `json:\"-\"`\n\tSemaphore       chan struct{}                    `json:\"-\"` // -p flag controls cap\n\tDebug           bool\n\tNobounds        bool\n\tPrintSizes      string\n\tPrintAllocs     *regexp.Regexp // regexp string\n\tPrintStacks     bool\n\tTags            []string\n\tGlobalValues    map[string]map[string]string // map[pkgpath]map[varname]value\n\tTestConfig      TestConfig\n\tProgrammer      string\n\tOpenOCDCommands []string\n\tLLVMFeatures    string\n\tMonitor         bool\n\tBaudRate        int\n\tTimeout         time.Duration\n\tWITPackage      string // pass through to wasm-tools component embed invocation\n\tWITWorld        string // pass through to wasm-tools component embed -w option\n\tExtLDFlags      []string\n\tGoCompatibility bool // enable to check for Go version compatibility\n}\n\n// Verify performs a validation on the given options, raising an error if options are not valid.\nfunc (o *Options) Verify() error {\n\tif o.BuildMode != \"\" {\n\t\tvalid := isInArray(validBuildModeOptions, o.BuildMode)\n\t\tif !valid {\n\t\t\treturn fmt.Errorf(`invalid buildmode option '%s': valid values are %s`,\n\t\t\t\to.BuildMode,\n\t\t\t\tstrings.Join(validBuildModeOptions, \", \"))\n\t\t}\n\t}\n\tif o.GC != \"\" {\n\t\tvalid := isInArray(validGCOptions, o.GC)\n\t\tif !valid {\n\t\t\treturn fmt.Errorf(`invalid gc option '%s': valid values are %s`,\n\t\t\t\to.GC,\n\t\t\t\tstrings.Join(validGCOptions, \", \"))\n\t\t}\n\t}\n\n\tif o.Scheduler != \"\" {\n\t\tvalid := isInArray(validSchedulerOptions, o.Scheduler)\n\t\tif !valid {\n\t\t\treturn fmt.Errorf(`invalid scheduler option '%s': valid values are %s`,\n\t\t\t\to.Scheduler,\n\t\t\t\tstrings.Join(validSchedulerOptions, \", \"))\n\t\t}\n\t}\n\n\tif o.Serial != \"\" {\n\t\tvalid := isInArray(validSerialOptions, o.Serial)\n\t\tif !valid {\n\t\t\treturn fmt.Errorf(`invalid serial option '%s': valid values are %s`,\n\t\t\t\to.Serial,\n\t\t\t\tstrings.Join(validSerialOptions, \", \"))\n\t\t}\n\t}\n\n\tif o.PrintSizes != \"\" {\n\t\tvalid := isInArray(validPrintSizeOptions, o.PrintSizes)\n\t\tif !valid {\n\t\t\treturn fmt.Errorf(`invalid size option '%s': valid values are %s`,\n\t\t\t\to.PrintSizes,\n\t\t\t\tstrings.Join(validPrintSizeOptions, \", \"))\n\t\t}\n\t}\n\n\tif o.PanicStrategy != \"\" {\n\t\tvalid := isInArray(validPanicStrategyOptions, o.PanicStrategy)\n\t\tif !valid {\n\t\t\treturn fmt.Errorf(`invalid panic option '%s': valid values are %s`,\n\t\t\t\to.PanicStrategy,\n\t\t\t\tstrings.Join(validPanicStrategyOptions, \", \"))\n\t\t}\n\t}\n\n\tif o.Opt != \"\" {\n\t\tif !isInArray(validOptOptions, o.Opt) {\n\t\t\treturn fmt.Errorf(\"invalid -opt=%s: valid values are %s\", o.Opt, strings.Join(validOptOptions, \", \"))\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc isInArray(arr []string, item string) bool {\n\tfor _, i := range arr {\n\t\tif i == item {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "compileopts/options_test.go",
    "content": "package compileopts_test\n\nimport (\n\t\"errors\"\n\t\"testing\"\n\n\t\"github.com/tinygo-org/tinygo/compileopts\"\n)\n\nfunc TestVerifyOptions(t *testing.T) {\n\n\texpectedGCError := errors.New(`invalid gc option 'incorrect': valid values are none, leaking, conservative, custom, precise, boehm`)\n\texpectedSchedulerError := errors.New(`invalid scheduler option 'incorrect': valid values are none, tasks, asyncify, threads, cores`)\n\texpectedPrintSizeError := errors.New(`invalid size option 'incorrect': valid values are none, short, full, html`)\n\texpectedPanicStrategyError := errors.New(`invalid panic option 'incorrect': valid values are print, trap`)\n\n\ttestCases := []struct {\n\t\tname          string\n\t\topts          compileopts.Options\n\t\texpectedError error\n\t}{\n\t\t{\n\t\t\tname: \"OptionsEmpty\",\n\t\t\topts: compileopts.Options{},\n\t\t},\n\t\t{\n\t\t\tname: \"InvalidGCOption\",\n\t\t\topts: compileopts.Options{\n\t\t\t\tGC: \"incorrect\",\n\t\t\t},\n\t\t\texpectedError: expectedGCError,\n\t\t},\n\t\t{\n\t\t\tname: \"GCOptionNone\",\n\t\t\topts: compileopts.Options{\n\t\t\t\tGC: \"none\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"GCOptionLeaking\",\n\t\t\topts: compileopts.Options{\n\t\t\t\tGC: \"leaking\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"GCOptionConservative\",\n\t\t\topts: compileopts.Options{\n\t\t\t\tGC: \"conservative\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"GCOptionCustom\",\n\t\t\topts: compileopts.Options{\n\t\t\t\tGC: \"custom\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"InvalidSchedulerOption\",\n\t\t\topts: compileopts.Options{\n\t\t\t\tScheduler: \"incorrect\",\n\t\t\t},\n\t\t\texpectedError: expectedSchedulerError,\n\t\t},\n\t\t{\n\t\t\tname: \"SchedulerOptionNone\",\n\t\t\topts: compileopts.Options{\n\t\t\t\tScheduler: \"none\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"SchedulerOptionTasks\",\n\t\t\topts: compileopts.Options{\n\t\t\t\tScheduler: \"tasks\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"InvalidPrintSizeOption\",\n\t\t\topts: compileopts.Options{\n\t\t\t\tPrintSizes: \"incorrect\",\n\t\t\t},\n\t\t\texpectedError: expectedPrintSizeError,\n\t\t},\n\t\t{\n\t\t\tname: \"PrintSizeOptionNone\",\n\t\t\topts: compileopts.Options{\n\t\t\t\tPrintSizes: \"none\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"PrintSizeOptionShort\",\n\t\t\topts: compileopts.Options{\n\t\t\t\tPrintSizes: \"short\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"PrintSizeOptionFull\",\n\t\t\topts: compileopts.Options{\n\t\t\t\tPrintSizes: \"full\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"InvalidPanicOption\",\n\t\t\topts: compileopts.Options{\n\t\t\t\tPanicStrategy: \"incorrect\",\n\t\t\t},\n\t\t\texpectedError: expectedPanicStrategyError,\n\t\t},\n\t\t{\n\t\t\tname: \"PanicOptionPrint\",\n\t\t\topts: compileopts.Options{\n\t\t\t\tPanicStrategy: \"print\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"PanicOptionTrap\",\n\t\t\topts: compileopts.Options{\n\t\t\t\tPanicStrategy: \"trap\",\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\terr := tc.opts.Verify()\n\t\t\tif tc.expectedError != err {\n\t\t\t\tif tc.expectedError.Error() != err.Error() {\n\t\t\t\t\tt.Errorf(\"expected %v, got %v\", tc.expectedError, err)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "compileopts/target.go",
    "content": "package compileopts\n\n// This file loads a target specification from a JSON file.\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"runtime\"\n\t\"strings\"\n\n\t\"github.com/tinygo-org/tinygo/goenv\"\n)\n\n// Target specification for a given target. Used for bare metal targets.\n//\n// The target specification is mostly inspired by Rust:\n// https://doc.rust-lang.org/nightly/nightly-rustc/rustc_target/spec/struct.TargetOptions.html\n// https://github.com/shepmaster/rust-arduino-blink-led-no-core-with-cargo/blob/master/blink/arduino.json\ntype TargetSpec struct {\n\tInherits         []string `json:\"inherits,omitempty\"`\n\tTriple           string   `json:\"llvm-target,omitempty\"`\n\tCPU              string   `json:\"cpu,omitempty\"`\n\tABI              string   `json:\"target-abi,omitempty\"` // roughly equivalent to -mabi= flag\n\tFeatures         string   `json:\"features,omitempty\"`\n\tGOOS             string   `json:\"goos,omitempty\"`\n\tGOARCH           string   `json:\"goarch,omitempty\"`\n\tSoftFloat        bool     // used for non-baremetal systems (GOMIPS=softfloat etc)\n\tBuildTags        []string `json:\"build-tags,omitempty\"`\n\tBuildMode        string   `json:\"buildmode,omitempty\"` // default build mode (if nothing specified)\n\tGC               string   `json:\"gc,omitempty\"`\n\tScheduler        string   `json:\"scheduler,omitempty\"`\n\tSerial           string   `json:\"serial,omitempty\"` // which serial output to use (uart, usb, none)\n\tLinker           string   `json:\"linker,omitempty\"`\n\tRTLib            string   `json:\"rtlib,omitempty\"` // compiler runtime library (libgcc, compiler-rt)\n\tLibc             string   `json:\"libc,omitempty\"`\n\tAutoStackSize    *bool    `json:\"automatic-stack-size,omitempty\"` // Determine stack size automatically at compile time.\n\tDefaultStackSize uint64   `json:\"default-stack-size,omitempty\"`   // Default stack size if the size couldn't be determined at compile time.\n\tCFlags           []string `json:\"cflags,omitempty\"`\n\tLDFlags          []string `json:\"ldflags,omitempty\"`\n\tLinkerScript     string   `json:\"linkerscript,omitempty\"`\n\tExtraFiles       []string `json:\"extra-files,omitempty\"`\n\tRP2040BootPatch  *bool    `json:\"rp2040-boot-patch,omitempty\"` // Patch RP2040 2nd stage bootloader checksum\n\tBootPatches      []string `json:\"boot-patches,omitempty\"`      // Bootloader patches to be applied in the order they appear.\n\tEmulator         string   `json:\"emulator,omitempty\"`\n\tFlashCommand     string   `json:\"flash-command,omitempty\"`\n\tGDB              []string `json:\"gdb,omitempty\"`\n\tPortReset        string   `json:\"flash-1200-bps-reset,omitempty\"`\n\tSerialPort       []string `json:\"serial-port,omitempty\"` // serial port IDs in the form \"vid:pid\"\n\tFlashMethod      string   `json:\"flash-method,omitempty\"`\n\tFlashVolume      []string `json:\"msd-volume-name,omitempty\"`\n\tFlashFilename    string   `json:\"msd-firmware-name,omitempty\"`\n\tUF2FamilyID      string   `json:\"uf2-family-id,omitempty\"`\n\tBinaryFormat     string   `json:\"binary-format,omitempty\"`\n\tOpenOCDInterface string   `json:\"openocd-interface,omitempty\"`\n\tOpenOCDTarget    string   `json:\"openocd-target,omitempty\"`\n\tOpenOCDTransport string   `json:\"openocd-transport,omitempty\"`\n\tOpenOCDCommands  []string `json:\"openocd-commands,omitempty\"`\n\tOpenOCDVerify    *bool    `json:\"openocd-verify,omitempty\"` // enable verify when flashing with openocd\n\tJLinkDevice      string   `json:\"jlink-device,omitempty\"`\n\tCodeModel        string   `json:\"code-model,omitempty\"`\n\tRelocationModel  string   `json:\"relocation-model,omitempty\"`\n\tWITPackage       string   `json:\"wit-package,omitempty\"`\n\tWITWorld         string   `json:\"wit-world,omitempty\"`\n}\n\n// overrideProperties overrides all properties that are set in child into itself using reflection.\nfunc (spec *TargetSpec) overrideProperties(child *TargetSpec) error {\n\tspecType := reflect.TypeOf(spec).Elem()\n\tspecValue := reflect.ValueOf(spec).Elem()\n\tchildValue := reflect.ValueOf(child).Elem()\n\n\tfor i := 0; i < specType.NumField(); i++ {\n\t\tfield := specType.Field(i)\n\t\tsrc := childValue.Field(i)\n\t\tdst := specValue.Field(i)\n\n\t\tswitch kind := field.Type.Kind(); kind {\n\t\tcase reflect.String: // for strings, just copy the field of child to spec if not empty\n\t\t\tif src.Len() > 0 {\n\t\t\t\tdst.Set(src)\n\t\t\t}\n\t\tcase reflect.Uint, reflect.Uint32, reflect.Uint64: // for Uint, copy if not zero\n\t\t\tif src.Uint() != 0 {\n\t\t\t\tdst.Set(src)\n\t\t\t}\n\t\tcase reflect.Bool:\n\t\t\tif src.Bool() {\n\t\t\t\tdst.Set(src)\n\t\t\t}\n\t\tcase reflect.Ptr: // for pointers, copy if not nil\n\t\t\tif !src.IsNil() {\n\t\t\t\tdst.Set(src)\n\t\t\t}\n\t\tcase reflect.Slice: // for slices, append the field and check for duplicates\n\t\t\tdst.Set(reflect.AppendSlice(dst, src))\n\t\t\tfor i := 0; i < dst.Len(); i++ {\n\t\t\t\tv := dst.Index(i).String()\n\t\t\t\tfor j := i + 1; j < dst.Len(); j++ {\n\t\t\t\t\tw := dst.Index(j).String()\n\t\t\t\t\tif v == w {\n\t\t\t\t\t\treturn fmt.Errorf(\"duplicate value '%s' in field %s\", v, field.Name)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"unknown field type: %s\", kind)\n\t\t}\n\t}\n\treturn nil\n}\n\n// load reads a target specification from the JSON in the given io.Reader. It\n// may load more targets specified using the \"inherits\" property.\nfunc (spec *TargetSpec) load(r io.Reader) error {\n\terr := json.NewDecoder(r).Decode(spec)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\n// loadFromGivenStr loads the TargetSpec from the given string that could be:\n//   - targets/ directory inside the compiler sources\n//   - a relative or absolute path to custom (project specific) target specification .json file;\n//     the Inherits[] could contain the files from target folder (ex. stm32f4disco)\n//     as well as path to custom files (ex. myAwesomeProject.json)\nfunc (spec *TargetSpec) loadFromGivenStr(str string) error {\n\tpath := \"\"\n\tif strings.HasSuffix(str, \".json\") {\n\t\tpath, _ = filepath.Abs(str)\n\t} else {\n\t\tpath = filepath.Join(goenv.Get(\"TINYGOROOT\"), \"targets\", strings.ToLower(str)+\".json\")\n\t}\n\tfp, err := os.Open(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer fp.Close()\n\treturn spec.load(fp)\n}\n\n// resolveInherits loads inherited targets, recursively.\nfunc (spec *TargetSpec) resolveInherits() error {\n\t// First create a new spec with all the inherited properties.\n\tnewSpec := &TargetSpec{}\n\tfor _, name := range spec.Inherits {\n\t\tsubtarget := &TargetSpec{}\n\t\terr := subtarget.loadFromGivenStr(name)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\terr = subtarget.resolveInherits()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\terr = newSpec.overrideProperties(subtarget)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// When all properties are loaded, make sure they are properly inherited.\n\terr := newSpec.overrideProperties(spec)\n\tif err != nil {\n\t\treturn err\n\t}\n\t*spec = *newSpec\n\n\treturn nil\n}\n\n// Load a target specification.\nfunc LoadTarget(options *Options) (*TargetSpec, error) {\n\tif options.Target == \"\" && options.GOARCH == \"wasm\" {\n\t\t// Set a specific target if we're building from a known GOOS/GOARCH\n\t\t// combination that is defined in a target JSON file.\n\t\tswitch options.GOOS {\n\t\tcase \"js\":\n\t\t\toptions.Target = \"wasm\"\n\t\tcase \"wasip1\":\n\t\t\toptions.Target = \"wasip1\"\n\t\tcase \"wasip2\":\n\t\t\toptions.Target = \"wasip2\"\n\t\tdefault:\n\t\t\treturn nil, errors.New(\"GOARCH=wasm but GOOS is not set correctly. Please set GOOS to js, wasip1, or wasip2.\")\n\t\t}\n\t}\n\n\tif options.Target == \"\" {\n\t\treturn defaultTarget(options)\n\t}\n\n\t// See whether there is a target specification for this target (e.g.\n\t// Arduino).\n\tspec := &TargetSpec{}\n\terr := spec.loadFromGivenStr(options.Target)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t// Successfully loaded this target from a built-in .json file. Make sure\n\t// it includes all parents as specified in the \"inherits\" key.\n\terr = spec.resolveInherits()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"%s : %w\", options.Target, err)\n\t}\n\n\tif spec.Scheduler == \"asyncify\" {\n\t\tspec.ExtraFiles = append(spec.ExtraFiles, \"src/internal/task/task_asyncify_wasm.S\")\n\t}\n\n\treturn spec, nil\n}\n\n// GetTargetSpecs retrieves target specifications from the TINYGOROOT targets\n// directory.  Only valid target JSON files are considered, and the function\n// returns a map of target names to their respective TargetSpec.\nfunc GetTargetSpecs() (map[string]*TargetSpec, error) {\n\tdir := filepath.Join(goenv.Get(\"TINYGOROOT\"), \"targets\")\n\tentries, err := os.ReadDir(dir)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"could not list targets: %w\", err)\n\t}\n\n\tmaps := map[string]*TargetSpec{}\n\tfor _, entry := range entries {\n\t\tentryInfo, err := entry.Info()\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"could not get entry info: %w\", err)\n\t\t}\n\t\tif !entryInfo.Mode().IsRegular() || !strings.HasSuffix(entry.Name(), \".json\") {\n\t\t\t// Only inspect JSON files.\n\t\t\tcontinue\n\t\t}\n\t\tpath := filepath.Join(dir, entry.Name())\n\t\tspec, err := LoadTarget(&Options{Target: path})\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"could not list target: %w\", err)\n\t\t}\n\t\tif spec.FlashMethod == \"\" && spec.FlashCommand == \"\" && spec.Emulator == \"\" {\n\t\t\t// This doesn't look like a regular target file, but rather like\n\t\t\t// a parent target (such as targets/cortex-m.json).\n\t\t\tcontinue\n\t\t}\n\t\tname := entry.Name()\n\t\tname = name[:len(name)-5]\n\t\tmaps[name] = spec\n\t}\n\treturn maps, nil\n}\n\n// Load a target from environment variables (which default to\n// runtime.GOOS/runtime.GOARCH).\nfunc defaultTarget(options *Options) (*TargetSpec, error) {\n\tspec := TargetSpec{\n\t\tGOOS:             options.GOOS,\n\t\tGOARCH:           options.GOARCH,\n\t\tBuildTags:        []string{options.GOOS, options.GOARCH},\n\t\tLinker:           \"cc\",\n\t\tDefaultStackSize: 1024 * 64, // 64kB\n\t\tGDB:              []string{\"gdb\"},\n\t\tPortReset:        \"false\",\n\t}\n\n\t// Configure target based on GOARCH.\n\tvar llvmarch string\n\tswitch options.GOARCH {\n\tcase \"386\":\n\t\tllvmarch = \"i386\"\n\t\tspec.CPU = \"pentium4\"\n\t\tspec.Features = \"+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87\"\n\tcase \"amd64\":\n\t\tllvmarch = \"x86_64\"\n\t\tspec.CPU = \"x86-64\"\n\t\tspec.Features = \"+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87\"\n\tcase \"arm\":\n\t\tspec.CPU = \"generic\"\n\t\tspec.CFlags = append(spec.CFlags, \"-fno-unwind-tables\", \"-fno-asynchronous-unwind-tables\")\n\t\tsubarch := strings.Split(options.GOARM, \",\")\n\t\tif len(subarch) > 2 {\n\t\t\treturn nil, fmt.Errorf(\"invalid GOARM=%s, must be of form <num>,[hardfloat|softfloat]\", options.GOARM)\n\t\t}\n\t\tarchLevel := subarch[0]\n\t\tvar fpu string\n\t\tif len(subarch) >= 2 {\n\t\t\tfpu = subarch[1]\n\t\t} else {\n\t\t\t// Pick the default fpu value: softfloat for armv5 and hardfloat\n\t\t\t// above that.\n\t\t\tif archLevel == \"5\" {\n\t\t\t\tfpu = \"softfloat\"\n\t\t\t} else {\n\t\t\t\tfpu = \"hardfloat\"\n\t\t\t}\n\t\t}\n\t\tswitch fpu {\n\t\tcase \"softfloat\":\n\t\t\tspec.CFlags = append(spec.CFlags, \"-msoft-float\")\n\t\t\tspec.SoftFloat = true\n\t\tcase \"hardfloat\":\n\t\t\t// Hardware floating point support is the default everywhere except\n\t\t\t// on ARMv5 where it needs to be enabled explicitly.\n\t\t\tif archLevel == \"5\" {\n\t\t\t\tspec.CFlags = append(spec.CFlags, \"-mfpu=vfpv2\")\n\t\t\t}\n\t\tdefault:\n\t\t\treturn nil, fmt.Errorf(\"invalid extension GOARM=%s, must be softfloat or hardfloat\", options.GOARM)\n\t\t}\n\t\tswitch archLevel {\n\t\tcase \"5\":\n\t\t\tllvmarch = \"armv5\"\n\t\t\tif spec.SoftFloat {\n\t\t\t\tspec.Features = \"+armv5t,+soft-float,+strict-align,-aes,-bf16,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-mve,-mve.fp,-neon,-sha2,-thumb-mode,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp\"\n\t\t\t} else {\n\t\t\t\tspec.Features = \"+armv5t,+fp64,+strict-align,+vfp2,+vfp2sp,-aes,-d32,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fullfp16,-neon,-sha2,-thumb-mode,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp\"\n\t\t\t}\n\t\tcase \"6\":\n\t\t\tllvmarch = \"armv6\"\n\t\t\tif spec.SoftFloat {\n\t\t\t\tspec.Features = \"+armv6,+dsp,+soft-float,+strict-align,-aes,-bf16,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-mve,-mve.fp,-neon,-sha2,-thumb-mode,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp\"\n\t\t\t} else {\n\t\t\t\tspec.Features = \"+armv6,+dsp,+fp64,+strict-align,+vfp2,+vfp2sp,-aes,-d32,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fullfp16,-neon,-sha2,-thumb-mode,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp\"\n\t\t\t}\n\t\tcase \"7\":\n\t\t\tllvmarch = \"armv7\"\n\t\t\tif spec.SoftFloat {\n\t\t\t\tspec.Features = \"+armv7-a,+dsp,+soft-float,-aes,-bf16,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-mve,-mve.fp,-neon,-sha2,-thumb-mode,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp\"\n\t\t\t} else {\n\t\t\t\tspec.Features = \"+armv7-a,+d32,+dsp,+fp64,+neon,+vfp2,+vfp2sp,+vfp3,+vfp3d16,+vfp3d16sp,+vfp3sp,-aes,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fullfp16,-sha2,-thumb-mode,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp\"\n\t\t\t}\n\t\tdefault:\n\t\t\treturn nil, fmt.Errorf(\"invalid GOARM=%s, must be of form <num>,[hardfloat|softfloat] where num is 5, 6, or 7\", options.GOARM)\n\t\t}\n\tcase \"arm64\":\n\t\tspec.CPU = \"generic\"\n\t\tllvmarch = \"aarch64\"\n\t\tif options.GOOS == \"darwin\" {\n\t\t\tspec.Features = \"+ete,+fp-armv8,+neon,+trbe,+v8a\"\n\t\t\t// Looks like Apple prefers to call this architecture ARM64\n\t\t\t// instead of AArch64.\n\t\t\tllvmarch = \"arm64\"\n\t\t} else if options.GOOS == \"windows\" {\n\t\t\tspec.Features = \"+ete,+fp-armv8,+neon,+trbe,+v8a,-fmv\"\n\t\t} else { // linux\n\t\t\tspec.Features = \"+ete,+fp-armv8,+neon,+trbe,+v8a,-fmv,-outline-atomics\"\n\t\t}\n\tcase \"mips\", \"mipsle\":\n\t\tspec.CPU = \"mips32\"\n\t\tspec.CFlags = append(spec.CFlags, \"-fno-pic\")\n\t\tif options.GOARCH == \"mips\" {\n\t\t\tllvmarch = \"mips\" // big endian\n\t\t} else {\n\t\t\tllvmarch = \"mipsel\" // little endian\n\t\t}\n\t\tswitch options.GOMIPS {\n\t\tcase \"hardfloat\":\n\t\t\tspec.Features = \"+fpxx,+mips32,+nooddspreg,-noabicalls\"\n\t\tcase \"softfloat\":\n\t\t\tspec.SoftFloat = true\n\t\t\tspec.Features = \"+mips32,+soft-float,-noabicalls\"\n\t\t\tspec.CFlags = append(spec.CFlags, \"-msoft-float\")\n\t\tdefault:\n\t\t\treturn nil, fmt.Errorf(\"invalid GOMIPS=%s: must be hardfloat or softfloat\", options.GOMIPS)\n\t\t}\n\tcase \"wasm\":\n\t\treturn nil, fmt.Errorf(\"GOARCH=wasm but GOOS is unset. Please set GOOS to js, wasip1, or wasip2.\")\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unknown GOARCH=%s\", options.GOARCH)\n\t}\n\n\t// Configure target based on GOOS.\n\tllvmos := options.GOOS\n\tllvmvendor := \"unknown\"\n\tswitch options.GOOS {\n\tcase \"darwin\":\n\t\tspec.GC = \"boehm\"\n\t\tplatformVersion := \"10.12.0\"\n\t\tif options.GOARCH == \"arm64\" {\n\t\t\tplatformVersion = \"11.0.0\" // first macosx platform with arm64 support\n\t\t}\n\t\tllvmvendor = \"apple\"\n\t\tspec.Scheduler = \"threads\"\n\t\tspec.Linker = \"ld.lld\"\n\t\tspec.Libc = \"darwin-libSystem\"\n\t\t// Use macosx* instead of darwin, otherwise darwin/arm64 will refer to\n\t\t// iOS!\n\t\tllvmos = \"macosx\" + platformVersion\n\t\tspec.LDFlags = append(spec.LDFlags,\n\t\t\t\"-flavor\", \"darwin\",\n\t\t\t\"-dead_strip\",\n\t\t\t\"-arch\", llvmarch,\n\t\t\t\"-platform_version\", \"macos\", platformVersion, platformVersion,\n\t\t)\n\t\tspec.ExtraFiles = append(spec.ExtraFiles,\n\t\t\t\"src/internal/futex/futex_darwin.c\",\n\t\t\t\"src/internal/task/task_threads.c\",\n\t\t\t\"src/runtime/os_darwin.c\",\n\t\t\t\"src/runtime/runtime_unix.c\",\n\t\t\t\"src/runtime/signal.c\")\n\tcase \"linux\":\n\t\tspec.GC = \"boehm\"\n\t\tspec.Scheduler = \"threads\"\n\t\tspec.Linker = \"ld.lld\"\n\t\tspec.RTLib = \"compiler-rt\"\n\t\tspec.Libc = \"musl\"\n\t\tspec.LDFlags = append(spec.LDFlags, \"--gc-sections\")\n\t\tif options.GOARCH == \"arm64\" {\n\t\t\t// Disable outline atomics. For details, see:\n\t\t\t// https://cpufun.substack.com/p/atomics-in-aarch64\n\t\t\t// A better way would be to fully support outline atomics, which\n\t\t\t// makes atomics slightly more efficient on systems with many cores.\n\t\t\t// But the instructions are only supported on newer aarch64 CPUs, so\n\t\t\t// this feature is normally put in a system library which does\n\t\t\t// feature detection for you.\n\t\t\t// We take the lazy way out and simply disable this feature, instead\n\t\t\t// of enabling it in compiler-rt (which is a bit more complicated).\n\t\t\t// We don't really need this feature anyway as we don't even support\n\t\t\t// proper threading.\n\t\t\tspec.CFlags = append(spec.CFlags, \"-mno-outline-atomics\")\n\t\t}\n\t\tspec.ExtraFiles = append(spec.ExtraFiles,\n\t\t\t\"src/internal/futex/futex_linux.c\",\n\t\t\t\"src/internal/task/task_threads.c\",\n\t\t\t\"src/runtime/runtime_unix.c\",\n\t\t\t\"src/runtime/signal.c\")\n\tcase \"windows\":\n\t\tspec.GC = \"boehm\"\n\t\tspec.Scheduler = \"tasks\"\n\t\tspec.Linker = \"ld.lld\"\n\t\tspec.Libc = \"mingw-w64\"\n\t\tswitch options.GOARCH {\n\t\tcase \"386\":\n\t\t\tspec.LDFlags = append(spec.LDFlags,\n\t\t\t\t\"-m\", \"i386pe\",\n\t\t\t\t\"--major-os-version\", \"4\",\n\t\t\t\t\"--major-subsystem-version\", \"4\",\n\t\t\t)\n\t\t\t// __udivdi3 is not present in ucrt it seems.\n\t\t\tspec.RTLib = \"compiler-rt\"\n\t\tcase \"amd64\":\n\t\t\t// Note: using a medium code model, low image base and no ASLR\n\t\t\t// because Go doesn't really need those features. ASLR patches\n\t\t\t// around issues for unsafe languages like C/C++ that are not\n\t\t\t// normally present in Go (without explicitly opting in).\n\t\t\t// For more discussion:\n\t\t\t// https://groups.google.com/g/Golang-nuts/c/Jd9tlNc6jUE/m/Zo-7zIP_m3MJ?pli=1\n\t\t\tspec.LDFlags = append(spec.LDFlags,\n\t\t\t\t\"-m\", \"i386pep\",\n\t\t\t\t\"--image-base\", \"0x400000\",\n\t\t\t)\n\t\tcase \"arm64\":\n\t\t\tspec.LDFlags = append(spec.LDFlags,\n\t\t\t\t\"-m\", \"arm64pe\",\n\t\t\t)\n\t\t}\n\t\tspec.LDFlags = append(spec.LDFlags,\n\t\t\t\"-Bdynamic\",\n\t\t\t\"--gc-sections\",\n\t\t\t\"--no-insert-timestamp\",\n\t\t\t\"--no-dynamicbase\",\n\t\t)\n\tcase \"wasm\", \"wasip1\", \"wasip2\":\n\t\treturn nil, fmt.Errorf(\"GOOS=%s but GOARCH is unset. Please set GOARCH to wasm\", options.GOOS)\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unknown GOOS=%s\", options.GOOS)\n\t}\n\n\tif spec.GC == \"boehm\" {\n\t\t// Add this file only when needed. This fixes a build failure on\n\t\t// Windows.\n\t\tspec.ExtraFiles = append(spec.ExtraFiles, \"src/runtime/gc_boehm.c\")\n\t}\n\n\t// Target triples (which actually have four components, but are called\n\t// triples for historical reasons) have the form:\n\t//   arch-vendor-os-environment\n\tspec.Triple = llvmarch + \"-\" + llvmvendor + \"-\" + llvmos\n\tif options.GOOS == \"windows\" {\n\t\tspec.Triple += \"-gnu\"\n\t} else if options.GOOS == \"linux\" {\n\t\t// We use musl on Linux (not glibc) so we should use -musleabi* instead\n\t\t// of -gnueabi*.\n\t\t// The *hf suffix selects between soft/hard floating point ABI.\n\t\tif spec.SoftFloat {\n\t\t\tspec.Triple += \"-musleabi\"\n\t\t} else {\n\t\t\tspec.Triple += \"-musleabihf\"\n\t\t}\n\t}\n\n\t// Add extra assembly files (needed for the scheduler etc).\n\tif options.GOARCH != \"wasm\" {\n\t\tsuffix := \"\"\n\t\tif options.GOOS == \"windows\" && options.GOARCH == \"amd64\" {\n\t\t\t// Windows uses a different calling convention on amd64 from other\n\t\t\t// operating systems so we need separate assembly files.\n\t\t\tsuffix = \"_windows\"\n\t\t}\n\t\tasmGoarch := options.GOARCH\n\t\tif options.GOARCH == \"mips\" || options.GOARCH == \"mipsle\" {\n\t\t\tasmGoarch = \"mipsx\"\n\t\t}\n\t\tspec.ExtraFiles = append(spec.ExtraFiles, \"src/runtime/asm_\"+asmGoarch+suffix+\".S\")\n\t\tspec.ExtraFiles = append(spec.ExtraFiles, \"src/internal/task/task_stack_\"+asmGoarch+suffix+\".S\")\n\t}\n\n\t// Configure the emulator.\n\tif options.GOARCH != runtime.GOARCH {\n\t\t// Some educated guesses as to how to invoke helper programs.\n\t\tspec.GDB = []string{\"gdb-multiarch\"}\n\t\tif options.GOOS == \"linux\" {\n\t\t\tswitch options.GOARCH {\n\t\t\tcase \"386\":\n\t\t\t\t// amd64 can _usually_ run 32-bit programs, so skip the emulator in that case.\n\t\t\t\tif runtime.GOARCH != \"amd64\" {\n\t\t\t\t\tspec.Emulator = \"qemu-i386 {}\"\n\t\t\t\t}\n\t\t\tcase \"amd64\":\n\t\t\t\tspec.Emulator = \"qemu-x86_64 {}\"\n\t\t\tcase \"arm\":\n\t\t\t\tspec.Emulator = \"qemu-arm {}\"\n\t\t\tcase \"arm64\":\n\t\t\t\tspec.Emulator = \"qemu-aarch64 {}\"\n\t\t\tcase \"mips\":\n\t\t\t\tspec.Emulator = \"qemu-mips {}\"\n\t\t\tcase \"mipsle\":\n\t\t\t\tspec.Emulator = \"qemu-mipsel {}\"\n\t\t\t}\n\t\t}\n\t}\n\tif options.GOOS != runtime.GOOS {\n\t\tif options.GOOS == \"windows\" {\n\t\t\tspec.Emulator = \"wine {}\"\n\t\t}\n\t}\n\n\treturn &spec, nil\n}\n\n// LookupGDB looks up a gdb executable.\nfunc (spec *TargetSpec) LookupGDB() (string, error) {\n\tif len(spec.GDB) == 0 {\n\t\treturn \"\", errors.New(\"gdb not configured in the target specification\")\n\t}\n\tfor _, d := range spec.GDB {\n\t\t_, err := exec.LookPath(d)\n\t\tif err == nil {\n\t\t\treturn d, nil\n\t\t}\n\t}\n\treturn \"\", errors.New(\"no gdb found configured in the target specification (\" + strings.Join(spec.GDB, \", \") + \")\")\n}\n"
  },
  {
    "path": "compileopts/target_test.go",
    "content": "package compileopts\n\nimport (\n\t\"errors\"\n\t\"io/fs\"\n\t\"reflect\"\n\t\"testing\"\n)\n\nfunc TestLoadTarget(t *testing.T) {\n\t_, err := LoadTarget(&Options{Target: \"arduino\"})\n\tif err != nil {\n\t\tt.Error(\"LoadTarget test failed:\", err)\n\t}\n\n\t_, err = LoadTarget(&Options{Target: \"notexist\"})\n\tif err == nil {\n\t\tt.Error(\"LoadTarget should have failed with non existing target\")\n\t}\n\n\tif !errors.Is(err, fs.ErrNotExist) {\n\t\tt.Error(\"LoadTarget failed for wrong reason:\", err)\n\t}\n}\n\nfunc TestOverrideProperties(t *testing.T) {\n\tbaseAutoStackSize := true\n\tbase := &TargetSpec{\n\t\tGOOS:             \"baseGoos\",\n\t\tCPU:              \"baseCpu\",\n\t\tCFlags:           []string{\"-base-foo\", \"-base-bar\"},\n\t\tBuildTags:        []string{\"bt1\", \"bt2\"},\n\t\tDefaultStackSize: 42,\n\t\tAutoStackSize:    &baseAutoStackSize,\n\t}\n\tchildAutoStackSize := false\n\tchild := &TargetSpec{\n\t\tGOOS:             \"\",\n\t\tCPU:              \"chlidCpu\",\n\t\tCFlags:           []string{\"-child-foo\", \"-child-bar\"},\n\t\tAutoStackSize:    &childAutoStackSize,\n\t\tDefaultStackSize: 64,\n\t}\n\n\tbase.overrideProperties(child)\n\n\tif base.GOOS != \"baseGoos\" {\n\t\tt.Errorf(\"Overriding failed : got %v\", base.GOOS)\n\t}\n\tif base.CPU != \"chlidCpu\" {\n\t\tt.Errorf(\"Overriding failed : got %v\", base.CPU)\n\t}\n\tif !reflect.DeepEqual(base.CFlags, []string{\"-base-foo\", \"-base-bar\", \"-child-foo\", \"-child-bar\"}) {\n\t\tt.Errorf(\"Overriding failed : got %v\", base.CFlags)\n\t}\n\tif !reflect.DeepEqual(base.BuildTags, []string{\"bt1\", \"bt2\"}) {\n\t\tt.Errorf(\"Overriding failed : got %v\", base.BuildTags)\n\t}\n\tif *base.AutoStackSize != false {\n\t\tt.Errorf(\"Overriding failed : got %v\", base.AutoStackSize)\n\t}\n\tif base.DefaultStackSize != 64 {\n\t\tt.Errorf(\"Overriding failed : got %v\", base.DefaultStackSize)\n\t}\n\n\tbaseAutoStackSize = true\n\tbase = &TargetSpec{\n\t\tAutoStackSize:    &baseAutoStackSize,\n\t\tDefaultStackSize: 42,\n\t}\n\tchild = &TargetSpec{\n\t\tAutoStackSize:    nil,\n\t\tDefaultStackSize: 0,\n\t}\n\tbase.overrideProperties(child)\n\tif *base.AutoStackSize != true {\n\t\tt.Errorf(\"Overriding failed : got %v\", base.AutoStackSize)\n\t}\n\tif base.DefaultStackSize != 42 {\n\t\tt.Errorf(\"Overriding failed : got %v\", base.DefaultStackSize)\n\t}\n\n}\n"
  },
  {
    "path": "compiler/alias.go",
    "content": "package compiler\n\n// This file defines alias functions for functions that are normally defined in\n// Go assembly.\n//\n// The Go toolchain defines many performance critical functions in assembly\n// instead of plain Go. This is a problem for TinyGo as it currently (as of\n// august 2021) is not able to compile these assembly files and even if it\n// could, it would not be able to make use of them for many targets that are\n// supported by TinyGo (baremetal RISC-V, AVR, etc). Therefore, many of these\n// functions are aliased to their generic Go implementation.\n// This results in slower than possible implementations, but at least they are\n// usable.\n\nimport \"tinygo.org/x/go-llvm\"\n\nvar stdlibAliases = map[string]string{\n\t// crypto packages\n\t\"crypto/ed25519/internal/edwards25519/field.feMul\": \"crypto/ed25519/internal/edwards25519/field.feMulGeneric\",\n\t\"crypto/internal/edwards25519/field.feSquare\":      \"crypto/ed25519/internal/edwards25519/field.feSquareGeneric\",\n\t\"crypto/md5.block\":           \"crypto/md5.blockGeneric\",\n\t\"crypto/sha1.block\":          \"crypto/sha1.blockGeneric\",\n\t\"crypto/sha1.blockAMD64\":     \"crypto/sha1.blockGeneric\",\n\t\"crypto/sha256.block\":        \"crypto/sha256.blockGeneric\",\n\t\"crypto/sha512.blockAMD64\":   \"crypto/sha512.blockGeneric\",\n\t\"internal/chacha8rand.block\": \"internal/chacha8rand.block_generic\",\n\n\t// AES\n\t\"crypto/aes.decryptBlockAsm\": \"crypto/aes.decryptBlock\",\n\t\"crypto/aes.encryptBlockAsm\": \"crypto/aes.encryptBlock\",\n\n\t// math package\n\t\"math.archHypot\": \"math.hypot\",\n\t\"math.archMax\":   \"math.max\",\n\t\"math.archMin\":   \"math.min\",\n\t\"math.archModf\":  \"math.modf\",\n}\n\n// createAlias implements the function (in the builder) as a call to the alias\n// function.\nfunc (b *builder) createAlias(alias llvm.Value) {\n\tb.llvmFn.SetVisibility(llvm.HiddenVisibility)\n\tb.llvmFn.SetUnnamedAddr(true)\n\n\tif b.Debug {\n\t\tif b.fn.Syntax() != nil {\n\t\t\t// Create debug info file if present.\n\t\t\tb.difunc = b.attachDebugInfo(b.fn)\n\t\t}\n\t\tpos := b.program.Fset.Position(b.fn.Pos())\n\t\tb.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), b.difunc, llvm.Metadata{})\n\t}\n\tentryBlock := b.ctx.AddBasicBlock(b.llvmFn, \"entry\")\n\tb.SetInsertPointAtEnd(entryBlock)\n\tif b.llvmFn.Type() != alias.Type() {\n\t\tb.addError(b.fn.Pos(), \"alias function should have the same type as aliasee \"+alias.Name())\n\t\tb.CreateUnreachable()\n\t\treturn\n\t}\n\tresult := b.CreateCall(alias.GlobalValueType(), alias, b.llvmFn.Params(), \"\")\n\tif result.Type().TypeKind() == llvm.VoidTypeKind {\n\t\tb.CreateRetVoid()\n\t} else {\n\t\tb.CreateRet(result)\n\t}\n}\n"
  },
  {
    "path": "compiler/asserts.go",
    "content": "package compiler\n\n// This file implements functions that do certain safety checks that are\n// required by the Go programming language.\n\nimport (\n\t\"fmt\"\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/ssa\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// createLookupBoundsCheck emits a bounds check before doing a lookup into a\n// slice. This is required by the Go language spec: an index out of bounds must\n// cause a panic.\n// The caller should make sure that index is at least as big as arrayLen.\nfunc (b *builder) createLookupBoundsCheck(arrayLen, index llvm.Value) {\n\tif b.info.nobounds {\n\t\t// The //go:nobounds pragma was added to the function to avoid bounds\n\t\t// checking.\n\t\treturn\n\t}\n\n\t// Extend arrayLen if it's too small.\n\tif index.Type().IntTypeWidth() > arrayLen.Type().IntTypeWidth() {\n\t\t// The index is bigger than the array length type, so extend it.\n\t\tarrayLen = b.CreateZExt(arrayLen, index.Type(), \"\")\n\t}\n\n\t// Now do the bounds check: index >= arrayLen\n\toutOfBounds := b.CreateICmp(llvm.IntUGE, index, arrayLen, \"\")\n\tb.createRuntimeAssert(outOfBounds, \"lookup\", \"lookupPanic\")\n}\n\n// createSliceBoundsCheck emits a bounds check before a slicing operation to make\n// sure it is within bounds.\n//\n// This function is both used for slicing a slice (low and high have their\n// normal meaning) and for creating a new slice, where 'capacity' means the\n// biggest possible slice capacity, 'low' means len and 'high' means cap. The\n// logic is the same in both cases.\nfunc (b *builder) createSliceBoundsCheck(capacity, low, high, max llvm.Value, lowType, highType, maxType *types.Basic) {\n\tif b.info.nobounds {\n\t\t// The //go:nobounds pragma was added to the function to avoid bounds\n\t\t// checking.\n\t\treturn\n\t}\n\n\t// Extend the capacity integer to be at least as wide as low and high.\n\tcapacityType := capacity.Type()\n\tif low.Type().IntTypeWidth() > capacityType.IntTypeWidth() {\n\t\tcapacityType = low.Type()\n\t}\n\tif high.Type().IntTypeWidth() > capacityType.IntTypeWidth() {\n\t\tcapacityType = high.Type()\n\t}\n\tif max.Type().IntTypeWidth() > capacityType.IntTypeWidth() {\n\t\tcapacityType = max.Type()\n\t}\n\tif capacityType != capacity.Type() {\n\t\tcapacity = b.CreateZExt(capacity, capacityType, \"\")\n\t}\n\n\t// Extend low and high to be the same size as capacity.\n\tlow = b.extendInteger(low, lowType, capacityType)\n\thigh = b.extendInteger(high, highType, capacityType)\n\tmax = b.extendInteger(max, maxType, capacityType)\n\n\t// Now do the bounds check: low > high || high > capacity\n\toutOfBounds1 := b.CreateICmp(llvm.IntUGT, low, high, \"slice.lowhigh\")\n\toutOfBounds2 := b.CreateICmp(llvm.IntUGT, high, max, \"slice.highmax\")\n\toutOfBounds3 := b.CreateICmp(llvm.IntUGT, max, capacity, \"slice.maxcap\")\n\toutOfBounds := b.CreateOr(outOfBounds1, outOfBounds2, \"slice.lowmax\")\n\toutOfBounds = b.CreateOr(outOfBounds, outOfBounds3, \"slice.lowcap\")\n\tb.createRuntimeAssert(outOfBounds, \"slice\", \"slicePanic\")\n}\n\n// createSliceToArrayPointerCheck adds a check for slice-to-array pointer\n// conversions. This conversion was added in Go 1.17. For details, see:\n// https://tip.golang.org/ref/spec#Conversions_from_slice_to_array_pointer\nfunc (b *builder) createSliceToArrayPointerCheck(sliceLen llvm.Value, arrayLen int64) {\n\t// From the spec:\n\t// > If the length of the slice is less than the length of the array, a\n\t// > run-time panic occurs.\n\tarrayLenValue := llvm.ConstInt(b.uintptrType, uint64(arrayLen), false)\n\tisLess := b.CreateICmp(llvm.IntULT, sliceLen, arrayLenValue, \"\")\n\tb.createRuntimeAssert(isLess, \"slicetoarray\", \"sliceToArrayPointerPanic\")\n}\n\n// createUnsafeSliceStringCheck inserts a runtime check used for unsafe.Slice\n// and unsafe.String. This function must panic if the ptr/len parameters are\n// invalid.\nfunc (b *builder) createUnsafeSliceStringCheck(name string, ptr, len llvm.Value, elementType llvm.Type, lenType *types.Basic) {\n\t// From the documentation of unsafe.Slice and unsafe.String:\n\t//   > At run time, if len is negative, or if ptr is nil and len is not\n\t//   > zero, a run-time panic occurs.\n\t// However, in practice, it is also necessary to check that the length is\n\t// not too big that a GEP wouldn't be possible without wrapping the pointer.\n\t// These two checks (non-negative and not too big) can be merged into one\n\t// using an unsigned greater than.\n\n\t// Make sure the len value is at least as big as a uintptr.\n\tlen = b.extendInteger(len, lenType, b.uintptrType)\n\n\t// Determine the maximum slice size, and therefore the maximum value of the\n\t// len parameter.\n\tmaxSize := b.maxSliceSize(elementType)\n\tmaxSizeValue := llvm.ConstInt(len.Type(), maxSize, false)\n\n\t// Do the check. By using unsigned greater than for the length check, signed\n\t// negative values are also checked (which are very large numbers when\n\t// interpreted as signed values).\n\tzero := llvm.ConstInt(len.Type(), 0, false)\n\tlenOutOfBounds := b.CreateICmp(llvm.IntUGT, len, maxSizeValue, \"\")\n\tptrIsNil := b.CreateICmp(llvm.IntEQ, ptr, llvm.ConstNull(ptr.Type()), \"\")\n\tlenIsNotZero := b.CreateICmp(llvm.IntNE, len, zero, \"\")\n\tassert := b.CreateAnd(ptrIsNil, lenIsNotZero, \"\")\n\tassert = b.CreateOr(assert, lenOutOfBounds, \"\")\n\tb.createRuntimeAssert(assert, name, \"unsafeSlicePanic\")\n}\n\n// createChanBoundsCheck creates a bounds check before creating a new channel to\n// check that the value is not too big for runtime.chanMake.\nfunc (b *builder) createChanBoundsCheck(elementSize uint64, bufSize llvm.Value, bufSizeType *types.Basic, pos token.Pos) {\n\tif b.info.nobounds {\n\t\t// The //go:nobounds pragma was added to the function to avoid bounds\n\t\t// checking.\n\t\treturn\n\t}\n\n\t// Make sure bufSize is at least as big as maxBufSize (an uintptr).\n\tbufSize = b.extendInteger(bufSize, bufSizeType, b.uintptrType)\n\n\t// Calculate (^uintptr(0)) >> 1, which is the max value that fits in an\n\t// uintptr if uintptrs were signed.\n\tmaxBufSize := b.CreateLShr(llvm.ConstNot(llvm.ConstInt(b.uintptrType, 0, false)), llvm.ConstInt(b.uintptrType, 1, false), \"\")\n\tif elementSize > maxBufSize.ZExtValue() {\n\t\tb.addError(pos, fmt.Sprintf(\"channel element type is too big (%v bytes)\", elementSize))\n\t\treturn\n\t}\n\t// Avoid divide-by-zero.\n\tif elementSize == 0 {\n\t\telementSize = 1\n\t}\n\t// Make the maxBufSize actually the maximum allowed value (in number of\n\t// elements in the channel buffer).\n\tmaxBufSize = b.CreateUDiv(maxBufSize, llvm.ConstInt(b.uintptrType, elementSize, false), \"\")\n\n\t// Make sure maxBufSize has the same type as bufSize.\n\tif maxBufSize.Type() != bufSize.Type() {\n\t\tmaxBufSize = b.CreateZExt(maxBufSize, bufSize.Type(), \"\")\n\t}\n\n\t// Do the check for a too large (or negative) buffer size.\n\tbufSizeTooBig := b.CreateICmp(llvm.IntUGE, bufSize, maxBufSize, \"\")\n\tb.createRuntimeAssert(bufSizeTooBig, \"chan\", \"chanMakePanic\")\n}\n\n// createNilCheck checks whether the given pointer is nil, and panics if it is.\n// It has no effect in well-behaved programs, but makes sure no uncaught nil\n// pointer dereferences exist in valid Go code.\nfunc (b *builder) createNilCheck(inst ssa.Value, ptr llvm.Value, blockPrefix string) {\n\t// Check whether we need to emit this check at all.\n\tif !ptr.IsAGlobalValue().IsNil() {\n\t\treturn\n\t}\n\n\tswitch inst := inst.(type) {\n\tcase *ssa.Alloc:\n\t\t// An alloc is never nil.\n\t\treturn\n\tcase *ssa.FreeVar:\n\t\t// A free variable is allocated in a parent function and is thus never\n\t\t// nil.\n\t\treturn\n\tcase *ssa.IndexAddr:\n\t\t// This pointer is the result of an index operation into a slice or\n\t\t// array. Such slices/arrays are already bounds checked so the pointer\n\t\t// must be a valid (non-nil) pointer. No nil checking is necessary.\n\t\treturn\n\tcase *ssa.Convert:\n\t\t// This is a pointer that comes from a conversion from unsafe.Pointer.\n\t\t// Don't do nil checking because this is unsafe code and the code should\n\t\t// know what it is doing.\n\t\t// Note: all *ssa.Convert instructions that result in a pointer must\n\t\t// come from unsafe.Pointer. Testing here for unsafe.Pointer to be sure.\n\t\tif inst.X.Type() == types.Typ[types.UnsafePointer] {\n\t\t\treturn\n\t\t}\n\t}\n\n\t// Compare against nil.\n\t// We previously used a hack to make sure this wouldn't break escape\n\t// analysis, but this is not necessary anymore since\n\t// https://reviews.llvm.org/D60047 has been merged.\n\tnilptr := llvm.ConstPointerNull(ptr.Type())\n\tisnil := b.CreateICmp(llvm.IntEQ, ptr, nilptr, \"\")\n\n\t// Emit the nil check in IR.\n\tb.createRuntimeAssert(isnil, blockPrefix, \"nilPanic\")\n}\n\n// createNegativeShiftCheck creates an assertion that panics if the given shift value is negative.\n// This function assumes that the shift value is signed.\nfunc (b *builder) createNegativeShiftCheck(shift llvm.Value) {\n\tif b.info.nobounds {\n\t\t// Function disabled bounds checking - skip shift check.\n\t\treturn\n\t}\n\n\t// isNegative = shift < 0\n\tisNegative := b.CreateICmp(llvm.IntSLT, shift, llvm.ConstInt(shift.Type(), 0, false), \"\")\n\tb.createRuntimeAssert(isNegative, \"shift\", \"negativeShiftPanic\")\n}\n\n// createDivideByZeroCheck asserts that y is not zero. If it is, a runtime panic\n// will be emitted. This follows the Go specification which says that a divide\n// by zero must cause a run time panic.\nfunc (b *builder) createDivideByZeroCheck(y llvm.Value) {\n\tif b.info.nobounds {\n\t\treturn\n\t}\n\n\t// isZero = y == 0\n\tisZero := b.CreateICmp(llvm.IntEQ, y, llvm.ConstInt(y.Type(), 0, false), \"\")\n\tb.createRuntimeAssert(isZero, \"divbyzero\", \"divideByZeroPanic\")\n}\n\n// createRuntimeAssert is a common function to create a new branch on an assert\n// bool, calling an assert func if the assert value is true (1).\nfunc (b *builder) createRuntimeAssert(assert llvm.Value, blockPrefix, assertFunc string) {\n\t// Check whether we can resolve this check at compile time.\n\tif !assert.IsAConstantInt().IsNil() {\n\t\tval := assert.ZExtValue()\n\t\tif val == 0 {\n\t\t\t// Everything is constant so the check does not have to be emitted\n\t\t\t// in IR. This avoids emitting some redundant IR.\n\t\t\treturn\n\t\t}\n\t}\n\n\t// Put the fault block at the end of the function and the next block at the\n\t// current insert position.\n\tfaultBlock := b.ctx.AddBasicBlock(b.llvmFn, blockPrefix+\".throw\")\n\tnextBlock := b.insertBasicBlock(blockPrefix + \".next\")\n\tb.currentBlockInfo.exit = nextBlock // adjust outgoing block for phi nodes\n\n\t// Now branch to the out-of-bounds or the regular block.\n\tb.CreateCondBr(assert, faultBlock, nextBlock)\n\n\t// Fail: the assert triggered so panic.\n\tb.SetInsertPointAtEnd(faultBlock)\n\tb.createRuntimeCall(assertFunc, nil, \"\")\n\tb.CreateUnreachable()\n\n\t// Ok: assert didn't trigger so continue normally.\n\tb.SetInsertPointAtEnd(nextBlock)\n}\n\n// extendInteger extends the value to at least targetType using a zero or sign\n// extend. The resulting value is not truncated: it may still be bigger than\n// targetType.\nfunc (b *builder) extendInteger(value llvm.Value, valueType types.Type, targetType llvm.Type) llvm.Value {\n\tif value.Type().IntTypeWidth() < targetType.IntTypeWidth() {\n\t\tif valueType.Underlying().(*types.Basic).Info()&types.IsUnsigned != 0 {\n\t\t\t// Unsigned, so zero-extend to the target type.\n\t\t\tvalue = b.CreateZExt(value, targetType, \"\")\n\t\t} else {\n\t\t\t// Signed, so sign-extend to the target type.\n\t\t\tvalue = b.CreateSExt(value, targetType, \"\")\n\t\t}\n\t}\n\treturn value\n}\n"
  },
  {
    "path": "compiler/atomic.go",
    "content": "package compiler\n\nimport (\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// createAtomicOp lowers a sync/atomic function by lowering it as an LLVM atomic\n// operation. It returns the result of the operation, or a zero llvm.Value if\n// the result is void.\nfunc (b *builder) createAtomicOp(name string) llvm.Value {\n\tswitch name {\n\tcase \"AddInt32\", \"AddInt64\", \"AddUint32\", \"AddUint64\", \"AddUintptr\":\n\t\tptr := b.getValue(b.fn.Params[0], getPos(b.fn))\n\t\tval := b.getValue(b.fn.Params[1], getPos(b.fn))\n\t\toldVal := b.CreateAtomicRMW(llvm.AtomicRMWBinOpAdd, ptr, val, llvm.AtomicOrderingSequentiallyConsistent, true)\n\t\t// Return the new value, not the original value returned by atomicrmw.\n\t\treturn b.CreateAdd(oldVal, val, \"\")\n\tcase \"AndInt32\", \"AndInt64\", \"AndUint32\", \"AndUint64\", \"AndUintptr\":\n\t\tptr := b.getValue(b.fn.Params[0], getPos(b.fn))\n\t\tval := b.getValue(b.fn.Params[1], getPos(b.fn))\n\t\toldVal := b.CreateAtomicRMW(llvm.AtomicRMWBinOpAnd, ptr, val, llvm.AtomicOrderingSequentiallyConsistent, true)\n\t\treturn oldVal\n\tcase \"OrInt32\", \"OrInt64\", \"OrUint32\", \"OrUint64\", \"OrUintptr\":\n\t\tptr := b.getValue(b.fn.Params[0], getPos(b.fn))\n\t\tval := b.getValue(b.fn.Params[1], getPos(b.fn))\n\t\toldVal := b.CreateAtomicRMW(llvm.AtomicRMWBinOpOr, ptr, val, llvm.AtomicOrderingSequentiallyConsistent, true)\n\t\treturn oldVal\n\tcase \"SwapInt32\", \"SwapInt64\", \"SwapUint32\", \"SwapUint64\", \"SwapUintptr\", \"SwapPointer\":\n\t\tptr := b.getValue(b.fn.Params[0], getPos(b.fn))\n\t\tval := b.getValue(b.fn.Params[1], getPos(b.fn))\n\t\toldVal := b.CreateAtomicRMW(llvm.AtomicRMWBinOpXchg, ptr, val, llvm.AtomicOrderingSequentiallyConsistent, true)\n\t\treturn oldVal\n\tcase \"CompareAndSwapInt32\", \"CompareAndSwapInt64\", \"CompareAndSwapUint32\", \"CompareAndSwapUint64\", \"CompareAndSwapUintptr\", \"CompareAndSwapPointer\":\n\t\tptr := b.getValue(b.fn.Params[0], getPos(b.fn))\n\t\told := b.getValue(b.fn.Params[1], getPos(b.fn))\n\t\tnewVal := b.getValue(b.fn.Params[2], getPos(b.fn))\n\t\ttuple := b.CreateAtomicCmpXchg(ptr, old, newVal, llvm.AtomicOrderingSequentiallyConsistent, llvm.AtomicOrderingSequentiallyConsistent, true)\n\t\tswapped := b.CreateExtractValue(tuple, 1, \"\")\n\t\treturn swapped\n\tcase \"LoadInt32\", \"LoadInt64\", \"LoadUint32\", \"LoadUint64\", \"LoadUintptr\", \"LoadPointer\":\n\t\tptr := b.getValue(b.fn.Params[0], getPos(b.fn))\n\t\tval := b.CreateLoad(b.getLLVMType(b.fn.Signature.Results().At(0).Type()), ptr, \"\")\n\t\tval.SetOrdering(llvm.AtomicOrderingSequentiallyConsistent)\n\t\tval.SetAlignment(b.targetData.PrefTypeAlignment(val.Type())) // required\n\t\treturn val\n\tcase \"StoreInt32\", \"StoreInt64\", \"StoreUint32\", \"StoreUint64\", \"StoreUintptr\", \"StorePointer\":\n\t\tptr := b.getValue(b.fn.Params[0], getPos(b.fn))\n\t\tval := b.getValue(b.fn.Params[1], getPos(b.fn))\n\t\tstore := b.CreateStore(val, ptr)\n\t\tstore.SetOrdering(llvm.AtomicOrderingSequentiallyConsistent)\n\t\tstore.SetAlignment(b.targetData.PrefTypeAlignment(val.Type())) // required\n\t\treturn llvm.Value{}\n\tdefault:\n\t\tb.addError(b.fn.Pos(), \"unknown atomic operation: \"+b.fn.Name())\n\t\treturn llvm.Value{}\n\t}\n}\n"
  },
  {
    "path": "compiler/calls.go",
    "content": "package compiler\n\nimport (\n\t\"go/types\"\n\t\"strconv\"\n\n\t\"golang.org/x/tools/go/ssa\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// For a description of the calling convention in prose, see:\n// https://tinygo.org/compiler-internals/calling-convention/\n\n// The maximum number of arguments that can be expanded from a single struct. If\n// a struct contains more fields, it is passed as a struct without expanding.\nconst maxFieldsPerParam = 3\n\n// paramInfo contains some information collected about a function parameter,\n// useful while declaring or defining a function.\ntype paramInfo struct {\n\tllvmType llvm.Type\n\tname     string     // name, possibly with suffixes for e.g. struct fields\n\telemSize uint64     // size of pointer element type, or 0 if this isn't a pointer\n\tflags    paramFlags // extra flags for this parameter\n}\n\n// paramFlags identifies parameter attributes for flags. Most importantly, it\n// determines which parameters are dereferenceable_or_null and which aren't.\ntype paramFlags uint8\n\nconst (\n\t// Whether this is a full or partial Go parameter (int, slice, etc).\n\t// The extra context parameter is not a Go parameter.\n\tparamIsGoParam = 1 << iota\n\n\t// Whether this is a readonly parameter (for example, a string pointer).\n\tparamIsReadonly\n)\n\n// createRuntimeCallCommon creates a runtime call. Use createRuntimeCall or\n// createRuntimeInvoke instead.\nfunc (b *builder) createRuntimeCallCommon(fnName string, args []llvm.Value, name string, isInvoke bool) llvm.Value {\n\tmember := b.program.ImportedPackage(\"runtime\").Members[fnName]\n\tif member == nil {\n\t\tpanic(\"unknown runtime call: \" + fnName)\n\t}\n\tfn := member.(*ssa.Function)\n\tfnType, llvmFn := b.getFunction(fn)\n\tif llvmFn.IsNil() {\n\t\tpanic(\"trying to call non-existent function: \" + fn.RelString(nil))\n\t}\n\targs = append(args, llvm.Undef(b.dataPtrType)) // unused context parameter\n\tif isInvoke {\n\t\treturn b.createInvoke(fnType, llvmFn, args, name)\n\t}\n\treturn b.createCall(fnType, llvmFn, args, name)\n}\n\n// createRuntimeCall creates a new call to runtime.<fnName> with the given\n// arguments.\nfunc (b *builder) createRuntimeCall(fnName string, args []llvm.Value, name string) llvm.Value {\n\treturn b.createRuntimeCallCommon(fnName, args, name, false)\n}\n\n// createRuntimeInvoke creates a new call to runtime.<fnName> with the given\n// arguments. If the runtime call panics, control flow is diverted to the\n// landing pad block.\n// Note that \"invoke\" here is meant in the LLVM sense (a call that can\n// panic/throw), not in the Go sense (an interface method call).\nfunc (b *builder) createRuntimeInvoke(fnName string, args []llvm.Value, name string) llvm.Value {\n\treturn b.createRuntimeCallCommon(fnName, args, name, true)\n}\n\n// createCall creates a call to the given function with the arguments possibly\n// expanded.\nfunc (b *builder) createCall(fnType llvm.Type, fn llvm.Value, args []llvm.Value, name string) llvm.Value {\n\texpanded := make([]llvm.Value, 0, len(args))\n\tfor _, arg := range args {\n\t\tfragments := b.expandFormalParam(arg)\n\t\texpanded = append(expanded, fragments...)\n\t}\n\tcall := b.CreateCall(fnType, fn, expanded, name)\n\tif !fn.IsAFunction().IsNil() {\n\t\tif cc := fn.FunctionCallConv(); cc != llvm.CCallConv {\n\t\t\t// Set a different calling convention if needed.\n\t\t\t// This is needed for GetModuleHandleExA on Windows, for example.\n\t\t\tcall.SetInstructionCallConv(cc)\n\t\t}\n\t}\n\treturn call\n}\n\n// createInvoke is like createCall but continues execution at the landing pad if\n// the call resulted in a panic.\nfunc (b *builder) createInvoke(fnType llvm.Type, fn llvm.Value, args []llvm.Value, name string) llvm.Value {\n\tif b.hasDeferFrame() {\n\t\tb.createInvokeCheckpoint()\n\t}\n\treturn b.createCall(fnType, fn, args, name)\n}\n\n// Expand an argument type to a list that can be used in a function call\n// parameter list.\nfunc (c *compilerContext) expandFormalParamType(t llvm.Type, name string, goType types.Type) []paramInfo {\n\tswitch t.TypeKind() {\n\tcase llvm.StructTypeKind:\n\t\tfieldInfos := c.flattenAggregateType(t, name, goType)\n\t\tif len(fieldInfos) <= maxFieldsPerParam {\n\t\t\t// managed to expand this parameter\n\t\t\treturn fieldInfos\n\t\t}\n\t\t// failed to expand this parameter: too many fields\n\t}\n\t// TODO: split small arrays\n\treturn []paramInfo{c.getParamInfo(t, name, goType)}\n}\n\n// expandFormalParamOffsets returns a list of offsets from the start of an\n// object of type t after it would have been split up by expandFormalParam. This\n// is useful for debug information, where it is necessary to know the offset\n// from the start of the combined object.\nfunc (b *builder) expandFormalParamOffsets(t llvm.Type) []uint64 {\n\tswitch t.TypeKind() {\n\tcase llvm.StructTypeKind:\n\t\tfields := b.flattenAggregateTypeOffsets(t)\n\t\tif len(fields) <= maxFieldsPerParam {\n\t\t\treturn fields\n\t\t} else {\n\t\t\t// failed to lower\n\t\t\treturn []uint64{0}\n\t\t}\n\tdefault:\n\t\t// TODO: split small arrays\n\t\treturn []uint64{0}\n\t}\n}\n\n// expandFormalParam splits a formal param value into pieces, so it can be\n// passed directly as part of a function call. For example, it splits up small\n// structs into individual fields. It is the equivalent of expandFormalParamType\n// for parameter values.\nfunc (b *builder) expandFormalParam(v llvm.Value) []llvm.Value {\n\tswitch v.Type().TypeKind() {\n\tcase llvm.StructTypeKind:\n\t\tfieldInfos := b.flattenAggregateType(v.Type(), \"\", nil)\n\t\tif len(fieldInfos) <= maxFieldsPerParam {\n\t\t\tfields := b.flattenAggregate(v)\n\t\t\tif len(fields) != len(fieldInfos) {\n\t\t\t\tpanic(\"type and value param lowering don't match\")\n\t\t\t}\n\t\t\treturn fields\n\t\t} else {\n\t\t\t// failed to lower\n\t\t\treturn []llvm.Value{v}\n\t\t}\n\tdefault:\n\t\t// TODO: split small arrays\n\t\treturn []llvm.Value{v}\n\t}\n}\n\n// Try to flatten a struct type to a list of types. Returns a 1-element slice\n// with the passed in type if this is not possible.\nfunc (c *compilerContext) flattenAggregateType(t llvm.Type, name string, goType types.Type) []paramInfo {\n\tswitch t.TypeKind() {\n\tcase llvm.StructTypeKind:\n\t\tvar paramInfos []paramInfo\n\t\tfor i, subfield := range t.StructElementTypes() {\n\t\t\tif c.targetData.TypeAllocSize(subfield) == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tsuffix := strconv.Itoa(i)\n\t\t\tisString := false\n\t\t\tif goType != nil {\n\t\t\t\t// Try to come up with a good suffix for this struct field,\n\t\t\t\t// depending on which Go type it's based on.\n\t\t\t\tswitch goType := goType.Underlying().(type) {\n\t\t\t\tcase *types.Interface:\n\t\t\t\t\tsuffix = []string{\"typecode\", \"value\"}[i]\n\t\t\t\tcase *types.Slice:\n\t\t\t\t\tsuffix = []string{\"data\", \"len\", \"cap\"}[i]\n\t\t\t\tcase *types.Struct:\n\t\t\t\t\tsuffix = goType.Field(i).Name()\n\t\t\t\tcase *types.Basic:\n\t\t\t\t\tswitch goType.Kind() {\n\t\t\t\t\tcase types.Complex64, types.Complex128:\n\t\t\t\t\t\tsuffix = []string{\"r\", \"i\"}[i]\n\t\t\t\t\tcase types.String:\n\t\t\t\t\t\tsuffix = []string{\"data\", \"len\"}[i]\n\t\t\t\t\t\tisString = true\n\t\t\t\t\t}\n\t\t\t\tcase *types.Signature:\n\t\t\t\t\tsuffix = []string{\"context\", \"funcptr\"}[i]\n\t\t\t\t}\n\t\t\t}\n\t\t\tsubInfos := c.flattenAggregateType(subfield, name+\".\"+suffix, extractSubfield(goType, i))\n\t\t\tif isString {\n\t\t\t\tsubInfos[0].flags |= paramIsReadonly\n\t\t\t}\n\t\t\tparamInfos = append(paramInfos, subInfos...)\n\t\t}\n\t\treturn paramInfos\n\tdefault:\n\t\treturn []paramInfo{c.getParamInfo(t, name, goType)}\n\t}\n}\n\n// getParamInfo collects information about a parameter. For example, if this\n// parameter is pointer-like, it will also store the element type for the\n// dereferenceable_or_null attribute.\nfunc (c *compilerContext) getParamInfo(t llvm.Type, name string, goType types.Type) paramInfo {\n\tinfo := paramInfo{\n\t\tllvmType: t,\n\t\tname:     name,\n\t\tflags:    paramIsGoParam,\n\t}\n\tif goType != nil {\n\t\tswitch underlying := goType.Underlying().(type) {\n\t\tcase *types.Pointer:\n\t\t\t// Pointers in Go must either point to an object or be nil.\n\t\t\tinfo.elemSize = c.targetData.TypeAllocSize(c.getLLVMType(underlying.Elem()))\n\t\tcase *types.Chan:\n\t\t\t// Channels are implemented simply as a *runtime.channel.\n\t\t\tinfo.elemSize = c.targetData.TypeAllocSize(c.getLLVMRuntimeType(\"channel\"))\n\t\tcase *types.Map:\n\t\t\t// Maps are similar to channels: they are implemented as a\n\t\t\t// *runtime.hashmap.\n\t\t\tinfo.elemSize = c.targetData.TypeAllocSize(c.getLLVMRuntimeType(\"hashmap\"))\n\t\t}\n\t}\n\treturn info\n}\n\n// extractSubfield extracts a field from a struct, or returns null if this is\n// not a struct and thus no subfield can be obtained.\nfunc extractSubfield(t types.Type, field int) types.Type {\n\tif t == nil {\n\t\treturn nil\n\t}\n\tswitch t := t.Underlying().(type) {\n\tcase *types.Struct:\n\t\treturn t.Field(field).Type()\n\tcase *types.Interface, *types.Slice, *types.Basic, *types.Signature:\n\t\t// These Go types are (sometimes) implemented as LLVM structs but can't\n\t\t// really be split further up in Go (with the possible exception of\n\t\t// complex numbers).\n\t\treturn nil\n\tdefault:\n\t\t// This should be unreachable.\n\t\tpanic(\"cannot split subfield: \" + t.String())\n\t}\n}\n\n// flattenAggregateTypeOffsets returns the offsets from the start of an object of\n// type t if this object were flattened like in flattenAggregate. Used together\n// with flattenAggregate to know the start indices of each value in the\n// non-flattened object.\n//\n// Note: this is an implementation detail, use expandFormalParamOffsets instead.\nfunc (c *compilerContext) flattenAggregateTypeOffsets(t llvm.Type) []uint64 {\n\tswitch t.TypeKind() {\n\tcase llvm.StructTypeKind:\n\t\tvar fields []uint64\n\t\tfor fieldIndex, field := range t.StructElementTypes() {\n\t\t\tif c.targetData.TypeAllocSize(field) == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tsuboffsets := c.flattenAggregateTypeOffsets(field)\n\t\t\toffset := c.targetData.ElementOffset(t, fieldIndex)\n\t\t\tfor i := range suboffsets {\n\t\t\t\tsuboffsets[i] += offset\n\t\t\t}\n\t\t\tfields = append(fields, suboffsets...)\n\t\t}\n\t\treturn fields\n\tdefault:\n\t\treturn []uint64{0}\n\t}\n}\n\n// flattenAggregate breaks down a struct into its elementary values for argument\n// passing. It is the value equivalent of flattenAggregateType\nfunc (b *builder) flattenAggregate(v llvm.Value) []llvm.Value {\n\tswitch v.Type().TypeKind() {\n\tcase llvm.StructTypeKind:\n\t\tvar fields []llvm.Value\n\t\tfor i, field := range v.Type().StructElementTypes() {\n\t\t\tif b.targetData.TypeAllocSize(field) == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tsubfield := b.CreateExtractValue(v, i, \"\")\n\t\t\tsubfields := b.flattenAggregate(subfield)\n\t\t\tfields = append(fields, subfields...)\n\t\t}\n\t\treturn fields\n\tdefault:\n\t\treturn []llvm.Value{v}\n\t}\n}\n\n// collapseFormalParam combines an aggregate object back into the original\n// value. This is used to join multiple LLVM parameters into a single Go value\n// in the function entry block.\nfunc (b *builder) collapseFormalParam(t llvm.Type, fields []llvm.Value) llvm.Value {\n\tparam, remaining := b.collapseFormalParamInternal(t, fields)\n\tif len(remaining) != 0 {\n\t\tpanic(\"failed to expand back all fields\")\n\t}\n\treturn param\n}\n\n// collapseFormalParamInternal is an implementation detail of\n// collapseFormalParam: it works by recursing until there are no fields left.\nfunc (b *builder) collapseFormalParamInternal(t llvm.Type, fields []llvm.Value) (llvm.Value, []llvm.Value) {\n\tswitch t.TypeKind() {\n\tcase llvm.StructTypeKind:\n\t\tflattened := b.flattenAggregateType(t, \"\", nil)\n\t\tif len(flattened) <= maxFieldsPerParam {\n\t\t\tvalue := llvm.ConstNull(t)\n\t\t\tfor i, subtyp := range t.StructElementTypes() {\n\t\t\t\tif b.targetData.TypeAllocSize(subtyp) == 0 {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tstructField, remaining := b.collapseFormalParamInternal(subtyp, fields)\n\t\t\t\tfields = remaining\n\t\t\t\tvalue = b.CreateInsertValue(value, structField, i, \"\")\n\t\t\t}\n\t\t\treturn value, fields\n\t\t} else {\n\t\t\t// this struct was not flattened\n\t\t\treturn fields[0], fields[1:]\n\t\t}\n\tdefault:\n\t\treturn fields[0], fields[1:]\n\t}\n}\n"
  },
  {
    "path": "compiler/channel.go",
    "content": "package compiler\n\n// This file lowers channel operations (make/send/recv/close) to runtime calls\n// or pseudo-operations that are lowered during goroutine lowering.\n\nimport (\n\t\"fmt\"\n\t\"go/types\"\n\t\"math\"\n\n\t\"github.com/tinygo-org/tinygo/compiler/llvmutil\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\nfunc (b *builder) createMakeChan(expr *ssa.MakeChan) llvm.Value {\n\telementSize := b.targetData.TypeAllocSize(b.getLLVMType(expr.Type().Underlying().(*types.Chan).Elem()))\n\telementSizeValue := llvm.ConstInt(b.uintptrType, elementSize, false)\n\tbufSize := b.getValue(expr.Size, getPos(expr))\n\tb.createChanBoundsCheck(elementSize, bufSize, expr.Size.Type().Underlying().(*types.Basic), expr.Pos())\n\tif bufSize.Type().IntTypeWidth() < b.uintptrType.IntTypeWidth() {\n\t\tbufSize = b.CreateZExt(bufSize, b.uintptrType, \"\")\n\t} else if bufSize.Type().IntTypeWidth() > b.uintptrType.IntTypeWidth() {\n\t\tbufSize = b.CreateTrunc(bufSize, b.uintptrType, \"\")\n\t}\n\treturn b.createRuntimeCall(\"chanMake\", []llvm.Value{elementSizeValue, bufSize}, \"\")\n}\n\n// createChanSend emits a pseudo chan send operation. It is lowered to the\n// actual channel send operation during goroutine lowering.\nfunc (b *builder) createChanSend(instr *ssa.Send) {\n\tch := b.getValue(instr.Chan, getPos(instr))\n\tchanValue := b.getValue(instr.X, getPos(instr))\n\n\t// store value-to-send\n\tvalueType := b.getLLVMType(instr.X.Type())\n\tisZeroSize := b.targetData.TypeAllocSize(valueType) == 0\n\tvar valueAlloca, valueAllocaSize llvm.Value\n\tif isZeroSize {\n\t\tvalueAlloca = llvm.ConstNull(b.dataPtrType)\n\t} else {\n\t\tvalueAlloca, valueAllocaSize = b.createTemporaryAlloca(valueType, \"chan.value\")\n\t\tb.CreateStore(chanValue, valueAlloca)\n\t}\n\n\t// Allocate buffer for the channel operation.\n\tchannelOp := b.getLLVMRuntimeType(\"channelOp\")\n\tchannelOpAlloca, channelOpAllocaSize := b.createTemporaryAlloca(channelOp, \"chan.op\")\n\n\t// Do the send.\n\tb.createRuntimeCall(\"chanSend\", []llvm.Value{ch, valueAlloca, channelOpAlloca}, \"\")\n\n\t// End the lifetime of the allocas.\n\t// This also works around a bug in CoroSplit, at least in LLVM 8:\n\t// https://bugs.llvm.org/show_bug.cgi?id=41742\n\tb.emitLifetimeEnd(channelOpAlloca, channelOpAllocaSize)\n\tif !isZeroSize {\n\t\tb.emitLifetimeEnd(valueAlloca, valueAllocaSize)\n\t}\n}\n\n// createChanRecv emits a pseudo chan receive operation. It is lowered to the\n// actual channel receive operation during goroutine lowering.\nfunc (b *builder) createChanRecv(unop *ssa.UnOp) llvm.Value {\n\tvalueType := b.getLLVMType(unop.X.Type().Underlying().(*types.Chan).Elem())\n\tch := b.getValue(unop.X, getPos(unop))\n\n\t// Allocate memory to receive into.\n\tisZeroSize := b.targetData.TypeAllocSize(valueType) == 0\n\tvar valueAlloca, valueAllocaSize llvm.Value\n\tif isZeroSize {\n\t\tvalueAlloca = llvm.ConstNull(b.dataPtrType)\n\t} else {\n\t\tvalueAlloca, valueAllocaSize = b.createTemporaryAlloca(valueType, \"chan.value\")\n\t}\n\n\t// Allocate buffer for the channel operation.\n\tchannelOp := b.getLLVMRuntimeType(\"channelOp\")\n\tchannelOpAlloca, channelOpAllocaSize := b.createTemporaryAlloca(channelOp, \"chan.op\")\n\n\t// Do the receive.\n\tcommaOk := b.createRuntimeCall(\"chanRecv\", []llvm.Value{ch, valueAlloca, channelOpAlloca}, \"\")\n\tvar received llvm.Value\n\tif isZeroSize {\n\t\treceived = llvm.ConstNull(valueType)\n\t} else {\n\t\treceived = b.CreateLoad(valueType, valueAlloca, \"chan.received\")\n\t\tb.emitLifetimeEnd(valueAlloca, valueAllocaSize)\n\t}\n\tb.emitLifetimeEnd(channelOpAlloca, channelOpAllocaSize)\n\n\tif unop.CommaOk {\n\t\ttuple := llvm.Undef(b.ctx.StructType([]llvm.Type{valueType, b.ctx.Int1Type()}, false))\n\t\ttuple = b.CreateInsertValue(tuple, received, 0, \"\")\n\t\ttuple = b.CreateInsertValue(tuple, commaOk, 1, \"\")\n\t\treturn tuple\n\t} else {\n\t\treturn received\n\t}\n}\n\n// createChanClose closes the given channel.\nfunc (b *builder) createChanClose(ch llvm.Value) {\n\tb.createRuntimeCall(\"chanClose\", []llvm.Value{ch}, \"\")\n}\n\n// createSelect emits all IR necessary for a select statements. That's a\n// non-trivial amount of code because select is very complex to implement.\nfunc (b *builder) createSelect(expr *ssa.Select) llvm.Value {\n\tif len(expr.States) == 0 {\n\t\t// Shortcuts for some simple selects.\n\t\tllvmType := b.getLLVMType(expr.Type())\n\t\tif expr.Blocking {\n\t\t\t// Blocks forever:\n\t\t\t//     select {}\n\t\t\tb.createRuntimeCall(\"deadlock\", nil, \"\")\n\t\t\treturn llvm.Undef(llvmType)\n\t\t} else {\n\t\t\t// No-op:\n\t\t\t//     select {\n\t\t\t//     default:\n\t\t\t//     }\n\t\t\tretval := llvm.Undef(llvmType)\n\t\t\tretval = b.CreateInsertValue(retval, llvm.ConstInt(b.intType, 0xffffffffffffffff, true), 0, \"\")\n\t\t\treturn retval // {-1, false}\n\t\t}\n\t}\n\n\tconst maxSelectStates = math.MaxUint32 >> 2\n\tif len(expr.States) > maxSelectStates {\n\t\t// The runtime code assumes that the number of state must fit in 30 bits\n\t\t// (so the select index can be stored in a uint32 with two bits reserved\n\t\t// for other purposes). It seems unlikely that a real program would have\n\t\t// that many states, but we check for this case anyway to be sure.\n\t\t// We use a uint32 (and not a uintptr or uint64) to avoid 64-bit atomic\n\t\t// operations which aren't available everywhere.\n\t\tb.addError(expr.Pos(), fmt.Sprintf(\"too many select states: got %d but the maximum supported number is %d\", len(expr.States), maxSelectStates))\n\n\t\t// Continue as usual (we'll generate broken code but the error will\n\t\t// prevent the compilation to complete).\n\t}\n\n\t// This code create a (stack-allocated) slice containing all the select\n\t// cases and then calls runtime.chanSelect to perform the actual select\n\t// statement.\n\t// Simple selects (blocking and with just one case) are already transformed\n\t// into regular chan operations during SSA construction so we don't have to\n\t// optimize such small selects.\n\n\t// Go through all the cases. Create the selectStates slice and and\n\t// determine the receive buffer size and alignment.\n\trecvbufSize := uint64(0)\n\trecvbufAlign := 0\n\tvar selectStates []llvm.Value\n\tchanSelectStateType := b.getLLVMRuntimeType(\"chanSelectState\")\n\tfor _, state := range expr.States {\n\t\tch := b.getValue(state.Chan, state.Pos)\n\t\tselectState := llvm.ConstNull(chanSelectStateType)\n\t\tselectState = b.CreateInsertValue(selectState, ch, 0, \"\")\n\t\tswitch state.Dir {\n\t\tcase types.RecvOnly:\n\t\t\t// Make sure the receive buffer is big enough and has the correct alignment.\n\t\t\tllvmType := b.getLLVMType(state.Chan.Type().Underlying().(*types.Chan).Elem())\n\t\t\tif size := b.targetData.TypeAllocSize(llvmType); size > recvbufSize {\n\t\t\t\trecvbufSize = size\n\t\t\t}\n\t\t\tif align := b.targetData.ABITypeAlignment(llvmType); align > recvbufAlign {\n\t\t\t\trecvbufAlign = align\n\t\t\t}\n\t\tcase types.SendOnly:\n\t\t\t// Store this value in an alloca and put a pointer to this alloca\n\t\t\t// in the send state.\n\t\t\tsendValue := b.getValue(state.Send, state.Pos)\n\t\t\talloca := llvmutil.CreateEntryBlockAlloca(b.Builder, sendValue.Type(), \"select.send.value\")\n\t\t\tb.CreateStore(sendValue, alloca)\n\t\t\tselectState = b.CreateInsertValue(selectState, alloca, 1, \"\")\n\t\tdefault:\n\t\t\tpanic(\"unreachable\")\n\t\t}\n\t\tselectStates = append(selectStates, selectState)\n\t}\n\n\t// Create a receive buffer, where the received value will be stored.\n\trecvbuf := llvm.Undef(b.dataPtrType)\n\tif recvbufSize != 0 {\n\t\tallocaType := llvm.ArrayType(b.ctx.Int8Type(), int(recvbufSize))\n\t\trecvbufAlloca, _ := b.createTemporaryAlloca(allocaType, \"select.recvbuf.alloca\")\n\t\trecvbufAlloca.SetAlignment(recvbufAlign)\n\t\trecvbuf = b.CreateGEP(allocaType, recvbufAlloca, []llvm.Value{\n\t\t\tllvm.ConstInt(b.ctx.Int32Type(), 0, false),\n\t\t\tllvm.ConstInt(b.ctx.Int32Type(), 0, false),\n\t\t}, \"select.recvbuf\")\n\t}\n\n\t// Create the states slice (allocated on the stack).\n\tstatesAllocaType := llvm.ArrayType(chanSelectStateType, len(selectStates))\n\tstatesAlloca, statesSize := b.createTemporaryAlloca(statesAllocaType, \"select.states.alloca\")\n\tfor i, state := range selectStates {\n\t\t// Set each slice element to the appropriate channel.\n\t\tgep := b.CreateGEP(statesAllocaType, statesAlloca, []llvm.Value{\n\t\t\tllvm.ConstInt(b.ctx.Int32Type(), 0, false),\n\t\t\tllvm.ConstInt(b.ctx.Int32Type(), uint64(i), false),\n\t\t}, \"\")\n\t\tb.CreateStore(state, gep)\n\t}\n\tstatesPtr := b.CreateGEP(statesAllocaType, statesAlloca, []llvm.Value{\n\t\tllvm.ConstInt(b.ctx.Int32Type(), 0, false),\n\t\tllvm.ConstInt(b.ctx.Int32Type(), 0, false),\n\t}, \"select.states\")\n\tstatesLen := llvm.ConstInt(b.uintptrType, uint64(len(selectStates)), false)\n\n\t// Do the select in the runtime.\n\tvar results llvm.Value\n\tif expr.Blocking {\n\t\t// Stack-allocate operation structures.\n\t\t// If these were simply created as a slice, they would heap-allocate.\n\t\topsAllocaType := llvm.ArrayType(b.getLLVMRuntimeType(\"channelOp\"), len(selectStates))\n\t\topsAlloca, opsSize := b.createTemporaryAlloca(opsAllocaType, \"select.block.alloca\")\n\t\topsLen := llvm.ConstInt(b.uintptrType, uint64(len(selectStates)), false)\n\t\topsPtr := b.CreateGEP(opsAllocaType, opsAlloca, []llvm.Value{\n\t\t\tllvm.ConstInt(b.ctx.Int32Type(), 0, false),\n\t\t\tllvm.ConstInt(b.ctx.Int32Type(), 0, false),\n\t\t}, \"select.block\")\n\n\t\tresults = b.createRuntimeCall(\"chanSelect\", []llvm.Value{\n\t\t\trecvbuf,\n\t\t\tstatesPtr, statesLen, statesLen, // []chanSelectState\n\t\t\topsPtr, opsLen, opsLen, // []channelOp\n\t\t}, \"select.result\")\n\n\t\t// Terminate the lifetime of the operation structures.\n\t\tb.emitLifetimeEnd(opsAlloca, opsSize)\n\t} else {\n\t\topsPtr := llvm.ConstNull(b.dataPtrType)\n\t\topsLen := llvm.ConstInt(b.uintptrType, 0, false)\n\t\tresults = b.createRuntimeCall(\"chanSelect\", []llvm.Value{\n\t\t\trecvbuf,\n\t\t\tstatesPtr, statesLen, statesLen, // []chanSelectState\n\t\t\topsPtr, opsLen, opsLen, // []channelOp (nil slice)\n\t\t}, \"select.result\")\n\t}\n\n\t// Terminate the lifetime of the states alloca.\n\tb.emitLifetimeEnd(statesAlloca, statesSize)\n\n\t// The result value does not include all the possible received values,\n\t// because we can't load them in advance. Instead, the *ssa.Extract\n\t// instruction will treat a *ssa.Select specially and load it there inline.\n\t// Store the receive alloca in a sidetable until we hit this extract\n\t// instruction.\n\tif b.selectRecvBuf == nil {\n\t\tb.selectRecvBuf = make(map[*ssa.Select]llvm.Value)\n\t}\n\tb.selectRecvBuf[expr] = recvbuf\n\n\treturn results\n}\n\n// getChanSelectResult returns the special values from a *ssa.Extract expression\n// when extracting a value from a select statement (*ssa.Select). Because\n// *ssa.Select cannot load all values in advance, it does this later in the\n// *ssa.Extract expression.\nfunc (b *builder) getChanSelectResult(expr *ssa.Extract) llvm.Value {\n\tif expr.Index == 0 {\n\t\t// index\n\t\tvalue := b.getValue(expr.Tuple, getPos(expr))\n\t\tindex := b.CreateExtractValue(value, expr.Index, \"\")\n\t\tif index.Type().IntTypeWidth() < b.intType.IntTypeWidth() {\n\t\t\tindex = b.CreateSExt(index, b.intType, \"\")\n\t\t}\n\t\treturn index\n\t} else if expr.Index == 1 {\n\t\t// comma-ok\n\t\tvalue := b.getValue(expr.Tuple, getPos(expr))\n\t\treturn b.CreateExtractValue(value, expr.Index, \"\")\n\t} else {\n\t\t// Select statements are (index, ok, ...) where ... is a number of\n\t\t// received values, depending on how many receive statements there\n\t\t// are. They are all combined into one alloca (because only one\n\t\t// receive can proceed at a time) so we'll get that alloca, bitcast\n\t\t// it to the correct type, and dereference it.\n\t\trecvbuf := b.selectRecvBuf[expr.Tuple.(*ssa.Select)]\n\t\ttyp := b.getLLVMType(expr.Type())\n\t\treturn b.CreateLoad(typ, recvbuf, \"\")\n\t}\n}\n"
  },
  {
    "path": "compiler/compiler.go",
    "content": "package compiler\n\nimport (\n\t\"debug/dwarf\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"math/bits\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/tinygo-org/tinygo/compiler/llvmutil\"\n\t\"github.com/tinygo-org/tinygo/loader\"\n\t\"github.com/tinygo-org/tinygo/src/tinygo\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"golang.org/x/tools/go/types/typeutil\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\nfunc init() {\n\tllvm.InitializeAllTargets()\n\tllvm.InitializeAllTargetMCs()\n\tllvm.InitializeAllTargetInfos()\n\tllvm.InitializeAllAsmParsers()\n\tllvm.InitializeAllAsmPrinters()\n}\n\n// Config is the configuration for the compiler. Most settings should be copied\n// directly from compileopts.Config, it recreated here to decouple the compiler\n// package a bit and because it makes caching easier.\n//\n// This struct can be used for caching: if one of the flags here changes the\n// code must be recompiled.\ntype Config struct {\n\t// Target and output information.\n\tTriple          string\n\tCPU             string\n\tFeatures        string\n\tABI             string\n\tGOOS            string\n\tGOARCH          string\n\tBuildMode       string\n\tCodeModel       string\n\tRelocationModel string\n\tSizeLevel       int\n\tTinyGoVersion   string // for llvm.ident\n\n\t// Various compiler options that determine how code is generated.\n\tScheduler          string\n\tAutomaticStackSize bool\n\tDefaultStackSize   uint64\n\tMaxStackAlloc      uint64\n\tNeedsStackObjects  bool\n\tDebug              bool // Whether to emit debug information in the LLVM module.\n\tNobounds           bool // Whether to skip bounds checks\n\tPanicStrategy      string\n}\n\n// compilerContext contains function-independent data that should still be\n// available while compiling every function. It is not strictly read-only, but\n// must not contain function-dependent data such as an IR builder.\ntype compilerContext struct {\n\t*Config\n\tDumpSSA          bool\n\tmod              llvm.Module\n\tctx              llvm.Context\n\tbuilder          llvm.Builder // only used for constant operations\n\tdibuilder        *llvm.DIBuilder\n\tcu               llvm.Metadata\n\tdifiles          map[string]llvm.Metadata\n\tditypes          map[types.Type]llvm.Metadata\n\tllvmTypes        typeutil.Map\n\tinterfaceTypes   typeutil.Map\n\tmachine          llvm.TargetMachine\n\ttargetData       llvm.TargetData\n\tintType          llvm.Type\n\tdataPtrType      llvm.Type // pointer in address space 0\n\tfuncPtrType      llvm.Type // pointer in function address space (1 for AVR, 0 elsewhere)\n\tfuncPtrAddrSpace int\n\tuintptrType      llvm.Type\n\tprogram          *ssa.Program\n\tdiagnostics      []error\n\tfunctionInfos    map[*ssa.Function]functionInfo\n\tastComments      map[string]*ast.CommentGroup\n\tembedGlobals     map[string][]*loader.EmbedFile\n\tpkg              *types.Package\n\tpackageDir       string // directory for this package\n\truntimePkg       *types.Package\n}\n\n// newCompilerContext returns a new compiler context ready for use, most\n// importantly with a newly created LLVM context and module.\nfunc newCompilerContext(moduleName string, machine llvm.TargetMachine, config *Config, dumpSSA bool) *compilerContext {\n\tc := &compilerContext{\n\t\tConfig:        config,\n\t\tDumpSSA:       dumpSSA,\n\t\tdifiles:       make(map[string]llvm.Metadata),\n\t\tditypes:       make(map[types.Type]llvm.Metadata),\n\t\tmachine:       machine,\n\t\ttargetData:    machine.CreateTargetData(),\n\t\tfunctionInfos: map[*ssa.Function]functionInfo{},\n\t\tastComments:   map[string]*ast.CommentGroup{},\n\t}\n\n\tc.ctx = llvm.NewContext()\n\tc.builder = c.ctx.NewBuilder()\n\tc.mod = c.ctx.NewModule(moduleName)\n\tc.mod.SetTarget(config.Triple)\n\tc.mod.SetDataLayout(c.targetData.String())\n\tif c.Debug {\n\t\tc.dibuilder = llvm.NewDIBuilder(c.mod)\n\t}\n\n\tc.uintptrType = c.ctx.IntType(c.targetData.PointerSize() * 8)\n\tif c.targetData.PointerSize() <= 4 {\n\t\t// 8, 16, 32 bits targets\n\t\tc.intType = c.ctx.Int32Type()\n\t} else if c.targetData.PointerSize() == 8 {\n\t\t// 64 bits target\n\t\tc.intType = c.ctx.Int64Type()\n\t} else {\n\t\tpanic(\"unknown pointer size\")\n\t}\n\tc.dataPtrType = llvm.PointerType(c.ctx.Int8Type(), 0)\n\n\tdummyFuncType := llvm.FunctionType(c.ctx.VoidType(), nil, false)\n\tdummyFunc := llvm.AddFunction(c.mod, \"tinygo.dummy\", dummyFuncType)\n\tc.funcPtrAddrSpace = dummyFunc.Type().PointerAddressSpace()\n\tc.funcPtrType = dummyFunc.Type()\n\tdummyFunc.EraseFromParentAsFunction()\n\n\treturn c\n}\n\n// Dispose everything related to the context, _except_ for the IR module (and\n// the associated context).\nfunc (c *compilerContext) dispose() {\n\tc.builder.Dispose()\n}\n\n// builder contains all information relevant to build a single function.\ntype builder struct {\n\t*compilerContext\n\tllvm.Builder\n\tfn                *ssa.Function\n\tllvmFnType        llvm.Type\n\tllvmFn            llvm.Value\n\tinfo              functionInfo\n\tlocals            map[ssa.Value]llvm.Value // local variables\n\tblockInfo         []blockInfo\n\tcurrentBlock      *ssa.BasicBlock\n\tcurrentBlockInfo  *blockInfo\n\ttarjanStack       []uint\n\ttarjanIndex       uint\n\tphis              []phiNode\n\tdeferPtr          llvm.Value\n\tdeferFrame        llvm.Value\n\tstackChainAlloca  llvm.Value\n\tlandingpad        llvm.BasicBlock\n\tdifunc            llvm.Metadata\n\tdilocals          map[*types.Var]llvm.Metadata\n\tinitInlinedAt     llvm.Metadata            // fake inlinedAt position\n\tinitPseudoFuncs   map[string]llvm.Metadata // fake \"inlined\" functions for proper init debug locations\n\tallDeferFuncs     []interface{}\n\tdeferFuncs        map[*ssa.Function]int\n\tdeferInvokeFuncs  map[string]int\n\tdeferClosureFuncs map[*ssa.Function]int\n\tdeferExprFuncs    map[ssa.Value]int\n\tselectRecvBuf     map[*ssa.Select]llvm.Value\n\tdeferBuiltinFuncs map[ssa.Value]deferBuiltin\n\trunDefersBlock    []llvm.BasicBlock\n\tafterDefersBlock  []llvm.BasicBlock\n}\n\nfunc newBuilder(c *compilerContext, irbuilder llvm.Builder, f *ssa.Function) *builder {\n\tfnType, fn := c.getFunction(f)\n\treturn &builder{\n\t\tcompilerContext: c,\n\t\tBuilder:         irbuilder,\n\t\tfn:              f,\n\t\tllvmFnType:      fnType,\n\t\tllvmFn:          fn,\n\t\tinfo:            c.getFunctionInfo(f),\n\t\tlocals:          make(map[ssa.Value]llvm.Value),\n\t\tdilocals:        make(map[*types.Var]llvm.Metadata),\n\t}\n}\n\ntype blockInfo struct {\n\t// entry is the LLVM basic block corresponding to the start of this *ssa.Block.\n\tentry llvm.BasicBlock\n\n\t// exit is the LLVM basic block corresponding to the end of this *ssa.Block.\n\t// It will be different than entry if any of the block's instructions contain internal branches.\n\texit llvm.BasicBlock\n\n\t// tarjan holds state for applying Tarjan's strongly connected components algorithm to the CFG.\n\t// This is used by defer.go to determine whether to stack- or heap-allocate defer data.\n\ttarjan tarjanNode\n}\n\ntype deferBuiltin struct {\n\tcallName string\n\tpos      token.Pos\n\targTypes []types.Type\n\tcallback int\n}\n\ntype phiNode struct {\n\tssa  *ssa.Phi\n\tllvm llvm.Value\n}\n\n// NewTargetMachine returns a new llvm.TargetMachine based on the passed-in\n// configuration. It is used by the compiler and is needed for machine code\n// emission.\nfunc NewTargetMachine(config *Config) (llvm.TargetMachine, error) {\n\ttarget, err := llvm.GetTargetFromTriple(config.Triple)\n\tif err != nil {\n\t\treturn llvm.TargetMachine{}, err\n\t}\n\n\tvar codeModel llvm.CodeModel\n\tvar relocationModel llvm.RelocMode\n\n\tswitch config.CodeModel {\n\tcase \"default\":\n\t\tcodeModel = llvm.CodeModelDefault\n\tcase \"tiny\":\n\t\tcodeModel = llvm.CodeModelTiny\n\tcase \"small\":\n\t\tcodeModel = llvm.CodeModelSmall\n\tcase \"kernel\":\n\t\tcodeModel = llvm.CodeModelKernel\n\tcase \"medium\":\n\t\tcodeModel = llvm.CodeModelMedium\n\tcase \"large\":\n\t\tcodeModel = llvm.CodeModelLarge\n\t}\n\n\tswitch config.RelocationModel {\n\tcase \"static\":\n\t\trelocationModel = llvm.RelocStatic\n\tcase \"pic\":\n\t\trelocationModel = llvm.RelocPIC\n\tcase \"dynamicnopic\":\n\t\trelocationModel = llvm.RelocDynamicNoPic\n\t}\n\n\tmachine := target.CreateTargetMachine(config.Triple, config.CPU, config.Features, llvm.CodeGenLevelDefault, relocationModel, codeModel)\n\treturn machine, nil\n}\n\n// Sizes returns a types.Sizes appropriate for the given target machine. It\n// includes the correct int size and alignment as is necessary for the Go\n// typechecker.\nfunc Sizes(machine llvm.TargetMachine) types.Sizes {\n\ttargetData := machine.CreateTargetData()\n\tdefer targetData.Dispose()\n\n\tvar intWidth int\n\tif targetData.PointerSize() <= 4 {\n\t\t// 8, 16, 32 bits targets\n\t\tintWidth = 32\n\t} else if targetData.PointerSize() == 8 {\n\t\t// 64 bits target\n\t\tintWidth = 64\n\t} else {\n\t\tpanic(\"unknown pointer size\")\n\t}\n\n\t// Construct a complex128 type because that's likely the type with the\n\t// biggest alignment on most/all ABIs.\n\tctx := llvm.NewContext()\n\tdefer ctx.Dispose()\n\tcomplex128Type := ctx.StructType([]llvm.Type{ctx.DoubleType(), ctx.DoubleType()}, false)\n\treturn &stdSizes{\n\t\tIntSize:  int64(intWidth / 8),\n\t\tPtrSize:  int64(targetData.PointerSize()),\n\t\tMaxAlign: int64(targetData.ABITypeAlignment(complex128Type)),\n\t}\n}\n\n// CompilePackage compiles a single package to a LLVM module.\nfunc CompilePackage(moduleName string, pkg *loader.Package, ssaPkg *ssa.Package, machine llvm.TargetMachine, config *Config, dumpSSA bool) (llvm.Module, []error) {\n\tc := newCompilerContext(moduleName, machine, config, dumpSSA)\n\tdefer c.dispose()\n\tc.packageDir = pkg.OriginalDir()\n\tc.embedGlobals = pkg.EmbedGlobals\n\tc.pkg = pkg.Pkg\n\tc.runtimePkg = ssaPkg.Prog.ImportedPackage(\"runtime\").Pkg\n\tc.program = ssaPkg.Prog\n\n\t// Convert AST to SSA.\n\tssaPkg.Build()\n\n\t// Initialize debug information.\n\tif c.Debug {\n\t\tc.cu = c.dibuilder.CreateCompileUnit(llvm.DICompileUnit{\n\t\t\tLanguage:  0xb, // DW_LANG_C99 (0xc, off-by-one?)\n\t\t\tFile:      \"<unknown>\",\n\t\t\tDir:       \"\",\n\t\t\tProducer:  \"TinyGo\",\n\t\t\tOptimized: true,\n\t\t})\n\t}\n\n\t// Load comments such as //go:extern on globals.\n\tc.loadASTComments(pkg)\n\n\t// Predeclare the runtime.alloc function, which is used by the wordpack\n\t// functionality.\n\tc.getFunction(c.program.ImportedPackage(\"runtime\").Members[\"alloc\"].(*ssa.Function))\n\tif c.NeedsStackObjects {\n\t\t// Predeclare trackPointer, which is used everywhere we use runtime.alloc.\n\t\tc.getFunction(c.program.ImportedPackage(\"runtime\").Members[\"trackPointer\"].(*ssa.Function))\n\t}\n\n\t// Compile all functions, methods, and global variables in this package.\n\tirbuilder := c.ctx.NewBuilder()\n\tdefer irbuilder.Dispose()\n\tc.createPackage(irbuilder, ssaPkg)\n\n\t// see: https://reviews.llvm.org/D18355\n\tif c.Debug {\n\t\tc.mod.AddNamedMetadataOperand(\"llvm.module.flags\",\n\t\t\tc.ctx.MDNode([]llvm.Metadata{\n\t\t\t\tllvm.ConstInt(c.ctx.Int32Type(), 2, false).ConstantAsMetadata(), // Warning on mismatch\n\t\t\t\tc.ctx.MDString(\"Debug Info Version\"),\n\t\t\t\tllvm.ConstInt(c.ctx.Int32Type(), 3, false).ConstantAsMetadata(), // DWARF version\n\t\t\t}),\n\t\t)\n\t\tc.mod.AddNamedMetadataOperand(\"llvm.module.flags\",\n\t\t\tc.ctx.MDNode([]llvm.Metadata{\n\t\t\t\tllvm.ConstInt(c.ctx.Int32Type(), 7, false).ConstantAsMetadata(), // Max on mismatch\n\t\t\t\tc.ctx.MDString(\"Dwarf Version\"),\n\t\t\t\tllvm.ConstInt(c.ctx.Int32Type(), 4, false).ConstantAsMetadata(),\n\t\t\t}),\n\t\t)\n\t\tif c.TinyGoVersion != \"\" {\n\t\t\t// It is necessary to set llvm.ident, otherwise debugging on MacOS\n\t\t\t// won't work.\n\t\t\tc.mod.AddNamedMetadataOperand(\"llvm.ident\",\n\t\t\t\tc.ctx.MDNode(([]llvm.Metadata{\n\t\t\t\t\tc.ctx.MDString(\"TinyGo version \" + c.TinyGoVersion),\n\t\t\t\t})))\n\t\t}\n\t\tc.dibuilder.Finalize()\n\t\tc.dibuilder.Destroy()\n\t}\n\n\t// Add the \"target-abi\" flag, which is necessary on RISC-V otherwise it will\n\t// pick one that doesn't match the -mabi Clang flag.\n\tif c.ABI != \"\" {\n\t\tc.mod.AddNamedMetadataOperand(\"llvm.module.flags\",\n\t\t\tc.ctx.MDNode([]llvm.Metadata{\n\t\t\t\tllvm.ConstInt(c.ctx.Int32Type(), 1, false).ConstantAsMetadata(), // Error on mismatch\n\t\t\t\tc.ctx.MDString(\"target-abi\"),\n\t\t\t\tc.ctx.MDString(c.ABI),\n\t\t\t}),\n\t\t)\n\t}\n\n\treturn c.mod, c.diagnostics\n}\n\nfunc (c *compilerContext) getRuntimeType(name string) types.Type {\n\treturn c.runtimePkg.Scope().Lookup(name).(*types.TypeName).Type()\n}\n\n// getLLVMRuntimeType obtains a named type from the runtime package and returns\n// it as a LLVM type, creating it if necessary. It is a shorthand for\n// getLLVMType(getRuntimeType(name)).\nfunc (c *compilerContext) getLLVMRuntimeType(name string) llvm.Type {\n\treturn c.getLLVMType(c.getRuntimeType(name))\n}\n\n// getLLVMType returns a LLVM type for a Go type. It doesn't recreate already\n// created types. This is somewhat important for performance, but especially\n// important for named struct types (which should only be created once).\nfunc (c *compilerContext) getLLVMType(goType types.Type) llvm.Type {\n\t// Try to load the LLVM type from the cache.\n\t// Note: *types.Named isn't unique when working with generics.\n\t// See https://github.com/golang/go/issues/53914\n\t// This is the reason for using typeutil.Map to lookup LLVM types for Go types.\n\tival := c.llvmTypes.At(goType)\n\tif ival != nil {\n\t\treturn ival.(llvm.Type)\n\t}\n\t// Not already created, so adding this type to the cache.\n\tllvmType := c.makeLLVMType(goType)\n\tc.llvmTypes.Set(goType, llvmType)\n\treturn llvmType\n}\n\n// makeLLVMType creates a LLVM type for a Go type. Don't call this, use\n// getLLVMType instead.\nfunc (c *compilerContext) makeLLVMType(goType types.Type) llvm.Type {\n\tswitch typ := types.Unalias(goType).(type) {\n\tcase *types.Array:\n\t\telemType := c.getLLVMType(typ.Elem())\n\t\treturn llvm.ArrayType(elemType, int(typ.Len()))\n\tcase *types.Basic:\n\t\tswitch typ.Kind() {\n\t\tcase types.Bool, types.UntypedBool:\n\t\t\treturn c.ctx.Int1Type()\n\t\tcase types.Int8, types.Uint8:\n\t\t\treturn c.ctx.Int8Type()\n\t\tcase types.Int16, types.Uint16:\n\t\t\treturn c.ctx.Int16Type()\n\t\tcase types.Int32, types.Uint32:\n\t\t\treturn c.ctx.Int32Type()\n\t\tcase types.Int, types.Uint:\n\t\t\treturn c.intType\n\t\tcase types.Int64, types.Uint64:\n\t\t\treturn c.ctx.Int64Type()\n\t\tcase types.Float32:\n\t\t\treturn c.ctx.FloatType()\n\t\tcase types.Float64:\n\t\t\treturn c.ctx.DoubleType()\n\t\tcase types.Complex64:\n\t\t\treturn c.ctx.StructType([]llvm.Type{c.ctx.FloatType(), c.ctx.FloatType()}, false)\n\t\tcase types.Complex128:\n\t\t\treturn c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(), c.ctx.DoubleType()}, false)\n\t\tcase types.String, types.UntypedString:\n\t\t\treturn c.getLLVMRuntimeType(\"_string\")\n\t\tcase types.Uintptr:\n\t\t\treturn c.uintptrType\n\t\tcase types.UnsafePointer:\n\t\t\treturn c.dataPtrType\n\t\tdefault:\n\t\t\tpanic(\"unknown basic type: \" + typ.String())\n\t\t}\n\tcase *types.Chan, *types.Map, *types.Pointer:\n\t\treturn c.dataPtrType // all pointers are the same\n\tcase *types.Interface:\n\t\treturn c.getLLVMRuntimeType(\"_interface\")\n\tcase *types.Named:\n\t\tif st, ok := typ.Underlying().(*types.Struct); ok {\n\t\t\t// Structs are a special case. While other named types are ignored\n\t\t\t// in LLVM IR, named structs are implemented as named structs in\n\t\t\t// LLVM. This is because it is otherwise impossible to create\n\t\t\t// self-referencing types such as linked lists.\n\t\t\tllvmName := typ.String()\n\t\t\tllvmType := c.ctx.StructCreateNamed(llvmName)\n\t\t\tc.llvmTypes.Set(goType, llvmType) // avoid infinite recursion\n\t\t\tunderlying := c.getLLVMType(st)\n\t\t\tllvmType.StructSetBody(underlying.StructElementTypes(), false)\n\t\t\treturn llvmType\n\t\t}\n\t\treturn c.getLLVMType(typ.Underlying())\n\tcase *types.Signature: // function value\n\t\treturn c.getFuncType(typ)\n\tcase *types.Slice:\n\t\tmembers := []llvm.Type{\n\t\t\tc.dataPtrType,\n\t\t\tc.uintptrType, // len\n\t\t\tc.uintptrType, // cap\n\t\t}\n\t\treturn c.ctx.StructType(members, false)\n\tcase *types.Struct:\n\t\tmembers := make([]llvm.Type, typ.NumFields())\n\t\tfor i := 0; i < typ.NumFields(); i++ {\n\t\t\tmembers[i] = c.getLLVMType(typ.Field(i).Type())\n\t\t}\n\t\treturn c.ctx.StructType(members, false)\n\tcase *types.TypeParam:\n\t\treturn c.getLLVMType(typ.Underlying())\n\tcase *types.Tuple:\n\t\tmembers := make([]llvm.Type, typ.Len())\n\t\tfor i := 0; i < typ.Len(); i++ {\n\t\t\tmembers[i] = c.getLLVMType(typ.At(i).Type())\n\t\t}\n\t\treturn c.ctx.StructType(members, false)\n\tdefault:\n\t\tpanic(\"unknown type: \" + goType.String())\n\t}\n}\n\n// Is this a pointer type of some sort? Can be unsafe.Pointer or any *T pointer.\nfunc isPointer(typ types.Type) bool {\n\tif _, ok := typ.(*types.Pointer); ok {\n\t\treturn true\n\t} else if typ, ok := typ.(*types.Basic); ok && typ.Kind() == types.UnsafePointer {\n\t\treturn true\n\t} else {\n\t\treturn false\n\t}\n}\n\n// Get the DWARF type for this Go type.\nfunc (c *compilerContext) getDIType(typ types.Type) llvm.Metadata {\n\tif md, ok := c.ditypes[typ]; ok {\n\t\treturn md\n\t}\n\tmd := c.createDIType(typ)\n\tc.ditypes[typ] = md\n\treturn md\n}\n\n// createDIType creates a new DWARF type. Don't call this function directly,\n// call getDIType instead.\nfunc (c *compilerContext) createDIType(typ types.Type) llvm.Metadata {\n\tllvmType := c.getLLVMType(typ)\n\tsizeInBytes := c.targetData.TypeAllocSize(llvmType)\n\tswitch typ := typ.(type) {\n\tcase *types.Alias:\n\t\t// Implement types.Alias just like types.Named: by treating them like a\n\t\t// C typedef.\n\t\ttemporaryMDNode := c.dibuilder.CreateReplaceableCompositeType(llvm.Metadata{}, llvm.DIReplaceableCompositeType{\n\t\t\tTag:         dwarf.TagTypedef,\n\t\t\tSizeInBits:  sizeInBytes * 8,\n\t\t\tAlignInBits: uint32(c.targetData.ABITypeAlignment(llvmType)) * 8,\n\t\t})\n\t\tc.ditypes[typ] = temporaryMDNode\n\t\tmd := c.dibuilder.CreateTypedef(llvm.DITypedef{\n\t\t\tType: c.getDIType(types.Unalias(typ)), // TODO: use typ.Rhs in Go 1.23\n\t\t\tName: typ.String(),\n\t\t})\n\t\ttemporaryMDNode.ReplaceAllUsesWith(md)\n\t\treturn md\n\tcase *types.Array:\n\t\treturn c.dibuilder.CreateArrayType(llvm.DIArrayType{\n\t\t\tSizeInBits:  sizeInBytes * 8,\n\t\t\tAlignInBits: uint32(c.targetData.ABITypeAlignment(llvmType)) * 8,\n\t\t\tElementType: c.getDIType(typ.Elem()),\n\t\t\tSubscripts: []llvm.DISubrange{\n\t\t\t\t{\n\t\t\t\t\tLo:    0,\n\t\t\t\t\tCount: typ.Len(),\n\t\t\t\t},\n\t\t\t},\n\t\t})\n\tcase *types.Basic:\n\t\tvar encoding llvm.DwarfTypeEncoding\n\t\tif typ.Info()&types.IsBoolean != 0 {\n\t\t\tencoding = llvm.DW_ATE_boolean\n\t\t} else if typ.Info()&types.IsFloat != 0 {\n\t\t\tencoding = llvm.DW_ATE_float\n\t\t} else if typ.Info()&types.IsComplex != 0 {\n\t\t\tencoding = llvm.DW_ATE_complex_float\n\t\t} else if typ.Info()&types.IsUnsigned != 0 {\n\t\t\tencoding = llvm.DW_ATE_unsigned\n\t\t} else if typ.Info()&types.IsInteger != 0 {\n\t\t\tencoding = llvm.DW_ATE_signed\n\t\t} else if typ.Kind() == types.UnsafePointer {\n\t\t\treturn c.dibuilder.CreatePointerType(llvm.DIPointerType{\n\t\t\t\tName:         \"unsafe.Pointer\",\n\t\t\t\tSizeInBits:   c.targetData.TypeAllocSize(llvmType) * 8,\n\t\t\t\tAlignInBits:  uint32(c.targetData.ABITypeAlignment(llvmType)) * 8,\n\t\t\t\tAddressSpace: 0,\n\t\t\t})\n\t\t} else if typ.Info()&types.IsString != 0 {\n\t\t\treturn c.dibuilder.CreateStructType(llvm.Metadata{}, llvm.DIStructType{\n\t\t\t\tName:        \"string\",\n\t\t\t\tSizeInBits:  sizeInBytes * 8,\n\t\t\t\tAlignInBits: uint32(c.targetData.ABITypeAlignment(llvmType)) * 8,\n\t\t\t\tElements: []llvm.Metadata{\n\t\t\t\t\tc.dibuilder.CreateMemberType(llvm.Metadata{}, llvm.DIMemberType{\n\t\t\t\t\t\tName:         \"ptr\",\n\t\t\t\t\t\tSizeInBits:   c.targetData.TypeAllocSize(c.dataPtrType) * 8,\n\t\t\t\t\t\tAlignInBits:  uint32(c.targetData.ABITypeAlignment(c.dataPtrType)) * 8,\n\t\t\t\t\t\tOffsetInBits: 0,\n\t\t\t\t\t\tType:         c.getDIType(types.NewPointer(types.Typ[types.Byte])),\n\t\t\t\t\t}),\n\t\t\t\t\tc.dibuilder.CreateMemberType(llvm.Metadata{}, llvm.DIMemberType{\n\t\t\t\t\t\tName:         \"len\",\n\t\t\t\t\t\tSizeInBits:   c.targetData.TypeAllocSize(c.uintptrType) * 8,\n\t\t\t\t\t\tAlignInBits:  uint32(c.targetData.ABITypeAlignment(c.uintptrType)) * 8,\n\t\t\t\t\t\tOffsetInBits: c.targetData.ElementOffset(llvmType, 1) * 8,\n\t\t\t\t\t\tType:         c.getDIType(types.Typ[types.Uintptr]),\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t})\n\t\t} else {\n\t\t\tpanic(\"unknown basic type\")\n\t\t}\n\t\treturn c.dibuilder.CreateBasicType(llvm.DIBasicType{\n\t\t\tName:       typ.String(),\n\t\t\tSizeInBits: sizeInBytes * 8,\n\t\t\tEncoding:   encoding,\n\t\t})\n\tcase *types.Chan:\n\t\treturn c.getDIType(types.NewPointer(c.program.ImportedPackage(\"runtime\").Members[\"channel\"].(*ssa.Type).Type()))\n\tcase *types.Interface:\n\t\treturn c.getDIType(c.program.ImportedPackage(\"runtime\").Members[\"_interface\"].(*ssa.Type).Type())\n\tcase *types.Map:\n\t\treturn c.getDIType(types.NewPointer(c.program.ImportedPackage(\"runtime\").Members[\"hashmap\"].(*ssa.Type).Type()))\n\tcase *types.Named:\n\t\t// Placeholder metadata node, to be replaced afterwards.\n\t\ttemporaryMDNode := c.dibuilder.CreateReplaceableCompositeType(llvm.Metadata{}, llvm.DIReplaceableCompositeType{\n\t\t\tTag:         dwarf.TagTypedef,\n\t\t\tSizeInBits:  sizeInBytes * 8,\n\t\t\tAlignInBits: uint32(c.targetData.ABITypeAlignment(llvmType)) * 8,\n\t\t})\n\t\tc.ditypes[typ] = temporaryMDNode\n\t\tmd := c.dibuilder.CreateTypedef(llvm.DITypedef{\n\t\t\tType: c.getDIType(typ.Underlying()),\n\t\t\tName: typ.String(),\n\t\t})\n\t\ttemporaryMDNode.ReplaceAllUsesWith(md)\n\t\treturn md\n\tcase *types.Pointer:\n\t\treturn c.dibuilder.CreatePointerType(llvm.DIPointerType{\n\t\t\tPointee:      c.getDIType(typ.Elem()),\n\t\t\tSizeInBits:   c.targetData.TypeAllocSize(llvmType) * 8,\n\t\t\tAlignInBits:  uint32(c.targetData.ABITypeAlignment(llvmType)) * 8,\n\t\t\tAddressSpace: 0,\n\t\t})\n\tcase *types.Signature:\n\t\t// actually a closure\n\t\tfields := llvmType.StructElementTypes()\n\t\treturn c.dibuilder.CreateStructType(llvm.Metadata{}, llvm.DIStructType{\n\t\t\tSizeInBits:  sizeInBytes * 8,\n\t\t\tAlignInBits: uint32(c.targetData.ABITypeAlignment(llvmType)) * 8,\n\t\t\tElements: []llvm.Metadata{\n\t\t\t\tc.dibuilder.CreateMemberType(llvm.Metadata{}, llvm.DIMemberType{\n\t\t\t\t\tName:         \"context\",\n\t\t\t\t\tSizeInBits:   c.targetData.TypeAllocSize(fields[1]) * 8,\n\t\t\t\t\tAlignInBits:  uint32(c.targetData.ABITypeAlignment(fields[1])) * 8,\n\t\t\t\t\tOffsetInBits: 0,\n\t\t\t\t\tType:         c.getDIType(types.Typ[types.UnsafePointer]),\n\t\t\t\t}),\n\t\t\t\tc.dibuilder.CreateMemberType(llvm.Metadata{}, llvm.DIMemberType{\n\t\t\t\t\tName:         \"fn\",\n\t\t\t\t\tSizeInBits:   c.targetData.TypeAllocSize(fields[0]) * 8,\n\t\t\t\t\tAlignInBits:  uint32(c.targetData.ABITypeAlignment(fields[0])) * 8,\n\t\t\t\t\tOffsetInBits: c.targetData.ElementOffset(llvmType, 1) * 8,\n\t\t\t\t\tType:         c.getDIType(types.Typ[types.UnsafePointer]),\n\t\t\t\t}),\n\t\t\t},\n\t\t})\n\tcase *types.Slice:\n\t\tfields := llvmType.StructElementTypes()\n\t\treturn c.dibuilder.CreateStructType(llvm.Metadata{}, llvm.DIStructType{\n\t\t\tName:        typ.String(),\n\t\t\tSizeInBits:  sizeInBytes * 8,\n\t\t\tAlignInBits: uint32(c.targetData.ABITypeAlignment(llvmType)) * 8,\n\t\t\tElements: []llvm.Metadata{\n\t\t\t\tc.dibuilder.CreateMemberType(llvm.Metadata{}, llvm.DIMemberType{\n\t\t\t\t\tName:         \"ptr\",\n\t\t\t\t\tSizeInBits:   c.targetData.TypeAllocSize(fields[0]) * 8,\n\t\t\t\t\tAlignInBits:  uint32(c.targetData.ABITypeAlignment(fields[0])) * 8,\n\t\t\t\t\tOffsetInBits: 0,\n\t\t\t\t\tType:         c.getDIType(types.NewPointer(typ.Elem())),\n\t\t\t\t}),\n\t\t\t\tc.dibuilder.CreateMemberType(llvm.Metadata{}, llvm.DIMemberType{\n\t\t\t\t\tName:         \"len\",\n\t\t\t\t\tSizeInBits:   c.targetData.TypeAllocSize(c.uintptrType) * 8,\n\t\t\t\t\tAlignInBits:  uint32(c.targetData.ABITypeAlignment(c.uintptrType)) * 8,\n\t\t\t\t\tOffsetInBits: c.targetData.ElementOffset(llvmType, 1) * 8,\n\t\t\t\t\tType:         c.getDIType(types.Typ[types.Uintptr]),\n\t\t\t\t}),\n\t\t\t\tc.dibuilder.CreateMemberType(llvm.Metadata{}, llvm.DIMemberType{\n\t\t\t\t\tName:         \"cap\",\n\t\t\t\t\tSizeInBits:   c.targetData.TypeAllocSize(c.uintptrType) * 8,\n\t\t\t\t\tAlignInBits:  uint32(c.targetData.ABITypeAlignment(c.uintptrType)) * 8,\n\t\t\t\t\tOffsetInBits: c.targetData.ElementOffset(llvmType, 2) * 8,\n\t\t\t\t\tType:         c.getDIType(types.Typ[types.Uintptr]),\n\t\t\t\t}),\n\t\t\t},\n\t\t})\n\tcase *types.Struct:\n\t\telements := make([]llvm.Metadata, typ.NumFields())\n\t\tfor i := range elements {\n\t\t\tfield := typ.Field(i)\n\t\t\tfieldType := field.Type()\n\t\t\tllvmField := c.getLLVMType(fieldType)\n\t\t\telements[i] = c.dibuilder.CreateMemberType(llvm.Metadata{}, llvm.DIMemberType{\n\t\t\t\tName:         field.Name(),\n\t\t\t\tSizeInBits:   c.targetData.TypeAllocSize(llvmField) * 8,\n\t\t\t\tAlignInBits:  uint32(c.targetData.ABITypeAlignment(llvmField)) * 8,\n\t\t\t\tOffsetInBits: c.targetData.ElementOffset(llvmType, i) * 8,\n\t\t\t\tType:         c.getDIType(fieldType),\n\t\t\t})\n\t\t}\n\t\tmd := c.dibuilder.CreateStructType(llvm.Metadata{}, llvm.DIStructType{\n\t\t\tSizeInBits:  sizeInBytes * 8,\n\t\t\tAlignInBits: uint32(c.targetData.ABITypeAlignment(llvmType)) * 8,\n\t\t\tElements:    elements,\n\t\t})\n\t\treturn md\n\tcase *types.TypeParam:\n\t\treturn c.getDIType(typ.Underlying())\n\tdefault:\n\t\tpanic(\"unknown type while generating DWARF debug type: \" + typ.String())\n\t}\n}\n\n// setDebugLocation sets the current debug location for the builder.\nfunc (b *builder) setDebugLocation(pos token.Pos) {\n\tif pos == token.NoPos {\n\t\t// No debug information available for this instruction.\n\t\tb.SetCurrentDebugLocation(0, 0, b.difunc, llvm.Metadata{})\n\t\treturn\n\t}\n\n\tposition := b.program.Fset.Position(pos)\n\tif b.fn.Synthetic == \"package initializer\" {\n\t\t// Package initializers are treated specially, because while individual\n\t\t// Go SSA instructions have file/line/col information, the parent\n\t\t// function does not. LLVM doesn't store filename information per\n\t\t// instruction, only per function. We work around this difference by\n\t\t// creating a fake DIFunction for each Go file and say that the\n\t\t// instruction really came from that (fake) function but was inlined in\n\t\t// the package initializer function.\n\t\tposition := b.program.Fset.Position(pos)\n\t\tname := filepath.Base(position.Filename)\n\t\tdifunc, ok := b.initPseudoFuncs[name]\n\t\tif !ok {\n\t\t\tdiFuncType := b.dibuilder.CreateSubroutineType(llvm.DISubroutineType{\n\t\t\t\tFile: b.getDIFile(position.Filename),\n\t\t\t})\n\t\t\tdifunc = b.dibuilder.CreateFunction(b.getDIFile(position.Filename), llvm.DIFunction{\n\t\t\t\tName:         b.fn.RelString(nil) + \"#\" + name,\n\t\t\t\tFile:         b.getDIFile(position.Filename),\n\t\t\t\tLine:         0,\n\t\t\t\tType:         diFuncType,\n\t\t\t\tLocalToUnit:  true,\n\t\t\t\tIsDefinition: true,\n\t\t\t\tScopeLine:    0,\n\t\t\t\tFlags:        llvm.FlagPrototyped,\n\t\t\t\tOptimized:    true,\n\t\t\t})\n\t\t\tb.initPseudoFuncs[name] = difunc\n\t\t}\n\t\tb.SetCurrentDebugLocation(uint(position.Line), uint(position.Column), difunc, b.initInlinedAt)\n\t\treturn\n\t}\n\n\t// Regular debug information.\n\tb.SetCurrentDebugLocation(uint(position.Line), uint(position.Column), b.difunc, llvm.Metadata{})\n}\n\n// getLocalVariable returns a debug info entry for a local variable, which may\n// either be a parameter or a regular variable. It will create a new metadata\n// entry if there isn't one for the variable yet.\nfunc (b *builder) getLocalVariable(variable *types.Var) llvm.Metadata {\n\tif dilocal, ok := b.dilocals[variable]; ok {\n\t\t// DILocalVariable was already created, return it directly.\n\t\treturn dilocal\n\t}\n\n\tpos := b.program.Fset.Position(variable.Pos())\n\n\t// Check whether this is a function parameter.\n\tfor i, param := range b.fn.Params {\n\t\tif param.Object().(*types.Var) == variable {\n\t\t\t// Yes it is, create it as a function parameter.\n\t\t\tdilocal := b.dibuilder.CreateParameterVariable(b.difunc, llvm.DIParameterVariable{\n\t\t\t\tName:           param.Name(),\n\t\t\t\tFile:           b.getDIFile(pos.Filename),\n\t\t\t\tLine:           pos.Line,\n\t\t\t\tType:           b.getDIType(param.Type()),\n\t\t\t\tAlwaysPreserve: true,\n\t\t\t\tArgNo:          i + 1,\n\t\t\t})\n\t\t\tb.dilocals[variable] = dilocal\n\t\t\treturn dilocal\n\t\t}\n\t}\n\n\t// No, it's not a parameter. Create a regular (auto) variable.\n\tdilocal := b.dibuilder.CreateAutoVariable(b.difunc, llvm.DIAutoVariable{\n\t\tName:           variable.Name(),\n\t\tFile:           b.getDIFile(pos.Filename),\n\t\tLine:           pos.Line,\n\t\tType:           b.getDIType(variable.Type()),\n\t\tAlwaysPreserve: true,\n\t})\n\tb.dilocals[variable] = dilocal\n\treturn dilocal\n}\n\n// attachDebugInfo adds debug info to a function declaration. It returns the\n// DISubprogram metadata node.\nfunc (c *compilerContext) attachDebugInfo(f *ssa.Function) llvm.Metadata {\n\tpos := c.program.Fset.Position(f.Syntax().Pos())\n\t_, fn := c.getFunction(f)\n\treturn c.attachDebugInfoRaw(f, fn, \"\", pos.Filename, pos.Line)\n}\n\n// attachDebugInfo adds debug info to a function declaration. It returns the\n// DISubprogram metadata node. This method allows some more control over how\n// debug info is added to the function.\nfunc (c *compilerContext) attachDebugInfoRaw(f *ssa.Function, llvmFn llvm.Value, suffix, filename string, line int) llvm.Metadata {\n\t// Debug info for this function.\n\tparams := getParams(f.Signature)\n\tdiparams := make([]llvm.Metadata, 0, len(params))\n\tfor _, param := range params {\n\t\tdiparams = append(diparams, c.getDIType(param.Type()))\n\t}\n\tdiFuncType := c.dibuilder.CreateSubroutineType(llvm.DISubroutineType{\n\t\tFile:       c.getDIFile(filename),\n\t\tParameters: diparams,\n\t\tFlags:      0, // ?\n\t})\n\tdifunc := c.dibuilder.CreateFunction(c.getDIFile(filename), llvm.DIFunction{\n\t\tName:         f.RelString(nil) + suffix,\n\t\tLinkageName:  c.getFunctionInfo(f).linkName + suffix,\n\t\tFile:         c.getDIFile(filename),\n\t\tLine:         line,\n\t\tType:         diFuncType,\n\t\tLocalToUnit:  true,\n\t\tIsDefinition: true,\n\t\tScopeLine:    0,\n\t\tFlags:        llvm.FlagPrototyped,\n\t\tOptimized:    true,\n\t})\n\tllvmFn.SetSubprogram(difunc)\n\treturn difunc\n}\n\n// getDIFile returns a DIFile metadata node for the given filename. It tries to\n// use one that was already created, otherwise it falls back to creating a new\n// one.\nfunc (c *compilerContext) getDIFile(filename string) llvm.Metadata {\n\tif _, ok := c.difiles[filename]; !ok {\n\t\tdir, file := filepath.Split(filename)\n\t\tif dir != \"\" {\n\t\t\tdir = dir[:len(dir)-1]\n\t\t}\n\t\tc.difiles[filename] = c.dibuilder.CreateFile(file, dir)\n\t}\n\treturn c.difiles[filename]\n}\n\n// createPackage builds the LLVM IR for all types, methods, and global variables\n// in the given package.\nfunc (c *compilerContext) createPackage(irbuilder llvm.Builder, pkg *ssa.Package) {\n\t// Sort by position, so that the order of the functions in the IR matches\n\t// the order of functions in the source file. This is useful for testing,\n\t// for example.\n\tvar members []string\n\tfor name := range pkg.Members {\n\t\tmembers = append(members, name)\n\t}\n\tsort.Slice(members, func(i, j int) bool {\n\t\tiPos := pkg.Members[members[i]].Pos()\n\t\tjPos := pkg.Members[members[j]].Pos()\n\t\tif i == j {\n\t\t\t// Cannot sort by pos, so do it by name.\n\t\t\treturn members[i] < members[j]\n\t\t}\n\t\treturn iPos < jPos\n\t})\n\n\t// Define all functions.\n\tfor _, name := range members {\n\t\tmember := pkg.Members[name]\n\t\tswitch member := member.(type) {\n\t\tcase *ssa.Function:\n\t\t\tif member.TypeParams() != nil {\n\t\t\t\t// Do not try to build generic (non-instantiated) functions.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// Create the function definition.\n\t\t\tb := newBuilder(c, irbuilder, member)\n\t\t\tif _, ok := mathToLLVMMapping[member.RelString(nil)]; ok {\n\t\t\t\t// The body of this function (if there is one) is ignored and\n\t\t\t\t// replaced with a LLVM intrinsic call.\n\t\t\t\tb.defineMathOp()\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif ok := b.defineMathBitsIntrinsic(); ok {\n\t\t\t\t// Like a math intrinsic, the body of this function was replaced\n\t\t\t\t// with a LLVM intrinsic.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif member.Blocks == nil {\n\t\t\t\t// Try to define this as an intrinsic function.\n\t\t\t\tb.defineIntrinsicFunction()\n\t\t\t\t// It might not be an intrinsic function but simply an external\n\t\t\t\t// function (defined via //go:linkname). Leave it undefined in\n\t\t\t\t// that case.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tb.createFunction()\n\t\tcase *ssa.Type:\n\t\t\tif types.IsInterface(member.Type()) {\n\t\t\t\t// Interfaces don't have concrete methods.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif _, isalias := member.Type().(*types.Alias); isalias {\n\t\t\t\t// Aliases don't need to be redefined, since they just refer to\n\t\t\t\t// an already existing type whose methods will be defined.\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Named type. We should make sure all methods are created.\n\t\t\t// This includes both functions with pointer receivers and those\n\t\t\t// without.\n\t\t\tmethods := getAllMethods(pkg.Prog, member.Type())\n\t\t\tmethods = append(methods, getAllMethods(pkg.Prog, types.NewPointer(member.Type()))...)\n\t\t\tfor _, method := range methods {\n\t\t\t\t// Parse this method.\n\t\t\t\tfn := pkg.Prog.MethodValue(method)\n\t\t\t\tif fn == nil {\n\t\t\t\t\tcontinue // probably a generic method\n\t\t\t\t}\n\t\t\t\tif member.Type().String() != member.String() {\n\t\t\t\t\t// This is a member on a type alias. Do not build such a\n\t\t\t\t\t// function.\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif fn.Blocks == nil {\n\t\t\t\t\tcontinue // external function\n\t\t\t\t}\n\t\t\t\tif fn.Synthetic != \"\" && fn.Synthetic != \"package initializer\" {\n\t\t\t\t\t// This function is a kind of wrapper function (created by\n\t\t\t\t\t// the ssa package, not appearing in the source code) that\n\t\t\t\t\t// is created by the getFunction method as needed.\n\t\t\t\t\t// Therefore, don't build it here to avoid \"function\n\t\t\t\t\t// redeclared\" errors.\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t// Create the function definition.\n\t\t\t\tb := newBuilder(c, irbuilder, fn)\n\t\t\t\tb.createFunction()\n\t\t\t}\n\t\tcase *ssa.Global:\n\t\t\t// Global variable.\n\t\t\tinfo := c.getGlobalInfo(member)\n\t\t\tglobal := c.getGlobal(member)\n\t\t\tif files, ok := c.embedGlobals[member.Name()]; ok {\n\t\t\t\tc.createEmbedGlobal(member, global, files)\n\t\t\t} else if !info.extern {\n\t\t\t\tglobal.SetInitializer(llvm.ConstNull(global.GlobalValueType()))\n\t\t\t\tglobal.SetVisibility(llvm.HiddenVisibility)\n\t\t\t\tif info.section != \"\" {\n\t\t\t\t\tglobal.SetSection(info.section)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Add forwarding functions for functions that would otherwise be\n\t// implemented in assembly.\n\tfor _, name := range members {\n\t\tmember := pkg.Members[name]\n\t\tswitch member := member.(type) {\n\t\tcase *ssa.Function:\n\t\t\tif member.Blocks != nil {\n\t\t\t\tcontinue // external function\n\t\t\t}\n\t\t\tinfo := c.getFunctionInfo(member)\n\t\t\tif aliasName, ok := stdlibAliases[info.linkName]; ok {\n\t\t\t\talias := c.mod.NamedFunction(aliasName)\n\t\t\t\tif alias.IsNil() {\n\t\t\t\t\t// Shouldn't happen, but perhaps best to just ignore.\n\t\t\t\t\t// The error will be a link error, if there is an error.\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tb := newBuilder(c, irbuilder, member)\n\t\t\t\tb.createAlias(alias)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// createEmbedGlobal creates an initializer for a //go:embed global variable.\nfunc (c *compilerContext) createEmbedGlobal(member *ssa.Global, global llvm.Value, files []*loader.EmbedFile) {\n\tswitch typ := member.Type().(*types.Pointer).Elem().Underlying().(type) {\n\tcase *types.Basic:\n\t\t// String type.\n\t\tif typ.Kind() != types.String {\n\t\t\t// This is checked at the AST level, so should be unreachable.\n\t\t\tpanic(\"expected a string type\")\n\t\t}\n\t\tif len(files) != 1 {\n\t\t\tc.addError(member.Pos(), fmt.Sprintf(\"//go:embed for a string should be given exactly one file, got %d\", len(files)))\n\t\t\treturn\n\t\t}\n\t\tstrObj := c.getEmbedFileString(files[0])\n\t\tglobal.SetInitializer(strObj)\n\t\tglobal.SetVisibility(llvm.HiddenVisibility)\n\n\tcase *types.Slice:\n\t\tif typ.Elem().Underlying().(*types.Basic).Kind() != types.Byte {\n\t\t\t// This is checked at the AST level, so should be unreachable.\n\t\t\tpanic(\"expected a byte slice\")\n\t\t}\n\t\tif len(files) != 1 {\n\t\t\tc.addError(member.Pos(), fmt.Sprintf(\"//go:embed for a string should be given exactly one file, got %d\", len(files)))\n\t\t\treturn\n\t\t}\n\t\tfile := files[0]\n\t\tbufferValue := c.ctx.ConstString(string(file.Data), false)\n\t\tbufferGlobal := llvm.AddGlobal(c.mod, bufferValue.Type(), c.pkg.Path()+\"$embedslice\")\n\t\tbufferGlobal.SetInitializer(bufferValue)\n\t\tbufferGlobal.SetLinkage(llvm.InternalLinkage)\n\t\tbufferGlobal.SetAlignment(1)\n\t\tslicePtr := llvm.ConstInBoundsGEP(bufferValue.Type(), bufferGlobal, []llvm.Value{\n\t\t\tllvm.ConstInt(c.uintptrType, 0, false),\n\t\t\tllvm.ConstInt(c.uintptrType, 0, false),\n\t\t})\n\t\tsliceLen := llvm.ConstInt(c.uintptrType, file.Size, false)\n\t\tsliceObj := c.ctx.ConstStruct([]llvm.Value{slicePtr, sliceLen, sliceLen}, false)\n\t\tglobal.SetInitializer(sliceObj)\n\t\tglobal.SetVisibility(llvm.HiddenVisibility)\n\n\t\tif c.Debug {\n\t\t\t// Add debug info to the slice backing array.\n\t\t\tposition := c.program.Fset.Position(member.Pos())\n\t\t\tdiglobal := c.dibuilder.CreateGlobalVariableExpression(llvm.Metadata{}, llvm.DIGlobalVariableExpression{\n\t\t\t\tFile:        c.getDIFile(position.Filename),\n\t\t\t\tLine:        position.Line,\n\t\t\t\tType:        c.getDIType(types.NewArray(types.Typ[types.Byte], int64(len(file.Data)))),\n\t\t\t\tLocalToUnit: true,\n\t\t\t\tExpr:        c.dibuilder.CreateExpression(nil),\n\t\t\t})\n\t\t\tbufferGlobal.AddMetadata(0, diglobal)\n\t\t}\n\n\tcase *types.Struct:\n\t\t// Assume this is an embed.FS struct:\n\t\t// https://cs.opensource.google/go/go/+/refs/tags/go1.18.2:src/embed/embed.go;l=148\n\t\t// It looks like this:\n\t\t//   type FS struct {\n\t\t//       files *file\n\t\t//   }\n\n\t\t// Make a slice of the files, as they will appear in the binary. They\n\t\t// are sorted in a special way to allow for binary searches, see\n\t\t// src/embed/embed.go for details.\n\t\tdirset := map[string]struct{}{}\n\t\tvar allFiles []*loader.EmbedFile\n\t\tfor _, file := range files {\n\t\t\tallFiles = append(allFiles, file)\n\t\t\tdirname := file.Name\n\t\t\tfor {\n\t\t\t\tdirname, _ = path.Split(path.Clean(dirname))\n\t\t\t\tif dirname == \"\" {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tif _, ok := dirset[dirname]; ok {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tdirset[dirname] = struct{}{}\n\t\t\t\tallFiles = append(allFiles, &loader.EmbedFile{\n\t\t\t\t\tName: dirname,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\tsort.Slice(allFiles, func(i, j int) bool {\n\t\t\tdir1, name1 := path.Split(path.Clean(allFiles[i].Name))\n\t\t\tdir2, name2 := path.Split(path.Clean(allFiles[j].Name))\n\t\t\tif dir1 != dir2 {\n\t\t\t\treturn dir1 < dir2\n\t\t\t}\n\t\t\treturn name1 < name2\n\t\t})\n\n\t\t// Make the backing array for the []files slice. This is a LLVM global.\n\t\tembedFileStructType := typ.Field(0).Type().(*types.Pointer).Elem().(*types.Slice).Elem()\n\t\tllvmEmbedFileStructType := c.getLLVMType(embedFileStructType)\n\t\tvar fileStructs []llvm.Value\n\t\tfor _, file := range allFiles {\n\t\t\tfileStruct := llvm.ConstNull(llvmEmbedFileStructType)\n\t\t\tname := c.createConst(ssa.NewConst(constant.MakeString(file.Name), types.Typ[types.String]), getPos(member))\n\t\t\tfileStruct = c.builder.CreateInsertValue(fileStruct, name, 0, \"\") // \"name\" field\n\t\t\tif file.Hash != \"\" {\n\t\t\t\tdata := c.getEmbedFileString(file)\n\t\t\t\tfileStruct = c.builder.CreateInsertValue(fileStruct, data, 1, \"\") // \"data\" field\n\t\t\t}\n\t\t\tfileStructs = append(fileStructs, fileStruct)\n\t\t}\n\t\tsliceDataInitializer := llvm.ConstArray(llvmEmbedFileStructType, fileStructs)\n\t\tsliceDataGlobal := llvm.AddGlobal(c.mod, sliceDataInitializer.Type(), c.pkg.Path()+\"$embedfsfiles\")\n\t\tsliceDataGlobal.SetInitializer(sliceDataInitializer)\n\t\tsliceDataGlobal.SetLinkage(llvm.InternalLinkage)\n\t\tsliceDataGlobal.SetGlobalConstant(true)\n\t\tsliceDataGlobal.SetUnnamedAddr(true)\n\t\tsliceDataGlobal.SetAlignment(c.targetData.ABITypeAlignment(sliceDataInitializer.Type()))\n\t\tif c.Debug {\n\t\t\t// Add debug information for code size attribution (among others).\n\t\t\tposition := c.program.Fset.Position(member.Pos())\n\t\t\tdiglobal := c.dibuilder.CreateGlobalVariableExpression(llvm.Metadata{}, llvm.DIGlobalVariableExpression{\n\t\t\t\tFile:        c.getDIFile(position.Filename),\n\t\t\t\tLine:        position.Line,\n\t\t\t\tType:        c.getDIType(types.NewArray(embedFileStructType, int64(len(allFiles)))),\n\t\t\t\tLocalToUnit: true,\n\t\t\t\tExpr:        c.dibuilder.CreateExpression(nil),\n\t\t\t})\n\t\t\tsliceDataGlobal.AddMetadata(0, diglobal)\n\t\t}\n\n\t\t// Create the slice object itself.\n\t\t// Because embed.FS refers to it as *[]embed.file instead of a plain\n\t\t// []embed.file, we have to store this as a global.\n\t\tslicePtr := llvm.ConstInBoundsGEP(sliceDataInitializer.Type(), sliceDataGlobal, []llvm.Value{\n\t\t\tllvm.ConstInt(c.uintptrType, 0, false),\n\t\t\tllvm.ConstInt(c.uintptrType, 0, false),\n\t\t})\n\t\tsliceLen := llvm.ConstInt(c.uintptrType, uint64(len(fileStructs)), false)\n\t\tsliceInitializer := c.ctx.ConstStruct([]llvm.Value{slicePtr, sliceLen, sliceLen}, false)\n\t\tsliceGlobal := llvm.AddGlobal(c.mod, sliceInitializer.Type(), c.pkg.Path()+\"$embedfsslice\")\n\t\tsliceGlobal.SetInitializer(sliceInitializer)\n\t\tsliceGlobal.SetLinkage(llvm.InternalLinkage)\n\t\tsliceGlobal.SetGlobalConstant(true)\n\t\tsliceGlobal.SetUnnamedAddr(true)\n\t\tsliceGlobal.SetAlignment(c.targetData.ABITypeAlignment(sliceInitializer.Type()))\n\t\tif c.Debug {\n\t\t\tposition := c.program.Fset.Position(member.Pos())\n\t\t\tdiglobal := c.dibuilder.CreateGlobalVariableExpression(llvm.Metadata{}, llvm.DIGlobalVariableExpression{\n\t\t\t\tFile:        c.getDIFile(position.Filename),\n\t\t\t\tLine:        position.Line,\n\t\t\t\tType:        c.getDIType(types.NewSlice(embedFileStructType)),\n\t\t\t\tLocalToUnit: true,\n\t\t\t\tExpr:        c.dibuilder.CreateExpression(nil),\n\t\t\t})\n\t\t\tsliceGlobal.AddMetadata(0, diglobal)\n\t\t}\n\n\t\t// Define the embed.FS struct. It has only one field: the files (as a\n\t\t// *[]embed.file).\n\t\tglobalInitializer := llvm.ConstNull(c.getLLVMType(member.Type().(*types.Pointer).Elem()))\n\t\tglobalInitializer = c.builder.CreateInsertValue(globalInitializer, sliceGlobal, 0, \"\")\n\t\tglobal.SetInitializer(globalInitializer)\n\t\tglobal.SetVisibility(llvm.HiddenVisibility)\n\t\tglobal.SetAlignment(c.targetData.ABITypeAlignment(globalInitializer.Type()))\n\t}\n}\n\n// getEmbedFileString returns the (constant) string object with the contents of\n// the given file. This is a llvm.Value of a regular Go string.\nfunc (c *compilerContext) getEmbedFileString(file *loader.EmbedFile) llvm.Value {\n\tdataGlobalName := \"embed/file_\" + file.Hash\n\tdataGlobal := c.mod.NamedGlobal(dataGlobalName)\n\tdataGlobalType := llvm.ArrayType(c.ctx.Int8Type(), int(file.Size))\n\tif dataGlobal.IsNil() {\n\t\tdataGlobal = llvm.AddGlobal(c.mod, dataGlobalType, dataGlobalName)\n\t}\n\tstrPtr := llvm.ConstInBoundsGEP(dataGlobalType, dataGlobal, []llvm.Value{\n\t\tllvm.ConstInt(c.uintptrType, 0, false),\n\t\tllvm.ConstInt(c.uintptrType, 0, false),\n\t})\n\tstrLen := llvm.ConstInt(c.uintptrType, file.Size, false)\n\treturn llvm.ConstNamedStruct(c.getLLVMRuntimeType(\"_string\"), []llvm.Value{strPtr, strLen})\n}\n\n// Start defining a function so that it can be filled with instructions: load\n// parameters, create basic blocks, and set up debug information.\n// This is separated out from createFunction() so that it is also usable to\n// define compiler intrinsics like the atomic operations in sync/atomic.\nfunc (b *builder) createFunctionStart(intrinsic bool) {\n\tif b.DumpSSA {\n\t\tfmt.Printf(\"\\nfunc %s:\\n\", b.fn)\n\t}\n\tif !b.llvmFn.IsDeclaration() {\n\t\terrValue := b.llvmFn.Name() + \" redeclared in this program\"\n\t\tfnPos := getPosition(b.llvmFn)\n\t\tif fnPos.IsValid() {\n\t\t\terrValue += \"\\n\\tprevious declaration at \" + fnPos.String()\n\t\t}\n\t\tb.addError(b.fn.Pos(), errValue)\n\t\treturn\n\t}\n\n\tb.addStandardDefinedAttributes(b.llvmFn)\n\tif !b.info.exported {\n\t\t// Do not set visibility for local linkage (internal or private).\n\t\t// Otherwise a \"local linkage requires default visibility\"\n\t\t// assertion error in llvm-project/llvm/include/llvm/IR/GlobalValue.h:236\n\t\t// is thrown.\n\t\tif b.llvmFn.Linkage() != llvm.InternalLinkage &&\n\t\t\tb.llvmFn.Linkage() != llvm.PrivateLinkage {\n\t\t\tb.llvmFn.SetVisibility(llvm.HiddenVisibility)\n\t\t}\n\t\tb.llvmFn.SetUnnamedAddr(true)\n\t}\n\tif b.info.section != \"\" {\n\t\tb.llvmFn.SetSection(b.info.section)\n\t}\n\tif b.info.exported && strings.HasPrefix(b.Triple, \"wasm\") {\n\t\t// Set the exported name. This is necessary for WebAssembly because\n\t\t// otherwise the function is not exported.\n\t\tfunctionAttr := b.ctx.CreateStringAttribute(\"wasm-export-name\", b.info.linkName)\n\t\tb.llvmFn.AddFunctionAttr(functionAttr)\n\t\t// Unlike most targets, exported functions are actually visible in\n\t\t// WebAssembly (even if it's not called from within the WebAssembly\n\t\t// module). But LTO generally optimizes such functions away. Therefore,\n\t\t// exported functions must be explicitly marked as used.\n\t\tllvmutil.AppendToGlobal(b.mod, \"llvm.used\", b.llvmFn)\n\t}\n\n\t// Some functions have a pragma controlling the inlining level.\n\tswitch b.info.inline {\n\tcase inlineHint:\n\t\t// Add LLVM inline hint to functions with //go:inline pragma.\n\t\tinline := b.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"inlinehint\"), 0)\n\t\tb.llvmFn.AddFunctionAttr(inline)\n\tcase inlineNone:\n\t\t// Add LLVM attribute to always avoid inlining this function.\n\t\tnoinline := b.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"noinline\"), 0)\n\t\tb.llvmFn.AddFunctionAttr(noinline)\n\t}\n\n\tif b.info.interrupt {\n\t\t// Mark this function as an interrupt.\n\t\t// This is necessary on MCUs that don't push caller saved registers when\n\t\t// entering an interrupt, such as on AVR.\n\t\tif strings.HasPrefix(b.Triple, \"avr\") {\n\t\t\tb.llvmFn.AddFunctionAttr(b.ctx.CreateStringAttribute(\"signal\", \"\"))\n\t\t} else {\n\t\t\tb.addError(b.fn.Pos(), \"//go:interrupt not supported on this architecture\")\n\t\t}\n\t}\n\n\t// Add debug info, if needed.\n\tif b.Debug {\n\t\tif b.fn.Synthetic == \"package initializer\" {\n\t\t\t// Package initializer functions have no debug info. Create some\n\t\t\t// fake debug info to at least have *something*.\n\t\t\tb.difunc = b.attachDebugInfoRaw(b.fn, b.llvmFn, \"\", b.packageDir, 0)\n\t\t} else if b.fn.Syntax() != nil {\n\t\t\t// Create debug info file if needed.\n\t\t\tb.difunc = b.attachDebugInfo(b.fn)\n\t\t}\n\t\tb.setDebugLocation(b.fn.Pos())\n\t}\n\n\t// Pre-create all basic blocks in the function.\n\tvar entryBlock llvm.BasicBlock\n\tif intrinsic {\n\t\t// This function isn't defined in Go SSA. It is probably a compiler\n\t\t// intrinsic (like an atomic operation). Create the entry block\n\t\t// manually.\n\t\tentryBlock = b.ctx.AddBasicBlock(b.llvmFn, \"entry\")\n\t\t// Intrinsics may create internal branches (e.g. nil checks).\n\t\t// They will attempt to access b.currentBlockInfo to update the exit block.\n\t\t// Create some fake block info for them to access.\n\t\tblockInfo := []blockInfo{\n\t\t\t{\n\t\t\t\tentry: entryBlock,\n\t\t\t\texit:  entryBlock,\n\t\t\t},\n\t\t}\n\t\tb.blockInfo = blockInfo\n\t\tb.currentBlockInfo = &blockInfo[0]\n\t} else {\n\t\tblocks := b.fn.Blocks\n\t\tblockInfo := make([]blockInfo, len(blocks))\n\t\tfor _, block := range b.fn.DomPreorder() {\n\t\t\tinfo := &blockInfo[block.Index]\n\t\t\tllvmBlock := b.ctx.AddBasicBlock(b.llvmFn, block.Comment)\n\t\t\tinfo.entry = llvmBlock\n\t\t\tinfo.exit = llvmBlock\n\t\t}\n\t\tb.blockInfo = blockInfo\n\t\t// Normal functions have an entry block.\n\t\tentryBlock = blockInfo[0].entry\n\t}\n\tb.SetInsertPointAtEnd(entryBlock)\n\n\tif b.fn.Synthetic == \"package initializer\" {\n\t\tb.initPseudoFuncs = make(map[string]llvm.Metadata)\n\n\t\t// Create a fake 'inlined at' metadata node.\n\t\t// See setDebugLocation for details.\n\t\talloca := b.CreateAlloca(b.uintptrType, \"\")\n\t\tb.initInlinedAt = alloca.InstructionDebugLoc()\n\t\talloca.EraseFromParentAsInstruction()\n\t}\n\n\t// Load function parameters\n\tllvmParamIndex := 0\n\tfor _, param := range b.fn.Params {\n\t\tllvmType := b.getLLVMType(param.Type())\n\t\tfields := make([]llvm.Value, 0, 1)\n\t\tfor _, info := range b.expandFormalParamType(llvmType, param.Name(), param.Type()) {\n\t\t\tparam := b.llvmFn.Param(llvmParamIndex)\n\t\t\tparam.SetName(info.name)\n\t\t\tfields = append(fields, param)\n\t\t\tllvmParamIndex++\n\t\t}\n\t\tb.locals[param] = b.collapseFormalParam(llvmType, fields)\n\n\t\t// Add debug information to this parameter (if available)\n\t\tif b.Debug && b.fn.Syntax() != nil {\n\t\t\tdbgParam := b.getLocalVariable(param.Object().(*types.Var))\n\t\t\tloc := b.GetCurrentDebugLocation()\n\t\t\tif len(fields) == 1 {\n\t\t\t\texpr := b.dibuilder.CreateExpression(nil)\n\t\t\t\tb.dibuilder.InsertValueAtEnd(fields[0], dbgParam, expr, loc, entryBlock)\n\t\t\t} else {\n\t\t\t\tfieldOffsets := b.expandFormalParamOffsets(llvmType)\n\t\t\t\tfor i, field := range fields {\n\t\t\t\t\texpr := b.dibuilder.CreateExpression([]uint64{\n\t\t\t\t\t\t0x1000,              // DW_OP_LLVM_fragment\n\t\t\t\t\t\tfieldOffsets[i] * 8, // offset in bits\n\t\t\t\t\t\tb.targetData.TypeAllocSize(field.Type()) * 8, // size in bits\n\t\t\t\t\t})\n\t\t\t\t\tb.dibuilder.InsertValueAtEnd(field, dbgParam, expr, loc, entryBlock)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Load free variables from the context. This is a closure (or bound\n\t// method).\n\tvar context llvm.Value\n\tif !b.info.exported {\n\t\tcontext = b.llvmFn.LastParam()\n\t\tcontext.SetName(\"context\")\n\t}\n\tif len(b.fn.FreeVars) != 0 {\n\t\t// Get a list of all variable types in the context.\n\t\tfreeVarTypes := make([]llvm.Type, len(b.fn.FreeVars))\n\t\tfor i, freeVar := range b.fn.FreeVars {\n\t\t\tfreeVarTypes[i] = b.getLLVMType(freeVar.Type())\n\t\t}\n\n\t\t// Load each free variable from the context pointer.\n\t\t// A free variable is always a pointer when this is a closure, but it\n\t\t// can be another type when it is a wrapper for a bound method (these\n\t\t// wrappers are generated by the ssa package).\n\t\tfor i, val := range b.emitPointerUnpack(context, freeVarTypes) {\n\t\t\tb.locals[b.fn.FreeVars[i]] = val\n\t\t}\n\t}\n\n\tif b.fn.Recover != nil {\n\t\t// This function has deferred function calls. Set some things up for\n\t\t// them.\n\t\tb.deferInitFunc()\n\t}\n\n\tif b.NeedsStackObjects {\n\t\t// Create a dummy alloca that will be used in runtime.trackPointer.\n\t\t// It is necessary to pass a dummy alloca to runtime.trackPointer\n\t\t// because runtime.trackPointer is replaced by an alloca store.\n\t\tb.stackChainAlloca = b.CreateAlloca(b.ctx.Int8Type(), \"stackalloc\")\n\t}\n}\n\n// createFunction builds the LLVM IR implementation for this function. The\n// function must not yet be defined, otherwise this function will create a\n// diagnostic.\nfunc (b *builder) createFunction() {\n\tb.createFunctionStart(false)\n\n\t// Fill blocks with instructions.\n\tfor _, block := range b.fn.DomPreorder() {\n\t\tif b.DumpSSA {\n\t\t\tfmt.Printf(\"%d: %s:\\n\", block.Index, block.Comment)\n\t\t}\n\t\tb.currentBlock = block\n\t\tb.currentBlockInfo = &b.blockInfo[block.Index]\n\t\tb.SetInsertPointAtEnd(b.currentBlockInfo.entry)\n\t\tfor _, instr := range block.Instrs {\n\t\t\tif instr, ok := instr.(*ssa.DebugRef); ok {\n\t\t\t\tif !b.Debug {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tobject := instr.Object()\n\t\t\t\tvariable, ok := object.(*types.Var)\n\t\t\t\tif !ok {\n\t\t\t\t\t// Not a local variable.\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif instr.IsAddr {\n\t\t\t\t\t// TODO, this may happen for *ssa.Alloc and *ssa.FieldAddr\n\t\t\t\t\t// for example.\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tdbgVar := b.getLocalVariable(variable)\n\t\t\t\tpos := b.program.Fset.Position(instr.Pos())\n\t\t\t\tb.dibuilder.InsertValueAtEnd(b.getValue(instr.X, getPos(instr)), dbgVar, b.dibuilder.CreateExpression(nil), llvm.DebugLoc{\n\t\t\t\t\tLine:  uint(pos.Line),\n\t\t\t\t\tCol:   uint(pos.Column),\n\t\t\t\t\tScope: b.difunc,\n\t\t\t\t}, b.GetInsertBlock())\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif b.DumpSSA {\n\t\t\t\tif val, ok := instr.(ssa.Value); ok && val.Name() != \"\" {\n\t\t\t\t\tfmt.Printf(\"\\t%s = %s\\n\", val.Name(), val.String())\n\t\t\t\t} else {\n\t\t\t\t\tfmt.Printf(\"\\t%s\\n\", instr.String())\n\t\t\t\t}\n\t\t\t}\n\t\t\tb.createInstruction(instr)\n\t\t}\n\t\tif b.fn.Name() == \"init\" && len(block.Instrs) == 0 {\n\t\t\tb.CreateRetVoid()\n\t\t}\n\t}\n\n\t// The rundefers instruction needs to be created after all defer\n\t// instructions have been created. Otherwise it won't handle all defer\n\t// cases.\n\tfor i, bb := range b.runDefersBlock {\n\t\tb.SetInsertPointAtEnd(bb)\n\t\tb.createRunDefers()\n\t\tb.CreateBr(b.afterDefersBlock[i])\n\t}\n\n\tif b.hasDeferFrame() {\n\t\t// Create the landing pad block, where execution continues after a\n\t\t// panic.\n\t\tb.createLandingPad()\n\t}\n\n\t// Resolve phi nodes\n\tfor _, phi := range b.phis {\n\t\tblock := phi.ssa.Block()\n\t\tfor i, edge := range phi.ssa.Edges {\n\t\t\tllvmVal := b.getValue(edge, getPos(phi.ssa))\n\t\t\tllvmBlock := b.blockInfo[block.Preds[i].Index].exit\n\t\t\tphi.llvm.AddIncoming([]llvm.Value{llvmVal}, []llvm.BasicBlock{llvmBlock})\n\t\t}\n\t}\n\n\tif b.NeedsStackObjects {\n\t\t// Track phi nodes.\n\t\tfor _, phi := range b.phis {\n\t\t\tinsertPoint := llvm.NextInstruction(phi.llvm)\n\t\t\tfor !insertPoint.IsAPHINode().IsNil() {\n\t\t\t\tinsertPoint = llvm.NextInstruction(insertPoint)\n\t\t\t}\n\t\t\tb.SetInsertPointBefore(insertPoint)\n\t\t\tb.trackValue(phi.llvm)\n\t\t}\n\t}\n\n\t// Create anonymous functions (closures etc.).\n\tfor _, sub := range b.fn.AnonFuncs {\n\t\tb := newBuilder(b.compilerContext, b.Builder, sub)\n\t\tb.llvmFn.SetLinkage(llvm.InternalLinkage)\n\t\tb.createFunction()\n\t}\n\n\t// Create wrapper function that can be called externally.\n\tif b.info.wasmExport != \"\" {\n\t\tb.createWasmExport()\n\t}\n}\n\n// posser is an interface that's implemented by both ssa.Value and\n// ssa.Instruction. It is implemented by everything that has a Pos() method,\n// which is all that getPos() needs.\ntype posser interface {\n\tPos() token.Pos\n}\n\n// getPos returns position information for a ssa.Value or ssa.Instruction.\n//\n// Not all instructions have position information, especially when they're\n// implicit (such as implicit casts or implicit returns at the end of a\n// function). In these cases, it makes sense to try a bit harder to guess what\n// the position really should be.\nfunc getPos(val posser) token.Pos {\n\tpos := val.Pos()\n\tif pos != token.NoPos {\n\t\t// Easy: position is known.\n\t\treturn pos\n\t}\n\n\t// No position information is known.\n\tswitch val := val.(type) {\n\tcase *ssa.MakeInterface:\n\t\treturn getPos(val.X)\n\tcase *ssa.MakeClosure:\n\t\treturn val.Fn.(*ssa.Function).Pos()\n\tcase *ssa.Return:\n\t\tsyntax := val.Parent().Syntax()\n\t\tif syntax != nil {\n\t\t\t// non-synthetic\n\t\t\treturn syntax.End()\n\t\t}\n\t\treturn token.NoPos\n\tcase *ssa.FieldAddr:\n\t\treturn getPos(val.X)\n\tcase *ssa.IndexAddr:\n\t\treturn getPos(val.X)\n\tcase *ssa.Slice:\n\t\treturn getPos(val.X)\n\tcase *ssa.Store:\n\t\treturn getPos(val.Addr)\n\tcase *ssa.Extract:\n\t\treturn getPos(val.Tuple)\n\tdefault:\n\t\t// This is reachable, for example with *ssa.Const, *ssa.If, and\n\t\t// *ssa.Jump. They might be implemented in some way in the future.\n\t\treturn token.NoPos\n\t}\n}\n\n// createInstruction builds the LLVM IR equivalent instructions for the\n// particular Go SSA instruction.\nfunc (b *builder) createInstruction(instr ssa.Instruction) {\n\tif b.Debug {\n\t\tb.setDebugLocation(getPos(instr))\n\t}\n\n\tswitch instr := instr.(type) {\n\tcase ssa.Value:\n\t\tif value, err := b.createExpr(instr); err != nil {\n\t\t\t// This expression could not be parsed. Add the error to the list\n\t\t\t// of diagnostics and continue with an undef value.\n\t\t\t// The resulting IR will be incorrect (but valid). However,\n\t\t\t// compilation can proceed which is useful because there may be\n\t\t\t// more compilation errors which can then all be shown together to\n\t\t\t// the user.\n\t\t\tb.diagnostics = append(b.diagnostics, err)\n\t\t\tb.locals[instr] = llvm.Undef(b.getLLVMType(instr.Type()))\n\t\t} else {\n\t\t\tb.locals[instr] = value\n\t\t\tif len(*instr.Referrers()) != 0 && b.NeedsStackObjects {\n\t\t\t\tb.trackExpr(instr, value)\n\t\t\t}\n\t\t}\n\tcase *ssa.DebugRef:\n\t\t// ignore\n\tcase *ssa.Defer:\n\t\tb.createDefer(instr)\n\tcase *ssa.Go:\n\t\t// Start a new goroutine.\n\t\tb.createGo(instr)\n\tcase *ssa.If:\n\t\tcond := b.getValue(instr.Cond, getPos(instr))\n\t\tblock := instr.Block()\n\t\tblockThen := b.blockInfo[block.Succs[0].Index].entry\n\t\tblockElse := b.blockInfo[block.Succs[1].Index].entry\n\t\tb.CreateCondBr(cond, blockThen, blockElse)\n\tcase *ssa.Jump:\n\t\tblockJump := b.blockInfo[instr.Block().Succs[0].Index].entry\n\t\tb.CreateBr(blockJump)\n\tcase *ssa.MapUpdate:\n\t\tm := b.getValue(instr.Map, getPos(instr))\n\t\tkey := b.getValue(instr.Key, getPos(instr))\n\t\tvalue := b.getValue(instr.Value, getPos(instr))\n\t\tmapType := instr.Map.Type().Underlying().(*types.Map)\n\t\tb.createMapUpdate(mapType.Key(), m, key, value, instr.Pos())\n\tcase *ssa.Panic:\n\t\tvalue := b.getValue(instr.X, getPos(instr))\n\t\tb.createRuntimeInvoke(\"_panic\", []llvm.Value{value}, \"\")\n\t\tb.CreateUnreachable()\n\tcase *ssa.Return:\n\t\tif b.hasDeferFrame() {\n\t\t\tb.createRuntimeCall(\"destroyDeferFrame\", []llvm.Value{b.deferFrame}, \"\")\n\t\t}\n\t\tif len(instr.Results) == 0 {\n\t\t\tb.CreateRetVoid()\n\t\t} else if len(instr.Results) == 1 {\n\t\t\tb.CreateRet(b.getValue(instr.Results[0], getPos(instr)))\n\t\t} else {\n\t\t\t// Multiple return values. Put them all in a struct.\n\t\t\tretVal := llvm.ConstNull(b.llvmFn.GlobalValueType().ReturnType())\n\t\t\tfor i, result := range instr.Results {\n\t\t\t\tval := b.getValue(result, getPos(instr))\n\t\t\t\tretVal = b.CreateInsertValue(retVal, val, i, \"\")\n\t\t\t}\n\t\t\tb.CreateRet(retVal)\n\t\t}\n\tcase *ssa.RunDefers:\n\t\t// Note where we're going to put the rundefers block\n\t\trun := b.insertBasicBlock(\"rundefers.block\")\n\t\tb.CreateBr(run)\n\t\tb.runDefersBlock = append(b.runDefersBlock, run)\n\n\t\tafter := b.insertBasicBlock(\"rundefers.after\")\n\t\tb.SetInsertPointAtEnd(after)\n\t\tb.afterDefersBlock = append(b.afterDefersBlock, after)\n\tcase *ssa.Send:\n\t\tb.createChanSend(instr)\n\tcase *ssa.Store:\n\t\tllvmAddr := b.getValue(instr.Addr, getPos(instr))\n\t\tllvmVal := b.getValue(instr.Val, getPos(instr))\n\t\tb.createNilCheck(instr.Addr, llvmAddr, \"store\")\n\t\tif b.targetData.TypeAllocSize(llvmVal.Type()) == 0 {\n\t\t\t// nothing to store\n\t\t\treturn\n\t\t}\n\t\tb.CreateStore(llvmVal, llvmAddr)\n\tdefault:\n\t\tb.addError(instr.Pos(), \"unknown instruction: \"+instr.String())\n\t}\n}\n\n// createBuiltin lowers a builtin Go function (append, close, delete, etc.) to\n// LLVM IR. It uses runtime calls for some builtins.\nfunc (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, callName string, pos token.Pos) (llvm.Value, error) {\n\tswitch callName {\n\tcase \"append\":\n\t\tsrc := argValues[0]\n\t\telems := argValues[1]\n\t\tsrcBuf := b.CreateExtractValue(src, 0, \"append.srcBuf\")\n\t\tsrcLen := b.CreateExtractValue(src, 1, \"append.srcLen\")\n\t\tsrcCap := b.CreateExtractValue(src, 2, \"append.srcCap\")\n\t\telemsBuf := b.CreateExtractValue(elems, 0, \"append.elemsBuf\")\n\t\telemsLen := b.CreateExtractValue(elems, 1, \"append.elemsLen\")\n\t\telemType := b.getLLVMType(argTypes[0].Underlying().(*types.Slice).Elem())\n\t\telemSize := llvm.ConstInt(b.uintptrType, b.targetData.TypeAllocSize(elemType), false)\n\t\tresult := b.createRuntimeCall(\"sliceAppend\", []llvm.Value{srcBuf, elemsBuf, srcLen, srcCap, elemsLen, elemSize}, \"append.new\")\n\t\tnewPtr := b.CreateExtractValue(result, 0, \"append.newPtr\")\n\t\tnewLen := b.CreateExtractValue(result, 1, \"append.newLen\")\n\t\tnewCap := b.CreateExtractValue(result, 2, \"append.newCap\")\n\t\tnewSlice := llvm.Undef(src.Type())\n\t\tnewSlice = b.CreateInsertValue(newSlice, newPtr, 0, \"\")\n\t\tnewSlice = b.CreateInsertValue(newSlice, newLen, 1, \"\")\n\t\tnewSlice = b.CreateInsertValue(newSlice, newCap, 2, \"\")\n\t\treturn newSlice, nil\n\tcase \"cap\":\n\t\tvalue := argValues[0]\n\t\tvar llvmCap llvm.Value\n\t\tswitch argTypes[0].Underlying().(type) {\n\t\tcase *types.Chan:\n\t\t\tllvmCap = b.createRuntimeCall(\"chanCap\", []llvm.Value{value}, \"cap\")\n\t\tcase *types.Slice:\n\t\t\tllvmCap = b.CreateExtractValue(value, 2, \"cap\")\n\t\tdefault:\n\t\t\treturn llvm.Value{}, b.makeError(pos, \"todo: cap: unknown type\")\n\t\t}\n\t\tif b.targetData.TypeAllocSize(llvmCap.Type()) < b.targetData.TypeAllocSize(b.intType) {\n\t\t\tllvmCap = b.CreateZExt(llvmCap, b.intType, \"len.int\")\n\t\t}\n\t\treturn llvmCap, nil\n\tcase \"close\":\n\t\tb.createChanClose(argValues[0])\n\t\treturn llvm.Value{}, nil\n\tcase \"complex\":\n\t\tr := argValues[0]\n\t\ti := argValues[1]\n\t\tt := argTypes[0].Underlying().(*types.Basic)\n\t\tvar cplx llvm.Value\n\t\tswitch t.Kind() {\n\t\tcase types.Float32:\n\t\t\tcplx = llvm.Undef(b.ctx.StructType([]llvm.Type{b.ctx.FloatType(), b.ctx.FloatType()}, false))\n\t\tcase types.Float64:\n\t\t\tcplx = llvm.Undef(b.ctx.StructType([]llvm.Type{b.ctx.DoubleType(), b.ctx.DoubleType()}, false))\n\t\tdefault:\n\t\t\treturn llvm.Value{}, b.makeError(pos, \"unsupported type in complex builtin: \"+t.String())\n\t\t}\n\t\tcplx = b.CreateInsertValue(cplx, r, 0, \"\")\n\t\tcplx = b.CreateInsertValue(cplx, i, 1, \"\")\n\t\treturn cplx, nil\n\tcase \"clear\":\n\t\tvalue := argValues[0]\n\t\tswitch typ := argTypes[0].Underlying().(type) {\n\t\tcase *types.Slice:\n\t\t\telementType := b.getLLVMType(typ.Elem())\n\t\t\telementSize := b.targetData.TypeAllocSize(elementType)\n\t\t\telementAlign := b.targetData.ABITypeAlignment(elementType)\n\n\t\t\t// The pointer to the data to be cleared.\n\t\t\tllvmBuf := b.CreateExtractValue(value, 0, \"buf\")\n\n\t\t\t// The length (in bytes) to be cleared.\n\t\t\tllvmLen := b.CreateExtractValue(value, 1, \"len\")\n\t\t\tllvmLen = b.CreateMul(llvmLen, llvm.ConstInt(llvmLen.Type(), elementSize, false), \"\")\n\n\t\t\t// Do the clear operation using the LLVM memset builtin.\n\t\t\t// This is also correct for nil slices: in those cases, len will be\n\t\t\t// 0 which means the memset call is a no-op (according to the LLVM\n\t\t\t// LangRef).\n\t\t\tmemset := b.getMemsetFunc()\n\t\t\tcall := b.createCall(memset.GlobalValueType(), memset, []llvm.Value{\n\t\t\t\tllvmBuf, // dest\n\t\t\t\tllvm.ConstInt(b.ctx.Int8Type(), 0, false), // val\n\t\t\t\tllvmLen, // len\n\t\t\t\tllvm.ConstInt(b.ctx.Int1Type(), 0, false), // isVolatile\n\t\t\t}, \"\")\n\t\t\tcall.AddCallSiteAttribute(1, b.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"align\"), uint64(elementAlign)))\n\n\t\t\treturn llvm.Value{}, nil\n\t\tcase *types.Map:\n\t\t\tm := argValues[0]\n\t\t\tb.createMapClear(m)\n\t\t\treturn llvm.Value{}, nil\n\t\tdefault:\n\t\t\treturn llvm.Value{}, b.makeError(pos, \"unsupported type in clear builtin: \"+typ.String())\n\t\t}\n\tcase \"copy\":\n\t\tdst := argValues[0]\n\t\tsrc := argValues[1]\n\t\tdstLen := b.CreateExtractValue(dst, 1, \"copy.dstLen\")\n\t\tsrcLen := b.CreateExtractValue(src, 1, \"copy.srcLen\")\n\t\tdstBuf := b.CreateExtractValue(dst, 0, \"copy.dstArray\")\n\t\tsrcBuf := b.CreateExtractValue(src, 0, \"copy.srcArray\")\n\t\telemType := b.getLLVMType(argTypes[0].Underlying().(*types.Slice).Elem())\n\t\telemSize := llvm.ConstInt(b.uintptrType, b.targetData.TypeAllocSize(elemType), false)\n\t\treturn b.createRuntimeCall(\"sliceCopy\", []llvm.Value{dstBuf, srcBuf, dstLen, srcLen, elemSize}, \"copy.n\"), nil\n\tcase \"delete\":\n\t\tm := argValues[0]\n\t\tkey := argValues[1]\n\t\treturn llvm.Value{}, b.createMapDelete(argTypes[1], m, key, pos)\n\tcase \"imag\":\n\t\tcplx := argValues[0]\n\t\treturn b.CreateExtractValue(cplx, 1, \"imag\"), nil\n\tcase \"len\":\n\t\tvalue := argValues[0]\n\t\tvar llvmLen llvm.Value\n\t\tswitch argTypes[0].Underlying().(type) {\n\t\tcase *types.Basic, *types.Slice:\n\t\t\t// string or slice\n\t\t\tllvmLen = b.CreateExtractValue(value, 1, \"len\")\n\t\tcase *types.Chan:\n\t\t\tllvmLen = b.createRuntimeCall(\"chanLen\", []llvm.Value{value}, \"len\")\n\t\tcase *types.Map:\n\t\t\tllvmLen = b.createRuntimeCall(\"hashmapLen\", []llvm.Value{value}, \"len\")\n\t\tdefault:\n\t\t\treturn llvm.Value{}, b.makeError(pos, \"todo: len: unknown type\")\n\t\t}\n\t\tif b.targetData.TypeAllocSize(llvmLen.Type()) < b.targetData.TypeAllocSize(b.intType) {\n\t\t\tllvmLen = b.CreateZExt(llvmLen, b.intType, \"len.int\")\n\t\t}\n\t\treturn llvmLen, nil\n\tcase \"min\", \"max\":\n\t\t// min and max builtins, added in Go 1.21.\n\t\t// We can simply reuse the existing binop comparison code, which has all\n\t\t// the edge cases figured out already.\n\t\ttok := token.LSS\n\t\tif callName == \"max\" {\n\t\t\ttok = token.GTR\n\t\t}\n\t\tresult := argValues[0]\n\t\ttyp := argTypes[0]\n\t\tfor _, arg := range argValues[1:] {\n\t\t\tcmp, err := b.createBinOp(tok, typ, typ, result, arg, pos)\n\t\t\tif err != nil {\n\t\t\t\treturn result, err\n\t\t\t}\n\t\t\tresult = b.CreateSelect(cmp, result, arg, \"\")\n\t\t}\n\t\treturn result, nil\n\tcase \"panic\":\n\t\t// This is rare, but happens in \"defer panic()\".\n\t\tb.createRuntimeInvoke(\"_panic\", argValues, \"\")\n\t\treturn llvm.Value{}, nil\n\tcase \"print\", \"println\":\n\t\tb.createRuntimeCall(\"printlock\", nil, \"\")\n\t\tfor i, value := range argValues {\n\t\t\tif i >= 1 && callName == \"println\" {\n\t\t\t\tb.createRuntimeCall(\"printspace\", nil, \"\")\n\t\t\t}\n\t\t\ttyp := argTypes[i].Underlying()\n\t\t\tswitch typ := typ.(type) {\n\t\t\tcase *types.Basic:\n\t\t\t\tswitch typ.Kind() {\n\t\t\t\tcase types.String, types.UntypedString:\n\t\t\t\t\tb.createRuntimeCall(\"printstring\", []llvm.Value{value}, \"\")\n\t\t\t\tcase types.Uintptr:\n\t\t\t\t\tb.createRuntimeCall(\"printptr\", []llvm.Value{value}, \"\")\n\t\t\t\tcase types.UnsafePointer:\n\t\t\t\t\tptrValue := b.CreatePtrToInt(value, b.uintptrType, \"\")\n\t\t\t\t\tb.createRuntimeCall(\"printptr\", []llvm.Value{ptrValue}, \"\")\n\t\t\t\tdefault:\n\t\t\t\t\t// runtime.print{int,uint}{8,16,32,64}\n\t\t\t\t\tif typ.Info()&types.IsInteger != 0 {\n\t\t\t\t\t\tname := \"print\"\n\t\t\t\t\t\tif typ.Info()&types.IsUnsigned != 0 {\n\t\t\t\t\t\t\tname += \"uint\"\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tname += \"int\"\n\t\t\t\t\t\t}\n\t\t\t\t\t\tname += strconv.FormatUint(b.targetData.TypeAllocSize(value.Type())*8, 10)\n\t\t\t\t\t\tb.createRuntimeCall(name, []llvm.Value{value}, \"\")\n\t\t\t\t\t} else if typ.Kind() == types.Bool {\n\t\t\t\t\t\tb.createRuntimeCall(\"printbool\", []llvm.Value{value}, \"\")\n\t\t\t\t\t} else if typ.Kind() == types.Float32 {\n\t\t\t\t\t\tb.createRuntimeCall(\"printfloat32\", []llvm.Value{value}, \"\")\n\t\t\t\t\t} else if typ.Kind() == types.Float64 {\n\t\t\t\t\t\tb.createRuntimeCall(\"printfloat64\", []llvm.Value{value}, \"\")\n\t\t\t\t\t} else if typ.Kind() == types.Complex64 {\n\t\t\t\t\t\tb.createRuntimeCall(\"printcomplex64\", []llvm.Value{value}, \"\")\n\t\t\t\t\t} else if typ.Kind() == types.Complex128 {\n\t\t\t\t\t\tb.createRuntimeCall(\"printcomplex128\", []llvm.Value{value}, \"\")\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn llvm.Value{}, b.makeError(pos, \"unknown basic arg type: \"+typ.String())\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tcase *types.Interface:\n\t\t\t\tb.createRuntimeCall(\"printitf\", []llvm.Value{value}, \"\")\n\t\t\tcase *types.Map:\n\t\t\t\tb.createRuntimeCall(\"printmap\", []llvm.Value{value}, \"\")\n\t\t\tcase *types.Pointer:\n\t\t\t\tptrValue := b.CreatePtrToInt(value, b.uintptrType, \"\")\n\t\t\t\tb.createRuntimeCall(\"printptr\", []llvm.Value{ptrValue}, \"\")\n\t\t\tcase *types.Slice:\n\t\t\t\tbufptr := b.CreateExtractValue(value, 0, \"\")\n\t\t\t\tbuflen := b.CreateExtractValue(value, 1, \"\")\n\t\t\t\tbufcap := b.CreateExtractValue(value, 2, \"\")\n\t\t\t\tptrValue := b.CreatePtrToInt(bufptr, b.uintptrType, \"\")\n\t\t\t\tb.createRuntimeCall(\"printslice\", []llvm.Value{ptrValue, buflen, bufcap}, \"\")\n\t\t\tdefault:\n\t\t\t\treturn llvm.Value{}, b.makeError(pos, \"unknown arg type: \"+typ.String())\n\t\t\t}\n\t\t}\n\t\tif callName == \"println\" {\n\t\t\tb.createRuntimeCall(\"printnl\", nil, \"\")\n\t\t}\n\t\tb.createRuntimeCall(\"printunlock\", nil, \"\")\n\t\treturn llvm.Value{}, nil // print() or println() returns void\n\tcase \"real\":\n\t\tcplx := argValues[0]\n\t\treturn b.CreateExtractValue(cplx, 0, \"real\"), nil\n\tcase \"recover\":\n\t\tuseParentFrame := uint64(0)\n\t\tif b.hasDeferFrame() {\n\t\t\t// recover() should return the panic value of the parent function,\n\t\t\t// not of the current function.\n\t\t\tuseParentFrame = 1\n\t\t}\n\t\treturn b.createRuntimeCall(\"_recover\", []llvm.Value{llvm.ConstInt(b.ctx.Int1Type(), useParentFrame, false)}, \"\"), nil\n\tcase \"ssa:wrapnilchk\":\n\t\t// TODO: do an actual nil check?\n\t\treturn argValues[0], nil\n\n\t// Builtins from the unsafe package.\n\tcase \"Add\": // unsafe.Add\n\t\t// This is basically just a GEP operation.\n\t\t// Note: the pointer is always of type *i8.\n\t\tptr := argValues[0]\n\t\tlen := argValues[1]\n\t\treturn b.CreateGEP(b.ctx.Int8Type(), ptr, []llvm.Value{len}, \"\"), nil\n\tcase \"Alignof\": // unsafe.Alignof\n\t\talign := b.targetData.ABITypeAlignment(argValues[0].Type())\n\t\treturn llvm.ConstInt(b.uintptrType, uint64(align), false), nil\n\tcase \"Offsetof\": // unsafe.Offsetof\n\t\t// This builtin is a bit harder to implement and may need a bit of\n\t\t// refactoring to work (it may be easier to implement if we have access\n\t\t// to the underlying Go SSA instruction). It is also rarely used: it\n\t\t// only applies in generic code and unsafe.Offsetof isn't very commonly\n\t\t// used anyway.\n\t\t// In other words, postpone it to some other day.\n\t\treturn llvm.Value{}, b.makeError(pos, \"todo: unsafe.Offsetof\")\n\tcase \"Sizeof\": // unsafe.Sizeof\n\t\tsize := b.targetData.TypeAllocSize(argValues[0].Type())\n\t\treturn llvm.ConstInt(b.uintptrType, size, false), nil\n\tcase \"Slice\", \"String\": // unsafe.Slice, unsafe.String\n\t\t// This creates a slice or string from a pointer and a length.\n\t\t// Note that the exception mentioned in the documentation (if the\n\t\t// pointer and length are nil, the slice is also nil) is trivially\n\t\t// already the case.\n\t\tptr := argValues[0]\n\t\tlen := argValues[1]\n\t\tvar elementType llvm.Type\n\t\tif callName == \"Slice\" {\n\t\t\telementType = b.getLLVMType(argTypes[0].Underlying().(*types.Pointer).Elem())\n\t\t} else {\n\t\t\telementType = b.ctx.Int8Type()\n\t\t}\n\t\tb.createUnsafeSliceStringCheck(\"unsafe.\"+callName, ptr, len, elementType, argTypes[1].Underlying().(*types.Basic))\n\t\tif len.Type().IntTypeWidth() < b.uintptrType.IntTypeWidth() {\n\t\t\t// Too small, zero-extend len.\n\t\t\tlen = b.CreateZExt(len, b.uintptrType, \"\")\n\t\t} else if len.Type().IntTypeWidth() > b.uintptrType.IntTypeWidth() {\n\t\t\t// Too big, truncate len.\n\t\t\tlen = b.CreateTrunc(len, b.uintptrType, \"\")\n\t\t}\n\t\tif callName == \"Slice\" {\n\t\t\tslice := llvm.Undef(b.ctx.StructType([]llvm.Type{\n\t\t\t\tptr.Type(),\n\t\t\t\tb.uintptrType,\n\t\t\t\tb.uintptrType,\n\t\t\t}, false))\n\t\t\tslice = b.CreateInsertValue(slice, ptr, 0, \"\")\n\t\t\tslice = b.CreateInsertValue(slice, len, 1, \"\")\n\t\t\tslice = b.CreateInsertValue(slice, len, 2, \"\")\n\t\t\treturn slice, nil\n\t\t} else {\n\t\t\tstr := llvm.Undef(b.getLLVMRuntimeType(\"_string\"))\n\t\t\tstr = b.CreateInsertValue(str, argValues[0], 0, \"\")\n\t\t\tstr = b.CreateInsertValue(str, len, 1, \"\")\n\t\t\treturn str, nil\n\t\t}\n\tcase \"SliceData\", \"StringData\": // unsafe.SliceData, unsafe.StringData\n\t\treturn b.CreateExtractValue(argValues[0], 0, \"slice.data\"), nil\n\tdefault:\n\t\treturn llvm.Value{}, b.makeError(pos, \"todo: builtin: \"+callName)\n\t}\n}\n\n// createFunctionCall lowers a Go SSA call instruction (to a simple function,\n// closure, function pointer, builtin, method, etc.) to LLVM IR, usually a call\n// instruction.\n//\n// This is also where compiler intrinsics are implemented.\nfunc (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error) {\n\t// See if this is an intrinsic function that is handled specially.\n\tif fn := instr.StaticCallee(); fn != nil {\n\t\t// Direct function call, either to a named or anonymous (directly\n\t\t// applied) function call. If it is anonymous, it may be a closure.\n\t\tname := fn.RelString(nil)\n\t\tswitch {\n\t\tcase name == \"device.Asm\" || name == \"device/arm.Asm\" || name == \"device/arm64.Asm\" || name == \"device/avr.Asm\" || name == \"device/riscv.Asm\":\n\t\t\treturn b.createInlineAsm(instr.Args)\n\t\tcase name == \"device.AsmFull\" || name == \"device/arm.AsmFull\" || name == \"device/arm64.AsmFull\" || name == \"device/avr.AsmFull\" || name == \"device/riscv.AsmFull\":\n\t\t\treturn b.createInlineAsmFull(instr)\n\t\tcase strings.HasPrefix(name, \"device/arm.SVCall\"):\n\t\t\treturn b.emitSVCall(instr.Args, getPos(instr))\n\t\tcase strings.HasPrefix(name, \"device/arm64.SVCall\"):\n\t\t\treturn b.emitSV64Call(instr.Args, getPos(instr))\n\t\tcase strings.HasPrefix(name, \"(device/riscv.CSR).\"):\n\t\t\treturn b.emitCSROperation(instr)\n\t\tcase strings.HasPrefix(name, \"syscall.Syscall\") || strings.HasPrefix(name, \"syscall.RawSyscall\") || strings.HasPrefix(name, \"golang.org/x/sys/unix.Syscall\") || strings.HasPrefix(name, \"golang.org/x/sys/unix.RawSyscall\"):\n\t\t\tif b.GOOS != \"darwin\" {\n\t\t\t\treturn b.createSyscall(instr)\n\t\t\t}\n\t\tcase strings.HasPrefix(name, \"syscall.rawSyscallNoError\") || strings.HasPrefix(name, \"golang.org/x/sys/unix.RawSyscallNoError\"):\n\t\t\treturn b.createRawSyscallNoError(instr)\n\t\tcase name == \"runtime.supportsRecover\":\n\t\t\tsupportsRecover := uint64(0)\n\t\t\tif b.supportsRecover() {\n\t\t\t\tsupportsRecover = 1\n\t\t\t}\n\t\t\treturn llvm.ConstInt(b.ctx.Int1Type(), supportsRecover, false), nil\n\t\tcase name == \"runtime.panicStrategy\":\n\t\t\tpanicStrategy := map[string]uint64{\n\t\t\t\t\"print\": tinygo.PanicStrategyPrint,\n\t\t\t\t\"trap\":  tinygo.PanicStrategyTrap,\n\t\t\t}[b.Config.PanicStrategy]\n\t\t\treturn llvm.ConstInt(b.ctx.Int8Type(), panicStrategy, false), nil\n\t\tcase name == \"runtime/interrupt.New\":\n\t\t\treturn b.createInterruptGlobal(instr)\n\t\tcase name == \"runtime.exportedFuncPtr\":\n\t\t\t_, ptr := b.getFunction(instr.Args[0].(*ssa.Function))\n\t\t\treturn b.CreatePtrToInt(ptr, b.uintptrType, \"\"), nil\n\t\tcase name == \"(*runtime/interrupt.Checkpoint).Save\":\n\t\t\treturn b.createInterruptCheckpoint(instr.Args[0]), nil\n\t\tcase name == \"internal/abi.FuncPCABI0\":\n\t\t\tretval := b.createDarwinFuncPCABI0Call(instr)\n\t\t\tif !retval.IsNil() {\n\t\t\t\treturn retval, nil\n\t\t\t}\n\t\t}\n\t}\n\n\tvar params []llvm.Value\n\tfor _, param := range instr.Args {\n\t\tparams = append(params, b.getValue(param, getPos(instr)))\n\t}\n\n\t// Try to call the function directly for trivially static calls.\n\tvar callee, context llvm.Value\n\tvar calleeType llvm.Type\n\texported := false\n\tif fn := instr.StaticCallee(); fn != nil {\n\t\tcalleeType, callee = b.getFunction(fn)\n\t\tinfo := b.getFunctionInfo(fn)\n\t\tif callee.IsNil() {\n\t\t\treturn llvm.Value{}, b.makeError(instr.Pos(), \"undefined function: \"+info.linkName)\n\t\t}\n\t\tswitch value := instr.Value.(type) {\n\t\tcase *ssa.Function:\n\t\t\t// Regular function call. No context is necessary.\n\t\t\tcontext = llvm.Undef(b.dataPtrType)\n\t\t\tif info.variadic && len(fn.Params) == 0 {\n\t\t\t\t// This matches Clang, see: https://godbolt.org/z/Gqv49xKMq\n\t\t\t\t// Eventually we might be able to eliminate this special case\n\t\t\t\t// entirely. For details, see:\n\t\t\t\t// https://discourse.llvm.org/t/rfc-enabling-wstrict-prototypes-by-default-in-c/60521\n\t\t\t\tcalleeType = llvm.FunctionType(callee.GlobalValueType().ReturnType(), nil, false)\n\t\t\t}\n\t\tcase *ssa.MakeClosure:\n\t\t\t// A call on a func value, but the callee is trivial to find. For\n\t\t\t// example: immediately applied functions.\n\t\t\tfuncValue := b.getValue(value, getPos(value))\n\t\t\tcontext = b.extractFuncContext(funcValue)\n\t\tdefault:\n\t\t\tpanic(\"StaticCallee returned an unexpected value\")\n\t\t}\n\t\texported = info.exported\n\t} else if call, ok := instr.Value.(*ssa.Builtin); ok {\n\t\t// Builtin function (append, close, delete, etc.).)\n\t\tvar argTypes []types.Type\n\t\tfor _, arg := range instr.Args {\n\t\t\targTypes = append(argTypes, arg.Type())\n\t\t}\n\t\treturn b.createBuiltin(argTypes, params, call.Name(), instr.Pos())\n\t} else if instr.IsInvoke() {\n\t\t// Interface method call (aka invoke call).\n\t\titf := b.getValue(instr.Value, getPos(instr)) // interface value (runtime._interface)\n\t\ttypecode := b.CreateExtractValue(itf, 0, \"invoke.func.typecode\")\n\t\tvalue := b.CreateExtractValue(itf, 1, \"invoke.func.value\") // receiver\n\t\t// Prefix the params with receiver value and suffix with typecode.\n\t\tparams = append([]llvm.Value{value}, params...)\n\t\tparams = append(params, typecode)\n\t\tcallee = b.getInvokeFunction(instr)\n\t\tcalleeType = callee.GlobalValueType()\n\t\tcontext = llvm.Undef(b.dataPtrType)\n\t} else {\n\t\t// Function pointer.\n\t\tvalue := b.getValue(instr.Value, getPos(instr))\n\t\t// This is a func value, which cannot be called directly. We have to\n\t\t// extract the function pointer and context first from the func value.\n\t\tcallee, context = b.decodeFuncValue(value)\n\t\tcalleeType = b.getLLVMFunctionType(instr.Value.Type().Underlying().(*types.Signature))\n\t\tb.createNilCheck(instr.Value, callee, \"fpcall\")\n\t}\n\n\tif !exported {\n\t\t// This function takes a context parameter.\n\t\t// Add it to the end of the parameter list.\n\t\tparams = append(params, context)\n\t}\n\n\treturn b.createInvoke(calleeType, callee, params, \"\"), nil\n}\n\n// getValue returns the LLVM value of a constant, function value, global, or\n// already processed SSA expression.\nfunc (b *builder) getValue(expr ssa.Value, pos token.Pos) llvm.Value {\n\tswitch expr := expr.(type) {\n\tcase *ssa.Const:\n\t\tif pos == token.NoPos {\n\t\t\t// If the position isn't known, at least try to find in which file\n\t\t\t// it is defined.\n\t\t\tfile := b.program.Fset.File(b.fn.Pos())\n\t\t\tif file != nil {\n\t\t\t\tpos = file.Pos(0)\n\t\t\t}\n\t\t}\n\t\treturn b.createConst(expr, pos)\n\tcase *ssa.Function:\n\t\tif b.getFunctionInfo(expr).exported {\n\t\t\tb.addError(expr.Pos(), \"cannot use an exported function as value: \"+expr.String())\n\t\t\treturn llvm.Undef(b.getLLVMType(expr.Type()))\n\t\t}\n\t\t_, fn := b.getFunction(expr)\n\t\treturn b.createFuncValue(fn, llvm.Undef(b.dataPtrType), expr.Signature)\n\tcase *ssa.Global:\n\t\tvalue := b.getGlobal(expr)\n\t\tif value.IsNil() {\n\t\t\tb.addError(expr.Pos(), \"global not found: \"+expr.RelString(nil))\n\t\t\treturn llvm.Undef(b.getLLVMType(expr.Type()))\n\t\t}\n\t\treturn value\n\tdefault:\n\t\t// other (local) SSA value\n\t\tif value, ok := b.locals[expr]; ok {\n\t\t\treturn value\n\t\t} else {\n\t\t\t// indicates a compiler bug\n\t\t\tpanic(\"SSA value not previously found in function: \" + expr.String())\n\t\t}\n\t}\n}\n\n// maxSliceSize determines the maximum size a slice of the given element type\n// can be.\nfunc (c *compilerContext) maxSliceSize(elementType llvm.Type) uint64 {\n\t// Calculate ^uintptr(0), which is the max value that fits in uintptr.\n\tmaxPointerValue := llvm.ConstNot(llvm.ConstInt(c.uintptrType, 0, false)).ZExtValue()\n\t// Calculate (^uint(0))/2, which is the max value that fits in an int.\n\tmaxIntegerValue := llvm.ConstNot(llvm.ConstInt(c.intType, 0, false)).ZExtValue() / 2\n\n\t// Determine the maximum allowed size for a slice. The biggest possible\n\t// pointer (starting from 0) would be maxPointerValue*sizeof(elementType) so\n\t// divide by the element type to get the real maximum size.\n\telementSize := c.targetData.TypeAllocSize(elementType)\n\tif elementSize == 0 {\n\t\telementSize = 1\n\t}\n\tmaxSize := maxPointerValue / elementSize\n\n\t// len(slice) is an int. Make sure the length remains small enough to fit in\n\t// an int.\n\tif maxSize > maxIntegerValue {\n\t\tmaxSize = maxIntegerValue\n\t}\n\n\treturn maxSize\n}\n\n// createExpr translates a Go SSA expression to LLVM IR. This can be zero, one,\n// or multiple LLVM IR instructions and/or runtime calls.\nfunc (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {\n\tif _, ok := b.locals[expr]; ok {\n\t\t// sanity check\n\t\tpanic(\"instruction has already been created: \" + expr.String())\n\t}\n\n\tswitch expr := expr.(type) {\n\tcase *ssa.Alloc:\n\t\ttyp := b.getLLVMType(expr.Type().Underlying().(*types.Pointer).Elem())\n\t\tsize := b.targetData.TypeAllocSize(typ)\n\t\t// Move all \"large\" allocations to the heap.\n\t\tif expr.Heap || size > b.MaxStackAlloc {\n\t\t\t// Calculate ^uintptr(0)\n\t\t\tmaxSize := llvm.ConstNot(llvm.ConstInt(b.uintptrType, 0, false)).ZExtValue()\n\t\t\tif size > maxSize {\n\t\t\t\t// Size would be truncated if truncated to uintptr.\n\t\t\t\treturn llvm.Value{}, b.makeError(expr.Pos(), fmt.Sprintf(\"value is too big (%v bytes)\", size))\n\t\t\t}\n\t\t\tsizeValue := llvm.ConstInt(b.uintptrType, size, false)\n\t\t\tlayoutValue := b.createObjectLayout(typ, expr.Pos())\n\t\t\tbuf := b.createRuntimeCall(\"alloc\", []llvm.Value{sizeValue, layoutValue}, expr.Comment)\n\t\t\talign := b.targetData.ABITypeAlignment(typ)\n\t\t\tbuf.AddCallSiteAttribute(0, b.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"align\"), uint64(align)))\n\t\t\treturn buf, nil\n\t\t} else {\n\t\t\tbuf := llvmutil.CreateEntryBlockAlloca(b.Builder, typ, expr.Comment)\n\t\t\tif b.targetData.TypeAllocSize(typ) != 0 {\n\t\t\t\tb.CreateStore(llvm.ConstNull(typ), buf) // zero-initialize var\n\t\t\t}\n\t\t\treturn buf, nil\n\t\t}\n\tcase *ssa.BinOp:\n\t\tx := b.getValue(expr.X, getPos(expr))\n\t\ty := b.getValue(expr.Y, getPos(expr))\n\t\treturn b.createBinOp(expr.Op, expr.X.Type(), expr.Y.Type(), x, y, expr.Pos())\n\tcase *ssa.Call:\n\t\treturn b.createFunctionCall(expr.Common())\n\tcase *ssa.ChangeInterface:\n\t\t// Do not change between interface types: always use the underlying\n\t\t// (concrete) type in the type number of the interface. Every method\n\t\t// call on an interface will do a lookup which method to call.\n\t\t// This is different from how the official Go compiler works, because of\n\t\t// heap allocation and because it's easier to implement, see:\n\t\t// https://research.swtch.com/interfaces\n\t\treturn b.getValue(expr.X, getPos(expr)), nil\n\tcase *ssa.ChangeType:\n\t\t// This instruction changes the type, but the underlying value remains\n\t\t// the same. This is often a no-op, but sometimes we have to change the\n\t\t// LLVM type as well.\n\t\tx := b.getValue(expr.X, getPos(expr))\n\t\tllvmType := b.getLLVMType(expr.Type())\n\t\tif x.Type() == llvmType {\n\t\t\t// Different Go type but same LLVM type (for example, named int).\n\t\t\t// This is the common case.\n\t\t\treturn x, nil\n\t\t}\n\t\t// Figure out what kind of type we need to cast.\n\t\tswitch llvmType.TypeKind() {\n\t\tcase llvm.StructTypeKind:\n\t\t\t// Unfortunately, we can't just bitcast structs. We have to\n\t\t\t// actually create a new struct of the correct type and insert the\n\t\t\t// values from the previous struct in there.\n\t\t\tvalue := llvm.Undef(llvmType)\n\t\t\tfor i := 0; i < llvmType.StructElementTypesCount(); i++ {\n\t\t\t\tfield := b.CreateExtractValue(x, i, \"changetype.field\")\n\t\t\t\tvalue = b.CreateInsertValue(value, field, i, \"changetype.struct\")\n\t\t\t}\n\t\t\treturn value, nil\n\t\tdefault:\n\t\t\treturn llvm.Value{}, errors.New(\"todo: unknown ChangeType type: \" + expr.X.Type().String())\n\t\t}\n\tcase *ssa.Const:\n\t\tpanic(\"const is not an expression\")\n\tcase *ssa.Convert:\n\t\tx := b.getValue(expr.X, getPos(expr))\n\t\treturn b.createConvert(expr.X.Type(), expr.Type(), x, expr.Pos())\n\tcase *ssa.Extract:\n\t\tif _, ok := expr.Tuple.(*ssa.Select); ok {\n\t\t\treturn b.getChanSelectResult(expr), nil\n\t\t}\n\t\tvalue := b.getValue(expr.Tuple, getPos(expr))\n\t\treturn b.CreateExtractValue(value, expr.Index, \"\"), nil\n\tcase *ssa.Field:\n\t\tvalue := b.getValue(expr.X, getPos(expr))\n\t\tresult := b.CreateExtractValue(value, expr.Field, \"\")\n\t\treturn result, nil\n\tcase *ssa.FieldAddr:\n\t\tval := b.getValue(expr.X, getPos(expr))\n\t\t// Check for nil pointer before calculating the address, from the spec:\n\t\t// > For an operand x of type T, the address operation &x generates a\n\t\t// > pointer of type *T to x. [...] If the evaluation of x would cause a\n\t\t// > run-time panic, then the evaluation of &x does too.\n\t\tb.createNilCheck(expr.X, val, \"gep\")\n\t\t// Do a GEP on the pointer to get the field address.\n\t\tindices := []llvm.Value{\n\t\t\tllvm.ConstInt(b.ctx.Int32Type(), 0, false),\n\t\t\tllvm.ConstInt(b.ctx.Int32Type(), uint64(expr.Field), false),\n\t\t}\n\t\telementType := b.getLLVMType(expr.X.Type().Underlying().(*types.Pointer).Elem())\n\t\treturn b.CreateInBoundsGEP(elementType, val, indices, \"\"), nil\n\tcase *ssa.Function:\n\t\tpanic(\"function is not an expression\")\n\tcase *ssa.Global:\n\t\tpanic(\"global is not an expression\")\n\tcase *ssa.Index:\n\t\tcollection := b.getValue(expr.X, getPos(expr))\n\t\tindex := b.getValue(expr.Index, getPos(expr))\n\n\t\tswitch xType := expr.X.Type().Underlying().(type) {\n\t\tcase *types.Basic: // extract byte from string\n\t\t\t// Value type must be a string, which is a basic type.\n\t\t\tif xType.Info()&types.IsString == 0 {\n\t\t\t\tpanic(\"lookup on non-string?\")\n\t\t\t}\n\n\t\t\t// Sometimes, the index can be e.g. an uint8 or int8, and we have to\n\t\t\t// correctly extend that type for two reasons:\n\t\t\t//  1. The lookup bounds check expects an index of at least uintptr\n\t\t\t//     size.\n\t\t\t//  2. getelementptr has signed operands, and therefore s[uint8(x)]\n\t\t\t//     can be lowered as s[int8(x)]. That would be a bug.\n\t\t\tindex = b.extendInteger(index, expr.Index.Type(), b.uintptrType)\n\n\t\t\t// Bounds check.\n\t\t\tlength := b.CreateExtractValue(collection, 1, \"len\")\n\t\t\tb.createLookupBoundsCheck(length, index)\n\n\t\t\t// Lookup byte\n\t\t\tbuf := b.CreateExtractValue(collection, 0, \"\")\n\t\t\tbufElemType := b.ctx.Int8Type()\n\t\t\tbufPtr := b.CreateInBoundsGEP(bufElemType, buf, []llvm.Value{index}, \"\")\n\t\t\treturn b.CreateLoad(bufElemType, bufPtr, \"\"), nil\n\t\tcase *types.Array: // extract element from array\n\t\t\t// Extend index to at least uintptr size, because getelementptr\n\t\t\t// assumes index is a signed integer.\n\t\t\tindex = b.extendInteger(index, expr.Index.Type(), b.uintptrType)\n\n\t\t\t// Check bounds.\n\t\t\tarrayLen := llvm.ConstInt(b.uintptrType, uint64(xType.Len()), false)\n\t\t\tb.createLookupBoundsCheck(arrayLen, index)\n\n\t\t\t// Can't load directly from array (as index is non-constant), so\n\t\t\t// have to do it using an alloca+gep+load.\n\t\t\tarrayType := collection.Type()\n\t\t\talloca, allocaSize := b.createTemporaryAlloca(arrayType, \"index.alloca\")\n\t\t\tb.CreateStore(collection, alloca)\n\t\t\tzero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)\n\t\t\tptr := b.CreateInBoundsGEP(arrayType, alloca, []llvm.Value{zero, index}, \"index.gep\")\n\t\t\tresult := b.CreateLoad(arrayType.ElementType(), ptr, \"index.load\")\n\t\t\tb.emitLifetimeEnd(alloca, allocaSize)\n\t\t\treturn result, nil\n\t\tdefault:\n\t\t\tpanic(\"unknown *ssa.Index type\")\n\t\t}\n\tcase *ssa.IndexAddr:\n\t\tval := b.getValue(expr.X, getPos(expr))\n\t\tindex := b.getValue(expr.Index, getPos(expr))\n\n\t\t// Get buffer pointer and length\n\t\tvar bufptr, buflen llvm.Value\n\t\tvar bufType llvm.Type\n\t\tswitch ptrTyp := expr.X.Type().Underlying().(type) {\n\t\tcase *types.Pointer:\n\t\t\ttyp := ptrTyp.Elem().Underlying()\n\t\t\tswitch typ := typ.(type) {\n\t\t\tcase *types.Array:\n\t\t\t\tbufptr = val\n\t\t\t\tbuflen = llvm.ConstInt(b.uintptrType, uint64(typ.Len()), false)\n\t\t\t\tbufType = b.getLLVMType(typ)\n\t\t\t\t// Check for nil pointer before calculating the address, from\n\t\t\t\t// the spec:\n\t\t\t\t// > For an operand x of type T, the address operation &x\n\t\t\t\t// > generates a pointer of type *T to x. [...] If the\n\t\t\t\t// > evaluation of x would cause a run-time panic, then the\n\t\t\t\t// > evaluation of &x does too.\n\t\t\t\tb.createNilCheck(expr.X, bufptr, \"gep\")\n\t\t\tdefault:\n\t\t\t\treturn llvm.Value{}, b.makeError(expr.Pos(), \"todo: indexaddr: \"+typ.String())\n\t\t\t}\n\t\tcase *types.Slice:\n\t\t\tbufptr = b.CreateExtractValue(val, 0, \"indexaddr.ptr\")\n\t\t\tbuflen = b.CreateExtractValue(val, 1, \"indexaddr.len\")\n\t\t\tbufType = b.getLLVMType(ptrTyp.Elem())\n\t\tdefault:\n\t\t\treturn llvm.Value{}, b.makeError(expr.Pos(), \"todo: indexaddr: \"+ptrTyp.String())\n\t\t}\n\n\t\t// Make sure index is at least the size of uintptr because getelementptr\n\t\t// assumes index is a signed integer.\n\t\tindex = b.extendInteger(index, expr.Index.Type(), b.uintptrType)\n\n\t\t// Bounds check.\n\t\tb.createLookupBoundsCheck(buflen, index)\n\n\t\tswitch expr.X.Type().Underlying().(type) {\n\t\tcase *types.Pointer:\n\t\t\tindices := []llvm.Value{\n\t\t\t\tllvm.ConstInt(b.ctx.Int32Type(), 0, false),\n\t\t\t\tindex,\n\t\t\t}\n\t\t\treturn b.CreateInBoundsGEP(bufType, bufptr, indices, \"\"), nil\n\t\tcase *types.Slice:\n\t\t\treturn b.CreateInBoundsGEP(bufType, bufptr, []llvm.Value{index}, \"\"), nil\n\t\tdefault:\n\t\t\tpanic(\"unreachable\")\n\t\t}\n\tcase *ssa.Lookup: // map lookup\n\t\tvalue := b.getValue(expr.X, getPos(expr))\n\t\tindex := b.getValue(expr.Index, getPos(expr))\n\t\tvalueType := expr.Type()\n\t\tif expr.CommaOk {\n\t\t\tvalueType = valueType.(*types.Tuple).At(0).Type()\n\t\t}\n\t\treturn b.createMapLookup(expr.X.Type().Underlying().(*types.Map).Key(), valueType, value, index, expr.CommaOk, expr.Pos())\n\tcase *ssa.MakeChan:\n\t\treturn b.createMakeChan(expr), nil\n\tcase *ssa.MakeClosure:\n\t\treturn b.parseMakeClosure(expr)\n\tcase *ssa.MakeInterface:\n\t\tval := b.getValue(expr.X, getPos(expr))\n\t\treturn b.createMakeInterface(val, expr.X.Type(), expr.Pos()), nil\n\tcase *ssa.MakeMap:\n\t\treturn b.createMakeMap(expr)\n\tcase *ssa.MakeSlice:\n\t\tsliceLen := b.getValue(expr.Len, getPos(expr))\n\t\tsliceCap := b.getValue(expr.Cap, getPos(expr))\n\t\tsliceType := expr.Type().Underlying().(*types.Slice)\n\t\tllvmElemType := b.getLLVMType(sliceType.Elem())\n\t\telemSize := b.targetData.TypeAllocSize(llvmElemType)\n\t\telemAlign := b.targetData.ABITypeAlignment(llvmElemType)\n\t\telemSizeValue := llvm.ConstInt(b.uintptrType, elemSize, false)\n\n\t\tmaxSize := b.maxSliceSize(llvmElemType)\n\t\tif elemSize > maxSize {\n\t\t\t// This seems to be checked by the typechecker already, but let's\n\t\t\t// check it again just to be sure.\n\t\t\treturn llvm.Value{}, b.makeError(expr.Pos(), fmt.Sprintf(\"slice element type is too big (%v bytes)\", elemSize))\n\t\t}\n\n\t\t// Bounds checking.\n\t\tlenType := expr.Len.Type().Underlying().(*types.Basic)\n\t\tcapType := expr.Cap.Type().Underlying().(*types.Basic)\n\t\tmaxSizeValue := llvm.ConstInt(b.uintptrType, maxSize, false)\n\t\tb.createSliceBoundsCheck(maxSizeValue, sliceLen, sliceCap, sliceCap, lenType, capType, capType)\n\n\t\t// Allocate the backing array.\n\t\tsliceCapCast, err := b.createConvert(expr.Cap.Type(), types.Typ[types.Uintptr], sliceCap, expr.Pos())\n\t\tif err != nil {\n\t\t\treturn llvm.Value{}, err\n\t\t}\n\t\tsliceSize := b.CreateBinOp(llvm.Mul, elemSizeValue, sliceCapCast, \"makeslice.cap\")\n\t\tlayoutValue := b.createObjectLayout(llvmElemType, expr.Pos())\n\t\tslicePtr := b.createRuntimeCall(\"alloc\", []llvm.Value{sliceSize, layoutValue}, \"makeslice.buf\")\n\t\tslicePtr.AddCallSiteAttribute(0, b.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"align\"), uint64(elemAlign)))\n\n\t\t// Extend or truncate if necessary. This is safe as we've already done\n\t\t// the bounds check.\n\t\tsliceLen, err = b.createConvert(expr.Len.Type(), types.Typ[types.Uintptr], sliceLen, expr.Pos())\n\t\tif err != nil {\n\t\t\treturn llvm.Value{}, err\n\t\t}\n\t\tsliceCap, err = b.createConvert(expr.Cap.Type(), types.Typ[types.Uintptr], sliceCap, expr.Pos())\n\t\tif err != nil {\n\t\t\treturn llvm.Value{}, err\n\t\t}\n\n\t\t// Create the slice.\n\t\tslice := b.ctx.ConstStruct([]llvm.Value{\n\t\t\tllvm.Undef(slicePtr.Type()),\n\t\t\tllvm.Undef(b.uintptrType),\n\t\t\tllvm.Undef(b.uintptrType),\n\t\t}, false)\n\t\tslice = b.CreateInsertValue(slice, slicePtr, 0, \"\")\n\t\tslice = b.CreateInsertValue(slice, sliceLen, 1, \"\")\n\t\tslice = b.CreateInsertValue(slice, sliceCap, 2, \"\")\n\t\treturn slice, nil\n\tcase *ssa.Next:\n\t\trangeVal := expr.Iter.(*ssa.Range).X\n\t\tllvmRangeVal := b.getValue(rangeVal, getPos(expr))\n\t\tit := b.getValue(expr.Iter, getPos(expr))\n\t\tif expr.IsString {\n\t\t\treturn b.createRuntimeCall(\"stringNext\", []llvm.Value{llvmRangeVal, it}, \"range.next\"), nil\n\t\t} else { // map\n\t\t\treturn b.createMapIteratorNext(rangeVal, llvmRangeVal, it), nil\n\t\t}\n\tcase *ssa.Phi:\n\t\tphi := b.CreatePHI(b.getLLVMType(expr.Type()), \"\")\n\t\tb.phis = append(b.phis, phiNode{expr, phi})\n\t\treturn phi, nil\n\tcase *ssa.Range:\n\t\tvar iteratorType llvm.Type\n\t\tswitch typ := expr.X.Type().Underlying().(type) {\n\t\tcase *types.Basic: // string\n\t\t\titeratorType = b.getLLVMRuntimeType(\"stringIterator\")\n\t\tcase *types.Map:\n\t\t\titeratorType = b.getLLVMRuntimeType(\"hashmapIterator\")\n\t\tdefault:\n\t\t\tpanic(\"unknown type in range: \" + typ.String())\n\t\t}\n\t\tit, _ := b.createTemporaryAlloca(iteratorType, \"range.it\")\n\t\tb.CreateStore(llvm.ConstNull(iteratorType), it)\n\t\treturn it, nil\n\tcase *ssa.Select:\n\t\treturn b.createSelect(expr), nil\n\tcase *ssa.Slice:\n\t\tvalue := b.getValue(expr.X, getPos(expr))\n\n\t\tvar lowType, highType, maxType *types.Basic\n\t\tvar low, high, max llvm.Value\n\n\t\tif expr.Low != nil {\n\t\t\tlowType = expr.Low.Type().Underlying().(*types.Basic)\n\t\t\tlow = b.getValue(expr.Low, getPos(expr))\n\t\t\tlow = b.extendInteger(low, lowType, b.uintptrType)\n\t\t} else {\n\t\t\tlowType = types.Typ[types.Uintptr]\n\t\t\tlow = llvm.ConstInt(b.uintptrType, 0, false)\n\t\t}\n\n\t\tif expr.High != nil {\n\t\t\thighType = expr.High.Type().Underlying().(*types.Basic)\n\t\t\thigh = b.getValue(expr.High, getPos(expr))\n\t\t\thigh = b.extendInteger(high, highType, b.uintptrType)\n\t\t} else {\n\t\t\thighType = types.Typ[types.Uintptr]\n\t\t}\n\n\t\tif expr.Max != nil {\n\t\t\tmaxType = expr.Max.Type().Underlying().(*types.Basic)\n\t\t\tmax = b.getValue(expr.Max, getPos(expr))\n\t\t\tmax = b.extendInteger(max, maxType, b.uintptrType)\n\t\t} else {\n\t\t\tmaxType = types.Typ[types.Uintptr]\n\t\t}\n\n\t\tswitch typ := expr.X.Type().Underlying().(type) {\n\t\tcase *types.Pointer: // pointer to array\n\t\t\t// slice an array\n\t\t\tarrayType := typ.Elem().Underlying().(*types.Array)\n\t\t\tlength := arrayType.Len()\n\t\t\tllvmLen := llvm.ConstInt(b.uintptrType, uint64(length), false)\n\t\t\tif high.IsNil() {\n\t\t\t\thigh = llvmLen\n\t\t\t}\n\t\t\tif max.IsNil() {\n\t\t\t\tmax = llvmLen\n\t\t\t}\n\t\t\tindices := []llvm.Value{\n\t\t\t\tllvm.ConstInt(b.ctx.Int32Type(), 0, false),\n\t\t\t\tlow,\n\t\t\t}\n\n\t\t\tb.createNilCheck(expr.X, value, \"slice\")\n\t\t\tb.createSliceBoundsCheck(llvmLen, low, high, max, lowType, highType, maxType)\n\n\t\t\t// Truncate ints bigger than uintptr. This is after the bounds\n\t\t\t// check so it's safe.\n\t\t\tif b.targetData.TypeAllocSize(low.Type()) > b.targetData.TypeAllocSize(b.uintptrType) {\n\t\t\t\tlow = b.CreateTrunc(low, b.uintptrType, \"\")\n\t\t\t}\n\t\t\tif b.targetData.TypeAllocSize(high.Type()) > b.targetData.TypeAllocSize(b.uintptrType) {\n\t\t\t\thigh = b.CreateTrunc(high, b.uintptrType, \"\")\n\t\t\t}\n\t\t\tif b.targetData.TypeAllocSize(max.Type()) > b.targetData.TypeAllocSize(b.uintptrType) {\n\t\t\t\tmax = b.CreateTrunc(max, b.uintptrType, \"\")\n\t\t\t}\n\n\t\t\tsliceLen := b.CreateSub(high, low, \"slice.len\")\n\t\t\tslicePtr := b.CreateInBoundsGEP(b.getLLVMType(arrayType), value, indices, \"slice.ptr\")\n\t\t\tsliceCap := b.CreateSub(max, low, \"slice.cap\")\n\n\t\t\tslice := b.ctx.ConstStruct([]llvm.Value{\n\t\t\t\tllvm.Undef(slicePtr.Type()),\n\t\t\t\tllvm.Undef(b.uintptrType),\n\t\t\t\tllvm.Undef(b.uintptrType),\n\t\t\t}, false)\n\t\t\tslice = b.CreateInsertValue(slice, slicePtr, 0, \"\")\n\t\t\tslice = b.CreateInsertValue(slice, sliceLen, 1, \"\")\n\t\t\tslice = b.CreateInsertValue(slice, sliceCap, 2, \"\")\n\t\t\treturn slice, nil\n\n\t\tcase *types.Slice:\n\t\t\t// slice a slice\n\t\t\toldPtr := b.CreateExtractValue(value, 0, \"\")\n\t\t\toldLen := b.CreateExtractValue(value, 1, \"\")\n\t\t\toldCap := b.CreateExtractValue(value, 2, \"\")\n\t\t\tif high.IsNil() {\n\t\t\t\thigh = oldLen\n\t\t\t}\n\t\t\tif max.IsNil() {\n\t\t\t\tmax = oldCap\n\t\t\t}\n\n\t\t\tb.createSliceBoundsCheck(oldCap, low, high, max, lowType, highType, maxType)\n\n\t\t\t// Truncate ints bigger than uintptr. This is after the bounds\n\t\t\t// check so it's safe.\n\t\t\tif b.targetData.TypeAllocSize(low.Type()) > b.targetData.TypeAllocSize(b.uintptrType) {\n\t\t\t\tlow = b.CreateTrunc(low, b.uintptrType, \"\")\n\t\t\t}\n\t\t\tif b.targetData.TypeAllocSize(high.Type()) > b.targetData.TypeAllocSize(b.uintptrType) {\n\t\t\t\thigh = b.CreateTrunc(high, b.uintptrType, \"\")\n\t\t\t}\n\t\t\tif b.targetData.TypeAllocSize(max.Type()) > b.targetData.TypeAllocSize(b.uintptrType) {\n\t\t\t\tmax = b.CreateTrunc(max, b.uintptrType, \"\")\n\t\t\t}\n\n\t\t\tptrElemType := b.getLLVMType(typ.Elem())\n\t\t\tnewPtr := b.CreateInBoundsGEP(ptrElemType, oldPtr, []llvm.Value{low}, \"\")\n\t\t\tnewLen := b.CreateSub(high, low, \"\")\n\t\t\tnewCap := b.CreateSub(max, low, \"\")\n\t\t\tslice := b.ctx.ConstStruct([]llvm.Value{\n\t\t\t\tllvm.Undef(newPtr.Type()),\n\t\t\t\tllvm.Undef(b.uintptrType),\n\t\t\t\tllvm.Undef(b.uintptrType),\n\t\t\t}, false)\n\t\t\tslice = b.CreateInsertValue(slice, newPtr, 0, \"\")\n\t\t\tslice = b.CreateInsertValue(slice, newLen, 1, \"\")\n\t\t\tslice = b.CreateInsertValue(slice, newCap, 2, \"\")\n\t\t\treturn slice, nil\n\n\t\tcase *types.Basic:\n\t\t\tif typ.Info()&types.IsString == 0 {\n\t\t\t\treturn llvm.Value{}, b.makeError(expr.Pos(), \"unknown slice type: \"+typ.String())\n\t\t\t}\n\t\t\t// slice a string\n\t\t\tif expr.Max != nil {\n\t\t\t\t// This might as well be a panic, as the frontend should have\n\t\t\t\t// handled this already.\n\t\t\t\treturn llvm.Value{}, b.makeError(expr.Pos(), \"slicing a string with a max parameter is not allowed by the spec\")\n\t\t\t}\n\t\t\toldPtr := b.CreateExtractValue(value, 0, \"\")\n\t\t\toldLen := b.CreateExtractValue(value, 1, \"\")\n\t\t\tif high.IsNil() {\n\t\t\t\thigh = oldLen\n\t\t\t}\n\n\t\t\tb.createSliceBoundsCheck(oldLen, low, high, high, lowType, highType, maxType)\n\n\t\t\t// Truncate ints bigger than uintptr. This is after the bounds\n\t\t\t// check so it's safe.\n\t\t\tif b.targetData.TypeAllocSize(low.Type()) > b.targetData.TypeAllocSize(b.uintptrType) {\n\t\t\t\tlow = b.CreateTrunc(low, b.uintptrType, \"\")\n\t\t\t}\n\t\t\tif b.targetData.TypeAllocSize(high.Type()) > b.targetData.TypeAllocSize(b.uintptrType) {\n\t\t\t\thigh = b.CreateTrunc(high, b.uintptrType, \"\")\n\t\t\t}\n\n\t\t\tnewPtr := b.CreateInBoundsGEP(b.ctx.Int8Type(), oldPtr, []llvm.Value{low}, \"\")\n\t\t\tnewLen := b.CreateSub(high, low, \"\")\n\t\t\tstr := llvm.Undef(b.getLLVMRuntimeType(\"_string\"))\n\t\t\tstr = b.CreateInsertValue(str, newPtr, 0, \"\")\n\t\t\tstr = b.CreateInsertValue(str, newLen, 1, \"\")\n\t\t\treturn str, nil\n\n\t\tdefault:\n\t\t\treturn llvm.Value{}, b.makeError(expr.Pos(), \"unknown slice type: \"+typ.String())\n\t\t}\n\tcase *ssa.SliceToArrayPointer:\n\t\t// Conversion from a slice to an array pointer, as the name clearly\n\t\t// says. This requires a runtime check to make sure the slice is at\n\t\t// least as big as the array.\n\t\tslice := b.getValue(expr.X, getPos(expr))\n\t\tsliceLen := b.CreateExtractValue(slice, 1, \"\")\n\t\tarrayLen := expr.Type().Underlying().(*types.Pointer).Elem().Underlying().(*types.Array).Len()\n\t\tb.createSliceToArrayPointerCheck(sliceLen, arrayLen)\n\t\tptr := b.CreateExtractValue(slice, 0, \"\")\n\t\treturn ptr, nil\n\tcase *ssa.TypeAssert:\n\t\treturn b.createTypeAssert(expr), nil\n\tcase *ssa.UnOp:\n\t\treturn b.createUnOp(expr)\n\tdefault:\n\t\treturn llvm.Value{}, b.makeError(expr.Pos(), \"todo: unknown expression: \"+expr.String())\n\t}\n}\n\n// createBinOp creates a LLVM binary operation (add, sub, mul, etc) for a Go\n// binary operation. This is almost a direct mapping, but there are some subtle\n// differences such as the requirement in LLVM IR that both sides must have the\n// same type, even for bitshifts. Also, signedness in Go is encoded in the type\n// and is encoded in the operation in LLVM IR: this is important for some\n// operations such as divide.\nfunc (b *builder) createBinOp(op token.Token, typ, ytyp types.Type, x, y llvm.Value, pos token.Pos) (llvm.Value, error) {\n\tswitch typ := typ.Underlying().(type) {\n\tcase *types.Basic:\n\t\tif typ.Info()&types.IsInteger != 0 {\n\t\t\t// Operations on integers\n\t\t\tsigned := typ.Info()&types.IsUnsigned == 0\n\t\t\tswitch op {\n\t\t\tcase token.ADD: // +\n\t\t\t\treturn b.CreateAdd(x, y, \"\"), nil\n\t\t\tcase token.SUB: // -\n\t\t\t\treturn b.CreateSub(x, y, \"\"), nil\n\t\t\tcase token.MUL: // *\n\t\t\t\treturn b.CreateMul(x, y, \"\"), nil\n\t\t\tcase token.QUO, token.REM: // /, %\n\t\t\t\t// Check for a divide by zero. If y is zero, the Go\n\t\t\t\t// specification says that a runtime error must be triggered.\n\t\t\t\tb.createDivideByZeroCheck(y)\n\n\t\t\t\tif signed {\n\t\t\t\t\t// Deal with signed division overflow.\n\t\t\t\t\t// The LLVM LangRef says:\n\t\t\t\t\t//\n\t\t\t\t\t//   Overflow also leads to undefined behavior; this is a\n\t\t\t\t\t//   rare case, but can occur, for example, by doing a\n\t\t\t\t\t//   32-bit division of -2147483648 by -1.\n\t\t\t\t\t//\n\t\t\t\t\t// The Go specification however says this about division:\n\t\t\t\t\t//\n\t\t\t\t\t//   The one exception to this rule is that if the dividend\n\t\t\t\t\t//   x is the most negative value for the int type of x, the\n\t\t\t\t\t//   quotient q = x / -1 is equal to x (and r = 0) due to\n\t\t\t\t\t//   two's-complement integer overflow.\n\t\t\t\t\t//\n\t\t\t\t\t// In other words, in the special case that the lowest\n\t\t\t\t\t// possible signed integer is divided by -1, the result of\n\t\t\t\t\t// the division is the same as x (the dividend).\n\t\t\t\t\t// This is implemented by checking for this condition and\n\t\t\t\t\t// changing y to 1 if it occurs, for example for 32-bit\n\t\t\t\t\t// ints:\n\t\t\t\t\t//\n\t\t\t\t\t//   if x == -2147483648 && y == -1 {\n\t\t\t\t\t//       y = 1\n\t\t\t\t\t//   }\n\t\t\t\t\t//\n\t\t\t\t\t// Dividing x by 1 obviously returns x, therefore satisfying\n\t\t\t\t\t// the Go specification without a branch.\n\t\t\t\t\tllvmType := x.Type()\n\t\t\t\t\tminusOne := llvm.ConstSub(llvm.ConstInt(llvmType, 0, false), llvm.ConstInt(llvmType, 1, false))\n\t\t\t\t\tlowestInteger := llvm.ConstInt(x.Type(), 1<<(llvmType.IntTypeWidth()-1), false)\n\t\t\t\t\tyIsMinusOne := b.CreateICmp(llvm.IntEQ, y, minusOne, \"\")\n\t\t\t\t\txIsLowestInteger := b.CreateICmp(llvm.IntEQ, x, lowestInteger, \"\")\n\t\t\t\t\thasOverflow := b.CreateAnd(yIsMinusOne, xIsLowestInteger, \"\")\n\t\t\t\t\ty = b.CreateSelect(hasOverflow, llvm.ConstInt(llvmType, 1, true), y, \"\")\n\n\t\t\t\t\tif op == token.QUO {\n\t\t\t\t\t\treturn b.CreateSDiv(x, y, \"\"), nil\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn b.CreateSRem(x, y, \"\"), nil\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif op == token.QUO {\n\t\t\t\t\t\treturn b.CreateUDiv(x, y, \"\"), nil\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn b.CreateURem(x, y, \"\"), nil\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tcase token.AND: // &\n\t\t\t\treturn b.CreateAnd(x, y, \"\"), nil\n\t\t\tcase token.OR: // |\n\t\t\t\treturn b.CreateOr(x, y, \"\"), nil\n\t\t\tcase token.XOR: // ^\n\t\t\t\treturn b.CreateXor(x, y, \"\"), nil\n\t\t\tcase token.SHL, token.SHR:\n\t\t\t\tif ytyp.Underlying().(*types.Basic).Info()&types.IsUnsigned == 0 {\n\t\t\t\t\t// Ensure that y is not negative.\n\t\t\t\t\tb.createNegativeShiftCheck(y)\n\t\t\t\t}\n\n\t\t\t\tsizeX := b.targetData.TypeAllocSize(x.Type())\n\t\t\t\tsizeY := b.targetData.TypeAllocSize(y.Type())\n\n\t\t\t\t// Check if the shift is bigger than the bit-width of the shifted value.\n\t\t\t\t// This is UB in LLVM, so it needs to be handled separately.\n\t\t\t\t// The Go spec indirectly defines the result as 0.\n\t\t\t\t// Negative shifts are handled earlier, so we can treat y as unsigned.\n\t\t\t\tovershifted := b.CreateICmp(llvm.IntUGE, y, llvm.ConstInt(y.Type(), 8*sizeX, false), \"shift.overflow\")\n\n\t\t\t\t// Adjust the size of y to match x.\n\t\t\t\tswitch {\n\t\t\t\tcase sizeX > sizeY:\n\t\t\t\t\ty = b.CreateZExt(y, x.Type(), \"\")\n\t\t\t\tcase sizeX < sizeY:\n\t\t\t\t\t// If it gets truncated, overshifted will be true and it will not matter.\n\t\t\t\t\ty = b.CreateTrunc(y, x.Type(), \"\")\n\t\t\t\t}\n\n\t\t\t\t// Create a shift operation.\n\t\t\t\tvar val llvm.Value\n\t\t\t\tswitch op {\n\t\t\t\tcase token.SHL: // <<\n\t\t\t\t\tval = b.CreateShl(x, y, \"\")\n\t\t\t\tcase token.SHR: // >>\n\t\t\t\t\tif signed {\n\t\t\t\t\t\t// Arithmetic right shifts work differently, since shifting a negative number right yields -1.\n\t\t\t\t\t\t// Cap the shift input rather than selecting the output.\n\t\t\t\t\t\ty = b.CreateSelect(overshifted, llvm.ConstInt(y.Type(), 8*sizeX-1, false), y, \"shift.offset\")\n\t\t\t\t\t\treturn b.CreateAShr(x, y, \"\"), nil\n\t\t\t\t\t} else {\n\t\t\t\t\t\tval = b.CreateLShr(x, y, \"\")\n\t\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\tpanic(\"unreachable\")\n\t\t\t\t}\n\n\t\t\t\t// Select between the shift result and zero depending on whether there was an overshift.\n\t\t\t\treturn b.CreateSelect(overshifted, llvm.ConstInt(val.Type(), 0, false), val, \"shift.result\"), nil\n\t\t\tcase token.EQL: // ==\n\t\t\t\treturn b.CreateICmp(llvm.IntEQ, x, y, \"\"), nil\n\t\t\tcase token.NEQ: // !=\n\t\t\t\treturn b.CreateICmp(llvm.IntNE, x, y, \"\"), nil\n\t\t\tcase token.AND_NOT: // &^\n\t\t\t\t// Go specific. Calculate \"and not\" with x & (~y)\n\t\t\t\tinv := b.CreateNot(y, \"\") // ~y\n\t\t\t\treturn b.CreateAnd(x, inv, \"\"), nil\n\t\t\tcase token.LSS: // <\n\t\t\t\tif signed {\n\t\t\t\t\treturn b.CreateICmp(llvm.IntSLT, x, y, \"\"), nil\n\t\t\t\t} else {\n\t\t\t\t\treturn b.CreateICmp(llvm.IntULT, x, y, \"\"), nil\n\t\t\t\t}\n\t\t\tcase token.LEQ: // <=\n\t\t\t\tif signed {\n\t\t\t\t\treturn b.CreateICmp(llvm.IntSLE, x, y, \"\"), nil\n\t\t\t\t} else {\n\t\t\t\t\treturn b.CreateICmp(llvm.IntULE, x, y, \"\"), nil\n\t\t\t\t}\n\t\t\tcase token.GTR: // >\n\t\t\t\tif signed {\n\t\t\t\t\treturn b.CreateICmp(llvm.IntSGT, x, y, \"\"), nil\n\t\t\t\t} else {\n\t\t\t\t\treturn b.CreateICmp(llvm.IntUGT, x, y, \"\"), nil\n\t\t\t\t}\n\t\t\tcase token.GEQ: // >=\n\t\t\t\tif signed {\n\t\t\t\t\treturn b.CreateICmp(llvm.IntSGE, x, y, \"\"), nil\n\t\t\t\t} else {\n\t\t\t\t\treturn b.CreateICmp(llvm.IntUGE, x, y, \"\"), nil\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\tpanic(\"binop on integer: \" + op.String())\n\t\t\t}\n\t\t} else if typ.Info()&types.IsFloat != 0 {\n\t\t\t// Operations on floats\n\t\t\tswitch op {\n\t\t\tcase token.ADD: // +\n\t\t\t\treturn b.CreateFAdd(x, y, \"\"), nil\n\t\t\tcase token.SUB: // -\n\t\t\t\treturn b.CreateFSub(x, y, \"\"), nil\n\t\t\tcase token.MUL: // *\n\t\t\t\treturn b.CreateFMul(x, y, \"\"), nil\n\t\t\tcase token.QUO: // /\n\t\t\t\treturn b.CreateFDiv(x, y, \"\"), nil\n\t\t\tcase token.EQL: // ==\n\t\t\t\treturn b.CreateFCmp(llvm.FloatOEQ, x, y, \"\"), nil\n\t\t\tcase token.NEQ: // !=\n\t\t\t\treturn b.CreateFCmp(llvm.FloatUNE, x, y, \"\"), nil\n\t\t\tcase token.LSS: // <\n\t\t\t\treturn b.CreateFCmp(llvm.FloatOLT, x, y, \"\"), nil\n\t\t\tcase token.LEQ: // <=\n\t\t\t\treturn b.CreateFCmp(llvm.FloatOLE, x, y, \"\"), nil\n\t\t\tcase token.GTR: // >\n\t\t\t\treturn b.CreateFCmp(llvm.FloatOGT, x, y, \"\"), nil\n\t\t\tcase token.GEQ: // >=\n\t\t\t\treturn b.CreateFCmp(llvm.FloatOGE, x, y, \"\"), nil\n\t\t\tdefault:\n\t\t\t\tpanic(\"binop on float: \" + op.String())\n\t\t\t}\n\t\t} else if typ.Info()&types.IsComplex != 0 {\n\t\t\tr1 := b.CreateExtractValue(x, 0, \"r1\")\n\t\t\tr2 := b.CreateExtractValue(y, 0, \"r2\")\n\t\t\ti1 := b.CreateExtractValue(x, 1, \"i1\")\n\t\t\ti2 := b.CreateExtractValue(y, 1, \"i2\")\n\t\t\tswitch op {\n\t\t\tcase token.EQL: // ==\n\t\t\t\treq := b.CreateFCmp(llvm.FloatOEQ, r1, r2, \"\")\n\t\t\t\tieq := b.CreateFCmp(llvm.FloatOEQ, i1, i2, \"\")\n\t\t\t\treturn b.CreateAnd(req, ieq, \"\"), nil\n\t\t\tcase token.NEQ: // !=\n\t\t\t\treq := b.CreateFCmp(llvm.FloatOEQ, r1, r2, \"\")\n\t\t\t\tieq := b.CreateFCmp(llvm.FloatOEQ, i1, i2, \"\")\n\t\t\t\tneq := b.CreateAnd(req, ieq, \"\")\n\t\t\t\treturn b.CreateNot(neq, \"\"), nil\n\t\t\tcase token.ADD, token.SUB:\n\t\t\t\tvar r, i llvm.Value\n\t\t\t\tswitch op {\n\t\t\t\tcase token.ADD:\n\t\t\t\t\tr = b.CreateFAdd(r1, r2, \"\")\n\t\t\t\t\ti = b.CreateFAdd(i1, i2, \"\")\n\t\t\t\tcase token.SUB:\n\t\t\t\t\tr = b.CreateFSub(r1, r2, \"\")\n\t\t\t\t\ti = b.CreateFSub(i1, i2, \"\")\n\t\t\t\tdefault:\n\t\t\t\t\tpanic(\"unreachable\")\n\t\t\t\t}\n\t\t\t\tcplx := llvm.Undef(b.ctx.StructType([]llvm.Type{r.Type(), i.Type()}, false))\n\t\t\t\tcplx = b.CreateInsertValue(cplx, r, 0, \"\")\n\t\t\t\tcplx = b.CreateInsertValue(cplx, i, 1, \"\")\n\t\t\t\treturn cplx, nil\n\t\t\tcase token.MUL:\n\t\t\t\t// Complex multiplication follows the current implementation in\n\t\t\t\t// the Go compiler, with the difference that complex64\n\t\t\t\t// components are not first scaled up to float64 for increased\n\t\t\t\t// precision.\n\t\t\t\t// https://github.com/golang/go/blob/170b8b4b12be50eeccbcdadb8523fb4fc670ca72/src/cmd/compile/internal/gc/ssa.go#L2089-L2127\n\t\t\t\t// The implementation is as follows:\n\t\t\t\t//   r := real(a) * real(b) - imag(a) * imag(b)\n\t\t\t\t//   i := real(a) * imag(b) + imag(a) * real(b)\n\t\t\t\t// Note: this does NOT follow the C11 specification (annex G):\n\t\t\t\t// http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf#page=549\n\t\t\t\t// See https://github.com/golang/go/issues/29846 for a related\n\t\t\t\t// discussion.\n\t\t\t\tr := b.CreateFSub(b.CreateFMul(r1, r2, \"\"), b.CreateFMul(i1, i2, \"\"), \"\")\n\t\t\t\ti := b.CreateFAdd(b.CreateFMul(r1, i2, \"\"), b.CreateFMul(i1, r2, \"\"), \"\")\n\t\t\t\tcplx := llvm.Undef(b.ctx.StructType([]llvm.Type{r.Type(), i.Type()}, false))\n\t\t\t\tcplx = b.CreateInsertValue(cplx, r, 0, \"\")\n\t\t\t\tcplx = b.CreateInsertValue(cplx, i, 1, \"\")\n\t\t\t\treturn cplx, nil\n\t\t\tcase token.QUO:\n\t\t\t\t// Complex division.\n\t\t\t\t// Do this in a library call because it's too difficult to do\n\t\t\t\t// inline.\n\t\t\t\tswitch r1.Type().TypeKind() {\n\t\t\t\tcase llvm.FloatTypeKind:\n\t\t\t\t\treturn b.createRuntimeCall(\"complex64div\", []llvm.Value{x, y}, \"\"), nil\n\t\t\t\tcase llvm.DoubleTypeKind:\n\t\t\t\t\treturn b.createRuntimeCall(\"complex128div\", []llvm.Value{x, y}, \"\"), nil\n\t\t\t\tdefault:\n\t\t\t\t\tpanic(\"unexpected complex type\")\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\tpanic(\"binop on complex: \" + op.String())\n\t\t\t}\n\t\t} else if typ.Info()&types.IsBoolean != 0 {\n\t\t\t// Operations on booleans\n\t\t\tswitch op {\n\t\t\tcase token.EQL: // ==\n\t\t\t\treturn b.CreateICmp(llvm.IntEQ, x, y, \"\"), nil\n\t\t\tcase token.NEQ: // !=\n\t\t\t\treturn b.CreateICmp(llvm.IntNE, x, y, \"\"), nil\n\t\t\tdefault:\n\t\t\t\tpanic(\"binop on bool: \" + op.String())\n\t\t\t}\n\t\t} else if typ.Kind() == types.UnsafePointer {\n\t\t\t// Operations on pointers\n\t\t\tswitch op {\n\t\t\tcase token.EQL: // ==\n\t\t\t\treturn b.CreateICmp(llvm.IntEQ, x, y, \"\"), nil\n\t\t\tcase token.NEQ: // !=\n\t\t\t\treturn b.CreateICmp(llvm.IntNE, x, y, \"\"), nil\n\t\t\tdefault:\n\t\t\t\tpanic(\"binop on pointer: \" + op.String())\n\t\t\t}\n\t\t} else if typ.Info()&types.IsString != 0 {\n\t\t\t// Operations on strings\n\t\t\tswitch op {\n\t\t\tcase token.ADD: // +\n\t\t\t\treturn b.createRuntimeCall(\"stringConcat\", []llvm.Value{x, y}, \"\"), nil\n\t\t\tcase token.EQL: // ==\n\t\t\t\treturn b.createRuntimeCall(\"stringEqual\", []llvm.Value{x, y}, \"\"), nil\n\t\t\tcase token.NEQ: // !=\n\t\t\t\tresult := b.createRuntimeCall(\"stringEqual\", []llvm.Value{x, y}, \"\")\n\t\t\t\treturn b.CreateNot(result, \"\"), nil\n\t\t\tcase token.LSS: // x < y\n\t\t\t\treturn b.createRuntimeCall(\"stringLess\", []llvm.Value{x, y}, \"\"), nil\n\t\t\tcase token.LEQ: // x <= y becomes NOT (y < x)\n\t\t\t\tresult := b.createRuntimeCall(\"stringLess\", []llvm.Value{y, x}, \"\")\n\t\t\t\treturn b.CreateNot(result, \"\"), nil\n\t\t\tcase token.GTR: // x > y becomes y < x\n\t\t\t\treturn b.createRuntimeCall(\"stringLess\", []llvm.Value{y, x}, \"\"), nil\n\t\t\tcase token.GEQ: // x >= y becomes NOT (x < y)\n\t\t\t\tresult := b.createRuntimeCall(\"stringLess\", []llvm.Value{x, y}, \"\")\n\t\t\t\treturn b.CreateNot(result, \"\"), nil\n\t\t\tdefault:\n\t\t\t\tpanic(\"binop on string: \" + op.String())\n\t\t\t}\n\t\t} else {\n\t\t\treturn llvm.Value{}, b.makeError(pos, \"todo: unknown basic type in binop: \"+typ.String())\n\t\t}\n\tcase *types.Signature:\n\t\t// Get raw scalars from the function value and compare those.\n\t\t// Function values may be implemented in multiple ways, but they all\n\t\t// have some way of getting a scalar value identifying the function.\n\t\t// This is safe: function pointers are generally not comparable\n\t\t// against each other, only against nil. So one of these has to be nil.\n\t\tx = b.extractFuncScalar(x)\n\t\ty = b.extractFuncScalar(y)\n\t\tswitch op {\n\t\tcase token.EQL: // ==\n\t\t\treturn b.CreateICmp(llvm.IntEQ, x, y, \"\"), nil\n\t\tcase token.NEQ: // !=\n\t\t\treturn b.CreateICmp(llvm.IntNE, x, y, \"\"), nil\n\t\tdefault:\n\t\t\treturn llvm.Value{}, b.makeError(pos, \"binop on signature: \"+op.String())\n\t\t}\n\tcase *types.Interface:\n\t\tswitch op {\n\t\tcase token.EQL, token.NEQ: // ==, !=\n\t\t\tnilInterface := llvm.ConstNull(x.Type())\n\t\t\tvar result llvm.Value\n\t\t\tif x == nilInterface || y == nilInterface {\n\t\t\t\t// An interface value is compared against nil.\n\t\t\t\t// This is a very common case and is easy to optimize: simply\n\t\t\t\t// compare the typecodes (of which one is nil).\n\t\t\t\ttypecodeX := b.CreateExtractValue(x, 0, \"\")\n\t\t\t\ttypecodeY := b.CreateExtractValue(y, 0, \"\")\n\t\t\t\tresult = b.CreateICmp(llvm.IntEQ, typecodeX, typecodeY, \"\")\n\t\t\t} else {\n\t\t\t\t// Fall back to a full interface comparison.\n\t\t\t\tresult = b.createRuntimeCall(\"interfaceEqual\", []llvm.Value{x, y}, \"\")\n\t\t\t}\n\t\t\tif op == token.NEQ {\n\t\t\t\tresult = b.CreateNot(result, \"\")\n\t\t\t}\n\t\t\treturn result, nil\n\t\tdefault:\n\t\t\treturn llvm.Value{}, b.makeError(pos, \"binop on interface: \"+op.String())\n\t\t}\n\tcase *types.Chan, *types.Map, *types.Pointer:\n\t\t// Maps are in general not comparable, but can be compared against nil\n\t\t// (which is a nil pointer). This means they can be trivially compared\n\t\t// by treating them as a pointer.\n\t\t// Channels behave as pointers in that they are equal as long as they\n\t\t// are created with the same call to make or if both are nil.\n\t\tswitch op {\n\t\tcase token.EQL: // ==\n\t\t\treturn b.CreateICmp(llvm.IntEQ, x, y, \"\"), nil\n\t\tcase token.NEQ: // !=\n\t\t\treturn b.CreateICmp(llvm.IntNE, x, y, \"\"), nil\n\t\tdefault:\n\t\t\treturn llvm.Value{}, b.makeError(pos, \"todo: binop on pointer: \"+op.String())\n\t\t}\n\tcase *types.Slice:\n\t\t// Slices are in general not comparable, but can be compared against\n\t\t// nil. Assume at least one of them is nil to make the code easier.\n\t\txPtr := b.CreateExtractValue(x, 0, \"\")\n\t\tyPtr := b.CreateExtractValue(y, 0, \"\")\n\t\tswitch op {\n\t\tcase token.EQL: // ==\n\t\t\treturn b.CreateICmp(llvm.IntEQ, xPtr, yPtr, \"\"), nil\n\t\tcase token.NEQ: // !=\n\t\t\treturn b.CreateICmp(llvm.IntNE, xPtr, yPtr, \"\"), nil\n\t\tdefault:\n\t\t\treturn llvm.Value{}, b.makeError(pos, \"todo: binop on slice: \"+op.String())\n\t\t}\n\tcase *types.Array:\n\t\t// Compare each array element and combine the result. From the spec:\n\t\t//     Array values are comparable if values of the array element type\n\t\t//     are comparable. Two array values are equal if their corresponding\n\t\t//     elements are equal.\n\t\tresult := llvm.ConstInt(b.ctx.Int1Type(), 1, true)\n\t\tfor i := 0; i < int(typ.Len()); i++ {\n\t\t\txField := b.CreateExtractValue(x, i, \"\")\n\t\t\tyField := b.CreateExtractValue(y, i, \"\")\n\t\t\tfieldEqual, err := b.createBinOp(token.EQL, typ.Elem(), typ.Elem(), xField, yField, pos)\n\t\t\tif err != nil {\n\t\t\t\treturn llvm.Value{}, err\n\t\t\t}\n\t\t\tresult = b.CreateAnd(result, fieldEqual, \"\")\n\t\t}\n\t\tswitch op {\n\t\tcase token.EQL: // ==\n\t\t\treturn result, nil\n\t\tcase token.NEQ: // !=\n\t\t\treturn b.CreateNot(result, \"\"), nil\n\t\tdefault:\n\t\t\treturn llvm.Value{}, b.makeError(pos, \"unknown: binop on struct: \"+op.String())\n\t\t}\n\tcase *types.Struct:\n\t\t// Compare each struct field and combine the result. From the spec:\n\t\t//     Struct values are comparable if all their fields are comparable.\n\t\t//     Two struct values are equal if their corresponding non-blank\n\t\t//     fields are equal.\n\t\tresult := llvm.ConstInt(b.ctx.Int1Type(), 1, true)\n\t\tfor i := 0; i < typ.NumFields(); i++ {\n\t\t\tif typ.Field(i).Name() == \"_\" {\n\t\t\t\t// skip blank fields\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfieldType := typ.Field(i).Type()\n\t\t\txField := b.CreateExtractValue(x, i, \"\")\n\t\t\tyField := b.CreateExtractValue(y, i, \"\")\n\t\t\tfieldEqual, err := b.createBinOp(token.EQL, fieldType, fieldType, xField, yField, pos)\n\t\t\tif err != nil {\n\t\t\t\treturn llvm.Value{}, err\n\t\t\t}\n\t\t\tresult = b.CreateAnd(result, fieldEqual, \"\")\n\t\t}\n\t\tswitch op {\n\t\tcase token.EQL: // ==\n\t\t\treturn result, nil\n\t\tcase token.NEQ: // !=\n\t\t\treturn b.CreateNot(result, \"\"), nil\n\t\tdefault:\n\t\t\treturn llvm.Value{}, b.makeError(pos, \"unknown: binop on struct: \"+op.String())\n\t\t}\n\tdefault:\n\t\treturn llvm.Value{}, b.makeError(pos, \"todo: binop type: \"+typ.String())\n\t}\n}\n\n// createConst creates a LLVM constant value from a Go constant.\nfunc (c *compilerContext) createConst(expr *ssa.Const, pos token.Pos) llvm.Value {\n\tswitch typ := expr.Type().Underlying().(type) {\n\tcase *types.Basic:\n\t\tllvmType := c.getLLVMType(typ)\n\t\tif typ.Info()&types.IsBoolean != 0 {\n\t\t\tn := uint64(0)\n\t\t\tif constant.BoolVal(expr.Value) {\n\t\t\t\tn = 1\n\t\t\t}\n\t\t\treturn llvm.ConstInt(llvmType, n, false)\n\t\t} else if typ.Info()&types.IsString != 0 {\n\t\t\tstr := constant.StringVal(expr.Value)\n\t\t\tstrLen := llvm.ConstInt(c.uintptrType, uint64(len(str)), false)\n\t\t\tvar strPtr llvm.Value\n\t\t\tif str != \"\" {\n\t\t\t\tobjname := c.pkg.Path() + \"$string\"\n\t\t\t\tglobalType := llvm.ArrayType(c.ctx.Int8Type(), len(str))\n\t\t\t\tglobal := llvm.AddGlobal(c.mod, globalType, objname)\n\t\t\t\tglobal.SetInitializer(c.ctx.ConstString(str, false))\n\t\t\t\tglobal.SetLinkage(llvm.InternalLinkage)\n\t\t\t\tglobal.SetGlobalConstant(true)\n\t\t\t\tglobal.SetUnnamedAddr(true)\n\t\t\t\tglobal.SetAlignment(1)\n\t\t\t\tif c.Debug {\n\t\t\t\t\t// Unfortunately, expr.Pos() is always token.NoPos.\n\t\t\t\t\tposition := c.program.Fset.Position(pos)\n\t\t\t\t\tdiglobal := c.dibuilder.CreateGlobalVariableExpression(llvm.Metadata{}, llvm.DIGlobalVariableExpression{\n\t\t\t\t\t\tFile:        c.getDIFile(position.Filename),\n\t\t\t\t\t\tLine:        position.Line,\n\t\t\t\t\t\tType:        c.getDIType(types.NewArray(types.Typ[types.Byte], int64(len(str)))),\n\t\t\t\t\t\tLocalToUnit: true,\n\t\t\t\t\t\tExpr:        c.dibuilder.CreateExpression(nil),\n\t\t\t\t\t})\n\t\t\t\t\tglobal.AddMetadata(0, diglobal)\n\t\t\t\t}\n\t\t\t\tzero := llvm.ConstInt(c.ctx.Int32Type(), 0, false)\n\t\t\t\tstrPtr = llvm.ConstInBoundsGEP(globalType, global, []llvm.Value{zero, zero})\n\t\t\t} else {\n\t\t\t\tstrPtr = llvm.ConstNull(c.dataPtrType)\n\t\t\t}\n\t\t\tstrObj := llvm.ConstNamedStruct(c.getLLVMRuntimeType(\"_string\"), []llvm.Value{strPtr, strLen})\n\t\t\treturn strObj\n\t\t} else if typ.Kind() == types.UnsafePointer {\n\t\t\tif !expr.IsNil() {\n\t\t\t\tvalue, _ := constant.Uint64Val(constant.ToInt(expr.Value))\n\t\t\t\treturn llvm.ConstIntToPtr(llvm.ConstInt(c.uintptrType, value, false), c.dataPtrType)\n\t\t\t}\n\t\t\treturn llvm.ConstNull(c.dataPtrType)\n\t\t} else if typ.Info()&types.IsUnsigned != 0 {\n\t\t\tn, _ := constant.Uint64Val(constant.ToInt(expr.Value))\n\t\t\treturn llvm.ConstInt(llvmType, n, false)\n\t\t} else if typ.Info()&types.IsInteger != 0 { // signed\n\t\t\tn, _ := constant.Int64Val(constant.ToInt(expr.Value))\n\t\t\treturn llvm.ConstInt(llvmType, uint64(n), true)\n\t\t} else if typ.Info()&types.IsFloat != 0 {\n\t\t\tn, _ := constant.Float64Val(expr.Value)\n\t\t\treturn llvm.ConstFloat(llvmType, n)\n\t\t} else if typ.Kind() == types.Complex64 {\n\t\t\tr := c.createConst(ssa.NewConst(constant.Real(expr.Value), types.Typ[types.Float32]), pos)\n\t\t\ti := c.createConst(ssa.NewConst(constant.Imag(expr.Value), types.Typ[types.Float32]), pos)\n\t\t\tcplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.FloatType(), c.ctx.FloatType()}, false))\n\t\t\tcplx = c.builder.CreateInsertValue(cplx, r, 0, \"\")\n\t\t\tcplx = c.builder.CreateInsertValue(cplx, i, 1, \"\")\n\t\t\treturn cplx\n\t\t} else if typ.Kind() == types.Complex128 {\n\t\t\tr := c.createConst(ssa.NewConst(constant.Real(expr.Value), types.Typ[types.Float64]), pos)\n\t\t\ti := c.createConst(ssa.NewConst(constant.Imag(expr.Value), types.Typ[types.Float64]), pos)\n\t\t\tcplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(), c.ctx.DoubleType()}, false))\n\t\t\tcplx = c.builder.CreateInsertValue(cplx, r, 0, \"\")\n\t\t\tcplx = c.builder.CreateInsertValue(cplx, i, 1, \"\")\n\t\t\treturn cplx\n\t\t} else {\n\t\t\tpanic(\"unknown constant of basic type: \" + expr.String())\n\t\t}\n\tcase *types.Chan:\n\t\tif expr.Value != nil {\n\t\t\tpanic(\"expected nil chan constant\")\n\t\t}\n\t\treturn llvm.ConstNull(c.getLLVMType(expr.Type()))\n\tcase *types.Signature:\n\t\tif expr.Value != nil {\n\t\t\tpanic(\"expected nil signature constant\")\n\t\t}\n\t\treturn llvm.ConstNull(c.getLLVMType(expr.Type()))\n\tcase *types.Interface:\n\t\tif expr.Value != nil {\n\t\t\tpanic(\"expected nil interface constant\")\n\t\t}\n\t\t// Create a generic nil interface with no dynamic type (typecode=0).\n\t\tfields := []llvm.Value{\n\t\t\tllvm.ConstInt(c.uintptrType, 0, false),\n\t\t\tllvm.ConstPointerNull(c.dataPtrType),\n\t\t}\n\t\treturn llvm.ConstNamedStruct(c.getLLVMRuntimeType(\"_interface\"), fields)\n\tcase *types.Pointer:\n\t\tif expr.Value != nil {\n\t\t\tpanic(\"expected nil pointer constant\")\n\t\t}\n\t\treturn llvm.ConstPointerNull(c.getLLVMType(typ))\n\tcase *types.Array:\n\t\tif expr.Value != nil {\n\t\t\tpanic(\"expected nil array constant\")\n\t\t}\n\t\treturn llvm.ConstNull(c.getLLVMType(expr.Type()))\n\tcase *types.Slice:\n\t\tif expr.Value != nil {\n\t\t\tpanic(\"expected nil slice constant\")\n\t\t}\n\t\tllvmPtr := llvm.ConstPointerNull(c.dataPtrType)\n\t\tllvmLen := llvm.ConstInt(c.uintptrType, 0, false)\n\t\tslice := c.ctx.ConstStruct([]llvm.Value{\n\t\t\tllvmPtr, // backing array\n\t\t\tllvmLen, // len\n\t\t\tllvmLen, // cap\n\t\t}, false)\n\t\treturn slice\n\tcase *types.Struct:\n\t\tif expr.Value != nil {\n\t\t\tpanic(\"expected nil struct constant\")\n\t\t}\n\t\treturn llvm.ConstNull(c.getLLVMType(expr.Type()))\n\tcase *types.Map:\n\t\tif !expr.IsNil() {\n\t\t\t// I believe this is not allowed by the Go spec.\n\t\t\tpanic(\"non-nil map constant\")\n\t\t}\n\t\tllvmType := c.getLLVMType(typ)\n\t\treturn llvm.ConstNull(llvmType)\n\tdefault:\n\t\tpanic(\"unknown constant: \" + expr.String())\n\t}\n}\n\n// createConvert creates a Go type conversion instruction.\nfunc (b *builder) createConvert(typeFrom, typeTo types.Type, value llvm.Value, pos token.Pos) (llvm.Value, error) {\n\tllvmTypeFrom := value.Type()\n\tllvmTypeTo := b.getLLVMType(typeTo)\n\n\t// Conversion between unsafe.Pointer and uintptr.\n\tisPtrFrom := isPointer(typeFrom.Underlying())\n\tisPtrTo := isPointer(typeTo.Underlying())\n\tif isPtrFrom && !isPtrTo {\n\t\treturn b.CreatePtrToInt(value, llvmTypeTo, \"\"), nil\n\t} else if !isPtrFrom && isPtrTo {\n\t\treturn b.CreateIntToPtr(value, llvmTypeTo, \"\"), nil\n\t}\n\n\t// Conversion between pointers and unsafe.Pointer.\n\tif isPtrFrom && isPtrTo {\n\t\treturn value, nil\n\t}\n\n\tswitch typeTo := typeTo.Underlying().(type) {\n\tcase *types.Basic:\n\t\tsizeFrom := b.targetData.TypeAllocSize(llvmTypeFrom)\n\n\t\tif typeTo.Info()&types.IsString != 0 {\n\t\t\tswitch typeFrom := typeFrom.Underlying().(type) {\n\t\t\tcase *types.Basic:\n\t\t\t\t// Assume a Unicode code point, as that is the only possible\n\t\t\t\t// value here.\n\t\t\t\t// Cast to an i32 value as expected by\n\t\t\t\t// runtime.stringFromUnicode.\n\t\t\t\tif sizeFrom > 4 {\n\t\t\t\t\tvalue = b.CreateTrunc(value, b.ctx.Int32Type(), \"\")\n\t\t\t\t} else if sizeFrom < 4 && typeTo.Info()&types.IsUnsigned != 0 {\n\t\t\t\t\tvalue = b.CreateZExt(value, b.ctx.Int32Type(), \"\")\n\t\t\t\t} else if sizeFrom < 4 {\n\t\t\t\t\tvalue = b.CreateSExt(value, b.ctx.Int32Type(), \"\")\n\t\t\t\t}\n\t\t\t\treturn b.createRuntimeCall(\"stringFromUnicode\", []llvm.Value{value}, \"\"), nil\n\t\t\tcase *types.Slice:\n\t\t\t\tswitch typeFrom.Elem().(*types.Basic).Kind() {\n\t\t\t\tcase types.Byte:\n\t\t\t\t\treturn b.createRuntimeCall(\"stringFromBytes\", []llvm.Value{value}, \"\"), nil\n\t\t\t\tcase types.Rune:\n\t\t\t\t\treturn b.createRuntimeCall(\"stringFromRunes\", []llvm.Value{value}, \"\"), nil\n\t\t\t\tdefault:\n\t\t\t\t\treturn llvm.Value{}, b.makeError(pos, \"todo: convert to string: \"+typeFrom.String())\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn llvm.Value{}, b.makeError(pos, \"todo: convert to string: \"+typeFrom.String())\n\t\t\t}\n\t\t}\n\n\t\ttypeFrom := typeFrom.Underlying().(*types.Basic)\n\t\tsizeTo := b.targetData.TypeAllocSize(llvmTypeTo)\n\n\t\tif typeFrom.Info()&types.IsInteger != 0 && typeTo.Info()&types.IsInteger != 0 {\n\t\t\t// Conversion between two integers.\n\t\t\tif sizeFrom > sizeTo {\n\t\t\t\treturn b.CreateTrunc(value, llvmTypeTo, \"\"), nil\n\t\t\t} else if typeFrom.Info()&types.IsUnsigned != 0 { // if unsigned\n\t\t\t\treturn b.CreateZExt(value, llvmTypeTo, \"\"), nil\n\t\t\t} else { // if signed\n\t\t\t\treturn b.CreateSExt(value, llvmTypeTo, \"\"), nil\n\t\t\t}\n\t\t}\n\n\t\tif typeFrom.Info()&types.IsFloat != 0 && typeTo.Info()&types.IsFloat != 0 {\n\t\t\t// Conversion between two floats.\n\t\t\tif sizeFrom > sizeTo {\n\t\t\t\treturn b.CreateFPTrunc(value, llvmTypeTo, \"\"), nil\n\t\t\t} else if sizeFrom < sizeTo {\n\t\t\t\treturn b.CreateFPExt(value, llvmTypeTo, \"\"), nil\n\t\t\t} else {\n\t\t\t\treturn value, nil\n\t\t\t}\n\t\t}\n\n\t\tif typeFrom.Info()&types.IsFloat != 0 && typeTo.Info()&types.IsInteger != 0 {\n\t\t\t// Conversion from float to int.\n\t\t\t// Passing an out-of-bounds float to LLVM would cause UB, so that UB is trapped by select instructions.\n\t\t\t// The Go specification says that this should be implementation-defined behavior.\n\t\t\t// This implements saturating behavior, except that NaN is mapped to the minimum value.\n\t\t\tvar significandBits int\n\t\t\tswitch typeFrom.Kind() {\n\t\t\tcase types.Float32:\n\t\t\t\tsignificandBits = 23\n\t\t\tcase types.Float64:\n\t\t\t\tsignificandBits = 52\n\t\t\t}\n\t\t\tif typeTo.Info()&types.IsUnsigned != 0 { // if unsigned\n\t\t\t\t// Select the maximum value for this unsigned integer type.\n\t\t\t\tmax := ^(^uint64(0) << uint(llvmTypeTo.IntTypeWidth()))\n\t\t\t\tmaxFloat := float64(max)\n\t\t\t\tif bits.Len64(max) > significandBits {\n\t\t\t\t\t// Round the max down to fit within the significand.\n\t\t\t\t\tmaxFloat = float64(max & (^uint64(0) << uint(bits.Len64(max)-significandBits)))\n\t\t\t\t}\n\n\t\t\t\t// Check if the value is in-bounds (0 <= value <= max).\n\t\t\t\tpositive := b.CreateFCmp(llvm.FloatOLE, llvm.ConstNull(llvmTypeFrom), value, \"positive\")\n\t\t\t\twithinMax := b.CreateFCmp(llvm.FloatOLE, value, llvm.ConstFloat(llvmTypeFrom, maxFloat), \"withinmax\")\n\t\t\t\tinBounds := b.CreateAnd(positive, withinMax, \"inbounds\")\n\n\t\t\t\t// Assuming that the value is out-of-bounds, select a saturated value.\n\t\t\t\tsaturated := b.CreateSelect(positive,\n\t\t\t\t\tllvm.ConstInt(llvmTypeTo, max, false), // value > max\n\t\t\t\t\tllvm.ConstNull(llvmTypeTo),            // value < 0 (or NaN)\n\t\t\t\t\t\"saturated\",\n\t\t\t\t)\n\n\t\t\t\t// Do a normal conversion.\n\t\t\t\tnormal := b.CreateFPToUI(value, llvmTypeTo, \"normal\")\n\n\t\t\t\treturn b.CreateSelect(inBounds, normal, saturated, \"\"), nil\n\t\t\t} else { // if signed\n\t\t\t\t// Select the minimum value for this signed integer type.\n\t\t\t\tmin := uint64(1) << uint(llvmTypeTo.IntTypeWidth()-1)\n\t\t\t\tminFloat := -float64(min)\n\n\t\t\t\t// Select the maximum value for this signed integer type.\n\t\t\t\tmax := ^(^uint64(0) << uint(llvmTypeTo.IntTypeWidth()-1))\n\t\t\t\tmaxFloat := float64(max)\n\t\t\t\tif bits.Len64(max) > significandBits {\n\t\t\t\t\t// Round the max down to fit within the significand.\n\t\t\t\t\tmaxFloat = float64(max & (^uint64(0) << uint(bits.Len64(max)-significandBits)))\n\t\t\t\t}\n\n\t\t\t\t// Check if the value is in-bounds (min <= value <= max).\n\t\t\t\taboveMin := b.CreateFCmp(llvm.FloatOLE, llvm.ConstFloat(llvmTypeFrom, minFloat), value, \"abovemin\")\n\t\t\t\tbelowMax := b.CreateFCmp(llvm.FloatOLE, value, llvm.ConstFloat(llvmTypeFrom, maxFloat), \"belowmax\")\n\t\t\t\tinBounds := b.CreateAnd(aboveMin, belowMax, \"inbounds\")\n\n\t\t\t\t// Assuming that the value is out-of-bounds, select a saturated value.\n\t\t\t\tsaturated := b.CreateSelect(aboveMin,\n\t\t\t\t\tllvm.ConstInt(llvmTypeTo, max, false), // value > max\n\t\t\t\t\tllvm.ConstInt(llvmTypeTo, min, false), // value < min\n\t\t\t\t\t\"saturated\",\n\t\t\t\t)\n\n\t\t\t\t// Map NaN to 0.\n\t\t\t\tsaturated = b.CreateSelect(b.CreateFCmp(llvm.FloatUNO, value, value, \"isnan\"),\n\t\t\t\t\tllvm.ConstNull(llvmTypeTo),\n\t\t\t\t\tsaturated,\n\t\t\t\t\t\"remapped\",\n\t\t\t\t)\n\n\t\t\t\t// Do a normal conversion.\n\t\t\t\tnormal := b.CreateFPToSI(value, llvmTypeTo, \"normal\")\n\n\t\t\t\treturn b.CreateSelect(inBounds, normal, saturated, \"\"), nil\n\t\t\t}\n\t\t}\n\n\t\tif typeFrom.Info()&types.IsInteger != 0 && typeTo.Info()&types.IsFloat != 0 {\n\t\t\t// Conversion from int to float.\n\t\t\tif typeFrom.Info()&types.IsUnsigned != 0 { // if unsigned\n\t\t\t\treturn b.CreateUIToFP(value, llvmTypeTo, \"\"), nil\n\t\t\t} else { // if signed\n\t\t\t\treturn b.CreateSIToFP(value, llvmTypeTo, \"\"), nil\n\t\t\t}\n\t\t}\n\n\t\tif typeFrom.Kind() == types.Complex128 && typeTo.Kind() == types.Complex64 {\n\t\t\t// Conversion from complex128 to complex64.\n\t\t\tr := b.CreateExtractValue(value, 0, \"real.f64\")\n\t\t\ti := b.CreateExtractValue(value, 1, \"imag.f64\")\n\t\t\tr = b.CreateFPTrunc(r, b.ctx.FloatType(), \"real.f32\")\n\t\t\ti = b.CreateFPTrunc(i, b.ctx.FloatType(), \"imag.f32\")\n\t\t\tcplx := llvm.Undef(b.ctx.StructType([]llvm.Type{b.ctx.FloatType(), b.ctx.FloatType()}, false))\n\t\t\tcplx = b.CreateInsertValue(cplx, r, 0, \"\")\n\t\t\tcplx = b.CreateInsertValue(cplx, i, 1, \"\")\n\t\t\treturn cplx, nil\n\t\t}\n\n\t\tif typeFrom.Kind() == types.Complex64 && typeTo.Kind() == types.Complex128 {\n\t\t\t// Conversion from complex64 to complex128.\n\t\t\tr := b.CreateExtractValue(value, 0, \"real.f32\")\n\t\t\ti := b.CreateExtractValue(value, 1, \"imag.f32\")\n\t\t\tr = b.CreateFPExt(r, b.ctx.DoubleType(), \"real.f64\")\n\t\t\ti = b.CreateFPExt(i, b.ctx.DoubleType(), \"imag.f64\")\n\t\t\tcplx := llvm.Undef(b.ctx.StructType([]llvm.Type{b.ctx.DoubleType(), b.ctx.DoubleType()}, false))\n\t\t\tcplx = b.CreateInsertValue(cplx, r, 0, \"\")\n\t\t\tcplx = b.CreateInsertValue(cplx, i, 1, \"\")\n\t\t\treturn cplx, nil\n\t\t}\n\n\t\treturn llvm.Value{}, b.makeError(pos, \"todo: convert: basic non-integer type: \"+typeFrom.String()+\" -> \"+typeTo.String())\n\n\tcase *types.Slice:\n\t\tif basic, ok := typeFrom.Underlying().(*types.Basic); !ok || basic.Info()&types.IsString == 0 {\n\t\t\tpanic(\"can only convert from a string to a slice\")\n\t\t}\n\n\t\telemType := typeTo.Elem().Underlying().(*types.Basic) // must be byte or rune\n\t\tswitch elemType.Kind() {\n\t\tcase types.Byte:\n\t\t\treturn b.createRuntimeCall(\"stringToBytes\", []llvm.Value{value}, \"\"), nil\n\t\tcase types.Rune:\n\t\t\treturn b.createRuntimeCall(\"stringToRunes\", []llvm.Value{value}, \"\"), nil\n\t\tdefault:\n\t\t\tpanic(\"unexpected type in string to slice conversion\")\n\t\t}\n\n\tdefault:\n\t\treturn llvm.Value{}, b.makeError(pos, \"todo: convert \"+typeTo.String()+\" <- \"+typeFrom.String())\n\t}\n}\n\n// createUnOp creates LLVM IR for a given Go unary operation.\n// Most unary operators are pretty simple, such as the not and minus operator\n// which can all be directly lowered to IR. However, there is also the channel\n// receive operator which is handled in the runtime directly.\nfunc (b *builder) createUnOp(unop *ssa.UnOp) (llvm.Value, error) {\n\tx := b.getValue(unop.X, getPos(unop))\n\tswitch unop.Op {\n\tcase token.NOT: // !x\n\t\treturn b.CreateNot(x, \"\"), nil\n\tcase token.SUB: // -x\n\t\tif typ, ok := unop.X.Type().Underlying().(*types.Basic); ok {\n\t\t\tif typ.Info()&types.IsInteger != 0 {\n\t\t\t\treturn b.CreateSub(llvm.ConstInt(x.Type(), 0, false), x, \"\"), nil\n\t\t\t} else if typ.Info()&types.IsFloat != 0 {\n\t\t\t\treturn b.CreateFNeg(x, \"\"), nil\n\t\t\t} else if typ.Info()&types.IsComplex != 0 {\n\t\t\t\t// Negate both components of the complex number.\n\t\t\t\tr := b.CreateExtractValue(x, 0, \"r\")\n\t\t\t\ti := b.CreateExtractValue(x, 1, \"i\")\n\t\t\t\tr = b.CreateFNeg(r, \"\")\n\t\t\t\ti = b.CreateFNeg(i, \"\")\n\t\t\t\tcplx := llvm.Undef(x.Type())\n\t\t\t\tcplx = b.CreateInsertValue(cplx, r, 0, \"\")\n\t\t\t\tcplx = b.CreateInsertValue(cplx, i, 1, \"\")\n\t\t\t\treturn cplx, nil\n\t\t\t} else {\n\t\t\t\treturn llvm.Value{}, b.makeError(unop.Pos(), \"todo: unknown basic type for negate: \"+typ.String())\n\t\t\t}\n\t\t} else {\n\t\t\treturn llvm.Value{}, b.makeError(unop.Pos(), \"todo: unknown type for negate: \"+unop.X.Type().Underlying().String())\n\t\t}\n\tcase token.MUL: // *x, dereference pointer\n\t\tvalueType := b.getLLVMType(unop.X.Type().Underlying().(*types.Pointer).Elem())\n\t\tif b.targetData.TypeAllocSize(valueType) == 0 {\n\t\t\t// zero-length data\n\t\t\treturn llvm.ConstNull(valueType), nil\n\t\t} else if strings.HasSuffix(unop.X.String(), \"$funcaddr\") {\n\t\t\t// CGo function pointer. The cgo part has rewritten CGo function\n\t\t\t// pointers as stub global variables of the form:\n\t\t\t//     var C.add unsafe.Pointer\n\t\t\t// Instead of a load from the global, create a bitcast of the\n\t\t\t// function pointer itself.\n\t\t\tname := strings.TrimSuffix(unop.X.(*ssa.Global).Name(), \"$funcaddr\")\n\t\t\tpkg := b.fn.Pkg\n\t\t\tif pkg == nil {\n\t\t\t\tpkg = b.fn.Origin().Pkg\n\t\t\t}\n\t\t\t_, fn := b.getFunction(pkg.Members[name].(*ssa.Function))\n\t\t\tif fn.IsNil() {\n\t\t\t\treturn llvm.Value{}, b.makeError(unop.Pos(), \"cgo function not found: \"+name)\n\t\t\t}\n\t\t\treturn fn, nil\n\t\t} else {\n\t\t\tb.createNilCheck(unop.X, x, \"deref\")\n\t\t\tload := b.CreateLoad(valueType, x, \"\")\n\t\t\treturn load, nil\n\t\t}\n\tcase token.XOR: // ^x, toggle all bits in integer\n\t\treturn b.CreateXor(x, llvm.ConstInt(x.Type(), ^uint64(0), false), \"\"), nil\n\tcase token.ARROW: // <-x, receive from channel\n\t\treturn b.createChanRecv(unop), nil\n\tdefault:\n\t\treturn llvm.Value{}, b.makeError(unop.Pos(), \"todo: unknown unop\")\n\t}\n}\n"
  },
  {
    "path": "compiler/compiler_test.go",
    "content": "package compiler\n\nimport (\n\t\"flag\"\n\t\"go/types\"\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/tinygo-org/tinygo/compileopts\"\n\t\"github.com/tinygo-org/tinygo/goenv\"\n\t\"github.com/tinygo-org/tinygo/loader\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// Pass -update to go test to update the output of the test files.\nvar flagUpdate = flag.Bool(\"update\", false, \"update tests based on test output\")\n\ntype testCase struct {\n\tfile      string\n\ttarget    string\n\tscheduler string\n}\n\n// Basic tests for the compiler. Build some Go files and compare the output with\n// the expected LLVM IR for regression testing.\nfunc TestCompiler(t *testing.T) {\n\tt.Parallel()\n\n\t// Determine Go minor version (e.g. 16 in go1.16.3).\n\t_, goMinor, err := goenv.GetGorootVersion()\n\tif err != nil {\n\t\tt.Fatal(\"could not read Go version:\", err)\n\t}\n\n\t// Determine which tests to run, depending on the Go and LLVM versions.\n\ttests := []testCase{\n\t\t{\"basic.go\", \"\", \"\"},\n\t\t{\"pointer.go\", \"\", \"\"},\n\t\t{\"slice.go\", \"\", \"\"},\n\t\t{\"string.go\", \"\", \"\"},\n\t\t{\"float.go\", \"\", \"\"},\n\t\t{\"interface.go\", \"\", \"\"},\n\t\t{\"func.go\", \"\", \"\"},\n\t\t{\"defer.go\", \"cortex-m-qemu\", \"\"},\n\t\t{\"pragma.go\", \"\", \"\"},\n\t\t{\"goroutine.go\", \"wasm\", \"asyncify\"},\n\t\t{\"goroutine.go\", \"cortex-m-qemu\", \"tasks\"},\n\t\t{\"channel.go\", \"\", \"\"},\n\t\t{\"gc.go\", \"\", \"\"},\n\t\t{\"zeromap.go\", \"\", \"\"},\n\t}\n\tif goMinor >= 20 {\n\t\ttests = append(tests, testCase{\"go1.20.go\", \"\", \"\"})\n\t}\n\tif goMinor >= 21 {\n\t\ttests = append(tests, testCase{\"go1.21.go\", \"\", \"\"})\n\t}\n\n\tfor _, tc := range tests {\n\t\tname := tc.file\n\t\ttargetString := \"wasm\"\n\t\tif tc.target != \"\" {\n\t\t\ttargetString = tc.target\n\t\t\tname += \"-\" + tc.target\n\t\t}\n\t\tif tc.scheduler != \"\" {\n\t\t\tname += \"-\" + tc.scheduler\n\t\t}\n\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\toptions := &compileopts.Options{\n\t\t\t\tTarget: targetString,\n\t\t\t}\n\t\t\tif tc.scheduler != \"\" {\n\t\t\t\toptions.Scheduler = tc.scheduler\n\t\t\t}\n\n\t\t\tmod, errs := testCompilePackage(t, options, tc.file)\n\t\t\tif errs != nil {\n\t\t\t\tfor _, err := range errs {\n\t\t\t\t\tt.Error(err)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\terr := llvm.VerifyModule(mod, llvm.PrintMessageAction)\n\t\t\tif err != nil {\n\t\t\t\tt.Error(err)\n\t\t\t}\n\n\t\t\t// Optimize IR a little.\n\t\t\tpassOptions := llvm.NewPassBuilderOptions()\n\t\t\tdefer passOptions.Dispose()\n\t\t\terr = mod.RunPasses(\"instcombine\", llvm.TargetMachine{}, passOptions)\n\t\t\tif err != nil {\n\t\t\t\tt.Error(err)\n\t\t\t}\n\n\t\t\toutFilePrefix := tc.file[:len(tc.file)-3]\n\t\t\tif tc.target != \"\" {\n\t\t\t\toutFilePrefix += \"-\" + tc.target\n\t\t\t}\n\t\t\tif tc.scheduler != \"\" {\n\t\t\t\toutFilePrefix += \"-\" + tc.scheduler\n\t\t\t}\n\t\t\toutPath := \"./testdata/\" + outFilePrefix + \".ll\"\n\n\t\t\t// Update test if needed. Do not check the result.\n\t\t\tif *flagUpdate {\n\t\t\t\terr := os.WriteFile(outPath, []byte(mod.String()), 0666)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Error(\"failed to write updated output file:\", err)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\texpected, err := os.ReadFile(outPath)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(\"failed to read golden file:\", err)\n\t\t\t}\n\n\t\t\tif !fuzzyEqualIR(mod.String(), string(expected)) {\n\t\t\t\tt.Errorf(\"output does not match expected output:\\n%s\", mod.String())\n\t\t\t}\n\t\t})\n\t}\n}\n\n// fuzzyEqualIR returns true if the two LLVM IR strings passed in are roughly\n// equal. That means, only relevant lines are compared (excluding comments\n// etc.).\nfunc fuzzyEqualIR(s1, s2 string) bool {\n\tlines1 := filterIrrelevantIRLines(strings.Split(s1, \"\\n\"))\n\tlines2 := filterIrrelevantIRLines(strings.Split(s2, \"\\n\"))\n\tif len(lines1) != len(lines2) {\n\t\treturn false\n\t}\n\tfor i, line1 := range lines1 {\n\t\tline2 := lines2[i]\n\t\tif line1 != line2 {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\n// filterIrrelevantIRLines removes lines from the input slice of strings that\n// are not relevant in comparing IR. For example, empty lines and comments are\n// stripped out.\nfunc filterIrrelevantIRLines(lines []string) []string {\n\tvar out []string\n\tllvmVersion, err := strconv.Atoi(strings.Split(llvm.Version, \".\")[0])\n\tif err != nil {\n\t\t// Note: this should never happen and if it does, it will always happen\n\t\t// for a particular build because llvm.Version is a constant.\n\t\tpanic(err)\n\t}\n\tfor _, line := range lines {\n\t\tline = strings.Split(line, \";\")[0]    // strip out comments/info\n\t\tline = strings.TrimRight(line, \"\\r \") // drop '\\r' on Windows and remove trailing spaces from comments\n\t\tif line == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tif strings.HasPrefix(line, \"source_filename = \") {\n\t\t\tcontinue\n\t\t}\n\t\tif llvmVersion < 15 && strings.HasPrefix(line, \"target datalayout = \") {\n\t\t\t// The datalayout string may vary betewen LLVM versions.\n\t\t\t// Right now test outputs are for LLVM 15 and higher.\n\t\t\tcontinue\n\t\t}\n\t\tout = append(out, line)\n\t}\n\treturn out\n}\n\nfunc TestCompilerErrors(t *testing.T) {\n\tt.Parallel()\n\n\t// Read expected errors from the test file.\n\tvar expectedErrors []string\n\terrorsFile, err := os.ReadFile(\"testdata/errors.go\")\n\tif err != nil {\n\t\tt.Error(err)\n\t}\n\terrorsFileString := strings.ReplaceAll(string(errorsFile), \"\\r\\n\", \"\\n\")\n\tfor _, line := range strings.Split(errorsFileString, \"\\n\") {\n\t\tif strings.HasPrefix(line, \"// ERROR: \") {\n\t\t\texpectedErrors = append(expectedErrors, strings.TrimPrefix(line, \"// ERROR: \"))\n\t\t}\n\t}\n\n\t// Compile the Go file with errors.\n\toptions := &compileopts.Options{\n\t\tTarget: \"wasm\",\n\t}\n\t_, errs := testCompilePackage(t, options, \"errors.go\")\n\n\t// Check whether the actual errors match the expected errors.\n\texpectedErrorsIdx := 0\n\tfor _, err := range errs {\n\t\terr := err.(types.Error)\n\t\tposition := err.Fset.Position(err.Pos)\n\t\tposition.Filename = \"errors.go\" // don't use a full path\n\t\tif expectedErrorsIdx >= len(expectedErrors) || expectedErrors[expectedErrorsIdx] != err.Msg {\n\t\t\tt.Errorf(\"unexpected compiler error: %s: %s\", position.String(), err.Msg)\n\t\t\tcontinue\n\t\t}\n\t\texpectedErrorsIdx++\n\t}\n}\n\n// Build a package given a number of compiler options and a file.\nfunc testCompilePackage(t *testing.T, options *compileopts.Options, file string) (llvm.Module, []error) {\n\ttarget, err := compileopts.LoadTarget(options)\n\tif err != nil {\n\t\tt.Fatal(\"failed to load target:\", err)\n\t}\n\tconfig := &compileopts.Config{\n\t\tOptions: options,\n\t\tTarget:  target,\n\t}\n\tcompilerConfig := &Config{\n\t\tTriple:             config.Triple(),\n\t\tFeatures:           config.Features(),\n\t\tABI:                config.ABI(),\n\t\tGOOS:               config.GOOS(),\n\t\tGOARCH:             config.GOARCH(),\n\t\tCodeModel:          config.CodeModel(),\n\t\tRelocationModel:    config.RelocationModel(),\n\t\tScheduler:          config.Scheduler(),\n\t\tAutomaticStackSize: config.AutomaticStackSize(),\n\t\tDefaultStackSize:   config.StackSize(),\n\t\tNeedsStackObjects:  config.NeedsStackObjects(),\n\t}\n\tmachine, err := NewTargetMachine(compilerConfig)\n\tif err != nil {\n\t\tt.Fatal(\"failed to create target machine:\", err)\n\t}\n\tdefer machine.Dispose()\n\n\t// Load entire program AST into memory.\n\tlprogram, err := loader.Load(config, \"./testdata/\"+file, types.Config{\n\t\tSizes: Sizes(machine),\n\t})\n\tif err != nil {\n\t\tt.Fatal(\"failed to create target machine:\", err)\n\t}\n\terr = lprogram.Parse()\n\tif err != nil {\n\t\tt.Fatalf(\"could not parse test case %s: %s\", file, err)\n\t}\n\n\t// Compile AST to IR.\n\tprogram := lprogram.LoadSSA()\n\tpkg := lprogram.MainPkg()\n\treturn CompilePackage(file, pkg, program.Package(pkg.Pkg), machine, compilerConfig, false)\n}\n"
  },
  {
    "path": "compiler/defer.go",
    "content": "package compiler\n\n// This file implements the 'defer' keyword in Go.\n// Defer statements are implemented by transforming the function in the\n// following way:\n//   * Creating an alloca in the entry block that contains a pointer (initially\n//     null) to the linked list of defer frames.\n//   * Every time a defer statement is executed, a new defer frame is created\n//     using alloca with a pointer to the previous defer frame, and the head\n//     pointer in the entry block is replaced with a pointer to this defer\n//     frame.\n//   * On return, runtime.rundefers is called which calls all deferred functions\n//     from the head of the linked list until it has gone through all defer\n//     frames.\n\nimport (\n\t\"go/types\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/tinygo-org/tinygo/compiler/llvmutil\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// supportsRecover returns whether the compiler supports the recover() builtin\n// for the current architecture.\nfunc (b *builder) supportsRecover() bool {\n\tswitch b.archFamily() {\n\tcase \"wasm32\":\n\t\t// Probably needs to be implemented using the exception handling\n\t\t// proposal of WebAssembly:\n\t\t// https://github.com/WebAssembly/exception-handling\n\t\treturn false\n\tcase \"riscv64\", \"xtensa\":\n\t\t// TODO: add support for these architectures\n\t\treturn false\n\tdefault:\n\t\treturn true\n\t}\n}\n\n// hasDeferFrame returns whether the current function needs to catch panics and\n// run defers.\nfunc (b *builder) hasDeferFrame() bool {\n\tif b.fn.Recover == nil {\n\t\treturn false\n\t}\n\treturn b.supportsRecover()\n}\n\n// deferInitFunc sets up this function for future deferred calls. It must be\n// called from within the entry block when this function contains deferred\n// calls.\nfunc (b *builder) deferInitFunc() {\n\t// Some setup.\n\tb.deferFuncs = make(map[*ssa.Function]int)\n\tb.deferInvokeFuncs = make(map[string]int)\n\tb.deferClosureFuncs = make(map[*ssa.Function]int)\n\tb.deferExprFuncs = make(map[ssa.Value]int)\n\tb.deferBuiltinFuncs = make(map[ssa.Value]deferBuiltin)\n\n\t// Create defer list pointer.\n\tb.deferPtr = b.CreateAlloca(b.dataPtrType, \"deferPtr\")\n\tb.CreateStore(llvm.ConstPointerNull(b.dataPtrType), b.deferPtr)\n\n\tif b.hasDeferFrame() {\n\t\t// Set up the defer frame with the current stack pointer.\n\t\t// This assumes that the stack pointer doesn't move outside of the\n\t\t// function prologue/epilogue (an invariant maintained by TinyGo but\n\t\t// possibly broken by the C alloca function).\n\t\t// The frame pointer is _not_ saved, because it is marked as clobbered\n\t\t// in the setjmp-like inline assembly.\n\t\tdeferFrameType := b.getLLVMRuntimeType(\"deferFrame\")\n\t\tb.deferFrame = b.CreateAlloca(deferFrameType, \"deferframe.buf\")\n\t\tstackPointer := b.readStackPointer()\n\t\tb.createRuntimeCall(\"setupDeferFrame\", []llvm.Value{b.deferFrame, stackPointer}, \"\")\n\n\t\t// Create the landing pad block, which is where control transfers after\n\t\t// a panic.\n\t\tb.landingpad = b.ctx.AddBasicBlock(b.llvmFn, \"lpad\")\n\t}\n}\n\n// createLandingPad fills in the landing pad block. This block runs the deferred\n// functions and returns (by jumping to the recover block). If the function is\n// still panicking after the defers are run, the panic will be re-raised in\n// destroyDeferFrame.\nfunc (b *builder) createLandingPad() {\n\tb.SetInsertPointAtEnd(b.landingpad)\n\n\t// Add debug info, if needed.\n\t// The location used is the closing bracket of the function.\n\tif b.Debug {\n\t\tpos := b.program.Fset.Position(b.fn.Syntax().End())\n\t\tb.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), b.difunc, llvm.Metadata{})\n\t}\n\n\tb.createRunDefers()\n\n\t// Continue at the 'recover' block, which returns to the parent in an\n\t// appropriate way.\n\tb.CreateBr(b.blockInfo[b.fn.Recover.Index].entry)\n}\n\n// Create a checkpoint (similar to setjmp). This emits inline assembly that\n// stores the current program counter inside the ptr address (actually\n// ptr+sizeof(ptr)) and then returns a boolean indicating whether this is the\n// normal flow (false) or we jumped here from somewhere else (true).\nfunc (b *builder) createCheckpoint(ptr llvm.Value) llvm.Value {\n\t// Construct inline assembly equivalents of setjmp.\n\t// The assembly works as follows:\n\t//   * All registers (both callee-saved and caller saved) are clobbered\n\t//     after the inline assembly returns.\n\t//   * The assembly stores the address just past the end of the assembly\n\t//     into the jump buffer.\n\t//   * The return value (eax, rax, r0, etc) is set to zero in the inline\n\t//     assembly but set to an unspecified non-zero value when jumping using\n\t//     a longjmp.\n\tvar asmString, constraints string\n\tresultType := b.uintptrType\n\tswitch b.archFamily() {\n\tcase \"i386\":\n\t\tasmString = `\nxorl %eax, %eax\nmovl $$1f, 4(%ebx)\n1:`\n\t\tconstraints = \"={eax},{ebx},~{ebx},~{ecx},~{edx},~{esi},~{edi},~{ebp},~{xmm0},~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{fpsr},~{fpcr},~{flags},~{dirflag},~{memory}\"\n\t\t// This doesn't include the floating point stack because TinyGo uses\n\t\t// newer floating point instructions.\n\tcase \"x86_64\":\n\t\tasmString = `\nleaq 1f(%rip), %rax\nmovq %rax, 8(%rbx)\nxorq %rax, %rax\n1:`\n\t\tconstraints = \"={rax},{rbx},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15},~{xmm0},~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{fpsr},~{fpcr},~{flags},~{dirflag},~{memory}\"\n\t\t// This list doesn't include AVX/AVX512 registers because TinyGo\n\t\t// doesn't currently enable support for AVX instructions.\n\tcase \"arm\":\n\t\t// Note: the following assembly takes into account that the PC is\n\t\t// always 4 bytes ahead on ARM. The PC that is stored always points\n\t\t// to the instruction just after the assembly fragment so that\n\t\t// tinygo_longjmp lands at the correct instruction.\n\t\tif b.isThumb() {\n\t\t\t// Instructions are 2 bytes in size.\n\t\t\tasmString = `\nmovs r0, #0\nmov r2, pc\nstr r2, [r1, #4]`\n\t\t} else {\n\t\t\t// Instructions are 4 bytes in size.\n\t\t\tasmString = `\nstr pc, [r1, #4]\nmovs r0, #0`\n\t\t}\n\t\tconstraints = \"={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}\"\n\tcase \"aarch64\":\n\t\tasmString = `\nadr x2, 1f\nstr x2, [x1, #8]\nmov x0, #0\n1:\n`\n\t\tconstraints = \"={x0},{x1},~{x1},~{x2},~{x3},~{x4},~{x5},~{x6},~{x7},~{x8},~{x9},~{x10},~{x11},~{x12},~{x13},~{x14},~{x15},~{x16},~{x17},~{x19},~{x20},~{x21},~{x22},~{x23},~{x24},~{x25},~{x26},~{x27},~{x28},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{q16},~{q17},~{q18},~{q19},~{q20},~{q21},~{q22},~{q23},~{q24},~{q25},~{q26},~{q27},~{q28},~{q29},~{q30},~{nzcv},~{ffr},~{memory}\"\n\t\tif b.GOOS != \"darwin\" && b.GOOS != \"windows\" {\n\t\t\t// These registers cause the following warning when compiling for\n\t\t\t// MacOS and Windows:\n\t\t\t//     warning: inline asm clobber list contains reserved registers:\n\t\t\t//     X18, FP\n\t\t\t//     Reserved registers on the clobber list may not be preserved\n\t\t\t//     across the asm statement, and clobbering them may lead to\n\t\t\t//     undefined behaviour.\n\t\t\tconstraints += \",~{x18},~{fp}\"\n\t\t}\n\t\t// TODO: SVE registers, which we don't use in TinyGo at the moment.\n\tcase \"avr\":\n\t\t// Note: the Y register (R28:R29) is a fixed register and therefore\n\t\t// needs to be saved manually. TODO: do this only once per function with\n\t\t// a defer frame, not for every call.\n\t\tresultType = b.ctx.Int8Type()\n\t\tasmString = `\nldi r24, pm_lo8(1f)\nldi r25, pm_hi8(1f)\nstd z+2, r24\nstd z+3, r25\nstd z+4, r28\nstd z+5, r29\nldi r24, 0\n1:`\n\t\tconstraints = \"={r24},z,~{r0},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15},~{r16},~{r17},~{r18},~{r19},~{r20},~{r21},~{r22},~{r23},~{r25},~{r26},~{r27}\"\n\tcase \"mips\":\n\t\t// $4 flag (zero or non-zero)\n\t\t// $5 defer frame\n\t\tasmString = `\n.set noat\nmove $$4, $$zero\njal 1f\n1:\naddiu $$ra, 8\nsw $$ra, 4($$5)\n.set at`\n\t\tconstraints = \"={$4},{$5},~{$1},~{$2},~{$3},~{$5},~{$6},~{$7},~{$8},~{$9},~{$10},~{$11},~{$12},~{$13},~{$14},~{$15},~{$16},~{$17},~{$18},~{$19},~{$20},~{$21},~{$22},~{$23},~{$24},~{$25},~{$26},~{$27},~{$28},~{$29},~{$30},~{$31},~{memory}\"\n\t\tif !strings.Contains(b.Features, \"+soft-float\") {\n\t\t\t// Using floating point registers together with GOMIPS=softfloat\n\t\t\t// results in a crash: \"This value type is not natively supported!\"\n\t\t\t// So only add them when using hardfloat.\n\t\t\tconstraints += \",~{$f0},~{$f1},~{$f2},~{$f3},~{$f4},~{$f5},~{$f6},~{$f7},~{$f8},~{$f9},~{$f10},~{$f11},~{$f12},~{$f13},~{$f14},~{$f15},~{$f16},~{$f17},~{$f18},~{$f19},~{$f20},~{$f21},~{$f22},~{$f23},~{$f24},~{$f25},~{$f26},~{$f27},~{$f28},~{$f29},~{$f30},~{$f31}\"\n\t\t}\n\tcase \"riscv32\":\n\t\tasmString = `\nla a2, 1f\nsw a2, 4(a1)\nli a0, 0\n1:`\n\t\tconstraints = \"={a0},{a1},~{a1},~{a2},~{a3},~{a4},~{a5},~{a6},~{a7},~{s0},~{s1},~{s2},~{s3},~{s4},~{s5},~{s6},~{s7},~{s8},~{s9},~{s10},~{s11},~{t0},~{t1},~{t2},~{t3},~{t4},~{t5},~{t6},~{ra},~{f0},~{f1},~{f2},~{f3},~{f4},~{f5},~{f6},~{f7},~{f8},~{f9},~{f10},~{f11},~{f12},~{f13},~{f14},~{f15},~{f16},~{f17},~{f18},~{f19},~{f20},~{f21},~{f22},~{f23},~{f24},~{f25},~{f26},~{f27},~{f28},~{f29},~{f30},~{f31},~{memory}\"\n\tdefault:\n\t\t// This case should have been handled by b.supportsRecover().\n\t\tb.addError(b.fn.Pos(), \"unknown architecture for defer: \"+b.archFamily())\n\t}\n\tasmType := llvm.FunctionType(resultType, []llvm.Type{b.dataPtrType}, false)\n\tasm := llvm.InlineAsm(asmType, asmString, constraints, false, false, 0, false)\n\tresult := b.CreateCall(asmType, asm, []llvm.Value{ptr}, \"setjmp\")\n\tresult.AddCallSiteAttribute(-1, b.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"returns_twice\"), 0))\n\tisZero := b.CreateICmp(llvm.IntEQ, result, llvm.ConstInt(resultType, 0, false), \"setjmp.result\")\n\treturn isZero\n}\n\n// createInvokeCheckpoint saves the function state at the given point, to\n// continue at the landing pad if a panic happened. This is implemented using a\n// setjmp-like construct.\nfunc (b *builder) createInvokeCheckpoint() {\n\tisZero := b.createCheckpoint(b.deferFrame)\n\tcontinueBB := b.insertBasicBlock(\"\")\n\tb.CreateCondBr(isZero, continueBB, b.landingpad)\n\tb.SetInsertPointAtEnd(continueBB)\n\tb.currentBlockInfo.exit = continueBB\n}\n\n// isInLoop checks if there is a path from the current block to itself.\n// Use Tarjan's strongly connected components algorithm to search for cycles.\n// A one-node SCC is a cycle iff there is an edge from the node to itself.\n// A multi-node SCC is always a cycle.\n// https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm\nfunc (b *builder) isInLoop() bool {\n\tif b.currentBlockInfo.tarjan.lowLink == 0 {\n\t\tb.strongConnect(b.currentBlock)\n\t}\n\treturn b.currentBlockInfo.tarjan.cyclic\n}\n\nfunc (b *builder) strongConnect(block *ssa.BasicBlock) {\n\t// Assign a new index.\n\t// Indices start from 1 so that 0 can be used as a sentinel.\n\tassignedIndex := b.tarjanIndex + 1\n\tb.tarjanIndex = assignedIndex\n\n\t// Apply the new index.\n\tblockIndex := block.Index\n\tnode := &b.blockInfo[blockIndex].tarjan\n\tnode.lowLink = assignedIndex\n\n\t// Push the node onto the stack.\n\tnode.onStack = true\n\tb.tarjanStack = append(b.tarjanStack, uint(blockIndex))\n\n\t// Process the successors.\n\tfor _, successor := range block.Succs {\n\t\t// Look up the successor's state.\n\t\tsuccessorIndex := successor.Index\n\t\tif successorIndex == blockIndex {\n\t\t\t// Handle a self-cycle specially.\n\t\t\tnode.cyclic = true\n\t\t\tcontinue\n\t\t}\n\t\tsuccessorNode := &b.blockInfo[successorIndex].tarjan\n\n\t\tswitch {\n\t\tcase successorNode.lowLink == 0:\n\t\t\t// This node has not yet been visisted.\n\t\t\tb.strongConnect(successor)\n\n\t\tcase !successorNode.onStack:\n\t\t\t// This node has been visited, but is in a different SCC.\n\t\t\t// Ignore it, and do not update lowLink.\n\t\t\tcontinue\n\t\t}\n\n\t\t// Update the lowLink index.\n\t\t// This always uses the min-of-lowlink instead of using index in the on-stack case.\n\t\t// This is done for two reasons:\n\t\t// 1. The lowLink update can be shared between the new-node and on-stack cases.\n\t\t// 2. The assigned index does not need to be saved - it is only needed for root node detection.\n\t\tif successorNode.lowLink < node.lowLink {\n\t\t\tnode.lowLink = successorNode.lowLink\n\t\t}\n\t}\n\n\tif node.lowLink == assignedIndex {\n\t\t// This is a root node.\n\t\t// Pop the SCC off the stack.\n\t\tstack := b.tarjanStack\n\t\ttop := stack[len(stack)-1]\n\t\tstack = stack[:len(stack)-1]\n\t\tblocks := b.blockInfo\n\t\ttopNode := &blocks[top].tarjan\n\t\ttopNode.onStack = false\n\n\t\tif top != uint(blockIndex) {\n\t\t\t// The root node is not the only node in the SCC.\n\t\t\t// Mark all nodes in this SCC as cyclic.\n\t\t\ttopNode.cyclic = true\n\t\t\tfor top != uint(blockIndex) {\n\t\t\t\ttop = stack[len(stack)-1]\n\t\t\t\tstack = stack[:len(stack)-1]\n\t\t\t\ttopNode = &blocks[top].tarjan\n\t\t\t\ttopNode.onStack = false\n\t\t\t\ttopNode.cyclic = true\n\t\t\t}\n\t\t}\n\n\t\tb.tarjanStack = stack\n\t}\n}\n\n// tarjanNode holds per-block state for isInLoop and strongConnect.\ntype tarjanNode struct {\n\t// lowLink is the index of the first visited node that is reachable from this block.\n\t// The lowLink indices are assigned by the SCC search, and do not correspond to b.Index.\n\t// A lowLink of 0 is used as a sentinel to mark a node which has not yet been visited.\n\tlowLink uint\n\n\t// onStack tracks whether this node is currently on the SCC search stack.\n\tonStack bool\n\n\t// cyclic indicates whether this block is in a loop.\n\t// If lowLink is 0, strongConnect must be called before reading this field.\n\tcyclic bool\n}\n\n// createDefer emits a single defer instruction, to be run when this function\n// returns.\nfunc (b *builder) createDefer(instr *ssa.Defer) {\n\t// The pointer to the previous defer struct, which we will replace to\n\t// make a linked list.\n\tnext := b.CreateLoad(b.dataPtrType, b.deferPtr, \"defer.next\")\n\n\tvar values []llvm.Value\n\tvalueTypes := []llvm.Type{b.uintptrType, next.Type()}\n\tif instr.Call.IsInvoke() {\n\t\t// Method call on an interface.\n\n\t\t// Get callback type number.\n\t\tmethodName := instr.Call.Method.FullName()\n\t\tif _, ok := b.deferInvokeFuncs[methodName]; !ok {\n\t\t\tb.deferInvokeFuncs[methodName] = len(b.allDeferFuncs)\n\t\t\tb.allDeferFuncs = append(b.allDeferFuncs, &instr.Call)\n\t\t}\n\t\tcallback := llvm.ConstInt(b.uintptrType, uint64(b.deferInvokeFuncs[methodName]), false)\n\n\t\t// Collect all values to be put in the struct (starting with\n\t\t// runtime._defer fields, followed by the call parameters).\n\t\titf := b.getValue(instr.Call.Value, getPos(instr)) // interface\n\t\ttypecode := b.CreateExtractValue(itf, 0, \"invoke.func.typecode\")\n\t\treceiverValue := b.CreateExtractValue(itf, 1, \"invoke.func.receiver\")\n\t\tvalues = []llvm.Value{callback, next, typecode, receiverValue}\n\t\tvalueTypes = append(valueTypes, b.dataPtrType, b.dataPtrType)\n\t\tfor _, arg := range instr.Call.Args {\n\t\t\tval := b.getValue(arg, getPos(instr))\n\t\t\tvalues = append(values, val)\n\t\t\tvalueTypes = append(valueTypes, val.Type())\n\t\t}\n\n\t} else if callee, ok := instr.Call.Value.(*ssa.Function); ok {\n\t\t// Regular function call.\n\t\tif _, ok := b.deferFuncs[callee]; !ok {\n\t\t\tb.deferFuncs[callee] = len(b.allDeferFuncs)\n\t\t\tb.allDeferFuncs = append(b.allDeferFuncs, callee)\n\t\t}\n\t\tcallback := llvm.ConstInt(b.uintptrType, uint64(b.deferFuncs[callee]), false)\n\n\t\t// Collect all values to be put in the struct (starting with\n\t\t// runtime._defer fields).\n\t\tvalues = []llvm.Value{callback, next}\n\t\tfor _, param := range instr.Call.Args {\n\t\t\tllvmParam := b.getValue(param, getPos(instr))\n\t\t\tvalues = append(values, llvmParam)\n\t\t\tvalueTypes = append(valueTypes, llvmParam.Type())\n\t\t}\n\n\t} else if makeClosure, ok := instr.Call.Value.(*ssa.MakeClosure); ok {\n\t\t// Immediately applied function literal with free variables.\n\n\t\t// Extract the context from the closure. We won't need the function\n\t\t// pointer.\n\t\t// TODO: ignore this closure entirely and put pointers to the free\n\t\t// variables directly in the defer struct, avoiding a memory allocation.\n\t\tclosure := b.getValue(instr.Call.Value, getPos(instr))\n\t\tcontext := b.CreateExtractValue(closure, 0, \"\")\n\n\t\t// Get the callback number.\n\t\tfn := makeClosure.Fn.(*ssa.Function)\n\t\tif _, ok := b.deferClosureFuncs[fn]; !ok {\n\t\t\tb.deferClosureFuncs[fn] = len(b.allDeferFuncs)\n\t\t\tb.allDeferFuncs = append(b.allDeferFuncs, makeClosure)\n\t\t}\n\t\tcallback := llvm.ConstInt(b.uintptrType, uint64(b.deferClosureFuncs[fn]), false)\n\n\t\t// Collect all values to be put in the struct (starting with\n\t\t// runtime._defer fields, followed by all parameters including the\n\t\t// context pointer).\n\t\tvalues = []llvm.Value{callback, next}\n\t\tfor _, param := range instr.Call.Args {\n\t\t\tllvmParam := b.getValue(param, getPos(instr))\n\t\t\tvalues = append(values, llvmParam)\n\t\t\tvalueTypes = append(valueTypes, llvmParam.Type())\n\t\t}\n\t\tvalues = append(values, context)\n\t\tvalueTypes = append(valueTypes, context.Type())\n\n\t} else if builtin, ok := instr.Call.Value.(*ssa.Builtin); ok {\n\t\tvar argTypes []types.Type\n\t\tvar argValues []llvm.Value\n\t\tfor _, arg := range instr.Call.Args {\n\t\t\targTypes = append(argTypes, arg.Type())\n\t\t\targValues = append(argValues, b.getValue(arg, getPos(instr)))\n\t\t}\n\n\t\tif _, ok := b.deferBuiltinFuncs[instr.Call.Value]; !ok {\n\t\t\tb.deferBuiltinFuncs[instr.Call.Value] = deferBuiltin{\n\t\t\t\tcallName: builtin.Name(),\n\t\t\t\tpos:      builtin.Pos(),\n\t\t\t\targTypes: argTypes,\n\t\t\t\tcallback: len(b.allDeferFuncs),\n\t\t\t}\n\t\t\tb.allDeferFuncs = append(b.allDeferFuncs, instr.Call.Value)\n\t\t}\n\t\tcallback := llvm.ConstInt(b.uintptrType, uint64(b.deferBuiltinFuncs[instr.Call.Value].callback), false)\n\n\t\t// Collect all values to be put in the struct (starting with\n\t\t// runtime._defer fields).\n\t\tvalues = []llvm.Value{callback, next}\n\t\tfor _, param := range argValues {\n\t\t\tvalues = append(values, param)\n\t\t\tvalueTypes = append(valueTypes, param.Type())\n\t\t}\n\n\t} else {\n\t\tfuncValue := b.getValue(instr.Call.Value, getPos(instr))\n\n\t\tif _, ok := b.deferExprFuncs[instr.Call.Value]; !ok {\n\t\t\tb.deferExprFuncs[instr.Call.Value] = len(b.allDeferFuncs)\n\t\t\tb.allDeferFuncs = append(b.allDeferFuncs, &instr.Call)\n\t\t}\n\n\t\tcallback := llvm.ConstInt(b.uintptrType, uint64(b.deferExprFuncs[instr.Call.Value]), false)\n\n\t\t// Collect all values to be put in the struct (starting with\n\t\t// runtime._defer fields, followed by all parameters including the\n\t\t// context pointer).\n\t\tvalues = []llvm.Value{callback, next, funcValue}\n\t\tvalueTypes = append(valueTypes, funcValue.Type())\n\t\tfor _, param := range instr.Call.Args {\n\t\t\tllvmParam := b.getValue(param, getPos(instr))\n\t\t\tvalues = append(values, llvmParam)\n\t\t\tvalueTypes = append(valueTypes, llvmParam.Type())\n\t\t}\n\t}\n\n\t// Make a struct out of the collected values to put in the deferred call\n\t// struct.\n\tdeferredCallType := b.ctx.StructType(valueTypes, false)\n\tdeferredCall := llvm.ConstNull(deferredCallType)\n\tfor i, value := range values {\n\t\tdeferredCall = b.CreateInsertValue(deferredCall, value, i, \"\")\n\t}\n\n\t// Put this struct in an allocation.\n\tvar alloca llvm.Value\n\tif instr.Block() != b.currentBlock {\n\t\tpanic(\"block mismatch\")\n\t}\n\tif !b.isInLoop() {\n\t\t// This can safely use a stack allocation.\n\t\talloca = llvmutil.CreateEntryBlockAlloca(b.Builder, deferredCallType, \"defer.alloca\")\n\t} else {\n\t\t// This may be hit a variable number of times, so use a heap allocation.\n\t\tsize := b.targetData.TypeAllocSize(deferredCallType)\n\t\tsizeValue := llvm.ConstInt(b.uintptrType, size, false)\n\t\tnilPtr := llvm.ConstNull(b.dataPtrType)\n\t\talloca = b.createRuntimeCall(\"alloc\", []llvm.Value{sizeValue, nilPtr}, \"defer.alloc.call\")\n\t}\n\tif b.NeedsStackObjects {\n\t\tb.trackPointer(alloca)\n\t}\n\tb.CreateStore(deferredCall, alloca)\n\n\t// Push it on top of the linked list by replacing deferPtr.\n\tb.CreateStore(alloca, b.deferPtr)\n}\n\n// createRunDefers emits code to run all deferred functions.\nfunc (b *builder) createRunDefers() {\n\tdeferType := b.getLLVMRuntimeType(\"_defer\")\n\n\t// Add a loop like the following:\n\t//     for stack != nil {\n\t//         _stack := stack\n\t//         stack = stack.next\n\t//         switch _stack.callback {\n\t//         case 0:\n\t//             // run first deferred call\n\t//         case 1:\n\t//             // run second deferred call\n\t//             // etc.\n\t//         default:\n\t//             unreachable\n\t//         }\n\t//     }\n\n\t// Create loop, in the order: loophead, loop, callback0, callback1, ..., unreachable, end.\n\tend := b.insertBasicBlock(\"rundefers.end\")\n\tunreachable := b.ctx.InsertBasicBlock(end, \"rundefers.default\")\n\tloop := b.ctx.InsertBasicBlock(unreachable, \"rundefers.loop\")\n\tloophead := b.ctx.InsertBasicBlock(loop, \"rundefers.loophead\")\n\tb.CreateBr(loophead)\n\n\t// Create loop head:\n\t//     for stack != nil {\n\tb.SetInsertPointAtEnd(loophead)\n\tdeferData := b.CreateLoad(b.dataPtrType, b.deferPtr, \"\")\n\tstackIsNil := b.CreateICmp(llvm.IntEQ, deferData, llvm.ConstPointerNull(deferData.Type()), \"stackIsNil\")\n\tb.CreateCondBr(stackIsNil, end, loop)\n\n\t// Create loop body:\n\t//     _stack := stack\n\t//     stack = stack.next\n\t//     switch stack.callback {\n\tb.SetInsertPointAtEnd(loop)\n\tnextStackGEP := b.CreateInBoundsGEP(deferType, deferData, []llvm.Value{\n\t\tllvm.ConstInt(b.ctx.Int32Type(), 0, false),\n\t\tllvm.ConstInt(b.ctx.Int32Type(), 1, false), // .next field\n\t}, \"stack.next.gep\")\n\tnextStack := b.CreateLoad(b.dataPtrType, nextStackGEP, \"stack.next\")\n\tb.CreateStore(nextStack, b.deferPtr)\n\tgep := b.CreateInBoundsGEP(deferType, deferData, []llvm.Value{\n\t\tllvm.ConstInt(b.ctx.Int32Type(), 0, false),\n\t\tllvm.ConstInt(b.ctx.Int32Type(), 0, false), // .callback field\n\t}, \"callback.gep\")\n\tcallback := b.CreateLoad(b.uintptrType, gep, \"callback\")\n\tsw := b.CreateSwitch(callback, unreachable, len(b.allDeferFuncs))\n\n\tfor i, callback := range b.allDeferFuncs {\n\t\t// Create switch case, for example:\n\t\t//     case 0:\n\t\t//         // run first deferred call\n\t\tblock := b.insertBasicBlock(\"rundefers.callback\" + strconv.Itoa(i))\n\t\tsw.AddCase(llvm.ConstInt(b.uintptrType, uint64(i), false), block)\n\t\tb.SetInsertPointAtEnd(block)\n\t\tswitch callback := callback.(type) {\n\t\tcase *ssa.CallCommon:\n\t\t\t// Call on an value or interface value.\n\n\t\t\t// Get the real defer struct type and cast to it.\n\t\t\tvalueTypes := []llvm.Type{b.uintptrType, b.dataPtrType}\n\n\t\t\tif !callback.IsInvoke() {\n\t\t\t\t//Expect funcValue to be passed through the deferred call.\n\t\t\t\tvalueTypes = append(valueTypes, b.getFuncType(callback.Signature()))\n\t\t\t} else {\n\t\t\t\t//Expect typecode\n\t\t\t\tvalueTypes = append(valueTypes, b.dataPtrType, b.dataPtrType)\n\t\t\t}\n\n\t\t\tfor _, arg := range callback.Args {\n\t\t\t\tvalueTypes = append(valueTypes, b.getLLVMType(arg.Type()))\n\t\t\t}\n\n\t\t\t// Extract the params from the struct (including receiver).\n\t\t\tforwardParams := []llvm.Value{}\n\t\t\tzero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)\n\t\t\tdeferredCallType := b.ctx.StructType(valueTypes, false)\n\t\t\tfor i := 2; i < len(valueTypes); i++ {\n\t\t\t\tgep := b.CreateInBoundsGEP(deferredCallType, deferData, []llvm.Value{zero, llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false)}, \"gep\")\n\t\t\t\tforwardParam := b.CreateLoad(valueTypes[i], gep, \"param\")\n\t\t\t\tforwardParams = append(forwardParams, forwardParam)\n\t\t\t}\n\n\t\t\tvar fnPtr llvm.Value\n\t\t\tvar fnType llvm.Type\n\n\t\t\tif !callback.IsInvoke() {\n\t\t\t\t// Isolate the func value.\n\t\t\t\tfuncValue := forwardParams[0]\n\t\t\t\tforwardParams = forwardParams[1:]\n\n\t\t\t\t//Get function pointer and context\n\t\t\t\tvar context llvm.Value\n\t\t\t\tfnPtr, context = b.decodeFuncValue(funcValue)\n\t\t\t\tfnType = b.getLLVMFunctionType(callback.Signature())\n\n\t\t\t\t//Pass context\n\t\t\t\tforwardParams = append(forwardParams, context)\n\t\t\t} else {\n\t\t\t\t// Move typecode from the start to the end of the list of\n\t\t\t\t// parameters.\n\t\t\t\tforwardParams = append(forwardParams[1:], forwardParams[0])\n\t\t\t\tfnPtr = b.getInvokeFunction(callback)\n\t\t\t\tfnType = fnPtr.GlobalValueType()\n\n\t\t\t\t// Add the context parameter. An interface call cannot also be a\n\t\t\t\t// closure but we have to supply the parameter anyway for platforms\n\t\t\t\t// with a strict calling convention.\n\t\t\t\tforwardParams = append(forwardParams, llvm.Undef(b.dataPtrType))\n\t\t\t}\n\n\t\t\tb.createCall(fnType, fnPtr, forwardParams, \"\")\n\n\t\tcase *ssa.Function:\n\t\t\t// Direct call.\n\n\t\t\t// Get the real defer struct type and cast to it.\n\t\t\tvalueTypes := []llvm.Type{b.uintptrType, b.dataPtrType}\n\t\t\tfor _, param := range getParams(callback.Signature) {\n\t\t\t\tvalueTypes = append(valueTypes, b.getLLVMType(param.Type()))\n\t\t\t}\n\t\t\tdeferredCallType := b.ctx.StructType(valueTypes, false)\n\n\t\t\t// Extract the params from the struct.\n\t\t\tforwardParams := []llvm.Value{}\n\t\t\tzero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)\n\t\t\tfor i := range getParams(callback.Signature) {\n\t\t\t\tgep := b.CreateInBoundsGEP(deferredCallType, deferData, []llvm.Value{zero, llvm.ConstInt(b.ctx.Int32Type(), uint64(i+2), false)}, \"gep\")\n\t\t\t\tforwardParam := b.CreateLoad(valueTypes[i+2], gep, \"param\")\n\t\t\t\tforwardParams = append(forwardParams, forwardParam)\n\t\t\t}\n\n\t\t\t// Plain TinyGo functions add some extra parameters to implement async functionality and function receivers.\n\t\t\t// These parameters should not be supplied when calling into an external C/ASM function.\n\t\t\tif !b.getFunctionInfo(callback).exported {\n\t\t\t\t// Add the context parameter. We know it is ignored by the receiving\n\t\t\t\t// function, but we have to pass one anyway.\n\t\t\t\tforwardParams = append(forwardParams, llvm.Undef(b.dataPtrType))\n\t\t\t}\n\n\t\t\t// Call real function.\n\t\t\tfnType, fn := b.getFunction(callback)\n\t\t\tb.createInvoke(fnType, fn, forwardParams, \"\")\n\n\t\tcase *ssa.MakeClosure:\n\t\t\t// Get the real defer struct type and cast to it.\n\t\t\tfn := callback.Fn.(*ssa.Function)\n\t\t\tvalueTypes := []llvm.Type{b.uintptrType, b.dataPtrType}\n\t\t\tparams := fn.Signature.Params()\n\t\t\tfor i := 0; i < params.Len(); i++ {\n\t\t\t\tvalueTypes = append(valueTypes, b.getLLVMType(params.At(i).Type()))\n\t\t\t}\n\t\t\tvalueTypes = append(valueTypes, b.dataPtrType) // closure\n\t\t\tdeferredCallType := b.ctx.StructType(valueTypes, false)\n\n\t\t\t// Extract the params from the struct.\n\t\t\tforwardParams := []llvm.Value{}\n\t\t\tzero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)\n\t\t\tfor i := 2; i < len(valueTypes); i++ {\n\t\t\t\tgep := b.CreateInBoundsGEP(deferredCallType, deferData, []llvm.Value{zero, llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false)}, \"\")\n\t\t\t\tforwardParam := b.CreateLoad(valueTypes[i], gep, \"param\")\n\t\t\t\tforwardParams = append(forwardParams, forwardParam)\n\t\t\t}\n\n\t\t\t// Call deferred function.\n\t\t\tfnType, llvmFn := b.getFunction(fn)\n\t\t\tb.createCall(fnType, llvmFn, forwardParams, \"\")\n\t\tcase *ssa.Builtin:\n\t\t\tdb := b.deferBuiltinFuncs[callback]\n\n\t\t\t//Get parameter types\n\t\t\tvalueTypes := []llvm.Type{b.uintptrType, b.dataPtrType}\n\n\t\t\t//Get signature from call results\n\t\t\tparams := callback.Type().Underlying().(*types.Signature).Params()\n\t\t\tfor i := 0; i < params.Len(); i++ {\n\t\t\t\tvalueTypes = append(valueTypes, b.getLLVMType(params.At(i).Type()))\n\t\t\t}\n\n\t\t\tdeferredCallType := b.ctx.StructType(valueTypes, false)\n\n\t\t\t// Extract the params from the struct.\n\t\t\tvar argValues []llvm.Value\n\t\t\tzero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)\n\t\t\tfor i := 0; i < params.Len(); i++ {\n\t\t\t\tgep := b.CreateInBoundsGEP(deferredCallType, deferData, []llvm.Value{zero, llvm.ConstInt(b.ctx.Int32Type(), uint64(i+2), false)}, \"gep\")\n\t\t\t\tforwardParam := b.CreateLoad(valueTypes[i+2], gep, \"param\")\n\t\t\t\targValues = append(argValues, forwardParam)\n\t\t\t}\n\n\t\t\t_, err := b.createBuiltin(db.argTypes, argValues, db.callName, db.pos)\n\t\t\tif err != nil {\n\t\t\t\tb.diagnostics = append(b.diagnostics, err)\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown deferred function type\")\n\t\t}\n\n\t\t// Branch back to the start of the loop.\n\t\tb.CreateBr(loophead)\n\t}\n\n\t// Create default unreachable block:\n\t//     default:\n\t//         unreachable\n\t//     }\n\tb.SetInsertPointAtEnd(unreachable)\n\tb.CreateUnreachable()\n\n\t// End of loop.\n\tb.SetInsertPointAtEnd(end)\n}\n"
  },
  {
    "path": "compiler/errors.go",
    "content": "package compiler\n\n// This file contains some utility functions related to error handling.\n\nimport (\n\t\"go/token\"\n\t\"go/types\"\n\t\"path/filepath\"\n\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// makeError makes it easy to create an error from a token.Pos with a message.\nfunc (c *compilerContext) makeError(pos token.Pos, msg string) types.Error {\n\treturn types.Error{\n\t\tFset: c.program.Fset,\n\t\tPos:  pos,\n\t\tMsg:  msg,\n\t}\n}\n\n// addError adds a new compiler diagnostic with the given location and message.\nfunc (c *compilerContext) addError(pos token.Pos, msg string) {\n\tc.diagnostics = append(c.diagnostics, c.makeError(pos, msg))\n}\n\n// getPosition returns the position information for the given value, as far as\n// it is available.\nfunc getPosition(val llvm.Value) token.Position {\n\tif !val.IsAInstruction().IsNil() {\n\t\tloc := val.InstructionDebugLoc()\n\t\tif loc.IsNil() {\n\t\t\treturn token.Position{}\n\t\t}\n\t\tfile := loc.LocationScope().ScopeFile()\n\t\treturn token.Position{\n\t\t\tFilename: filepath.Join(file.FileDirectory(), file.FileFilename()),\n\t\t\tLine:     int(loc.LocationLine()),\n\t\t\tColumn:   int(loc.LocationColumn()),\n\t\t}\n\t} else if !val.IsAFunction().IsNil() {\n\t\tloc := val.Subprogram()\n\t\tif loc.IsNil() {\n\t\t\treturn token.Position{}\n\t\t}\n\t\tfile := loc.ScopeFile()\n\t\treturn token.Position{\n\t\t\tFilename: filepath.Join(file.FileDirectory(), file.FileFilename()),\n\t\t\tLine:     int(loc.SubprogramLine()),\n\t\t}\n\t} else {\n\t\treturn token.Position{}\n\t}\n}\n"
  },
  {
    "path": "compiler/func.go",
    "content": "package compiler\n\n// This file implements function values and closures. It may need some lowering\n// in a later step, see func-lowering.go.\n\nimport (\n\t\"go/types\"\n\n\t\"golang.org/x/tools/go/ssa\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// createFuncValue creates a function value from a raw function pointer with no\n// context.\nfunc (b *builder) createFuncValue(funcPtr, context llvm.Value, sig *types.Signature) llvm.Value {\n\t// Closure is: {context, function pointer}\n\tfuncValueType := b.getFuncType(sig)\n\tfuncValue := llvm.Undef(funcValueType)\n\tfuncValue = b.CreateInsertValue(funcValue, context, 0, \"\")\n\tfuncValue = b.CreateInsertValue(funcValue, funcPtr, 1, \"\")\n\treturn funcValue\n}\n\n// extractFuncScalar returns some scalar that can be used in comparisons. It is\n// a cheap operation.\nfunc (b *builder) extractFuncScalar(funcValue llvm.Value) llvm.Value {\n\treturn b.CreateExtractValue(funcValue, 1, \"\")\n}\n\n// extractFuncContext extracts the context pointer from this function value. It\n// is a cheap operation.\nfunc (b *builder) extractFuncContext(funcValue llvm.Value) llvm.Value {\n\treturn b.CreateExtractValue(funcValue, 0, \"\")\n}\n\n// decodeFuncValue extracts the context and the function pointer from this func\n// value.\nfunc (b *builder) decodeFuncValue(funcValue llvm.Value) (funcPtr, context llvm.Value) {\n\tcontext = b.CreateExtractValue(funcValue, 0, \"\")\n\tfuncPtr = b.CreateExtractValue(funcValue, 1, \"\")\n\treturn\n}\n\n// getFuncType returns the type of a func value given a signature.\nfunc (c *compilerContext) getFuncType(typ *types.Signature) llvm.Type {\n\treturn c.ctx.StructType([]llvm.Type{c.dataPtrType, c.funcPtrType}, false)\n}\n\n// getLLVMFunctionType returns a LLVM function type for a given signature.\nfunc (c *compilerContext) getLLVMFunctionType(typ *types.Signature) llvm.Type {\n\t// Get the return type.\n\tvar returnType llvm.Type\n\tswitch typ.Results().Len() {\n\tcase 0:\n\t\t// No return values.\n\t\treturnType = c.ctx.VoidType()\n\tcase 1:\n\t\t// Just one return value.\n\t\treturnType = c.getLLVMType(typ.Results().At(0).Type())\n\tdefault:\n\t\t// Multiple return values. Put them together in a struct.\n\t\t// This appears to be the common way to handle multiple return values in\n\t\t// LLVM.\n\t\tmembers := make([]llvm.Type, typ.Results().Len())\n\t\tfor i := 0; i < typ.Results().Len(); i++ {\n\t\t\tmembers[i] = c.getLLVMType(typ.Results().At(i).Type())\n\t\t}\n\t\treturnType = c.ctx.StructType(members, false)\n\t}\n\n\t// Get the parameter types.\n\tvar paramTypes []llvm.Type\n\tif typ.Recv() != nil {\n\t\trecv := c.getLLVMType(typ.Recv().Type())\n\t\tif recv.StructName() == \"runtime._interface\" {\n\t\t\t// This is a call on an interface, not a concrete type.\n\t\t\t// The receiver is not an interface, but a i8* type.\n\t\t\trecv = c.dataPtrType\n\t\t}\n\t\tfor _, info := range c.expandFormalParamType(recv, \"\", nil) {\n\t\t\tparamTypes = append(paramTypes, info.llvmType)\n\t\t}\n\t}\n\tfor i := 0; i < typ.Params().Len(); i++ {\n\t\tsubType := c.getLLVMType(typ.Params().At(i).Type())\n\t\tfor _, info := range c.expandFormalParamType(subType, \"\", nil) {\n\t\t\tparamTypes = append(paramTypes, info.llvmType)\n\t\t}\n\t}\n\t// All functions take these parameters at the end.\n\tparamTypes = append(paramTypes, c.dataPtrType) // context\n\n\t// Make a func type out of the signature.\n\treturn llvm.FunctionType(returnType, paramTypes, false)\n}\n\n// parseMakeClosure makes a function value (with context) from the given\n// closure expression.\nfunc (b *builder) parseMakeClosure(expr *ssa.MakeClosure) (llvm.Value, error) {\n\tif len(expr.Bindings) == 0 {\n\t\tpanic(\"unexpected: MakeClosure without bound variables\")\n\t}\n\tf := expr.Fn.(*ssa.Function)\n\n\t// Collect all bound variables.\n\tboundVars := make([]llvm.Value, len(expr.Bindings))\n\tfor i, binding := range expr.Bindings {\n\t\t// The context stores the bound variables.\n\t\tllvmBoundVar := b.getValue(binding, getPos(expr))\n\t\tboundVars[i] = llvmBoundVar\n\t}\n\n\t// Store the bound variables in a single object, allocating it on the heap\n\t// if necessary.\n\tcontext := b.emitPointerPack(boundVars)\n\n\t// Create the closure.\n\t_, fn := b.getFunction(f)\n\treturn b.createFuncValue(fn, context, f.Signature), nil\n}\n"
  },
  {
    "path": "compiler/gc.go",
    "content": "package compiler\n\n// This file provides IR transformations necessary for precise and portable\n// garbage collectors.\n\nimport (\n\t\"go/token\"\n\n\t\"golang.org/x/tools/go/ssa\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// trackExpr inserts pointer tracking intrinsics for the GC if the expression is\n// one of the expressions that need this.\nfunc (b *builder) trackExpr(expr ssa.Value, value llvm.Value) {\n\t// There are uses of this expression, Make sure the pointers\n\t// are tracked during GC.\n\tswitch expr := expr.(type) {\n\tcase *ssa.Alloc, *ssa.MakeChan, *ssa.MakeMap:\n\t\t// These values are always of pointer type in IR.\n\t\tb.trackPointer(value)\n\tcase *ssa.Call, *ssa.Convert, *ssa.MakeClosure, *ssa.MakeInterface, *ssa.MakeSlice, *ssa.Next:\n\t\tif !value.IsNil() {\n\t\t\tb.trackValue(value)\n\t\t}\n\tcase *ssa.Select:\n\t\tif alloca, ok := b.selectRecvBuf[expr]; ok {\n\t\t\tif alloca.IsAUndefValue().IsNil() {\n\t\t\t\tb.trackPointer(alloca)\n\t\t\t}\n\t\t}\n\tcase *ssa.UnOp:\n\t\tswitch expr.Op {\n\t\tcase token.MUL:\n\t\t\t// Pointer dereference.\n\t\t\tb.trackValue(value)\n\t\tcase token.ARROW:\n\t\t\t// Channel receive operator.\n\t\t\t// It's not necessary to look at commaOk here, because in that\n\t\t\t// case it's just an aggregate and trackValue will extract the\n\t\t\t// pointer in there (if there is one).\n\t\t\tb.trackValue(value)\n\t\t}\n\tcase *ssa.BinOp:\n\t\tswitch expr.Op {\n\t\tcase token.ADD:\n\t\t\t// String concatenation.\n\t\t\tb.trackValue(value)\n\t\t}\n\t}\n}\n\n// trackValue locates pointers in a value (possibly an aggregate) and tracks the\n// individual pointers\nfunc (b *builder) trackValue(value llvm.Value) {\n\ttyp := value.Type()\n\tswitch typ.TypeKind() {\n\tcase llvm.PointerTypeKind:\n\t\tb.trackPointer(value)\n\tcase llvm.StructTypeKind:\n\t\tif !typeHasPointers(typ) {\n\t\t\treturn\n\t\t}\n\t\tnumElements := typ.StructElementTypesCount()\n\t\tfor i := 0; i < numElements; i++ {\n\t\t\tsubValue := b.CreateExtractValue(value, i, \"\")\n\t\t\tb.trackValue(subValue)\n\t\t}\n\tcase llvm.ArrayTypeKind:\n\t\tif !typeHasPointers(typ) {\n\t\t\treturn\n\t\t}\n\t\tnumElements := typ.ArrayLength()\n\t\tfor i := 0; i < numElements; i++ {\n\t\t\tsubValue := b.CreateExtractValue(value, i, \"\")\n\t\t\tb.trackValue(subValue)\n\t\t}\n\t}\n}\n\n// trackPointer creates a call to runtime.trackPointer, bitcasting the pointer\n// first if needed. The input value must be of LLVM pointer type.\nfunc (b *builder) trackPointer(value llvm.Value) {\n\tb.createRuntimeCall(\"trackPointer\", []llvm.Value{value, b.stackChainAlloca}, \"\")\n}\n\n// typeHasPointers returns whether this type is a pointer or contains pointers.\n// If the type is an aggregate type, it will check whether there is a pointer\n// inside.\nfunc typeHasPointers(t llvm.Type) bool {\n\tswitch t.TypeKind() {\n\tcase llvm.PointerTypeKind:\n\t\treturn true\n\tcase llvm.StructTypeKind:\n\t\tfor _, subType := range t.StructElementTypes() {\n\t\t\tif typeHasPointers(subType) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t\treturn false\n\tcase llvm.ArrayTypeKind:\n\t\tif typeHasPointers(t.ElementType()) {\n\t\t\treturn true\n\t\t}\n\t\treturn false\n\tdefault:\n\t\treturn false\n\t}\n}\n"
  },
  {
    "path": "compiler/goroutine.go",
    "content": "package compiler\n\n// This file implements the 'go' keyword to start a new goroutine. See\n// goroutine-lowering.go for more details.\n\nimport (\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"github.com/tinygo-org/tinygo/compiler/llvmutil\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// createGo emits code to start a new goroutine.\nfunc (b *builder) createGo(instr *ssa.Go) {\n\tif builtin, ok := instr.Call.Value.(*ssa.Builtin); ok {\n\t\t// We cheat. None of the builtins do any long or blocking operation, so\n\t\t// we might as well run these builtins right away without the program\n\t\t// noticing the difference.\n\t\t// Possible exceptions:\n\t\t//   - copy: this is a possibly long operation, but not a blocking\n\t\t//     operation. Semantically it makes no difference to run it right\n\t\t//     away (not in a goroutine). However, in practice it makes no sense\n\t\t//     to run copy in a goroutine as there is no way to (safely) know\n\t\t//     when it is finished.\n\t\t//   - panic: the error message would appear in the parent goroutine.\n\t\t//     But because `go panic(\"err\")` would halt the program anyway\n\t\t//     (there is no recover), panicking right away would give the same\n\t\t//     behavior as creating a goroutine, switching the scheduler to that\n\t\t//     goroutine, and panicking there. So this optimization seems\n\t\t//     correct.\n\t\t//   - recover: because it runs in a new goroutine, it is never a\n\t\t//     deferred function. Thus this is a no-op.\n\t\tif builtin.Name() == \"recover\" {\n\t\t\t// This is a no-op, even in a deferred function:\n\t\t\t//   go recover()\n\t\t\treturn\n\t\t}\n\t\tvar argTypes []types.Type\n\t\tvar argValues []llvm.Value\n\t\tfor _, arg := range instr.Call.Args {\n\t\t\targTypes = append(argTypes, arg.Type())\n\t\t\targValues = append(argValues, b.getValue(arg, getPos(instr)))\n\t\t}\n\t\tb.createBuiltin(argTypes, argValues, builtin.Name(), instr.Pos())\n\t\treturn\n\t}\n\n\t// Get all function parameters to pass to the goroutine.\n\tvar params []llvm.Value\n\tfor _, param := range instr.Call.Args {\n\t\tparams = append(params, b.expandFormalParam(b.getValue(param, getPos(instr)))...)\n\t}\n\n\tvar prefix string\n\tvar funcPtr llvm.Value\n\tvar funcType llvm.Type\n\thasContext := false\n\tif callee := instr.Call.StaticCallee(); callee != nil {\n\t\t// Static callee is known. This makes it easier to start a new\n\t\t// goroutine.\n\t\tvar context llvm.Value\n\t\tswitch value := instr.Call.Value.(type) {\n\t\tcase *ssa.Function:\n\t\t\t// Goroutine call is regular function call. No context is necessary.\n\t\tcase *ssa.MakeClosure:\n\t\t\t// A goroutine call on a func value, but the callee is trivial to find. For\n\t\t\t// example: immediately applied functions.\n\t\t\tfuncValue := b.getValue(value, getPos(instr))\n\t\t\tcontext = b.extractFuncContext(funcValue)\n\t\tdefault:\n\t\t\tpanic(\"StaticCallee returned an unexpected value\")\n\t\t}\n\t\tif !context.IsNil() {\n\t\t\tparams = append(params, context) // context parameter\n\t\t\thasContext = true\n\t\t}\n\t\tfuncType, funcPtr = b.getFunction(callee)\n\t} else if instr.Call.IsInvoke() {\n\t\t// This is a method call on an interface value.\n\t\titf := b.getValue(instr.Call.Value, getPos(instr))\n\t\titfTypeCode := b.CreateExtractValue(itf, 0, \"\")\n\t\titfValue := b.CreateExtractValue(itf, 1, \"\")\n\t\tfuncPtr = b.getInvokeFunction(&instr.Call)\n\t\tfuncType = funcPtr.GlobalValueType()\n\t\tparams = append([]llvm.Value{itfValue}, params...) // start with receiver\n\t\tparams = append(params, itfTypeCode)               // end with typecode\n\t} else {\n\t\t// This is a function pointer.\n\t\t// At the moment, two extra params are passed to the newly started\n\t\t// goroutine:\n\t\t//   * The function context, for closures.\n\t\t//   * The function pointer (for tasks).\n\t\tvar context llvm.Value\n\t\tfuncPtr, context = b.decodeFuncValue(b.getValue(instr.Call.Value, getPos(instr)))\n\t\tfuncType = b.getLLVMFunctionType(instr.Call.Value.Type().Underlying().(*types.Signature))\n\t\tparams = append(params, context, funcPtr)\n\t\thasContext = true\n\t\tprefix = b.fn.RelString(nil)\n\t}\n\n\tparamBundle := b.emitPointerPack(params)\n\tvar stackSize llvm.Value\n\tcallee := b.createGoroutineStartWrapper(funcType, funcPtr, prefix, hasContext, false, instr.Pos())\n\tif b.AutomaticStackSize {\n\t\t// The stack size is not known until after linking. Call a dummy\n\t\t// function that will be replaced with a load from a special ELF\n\t\t// section that contains the stack size (and is modified after\n\t\t// linking).\n\t\tstackSizeFnType, stackSizeFn := b.getFunction(b.program.ImportedPackage(\"internal/task\").Members[\"getGoroutineStackSize\"].(*ssa.Function))\n\t\tstackSize = b.createCall(stackSizeFnType, stackSizeFn, []llvm.Value{callee, llvm.Undef(b.dataPtrType)}, \"stacksize\")\n\t} else {\n\t\t// The stack size is fixed at compile time. By emitting it here as a\n\t\t// constant, it can be optimized.\n\t\tif (b.Scheduler == \"tasks\" || b.Scheduler == \"asyncify\") && b.DefaultStackSize == 0 {\n\t\t\tb.addError(instr.Pos(), \"default stack size for goroutines is not set\")\n\t\t}\n\t\tstackSize = llvm.ConstInt(b.uintptrType, b.DefaultStackSize, false)\n\t}\n\tfnType, start := b.getFunction(b.program.ImportedPackage(\"internal/task\").Members[\"start\"].(*ssa.Function))\n\tb.createCall(fnType, start, []llvm.Value{callee, paramBundle, stackSize, llvm.Undef(b.dataPtrType)}, \"\")\n}\n\n// Create an exported wrapper function for functions with the //go:wasmexport\n// pragma. This wrapper function is quite complex when the scheduler is enabled:\n// it needs to start a new goroutine each time the exported function is called.\nfunc (b *builder) createWasmExport() {\n\tpos := b.info.wasmExportPos\n\tif b.info.exported {\n\t\t// //export really shouldn't be used anymore when //go:wasmexport is\n\t\t// available, because //go:wasmexport is much better defined.\n\t\tb.addError(pos, \"cannot use //export and //go:wasmexport at the same time\")\n\t\treturn\n\t}\n\n\tconst suffix = \"#wasmexport\"\n\n\t// Declare the exported function.\n\tparamTypes := b.llvmFnType.ParamTypes()\n\texportedFnType := llvm.FunctionType(b.llvmFnType.ReturnType(), paramTypes[:len(paramTypes)-1], false)\n\texportedFn := llvm.AddFunction(b.mod, b.fn.RelString(nil)+suffix, exportedFnType)\n\tb.addStandardAttributes(exportedFn)\n\tllvmutil.AppendToGlobal(b.mod, \"llvm.used\", exportedFn)\n\texportedFn.AddFunctionAttr(b.ctx.CreateStringAttribute(\"wasm-export-name\", b.info.wasmExport))\n\n\t// Create a builder for this wrapper function.\n\tbuilder := newBuilder(b.compilerContext, b.ctx.NewBuilder(), b.fn)\n\tdefer builder.Dispose()\n\n\t// Define this function as a separate function in DWARF\n\tif b.Debug {\n\t\tif b.fn.Syntax() != nil {\n\t\t\t// Create debug info file if needed.\n\t\t\tpos := b.program.Fset.Position(pos)\n\t\t\tbuilder.difunc = builder.attachDebugInfoRaw(b.fn, exportedFn, suffix, pos.Filename, pos.Line)\n\t\t}\n\t\tbuilder.setDebugLocation(pos)\n\t}\n\n\t// Create a single basic block inside of it.\n\tbb := llvm.AddBasicBlock(exportedFn, \"entry\")\n\tbuilder.SetInsertPointAtEnd(bb)\n\n\t// Insert an assertion to make sure this //go:wasmexport function is not\n\t// called at a time when it is not allowed (for example, before the runtime\n\t// is initialized).\n\tbuilder.createRuntimeCall(\"wasmExportCheckRun\", nil, \"\")\n\n\tif b.Scheduler == \"none\" {\n\t\t// When the scheduler has been disabled, this is really trivial: just\n\t\t// call the function.\n\t\tparams := exportedFn.Params()\n\t\tparams = append(params, llvm.ConstNull(b.dataPtrType)) // context parameter\n\t\tretval := builder.CreateCall(b.llvmFnType, b.llvmFn, params, \"\")\n\t\tif b.fn.Signature.Results() == nil {\n\t\t\tbuilder.CreateRetVoid()\n\t\t} else {\n\t\t\tbuilder.CreateRet(retval)\n\t\t}\n\n\t} else {\n\t\t// The scheduler is enabled, so we need to start a new goroutine, wait\n\t\t// for it to complete, and read the result value.\n\n\t\t// Build a function that looks like this:\n\t\t//\n\t\t//   func foo#wasmexport(param0, param1, ..., paramN) {\n\t\t//       var state *stateStruct\n\t\t//\n\t\t//       // 'done' must be explicitly initialized ('state' is not zeroed)\n\t\t//       state.done = false\n\t\t//\n\t\t//       // store the parameters in the state object\n\t\t//       state.param0 = param0\n\t\t//       state.param1 = param1\n\t\t//       ...\n\t\t//       state.paramN = paramN\n\t\t//\n\t\t//       // create a goroutine and push it to the runqueue\n\t\t//       task.start(uintptr(gowrapper), &state)\n\t\t//\n\t\t//       // run the scheduler\n\t\t//       runtime.wasmExportRun(&state.done)\n\t\t//\n\t\t//       // if there is a return value, load it and return\n\t\t//       return state.result\n\t\t//   }\n\n\t\thasReturn := b.fn.Signature.Results() != nil\n\n\t\t// Build the state struct type.\n\t\t// It stores the function parameters, the 'done' flag, and reserves\n\t\t// space for a return value if needed.\n\t\tstateFields := exportedFnType.ParamTypes()\n\t\tnumParams := len(stateFields)\n\t\tstateFields = append(stateFields, b.ctx.Int1Type()) // 'done' field\n\t\tif hasReturn {\n\t\t\tstateFields = append(stateFields, b.llvmFnType.ReturnType())\n\t\t}\n\t\tstateStruct := b.ctx.StructType(stateFields, false)\n\n\t\t// Allocate the state struct on the stack.\n\t\tstatePtr := builder.CreateAlloca(stateStruct, \"status\")\n\n\t\t// Initialize the 'done' field.\n\t\tdoneGEP := builder.CreateInBoundsGEP(stateStruct, statePtr, []llvm.Value{\n\t\t\tllvm.ConstInt(b.ctx.Int32Type(), 0, false),\n\t\t\tllvm.ConstInt(b.ctx.Int32Type(), uint64(numParams), false),\n\t\t}, \"done.gep\")\n\t\tbuilder.CreateStore(llvm.ConstNull(b.ctx.Int1Type()), doneGEP)\n\n\t\t// Store all parameters in the state object.\n\t\tfor i, param := range exportedFn.Params() {\n\t\t\tgep := builder.CreateInBoundsGEP(stateStruct, statePtr, []llvm.Value{\n\t\t\t\tllvm.ConstInt(b.ctx.Int32Type(), 0, false),\n\t\t\t\tllvm.ConstInt(b.ctx.Int32Type(), uint64(i), false),\n\t\t\t}, \"\")\n\t\t\tbuilder.CreateStore(param, gep)\n\t\t}\n\n\t\t// Create a new goroutine and add it to the runqueue.\n\t\twrapper := b.createGoroutineStartWrapper(b.llvmFnType, b.llvmFn, \"\", false, true, pos)\n\t\tstackSize := llvm.ConstInt(b.uintptrType, b.DefaultStackSize, false)\n\t\ttaskStartFnType, taskStartFn := builder.getFunction(b.program.ImportedPackage(\"internal/task\").Members[\"start\"].(*ssa.Function))\n\t\tbuilder.createCall(taskStartFnType, taskStartFn, []llvm.Value{wrapper, statePtr, stackSize, llvm.Undef(b.dataPtrType)}, \"\")\n\n\t\t// Run the scheduler.\n\t\tbuilder.createRuntimeCall(\"wasmExportRun\", []llvm.Value{doneGEP}, \"\")\n\n\t\t// Read the return value (if any) and return to the caller of the\n\t\t// //go:wasmexport function.\n\t\tif hasReturn {\n\t\t\tgep := builder.CreateInBoundsGEP(stateStruct, statePtr, []llvm.Value{\n\t\t\t\tllvm.ConstInt(b.ctx.Int32Type(), 0, false),\n\t\t\t\tllvm.ConstInt(b.ctx.Int32Type(), uint64(numParams)+1, false),\n\t\t\t}, \"\")\n\t\t\tretval := builder.CreateLoad(b.llvmFnType.ReturnType(), gep, \"retval\")\n\t\t\tbuilder.CreateRet(retval)\n\t\t} else {\n\t\t\tbuilder.CreateRetVoid()\n\t\t}\n\t}\n}\n\n// createGoroutineStartWrapper creates a wrapper for the task-based\n// implementation of goroutines. For example, to call a function like this:\n//\n//\tfunc add(x, y int) int { ... }\n//\n// It creates a wrapper like this:\n//\n//\tfunc add$gowrapper(ptr *unsafe.Pointer) {\n//\t    args := (*struct{\n//\t        x, y int\n//\t    })(ptr)\n//\t    add(args.x, args.y)\n//\t}\n//\n// This is useful because the task-based goroutine start implementation only\n// allows a single (pointer) argument to the newly started goroutine. Also, it\n// ignores the return value because newly started goroutines do not have a\n// return value.\n//\n// The hasContext parameter indicates whether the context parameter (the second\n// to last parameter of the function) is used for this wrapper. If hasContext is\n// false, the parameter bundle is assumed to have no context parameter and undef\n// is passed instead.\nfunc (c *compilerContext) createGoroutineStartWrapper(fnType llvm.Type, fn llvm.Value, prefix string, hasContext, isWasmExport bool, pos token.Pos) llvm.Value {\n\tvar wrapper llvm.Value\n\n\tb := &builder{\n\t\tcompilerContext: c,\n\t\tBuilder:         c.ctx.NewBuilder(),\n\t}\n\tdefer b.Dispose()\n\n\tvar deadlock llvm.Value\n\tvar deadlockType llvm.Type\n\tif c.Scheduler == \"asyncify\" {\n\t\tdeadlockType, deadlock = c.getFunction(c.program.ImportedPackage(\"runtime\").Members[\"deadlock\"].(*ssa.Function))\n\t}\n\n\tif !fn.IsAFunction().IsNil() {\n\t\t// See whether this wrapper has already been created. If so, return it.\n\t\tname := fn.Name()\n\t\twrapperName := name + \"$gowrapper\"\n\t\tif isWasmExport {\n\t\t\twrapperName += \"-wasmexport\"\n\t\t}\n\t\twrapper = c.mod.NamedFunction(wrapperName)\n\t\tif !wrapper.IsNil() {\n\t\t\treturn llvm.ConstPtrToInt(wrapper, c.uintptrType)\n\t\t}\n\n\t\t// Create the wrapper.\n\t\twrapperType := llvm.FunctionType(c.ctx.VoidType(), []llvm.Type{c.dataPtrType}, false)\n\t\twrapper = llvm.AddFunction(c.mod, wrapperName, wrapperType)\n\t\tc.addStandardAttributes(wrapper)\n\t\twrapper.SetLinkage(llvm.LinkOnceODRLinkage)\n\t\twrapper.SetUnnamedAddr(true)\n\t\twrapper.AddAttributeAtIndex(-1, c.ctx.CreateStringAttribute(\"tinygo-gowrapper\", name))\n\t\tentry := c.ctx.AddBasicBlock(wrapper, \"entry\")\n\t\tb.SetInsertPointAtEnd(entry)\n\n\t\tif c.Debug {\n\t\t\tpos := c.program.Fset.Position(pos)\n\t\t\tdiFuncType := c.dibuilder.CreateSubroutineType(llvm.DISubroutineType{\n\t\t\t\tFile:       c.getDIFile(pos.Filename),\n\t\t\t\tParameters: nil, // do not show parameters in debugger\n\t\t\t\tFlags:      0,   // ?\n\t\t\t})\n\t\t\tdifunc := c.dibuilder.CreateFunction(c.getDIFile(pos.Filename), llvm.DIFunction{\n\t\t\t\tName:         \"<goroutine wrapper>\",\n\t\t\t\tFile:         c.getDIFile(pos.Filename),\n\t\t\t\tLine:         pos.Line,\n\t\t\t\tType:         diFuncType,\n\t\t\t\tLocalToUnit:  true,\n\t\t\t\tIsDefinition: true,\n\t\t\t\tScopeLine:    0,\n\t\t\t\tFlags:        llvm.FlagPrototyped,\n\t\t\t\tOptimized:    true,\n\t\t\t})\n\t\t\twrapper.SetSubprogram(difunc)\n\t\t\tb.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), difunc, llvm.Metadata{})\n\t\t}\n\n\t\tif !isWasmExport {\n\t\t\t// Regular 'go' instruction.\n\n\t\t\t// Create the list of params for the call.\n\t\t\tparamTypes := fnType.ParamTypes()\n\t\t\tif !hasContext {\n\t\t\t\tparamTypes = paramTypes[:len(paramTypes)-1] // strip context parameter\n\t\t\t}\n\n\t\t\tparams := b.emitPointerUnpack(wrapper.Param(0), paramTypes)\n\t\t\tif !hasContext {\n\t\t\t\tparams = append(params, llvm.Undef(c.dataPtrType)) // add dummy context parameter\n\t\t\t}\n\n\t\t\t// Create the call.\n\t\t\tb.CreateCall(fnType, fn, params, \"\")\n\n\t\t\tif c.Scheduler == \"asyncify\" {\n\t\t\t\tb.CreateCall(deadlockType, deadlock, []llvm.Value{\n\t\t\t\t\tllvm.Undef(c.dataPtrType),\n\t\t\t\t}, \"\")\n\t\t\t}\n\t\t} else {\n\t\t\t// Goroutine started from a //go:wasmexport pragma.\n\t\t\t// The function looks like this:\n\t\t\t//\n\t\t\t//   func foo$gowrapper-wasmexport(state *stateStruct) {\n\t\t\t//       // load values\n\t\t\t//       param0 := state.params[0]\n\t\t\t//       param1 := state.params[1]\n\t\t\t//\n\t\t\t//       // call wrapped functions\n\t\t\t//       result := foo(param0, param1, ...)\n\t\t\t//\n\t\t\t//       // store result value (if there is any)\n\t\t\t//       state.result = result\n\t\t\t//\n\t\t\t//       // finish exported function\n\t\t\t//       state.done = true\n\t\t\t//       runtime.wasmExportExit()\n\t\t\t//   }\n\t\t\t//\n\t\t\t// The state object here looks like:\n\t\t\t//\n\t\t\t//   struct state {\n\t\t\t//       param0\n\t\t\t//       param1\n\t\t\t//       param* // etc\n\t\t\t//       done bool\n\t\t\t//       result returnType\n\t\t\t//   }\n\n\t\t\treturnType := fnType.ReturnType()\n\t\t\thasReturn := returnType != b.ctx.VoidType()\n\t\t\tstatePtr := wrapper.Param(0)\n\n\t\t\t// Create the state struct (it must match the type in createWasmExport).\n\t\t\tstateFields := fnType.ParamTypes()\n\t\t\tnumParams := len(stateFields) - 1\n\t\t\tstateFields = stateFields[:numParams:numParams]     // strip 'context' parameter\n\t\t\tstateFields = append(stateFields, c.ctx.Int1Type()) // 'done' bool\n\t\t\tif hasReturn {\n\t\t\t\tstateFields = append(stateFields, returnType)\n\t\t\t}\n\t\t\tstateStruct := b.ctx.StructType(stateFields, false)\n\n\t\t\t// Extract parameters from the state object, and call the function\n\t\t\t// that's being wrapped.\n\t\t\tvar callParams []llvm.Value\n\t\t\tfor i := 0; i < numParams; i++ {\n\t\t\t\tgep := b.CreateInBoundsGEP(stateStruct, statePtr, []llvm.Value{\n\t\t\t\t\tllvm.ConstInt(b.ctx.Int32Type(), 0, false),\n\t\t\t\t\tllvm.ConstInt(b.ctx.Int32Type(), uint64(i), false),\n\t\t\t\t}, \"\")\n\t\t\t\tparam := b.CreateLoad(stateFields[i], gep, \"\")\n\t\t\t\tcallParams = append(callParams, param)\n\t\t\t}\n\t\t\tcallParams = append(callParams, llvm.ConstNull(c.dataPtrType)) // add 'context' parameter\n\t\t\tresult := b.CreateCall(fnType, fn, callParams, \"\")\n\n\t\t\t// Store the return value back into the shared state.\n\t\t\t// Unlike regular goroutines, these special //go:wasmexport\n\t\t\t// goroutines can return a value.\n\t\t\tif hasReturn {\n\t\t\t\tgep := b.CreateInBoundsGEP(stateStruct, statePtr, []llvm.Value{\n\t\t\t\t\tllvm.ConstInt(c.ctx.Int32Type(), 0, false),\n\t\t\t\t\tllvm.ConstInt(c.ctx.Int32Type(), uint64(numParams)+1, false),\n\t\t\t\t}, \"result.ptr\")\n\t\t\t\tb.CreateStore(result, gep)\n\t\t\t}\n\n\t\t\t// Mark this function as having finished executing.\n\t\t\t// This is important so the runtime knows the exported function\n\t\t\t// didn't block.\n\t\t\tdoneGEP := b.CreateInBoundsGEP(stateStruct, statePtr, []llvm.Value{\n\t\t\t\tllvm.ConstInt(c.ctx.Int32Type(), 0, false),\n\t\t\t\tllvm.ConstInt(c.ctx.Int32Type(), uint64(numParams), false),\n\t\t\t}, \"done.gep\")\n\t\t\tb.CreateStore(llvm.ConstInt(b.ctx.Int1Type(), 1, false), doneGEP)\n\n\t\t\t// Call back into the runtime. This will exit the goroutine, switch\n\t\t\t// back to the scheduler, which will in turn return from the\n\t\t\t// //go:wasmexport function.\n\t\t\tb.createRuntimeCall(\"wasmExportExit\", nil, \"\")\n\t\t}\n\n\t} else {\n\t\t// For a function pointer like this:\n\t\t//\n\t\t//     var funcPtr func(x, y int) int\n\t\t//\n\t\t// A wrapper like the following is created:\n\t\t//\n\t\t//     func .gowrapper(ptr *unsafe.Pointer) {\n\t\t//         args := (*struct{\n\t\t//             x, y int\n\t\t//             fn   func(x, y int) int\n\t\t//         })(ptr)\n\t\t//         args.fn(x, y)\n\t\t//     }\n\t\t//\n\t\t// With a bit of luck, identical wrapper functions like these can be\n\t\t// merged into one.\n\n\t\t// Create the wrapper.\n\t\twrapperType := llvm.FunctionType(c.ctx.VoidType(), []llvm.Type{c.dataPtrType}, false)\n\t\twrapper = llvm.AddFunction(c.mod, prefix+\".gowrapper\", wrapperType)\n\t\tc.addStandardAttributes(wrapper)\n\t\twrapper.SetLinkage(llvm.LinkOnceODRLinkage)\n\t\twrapper.SetUnnamedAddr(true)\n\t\twrapper.AddAttributeAtIndex(-1, c.ctx.CreateStringAttribute(\"tinygo-gowrapper\", \"\"))\n\t\tentry := c.ctx.AddBasicBlock(wrapper, \"entry\")\n\t\tb.SetInsertPointAtEnd(entry)\n\n\t\tif c.Debug {\n\t\t\tpos := c.program.Fset.Position(pos)\n\t\t\tdiFuncType := c.dibuilder.CreateSubroutineType(llvm.DISubroutineType{\n\t\t\t\tFile:       c.getDIFile(pos.Filename),\n\t\t\t\tParameters: nil, // do not show parameters in debugger\n\t\t\t\tFlags:      0,   // ?\n\t\t\t})\n\t\t\tdifunc := c.dibuilder.CreateFunction(c.getDIFile(pos.Filename), llvm.DIFunction{\n\t\t\t\tName:         \"<goroutine wrapper>\",\n\t\t\t\tFile:         c.getDIFile(pos.Filename),\n\t\t\t\tLine:         pos.Line,\n\t\t\t\tType:         diFuncType,\n\t\t\t\tLocalToUnit:  true,\n\t\t\t\tIsDefinition: true,\n\t\t\t\tScopeLine:    0,\n\t\t\t\tFlags:        llvm.FlagPrototyped,\n\t\t\t\tOptimized:    true,\n\t\t\t})\n\t\t\twrapper.SetSubprogram(difunc)\n\t\t\tb.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), difunc, llvm.Metadata{})\n\t\t}\n\n\t\t// Get the list of parameters, with the extra parameters at the end.\n\t\tparamTypes := fnType.ParamTypes()\n\t\tparamTypes = append(paramTypes, fn.Type()) // the last element is the function pointer\n\t\tparams := b.emitPointerUnpack(wrapper.Param(0), paramTypes)\n\n\t\t// Get the function pointer.\n\t\tfnPtr := params[len(params)-1]\n\t\tparams = params[:len(params)-1]\n\n\t\t// Create the call.\n\t\tb.CreateCall(fnType, fnPtr, params, \"\")\n\n\t\tif c.Scheduler == \"asyncify\" {\n\t\t\tb.CreateCall(deadlockType, deadlock, []llvm.Value{\n\t\t\t\tllvm.Undef(c.dataPtrType),\n\t\t\t}, \"\")\n\t\t}\n\t}\n\n\tif c.Scheduler == \"asyncify\" {\n\t\t// The goroutine was terminated via deadlock.\n\t\tb.CreateUnreachable()\n\t} else {\n\t\t// Finish the function. Every basic block must end in a terminator, and\n\t\t// because goroutines never return a value we can simply return void.\n\t\tb.CreateRetVoid()\n\t}\n\n\t// Return a ptrtoint of the wrapper, not the function itself.\n\treturn llvm.ConstPtrToInt(wrapper, c.uintptrType)\n}\n"
  },
  {
    "path": "compiler/inlineasm.go",
    "content": "package compiler\n\n// This file implements inline asm support by calling special functions.\n\nimport (\n\t\"fmt\"\n\t\"go/constant\"\n\t\"go/token\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/ssa\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// This is a compiler builtin, which emits a piece of inline assembly with no\n// operands or return values. It is useful for trivial instructions, like wfi in\n// ARM or sleep in AVR.\n//\n//\tfunc Asm(asm string)\n//\n// The provided assembly must be a constant.\nfunc (b *builder) createInlineAsm(args []ssa.Value) (llvm.Value, error) {\n\t// Magic function: insert inline assembly instead of calling it.\n\tfnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{}, false)\n\tasm := constant.StringVal(args[0].(*ssa.Const).Value)\n\ttarget := llvm.InlineAsm(fnType, asm, \"\", true, false, 0, false)\n\treturn b.CreateCall(fnType, target, nil, \"\"), nil\n}\n\n// This is a compiler builtin, which allows assembly to be called in a flexible\n// way.\n//\n//\tfunc AsmFull(asm string, regs map[string]interface{}) uintptr\n//\n// The asm parameter must be a constant string. The regs parameter must be\n// provided immediately. For example:\n//\n//\tarm.AsmFull(\n//\t    \"str {value}, [{result}]\",\n//\t    map[string]interface{}{\n//\t        \"value\":  1,\n//\t        \"result\": uintptr(unsafe.Pointer(&dest)),\n//\t    })\nfunc (b *builder) createInlineAsmFull(instr *ssa.CallCommon) (llvm.Value, error) {\n\tasmString := constant.StringVal(instr.Args[0].(*ssa.Const).Value)\n\tregisters := map[string]llvm.Value{}\n\tif registerMap, ok := instr.Args[1].(*ssa.MakeMap); ok {\n\t\tfor _, r := range *registerMap.Referrers() {\n\t\t\tswitch r := r.(type) {\n\t\t\tcase *ssa.DebugRef:\n\t\t\t\t// ignore\n\t\t\tcase *ssa.MapUpdate:\n\t\t\t\tif r.Block() != registerMap.Block() {\n\t\t\t\t\treturn llvm.Value{}, b.makeError(instr.Pos(), \"register value map must be created in the same basic block\")\n\t\t\t\t}\n\t\t\t\tkey := constant.StringVal(r.Key.(*ssa.Const).Value)\n\t\t\t\tregisters[key] = b.getValue(r.Value.(*ssa.MakeInterface).X, getPos(instr))\n\t\t\tcase *ssa.Call:\n\t\t\t\tif r.Common() == instr {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn llvm.Value{}, b.makeError(instr.Pos(), \"don't know how to handle argument to inline assembly: \"+r.String())\n\t\t\t}\n\t\t}\n\t}\n\t// TODO: handle dollar signs in asm string\n\tregisterNumbers := map[string]int{}\n\tvar err error\n\targTypes := []llvm.Type{}\n\targs := []llvm.Value{}\n\tconstraints := []string{}\n\thasOutput := false\n\tasmString = regexp.MustCompile(`\\{\\}`).ReplaceAllStringFunc(asmString, func(s string) string {\n\t\thasOutput = true\n\t\treturn \"$0\"\n\t})\n\tif hasOutput {\n\t\tconstraints = append(constraints, \"=&r\")\n\t\tregisterNumbers[\"\"] = 0\n\t}\n\tasmString = regexp.MustCompile(`\\{[a-zA-Z]+\\}`).ReplaceAllStringFunc(asmString, func(s string) string {\n\t\t// TODO: skip strings like {r4} etc. that look like ARM push/pop\n\t\t// instructions.\n\t\tname := s[1 : len(s)-1]\n\t\tif _, ok := registers[name]; !ok {\n\t\t\tif err == nil {\n\t\t\t\terr = b.makeError(instr.Pos(), \"unknown register name: \"+name)\n\t\t\t}\n\t\t\treturn s\n\t\t}\n\t\tif _, ok := registerNumbers[name]; !ok {\n\t\t\tregisterNumbers[name] = len(registerNumbers)\n\t\t\targTypes = append(argTypes, registers[name].Type())\n\t\t\targs = append(args, registers[name])\n\t\t\tswitch registers[name].Type().TypeKind() {\n\t\t\tcase llvm.IntegerTypeKind:\n\t\t\t\tconstraints = append(constraints, \"r\")\n\t\t\tcase llvm.PointerTypeKind:\n\t\t\t\t// Memory references require a type starting with LLVM 14,\n\t\t\t\t// probably as a preparation for opaque pointers.\n\t\t\t\terr = b.makeError(instr.Pos(), \"support for pointer operands was dropped in TinyGo 0.23\")\n\t\t\t\treturn s\n\t\t\tdefault:\n\t\t\t\terr = b.makeError(instr.Pos(), \"unknown type in inline assembly for value: \"+name)\n\t\t\t\treturn s\n\t\t\t}\n\t\t}\n\t\treturn fmt.Sprintf(\"${%v}\", registerNumbers[name])\n\t})\n\tif err != nil {\n\t\treturn llvm.Value{}, err\n\t}\n\tvar outputType llvm.Type\n\tif hasOutput {\n\t\toutputType = b.uintptrType\n\t} else {\n\t\toutputType = b.ctx.VoidType()\n\t}\n\tfnType := llvm.FunctionType(outputType, argTypes, false)\n\ttarget := llvm.InlineAsm(fnType, asmString, strings.Join(constraints, \",\"), true, false, 0, false)\n\tresult := b.CreateCall(fnType, target, args, \"\")\n\tif hasOutput {\n\t\treturn result, nil\n\t} else {\n\t\t// Make sure we return something valid.\n\t\treturn llvm.ConstInt(b.uintptrType, 0, false), nil\n\t}\n}\n\n// This is a compiler builtin which emits an inline SVCall instruction. It can\n// be one of:\n//\n//\tfunc SVCall0(num uintptr) uintptr\n//\tfunc SVCall1(num uintptr, a1 interface{}) uintptr\n//\tfunc SVCall2(num uintptr, a1, a2 interface{}) uintptr\n//\tfunc SVCall3(num uintptr, a1, a2, a3 interface{}) uintptr\n//\tfunc SVCall4(num uintptr, a1, a2, a3, a4 interface{}) uintptr\n//\n// The num parameter must be a constant. All other parameters may be any scalar\n// value supported by LLVM inline assembly.\nfunc (b *builder) emitSVCall(args []ssa.Value, pos token.Pos) (llvm.Value, error) {\n\tnum, _ := constant.Uint64Val(args[0].(*ssa.Const).Value)\n\tllvmArgs := []llvm.Value{}\n\targTypes := []llvm.Type{}\n\tasm := \"svc #\" + strconv.FormatUint(num, 10)\n\tconstraints := \"={r0}\"\n\tfor i, arg := range args[1:] {\n\t\targ = arg.(*ssa.MakeInterface).X\n\t\tif i == 0 {\n\t\t\tconstraints += \",0\"\n\t\t} else {\n\t\t\tconstraints += \",{r\" + strconv.Itoa(i) + \"}\"\n\t\t}\n\t\tllvmValue := b.getValue(arg, pos)\n\t\tllvmArgs = append(llvmArgs, llvmValue)\n\t\targTypes = append(argTypes, llvmValue.Type())\n\t}\n\t// Implement the ARM calling convention by marking r1-r3 as\n\t// clobbered. r0 is used as an output register so doesn't have to be\n\t// marked as clobbered.\n\tconstraints += \",~{r1},~{r2},~{r3}\"\n\tfnType := llvm.FunctionType(b.uintptrType, argTypes, false)\n\ttarget := llvm.InlineAsm(fnType, asm, constraints, true, false, 0, false)\n\treturn b.CreateCall(fnType, target, llvmArgs, \"\"), nil\n}\n\n// This is a compiler builtin which emits an inline SVCall instruction. It can\n// be one of:\n//\n//\tfunc SVCall0(num uintptr) uintptr\n//\tfunc SVCall1(num uintptr, a1 interface{}) uintptr\n//\tfunc SVCall2(num uintptr, a1, a2 interface{}) uintptr\n//\tfunc SVCall3(num uintptr, a1, a2, a3 interface{}) uintptr\n//\tfunc SVCall4(num uintptr, a1, a2, a3, a4 interface{}) uintptr\n//\n// The num parameter must be a constant. All other parameters may be any scalar\n// value supported by LLVM inline assembly.\n// Same as emitSVCall but for AArch64\nfunc (b *builder) emitSV64Call(args []ssa.Value, pos token.Pos) (llvm.Value, error) {\n\tnum, _ := constant.Uint64Val(args[0].(*ssa.Const).Value)\n\tllvmArgs := []llvm.Value{}\n\targTypes := []llvm.Type{}\n\tasm := \"svc #\" + strconv.FormatUint(num, 10)\n\tconstraints := \"={x0}\"\n\tfor i, arg := range args[1:] {\n\t\targ = arg.(*ssa.MakeInterface).X\n\t\tif i == 0 {\n\t\t\tconstraints += \",0\"\n\t\t} else {\n\t\t\tconstraints += \",{x\" + strconv.Itoa(i) + \"}\"\n\t\t}\n\t\tllvmValue := b.getValue(arg, pos)\n\t\tllvmArgs = append(llvmArgs, llvmValue)\n\t\targTypes = append(argTypes, llvmValue.Type())\n\t}\n\t// Implement the ARM64 calling convention by marking x1-x7 as\n\t// clobbered. x0 is used as an output register so doesn't have to be\n\t// marked as clobbered.\n\tconstraints += \",~{x1},~{x2},~{x3},~{x4},~{x5},~{x6},~{x7}\"\n\tfnType := llvm.FunctionType(b.uintptrType, argTypes, false)\n\ttarget := llvm.InlineAsm(fnType, asm, constraints, true, false, 0, false)\n\treturn b.CreateCall(fnType, target, llvmArgs, \"\"), nil\n}\n\n// This is a compiler builtin which emits CSR instructions. It can be one of:\n//\n//\tfunc (csr CSR) Get() uintptr\n//\tfunc (csr CSR) Set(uintptr)\n//\tfunc (csr CSR) SetBits(uintptr) uintptr\n//\tfunc (csr CSR) ClearBits(uintptr) uintptr\n//\n// The csr parameter (method receiver) must be a constant. Other parameter can\n// be any value.\nfunc (b *builder) emitCSROperation(call *ssa.CallCommon) (llvm.Value, error) {\n\tcsrConst, ok := call.Args[0].(*ssa.Const)\n\tif !ok {\n\t\treturn llvm.Value{}, b.makeError(call.Pos(), \"CSR must be constant\")\n\t}\n\tcsr := csrConst.Uint64()\n\tswitch name := call.StaticCallee().Name(); name {\n\tcase \"Get\":\n\t\t// Note that this instruction may have side effects, and thus must be\n\t\t// marked as such.\n\t\tfnType := llvm.FunctionType(b.uintptrType, nil, false)\n\t\tasm := fmt.Sprintf(\"csrr $0, %d\", csr)\n\t\ttarget := llvm.InlineAsm(fnType, asm, \"=r\", true, false, 0, false)\n\t\treturn b.CreateCall(fnType, target, nil, \"\"), nil\n\tcase \"Set\":\n\t\tfnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.uintptrType}, false)\n\t\tasm := fmt.Sprintf(\"csrw %d, $0\", csr)\n\t\ttarget := llvm.InlineAsm(fnType, asm, \"r\", true, false, 0, false)\n\t\treturn b.CreateCall(fnType, target, []llvm.Value{b.getValue(call.Args[1], getPos(call))}, \"\"), nil\n\tcase \"SetBits\":\n\t\t// Note: it may be possible to optimize this to csrrsi in many cases.\n\t\tfnType := llvm.FunctionType(b.uintptrType, []llvm.Type{b.uintptrType}, false)\n\t\tasm := fmt.Sprintf(\"csrrs $0, %d, $1\", csr)\n\t\ttarget := llvm.InlineAsm(fnType, asm, \"=r,r\", true, false, 0, false)\n\t\treturn b.CreateCall(fnType, target, []llvm.Value{b.getValue(call.Args[1], getPos(call))}, \"\"), nil\n\tcase \"ClearBits\":\n\t\t// Note: it may be possible to optimize this to csrrci in many cases.\n\t\tfnType := llvm.FunctionType(b.uintptrType, []llvm.Type{b.uintptrType}, false)\n\t\tasm := fmt.Sprintf(\"csrrc $0, %d, $1\", csr)\n\t\ttarget := llvm.InlineAsm(fnType, asm, \"=r,r\", true, false, 0, false)\n\t\treturn b.CreateCall(fnType, target, []llvm.Value{b.getValue(call.Args[1], getPos(call))}, \"\"), nil\n\tdefault:\n\t\treturn llvm.Value{}, b.makeError(call.Pos(), \"unknown CSR operation: \"+name)\n\t}\n}\n\n// Implement runtime/interrupt.Checkpoint.Save. It needs to be implemented\n// directly at the call site. If it isn't implemented directly at the call site\n// (but instead through a function call), it might result in an overwritten\n// stack in the non-jump return case.\nfunc (b *builder) createInterruptCheckpoint(ptr ssa.Value) llvm.Value {\n\taddr := b.getValue(ptr, ptr.Pos())\n\tb.createNilCheck(ptr, addr, \"deref\")\n\tstackPointer := b.readStackPointer()\n\tb.CreateStore(stackPointer, addr)\n\treturn b.createCheckpoint(addr)\n}\n"
  },
  {
    "path": "compiler/interface.go",
    "content": "package compiler\n\n// This file transforms interface-related instructions (*ssa.MakeInterface,\n// *ssa.TypeAssert, calls on interface types) to an intermediate IR form, to be\n// lowered to the final form by the interface lowering pass. See\n// interface-lowering.go for more details.\n\nimport (\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/ssa\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// Type kinds for basic types.\n// They must match the constants for the Kind type in src/reflect/type.go.\nvar basicTypes = [...]uint8{\n\ttypes.Bool:          1,\n\ttypes.Int:           2,\n\ttypes.Int8:          3,\n\ttypes.Int16:         4,\n\ttypes.Int32:         5,\n\ttypes.Int64:         6,\n\ttypes.Uint:          7,\n\ttypes.Uint8:         8,\n\ttypes.Uint16:        9,\n\ttypes.Uint32:        10,\n\ttypes.Uint64:        11,\n\ttypes.Uintptr:       12,\n\ttypes.Float32:       13,\n\ttypes.Float64:       14,\n\ttypes.Complex64:     15,\n\ttypes.Complex128:    16,\n\ttypes.String:        17,\n\ttypes.UnsafePointer: 18,\n}\n\n// These must also match the constants for the Kind type in src/reflect/type.go.\nconst (\n\ttypeKindChan      = 19\n\ttypeKindInterface = 20\n\ttypeKindPointer   = 21\n\ttypeKindSlice     = 22\n\ttypeKindArray     = 23\n\ttypeKindSignature = 24\n\ttypeKindMap       = 25\n\ttypeKindStruct    = 26\n)\n\n// Flags stored in the first byte of the struct field byte array. Must be kept\n// up to date with src/reflect/type.go.\nconst (\n\tstructFieldFlagAnonymous = 1 << iota\n\tstructFieldFlagHasTag\n\tstructFieldFlagIsExported\n\tstructFieldFlagIsEmbedded\n)\n\ntype reflectChanDir int\n\nconst (\n\trefRecvDir reflectChanDir            = 1 << iota // <-chan\n\trefSendDir                                       // chan<-\n\trefBothDir = refRecvDir | refSendDir             // chan\n)\n\n// createMakeInterface emits the LLVM IR for the *ssa.MakeInterface instruction.\n// It tries to put the type in the interface value, but if that's not possible,\n// it will do an allocation of the right size and put that in the interface\n// value field.\n//\n// An interface value is a {typecode, value} tuple named runtime._interface.\nfunc (b *builder) createMakeInterface(val llvm.Value, typ types.Type, pos token.Pos) llvm.Value {\n\titfValue := b.emitPointerPack([]llvm.Value{val})\n\titfType := b.getTypeCode(typ)\n\titf := llvm.Undef(b.getLLVMRuntimeType(\"_interface\"))\n\titf = b.CreateInsertValue(itf, itfType, 0, \"\")\n\titf = b.CreateInsertValue(itf, itfValue, 1, \"\")\n\treturn itf\n}\n\n// extractValueFromInterface extract the value from an interface value\n// (runtime._interface) under the assumption that it is of the type given in\n// llvmType. The behavior is undefined if the interface is nil or llvmType\n// doesn't match the underlying type of the interface.\nfunc (b *builder) extractValueFromInterface(itf llvm.Value, llvmType llvm.Type) llvm.Value {\n\tvaluePtr := b.CreateExtractValue(itf, 1, \"typeassert.value.ptr\")\n\treturn b.emitPointerUnpack(valuePtr, []llvm.Type{llvmType})[0]\n}\n\nfunc (c *compilerContext) pkgPathPtr(pkgpath string) llvm.Value {\n\tpkgpathName := \"reflect/types.type.pkgpath.empty\"\n\tif pkgpath != \"\" {\n\t\tpkgpathName = \"reflect/types.type.pkgpath:\" + pkgpath\n\t}\n\n\tpkgpathGlobal := c.mod.NamedGlobal(pkgpathName)\n\tif pkgpathGlobal.IsNil() {\n\t\tpkgpathInitializer := c.ctx.ConstString(pkgpath+\"\\x00\", false)\n\t\tpkgpathGlobal = llvm.AddGlobal(c.mod, pkgpathInitializer.Type(), pkgpathName)\n\t\tpkgpathGlobal.SetInitializer(pkgpathInitializer)\n\t\tpkgpathGlobal.SetAlignment(1)\n\t\tpkgpathGlobal.SetUnnamedAddr(true)\n\t\tpkgpathGlobal.SetLinkage(llvm.LinkOnceODRLinkage)\n\t\tpkgpathGlobal.SetGlobalConstant(true)\n\t}\n\tpkgPathPtr := llvm.ConstGEP(pkgpathGlobal.GlobalValueType(), pkgpathGlobal, []llvm.Value{\n\t\tllvm.ConstInt(c.ctx.Int32Type(), 0, false),\n\t\tllvm.ConstInt(c.ctx.Int32Type(), 0, false),\n\t})\n\n\treturn pkgPathPtr\n}\n\n// getTypeCode returns a reference to a type code.\n// A type code is a pointer to a constant global that describes the type.\n// This function returns a pointer to the 'kind' field (which might not be the\n// first field in the struct).\nfunc (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {\n\t// Resolve alias types: alias types are resolved at compile time.\n\ttyp = types.Unalias(typ)\n\n\tms := c.program.MethodSets.MethodSet(typ)\n\thasMethodSet := ms.Len() != 0\n\t_, isInterface := typ.Underlying().(*types.Interface)\n\tif isInterface {\n\t\thasMethodSet = false\n\t}\n\n\t// As defined in https://pkg.go.dev/reflect#Type:\n\t// NumMethod returns the number of methods accessible using Method.\n\t// For a non-interface type, it returns the number of exported methods.\n\t// For an interface type, it returns the number of exported and unexported methods.\n\tvar numMethods int\n\tfor i := 0; i < ms.Len(); i++ {\n\t\tif isInterface || ms.At(i).Obj().Exported() {\n\t\t\tnumMethods++\n\t\t}\n\t}\n\n\t// Short-circuit all the global pointer logic here for pointers to pointers.\n\tif typ, ok := typ.(*types.Pointer); ok {\n\t\tif _, ok := typ.Elem().(*types.Pointer); ok {\n\t\t\t// For a pointer to a pointer, we just increase the pointer by 1\n\t\t\tptr := c.getTypeCode(typ.Elem())\n\t\t\t// if the type is already *****T or higher, we can't make it.\n\t\t\tif typstr := typ.String(); strings.HasPrefix(typstr, \"*****\") {\n\t\t\t\tc.addError(token.NoPos, fmt.Sprintf(\"too many levels of pointers for typecode: %s\", typstr))\n\t\t\t}\n\t\t\treturn llvm.ConstGEP(c.ctx.Int8Type(), ptr, []llvm.Value{\n\t\t\t\tllvm.ConstInt(c.ctx.Int32Type(), 1, false),\n\t\t\t})\n\t\t}\n\t}\n\n\ttypeCodeName, isLocal := getTypeCodeName(typ)\n\tglobalName := \"reflect/types.type:\" + typeCodeName\n\tvar global llvm.Value\n\tif isLocal {\n\t\t// This type is a named type inside a function, like this:\n\t\t//\n\t\t//     func foo() any {\n\t\t//         type named int\n\t\t//         return named(0)\n\t\t//     }\n\t\tif obj := c.interfaceTypes.At(typ); obj != nil {\n\t\t\tglobal = obj.(llvm.Value)\n\t\t}\n\t} else {\n\t\t// Regular type (named or otherwise).\n\t\tglobal = c.mod.NamedGlobal(globalName)\n\t}\n\tif global.IsNil() {\n\t\tvar typeFields []llvm.Value\n\t\t// Define the type fields. These must match the structs in\n\t\t// src/reflect/type.go (ptrType, arrayType, etc). See the comment at the\n\t\t// top of src/reflect/type.go for more information on the layout of these structs.\n\t\ttypeFieldTypes := []*types.Var{\n\t\t\ttypes.NewVar(token.NoPos, nil, \"kind\", types.Typ[types.Int8]),\n\t\t}\n\t\tswitch typ := typ.(type) {\n\t\tcase *types.Basic:\n\t\t\ttypeFieldTypes = append(typeFieldTypes,\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"ptrTo\", types.Typ[types.UnsafePointer]),\n\t\t\t)\n\t\tcase *types.Named:\n\t\t\tname := typ.Obj().Name()\n\t\t\tvar pkgname string\n\t\t\tif pkg := typ.Obj().Pkg(); pkg != nil {\n\t\t\t\tpkgname = pkg.Name()\n\t\t\t}\n\t\t\ttypeFieldTypes = append(typeFieldTypes,\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"numMethods\", types.Typ[types.Uint16]),\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"ptrTo\", types.Typ[types.UnsafePointer]),\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"underlying\", types.Typ[types.UnsafePointer]),\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"pkgpath\", types.Typ[types.UnsafePointer]),\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"name\", types.NewArray(types.Typ[types.Int8], int64(len(pkgname)+1+len(name)+1))),\n\t\t\t)\n\t\tcase *types.Chan:\n\t\t\ttypeFieldTypes = append(typeFieldTypes,\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"numMethods\", types.Typ[types.Uint16]), // reuse for select chan direction\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"ptrTo\", types.Typ[types.UnsafePointer]),\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"elementType\", types.Typ[types.UnsafePointer]),\n\t\t\t)\n\t\tcase *types.Slice:\n\t\t\ttypeFieldTypes = append(typeFieldTypes,\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"numMethods\", types.Typ[types.Uint16]),\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"ptrTo\", types.Typ[types.UnsafePointer]),\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"elementType\", types.Typ[types.UnsafePointer]),\n\t\t\t)\n\t\tcase *types.Pointer:\n\t\t\ttypeFieldTypes = append(typeFieldTypes,\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"numMethods\", types.Typ[types.Uint16]),\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"elementType\", types.Typ[types.UnsafePointer]),\n\t\t\t)\n\t\tcase *types.Array:\n\t\t\ttypeFieldTypes = append(typeFieldTypes,\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"numMethods\", types.Typ[types.Uint16]),\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"ptrTo\", types.Typ[types.UnsafePointer]),\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"elementType\", types.Typ[types.UnsafePointer]),\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"length\", types.Typ[types.Uintptr]),\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"sliceOf\", types.Typ[types.UnsafePointer]),\n\t\t\t)\n\t\tcase *types.Map:\n\t\t\ttypeFieldTypes = append(typeFieldTypes,\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"numMethods\", types.Typ[types.Uint16]),\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"ptrTo\", types.Typ[types.UnsafePointer]),\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"elementType\", types.Typ[types.UnsafePointer]),\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"keyType\", types.Typ[types.UnsafePointer]),\n\t\t\t)\n\t\tcase *types.Struct:\n\t\t\ttypeFieldTypes = append(typeFieldTypes,\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"numMethods\", types.Typ[types.Uint16]),\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"ptrTo\", types.Typ[types.UnsafePointer]),\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"pkgpath\", types.Typ[types.UnsafePointer]),\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"size\", types.Typ[types.Uint32]),\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"numFields\", types.Typ[types.Uint16]),\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"fields\", types.NewArray(c.getRuntimeType(\"structField\"), int64(typ.NumFields()))),\n\t\t\t)\n\t\tcase *types.Interface:\n\t\t\ttypeFieldTypes = append(typeFieldTypes,\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"ptrTo\", types.Typ[types.UnsafePointer]),\n\t\t\t)\n\t\t\t// TODO: methods\n\t\tcase *types.Signature:\n\t\t\ttypeFieldTypes = append(typeFieldTypes,\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"ptrTo\", types.Typ[types.UnsafePointer]),\n\t\t\t)\n\t\t\t// TODO: signature params and return values\n\t\t}\n\t\tif hasMethodSet {\n\t\t\t// This method set is appended at the start of the struct. It is\n\t\t\t// removed in the interface lowering pass.\n\t\t\t// TODO: don't remove these and instead do what upstream Go is doing\n\t\t\t// instead. See: https://research.swtch.com/interfaces. This can\n\t\t\t// likely be optimized in LLVM using\n\t\t\t// https://llvm.org/docs/TypeMetadata.html.\n\t\t\ttypeFieldTypes = append([]*types.Var{\n\t\t\t\ttypes.NewVar(token.NoPos, nil, \"methodSet\", types.Typ[types.UnsafePointer]),\n\t\t\t}, typeFieldTypes...)\n\t\t}\n\t\tglobalType := types.NewStruct(typeFieldTypes, nil)\n\t\tglobal = llvm.AddGlobal(c.mod, c.getLLVMType(globalType), globalName)\n\t\tif isLocal {\n\t\t\tc.interfaceTypes.Set(typ, global)\n\t\t}\n\t\tmetabyte := getTypeKind(typ)\n\n\t\t// Precompute these so we don't have to calculate them at runtime.\n\t\tif types.Comparable(typ) {\n\t\t\tmetabyte |= 1 << 6\n\t\t}\n\n\t\tif hashmapIsBinaryKey(typ) {\n\t\t\tmetabyte |= 1 << 7\n\t\t}\n\n\t\tswitch typ := typ.(type) {\n\t\tcase *types.Basic:\n\t\t\ttypeFields = []llvm.Value{c.getTypeCode(types.NewPointer(typ))}\n\t\tcase *types.Named:\n\t\t\tname := typ.Obj().Name()\n\t\t\tvar pkgpath string\n\t\t\tvar pkgname string\n\t\t\tif pkg := typ.Obj().Pkg(); pkg != nil {\n\t\t\t\tpkgpath = pkg.Path()\n\t\t\t\tpkgname = pkg.Name()\n\t\t\t}\n\t\t\tpkgPathPtr := c.pkgPathPtr(pkgpath)\n\t\t\ttypeFields = []llvm.Value{\n\t\t\t\tllvm.ConstInt(c.ctx.Int16Type(), uint64(numMethods), false), // numMethods\n\t\t\t\tc.getTypeCode(types.NewPointer(typ)),                        // ptrTo\n\t\t\t\tc.getTypeCode(typ.Underlying()),                             // underlying\n\t\t\t\tpkgPathPtr,                                                  // pkgpath pointer\n\t\t\t\tc.ctx.ConstString(pkgname+\".\"+name+\"\\x00\", false),           // name\n\t\t\t}\n\t\t\tmetabyte |= 1 << 5 // \"named\" flag\n\t\tcase *types.Chan:\n\t\t\tvar dir reflectChanDir\n\t\t\tswitch typ.Dir() {\n\t\t\tcase types.SendRecv:\n\t\t\t\tdir = refBothDir\n\t\t\tcase types.RecvOnly:\n\t\t\t\tdir = refRecvDir\n\t\t\tcase types.SendOnly:\n\t\t\t\tdir = refSendDir\n\t\t\t}\n\n\t\t\ttypeFields = []llvm.Value{\n\t\t\t\tllvm.ConstInt(c.ctx.Int16Type(), uint64(dir), false), // actually channel direction\n\t\t\t\tc.getTypeCode(types.NewPointer(typ)),                 // ptrTo\n\t\t\t\tc.getTypeCode(typ.Elem()),                            // elementType\n\t\t\t}\n\t\tcase *types.Slice:\n\t\t\ttypeFields = []llvm.Value{\n\t\t\t\tllvm.ConstInt(c.ctx.Int16Type(), 0, false), // numMethods\n\t\t\t\tc.getTypeCode(types.NewPointer(typ)),       // ptrTo\n\t\t\t\tc.getTypeCode(typ.Elem()),                  // elementType\n\t\t\t}\n\t\tcase *types.Pointer:\n\t\t\ttypeFields = []llvm.Value{\n\t\t\t\tllvm.ConstInt(c.ctx.Int16Type(), uint64(numMethods), false), // numMethods\n\t\t\t\tc.getTypeCode(typ.Elem()),\n\t\t\t}\n\t\tcase *types.Array:\n\t\t\ttypeFields = []llvm.Value{\n\t\t\t\tllvm.ConstInt(c.ctx.Int16Type(), 0, false),             // numMethods\n\t\t\t\tc.getTypeCode(types.NewPointer(typ)),                   // ptrTo\n\t\t\t\tc.getTypeCode(typ.Elem()),                              // elementType\n\t\t\t\tllvm.ConstInt(c.uintptrType, uint64(typ.Len()), false), // length\n\t\t\t\tc.getTypeCode(types.NewSlice(typ.Elem())),              // slicePtr\n\t\t\t}\n\t\tcase *types.Map:\n\t\t\ttypeFields = []llvm.Value{\n\t\t\t\tllvm.ConstInt(c.ctx.Int16Type(), 0, false), // numMethods\n\t\t\t\tc.getTypeCode(types.NewPointer(typ)),       // ptrTo\n\t\t\t\tc.getTypeCode(typ.Elem()),                  // elem\n\t\t\t\tc.getTypeCode(typ.Key()),                   // key\n\t\t\t}\n\t\tcase *types.Struct:\n\t\t\tvar pkgpath string\n\t\t\tif typ.NumFields() > 0 {\n\t\t\t\tif pkg := typ.Field(0).Pkg(); pkg != nil {\n\t\t\t\t\tpkgpath = pkg.Path()\n\t\t\t\t}\n\t\t\t}\n\t\t\tpkgPathPtr := c.pkgPathPtr(pkgpath)\n\n\t\t\tllvmStructType := c.getLLVMType(typ)\n\t\t\tsize := c.targetData.TypeStoreSize(llvmStructType)\n\t\t\ttypeFields = []llvm.Value{\n\t\t\t\tllvm.ConstInt(c.ctx.Int16Type(), uint64(numMethods), false), // numMethods\n\t\t\t\tc.getTypeCode(types.NewPointer(typ)),                        // ptrTo\n\t\t\t\tpkgPathPtr,\n\t\t\t\tllvm.ConstInt(c.ctx.Int32Type(), uint64(size), false),            // size\n\t\t\t\tllvm.ConstInt(c.ctx.Int16Type(), uint64(typ.NumFields()), false), // numFields\n\t\t\t}\n\t\t\tstructFieldType := c.getLLVMRuntimeType(\"structField\")\n\n\t\t\tvar fields []llvm.Value\n\t\t\tfor i := 0; i < typ.NumFields(); i++ {\n\t\t\t\tfield := typ.Field(i)\n\t\t\t\toffset := c.targetData.ElementOffset(llvmStructType, i)\n\t\t\t\tvar flags uint8\n\t\t\t\tif field.Anonymous() {\n\t\t\t\t\tflags |= structFieldFlagAnonymous\n\t\t\t\t}\n\t\t\t\tif typ.Tag(i) != \"\" {\n\t\t\t\t\tflags |= structFieldFlagHasTag\n\t\t\t\t}\n\t\t\t\tif token.IsExported(field.Name()) {\n\t\t\t\t\tflags |= structFieldFlagIsExported\n\t\t\t\t}\n\t\t\t\tif field.Embedded() {\n\t\t\t\t\tflags |= structFieldFlagIsEmbedded\n\t\t\t\t}\n\n\t\t\t\tvar offsBytes [binary.MaxVarintLen32]byte\n\t\t\t\toffLen := binary.PutUvarint(offsBytes[:], offset)\n\n\t\t\t\tdata := string(flags) + string(offsBytes[:offLen]) + field.Name() + \"\\x00\"\n\t\t\t\tif typ.Tag(i) != \"\" {\n\t\t\t\t\tif len(typ.Tag(i)) > 0xff {\n\t\t\t\t\t\tc.addError(field.Pos(), fmt.Sprintf(\"struct tag is %d bytes which is too long, max is 255\", len(typ.Tag(i))))\n\t\t\t\t\t}\n\t\t\t\t\tdata += string([]byte{byte(len(typ.Tag(i)))}) + typ.Tag(i)\n\t\t\t\t}\n\t\t\t\tdataInitializer := c.ctx.ConstString(data, false)\n\t\t\t\tdataGlobal := llvm.AddGlobal(c.mod, dataInitializer.Type(), globalName+\".\"+field.Name())\n\t\t\t\tdataGlobal.SetInitializer(dataInitializer)\n\t\t\t\tdataGlobal.SetAlignment(1)\n\t\t\t\tdataGlobal.SetUnnamedAddr(true)\n\t\t\t\tdataGlobal.SetLinkage(llvm.InternalLinkage)\n\t\t\t\tdataGlobal.SetGlobalConstant(true)\n\t\t\t\tfieldType := c.getTypeCode(field.Type())\n\t\t\t\tfields = append(fields, llvm.ConstNamedStruct(structFieldType, []llvm.Value{\n\t\t\t\t\tfieldType,\n\t\t\t\t\tllvm.ConstGEP(dataGlobal.GlobalValueType(), dataGlobal, []llvm.Value{\n\t\t\t\t\t\tllvm.ConstInt(c.ctx.Int32Type(), 0, false),\n\t\t\t\t\t\tllvm.ConstInt(c.ctx.Int32Type(), 0, false),\n\t\t\t\t\t}),\n\t\t\t\t}))\n\t\t\t}\n\t\t\ttypeFields = append(typeFields, llvm.ConstArray(structFieldType, fields))\n\t\tcase *types.Interface:\n\t\t\ttypeFields = []llvm.Value{c.getTypeCode(types.NewPointer(typ))}\n\t\t\t// TODO: methods\n\t\tcase *types.Signature:\n\t\t\ttypeFields = []llvm.Value{c.getTypeCode(types.NewPointer(typ))}\n\t\t\t// TODO: params, return values, etc\n\t\t}\n\t\t// Prepend metadata byte.\n\t\ttypeFields = append([]llvm.Value{\n\t\t\tllvm.ConstInt(c.ctx.Int8Type(), uint64(metabyte), false),\n\t\t}, typeFields...)\n\t\tif hasMethodSet {\n\t\t\ttypeFields = append([]llvm.Value{\n\t\t\t\tc.getTypeMethodSet(typ),\n\t\t\t}, typeFields...)\n\t\t}\n\t\talignment := c.targetData.TypeAllocSize(c.dataPtrType)\n\t\tif alignment < 4 {\n\t\t\talignment = 4\n\t\t}\n\t\tglobalValue := c.ctx.ConstStruct(typeFields, false)\n\t\tglobal.SetInitializer(globalValue)\n\t\tif isLocal {\n\t\t\tglobal.SetLinkage(llvm.InternalLinkage)\n\t\t} else {\n\t\t\tglobal.SetLinkage(llvm.LinkOnceODRLinkage)\n\t\t}\n\t\tglobal.SetGlobalConstant(true)\n\t\tglobal.SetAlignment(int(alignment))\n\t\tif c.Debug {\n\t\t\tfile := c.getDIFile(\"<Go type>\")\n\t\t\tdiglobal := c.dibuilder.CreateGlobalVariableExpression(file, llvm.DIGlobalVariableExpression{\n\t\t\t\tName:        \"type \" + typ.String(),\n\t\t\t\tFile:        file,\n\t\t\t\tLine:        1,\n\t\t\t\tType:        c.getDIType(globalType),\n\t\t\t\tLocalToUnit: false,\n\t\t\t\tExpr:        c.dibuilder.CreateExpression(nil),\n\t\t\t\tAlignInBits: uint32(alignment * 8),\n\t\t\t})\n\t\t\tglobal.AddMetadata(0, diglobal)\n\t\t}\n\t}\n\toffset := uint64(0)\n\tif hasMethodSet {\n\t\t// The pointer to the method set is always the first element of the\n\t\t// global (if there is a method set). However, the pointer we return\n\t\t// should point to the 'kind' field not the method set.\n\t\toffset = 1\n\t}\n\treturn llvm.ConstGEP(global.GlobalValueType(), global, []llvm.Value{\n\t\tllvm.ConstInt(c.ctx.Int32Type(), 0, false),\n\t\tllvm.ConstInt(c.ctx.Int32Type(), offset, false),\n\t})\n}\n\n// getTypeKind returns the type kind for the given type, as defined by\n// reflect.Kind.\nfunc getTypeKind(t types.Type) uint8 {\n\tswitch t := t.Underlying().(type) {\n\tcase *types.Basic:\n\t\treturn basicTypes[t.Kind()]\n\tcase *types.Chan:\n\t\treturn typeKindChan\n\tcase *types.Interface:\n\t\treturn typeKindInterface\n\tcase *types.Pointer:\n\t\treturn typeKindPointer\n\tcase *types.Slice:\n\t\treturn typeKindSlice\n\tcase *types.Array:\n\t\treturn typeKindArray\n\tcase *types.Signature:\n\t\treturn typeKindSignature\n\tcase *types.Map:\n\t\treturn typeKindMap\n\tcase *types.Struct:\n\t\treturn typeKindStruct\n\tdefault:\n\t\tpanic(\"unknown type\")\n\t}\n}\n\nvar basicTypeNames = [...]string{\n\ttypes.Bool:          \"bool\",\n\ttypes.Int:           \"int\",\n\ttypes.Int8:          \"int8\",\n\ttypes.Int16:         \"int16\",\n\ttypes.Int32:         \"int32\",\n\ttypes.Int64:         \"int64\",\n\ttypes.Uint:          \"uint\",\n\ttypes.Uint8:         \"uint8\",\n\ttypes.Uint16:        \"uint16\",\n\ttypes.Uint32:        \"uint32\",\n\ttypes.Uint64:        \"uint64\",\n\ttypes.Uintptr:       \"uintptr\",\n\ttypes.Float32:       \"float32\",\n\ttypes.Float64:       \"float64\",\n\ttypes.Complex64:     \"complex64\",\n\ttypes.Complex128:    \"complex128\",\n\ttypes.String:        \"string\",\n\ttypes.UnsafePointer: \"unsafe.Pointer\",\n}\n\n// getTypeCodeName returns a name for this type that can be used in the\n// interface lowering pass to assign type codes as expected by the reflect\n// package. See getTypeCodeNum.\nfunc getTypeCodeName(t types.Type) (string, bool) {\n\tswitch t := types.Unalias(t).(type) {\n\tcase *types.Named:\n\t\tif t.Obj().Parent() != t.Obj().Pkg().Scope() {\n\t\t\treturn \"named:\" + t.String() + \"$local\", true\n\t\t}\n\t\treturn \"named:\" + t.String(), false\n\tcase *types.Array:\n\t\ts, isLocal := getTypeCodeName(t.Elem())\n\t\treturn \"array:\" + strconv.FormatInt(t.Len(), 10) + \":\" + s, isLocal\n\tcase *types.Basic:\n\t\treturn \"basic:\" + basicTypeNames[t.Kind()], false\n\tcase *types.Chan:\n\t\ts, isLocal := getTypeCodeName(t.Elem())\n\t\tvar dir string\n\t\tswitch t.Dir() {\n\t\tcase types.SendOnly:\n\t\t\tdir = \"s:\"\n\t\tcase types.RecvOnly:\n\t\t\tdir = \"r:\"\n\t\tcase types.SendRecv:\n\t\t\tdir = \"sr:\"\n\t\t}\n\n\t\treturn \"chan:\" + dir + s, isLocal\n\tcase *types.Interface:\n\t\tisLocal := false\n\t\tmethods := make([]string, t.NumMethods())\n\t\tfor i := 0; i < t.NumMethods(); i++ {\n\t\t\tname := t.Method(i).Name()\n\t\t\tif !token.IsExported(name) {\n\t\t\t\tname = t.Method(i).Pkg().Path() + \".\" + name\n\t\t\t}\n\t\t\ts, local := getTypeCodeName(t.Method(i).Type())\n\t\t\tif local {\n\t\t\t\tisLocal = true\n\t\t\t}\n\t\t\tmethods[i] = name + \":\" + s\n\t\t}\n\t\treturn \"interface:\" + \"{\" + strings.Join(methods, \",\") + \"}\", isLocal\n\tcase *types.Map:\n\t\tkeyType, keyLocal := getTypeCodeName(t.Key())\n\t\telemType, elemLocal := getTypeCodeName(t.Elem())\n\t\treturn \"map:\" + \"{\" + keyType + \",\" + elemType + \"}\", keyLocal || elemLocal\n\tcase *types.Pointer:\n\t\ts, isLocal := getTypeCodeName(t.Elem())\n\t\treturn \"pointer:\" + s, isLocal\n\tcase *types.Signature:\n\t\tisLocal := false\n\t\tparams := make([]string, t.Params().Len())\n\t\tfor i := 0; i < t.Params().Len(); i++ {\n\t\t\ts, local := getTypeCodeName(t.Params().At(i).Type())\n\t\t\tif local {\n\t\t\t\tisLocal = true\n\t\t\t}\n\t\t\tparams[i] = s\n\t\t}\n\t\tresults := make([]string, t.Results().Len())\n\t\tfor i := 0; i < t.Results().Len(); i++ {\n\t\t\ts, local := getTypeCodeName(t.Results().At(i).Type())\n\t\t\tif local {\n\t\t\t\tisLocal = true\n\t\t\t}\n\t\t\tresults[i] = s\n\t\t}\n\t\treturn \"func:\" + \"{\" + strings.Join(params, \",\") + \"}{\" + strings.Join(results, \",\") + \"}\", isLocal\n\tcase *types.Slice:\n\t\ts, isLocal := getTypeCodeName(t.Elem())\n\t\treturn \"slice:\" + s, isLocal\n\tcase *types.Struct:\n\t\telems := make([]string, t.NumFields())\n\t\tisLocal := false\n\t\tfor i := 0; i < t.NumFields(); i++ {\n\t\t\tembedded := \"\"\n\t\t\tif t.Field(i).Embedded() {\n\t\t\t\tembedded = \"#\"\n\t\t\t}\n\t\t\ts, local := getTypeCodeName(t.Field(i).Type())\n\t\t\tif local {\n\t\t\t\tisLocal = true\n\t\t\t}\n\t\t\telems[i] = embedded + t.Field(i).Name() + \":\" + s\n\t\t\tif t.Tag(i) != \"\" {\n\t\t\t\telems[i] += \"`\" + t.Tag(i) + \"`\"\n\t\t\t}\n\t\t}\n\t\treturn \"struct:\" + \"{\" + strings.Join(elems, \",\") + \"}\", isLocal\n\tdefault:\n\t\tpanic(\"unknown type: \" + t.String())\n\t}\n}\n\n// getTypeMethodSet returns a reference (GEP) to a global method set. This\n// method set should be unreferenced after the interface lowering pass.\nfunc (c *compilerContext) getTypeMethodSet(typ types.Type) llvm.Value {\n\tglobalName := typ.String() + \"$methodset\"\n\tglobal := c.mod.NamedGlobal(globalName)\n\tif global.IsNil() {\n\t\tms := c.program.MethodSets.MethodSet(typ)\n\n\t\t// Create method set.\n\t\tvar signatures, wrappers []llvm.Value\n\t\tfor i := 0; i < ms.Len(); i++ {\n\t\t\tmethod := ms.At(i)\n\t\t\tsignatureGlobal := c.getMethodSignature(method.Obj().(*types.Func))\n\t\t\tsignatures = append(signatures, signatureGlobal)\n\t\t\tfn := c.program.MethodValue(method)\n\t\t\tllvmFnType, llvmFn := c.getFunction(fn)\n\t\t\tif llvmFn.IsNil() {\n\t\t\t\t// compiler error, so panic\n\t\t\t\tpanic(\"cannot find function: \" + c.getFunctionInfo(fn).linkName)\n\t\t\t}\n\t\t\twrapper := c.getInterfaceInvokeWrapper(fn, llvmFnType, llvmFn)\n\t\t\twrappers = append(wrappers, wrapper)\n\t\t}\n\n\t\t// Construct global value.\n\t\tglobalValue := c.ctx.ConstStruct([]llvm.Value{\n\t\t\tllvm.ConstInt(c.uintptrType, uint64(ms.Len()), false),\n\t\t\tllvm.ConstArray(c.dataPtrType, signatures),\n\t\t\tc.ctx.ConstStruct(wrappers, false),\n\t\t}, false)\n\t\tglobal = llvm.AddGlobal(c.mod, globalValue.Type(), globalName)\n\t\tglobal.SetInitializer(globalValue)\n\t\tglobal.SetGlobalConstant(true)\n\t\tglobal.SetUnnamedAddr(true)\n\t\tglobal.SetLinkage(llvm.LinkOnceODRLinkage)\n\t}\n\treturn global\n}\n\n// getMethodSignatureName returns a unique name (that can be used as the name of\n// a global) for the given method.\nfunc (c *compilerContext) getMethodSignatureName(method *types.Func) string {\n\tsignature := methodSignature(method)\n\tvar globalName string\n\tif token.IsExported(method.Name()) {\n\t\tglobalName = \"reflect/methods.\" + signature\n\t} else {\n\t\tglobalName = method.Type().(*types.Signature).Recv().Pkg().Path() + \".$methods.\" + signature\n\t}\n\treturn globalName\n}\n\n// getMethodSignature returns a global variable which is a reference to an\n// external *i8 indicating the indicating the signature of this method. It is\n// used during the interface lowering pass.\nfunc (c *compilerContext) getMethodSignature(method *types.Func) llvm.Value {\n\tglobalName := c.getMethodSignatureName(method)\n\tsignatureGlobal := c.mod.NamedGlobal(globalName)\n\tif signatureGlobal.IsNil() {\n\t\t// TODO: put something useful in these globals, such as the method\n\t\t// signature. Useful to one day implement reflect.Value.Method(n).\n\t\tsignatureGlobal = llvm.AddGlobal(c.mod, c.ctx.Int8Type(), globalName)\n\t\tsignatureGlobal.SetInitializer(llvm.ConstInt(c.ctx.Int8Type(), 0, false))\n\t\tsignatureGlobal.SetLinkage(llvm.LinkOnceODRLinkage)\n\t\tsignatureGlobal.SetGlobalConstant(true)\n\t\tsignatureGlobal.SetAlignment(1)\n\t}\n\treturn signatureGlobal\n}\n\n// createTypeAssert will emit the code for a typeassert, used in if statements\n// and in type switches (Go SSA does not have type switches, only if/else\n// chains). Note that even though the Go SSA does not contain type switches,\n// LLVM will recognize the pattern and make it a real switch in many cases.\n//\n// Type asserts on concrete types are trivial: just compare type numbers. Type\n// asserts on interfaces are more difficult, see the comments in the function.\nfunc (b *builder) createTypeAssert(expr *ssa.TypeAssert) llvm.Value {\n\titf := b.getValue(expr.X, getPos(expr))\n\tassertedType := b.getLLVMType(expr.AssertedType)\n\n\tactualTypeNum := b.CreateExtractValue(itf, 0, \"interface.type\")\n\tcommaOk := llvm.Value{}\n\n\tif intf, ok := expr.AssertedType.Underlying().(*types.Interface); ok {\n\t\tif intf.Empty() {\n\t\t\t// intf is the empty interface => no methods\n\t\t\t// This type assertion always succeeds, so we can just set commaOk to true.\n\t\t\tcommaOk = llvm.ConstInt(b.ctx.Int1Type(), 1, true)\n\t\t} else {\n\t\t\t// Type assert on interface type with methods.\n\t\t\t// This is a call to an interface type assert function.\n\t\t\t// The interface lowering pass will define this function by filling it\n\t\t\t// with a type switch over all concrete types that implement this\n\t\t\t// interface, and returning whether it's one of the matched types.\n\t\t\t// This is very different from how interface asserts are implemented in\n\t\t\t// the main Go compiler, where the runtime checks whether the type\n\t\t\t// implements each method of the interface. See:\n\t\t\t// https://research.swtch.com/interfaces\n\t\t\tfn := b.getInterfaceImplementsFunc(expr.AssertedType)\n\t\t\tcommaOk = b.CreateCall(fn.GlobalValueType(), fn, []llvm.Value{actualTypeNum}, \"\")\n\t\t}\n\t} else {\n\t\tname, _ := getTypeCodeName(expr.AssertedType)\n\t\tglobalName := \"reflect/types.typeid:\" + name\n\t\tassertedTypeCodeGlobal := b.mod.NamedGlobal(globalName)\n\t\tif assertedTypeCodeGlobal.IsNil() {\n\t\t\t// Create a new typecode global.\n\t\t\tassertedTypeCodeGlobal = llvm.AddGlobal(b.mod, b.ctx.Int8Type(), globalName)\n\t\t\tassertedTypeCodeGlobal.SetGlobalConstant(true)\n\t\t}\n\t\t// Type assert on concrete type.\n\t\t// Call runtime.typeAssert, which will be lowered to a simple icmp or\n\t\t// const false in the interface lowering pass.\n\t\tcommaOk = b.createRuntimeCall(\"typeAssert\", []llvm.Value{actualTypeNum, assertedTypeCodeGlobal}, \"typecode\")\n\t}\n\n\t// Add 2 new basic blocks (that should get optimized away): one for the\n\t// 'ok' case and one for all instructions following this type assert.\n\t// This is necessary because we need to insert the casted value or the\n\t// nil value based on whether the assert was successful. Casting before\n\t// this check tells LLVM that it can use this value and may\n\t// speculatively dereference pointers before the check. This can lead to\n\t// a miscompilation resulting in a segfault at runtime.\n\t// Additionally, this is even required by the Go spec: a failed\n\t// typeassert should return a zero value, not an incorrectly casted\n\t// value.\n\n\tprevBlock := b.GetInsertBlock()\n\tokBlock := b.insertBasicBlock(\"typeassert.ok\")\n\tnextBlock := b.insertBasicBlock(\"typeassert.next\")\n\tb.currentBlockInfo.exit = nextBlock // adjust outgoing block for phi nodes\n\tb.CreateCondBr(commaOk, okBlock, nextBlock)\n\n\t// Retrieve the value from the interface if the type assert was\n\t// successful.\n\tb.SetInsertPointAtEnd(okBlock)\n\tvar valueOk llvm.Value\n\tif _, ok := expr.AssertedType.Underlying().(*types.Interface); ok {\n\t\t// Type assert on interface type. Easy: just return the same\n\t\t// interface value.\n\t\tvalueOk = itf\n\t} else {\n\t\t// Type assert on concrete type. Extract the underlying type from\n\t\t// the interface (but only after checking it matches).\n\t\tvalueOk = b.extractValueFromInterface(itf, assertedType)\n\t}\n\tb.CreateBr(nextBlock)\n\n\t// Continue after the if statement.\n\tb.SetInsertPointAtEnd(nextBlock)\n\tphi := b.CreatePHI(assertedType, \"typeassert.value\")\n\tphi.AddIncoming([]llvm.Value{llvm.ConstNull(assertedType), valueOk}, []llvm.BasicBlock{prevBlock, okBlock})\n\n\tif expr.CommaOk {\n\t\ttuple := b.ctx.ConstStruct([]llvm.Value{llvm.Undef(assertedType), llvm.Undef(b.ctx.Int1Type())}, false) // create empty tuple\n\t\ttuple = b.CreateInsertValue(tuple, phi, 0, \"\")                                                          // insert value\n\t\ttuple = b.CreateInsertValue(tuple, commaOk, 1, \"\")                                                      // insert 'comma ok' boolean\n\t\treturn tuple\n\t} else {\n\t\t// This is kind of dirty as the branch above becomes mostly useless,\n\t\t// but hopefully this gets optimized away.\n\t\tb.createRuntimeCall(\"interfaceTypeAssert\", []llvm.Value{commaOk}, \"\")\n\t\treturn phi\n\t}\n}\n\n// getMethodsString returns a string to be used in the \"tinygo-methods\" string\n// attribute for interface functions.\nfunc (c *compilerContext) getMethodsString(itf *types.Interface) string {\n\tmethods := make([]string, itf.NumMethods())\n\tfor i := range methods {\n\t\tmethods[i] = c.getMethodSignatureName(itf.Method(i))\n\t}\n\treturn strings.Join(methods, \"; \")\n}\n\n// getInterfaceImplementsFunc returns a declared function that works as a type\n// switch. The interface lowering pass will define this function.\nfunc (c *compilerContext) getInterfaceImplementsFunc(assertedType types.Type) llvm.Value {\n\ts, _ := getTypeCodeName(assertedType.Underlying())\n\tfnName := s + \".$typeassert\"\n\tllvmFn := c.mod.NamedFunction(fnName)\n\tif llvmFn.IsNil() {\n\t\tllvmFnType := llvm.FunctionType(c.ctx.Int1Type(), []llvm.Type{c.dataPtrType}, false)\n\t\tllvmFn = llvm.AddFunction(c.mod, fnName, llvmFnType)\n\t\tc.addStandardDeclaredAttributes(llvmFn)\n\t\tmethods := c.getMethodsString(assertedType.Underlying().(*types.Interface))\n\t\tllvmFn.AddFunctionAttr(c.ctx.CreateStringAttribute(\"tinygo-methods\", methods))\n\t}\n\treturn llvmFn\n}\n\n// getInvokeFunction returns the thunk to call the given interface method. The\n// thunk is declared, not defined: it will be defined by the interface lowering\n// pass.\nfunc (c *compilerContext) getInvokeFunction(instr *ssa.CallCommon) llvm.Value {\n\ts, _ := getTypeCodeName(instr.Value.Type().Underlying())\n\tfnName := s + \".\" + instr.Method.Name() + \"$invoke\"\n\tllvmFn := c.mod.NamedFunction(fnName)\n\tif llvmFn.IsNil() {\n\t\tsig := instr.Method.Type().(*types.Signature)\n\t\tvar paramTuple []*types.Var\n\t\tfor i := 0; i < sig.Params().Len(); i++ {\n\t\t\tparamTuple = append(paramTuple, sig.Params().At(i))\n\t\t}\n\t\tparamTuple = append(paramTuple, types.NewVar(token.NoPos, nil, \"$typecode\", types.Typ[types.UnsafePointer]))\n\t\tllvmFnType := c.getLLVMFunctionType(types.NewSignature(sig.Recv(), types.NewTuple(paramTuple...), sig.Results(), false))\n\t\tllvmFn = llvm.AddFunction(c.mod, fnName, llvmFnType)\n\t\tc.addStandardDeclaredAttributes(llvmFn)\n\t\tllvmFn.AddFunctionAttr(c.ctx.CreateStringAttribute(\"tinygo-invoke\", c.getMethodSignatureName(instr.Method)))\n\t\tmethods := c.getMethodsString(instr.Value.Type().Underlying().(*types.Interface))\n\t\tllvmFn.AddFunctionAttr(c.ctx.CreateStringAttribute(\"tinygo-methods\", methods))\n\t}\n\treturn llvmFn\n}\n\n// getInterfaceInvokeWrapper returns a wrapper for the given method so it can be\n// invoked from an interface. The wrapper takes in a pointer to the underlying\n// value, dereferences or unpacks it if necessary, and calls the real method.\n// If the method to wrap has a pointer receiver, no wrapping is necessary and\n// the function is returned directly.\nfunc (c *compilerContext) getInterfaceInvokeWrapper(fn *ssa.Function, llvmFnType llvm.Type, llvmFn llvm.Value) llvm.Value {\n\twrapperName := llvmFn.Name() + \"$invoke\"\n\twrapper := c.mod.NamedFunction(wrapperName)\n\tif !wrapper.IsNil() {\n\t\t// Wrapper already created. Return it directly.\n\t\treturn wrapper\n\t}\n\n\t// Get the expanded receiver type.\n\treceiverType := c.getLLVMType(fn.Signature.Recv().Type())\n\tvar expandedReceiverType []llvm.Type\n\tfor _, info := range c.expandFormalParamType(receiverType, \"\", nil) {\n\t\texpandedReceiverType = append(expandedReceiverType, info.llvmType)\n\t}\n\n\t// Does this method even need any wrapping?\n\tif len(expandedReceiverType) == 1 && receiverType.TypeKind() == llvm.PointerTypeKind {\n\t\t// Nothing to wrap.\n\t\t// Casting a function signature to a different signature and calling it\n\t\t// with a receiver pointer bitcasted to *i8 (as done in calls on an\n\t\t// interface) is hopefully a safe (defined) operation.\n\t\treturn llvmFn\n\t}\n\n\t// create wrapper function\n\tparamTypes := append([]llvm.Type{c.dataPtrType}, llvmFnType.ParamTypes()[len(expandedReceiverType):]...)\n\twrapFnType := llvm.FunctionType(llvmFnType.ReturnType(), paramTypes, false)\n\twrapper = llvm.AddFunction(c.mod, wrapperName, wrapFnType)\n\tc.addStandardAttributes(wrapper)\n\n\twrapper.SetLinkage(llvm.LinkOnceODRLinkage)\n\twrapper.SetUnnamedAddr(true)\n\n\t// Create a new builder just to create this wrapper.\n\tb := builder{\n\t\tcompilerContext: c,\n\t\tBuilder:         c.ctx.NewBuilder(),\n\t}\n\tdefer b.Builder.Dispose()\n\n\t// add debug info if needed\n\tif c.Debug {\n\t\tpos := c.program.Fset.Position(fn.Pos())\n\t\tdifunc := c.attachDebugInfoRaw(fn, wrapper, \"$invoke\", pos.Filename, pos.Line)\n\t\tb.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), difunc, llvm.Metadata{})\n\t}\n\n\t// set up IR builder\n\tblock := b.ctx.AddBasicBlock(wrapper, \"entry\")\n\tb.SetInsertPointAtEnd(block)\n\n\treceiverValue := b.emitPointerUnpack(wrapper.Param(0), []llvm.Type{receiverType})[0]\n\tparams := append(b.expandFormalParam(receiverValue), wrapper.Params()[1:]...)\n\tif llvmFnType.ReturnType().TypeKind() == llvm.VoidTypeKind {\n\t\tb.CreateCall(llvmFnType, llvmFn, params, \"\")\n\t\tb.CreateRetVoid()\n\t} else {\n\t\tret := b.CreateCall(llvmFnType, llvmFn, params, \"ret\")\n\t\tb.CreateRet(ret)\n\t}\n\n\treturn wrapper\n}\n\n// methodSignature creates a readable version of a method signature (including\n// the function name, excluding the receiver name). This string is used\n// internally to match interfaces and to call the correct method on an\n// interface. Examples:\n//\n//\tString() string\n//\tRead([]byte) (int, error)\nfunc methodSignature(method *types.Func) string {\n\treturn method.Name() + signature(method.Type().(*types.Signature))\n}\n\n// Make a readable version of a function (pointer) signature.\n// Examples:\n//\n//\t() string\n//\t(string, int) (int, error)\nfunc signature(sig *types.Signature) string {\n\ts := \"\"\n\tif sig.Params().Len() == 0 {\n\t\ts += \"()\"\n\t} else {\n\t\ts += \"(\"\n\t\tfor i := 0; i < sig.Params().Len(); i++ {\n\t\t\tif i > 0 {\n\t\t\t\ts += \", \"\n\t\t\t}\n\t\t\ts += typestring(sig.Params().At(i).Type())\n\t\t}\n\t\ts += \")\"\n\t}\n\tif sig.Results().Len() == 0 {\n\t\t// keep as-is\n\t} else if sig.Results().Len() == 1 {\n\t\ts += \" \" + typestring(sig.Results().At(0).Type())\n\t} else {\n\t\ts += \" (\"\n\t\tfor i := 0; i < sig.Results().Len(); i++ {\n\t\t\tif i > 0 {\n\t\t\t\ts += \", \"\n\t\t\t}\n\t\t\ts += typestring(sig.Results().At(i).Type())\n\t\t}\n\t\ts += \")\"\n\t}\n\treturn s\n}\n\n// typestring returns a stable (human-readable) type string for the given type\n// that can be used for interface equality checks. It is almost (but not\n// exactly) the same as calling t.String(). The main difference is some\n// normalization around `byte` vs `uint8` for example.\nfunc typestring(t types.Type) string {\n\t// See: https://github.com/golang/go/blob/master/src/go/types/typestring.go\n\tswitch t := types.Unalias(t).(type) {\n\tcase *types.Array:\n\t\treturn \"[\" + strconv.FormatInt(t.Len(), 10) + \"]\" + typestring(t.Elem())\n\tcase *types.Basic:\n\t\treturn basicTypeNames[t.Kind()]\n\tcase *types.Chan:\n\t\tswitch t.Dir() {\n\t\tcase types.SendRecv:\n\t\t\treturn \"chan (\" + typestring(t.Elem()) + \")\"\n\t\tcase types.SendOnly:\n\t\t\treturn \"chan<- (\" + typestring(t.Elem()) + \")\"\n\t\tcase types.RecvOnly:\n\t\t\treturn \"<-chan (\" + typestring(t.Elem()) + \")\"\n\t\tdefault:\n\t\t\tpanic(\"unknown channel direction\")\n\t\t}\n\tcase *types.Interface:\n\t\tmethods := make([]string, t.NumMethods())\n\t\tfor i := range methods {\n\t\t\tmethod := t.Method(i)\n\t\t\tmethods[i] = method.Name() + signature(method.Type().(*types.Signature))\n\t\t}\n\t\treturn \"interface{\" + strings.Join(methods, \";\") + \"}\"\n\tcase *types.Map:\n\t\treturn \"map[\" + typestring(t.Key()) + \"]\" + typestring(t.Elem())\n\tcase *types.Named:\n\t\treturn t.String()\n\tcase *types.Pointer:\n\t\treturn \"*\" + typestring(t.Elem())\n\tcase *types.Signature:\n\t\treturn \"func\" + signature(t)\n\tcase *types.Slice:\n\t\treturn \"[]\" + typestring(t.Elem())\n\tcase *types.Struct:\n\t\tfields := make([]string, t.NumFields())\n\t\tfor i := range fields {\n\t\t\tfield := t.Field(i)\n\t\t\tfields[i] = field.Name() + \" \" + typestring(field.Type())\n\t\t\tif tag := t.Tag(i); tag != \"\" {\n\t\t\t\tfields[i] += \" \" + strconv.Quote(tag)\n\t\t\t}\n\t\t}\n\t\treturn \"struct{\" + strings.Join(fields, \";\") + \"}\"\n\tdefault:\n\t\tpanic(\"unknown type: \" + t.String())\n\t}\n}\n"
  },
  {
    "path": "compiler/interrupt.go",
    "content": "package compiler\n\nimport (\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/ssa\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// createInterruptGlobal creates a new runtime/interrupt.Interrupt struct that\n// will be lowered to a real interrupt during interrupt lowering.\n//\n// This two-stage approach allows unused interrupts to be optimized away if\n// necessary.\nfunc (b *builder) createInterruptGlobal(instr *ssa.CallCommon) (llvm.Value, error) {\n\t// Get the interrupt number, which must be a compile-time constant.\n\tid, ok := instr.Args[0].(*ssa.Const)\n\tif !ok {\n\t\treturn llvm.Value{}, b.makeError(instr.Pos(), \"interrupt ID is not a constant\")\n\t}\n\n\t// Get the func value, which also must be a compile time constant.\n\t// Note that bound functions are allowed if the function has a pointer\n\t// receiver and is a global. This is rather strict but still allows for\n\t// idiomatic Go code.\n\tfuncValue := b.getValue(instr.Args[1], getPos(instr))\n\tif funcValue.IsAConstant().IsNil() {\n\t\t// Try to determine the cause of the non-constantness for a nice error\n\t\t// message.\n\t\tswitch instr.Args[1].(type) {\n\t\tcase *ssa.MakeClosure:\n\t\t\t// This may also be a bound method.\n\t\t\treturn llvm.Value{}, b.makeError(instr.Pos(), \"closures are not supported in interrupt.New\")\n\t\t}\n\t\t// Fall back to a generic error.\n\t\treturn llvm.Value{}, b.makeError(instr.Pos(), \"interrupt function must be constant\")\n\t}\n\tfuncRawPtr, funcContext := b.decodeFuncValue(funcValue)\n\tfuncPtr := llvm.ConstPtrToInt(funcRawPtr, b.uintptrType)\n\n\t// Create a new global of type runtime/interrupt.handle. Globals of this\n\t// type are lowered in the interrupt lowering pass.\n\t// It must have an alignment of 1, otherwise LLVM thinks a ptrtoint of the\n\t// global has the lower bits unset.\n\tglobalType := b.program.ImportedPackage(\"runtime/interrupt\").Type(\"handle\").Type()\n\tglobalLLVMType := b.getLLVMType(globalType)\n\tglobalName := b.fn.Package().Pkg.Path() + \"$interrupt\" + strconv.FormatInt(id.Int64(), 10)\n\tglobal := llvm.AddGlobal(b.mod, globalLLVMType, globalName)\n\tglobal.SetVisibility(llvm.HiddenVisibility)\n\tglobal.SetGlobalConstant(true)\n\tglobal.SetUnnamedAddr(true)\n\tglobal.SetAlignment(1)\n\tinitializer := llvm.ConstNull(globalLLVMType)\n\tinitializer = b.CreateInsertValue(initializer, funcContext, 0, \"\")\n\tinitializer = b.CreateInsertValue(initializer, funcPtr, 1, \"\")\n\tinitializer = b.CreateInsertValue(initializer, llvm.ConstNamedStruct(globalLLVMType.StructElementTypes()[2], []llvm.Value{\n\t\tllvm.ConstInt(b.intType, uint64(id.Int64()), true),\n\t}), 2, \"\")\n\tglobal.SetInitializer(initializer)\n\n\t// Add debug info to the interrupt global.\n\tif b.Debug {\n\t\tpos := b.program.Fset.Position(instr.Pos())\n\t\tdiglobal := b.dibuilder.CreateGlobalVariableExpression(b.getDIFile(pos.Filename), llvm.DIGlobalVariableExpression{\n\t\t\tName:        \"interrupt\" + strconv.FormatInt(id.Int64(), 10),\n\t\t\tLinkageName: globalName,\n\t\t\tFile:        b.getDIFile(pos.Filename),\n\t\t\tLine:        pos.Line,\n\t\t\tType:        b.getDIType(globalType),\n\t\t\tExpr:        b.dibuilder.CreateExpression(nil),\n\t\t\tLocalToUnit: false,\n\t\t})\n\t\tglobal.AddMetadata(0, diglobal)\n\t}\n\n\t// Create the runtime/interrupt.Interrupt type. It is a struct with a single\n\t// member of type int.\n\tnum := llvm.ConstPtrToInt(global, b.intType)\n\tinterrupt := llvm.ConstNamedStruct(b.mod.GetTypeByName(\"runtime/interrupt.Interrupt\"), []llvm.Value{num})\n\n\t// Add dummy \"use\" call for AVR, because interrupts may be used even though\n\t// they are never referenced again. This is unlike Cortex-M or the RISC-V\n\t// PLIC where each interrupt must be enabled using the interrupt number, and\n\t// thus keeps the Interrupt object alive.\n\t// This call is removed during interrupt lowering.\n\tif strings.HasPrefix(b.Triple, \"avr\") {\n\t\tuseFn := b.mod.NamedFunction(\"runtime/interrupt.use\")\n\t\tif useFn.IsNil() {\n\t\t\tuseFnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{interrupt.Type()}, false)\n\t\t\tuseFn = llvm.AddFunction(b.mod, \"runtime/interrupt.use\", useFnType)\n\t\t}\n\t\tb.CreateCall(useFn.GlobalValueType(), useFn, []llvm.Value{interrupt}, \"\")\n\t}\n\n\treturn interrupt, nil\n}\n"
  },
  {
    "path": "compiler/intrinsics.go",
    "content": "package compiler\n\n// This file contains helper functions to create calls to LLVM intrinsics.\n\nimport (\n\t\"go/token\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// Define unimplemented intrinsic functions.\n//\n// Some functions are either normally implemented in Go assembly (like\n// sync/atomic functions) or intentionally left undefined to be implemented\n// directly in the compiler (like runtime/volatile functions). Either way, look\n// for these and implement them if this is the case.\nfunc (b *builder) defineIntrinsicFunction() {\n\tname := b.fn.RelString(nil)\n\tswitch {\n\tcase name == \"runtime.memcpy\" || name == \"runtime.memmove\":\n\t\tb.createMemoryCopyImpl()\n\tcase name == \"runtime.memzero\":\n\t\tb.createMemoryZeroImpl()\n\tcase name == \"runtime.stacksave\":\n\t\tb.createStackSaveImpl()\n\tcase name == \"runtime.KeepAlive\":\n\t\tb.createKeepAliveImpl()\n\tcase name == \"machine.keepAliveNoEscape\":\n\t\tb.createMachineKeepAliveImpl()\n\tcase strings.HasPrefix(name, \"runtime/volatile.Load\"):\n\t\tb.createVolatileLoad()\n\tcase strings.HasPrefix(name, \"runtime/volatile.Store\"):\n\t\tb.createVolatileStore()\n\tcase strings.HasPrefix(name, \"sync/atomic.\") && token.IsExported(b.fn.Name()):\n\t\tb.createFunctionStart(true)\n\t\treturnValue := b.createAtomicOp(b.fn.Name())\n\t\tif !returnValue.IsNil() {\n\t\t\tb.CreateRet(returnValue)\n\t\t} else {\n\t\t\tb.CreateRetVoid()\n\t\t}\n\t}\n}\n\n// createMemoryCopyImpl creates a call to a builtin LLVM memcpy or memmove\n// function, declaring this function if needed. These calls are treated\n// specially by optimization passes possibly resulting in better generated code,\n// and will otherwise be lowered to regular libc memcpy/memmove calls.\nfunc (b *builder) createMemoryCopyImpl() {\n\tb.createFunctionStart(true)\n\tfnName := \"llvm.\" + b.fn.Name() + \".p0.p0.i\" + strconv.Itoa(b.uintptrType.IntTypeWidth())\n\tllvmFn := b.mod.NamedFunction(fnName)\n\tif llvmFn.IsNil() {\n\t\tfnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.dataPtrType, b.dataPtrType, b.uintptrType, b.ctx.Int1Type()}, false)\n\t\tllvmFn = llvm.AddFunction(b.mod, fnName, fnType)\n\t}\n\tvar params []llvm.Value\n\tfor _, param := range b.fn.Params {\n\t\tparams = append(params, b.getValue(param, getPos(b.fn)))\n\t}\n\tparams = append(params, llvm.ConstInt(b.ctx.Int1Type(), 0, false))\n\tb.CreateCall(llvmFn.GlobalValueType(), llvmFn, params, \"\")\n\tb.CreateRetVoid()\n}\n\n// createMemoryZeroImpl creates calls to llvm.memset.* to zero a block of\n// memory, declaring the function if needed. These calls will be lowered to\n// regular libc memset calls if they aren't optimized out in a different way.\nfunc (b *builder) createMemoryZeroImpl() {\n\tb.createFunctionStart(true)\n\tllvmFn := b.getMemsetFunc()\n\tparams := []llvm.Value{\n\t\tb.getValue(b.fn.Params[0], getPos(b.fn)),\n\t\tllvm.ConstInt(b.ctx.Int8Type(), 0, false),\n\t\tb.getValue(b.fn.Params[1], getPos(b.fn)),\n\t\tllvm.ConstInt(b.ctx.Int1Type(), 0, false),\n\t}\n\tb.CreateCall(llvmFn.GlobalValueType(), llvmFn, params, \"\")\n\tb.CreateRetVoid()\n}\n\n// createStackSaveImpl creates a call to llvm.stacksave.p0 to read the current\n// stack pointer.\nfunc (b *builder) createStackSaveImpl() {\n\tb.createFunctionStart(true)\n\tsp := b.readStackPointer()\n\tb.CreateRet(sp)\n}\n\n// Return the llvm.memset.p0.i8 function declaration.\nfunc (c *compilerContext) getMemsetFunc() llvm.Value {\n\tfnName := \"llvm.memset.p0.i\" + strconv.Itoa(c.uintptrType.IntTypeWidth())\n\tllvmFn := c.mod.NamedFunction(fnName)\n\tif llvmFn.IsNil() {\n\t\tfnType := llvm.FunctionType(c.ctx.VoidType(), []llvm.Type{c.dataPtrType, c.ctx.Int8Type(), c.uintptrType, c.ctx.Int1Type()}, false)\n\t\tllvmFn = llvm.AddFunction(c.mod, fnName, fnType)\n\t}\n\treturn llvmFn\n}\n\n// createKeepAlive creates the runtime.KeepAlive function. It is implemented\n// using inline assembly.\nfunc (b *builder) createKeepAliveImpl() {\n\tb.createFunctionStart(true)\n\n\t// Get the underlying value of the interface value.\n\tinterfaceValue := b.getValue(b.fn.Params[0], getPos(b.fn))\n\tpointerValue := b.CreateExtractValue(interfaceValue, 1, \"\")\n\n\t// Create an equivalent of the following C code, which is basically just a\n\t// nop but ensures the pointerValue is kept alive:\n\t//\n\t//     __asm__ __volatile__(\"\" : : \"r\"(pointerValue))\n\t//\n\t// It should be portable to basically everything as the \"r\" register type\n\t// exists basically everywhere.\n\tasmType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.dataPtrType}, false)\n\tasmFn := llvm.InlineAsm(asmType, \"\", \"r\", true, false, 0, false)\n\tb.createCall(asmType, asmFn, []llvm.Value{pointerValue}, \"\")\n\n\tb.CreateRetVoid()\n}\n\n// createAbiEscapeImpl implements the generic internal/abi.Escape function. It\n// currently only supports pointer types.\nfunc (b *builder) createAbiEscapeImpl() {\n\tb.createFunctionStart(true)\n\n\t// The first parameter is assumed to be a pointer. This is checked at the\n\t// call site of createAbiEscapeImpl.\n\tpointerValue := b.getValue(b.fn.Params[0], getPos(b.fn))\n\n\t// Create an equivalent of the following C code, which is basically just a\n\t// nop but ensures the pointerValue is kept alive:\n\t//\n\t//     __asm__ __volatile__(\"\" : : \"r\"(pointerValue))\n\t//\n\t// It should be portable to basically everything as the \"r\" register type\n\t// exists basically everywhere.\n\tasmType := llvm.FunctionType(b.dataPtrType, []llvm.Type{b.dataPtrType}, false)\n\tasmFn := llvm.InlineAsm(asmType, \"\", \"=r,0\", true, false, 0, false)\n\tresult := b.createCall(asmType, asmFn, []llvm.Value{pointerValue}, \"\")\n\n\tb.CreateRet(result)\n}\n\n// Implement machine.keepAliveNoEscape, which makes sure the compiler keeps the\n// pointer parameter alive until this point (for GC).\nfunc (b *builder) createMachineKeepAliveImpl() {\n\tb.createFunctionStart(true)\n\tpointerValue := b.getValue(b.fn.Params[0], getPos(b.fn))\n\n\t// See createKeepAliveImpl for details.\n\tasmType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.dataPtrType}, false)\n\tasmFn := llvm.InlineAsm(asmType, \"\", \"r\", true, false, 0, false)\n\tb.createCall(asmType, asmFn, []llvm.Value{pointerValue}, \"\")\n\n\tb.CreateRetVoid()\n}\n\nvar mathToLLVMMapping = map[string]string{\n\t\"math.Ceil\":  \"llvm.ceil.f64\",\n\t\"math.Exp\":   \"llvm.exp.f64\",\n\t\"math.Exp2\":  \"llvm.exp2.f64\",\n\t\"math.Floor\": \"llvm.floor.f64\",\n\t\"math.Log\":   \"llvm.log.f64\",\n\t\"math.Sqrt\":  \"llvm.sqrt.f64\",\n\t\"math.Trunc\": \"llvm.trunc.f64\",\n}\n\n// defineMathOp defines a math function body as a call to a LLVM intrinsic,\n// instead of the regular Go implementation. This allows LLVM to reason about\n// the math operation and (depending on the architecture) allows it to lower the\n// operation to very fast floating point instructions. If this is not possible,\n// LLVM will emit a call to a libm function that implements the same operation.\n//\n// One example of an optimization that LLVM can do is to convert\n// float32(math.Sqrt(float64(v))) to a 32-bit floating point operation, which is\n// beneficial on architectures where 64-bit floating point operations are (much)\n// more expensive than 32-bit ones.\nfunc (b *builder) defineMathOp() {\n\tb.createFunctionStart(true)\n\tllvmName := mathToLLVMMapping[b.fn.RelString(nil)]\n\tif llvmName == \"\" {\n\t\tpanic(\"unreachable: unknown math operation\") // sanity check\n\t}\n\tllvmFn := b.mod.NamedFunction(llvmName)\n\tif llvmFn.IsNil() {\n\t\t// The intrinsic doesn't exist yet, so declare it.\n\t\t// At the moment, all supported intrinsics have the form \"double\n\t\t// foo(double %x)\" so we can hardcode the signature here.\n\t\tllvmType := llvm.FunctionType(b.ctx.DoubleType(), []llvm.Type{b.ctx.DoubleType()}, false)\n\t\tllvmFn = llvm.AddFunction(b.mod, llvmName, llvmType)\n\t}\n\t// Create a call to the intrinsic.\n\targs := make([]llvm.Value, len(b.fn.Params))\n\tfor i, param := range b.fn.Params {\n\t\targs[i] = b.getValue(param, getPos(b.fn))\n\t}\n\tresult := b.CreateCall(llvmFn.GlobalValueType(), llvmFn, args, \"\")\n\tb.CreateRet(result)\n}\n\n// Implement most math/bits functions.\n//\n// This implements all the functions that operate on bits. It does not yet\n// implement the arithmetic functions (like bits.Add), which also have LLVM\n// intrinsics.\nfunc (b *builder) defineMathBitsIntrinsic() bool {\n\tif b.fn.Pkg.Pkg.Path() != \"math/bits\" {\n\t\treturn false\n\t}\n\tname := b.fn.Name()\n\tswitch name {\n\tcase \"LeadingZeros\", \"LeadingZeros8\", \"LeadingZeros16\", \"LeadingZeros32\", \"LeadingZeros64\",\n\t\t\"TrailingZeros\", \"TrailingZeros8\", \"TrailingZeros16\", \"TrailingZeros32\", \"TrailingZeros64\":\n\t\tb.createFunctionStart(true)\n\t\tparam := b.getValue(b.fn.Params[0], b.fn.Pos())\n\t\tvalueType := param.Type()\n\t\tvar intrinsicName string\n\t\tif strings.HasPrefix(name, \"Leading\") { // LeadingZeros\n\t\t\tintrinsicName = \"llvm.ctlz.i\" + strconv.Itoa(valueType.IntTypeWidth())\n\t\t} else { // TrailingZeros\n\t\t\tintrinsicName = \"llvm.cttz.i\" + strconv.Itoa(valueType.IntTypeWidth())\n\t\t}\n\t\tllvmFn := b.mod.NamedFunction(intrinsicName)\n\t\tllvmFnType := llvm.FunctionType(valueType, []llvm.Type{valueType, b.ctx.Int1Type()}, false)\n\t\tif llvmFn.IsNil() {\n\t\t\tllvmFn = llvm.AddFunction(b.mod, intrinsicName, llvmFnType)\n\t\t}\n\t\tresult := b.createCall(llvmFnType, llvmFn, []llvm.Value{\n\t\t\tparam,\n\t\t\tllvm.ConstInt(b.ctx.Int1Type(), 0, false),\n\t\t}, \"\")\n\t\tresult = b.createZExtOrTrunc(result, b.intType)\n\t\tb.CreateRet(result)\n\t\treturn true\n\tcase \"Len\", \"Len8\", \"Len16\", \"Len32\", \"Len64\":\n\t\t// bits.Len can be implemented as:\n\t\t//     (unsafe.Sizeof(v) * 8) -  bits.LeadingZeros(n)\n\t\t// Not sure why this isn't already done in the standard library, as it\n\t\t// is much simpler than a lookup table.\n\t\tb.createFunctionStart(true)\n\t\tparam := b.getValue(b.fn.Params[0], b.fn.Pos())\n\t\tvalueType := param.Type()\n\t\tvalueBits := valueType.IntTypeWidth()\n\t\tintrinsicName := \"llvm.ctlz.i\" + strconv.Itoa(valueBits)\n\t\tllvmFn := b.mod.NamedFunction(intrinsicName)\n\t\tllvmFnType := llvm.FunctionType(valueType, []llvm.Type{valueType, b.ctx.Int1Type()}, false)\n\t\tif llvmFn.IsNil() {\n\t\t\tllvmFn = llvm.AddFunction(b.mod, intrinsicName, llvmFnType)\n\t\t}\n\t\tresult := b.createCall(llvmFnType, llvmFn, []llvm.Value{\n\t\t\tparam,\n\t\t\tllvm.ConstInt(b.ctx.Int1Type(), 0, false),\n\t\t}, \"\")\n\t\tresult = b.createZExtOrTrunc(result, b.intType)\n\t\tmaxLen := llvm.ConstInt(b.intType, uint64(valueBits), false) // number of bits in the value\n\t\tresult = b.CreateSub(maxLen, result, \"\")\n\t\tb.CreateRet(result)\n\t\treturn true\n\tcase \"OnesCount\", \"OnesCount8\", \"OnesCount16\", \"OnesCount32\", \"OnesCount64\":\n\t\tb.createFunctionStart(true)\n\t\tparam := b.getValue(b.fn.Params[0], b.fn.Pos())\n\t\tvalueType := param.Type()\n\t\tintrinsicName := \"llvm.ctpop.i\" + strconv.Itoa(valueType.IntTypeWidth())\n\t\tllvmFn := b.mod.NamedFunction(intrinsicName)\n\t\tllvmFnType := llvm.FunctionType(valueType, []llvm.Type{valueType}, false)\n\t\tif llvmFn.IsNil() {\n\t\t\tllvmFn = llvm.AddFunction(b.mod, intrinsicName, llvmFnType)\n\t\t}\n\t\tresult := b.createCall(llvmFnType, llvmFn, []llvm.Value{param}, \"\")\n\t\tresult = b.createZExtOrTrunc(result, b.intType)\n\t\tb.CreateRet(result)\n\t\treturn true\n\tcase \"Reverse\", \"Reverse8\", \"Reverse16\", \"Reverse32\", \"Reverse64\",\n\t\t\"ReverseBytes\", \"ReverseBytes16\", \"ReverseBytes32\", \"ReverseBytes64\":\n\t\tb.createFunctionStart(true)\n\t\tparam := b.getValue(b.fn.Params[0], b.fn.Pos())\n\t\tvalueType := param.Type()\n\t\tvar intrinsicName string\n\t\tif strings.HasPrefix(name, \"ReverseBytes\") {\n\t\t\tintrinsicName = \"llvm.bswap.i\" + strconv.Itoa(valueType.IntTypeWidth())\n\t\t} else { // Reverse\n\t\t\tintrinsicName = \"llvm.bitreverse.i\" + strconv.Itoa(valueType.IntTypeWidth())\n\t\t}\n\t\tllvmFn := b.mod.NamedFunction(intrinsicName)\n\t\tllvmFnType := llvm.FunctionType(valueType, []llvm.Type{valueType}, false)\n\t\tif llvmFn.IsNil() {\n\t\t\tllvmFn = llvm.AddFunction(b.mod, intrinsicName, llvmFnType)\n\t\t}\n\t\tresult := b.createCall(llvmFnType, llvmFn, []llvm.Value{param}, \"\")\n\t\tb.CreateRet(result)\n\t\treturn true\n\tcase \"RotateLeft\", \"RotateLeft8\", \"RotateLeft16\", \"RotateLeft32\", \"RotateLeft64\":\n\t\t// Warning: the documentation says these functions must be constant time.\n\t\t// I do not think LLVM guarantees this, but there's a good chance LLVM\n\t\t// already recognized the rotate instruction so it probably won't get\n\t\t// any _worse_ by implementing these rotate functions.\n\t\tb.createFunctionStart(true)\n\t\tx := b.getValue(b.fn.Params[0], b.fn.Pos())\n\t\tk := b.getValue(b.fn.Params[1], b.fn.Pos())\n\t\tvalueType := x.Type()\n\t\tintrinsicName := \"llvm.fshl.i\" + strconv.Itoa(valueType.IntTypeWidth())\n\t\tllvmFn := b.mod.NamedFunction(intrinsicName)\n\t\tllvmFnType := llvm.FunctionType(valueType, []llvm.Type{valueType, valueType, valueType}, false)\n\t\tif llvmFn.IsNil() {\n\t\t\tllvmFn = llvm.AddFunction(b.mod, intrinsicName, llvmFnType)\n\t\t}\n\t\tk = b.createZExtOrTrunc(k, valueType)\n\t\tresult := b.createCall(llvmFnType, llvmFn, []llvm.Value{x, x, k}, \"\")\n\t\tb.CreateRet(result)\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n"
  },
  {
    "path": "compiler/ircheck/check.go",
    "content": "// Package ircheck implements a checker for LLVM IR, that goes a bit further\n// than the regular LLVM IR verifier. Note that it checks different things, so\n// this is not a replacement for the LLVM verifier but does catch things that\n// the LLVM verifier doesn't catch.\npackage ircheck\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\n\t\"tinygo.org/x/go-llvm\"\n)\n\ntype checker struct {\n\tctx llvm.Context\n}\n\nfunc (c *checker) checkType(t llvm.Type, checked map[llvm.Type]struct{}, specials map[llvm.TypeKind]llvm.Type) error {\n\t// prevent infinite recursion for self-referential types\n\tif _, ok := checked[t]; ok {\n\t\treturn nil\n\t}\n\tchecked[t] = struct{}{}\n\n\t// check for any context mismatches\n\tswitch {\n\tcase t.Context() == c.ctx:\n\t\t// this is correct\n\tcase t.Context() == llvm.GlobalContext():\n\t\t// somewhere we accidentally used the global context instead of a real context\n\t\treturn fmt.Errorf(\"type %q uses global context\", t.String())\n\tdefault:\n\t\t// we used some other context by accident\n\t\treturn fmt.Errorf(\"type %q uses context %v instead of the main context %v\", t.String(), t.Context(), c.ctx)\n\t}\n\n\t// if this is a composite type, check the components of the type\n\tswitch t.TypeKind() {\n\tcase llvm.VoidTypeKind, llvm.LabelTypeKind, llvm.TokenTypeKind, llvm.MetadataTypeKind:\n\t\t// there should only be one of any of these\n\t\tif s, ok := specials[t.TypeKind()]; !ok {\n\t\t\tspecials[t.TypeKind()] = t\n\t\t} else if s != t {\n\t\t\treturn fmt.Errorf(\"duplicate special type %q: %v and %v\", t.TypeKind().String(), t, s)\n\t\t}\n\tcase llvm.FloatTypeKind, llvm.DoubleTypeKind, llvm.X86_FP80TypeKind, llvm.FP128TypeKind, llvm.PPC_FP128TypeKind:\n\t\t// floating point numbers are primitives - nothing to recurse\n\tcase llvm.IntegerTypeKind:\n\t\t// integers are primitives - nothing to recurse\n\tcase llvm.FunctionTypeKind:\n\t\t// check arguments and return(s)\n\t\tfor i, v := range t.ParamTypes() {\n\t\t\tif err := c.checkType(v, checked, specials); err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to verify argument %d of type %s: %s\", i, t.String(), err.Error())\n\t\t\t}\n\t\t}\n\t\tif err := c.checkType(t.ReturnType(), checked, specials); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to verify return type of type %s: %s\", t.String(), err.Error())\n\t\t}\n\tcase llvm.StructTypeKind:\n\t\t// check all elements\n\t\tfor i, v := range t.StructElementTypes() {\n\t\t\tif err := c.checkType(v, checked, specials); err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to verify type of field %d of struct type %s: %s\", i, t.String(), err.Error())\n\t\t\t}\n\t\t}\n\tcase llvm.ArrayTypeKind:\n\t\t// check element type\n\t\tif err := c.checkType(t.ElementType(), checked, specials); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to verify element type of array type %s: %s\", t.String(), err.Error())\n\t\t}\n\tcase llvm.PointerTypeKind:\n\t\t// Pointers can't be checked in an opaque pointer world.\n\tcase llvm.VectorTypeKind:\n\t\t// check element type\n\t\tif err := c.checkType(t.ElementType(), checked, specials); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to verify element type of vector type %s: %s\", t.String(), err.Error())\n\t\t}\n\tdefault:\n\t\treturn fmt.Errorf(\"unrecognized kind %q of type %s\", t.TypeKind(), t.String())\n\t}\n\n\treturn nil\n}\n\nfunc (c *checker) checkValue(v llvm.Value, types map[llvm.Type]struct{}, specials map[llvm.TypeKind]llvm.Type) error {\n\t// check type\n\tif err := c.checkType(v.Type(), types, specials); err != nil {\n\t\treturn fmt.Errorf(\"failed to verify type of value: %s\", err.Error())\n\t}\n\n\t// check if this is an undefined void\n\tif v.IsUndef() && v.Type().TypeKind() == llvm.VoidTypeKind {\n\t\treturn errors.New(\"encountered undefined void value\")\n\t}\n\n\treturn nil\n}\n\nfunc (c *checker) checkInstruction(inst llvm.Value, types map[llvm.Type]struct{}, specials map[llvm.TypeKind]llvm.Type) error {\n\t// check value properties\n\tif err := c.checkValue(inst, types, specials); err != nil {\n\t\treturn errorAt(inst, err.Error())\n\t}\n\n\t// The alloca instruction can be present in every basic block. However,\n\t// allocas in basic blocks other than the entry basic block have a number of\n\t// problems:\n\t//   * They are hard to optimize, leading to potential missed optimizations.\n\t//   * They may cause stack overflows in loops that would otherwise be\n\t//     innocent.\n\t//   * They cause extra code to be generated, because it requires the use of\n\t//     a frame pointer.\n\t//   * Perhaps most importantly, the coroutine lowering pass of LLVM (as of\n\t//     LLVM 9) cannot deal with these allocas:\n\t//     https://llvm.org/docs/Coroutines.html\n\t// Therefore, alloca instructions should be limited to the entry block.\n\tif !inst.IsAAllocaInst().IsNil() {\n\t\tif inst.InstructionParent() != inst.InstructionParent().Parent().EntryBasicBlock() {\n\t\t\treturn errorAt(inst, \"internal error: non-static alloca\")\n\t\t}\n\t}\n\n\t// check operands\n\tfor i := 0; i < inst.OperandsCount(); i++ {\n\t\tif err := c.checkValue(inst.Operand(i), types, specials); err != nil {\n\t\t\treturn errorAt(inst, fmt.Sprintf(\"failed to validate operand %d of instruction %q: %s\", i, inst.Name(), err.Error()))\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (c *checker) checkBasicBlock(bb llvm.BasicBlock, types map[llvm.Type]struct{}, specials map[llvm.TypeKind]llvm.Type) []error {\n\t// check basic block value and type\n\tvar errs []error\n\tif err := c.checkValue(bb.AsValue(), types, specials); err != nil {\n\t\terrs = append(errs, errorAt(bb.Parent(), fmt.Sprintf(\"failed to validate value of basic block %s: %v\", bb.AsValue().Name(), err)))\n\t}\n\n\t// check instructions\n\tfor inst := bb.FirstInstruction(); !inst.IsNil(); inst = llvm.NextInstruction(inst) {\n\t\tif err := c.checkInstruction(inst, types, specials); err != nil {\n\t\t\terrs = append(errs, err)\n\t\t}\n\t}\n\n\treturn errs\n}\n\nfunc (c *checker) checkFunction(fn llvm.Value, types map[llvm.Type]struct{}, specials map[llvm.TypeKind]llvm.Type) []error {\n\t// check function value and type\n\tvar errs []error\n\tif err := c.checkValue(fn, types, specials); err != nil {\n\t\terrs = append(errs, fmt.Errorf(\"failed to validate value of function %s: %s\", fn.Name(), err.Error()))\n\t}\n\n\t// check basic blocks\n\tfor bb := fn.FirstBasicBlock(); !bb.IsNil(); bb = llvm.NextBasicBlock(bb) {\n\t\terrs = append(errs, c.checkBasicBlock(bb, types, specials)...)\n\t}\n\n\treturn errs\n}\n\n// Module checks the given module and returns a slice of error, if there are\n// any.\nfunc Module(mod llvm.Module) []error {\n\t// check for any context mismatches\n\tvar errs []error\n\tc := checker{\n\t\tctx: mod.Context(),\n\t}\n\tif c.ctx == llvm.GlobalContext() {\n\t\t// somewhere we accidentally used the global context instead of a real context\n\t\terrs = append(errs, errors.New(\"module uses global context\"))\n\t}\n\n\ttypes := map[llvm.Type]struct{}{}\n\tspecials := map[llvm.TypeKind]llvm.Type{}\n\tfor fn := mod.FirstFunction(); !fn.IsNil(); fn = llvm.NextFunction(fn) {\n\t\terrs = append(errs, c.checkFunction(fn, types, specials)...)\n\t}\n\tfor g := mod.FirstGlobal(); !g.IsNil(); g = llvm.NextGlobal(g) {\n\t\tif err := c.checkValue(g, types, specials); err != nil {\n\t\t\terrs = append(errs, fmt.Errorf(\"failed to verify global %s of module: %s\", g.Name(), err.Error()))\n\t\t}\n\t}\n\n\treturn errs\n}\n"
  },
  {
    "path": "compiler/ircheck/errors.go",
    "content": "package ircheck\n\nimport (\n\t\"go/scanner\"\n\t\"go/token\"\n\t\"path/filepath\"\n\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// errorAt returns an error value at the location of the instruction.\n// The location information may not be complete as it depends on debug\n// information in the IR.\nfunc errorAt(inst llvm.Value, msg string) scanner.Error {\n\treturn scanner.Error{\n\t\tPos: getPosition(inst),\n\t\tMsg: msg,\n\t}\n}\n\n// getPosition returns the position information for the given value, as far as\n// it is available.\nfunc getPosition(val llvm.Value) token.Position {\n\tif !val.IsAInstruction().IsNil() {\n\t\tloc := val.InstructionDebugLoc()\n\t\tif loc.IsNil() {\n\t\t\treturn token.Position{}\n\t\t}\n\t\tfile := loc.LocationScope().ScopeFile()\n\t\treturn token.Position{\n\t\t\tFilename: filepath.Join(file.FileDirectory(), file.FileFilename()),\n\t\t\tLine:     int(loc.LocationLine()),\n\t\t\tColumn:   int(loc.LocationColumn()),\n\t\t}\n\t} else if !val.IsAFunction().IsNil() {\n\t\tloc := val.Subprogram()\n\t\tif loc.IsNil() {\n\t\t\treturn token.Position{}\n\t\t}\n\t\tfile := loc.ScopeFile()\n\t\treturn token.Position{\n\t\t\tFilename: filepath.Join(file.FileDirectory(), file.FileFilename()),\n\t\t\tLine:     int(loc.SubprogramLine()),\n\t\t}\n\t} else {\n\t\treturn token.Position{}\n\t}\n}\n"
  },
  {
    "path": "compiler/llvm.go",
    "content": "package compiler\n\nimport (\n\t\"fmt\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"math/big\"\n\t\"strings\"\n\n\t\"github.com/tinygo-org/tinygo/compileopts\"\n\t\"github.com/tinygo-org/tinygo/compiler/llvmutil\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// This file contains helper functions for LLVM that are not exposed in the Go\n// bindings.\n\n// createTemporaryAlloca creates a new alloca in the entry block and adds\n// lifetime start information in the IR signalling that the alloca won't be used\n// before this point.\n//\n// This is useful for creating temporary allocas for intrinsics. Don't forget to\n// end the lifetime using emitLifetimeEnd after you're done with it.\nfunc (b *builder) createTemporaryAlloca(t llvm.Type, name string) (alloca, size llvm.Value) {\n\treturn llvmutil.CreateTemporaryAlloca(b.Builder, b.mod, t, name)\n}\n\n// insertBasicBlock inserts a new basic block after the current basic block.\n// This is useful when inserting new basic blocks while converting a\n// *ssa.BasicBlock to a llvm.BasicBlock and the LLVM basic block needs some\n// extra blocks.\n// It does not update b.blockExits, this must be done by the caller.\nfunc (b *builder) insertBasicBlock(name string) llvm.BasicBlock {\n\tcurrentBB := b.Builder.GetInsertBlock()\n\tnextBB := llvm.NextBasicBlock(currentBB)\n\tif nextBB.IsNil() {\n\t\t// Last basic block in the function, so add one to the end.\n\t\treturn b.ctx.AddBasicBlock(b.llvmFn, name)\n\t}\n\t// Insert a basic block before the next basic block - that is, at the\n\t// current insert location.\n\treturn b.ctx.InsertBasicBlock(nextBB, name)\n}\n\n// emitLifetimeEnd signals the end of an (alloca) lifetime by calling the\n// llvm.lifetime.end intrinsic. It is commonly used together with\n// createTemporaryAlloca.\nfunc (b *builder) emitLifetimeEnd(ptr, size llvm.Value) {\n\tllvmutil.EmitLifetimeEnd(b.Builder, b.mod, ptr, size)\n}\n\n// emitPointerPack packs the list of values into a single pointer value using\n// bitcasts, or else allocates a value on the heap if it cannot be packed in the\n// pointer value directly. It returns the pointer with the packed data.\n// If the values are all constants, they are be stored in a constant global and\n// deduplicated.\nfunc (b *builder) emitPointerPack(values []llvm.Value) llvm.Value {\n\tvalueTypes := make([]llvm.Type, len(values))\n\tfor i, value := range values {\n\t\tvalueTypes[i] = value.Type()\n\t}\n\tpackedType := b.ctx.StructType(valueTypes, false)\n\n\t// Allocate memory for the packed data.\n\tsize := b.targetData.TypeAllocSize(packedType)\n\tif size == 0 {\n\t\treturn llvm.ConstPointerNull(b.dataPtrType)\n\t} else if len(values) == 1 && values[0].Type().TypeKind() == llvm.PointerTypeKind {\n\t\treturn values[0]\n\t} else if size <= b.targetData.TypeAllocSize(b.dataPtrType) {\n\t\t// Packed data fits in a pointer, so store it directly inside the\n\t\t// pointer.\n\t\tif len(values) == 1 && values[0].Type().TypeKind() == llvm.IntegerTypeKind {\n\t\t\t// Try to keep this cast in SSA form.\n\t\t\treturn b.CreateIntToPtr(values[0], b.dataPtrType, \"pack.int\")\n\t\t}\n\n\t\t// Because packedType is a struct and we have to cast it to a *i8, store\n\t\t// it in a *i8 alloca first and load the *i8 value from there. This is\n\t\t// effectively a bitcast.\n\t\tpackedAlloc, _ := b.createTemporaryAlloca(b.dataPtrType, \"\")\n\n\t\tif size < b.targetData.TypeAllocSize(b.dataPtrType) {\n\t\t\t// The alloca is bigger than the value that will be stored in it.\n\t\t\t// To avoid having some bits undefined, zero the alloca first.\n\t\t\t// Hopefully this will get optimized away.\n\t\t\tb.CreateStore(llvm.ConstNull(b.dataPtrType), packedAlloc)\n\t\t}\n\n\t\t// Store all values in the alloca.\n\t\tfor i, value := range values {\n\t\t\tindices := []llvm.Value{\n\t\t\t\tllvm.ConstInt(b.ctx.Int32Type(), 0, false),\n\t\t\t\tllvm.ConstInt(b.ctx.Int32Type(), uint64(i), false),\n\t\t\t}\n\t\t\tgep := b.CreateInBoundsGEP(packedType, packedAlloc, indices, \"\")\n\t\t\tb.CreateStore(value, gep)\n\t\t}\n\n\t\t// Load value (the *i8) from the alloca.\n\t\tresult := b.CreateLoad(b.dataPtrType, packedAlloc, \"\")\n\n\t\t// End the lifetime of the alloca, to help the optimizer.\n\t\tpackedSize := llvm.ConstInt(b.ctx.Int64Type(), b.targetData.TypeAllocSize(packedAlloc.Type()), false)\n\t\tb.emitLifetimeEnd(packedAlloc, packedSize)\n\n\t\treturn result\n\t} else {\n\t\t// Check if the values are all constants.\n\t\tconstant := true\n\t\tfor _, v := range values {\n\t\t\tif !v.IsConstant() {\n\t\t\t\tconstant = false\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif constant {\n\t\t\t// The data is known at compile time, so store it in a constant global.\n\t\t\t// The global address is marked as unnamed, which allows LLVM to merge duplicates.\n\t\t\tglobal := llvm.AddGlobal(b.mod, packedType, b.pkg.Path()+\"$pack\")\n\t\t\tglobal.SetInitializer(b.ctx.ConstStruct(values, false))\n\t\t\tglobal.SetGlobalConstant(true)\n\t\t\tglobal.SetUnnamedAddr(true)\n\t\t\tglobal.SetLinkage(llvm.InternalLinkage)\n\t\t\treturn global\n\t\t}\n\n\t\t// Packed data is bigger than a pointer, so allocate it on the heap.\n\t\tsizeValue := llvm.ConstInt(b.uintptrType, size, false)\n\t\talign := b.targetData.ABITypeAlignment(packedType)\n\t\talloc := b.mod.NamedFunction(\"runtime.alloc\")\n\t\tpackedAlloc := b.CreateCall(alloc.GlobalValueType(), alloc, []llvm.Value{\n\t\t\tsizeValue,\n\t\t\tllvm.ConstNull(b.dataPtrType),\n\t\t\tllvm.Undef(b.dataPtrType), // unused context parameter\n\t\t}, \"\")\n\t\tpackedAlloc.AddCallSiteAttribute(0, b.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"align\"), uint64(align)))\n\t\tif b.NeedsStackObjects {\n\t\t\tb.trackPointer(packedAlloc)\n\t\t}\n\n\t\t// Store all values in the heap pointer.\n\t\tfor i, value := range values {\n\t\t\tindices := []llvm.Value{\n\t\t\t\tllvm.ConstInt(b.ctx.Int32Type(), 0, false),\n\t\t\t\tllvm.ConstInt(b.ctx.Int32Type(), uint64(i), false),\n\t\t\t}\n\t\t\tgep := b.CreateInBoundsGEP(packedType, packedAlloc, indices, \"\")\n\t\t\tb.CreateStore(value, gep)\n\t\t}\n\n\t\t// Return the original heap allocation pointer, which already is an *i8.\n\t\treturn packedAlloc\n\t}\n}\n\n// emitPointerUnpack extracts a list of values packed using emitPointerPack.\nfunc (b *builder) emitPointerUnpack(ptr llvm.Value, valueTypes []llvm.Type) []llvm.Value {\n\tpackedType := b.ctx.StructType(valueTypes, false)\n\n\t// Get a correctly-typed pointer to the packed data.\n\tvar packedAlloc llvm.Value\n\tneedsLifetimeEnd := false\n\tsize := b.targetData.TypeAllocSize(packedType)\n\tif size == 0 {\n\t\t// No data to unpack.\n\t} else if len(valueTypes) == 1 && valueTypes[0].TypeKind() == llvm.PointerTypeKind {\n\t\t// A single pointer is always stored directly.\n\t\treturn []llvm.Value{ptr}\n\t} else if size <= b.targetData.TypeAllocSize(b.dataPtrType) {\n\t\t// Packed data stored directly in pointer.\n\t\tif len(valueTypes) == 1 && valueTypes[0].TypeKind() == llvm.IntegerTypeKind {\n\t\t\t// Keep this cast in SSA form.\n\t\t\treturn []llvm.Value{b.CreatePtrToInt(ptr, valueTypes[0], \"unpack.int\")}\n\t\t}\n\t\t// Fallback: load it using an alloca.\n\t\tpackedAlloc, _ = b.createTemporaryAlloca(b.dataPtrType, \"unpack.raw.alloc\")\n\t\tb.CreateStore(ptr, packedAlloc)\n\t\tneedsLifetimeEnd = true\n\t} else {\n\t\t// Packed data stored on the heap.\n\t\tpackedAlloc = ptr\n\t}\n\t// Load each value from the packed data.\n\tvalues := make([]llvm.Value, len(valueTypes))\n\tfor i, valueType := range valueTypes {\n\t\tif b.targetData.TypeAllocSize(valueType) == 0 {\n\t\t\t// This value has length zero, so there's nothing to load.\n\t\t\tvalues[i] = llvm.ConstNull(valueType)\n\t\t\tcontinue\n\t\t}\n\t\tindices := []llvm.Value{\n\t\t\tllvm.ConstInt(b.ctx.Int32Type(), 0, false),\n\t\t\tllvm.ConstInt(b.ctx.Int32Type(), uint64(i), false),\n\t\t}\n\t\tgep := b.CreateInBoundsGEP(packedType, packedAlloc, indices, \"\")\n\t\tvalues[i] = b.CreateLoad(valueType, gep, \"\")\n\t}\n\tif needsLifetimeEnd {\n\t\tallocSize := llvm.ConstInt(b.ctx.Int64Type(), b.targetData.TypeAllocSize(b.uintptrType), false)\n\t\tb.emitLifetimeEnd(packedAlloc, allocSize)\n\t}\n\treturn values\n}\n\n// makeGlobalArray creates a new LLVM global with the given name and integers as\n// contents, and returns the global and initializer type.\n// Note that it is left with the default linkage etc., you should set\n// linkage/constant/etc properties yourself.\nfunc (c *compilerContext) makeGlobalArray(buf []byte, name string, elementType llvm.Type) (llvm.Type, llvm.Value) {\n\tglobalType := llvm.ArrayType(elementType, len(buf))\n\tglobal := llvm.AddGlobal(c.mod, globalType, name)\n\tvalue := llvm.Undef(globalType)\n\tfor i := 0; i < len(buf); i++ {\n\t\tch := uint64(buf[i])\n\t\tvalue = c.builder.CreateInsertValue(value, llvm.ConstInt(elementType, ch, false), i, \"\")\n\t}\n\tglobal.SetInitializer(value)\n\treturn globalType, global\n}\n\n// createObjectLayout returns a LLVM value (of type i8*) that describes where\n// there are pointers in the type t. If all the data fits in a word, it is\n// returned as a word. Otherwise it will store the data in a global.\n//\n// The value contains two pieces of information: the length of the object and\n// which words contain a pointer (indicated by setting the given bit to 1). For\n// arrays, only the element is stored. This works because the GC knows the\n// object size and can therefore know how this value is repeated in the object.\n//\n// For details on what's in this value, see src/runtime/gc_precise.go.\nfunc (c *compilerContext) createObjectLayout(t llvm.Type, pos token.Pos) llvm.Value {\n\t// Use the element type for arrays. This works even for nested arrays.\n\tfor {\n\t\tkind := t.TypeKind()\n\t\tif kind == llvm.ArrayTypeKind {\n\t\t\tt = t.ElementType()\n\t\t\tcontinue\n\t\t}\n\t\tif kind == llvm.StructTypeKind {\n\t\t\tfields := t.StructElementTypes()\n\t\t\tif len(fields) == 1 {\n\t\t\t\tt = fields[0]\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tbreak\n\t}\n\n\t// Do a few checks to see whether we need to generate any object layout\n\t// information at all.\n\tobjectSizeBytes := c.targetData.TypeAllocSize(t)\n\tpointerSize := c.targetData.TypeAllocSize(c.dataPtrType)\n\tpointerAlignment := c.targetData.PrefTypeAlignment(c.dataPtrType)\n\tif objectSizeBytes < pointerSize {\n\t\t// Too small to contain a pointer.\n\t\tlayout := (uint64(1) << 1) | 1\n\t\treturn llvm.ConstIntToPtr(llvm.ConstInt(c.uintptrType, layout, false), c.dataPtrType)\n\t}\n\tbitmap := c.getPointerBitmap(t, pos)\n\tif bitmap.BitLen() == 0 {\n\t\t// There are no pointers in this type, so we can simplify the layout.\n\t\t// TODO: this can be done in many other cases, e.g. when allocating an\n\t\t// array (like [4][]byte, which repeats a slice 4 times).\n\t\tlayout := (uint64(1) << 1) | 1\n\t\treturn llvm.ConstIntToPtr(llvm.ConstInt(c.uintptrType, layout, false), c.dataPtrType)\n\t}\n\tif objectSizeBytes%uint64(pointerAlignment) != 0 {\n\t\t// This shouldn't happen except for packed structs, which aren't\n\t\t// currently used.\n\t\tc.addError(pos, \"internal error: unexpected object size for object with pointer field\")\n\t\treturn llvm.ConstNull(c.dataPtrType)\n\t}\n\tobjectSizeWords := objectSizeBytes / uint64(pointerAlignment)\n\n\tpointerBits := pointerSize * 8\n\tvar sizeFieldBits uint64\n\tswitch pointerBits {\n\tcase 16:\n\t\tsizeFieldBits = 4\n\tcase 32:\n\t\tsizeFieldBits = 5\n\tcase 64:\n\t\tsizeFieldBits = 6\n\tdefault:\n\t\tpanic(\"unknown pointer size\")\n\t}\n\tlayoutFieldBits := pointerBits - 1 - sizeFieldBits\n\n\t// Try to emit the value as an inline integer. This is possible in most\n\t// cases.\n\tif objectSizeWords < layoutFieldBits {\n\t\t// If it can be stored directly in the pointer value, do so.\n\t\t// The runtime knows that if the least significant bit of the pointer is\n\t\t// set, the pointer contains the value itself.\n\t\tlayout := bitmap.Uint64()<<(sizeFieldBits+1) | (objectSizeWords << 1) | 1\n\t\treturn llvm.ConstIntToPtr(llvm.ConstInt(c.uintptrType, layout, false), c.dataPtrType)\n\t}\n\n\t// Unfortunately, the object layout is too big to fit in a pointer-sized\n\t// integer. Store it in a global instead.\n\n\t// Try first whether the global already exists. All objects with a\n\t// particular name have the same type, so this is possible.\n\tglobalName := \"runtime/gc.layout:\" + fmt.Sprintf(\"%d-%0*x\", objectSizeWords, (objectSizeWords+15)/16, bitmap)\n\tglobal := c.mod.NamedGlobal(globalName)\n\tif !global.IsNil() {\n\t\treturn global\n\t}\n\n\t// Create the global initializer.\n\tbitmapBytes := make([]byte, int(objectSizeWords+7)/8)\n\tbitmap.FillBytes(bitmapBytes)\n\treverseBytes(bitmapBytes) // big-endian to little-endian\n\tvar bitmapByteValues []llvm.Value\n\tfor _, b := range bitmapBytes {\n\t\tbitmapByteValues = append(bitmapByteValues, llvm.ConstInt(c.ctx.Int8Type(), uint64(b), false))\n\t}\n\tinitializer := c.ctx.ConstStruct([]llvm.Value{\n\t\tllvm.ConstInt(c.uintptrType, objectSizeWords, false),\n\t\tllvm.ConstArray(c.ctx.Int8Type(), bitmapByteValues),\n\t}, false)\n\n\tglobal = llvm.AddGlobal(c.mod, initializer.Type(), globalName)\n\tglobal.SetInitializer(initializer)\n\tglobal.SetUnnamedAddr(true)\n\tglobal.SetGlobalConstant(true)\n\tglobal.SetLinkage(llvm.LinkOnceODRLinkage)\n\tif c.targetData.PrefTypeAlignment(c.uintptrType) < 2 {\n\t\t// AVR doesn't have alignment by default.\n\t\tglobal.SetAlignment(2)\n\t}\n\tif c.Debug && pos != token.NoPos {\n\t\t// Creating a fake global so that the value can be inspected in GDB.\n\t\t// For example, the layout for strings.stringFinder (as of Go version\n\t\t// 1.15) has the following type according to GDB:\n\t\t//   type = struct {\n\t\t//       uintptr numBits;\n\t\t//       uint8 data[33];\n\t\t//   }\n\t\t// ...that's sort of a mixed C/Go type, but it is readable. More\n\t\t// importantly, these object layout globals can be read and printed by\n\t\t// GDB which may be useful for debugging.\n\t\tposition := c.program.Fset.Position(pos)\n\t\tdiglobal := c.dibuilder.CreateGlobalVariableExpression(c.difiles[position.Filename], llvm.DIGlobalVariableExpression{\n\t\t\tName: globalName,\n\t\t\tFile: c.getDIFile(position.Filename),\n\t\t\tLine: position.Line,\n\t\t\tType: c.getDIType(types.NewStruct([]*types.Var{\n\t\t\t\ttypes.NewVar(pos, nil, \"numBits\", types.Typ[types.Uintptr]),\n\t\t\t\ttypes.NewVar(pos, nil, \"data\", types.NewArray(types.Typ[types.Byte], int64(len(bitmapByteValues)))),\n\t\t\t}, nil)),\n\t\t\tLocalToUnit: false,\n\t\t\tExpr:        c.dibuilder.CreateExpression(nil),\n\t\t})\n\t\tglobal.AddMetadata(0, diglobal)\n\t}\n\n\treturn global\n}\n\n// getPointerBitmap scans the given LLVM type for pointers and sets bits in a\n// bigint at the word offset that contains a pointer. This scan is recursive.\nfunc (c *compilerContext) getPointerBitmap(typ llvm.Type, pos token.Pos) *big.Int {\n\talignment := c.targetData.PrefTypeAlignment(c.dataPtrType)\n\tswitch typ.TypeKind() {\n\tcase llvm.IntegerTypeKind, llvm.FloatTypeKind, llvm.DoubleTypeKind:\n\t\treturn big.NewInt(0)\n\tcase llvm.PointerTypeKind:\n\t\treturn big.NewInt(1)\n\tcase llvm.StructTypeKind:\n\t\tptrs := big.NewInt(0)\n\t\tfor i, subtyp := range typ.StructElementTypes() {\n\t\t\tsubptrs := c.getPointerBitmap(subtyp, pos)\n\t\t\tif subptrs.BitLen() == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\toffset := c.targetData.ElementOffset(typ, i)\n\t\t\tif offset%uint64(alignment) != 0 {\n\t\t\t\t// This error will let the compilation fail, but by continuing\n\t\t\t\t// the error can still easily be shown.\n\t\t\t\tc.addError(pos, \"internal error: allocated struct contains unaligned pointer\")\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tsubptrs.Lsh(subptrs, uint(offset)/uint(alignment))\n\t\t\tptrs.Or(ptrs, subptrs)\n\t\t}\n\t\treturn ptrs\n\tcase llvm.ArrayTypeKind:\n\t\tsubtyp := typ.ElementType()\n\t\tsubptrs := c.getPointerBitmap(subtyp, pos)\n\t\tptrs := big.NewInt(0)\n\t\tif subptrs.BitLen() == 0 {\n\t\t\treturn ptrs\n\t\t}\n\t\telementSize := c.targetData.TypeAllocSize(subtyp)\n\t\tif elementSize%uint64(alignment) != 0 {\n\t\t\t// This error will let the compilation fail (but continues so that\n\t\t\t// other errors can be shown).\n\t\t\tc.addError(pos, \"internal error: allocated array contains unaligned pointer\")\n\t\t\treturn ptrs\n\t\t}\n\t\tfor i := 0; i < typ.ArrayLength(); i++ {\n\t\t\tptrs.Lsh(ptrs, uint(elementSize)/uint(alignment))\n\t\t\tptrs.Or(ptrs, subptrs)\n\t\t}\n\t\treturn ptrs\n\tdefault:\n\t\t// Should not happen.\n\t\tpanic(\"unknown LLVM type\")\n\t}\n}\n\n// archFamily returns the architecture from the LLVM triple but with some\n// architecture names (\"armv6\", \"thumbv7m\", etc) merged into a single\n// architecture name (\"arm\").\nfunc (c *compilerContext) archFamily() string {\n\treturn compileopts.CanonicalArchName(c.Triple)\n}\n\n// isThumb returns whether we're in ARM or in Thumb mode. It panics if the\n// features string is not one for an ARM architecture.\nfunc (c *compilerContext) isThumb() bool {\n\tvar isThumb, isNotThumb bool\n\tfor _, feature := range strings.Split(c.Features, \",\") {\n\t\tif feature == \"+thumb-mode\" {\n\t\t\tisThumb = true\n\t\t}\n\t\tif feature == \"-thumb-mode\" {\n\t\t\tisNotThumb = true\n\t\t}\n\t}\n\tif isThumb == isNotThumb {\n\t\tpanic(\"unexpected feature flags\")\n\t}\n\treturn isThumb\n}\n\n// readStackPointer emits a LLVM intrinsic call that returns the current stack\n// pointer as an *i8.\nfunc (b *builder) readStackPointer() llvm.Value {\n\tname := \"llvm.stacksave.p0\"\n\tif llvmutil.Version() < 18 {\n\t\tname = \"llvm.stacksave\" // backwards compatibility with LLVM 17 and below\n\t}\n\tstacksave := b.mod.NamedFunction(name)\n\tif stacksave.IsNil() {\n\t\tfnType := llvm.FunctionType(b.dataPtrType, nil, false)\n\t\tstacksave = llvm.AddFunction(b.mod, name, fnType)\n\t}\n\treturn b.CreateCall(stacksave.GlobalValueType(), stacksave, nil, \"\")\n}\n\n// writeStackPointer emits a LLVM intrinsic call that updates the current stack\n// pointer.\nfunc (b *builder) writeStackPointer(sp llvm.Value) {\n\tname := \"llvm.stackrestore.p0\"\n\tif llvmutil.Version() < 18 {\n\t\tname = \"llvm.stackrestore\" // backwards compatibility with LLVM 17 and below\n\t}\n\tstackrestore := b.mod.NamedFunction(name)\n\tif stackrestore.IsNil() {\n\t\tfnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.dataPtrType}, false)\n\t\tstackrestore = llvm.AddFunction(b.mod, name, fnType)\n\t}\n\tb.CreateCall(stackrestore.GlobalValueType(), stackrestore, []llvm.Value{sp}, \"\")\n}\n\n// createZExtOrTrunc lets the input value fit in the output type bits, by zero\n// extending or truncating the integer.\nfunc (b *builder) createZExtOrTrunc(value llvm.Value, t llvm.Type) llvm.Value {\n\tvalueBits := value.Type().IntTypeWidth()\n\tresultBits := t.IntTypeWidth()\n\tif valueBits > resultBits {\n\t\tvalue = b.CreateTrunc(value, t, \"\")\n\t} else if valueBits < resultBits {\n\t\tvalue = b.CreateZExt(value, t, \"\")\n\t}\n\treturn value\n}\n\n// Reverse a slice of bytes. From the wiki:\n// https://github.com/golang/go/wiki/SliceTricks#reversing\nfunc reverseBytes(buf []byte) {\n\tfor i := len(buf)/2 - 1; i >= 0; i-- {\n\t\topp := len(buf) - 1 - i\n\t\tbuf[i], buf[opp] = buf[opp], buf[i]\n\t}\n}\n"
  },
  {
    "path": "compiler/llvmutil/llvm.go",
    "content": "// Package llvmutil contains utility functions used across multiple compiler\n// packages. For example, they may be used by both the compiler package and\n// transformation packages.\n//\n// Normally, utility packages are avoided. However, in this case, the utility\n// functions are non-trivial and hard to get right. Copying them to multiple\n// places would be a big risk if only one of them is updated.\npackage llvmutil\n\nimport (\n\t\"encoding/binary\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// CreateEntryBlockAlloca creates a new alloca in the entry block, even though\n// the IR builder is located elsewhere. It assumes that the insert point is\n// at the end of the current block.\nfunc CreateEntryBlockAlloca(builder llvm.Builder, t llvm.Type, name string) llvm.Value {\n\tcurrentBlock := builder.GetInsertBlock()\n\tentryBlock := currentBlock.Parent().EntryBasicBlock()\n\tif entryBlock.FirstInstruction().IsNil() {\n\t\tbuilder.SetInsertPointAtEnd(entryBlock)\n\t} else {\n\t\tbuilder.SetInsertPointBefore(entryBlock.FirstInstruction())\n\t}\n\talloca := builder.CreateAlloca(t, name)\n\tbuilder.SetInsertPointAtEnd(currentBlock)\n\treturn alloca\n}\n\n// CreateTemporaryAlloca creates a new alloca in the entry block and adds\n// lifetime start information in the IR signalling that the alloca won't be used\n// before this point.\n//\n// This is useful for creating temporary allocas for intrinsics. Don't forget to\n// end the lifetime using emitLifetimeEnd after you're done with it.\nfunc CreateTemporaryAlloca(builder llvm.Builder, mod llvm.Module, t llvm.Type, name string) (alloca, size llvm.Value) {\n\tctx := t.Context()\n\ttargetData := llvm.NewTargetData(mod.DataLayout())\n\tdefer targetData.Dispose()\n\talloca = CreateEntryBlockAlloca(builder, t, name)\n\tsize = llvm.ConstInt(ctx.Int64Type(), targetData.TypeAllocSize(t), false)\n\tfnType, fn := getLifetimeStartFunc(mod)\n\tbuilder.CreateCall(fnType, fn, []llvm.Value{size, alloca}, \"\")\n\treturn\n}\n\n// CreateInstructionAlloca creates an alloca in the entry block, and places lifetime control intrinsics around the instruction\nfunc CreateInstructionAlloca(builder llvm.Builder, mod llvm.Module, t llvm.Type, inst llvm.Value, name string) llvm.Value {\n\tctx := mod.Context()\n\ttargetData := llvm.NewTargetData(mod.DataLayout())\n\tdefer targetData.Dispose()\n\n\talloca := CreateEntryBlockAlloca(builder, t, name)\n\tbuilder.SetInsertPointBefore(inst)\n\tsize := llvm.ConstInt(ctx.Int64Type(), targetData.TypeAllocSize(t), false)\n\tfnType, fn := getLifetimeStartFunc(mod)\n\tbuilder.CreateCall(fnType, fn, []llvm.Value{size, alloca}, \"\")\n\tif next := llvm.NextInstruction(inst); !next.IsNil() {\n\t\tbuilder.SetInsertPointBefore(next)\n\t} else {\n\t\tbuilder.SetInsertPointAtEnd(inst.InstructionParent())\n\t}\n\tfnType, fn = getLifetimeEndFunc(mod)\n\tbuilder.CreateCall(fnType, fn, []llvm.Value{size, alloca}, \"\")\n\treturn alloca\n}\n\n// EmitLifetimeEnd signals the end of an (alloca) lifetime by calling the\n// llvm.lifetime.end intrinsic. It is commonly used together with\n// createTemporaryAlloca.\nfunc EmitLifetimeEnd(builder llvm.Builder, mod llvm.Module, ptr, size llvm.Value) {\n\tfnType, fn := getLifetimeEndFunc(mod)\n\tbuilder.CreateCall(fnType, fn, []llvm.Value{size, ptr}, \"\")\n}\n\n// getLifetimeStartFunc returns the llvm.lifetime.start intrinsic and creates it\n// first if it doesn't exist yet.\nfunc getLifetimeStartFunc(mod llvm.Module) (llvm.Type, llvm.Value) {\n\tfnName := \"llvm.lifetime.start.p0\"\n\tfn := mod.NamedFunction(fnName)\n\tctx := mod.Context()\n\tptrType := llvm.PointerType(ctx.Int8Type(), 0)\n\tfnType := llvm.FunctionType(ctx.VoidType(), []llvm.Type{ctx.Int64Type(), ptrType}, false)\n\tif fn.IsNil() {\n\t\tfn = llvm.AddFunction(mod, fnName, fnType)\n\t}\n\treturn fnType, fn\n}\n\n// getLifetimeEndFunc returns the llvm.lifetime.end intrinsic and creates it\n// first if it doesn't exist yet.\nfunc getLifetimeEndFunc(mod llvm.Module) (llvm.Type, llvm.Value) {\n\tfnName := \"llvm.lifetime.end.p0\"\n\tfn := mod.NamedFunction(fnName)\n\tctx := mod.Context()\n\tptrType := llvm.PointerType(ctx.Int8Type(), 0)\n\tfnType := llvm.FunctionType(ctx.VoidType(), []llvm.Type{ctx.Int64Type(), ptrType}, false)\n\tif fn.IsNil() {\n\t\tfn = llvm.AddFunction(mod, fnName, fnType)\n\t}\n\treturn fnType, fn\n}\n\n// SplitBasicBlock splits a LLVM basic block into two parts. All instructions\n// after afterInst are moved into a new basic block (created right after the\n// current one) with the given name.\nfunc SplitBasicBlock(builder llvm.Builder, afterInst llvm.Value, insertAfter llvm.BasicBlock, name string) llvm.BasicBlock {\n\toldBlock := afterInst.InstructionParent()\n\tnewBlock := afterInst.Type().Context().InsertBasicBlock(insertAfter, name)\n\tvar nextInstructions []llvm.Value // values to move\n\n\t// Collect to-be-moved instructions.\n\tinst := afterInst\n\tfor {\n\t\tinst = llvm.NextInstruction(inst)\n\t\tif inst.IsNil() {\n\t\t\tbreak\n\t\t}\n\t\tnextInstructions = append(nextInstructions, inst)\n\t}\n\n\t// Move instructions.\n\tbuilder.SetInsertPointAtEnd(newBlock)\n\tfor _, inst := range nextInstructions {\n\t\tinst.RemoveFromParentAsInstruction()\n\t\tbuilder.Insert(inst)\n\t}\n\n\t// Find PHI nodes to update.\n\tvar phiNodes []llvm.Value // PHI nodes to update\n\tfor bb := insertAfter.Parent().FirstBasicBlock(); !bb.IsNil(); bb = llvm.NextBasicBlock(bb) {\n\t\tfor inst := bb.FirstInstruction(); !inst.IsNil(); inst = llvm.NextInstruction(inst) {\n\t\t\tif inst.IsAPHINode().IsNil() {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tneedsUpdate := false\n\t\t\tincomingCount := inst.IncomingCount()\n\t\t\tfor i := 0; i < incomingCount; i++ {\n\t\t\t\tif inst.IncomingBlock(i) == oldBlock {\n\t\t\t\t\tneedsUpdate = true\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !needsUpdate {\n\t\t\t\t// PHI node has no incoming edge from the old block.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tphiNodes = append(phiNodes, inst)\n\t\t}\n\t}\n\n\t// Update PHI nodes.\n\tfor _, phi := range phiNodes {\n\t\tbuilder.SetInsertPointBefore(phi)\n\t\tnewPhi := builder.CreatePHI(phi.Type(), \"\")\n\t\tincomingCount := phi.IncomingCount()\n\t\tincomingVals := make([]llvm.Value, incomingCount)\n\t\tincomingBlocks := make([]llvm.BasicBlock, incomingCount)\n\t\tfor i := 0; i < incomingCount; i++ {\n\t\t\tvalue := phi.IncomingValue(i)\n\t\t\tblock := phi.IncomingBlock(i)\n\t\t\tif block == oldBlock {\n\t\t\t\tblock = newBlock\n\t\t\t}\n\t\t\tincomingVals[i] = value\n\t\t\tincomingBlocks[i] = block\n\t\t}\n\t\tnewPhi.AddIncoming(incomingVals, incomingBlocks)\n\t\tphi.ReplaceAllUsesWith(newPhi)\n\t\tphi.EraseFromParentAsInstruction()\n\t}\n\n\treturn newBlock\n}\n\n// AppendToGlobal appends the given values to a global array like llvm.used. The global might\n// not exist yet. The values can be any pointer type, they will be cast to i8*.\nfunc AppendToGlobal(mod llvm.Module, globalName string, values ...llvm.Value) {\n\t// Read the existing values in the llvm.used array (if it exists).\n\tvar usedValues []llvm.Value\n\tif used := mod.NamedGlobal(globalName); !used.IsNil() {\n\t\tbuilder := mod.Context().NewBuilder()\n\t\tdefer builder.Dispose()\n\t\tusedInitializer := used.Initializer()\n\t\tnum := usedInitializer.Type().ArrayLength()\n\t\tfor i := 0; i < num; i++ {\n\t\t\tusedValues = append(usedValues, builder.CreateExtractValue(usedInitializer, i, \"\"))\n\t\t}\n\t\tused.EraseFromParentAsGlobal()\n\t}\n\n\t// Add the new values.\n\tptrType := llvm.PointerType(mod.Context().Int8Type(), 0)\n\tfor _, value := range values {\n\t\t// Note: the bitcast is necessary to cast AVR function pointers to\n\t\t// address space 0 pointer types.\n\t\tusedValues = append(usedValues, llvm.ConstPointerCast(value, ptrType))\n\t}\n\n\t// Create a new array (with the old and new values).\n\tusedInitializer := llvm.ConstArray(ptrType, usedValues)\n\tused := llvm.AddGlobal(mod, usedInitializer.Type(), globalName)\n\tused.SetInitializer(usedInitializer)\n\tused.SetLinkage(llvm.AppendingLinkage)\n}\n\n// Version returns the LLVM major version.\nfunc Version() int {\n\tmajorStr := strings.Split(llvm.Version, \".\")[0]\n\tmajor, err := strconv.Atoi(majorStr)\n\tif err != nil {\n\t\tpanic(\"unexpected error while parsing LLVM version: \" + err.Error()) // should not happen\n\t}\n\treturn major\n}\n\n// ByteOrder returns the byte order for the given target triple. Most targets are little\n// endian, but for example MIPS can be big-endian.\nfunc ByteOrder(target string) binary.ByteOrder {\n\tif strings.HasPrefix(target, \"mips-\") {\n\t\treturn binary.BigEndian\n\t} else {\n\t\treturn binary.LittleEndian\n\t}\n}\n"
  },
  {
    "path": "compiler/map.go",
    "content": "package compiler\n\n// This file emits the correct map intrinsics for map operations.\n\nimport (\n\t\"go/token\"\n\t\"go/types\"\n\n\t\"github.com/tinygo-org/tinygo/src/tinygo\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// createMakeMap creates a new map object (runtime.hashmap) by allocating and\n// initializing an appropriately sized object.\nfunc (b *builder) createMakeMap(expr *ssa.MakeMap) (llvm.Value, error) {\n\tmapType := expr.Type().Underlying().(*types.Map)\n\tkeyType := mapType.Key().Underlying()\n\tllvmValueType := b.getLLVMType(mapType.Elem().Underlying())\n\tvar llvmKeyType llvm.Type\n\tvar alg uint64\n\tif t, ok := keyType.(*types.Basic); ok && t.Info()&types.IsString != 0 {\n\t\t// String keys.\n\t\tllvmKeyType = b.getLLVMType(keyType)\n\t\talg = uint64(tinygo.HashmapAlgorithmString)\n\t} else if hashmapIsBinaryKey(keyType) {\n\t\t// Trivially comparable keys.\n\t\tllvmKeyType = b.getLLVMType(keyType)\n\t\talg = uint64(tinygo.HashmapAlgorithmBinary)\n\t} else {\n\t\t// All other keys. Implemented as map[interface{}]valueType for ease of\n\t\t// implementation.\n\t\tllvmKeyType = b.getLLVMRuntimeType(\"_interface\")\n\t\talg = uint64(tinygo.HashmapAlgorithmInterface)\n\t}\n\tkeySize := b.targetData.TypeAllocSize(llvmKeyType)\n\tvalueSize := b.targetData.TypeAllocSize(llvmValueType)\n\tllvmKeySize := llvm.ConstInt(b.uintptrType, keySize, false)\n\tllvmValueSize := llvm.ConstInt(b.uintptrType, valueSize, false)\n\tsizeHint := llvm.ConstInt(b.uintptrType, 8, false)\n\talgEnum := llvm.ConstInt(b.ctx.Int8Type(), alg, false)\n\tif expr.Reserve != nil {\n\t\tsizeHint = b.getValue(expr.Reserve, getPos(expr))\n\t\tvar err error\n\t\tsizeHint, err = b.createConvert(expr.Reserve.Type(), types.Typ[types.Uintptr], sizeHint, expr.Pos())\n\t\tif err != nil {\n\t\t\treturn llvm.Value{}, err\n\t\t}\n\t}\n\thashmap := b.createRuntimeCall(\"hashmapMake\", []llvm.Value{llvmKeySize, llvmValueSize, sizeHint, algEnum}, \"\")\n\treturn hashmap, nil\n}\n\n// createMapLookup returns the value in a map. It calls a runtime function\n// depending on the map key type to load the map value and its comma-ok value.\nfunc (b *builder) createMapLookup(keyType, valueType types.Type, m, key llvm.Value, commaOk bool, pos token.Pos) (llvm.Value, error) {\n\tllvmValueType := b.getLLVMType(valueType)\n\n\t// Allocate the memory for the resulting type. Do not zero this memory: it\n\t// will be zeroed by the hashmap get implementation if the key is not\n\t// present in the map.\n\tmapValueAlloca, mapValueAllocaSize := b.createTemporaryAlloca(llvmValueType, \"hashmap.value\")\n\n\t// We need the map size (with type uintptr) to pass to the hashmap*Get\n\t// functions. This is necessary because those *Get functions are valid on\n\t// nil maps, and they'll need to zero the value pointer by that number of\n\t// bytes.\n\tmapValueSize := mapValueAllocaSize\n\tif mapValueSize.Type().IntTypeWidth() > b.uintptrType.IntTypeWidth() {\n\t\tmapValueSize = llvm.ConstTrunc(mapValueSize, b.uintptrType)\n\t}\n\n\t// Do the lookup. How it is done depends on the key type.\n\tvar commaOkValue llvm.Value\n\torigKeyType := keyType\n\tkeyType = keyType.Underlying()\n\tif t, ok := keyType.(*types.Basic); ok && t.Info()&types.IsString != 0 {\n\t\t// key is a string\n\t\tparams := []llvm.Value{m, key, mapValueAlloca, mapValueSize}\n\t\tcommaOkValue = b.createRuntimeCall(\"hashmapStringGet\", params, \"\")\n\t} else if hashmapIsBinaryKey(keyType) {\n\t\t// key can be compared with runtime.memequal\n\t\t// Store the key in an alloca, in the entry block to avoid dynamic stack\n\t\t// growth.\n\t\tmapKeyAlloca, mapKeySize := b.createTemporaryAlloca(key.Type(), \"hashmap.key\")\n\t\tb.CreateStore(key, mapKeyAlloca)\n\t\tb.zeroUndefBytes(b.getLLVMType(keyType), mapKeyAlloca)\n\t\t// Fetch the value from the hashmap.\n\t\tparams := []llvm.Value{m, mapKeyAlloca, mapValueAlloca, mapValueSize}\n\t\tcommaOkValue = b.createRuntimeCall(\"hashmapBinaryGet\", params, \"\")\n\t\tb.emitLifetimeEnd(mapKeyAlloca, mapKeySize)\n\t} else {\n\t\t// Not trivially comparable using memcmp. Make it an interface instead.\n\t\titfKey := key\n\t\tif _, ok := keyType.(*types.Interface); !ok {\n\t\t\t// Not already an interface, so convert it to an interface now.\n\t\t\titfKey = b.createMakeInterface(key, origKeyType, pos)\n\t\t}\n\t\tparams := []llvm.Value{m, itfKey, mapValueAlloca, mapValueSize}\n\t\tcommaOkValue = b.createRuntimeCall(\"hashmapInterfaceGet\", params, \"\")\n\t}\n\n\t// Load the resulting value from the hashmap. The value is set to the zero\n\t// value if the key doesn't exist in the hashmap.\n\tmapValue := b.CreateLoad(llvmValueType, mapValueAlloca, \"\")\n\tb.emitLifetimeEnd(mapValueAlloca, mapValueAllocaSize)\n\n\tif commaOk {\n\t\ttuple := llvm.Undef(b.ctx.StructType([]llvm.Type{llvmValueType, b.ctx.Int1Type()}, false))\n\t\ttuple = b.CreateInsertValue(tuple, mapValue, 0, \"\")\n\t\ttuple = b.CreateInsertValue(tuple, commaOkValue, 1, \"\")\n\t\treturn tuple, nil\n\t} else {\n\t\treturn mapValue, nil\n\t}\n}\n\n// createMapUpdate updates a map key to a given value, by creating an\n// appropriate runtime call.\nfunc (b *builder) createMapUpdate(keyType types.Type, m, key, value llvm.Value, pos token.Pos) {\n\tvalueAlloca, valueSize := b.createTemporaryAlloca(value.Type(), \"hashmap.value\")\n\tb.CreateStore(value, valueAlloca)\n\torigKeyType := keyType\n\tkeyType = keyType.Underlying()\n\tif t, ok := keyType.(*types.Basic); ok && t.Info()&types.IsString != 0 {\n\t\t// key is a string\n\t\tparams := []llvm.Value{m, key, valueAlloca}\n\t\tb.createRuntimeCall(\"hashmapStringSet\", params, \"\")\n\t} else if hashmapIsBinaryKey(keyType) {\n\t\t// key can be compared with runtime.memequal\n\t\tkeyAlloca, keySize := b.createTemporaryAlloca(key.Type(), \"hashmap.key\")\n\t\tb.CreateStore(key, keyAlloca)\n\t\tb.zeroUndefBytes(b.getLLVMType(keyType), keyAlloca)\n\t\tparams := []llvm.Value{m, keyAlloca, valueAlloca}\n\t\tb.createRuntimeCall(\"hashmapBinarySet\", params, \"\")\n\t\tb.emitLifetimeEnd(keyAlloca, keySize)\n\t} else {\n\t\t// Key is not trivially comparable, so compare it as an interface instead.\n\t\titfKey := key\n\t\tif _, ok := keyType.(*types.Interface); !ok {\n\t\t\t// Not already an interface, so convert it to an interface first.\n\t\t\titfKey = b.createMakeInterface(key, origKeyType, pos)\n\t\t}\n\t\tparams := []llvm.Value{m, itfKey, valueAlloca}\n\t\tb.createRuntimeCall(\"hashmapInterfaceSet\", params, \"\")\n\t}\n\tb.emitLifetimeEnd(valueAlloca, valueSize)\n}\n\n// createMapDelete deletes a key from a map by calling the appropriate runtime\n// function. It is the implementation of the Go delete() builtin.\nfunc (b *builder) createMapDelete(keyType types.Type, m, key llvm.Value, pos token.Pos) error {\n\torigKeyType := keyType\n\tkeyType = keyType.Underlying()\n\tif t, ok := keyType.(*types.Basic); ok && t.Info()&types.IsString != 0 {\n\t\t// key is a string\n\t\tparams := []llvm.Value{m, key}\n\t\tb.createRuntimeCall(\"hashmapStringDelete\", params, \"\")\n\t\treturn nil\n\t} else if hashmapIsBinaryKey(keyType) {\n\t\tkeyAlloca, keySize := b.createTemporaryAlloca(key.Type(), \"hashmap.key\")\n\t\tb.CreateStore(key, keyAlloca)\n\t\tb.zeroUndefBytes(b.getLLVMType(keyType), keyAlloca)\n\t\tparams := []llvm.Value{m, keyAlloca}\n\t\tb.createRuntimeCall(\"hashmapBinaryDelete\", params, \"\")\n\t\tb.emitLifetimeEnd(keyAlloca, keySize)\n\t\treturn nil\n\t} else {\n\t\t// Key is not trivially comparable, so compare it as an interface\n\t\t// instead.\n\t\titfKey := key\n\t\tif _, ok := keyType.(*types.Interface); !ok {\n\t\t\t// Not already an interface, so convert it to an interface first.\n\t\t\titfKey = b.createMakeInterface(key, origKeyType, pos)\n\t\t}\n\t\tparams := []llvm.Value{m, itfKey}\n\t\tb.createRuntimeCall(\"hashmapInterfaceDelete\", params, \"\")\n\t\treturn nil\n\t}\n}\n\n// Clear the given map.\nfunc (b *builder) createMapClear(m llvm.Value) {\n\tb.createRuntimeCall(\"hashmapClear\", []llvm.Value{m}, \"\")\n}\n\n// createMapIteratorNext lowers the *ssa.Next instruction for iterating over a\n// map. It returns a tuple of {bool, key, value} with the result of the\n// iteration.\nfunc (b *builder) createMapIteratorNext(rangeVal ssa.Value, llvmRangeVal, it llvm.Value) llvm.Value {\n\t// Determine the type of the values to return from the *ssa.Next\n\t// instruction. It is returned as {bool, keyType, valueType}.\n\tkeyType := rangeVal.Type().Underlying().(*types.Map).Key()\n\tvalueType := rangeVal.Type().Underlying().(*types.Map).Elem()\n\tllvmKeyType := b.getLLVMType(keyType)\n\tllvmValueType := b.getLLVMType(valueType)\n\n\t// There is a special case in which keys are stored as an interface value\n\t// instead of the value they normally are. This happens for non-trivially\n\t// comparable types such as float32 or some structs.\n\tisKeyStoredAsInterface := false\n\tif t, ok := keyType.Underlying().(*types.Basic); ok && t.Info()&types.IsString != 0 {\n\t\t// key is a string\n\t} else if hashmapIsBinaryKey(keyType) {\n\t\t// key can be compared with runtime.memequal\n\t} else {\n\t\t// The key is stored as an interface value, and may or may not be an\n\t\t// interface type (for example, float32 keys are stored as an interface\n\t\t// value).\n\t\tif _, ok := keyType.Underlying().(*types.Interface); !ok {\n\t\t\tisKeyStoredAsInterface = true\n\t\t}\n\t}\n\n\t// Determine the type of the key as stored in the map.\n\tllvmStoredKeyType := llvmKeyType\n\tif isKeyStoredAsInterface {\n\t\tllvmStoredKeyType = b.getLLVMRuntimeType(\"_interface\")\n\t}\n\n\t// Extract the key and value from the map.\n\tmapKeyAlloca, mapKeySize := b.createTemporaryAlloca(llvmStoredKeyType, \"range.key\")\n\tmapValueAlloca, mapValueSize := b.createTemporaryAlloca(llvmValueType, \"range.value\")\n\tok := b.createRuntimeCall(\"hashmapNext\", []llvm.Value{llvmRangeVal, it, mapKeyAlloca, mapValueAlloca}, \"range.next\")\n\tmapKey := b.CreateLoad(llvmStoredKeyType, mapKeyAlloca, \"\")\n\tmapValue := b.CreateLoad(llvmValueType, mapValueAlloca, \"\")\n\n\tif isKeyStoredAsInterface {\n\t\t// The key is stored as an interface but it isn't of interface type.\n\t\t// Extract the underlying value.\n\t\tmapKey = b.extractValueFromInterface(mapKey, llvmKeyType)\n\t}\n\n\t// End the lifetimes of the allocas, because we're done with them.\n\tb.emitLifetimeEnd(mapKeyAlloca, mapKeySize)\n\tb.emitLifetimeEnd(mapValueAlloca, mapValueSize)\n\n\t// Construct the *ssa.Next return value: {ok, mapKey, mapValue}\n\ttuple := llvm.Undef(b.ctx.StructType([]llvm.Type{b.ctx.Int1Type(), llvmKeyType, llvmValueType}, false))\n\ttuple = b.CreateInsertValue(tuple, ok, 0, \"\")\n\ttuple = b.CreateInsertValue(tuple, mapKey, 1, \"\")\n\ttuple = b.CreateInsertValue(tuple, mapValue, 2, \"\")\n\n\treturn tuple\n}\n\n// Returns true if this key type does not contain strings, interfaces etc., so\n// can be compared with runtime.memequal.  Note that padding bytes are undef\n// and can alter two \"equal\" structs being equal when compared with memequal.\nfunc hashmapIsBinaryKey(keyType types.Type) bool {\n\tswitch keyType := keyType.Underlying().(type) {\n\tcase *types.Basic:\n\t\t// TODO: unsafe.Pointer is also a binary key, but to support that we\n\t\t// need to fix an issue with interp first (see\n\t\t// https://github.com/tinygo-org/tinygo/pull/4898).\n\t\treturn keyType.Info()&(types.IsBoolean|types.IsInteger) != 0\n\tcase *types.Pointer:\n\t\treturn true\n\tcase *types.Struct:\n\t\tfor i := 0; i < keyType.NumFields(); i++ {\n\t\t\tfieldType := keyType.Field(i).Type().Underlying()\n\t\t\tif !hashmapIsBinaryKey(fieldType) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\tcase *types.Array:\n\t\treturn hashmapIsBinaryKey(keyType.Elem())\n\tdefault:\n\t\treturn false\n\t}\n}\n\nfunc (b *builder) zeroUndefBytes(llvmType llvm.Type, ptr llvm.Value) error {\n\t// We know that hashmapIsBinaryKey is true, so we only have to handle those types that can show up there.\n\t// To zero all undefined bytes, we iterate over all the fields in the type.  For each element, compute the\n\t// offset of that element.  If it's Basic type, there are no internal padding bytes.  For compound types, we recurse to ensure\n\t// we handle nested types.  Next, we determine if there are any padding bytes before the next\n\t// element and zero those as well.\n\n\tzero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)\n\n\tswitch llvmType.TypeKind() {\n\tcase llvm.IntegerTypeKind:\n\t\t// no padding bytes\n\t\treturn nil\n\tcase llvm.PointerTypeKind:\n\t\t// mo padding bytes\n\t\treturn nil\n\tcase llvm.ArrayTypeKind:\n\t\tllvmArrayType := llvmType\n\t\tllvmElemType := llvmType.ElementType()\n\n\t\tfor i := 0; i < llvmArrayType.ArrayLength(); i++ {\n\t\t\tidx := llvm.ConstInt(b.uintptrType, uint64(i), false)\n\t\t\telemPtr := b.CreateInBoundsGEP(llvmArrayType, ptr, []llvm.Value{zero, idx}, \"\")\n\n\t\t\t// zero any padding bytes in this element\n\t\t\tb.zeroUndefBytes(llvmElemType, elemPtr)\n\t\t}\n\n\tcase llvm.StructTypeKind:\n\t\tllvmStructType := llvmType\n\t\tnumFields := llvmStructType.StructElementTypesCount()\n\t\tllvmElementTypes := llvmStructType.StructElementTypes()\n\n\t\tfor i := 0; i < numFields; i++ {\n\t\t\tidx := llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false)\n\t\t\telemPtr := b.CreateInBoundsGEP(llvmStructType, ptr, []llvm.Value{zero, idx}, \"\")\n\n\t\t\t// zero any padding bytes in this field\n\t\t\tllvmElemType := llvmElementTypes[i]\n\t\t\tb.zeroUndefBytes(llvmElemType, elemPtr)\n\n\t\t\t// zero any padding bytes before the next field, if any\n\t\t\toffset := b.targetData.ElementOffset(llvmStructType, i)\n\t\t\tstoreSize := b.targetData.TypeStoreSize(llvmElemType)\n\t\t\tfieldEndOffset := offset + storeSize\n\n\t\t\tvar nextOffset uint64\n\t\t\tif i < numFields-1 {\n\t\t\t\tnextOffset = b.targetData.ElementOffset(llvmStructType, i+1)\n\t\t\t} else {\n\t\t\t\t// Last field?  Next offset is the total size of the allocate struct.\n\t\t\t\tnextOffset = b.targetData.TypeAllocSize(llvmStructType)\n\t\t\t}\n\n\t\t\tif fieldEndOffset != nextOffset {\n\t\t\t\tn := llvm.ConstInt(b.uintptrType, nextOffset-fieldEndOffset, false)\n\t\t\t\tllvmStoreSize := llvm.ConstInt(b.uintptrType, storeSize, false)\n\t\t\t\tpaddingStart := b.CreateInBoundsGEP(b.ctx.Int8Type(), elemPtr, []llvm.Value{llvmStoreSize}, \"\")\n\t\t\t\tb.createRuntimeCall(\"memzero\", []llvm.Value{paddingStart, n}, \"\")\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "compiler/sizes.go",
    "content": "package compiler\n\nimport (\n\t\"go/types\"\n)\n\n// The code in this file has been copied from\n// https://golang.org/src/go/types/sizes.go and modified to allow for int and\n// pointer sizes to differ.\n// The original license can be found here:\n//     https://golang.org/LICENSE\n\ntype stdSizes struct {\n\tIntSize  int64\n\tPtrSize  int64\n\tMaxAlign int64\n}\n\nfunc (s *stdSizes) Alignof(T types.Type) int64 {\n\t// For arrays and structs, alignment is defined in terms\n\t// of alignment of the elements and fields, respectively.\n\tswitch t := T.Underlying().(type) {\n\tcase *types.Array:\n\t\t// spec: \"For a variable x of array type: unsafe.Alignof(x)\n\t\t// is the same as unsafe.Alignof(x[0]), but at least 1.\"\n\t\treturn s.Alignof(t.Elem())\n\tcase *types.Struct:\n\t\t// spec: \"For a variable x of struct type: unsafe.Alignof(x)\n\t\t// is the largest of the values unsafe.Alignof(x.f) for each\n\t\t// field f of x, but at least 1.\"\n\t\tmax := int64(1)\n\t\tfor i := 0; i < t.NumFields(); i++ {\n\t\t\tf := t.Field(i)\n\t\t\tif a := s.Alignof(f.Type()); a > max {\n\t\t\t\tmax = a\n\t\t\t}\n\t\t}\n\t\treturn max\n\tcase *types.Slice, *types.Interface:\n\t\t// Multiword data structures are effectively structs\n\t\t// in which each element has size WordSize.\n\t\treturn s.PtrSize\n\tcase *types.Basic:\n\t\t// Strings are like slices and interfaces.\n\t\tif t.Info()&types.IsString != 0 {\n\t\t\treturn s.PtrSize\n\t\t}\n\tcase *types.Signature:\n\t\t// Even though functions in tinygo are 2 pointers, they are not 2 pointer aligned\n\t\treturn s.PtrSize\n\t}\n\n\ta := s.Sizeof(T) // may be 0\n\t// spec: \"For a variable x of any type: unsafe.Alignof(x) is at least 1.\"\n\tif a < 1 {\n\t\treturn 1\n\t}\n\t// complex{64,128} are aligned like [2]float{32,64}.\n\tif t, ok := T.Underlying().(*types.Basic); ok && t.Info()&types.IsComplex != 0 {\n\t\ta /= 2\n\t}\n\tif a > s.MaxAlign {\n\t\treturn s.MaxAlign\n\t}\n\treturn a\n}\n\nfunc (s *stdSizes) Offsetsof(fields []*types.Var) []int64 {\n\toffsets := make([]int64, len(fields))\n\tvar o int64\n\tfor i, f := range fields {\n\t\ta := s.Alignof(f.Type())\n\t\to = align(o, a)\n\t\toffsets[i] = o\n\t\to += s.Sizeof(f.Type())\n\t}\n\treturn offsets\n}\n\nvar basicSizes = [...]byte{\n\ttypes.Bool:       1,\n\ttypes.Int8:       1,\n\ttypes.Int16:      2,\n\ttypes.Int32:      4,\n\ttypes.Int64:      8,\n\ttypes.Uint8:      1,\n\ttypes.Uint16:     2,\n\ttypes.Uint32:     4,\n\ttypes.Uint64:     8,\n\ttypes.Float32:    4,\n\ttypes.Float64:    8,\n\ttypes.Complex64:  8,\n\ttypes.Complex128: 16,\n}\n\nfunc (s *stdSizes) Sizeof(T types.Type) int64 {\n\tswitch t := T.Underlying().(type) {\n\tcase *types.Basic:\n\t\tk := t.Kind()\n\t\tif int(k) < len(basicSizes) {\n\t\t\tif s := basicSizes[k]; s > 0 {\n\t\t\t\treturn int64(s)\n\t\t\t}\n\t\t}\n\t\tif k == types.String {\n\t\t\treturn s.PtrSize * 2\n\t\t}\n\t\tif k == types.Int || k == types.Uint {\n\t\t\treturn s.IntSize\n\t\t}\n\t\tif k == types.Uintptr {\n\t\t\treturn s.PtrSize\n\t\t}\n\t\tif k == types.UnsafePointer {\n\t\t\treturn s.PtrSize\n\t\t}\n\t\tif k == types.Invalid {\n\t\t\treturn 0 // only relevant when there is a type error somewhere\n\t\t}\n\t\tpanic(\"unknown basic type: \" + t.String())\n\tcase *types.Array:\n\t\tn := t.Len()\n\t\tif n <= 0 {\n\t\t\treturn 0\n\t\t}\n\t\t// n > 0\n\t\ta := s.Alignof(t.Elem())\n\t\tz := s.Sizeof(t.Elem())\n\t\treturn align(z, a)*(n-1) + z\n\tcase *types.Slice:\n\t\treturn s.PtrSize * 3\n\tcase *types.Struct:\n\t\tn := t.NumFields()\n\t\tif n == 0 {\n\t\t\treturn 0\n\t\t}\n\t\tfields := make([]*types.Var, t.NumFields())\n\t\tmaxAlign := int64(1)\n\t\tfor i := range fields {\n\t\t\tfield := t.Field(i)\n\t\t\tfields[i] = field\n\t\t\tal := s.Alignof(field.Type())\n\t\t\tif al > maxAlign {\n\t\t\t\tmaxAlign = al\n\t\t\t}\n\t\t}\n\t\t// Pick the size that fits this struct and add some alignment. Some\n\t\t// structs have some extra padding at the end which should also be taken\n\t\t// care of:\n\t\t//     struct { int32 n; byte b }\n\t\toffsets := s.Offsetsof(fields)\n\t\treturn align(offsets[n-1]+s.Sizeof(fields[n-1].Type()), maxAlign)\n\tcase *types.Interface:\n\t\treturn s.PtrSize * 2\n\tcase *types.Pointer, *types.Chan, *types.Map:\n\t\treturn s.PtrSize\n\tcase *types.Signature:\n\t\t// Func values in TinyGo are two words in size.\n\t\treturn s.PtrSize * 2\n\tdefault:\n\t\tpanic(\"unknown type: \" + t.String())\n\t}\n}\n\n// align returns the smallest y >= x such that y % a == 0.\nfunc align(x, a int64) int64 {\n\ty := x + a - 1\n\treturn y - y%a\n}\n"
  },
  {
    "path": "compiler/symbol.go",
    "content": "package compiler\n\n// This file manages symbols, that is, functions and globals. It reads their\n// pragmas, determines the link name, etc.\n\nimport (\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/tinygo-org/tinygo/compiler/llvmutil\"\n\t\"github.com/tinygo-org/tinygo/goenv\"\n\t\"github.com/tinygo-org/tinygo/loader\"\n\t\"golang.org/x/tools/go/ssa\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// functionInfo contains some information about a function or method. In\n// particular, it contains information obtained from pragmas.\n//\n// The linkName value contains a valid link name, even if //go:linkname is not\n// present.\ntype functionInfo struct {\n\twasmModule    string     // go:wasm-module\n\twasmName      string     // wasm-export-name or wasm-import-name in the IR\n\twasmExport    string     // go:wasmexport is defined (export is unset, this adds an exported wrapper)\n\twasmExportPos token.Pos  // position of //go:wasmexport comment\n\tlinkName      string     // go:linkname, go:export - the IR function name\n\tsection       string     // go:section - object file section name\n\texported      bool       // go:export, CGo\n\tinterrupt     bool       // go:interrupt\n\tnobounds      bool       // go:nobounds\n\tnoescape      bool       // go:noescape\n\tvariadic      bool       // go:variadic (CGo only)\n\tinline        inlineType // go:inline\n}\n\ntype inlineType int\n\n// How much to inline.\nconst (\n\t// Default behavior. The compiler decides for itself whether any given\n\t// function will be inlined. Whether any function is inlined depends on the\n\t// optimization level.\n\tinlineDefault inlineType = iota\n\n\t// Inline hint, just like the C inline keyword (signalled using\n\t// //go:inline). The compiler will be more likely to inline this function,\n\t// but it is not a guarantee.\n\tinlineHint\n\n\t// Don't inline, just like the GCC noinline attribute. Signalled using\n\t// //go:noinline.\n\tinlineNone\n)\n\n// Values for the allockind attribute. Source:\n// https://github.com/llvm/llvm-project/blob/release/16.x/llvm/include/llvm/IR/Attributes.h#L49\nconst (\n\tallocKindAlloc = 1 << iota\n\tallocKindRealloc\n\tallocKindFree\n\tallocKindUninitialized\n\tallocKindZeroed\n\tallocKindAligned\n)\n\n// getFunction returns the LLVM function for the given *ssa.Function, creating\n// it if needed. It can later be filled with compilerContext.createFunction().\nfunc (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value) {\n\tinfo := c.getFunctionInfo(fn)\n\tllvmFn := c.mod.NamedFunction(info.linkName)\n\tif !llvmFn.IsNil() {\n\t\treturn llvmFn.GlobalValueType(), llvmFn\n\t}\n\n\tvar retType llvm.Type\n\tif fn.Signature.Results() == nil {\n\t\tretType = c.ctx.VoidType()\n\t} else if fn.Signature.Results().Len() == 1 {\n\t\tretType = c.getLLVMType(fn.Signature.Results().At(0).Type())\n\t} else {\n\t\tresults := make([]llvm.Type, 0, fn.Signature.Results().Len())\n\t\tfor i := 0; i < fn.Signature.Results().Len(); i++ {\n\t\t\tresults = append(results, c.getLLVMType(fn.Signature.Results().At(i).Type()))\n\t\t}\n\t\tretType = c.ctx.StructType(results, false)\n\t}\n\n\tvar paramInfos []paramInfo\n\tfor _, param := range getParams(fn.Signature) {\n\t\tparamType := c.getLLVMType(param.Type())\n\t\tparamFragmentInfos := c.expandFormalParamType(paramType, param.Name(), param.Type())\n\t\tparamInfos = append(paramInfos, paramFragmentInfos...)\n\t}\n\n\t// Add an extra parameter as the function context. This context is used in\n\t// closures and bound methods, but should be optimized away when not used.\n\tif !info.exported {\n\t\tparamInfos = append(paramInfos, paramInfo{llvmType: c.dataPtrType, name: \"context\", elemSize: 0})\n\t}\n\n\tvar paramTypes []llvm.Type\n\tfor _, info := range paramInfos {\n\t\tparamTypes = append(paramTypes, info.llvmType)\n\t}\n\n\tfnType := llvm.FunctionType(retType, paramTypes, info.variadic)\n\tllvmFn = llvm.AddFunction(c.mod, info.linkName, fnType)\n\tif strings.HasPrefix(c.Triple, \"wasm\") {\n\t\t// C functions without prototypes like this:\n\t\t//   void foo();\n\t\t// are actually variadic functions. However, it appears that it has been\n\t\t// decided in WebAssembly that such prototype-less functions are not\n\t\t// allowed in WebAssembly.\n\t\t// In C, this can only happen when there are zero parameters, hence this\n\t\t// check here. For more information:\n\t\t// https://reviews.llvm.org/D48443\n\t\t// https://github.com/WebAssembly/tool-conventions/issues/16\n\t\tif info.variadic && len(fn.Params) == 0 {\n\t\t\tattr := c.ctx.CreateStringAttribute(\"no-prototype\", \"\")\n\t\t\tllvmFn.AddFunctionAttr(attr)\n\t\t}\n\t}\n\tc.addStandardDeclaredAttributes(llvmFn)\n\n\tdereferenceableOrNullKind := llvm.AttributeKindID(\"dereferenceable_or_null\")\n\tfor i, paramInfo := range paramInfos {\n\t\tif paramInfo.elemSize != 0 {\n\t\t\tdereferenceableOrNull := c.ctx.CreateEnumAttribute(dereferenceableOrNullKind, paramInfo.elemSize)\n\t\t\tllvmFn.AddAttributeAtIndex(i+1, dereferenceableOrNull)\n\t\t}\n\t\tif info.noescape && paramInfo.flags&paramIsGoParam != 0 && paramInfo.llvmType.TypeKind() == llvm.PointerTypeKind {\n\t\t\t// Parameters to functions with a //go:noescape parameter should get\n\t\t\t// the nocapture attribute. However, the context parameter should\n\t\t\t// not.\n\t\t\t// (It may be safe to add the nocapture parameter to the context\n\t\t\t// parameter, but I'd like to stay on the safe side here).\n\t\t\tnocapture := c.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"nocapture\"), 0)\n\t\t\tllvmFn.AddAttributeAtIndex(i+1, nocapture)\n\t\t}\n\t\tif paramInfo.flags&paramIsReadonly != 0 && paramInfo.llvmType.TypeKind() == llvm.PointerTypeKind {\n\t\t\t// Readonly pointer parameters (like strings) benefit from being marked as readonly.\n\t\t\treadonly := c.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"readonly\"), 0)\n\t\t\tllvmFn.AddAttributeAtIndex(i+1, readonly)\n\t\t}\n\t}\n\n\t// Set a number of function or parameter attributes, depending on the\n\t// function. These functions are runtime functions that are known to have\n\t// certain attributes that might not be inferred by the compiler.\n\tswitch info.linkName {\n\tcase \"abort\":\n\t\t// On *nix systems, the \"abort\" functuion in libc is used to handle fatal panics.\n\t\t// Mark it as noreturn so LLVM can optimize away code.\n\t\tllvmFn.AddFunctionAttr(c.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"noreturn\"), 0))\n\tcase \"internal/abi.NoEscape\":\n\t\tllvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"nocapture\"), 0))\n\tcase \"machine.keepAliveNoEscape\", \"machine.unsafeNoEscape\":\n\t\tllvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"nocapture\"), 0))\n\tcase \"runtime.alloc\":\n\t\t// Tell the optimizer that runtime.alloc is an allocator, meaning that it\n\t\t// returns values that are never null and never alias to an existing value.\n\t\tfor _, attrName := range []string{\"noalias\", \"nonnull\"} {\n\t\t\tllvmFn.AddAttributeAtIndex(0, c.ctx.CreateEnumAttribute(llvm.AttributeKindID(attrName), 0))\n\t\t}\n\t\t// Add attributes to signal to LLVM that this is an allocator function.\n\t\t// This enables a number of optimizations.\n\t\tllvmFn.AddFunctionAttr(c.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"allockind\"), allocKindAlloc|allocKindZeroed))\n\t\tllvmFn.AddFunctionAttr(c.ctx.CreateStringAttribute(\"alloc-family\", \"runtime.alloc\"))\n\t\t// Use a special value to indicate the first parameter:\n\t\t// > allocsize has two integer arguments, but because they're both 32 bits, we can\n\t\t// > pack them into one 64-bit value, at the cost of making said value\n\t\t// > nonsensical.\n\t\t// >\n\t\t// > In order to do this, we need to reserve one value of the second (optional)\n\t\t// > allocsize argument to signify \"not present.\"\n\t\tllvmFn.AddFunctionAttr(c.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"allocsize\"), 0x0000_0000_ffff_ffff))\n\tcase \"runtime.sliceAppend\":\n\t\t// Appending a slice will only read the to-be-appended slice, it won't\n\t\t// be modified.\n\t\tllvmFn.AddAttributeAtIndex(2, c.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"nocapture\"), 0))\n\t\tllvmFn.AddAttributeAtIndex(2, c.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"readonly\"), 0))\n\tcase \"runtime.sliceCopy\":\n\t\t// Copying a slice won't capture any of the parameters.\n\t\tllvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"writeonly\"), 0))\n\t\tllvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"nocapture\"), 0))\n\t\tllvmFn.AddAttributeAtIndex(2, c.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"readonly\"), 0))\n\t\tllvmFn.AddAttributeAtIndex(2, c.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"nocapture\"), 0))\n\tcase \"runtime.stringFromBytes\":\n\t\tllvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"nocapture\"), 0))\n\t\tllvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"readonly\"), 0))\n\tcase \"runtime.stringFromRunes\":\n\t\tllvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"nocapture\"), 0))\n\t\tllvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"readonly\"), 0))\n\tcase \"runtime.trackPointer\":\n\t\t// This function is necessary for tracking pointers on the stack in a\n\t\t// portable way (see gc_stack_portable.go). Indicate to the optimizer\n\t\t// that the only thing we'll do is read the pointer.\n\t\tllvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"nocapture\"), 0))\n\t\tllvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"readonly\"), 0))\n\tcase \"__mulsi3\", \"__divmodsi4\", \"__udivmodsi4\":\n\t\tif strings.Split(c.Triple, \"-\")[0] == \"avr\" {\n\t\t\t// These functions are compiler-rt/libgcc functions that are\n\t\t\t// currently implemented in Go. Assembly versions should appear in\n\t\t\t// LLVM 17 hopefully. Until then, they need to be made available to\n\t\t\t// the linker and the best way to do that is llvm.compiler.used.\n\t\t\t// I considered adding a pragma for this, but the LLVM language\n\t\t\t// reference explicitly says that this feature should not be exposed\n\t\t\t// to source languages:\n\t\t\t// > This is a rare construct that should only be used in rare\n\t\t\t// > circumstances, and should not be exposed to source languages.\n\t\t\tllvmutil.AppendToGlobal(c.mod, \"llvm.compiler.used\", llvmFn)\n\t\t}\n\tcase \"GetModuleHandleExA\", \"GetProcAddress\", \"GetSystemInfo\", \"GetSystemTimeAsFileTime\", \"LoadLibraryExW\", \"QueryPerformanceCounter\", \"QueryPerformanceFrequency\", \"QueryUnbiasedInterruptTime\", \"SetEnvironmentVariableA\", \"Sleep\", \"SystemFunction036\", \"VirtualAlloc\":\n\t\t// On Windows we need to use a special calling convention for some\n\t\t// external calls.\n\t\tif c.GOOS == \"windows\" && c.GOARCH == \"386\" {\n\t\t\tllvmFn.SetFunctionCallConv(llvm.X86StdcallCallConv)\n\t\t}\n\t}\n\n\t// External/exported functions may not retain pointer values.\n\t// https://golang.org/cmd/cgo/#hdr-Passing_pointers\n\tif info.exported {\n\t\tif c.archFamily() == \"wasm32\" && len(fn.Blocks) == 0 {\n\t\t\t// We need to add the wasm-import-module and the wasm-import-name\n\t\t\t// attributes.\n\t\t\tif info.wasmModule != \"\" {\n\t\t\t\tllvmFn.AddFunctionAttr(c.ctx.CreateStringAttribute(\"wasm-import-module\", info.wasmModule))\n\t\t\t}\n\n\t\t\tllvmFn.AddFunctionAttr(c.ctx.CreateStringAttribute(\"wasm-import-name\", info.wasmName))\n\t\t}\n\t\tnocaptureKind := llvm.AttributeKindID(\"nocapture\")\n\t\tnocapture := c.ctx.CreateEnumAttribute(nocaptureKind, 0)\n\t\tfor i, typ := range paramTypes {\n\t\t\tif typ.TypeKind() == llvm.PointerTypeKind {\n\t\t\t\tllvmFn.AddAttributeAtIndex(i+1, nocapture)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Build the function if needed.\n\tc.maybeCreateSyntheticFunction(fn, llvmFn)\n\n\treturn fnType, llvmFn\n}\n\n// If this is a synthetic function (such as a generic function or a wrapper),\n// create it now.\nfunc (c *compilerContext) maybeCreateSyntheticFunction(fn *ssa.Function, llvmFn llvm.Value) {\n\t// Synthetic functions are functions that do not appear in the source code,\n\t// they are artificially constructed. Usually they are wrapper functions\n\t// that are not referenced anywhere except in a SSA call instruction so\n\t// should be created right away.\n\t// The exception is the package initializer, which does appear in the\n\t// *ssa.Package members and so shouldn't be created here.\n\tif fn.Synthetic != \"\" && fn.Synthetic != \"package initializer\" && fn.Synthetic != \"generic function\" && fn.Synthetic != \"range-over-func yield\" {\n\t\tif origin := fn.Origin(); origin != nil && origin.RelString(nil) == \"internal/abi.Escape\" {\n\t\t\t// This is a special implementation or internal/abi.Escape, which\n\t\t\t// can only really be implemented in the compiler.\n\t\t\t// For simplicity we'll only implement pointer parameters for now.\n\t\t\tif _, ok := fn.Params[0].Type().Underlying().(*types.Pointer); ok {\n\t\t\t\tirbuilder := c.ctx.NewBuilder()\n\t\t\t\tdefer irbuilder.Dispose()\n\t\t\t\tb := newBuilder(c, irbuilder, fn)\n\t\t\t\tb.createAbiEscapeImpl()\n\t\t\t\tllvmFn.SetLinkage(llvm.LinkOnceODRLinkage)\n\t\t\t\tllvmFn.SetUnnamedAddr(true)\n\t\t\t}\n\t\t\t// If the parameter is not of a pointer type, it will be left\n\t\t\t// unimplemented. This will result in a linker error if the function\n\t\t\t// is really called, making it clear it needs to be implemented.\n\t\t\treturn\n\t\t}\n\t\tif len(fn.Blocks) == 0 {\n\t\t\tc.addError(fn.Pos(), \"missing function body\")\n\t\t\treturn\n\t\t}\n\t\tirbuilder := c.ctx.NewBuilder()\n\t\tb := newBuilder(c, irbuilder, fn)\n\t\tb.createFunction()\n\t\tirbuilder.Dispose()\n\t\tllvmFn.SetLinkage(llvm.LinkOnceODRLinkage)\n\t\tllvmFn.SetUnnamedAddr(true)\n\t}\n}\n\n// getFunctionInfo returns information about a function that is not directly\n// present in *ssa.Function, such as the link name and whether it should be\n// exported.\nfunc (c *compilerContext) getFunctionInfo(f *ssa.Function) functionInfo {\n\tif info, ok := c.functionInfos[f]; ok {\n\t\treturn info\n\t}\n\tinfo := functionInfo{\n\t\t// Pick the default linkName.\n\t\tlinkName: f.RelString(nil),\n\t}\n\n\t// Check for a few runtime functions that are treated specially.\n\tif info.linkName == \"runtime.wasmEntryReactor\" && c.BuildMode == \"c-shared\" {\n\t\tinfo.linkName = \"_initialize\"\n\t\tinfo.wasmName = \"_initialize\"\n\t\tinfo.exported = true\n\t}\n\tif info.linkName == \"runtime.wasmEntryCommand\" && c.BuildMode == \"default\" {\n\t\tinfo.linkName = \"_start\"\n\t\tinfo.wasmName = \"_start\"\n\t\tinfo.exported = true\n\t}\n\tif info.linkName == \"runtime.wasmEntryLegacy\" && c.BuildMode == \"wasi-legacy\" {\n\t\tinfo.linkName = \"_start\"\n\t\tinfo.wasmName = \"_start\"\n\t\tinfo.exported = true\n\t}\n\n\t// Check for //go: pragmas, which may change the link name (among others).\n\tc.parsePragmas(&info, f)\n\n\tc.functionInfos[f] = info\n\treturn info\n}\n\n// parsePragmas is used by getFunctionInfo to parse function pragmas such as\n// //export or //go:noinline.\nfunc (c *compilerContext) parsePragmas(info *functionInfo, f *ssa.Function) {\n\tsyntax := f.Syntax()\n\tif f.Origin() != nil {\n\t\tsyntax = f.Origin().Syntax()\n\t}\n\tif syntax == nil {\n\t\treturn\n\t}\n\n\t// Read all pragmas of this function.\n\tvar pragmas []*ast.Comment\n\thasWasmExport := false\n\tif decl, ok := syntax.(*ast.FuncDecl); ok && decl.Doc != nil {\n\t\tfor _, comment := range decl.Doc.List {\n\t\t\ttext := comment.Text\n\t\t\tif strings.HasPrefix(text, \"//go:\") || strings.HasPrefix(text, \"//export \") {\n\t\t\t\tpragmas = append(pragmas, comment)\n\t\t\t\tif strings.HasPrefix(comment.Text, \"//go:wasmexport \") {\n\t\t\t\t\thasWasmExport = true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Parse each pragma.\n\tfor _, comment := range pragmas {\n\t\tparts := strings.Fields(comment.Text)\n\t\tswitch parts[0] {\n\t\tcase \"//export\", \"//go:export\":\n\t\t\tif len(parts) != 2 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif hasWasmExport {\n\t\t\t\t// //go:wasmexport overrides //export.\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tinfo.linkName = parts[1]\n\t\t\tinfo.wasmName = info.linkName\n\t\t\tinfo.exported = true\n\t\tcase \"//go:interrupt\":\n\t\t\tif hasUnsafeImport(f.Pkg.Pkg) {\n\t\t\t\tinfo.interrupt = true\n\t\t\t}\n\t\tcase \"//go:wasm-module\":\n\t\t\t// Alternative comment for setting the import module.\n\t\t\t// This is deprecated, use //go:wasmimport instead.\n\t\t\tif len(parts) != 2 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tinfo.wasmModule = parts[1]\n\t\tcase \"//go:wasmimport\":\n\t\t\t// Import a WebAssembly function, for example a WASI function.\n\t\t\t// Original proposal: https://github.com/golang/go/issues/38248\n\t\t\t// Allow globally: https://github.com/golang/go/issues/59149\n\t\t\tif len(parts) != 3 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif f.Blocks != nil {\n\t\t\t\t// Defined functions cannot be exported.\n\t\t\t\tc.addError(f.Pos(), \"can only use //go:wasmimport on declarations\")\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tc.checkWasmImportExport(f, comment.Text)\n\t\t\tinfo.exported = true\n\t\t\tinfo.wasmModule = parts[1]\n\t\t\tinfo.wasmName = parts[2]\n\t\tcase \"//go:wasmexport\":\n\t\t\tif f.Blocks == nil {\n\t\t\t\tc.addError(f.Pos(), \"can only use //go:wasmexport on definitions\")\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif len(parts) != 2 {\n\t\t\t\tc.addError(f.Pos(), fmt.Sprintf(\"expected one parameter to //go:wasmexport, not %d\", len(parts)-1))\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tname := parts[1]\n\t\t\tif name == \"_start\" || name == \"_initialize\" {\n\t\t\t\tc.addError(f.Pos(), fmt.Sprintf(\"//go:wasmexport does not allow %#v\", name))\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif c.BuildMode != \"c-shared\" && f.RelString(nil) == \"main.main\" {\n\t\t\t\tc.addError(f.Pos(), fmt.Sprintf(\"//go:wasmexport does not allow main.main to be exported with -buildmode=%s\", c.BuildMode))\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif c.archFamily() != \"wasm32\" {\n\t\t\t\tc.addError(f.Pos(), \"//go:wasmexport is only supported on wasm\")\n\t\t\t}\n\t\t\tc.checkWasmImportExport(f, comment.Text)\n\t\t\tinfo.wasmExport = name\n\t\t\tinfo.wasmExportPos = comment.Slash\n\t\tcase \"//go:inline\":\n\t\t\tinfo.inline = inlineHint\n\t\tcase \"//go:noinline\":\n\t\t\tinfo.inline = inlineNone\n\t\tcase \"//go:linkname\":\n\t\t\tif len(parts) != 3 || parts[1] != f.Name() {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// Only enable go:linkname when the package imports \"unsafe\".\n\t\t\t// This is a slightly looser requirement than what gc uses: gc\n\t\t\t// requires the file to import \"unsafe\", not the package as a\n\t\t\t// whole.\n\t\t\tif hasUnsafeImport(f.Pkg.Pkg) {\n\t\t\t\tinfo.linkName = parts[2]\n\t\t\t}\n\t\tcase \"//go:section\":\n\t\t\t// Only enable go:section when the package imports \"unsafe\".\n\t\t\t// go:section also implies go:noinline since inlining could\n\t\t\t// move the code to a different section than that requested.\n\t\t\tif len(parts) == 2 && hasUnsafeImport(f.Pkg.Pkg) {\n\t\t\t\tinfo.section = parts[1]\n\t\t\t\tinfo.inline = inlineNone\n\t\t\t}\n\t\tcase \"//go:nobounds\":\n\t\t\t// Skip bounds checking in this function. Useful for some\n\t\t\t// runtime functions.\n\t\t\t// This is somewhat dangerous and thus only imported in packages\n\t\t\t// that import unsafe.\n\t\t\tif hasUnsafeImport(f.Pkg.Pkg) {\n\t\t\t\tinfo.nobounds = true\n\t\t\t}\n\t\tcase \"//go:noescape\":\n\t\t\t// Don't let pointer parameters escape.\n\t\t\t// Following the upstream Go implementation, we only do this for\n\t\t\t// declarations, not definitions.\n\t\t\tif len(f.Blocks) == 0 {\n\t\t\t\tinfo.noescape = true\n\t\t\t}\n\t\tcase \"//go:variadic\":\n\t\t\t// The //go:variadic pragma is emitted by the CGo preprocessing\n\t\t\t// pass for C variadic functions. This includes both explicit\n\t\t\t// (with ...) and implicit (no parameters in signature)\n\t\t\t// functions.\n\t\t\tif strings.HasPrefix(f.Name(), \"_Cgo_\") {\n\t\t\t\t// This prefix was created as a result of CGo preprocessing.\n\t\t\t\tinfo.variadic = true\n\t\t\t}\n\t\t}\n\t}\n\n\tif c.Nobounds {\n\t\tinfo.nobounds = true\n\t}\n}\n\n// Check whether this function can be used in //go:wasmimport or\n// //go:wasmexport. It will add an error if this is not the case.\n//\n// The list of allowed types is based on this proposal:\n// https://github.com/golang/go/issues/59149\nfunc (c *compilerContext) checkWasmImportExport(f *ssa.Function, pragma string) {\n\tif c.pkg.Path() == \"runtime\" || c.pkg.Path() == \"syscall/js\" || c.pkg.Path() == \"syscall\" || c.pkg.Path() == \"crypto/internal/sysrand\" {\n\t\t// The runtime is a special case. Allow all kinds of parameters\n\t\t// (importantly, including pointers).\n\t\treturn\n\t}\n\tif f.Signature.Results().Len() > 1 {\n\t\tc.addError(f.Signature.Results().At(1).Pos(), fmt.Sprintf(\"%s: too many return values\", pragma))\n\t} else if f.Signature.Results().Len() == 1 {\n\t\tresult := f.Signature.Results().At(0)\n\t\tif !c.isValidWasmType(result.Type(), siteResult) {\n\t\t\tc.addError(result.Pos(), fmt.Sprintf(\"%s: unsupported result type %s\", pragma, result.Type().String()))\n\t\t}\n\t}\n\tfor _, param := range f.Params {\n\t\t// Check whether the type is allowed.\n\t\t// Only a very limited number of types can be mapped to WebAssembly.\n\t\tif !c.isValidWasmType(param.Type(), siteParam) {\n\t\t\tc.addError(param.Pos(), fmt.Sprintf(\"%s: unsupported parameter type %s\", pragma, param.Type().String()))\n\t\t}\n\t}\n}\n\n// Check whether the type maps directly to a WebAssembly type.\n//\n// This reflects the relaxed type restrictions proposed here (except for structs.HostLayout):\n// https://github.com/golang/go/issues/66984\n//\n// This previously reflected the additional restrictions documented here:\n// https://github.com/golang/go/issues/59149\nfunc (c *compilerContext) isValidWasmType(typ types.Type, site wasmSite) bool {\n\tswitch typ := typ.Underlying().(type) {\n\tcase *types.Basic:\n\t\tswitch typ.Kind() {\n\t\tcase types.Bool:\n\t\t\treturn true\n\t\tcase types.Int8, types.Uint8, types.Int16, types.Uint16:\n\t\t\treturn site == siteIndirect\n\t\tcase types.Int32, types.Uint32, types.Int64, types.Uint64:\n\t\t\treturn true\n\t\tcase types.Float32, types.Float64:\n\t\t\treturn true\n\t\tcase types.Uintptr, types.UnsafePointer:\n\t\t\treturn true\n\t\tcase types.String:\n\t\t\t// string flattens to two values, so disallowed as a result\n\t\t\treturn site == siteParam || site == siteIndirect\n\t\t}\n\tcase *types.Array:\n\t\treturn site == siteIndirect && c.isValidWasmType(typ.Elem(), siteIndirect)\n\tcase *types.Struct:\n\t\tif site != siteIndirect {\n\t\t\treturn false\n\t\t}\n\t\t// Structs with no fields do not need structs.HostLayout\n\t\tif typ.NumFields() == 0 {\n\t\t\treturn true\n\t\t}\n\t\thasHostLayout := true // default to true before detecting Go version\n\t\t// (*types.Package).GoVersion added in go1.21\n\t\tif gv, ok := any(c.pkg).(interface{ GoVersion() string }); ok {\n\t\t\tif goenv.Compare(gv.GoVersion(), \"go1.23\") >= 0 {\n\t\t\t\thasHostLayout = false // package structs added in go1.23\n\t\t\t}\n\t\t}\n\t\tfor i := 0; i < typ.NumFields(); i++ {\n\t\t\tftyp := typ.Field(i).Type()\n\t\t\tif ftyp.String() == \"structs.HostLayout\" {\n\t\t\t\thasHostLayout = true\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif !c.isValidWasmType(ftyp, siteIndirect) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn hasHostLayout\n\tcase *types.Pointer:\n\t\treturn c.isValidWasmType(typ.Elem(), siteIndirect)\n\t}\n\treturn false\n}\n\ntype wasmSite int\n\nconst (\n\tsiteParam wasmSite = iota\n\tsiteResult\n\tsiteIndirect // pointer or field\n)\n\n// getParams returns the function parameters, including the receiver at the\n// start. This is an alternative to the Params member of *ssa.Function, which is\n// not yet populated when the package has not yet been built.\nfunc getParams(sig *types.Signature) []*types.Var {\n\tparams := []*types.Var{}\n\tif sig.Recv() != nil {\n\t\tparams = append(params, sig.Recv())\n\t}\n\tfor i := 0; i < sig.Params().Len(); i++ {\n\t\tparams = append(params, sig.Params().At(i))\n\t}\n\treturn params\n}\n\n// addStandardDeclaredAttributes adds attributes that are set for any function,\n// whether declared or defined.\nfunc (c *compilerContext) addStandardDeclaredAttributes(llvmFn llvm.Value) {\n\tif c.SizeLevel >= 1 {\n\t\t// Set the \"optsize\" attribute to make slightly smaller binaries at the\n\t\t// cost of minimal performance loss (-Os in Clang).\n\t\tkind := llvm.AttributeKindID(\"optsize\")\n\t\tattr := c.ctx.CreateEnumAttribute(kind, 0)\n\t\tllvmFn.AddFunctionAttr(attr)\n\t}\n\tif c.SizeLevel >= 2 {\n\t\t// Set the \"minsize\" attribute to reduce code size even further,\n\t\t// regardless of performance loss (-Oz in Clang).\n\t\tkind := llvm.AttributeKindID(\"minsize\")\n\t\tattr := c.ctx.CreateEnumAttribute(kind, 0)\n\t\tllvmFn.AddFunctionAttr(attr)\n\t}\n\tif c.CPU != \"\" {\n\t\tllvmFn.AddFunctionAttr(c.ctx.CreateStringAttribute(\"target-cpu\", c.CPU))\n\t}\n\tif c.Features != \"\" {\n\t\tllvmFn.AddFunctionAttr(c.ctx.CreateStringAttribute(\"target-features\", c.Features))\n\t}\n}\n\n// addStandardDefinedAttributes adds the set of attributes that are added to\n// every function defined by TinyGo (even thunks/wrappers), possibly depending\n// on the architecture. It does not set attributes only set for declared\n// functions, use addStandardDeclaredAttributes for this.\nfunc (c *compilerContext) addStandardDefinedAttributes(llvmFn llvm.Value) {\n\t// TinyGo does not currently raise exceptions, so set the 'nounwind' flag.\n\t// This behavior matches Clang when compiling C source files.\n\t// It reduces binary size on Linux a little bit on non-x86_64 targets by\n\t// eliminating exception tables for these functions.\n\tllvmFn.AddFunctionAttr(c.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"nounwind\"), 0))\n\tif strings.Split(c.Triple, \"-\")[0] == \"x86_64\" {\n\t\t// Required by the ABI.\n\t\t// The uwtable has two possible values: sync (1) or async (2). We use\n\t\t// sync because we currently don't use async unwind tables.\n\t\t// For details, see: https://llvm.org/docs/LangRef.html#function-attributes\n\t\tllvmFn.AddFunctionAttr(c.ctx.CreateEnumAttribute(llvm.AttributeKindID(\"uwtable\"), 1))\n\t}\n}\n\n// addStandardAttributes adds all attributes added to defined functions.\nfunc (c *compilerContext) addStandardAttributes(llvmFn llvm.Value) {\n\tc.addStandardDeclaredAttributes(llvmFn)\n\tc.addStandardDefinedAttributes(llvmFn)\n}\n\n// globalInfo contains some information about a specific global. By default,\n// linkName is equal to .RelString(nil) on a global and extern is false, but for\n// some symbols this is different (due to //go:extern for example).\ntype globalInfo struct {\n\tlinkName string // go:extern, go:linkname\n\textern   bool   // go:extern\n\talign    int    // go:align\n\tsection  string // go:section\n}\n\n// loadASTComments loads comments on globals from the AST, for use later in the\n// program. In particular, they are required for //go:extern pragmas on globals.\nfunc (c *compilerContext) loadASTComments(pkg *loader.Package) {\n\tfor _, file := range pkg.Files {\n\t\tfor _, decl := range file.Decls {\n\t\t\tswitch decl := decl.(type) {\n\t\t\tcase *ast.GenDecl:\n\t\t\t\tswitch decl.Tok {\n\t\t\t\tcase token.VAR:\n\t\t\t\t\tif len(decl.Specs) != 1 {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tfor _, spec := range decl.Specs {\n\t\t\t\t\t\tswitch spec := spec.(type) {\n\t\t\t\t\t\tcase *ast.ValueSpec: // decl.Tok == token.VAR\n\t\t\t\t\t\t\tfor _, name := range spec.Names {\n\t\t\t\t\t\t\t\tid := pkg.Pkg.Path() + \".\" + name.Name\n\t\t\t\t\t\t\t\tc.astComments[id] = decl.Doc\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// getGlobal returns a LLVM IR global value for a Go SSA global. It is added to\n// the LLVM IR if it has not been added already.\nfunc (c *compilerContext) getGlobal(g *ssa.Global) llvm.Value {\n\tinfo := c.getGlobalInfo(g)\n\tllvmGlobal := c.mod.NamedGlobal(info.linkName)\n\tif llvmGlobal.IsNil() {\n\t\ttyp := g.Type().(*types.Pointer).Elem()\n\t\tllvmType := c.getLLVMType(typ)\n\t\tllvmGlobal = llvm.AddGlobal(c.mod, llvmType, info.linkName)\n\n\t\t// Set alignment from the //go:align comment.\n\t\talignment := c.targetData.ABITypeAlignment(llvmType)\n\t\tif info.align > alignment {\n\t\t\talignment = info.align\n\t\t}\n\t\tif alignment <= 0 || alignment&(alignment-1) != 0 {\n\t\t\t// Check for power-of-two (or 0).\n\t\t\t// See: https://stackoverflow.com/a/108360\n\t\t\tc.addError(g.Pos(), \"global variable alignment must be a positive power of two\")\n\t\t} else {\n\t\t\t// Set the alignment only when it is a power of two.\n\t\t\tllvmGlobal.SetAlignment(alignment)\n\t\t}\n\n\t\tif c.Debug && !info.extern {\n\t\t\t// Add debug info.\n\t\t\tpos := c.program.Fset.Position(g.Pos())\n\t\t\tdiglobal := c.dibuilder.CreateGlobalVariableExpression(c.difiles[pos.Filename], llvm.DIGlobalVariableExpression{\n\t\t\t\tName:        g.RelString(nil),\n\t\t\t\tLinkageName: info.linkName,\n\t\t\t\tFile:        c.getDIFile(pos.Filename),\n\t\t\t\tLine:        pos.Line,\n\t\t\t\tType:        c.getDIType(typ),\n\t\t\t\tLocalToUnit: false,\n\t\t\t\tExpr:        c.dibuilder.CreateExpression(nil),\n\t\t\t\tAlignInBits: uint32(alignment) * 8,\n\t\t\t})\n\t\t\tllvmGlobal.AddMetadata(0, diglobal)\n\t\t}\n\t}\n\treturn llvmGlobal\n}\n\n// getGlobalInfo returns some information about a specific global.\nfunc (c *compilerContext) getGlobalInfo(g *ssa.Global) globalInfo {\n\tinfo := globalInfo{\n\t\t// Pick the default linkName.\n\t\tlinkName: g.RelString(nil),\n\t}\n\t// Check for //go: pragmas, which may change the link name (among others).\n\tdoc := c.astComments[info.linkName]\n\tif doc != nil {\n\t\tinfo.parsePragmas(doc, c, g)\n\t}\n\treturn info\n}\n\n// Parse //go: pragma comments from the source. In particular, it parses the\n// //go:extern and //go:linkname pragmas on globals.\nfunc (info *globalInfo) parsePragmas(doc *ast.CommentGroup, c *compilerContext, g *ssa.Global) {\n\tfor _, comment := range doc.List {\n\t\tif !strings.HasPrefix(comment.Text, \"//go:\") {\n\t\t\tcontinue\n\t\t}\n\t\tparts := strings.Fields(comment.Text)\n\t\tswitch parts[0] {\n\t\tcase \"//go:extern\":\n\t\t\tinfo.extern = true\n\t\t\tif len(parts) == 2 {\n\t\t\t\tinfo.linkName = parts[1]\n\t\t\t}\n\t\tcase \"//go:align\":\n\t\t\talign, err := strconv.Atoi(parts[1])\n\t\t\tif err == nil {\n\t\t\t\tinfo.align = align\n\t\t\t}\n\t\tcase \"//go:section\":\n\t\t\tif len(parts) == 2 {\n\t\t\t\tinfo.section = parts[1]\n\t\t\t}\n\t\tcase \"//go:linkname\":\n\t\t\tif len(parts) != 3 || parts[1] != g.Name() {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// Only enable go:linkname when the package imports \"unsafe\".\n\t\t\t// This is a slightly looser requirement than what gc uses: gc\n\t\t\t// requires the file to import \"unsafe\", not the package as a\n\t\t\t// whole.\n\t\t\tif hasUnsafeImport(g.Pkg.Pkg) {\n\t\t\t\tinfo.linkName = parts[2]\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Get all methods of a type.\nfunc getAllMethods(prog *ssa.Program, typ types.Type) []*types.Selection {\n\tms := prog.MethodSets.MethodSet(typ)\n\tmethods := make([]*types.Selection, ms.Len())\n\tfor i := 0; i < ms.Len(); i++ {\n\t\tmethods[i] = ms.At(i)\n\t}\n\treturn methods\n}\n\n// Return true if this package imports \"unsafe\", false otherwise.\nfunc hasUnsafeImport(pkg *types.Package) bool {\n\tfor _, imp := range pkg.Imports() {\n\t\tif imp == types.Unsafe {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "compiler/syscall.go",
    "content": "package compiler\n\n// This file implements the syscall.Syscall and syscall.Syscall6 instructions as\n// compiler builtins.\n\nimport (\n\t\"strconv\"\n\t\"strings\"\n\n\t\"golang.org/x/tools/go/ssa\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// createRawSyscall creates a system call with the provided system call number\n// and returns the result as a single integer (the system call result). The\n// result is not further interpreted (with the exception of MIPS to use the same\n// return value everywhere).\nfunc (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {\n\tnum := b.getValue(call.Args[0], getPos(call))\n\tswitch {\n\tcase b.GOARCH == \"amd64\" && b.GOOS == \"linux\":\n\t\t// Sources:\n\t\t//   https://stackoverflow.com/a/2538212\n\t\t//   https://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux#syscall\n\t\targs := []llvm.Value{num}\n\t\targTypes := []llvm.Type{b.uintptrType}\n\t\t// Constraints will look something like:\n\t\t//   \"={rax},0,{rdi},{rsi},{rdx},{r10},{r8},{r9},~{rcx},~{r11}\"\n\t\tconstraints := \"={rax},0\"\n\t\tfor i, arg := range call.Args[1:] {\n\t\t\tconstraints += \",\" + [...]string{\n\t\t\t\t\"{rdi}\",\n\t\t\t\t\"{rsi}\",\n\t\t\t\t\"{rdx}\",\n\t\t\t\t\"{r10}\",\n\t\t\t\t\"{r8}\",\n\t\t\t\t\"{r9}\",\n\t\t\t}[i]\n\t\t\tllvmValue := b.getValue(arg, getPos(call))\n\t\t\targs = append(args, llvmValue)\n\t\t\targTypes = append(argTypes, llvmValue.Type())\n\t\t}\n\t\t// rcx and r11 are clobbered by the syscall, so make sure they are not used\n\t\tconstraints += \",~{rcx},~{r11}\"\n\t\tfnType := llvm.FunctionType(b.uintptrType, argTypes, false)\n\t\ttarget := llvm.InlineAsm(fnType, \"syscall\", constraints, true, false, llvm.InlineAsmDialectIntel, false)\n\t\treturn b.CreateCall(fnType, target, args, \"\"), nil\n\n\tcase b.GOARCH == \"386\" && b.GOOS == \"linux\":\n\t\t// Sources:\n\t\t//   syscall(2) man page\n\t\t//   https://stackoverflow.com/a/2538212\n\t\t//   https://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux#int_0x80\n\t\targs := []llvm.Value{num}\n\t\targTypes := []llvm.Type{b.uintptrType}\n\t\t// Constraints will look something like:\n\t\t//   \"={eax},0,{ebx},{ecx},{edx},{esi},{edi},{ebp}\"\n\t\tconstraints := \"={eax},0\"\n\t\tfor i, arg := range call.Args[1:] {\n\t\t\tconstraints += \",\" + [...]string{\n\t\t\t\t\"{ebx}\",\n\t\t\t\t\"{ecx}\",\n\t\t\t\t\"{edx}\",\n\t\t\t\t\"{esi}\",\n\t\t\t\t\"{edi}\",\n\t\t\t\t\"{ebp}\",\n\t\t\t}[i]\n\t\t\tllvmValue := b.getValue(arg, getPos(call))\n\t\t\targs = append(args, llvmValue)\n\t\t\targTypes = append(argTypes, llvmValue.Type())\n\t\t}\n\t\tfnType := llvm.FunctionType(b.uintptrType, argTypes, false)\n\t\ttarget := llvm.InlineAsm(fnType, \"int 0x80\", constraints, true, false, llvm.InlineAsmDialectIntel, false)\n\t\treturn b.CreateCall(fnType, target, args, \"\"), nil\n\n\tcase b.GOARCH == \"arm\" && b.GOOS == \"linux\":\n\t\tif arch := b.archFamily(); arch != \"arm\" {\n\t\t\t// Some targets pretend to be linux/arm for compatibility but aren't\n\t\t\t// actually such a system. Make sure we emit an error instead of\n\t\t\t// creating inline assembly that will fail to compile.\n\t\t\t// See: https://github.com/tinygo-org/tinygo/issues/4959\n\t\t\treturn llvm.Value{}, b.makeError(call.Pos(), \"system calls are not supported: target emulates a linux/arm system on \"+arch)\n\t\t}\n\n\t\t// Implement the EABI system call convention for Linux.\n\t\t// Source: syscall(2) man page.\n\t\targs := []llvm.Value{}\n\t\targTypes := []llvm.Type{}\n\t\t// Constraints will look something like:\n\t\t//   ={r0},0,{r1},{r2},{r7},~{r3}\n\t\tconstraints := \"={r0}\"\n\t\tfor i, arg := range call.Args[1:] {\n\t\t\tconstraints += \",\" + [...]string{\n\t\t\t\t\"0\", // tie to output\n\t\t\t\t\"{r1}\",\n\t\t\t\t\"{r2}\",\n\t\t\t\t\"{r3}\",\n\t\t\t\t\"{r4}\",\n\t\t\t\t\"{r5}\",\n\t\t\t\t\"{r6}\",\n\t\t\t}[i]\n\t\t\tllvmValue := b.getValue(arg, getPos(call))\n\t\t\targs = append(args, llvmValue)\n\t\t\targTypes = append(argTypes, llvmValue.Type())\n\t\t}\n\t\targs = append(args, num)\n\t\targTypes = append(argTypes, b.uintptrType)\n\t\tconstraints += \",{r7}\" // syscall number\n\t\tfor i := len(call.Args) - 1; i < 4; i++ {\n\t\t\t// r0-r3 get clobbered after the syscall returns\n\t\t\tconstraints += \",~{r\" + strconv.Itoa(i) + \"}\"\n\t\t}\n\t\tfnType := llvm.FunctionType(b.uintptrType, argTypes, false)\n\t\ttarget := llvm.InlineAsm(fnType, \"svc #0\", constraints, true, false, 0, false)\n\t\treturn b.CreateCall(fnType, target, args, \"\"), nil\n\n\tcase b.GOARCH == \"arm64\" && b.GOOS == \"linux\":\n\t\t// Source: syscall(2) man page.\n\t\targs := []llvm.Value{}\n\t\targTypes := []llvm.Type{}\n\t\t// Constraints will look something like:\n\t\t//   ={x0},0,{x1},{x2},{x8},~{x3},~{x4},~{x5},~{x6},~{x7},~{x16},~{x17}\n\t\tconstraints := \"={x0}\"\n\t\tfor i, arg := range call.Args[1:] {\n\t\t\tconstraints += \",\" + [...]string{\n\t\t\t\t\"0\", // tie to output\n\t\t\t\t\"{x1}\",\n\t\t\t\t\"{x2}\",\n\t\t\t\t\"{x3}\",\n\t\t\t\t\"{x4}\",\n\t\t\t\t\"{x5}\",\n\t\t\t}[i]\n\t\t\tllvmValue := b.getValue(arg, getPos(call))\n\t\t\targs = append(args, llvmValue)\n\t\t\targTypes = append(argTypes, llvmValue.Type())\n\t\t}\n\t\targs = append(args, num)\n\t\targTypes = append(argTypes, b.uintptrType)\n\t\tconstraints += \",{x8}\" // syscall number\n\t\tfor i := len(call.Args) - 1; i < 8; i++ {\n\t\t\t// x0-x7 may get clobbered during the syscall following the aarch64\n\t\t\t// calling convention.\n\t\t\tconstraints += \",~{x\" + strconv.Itoa(i) + \"}\"\n\t\t}\n\t\tconstraints += \",~{x16},~{x17}\" // scratch registers\n\t\tfnType := llvm.FunctionType(b.uintptrType, argTypes, false)\n\t\ttarget := llvm.InlineAsm(fnType, \"svc #0\", constraints, true, false, 0, false)\n\t\treturn b.CreateCall(fnType, target, args, \"\"), nil\n\n\tcase (b.GOARCH == \"mips\" || b.GOARCH == \"mipsle\") && b.GOOS == \"linux\":\n\t\t// Implement the system call convention for Linux.\n\t\t// Source: syscall(2) man page and musl:\n\t\t// https://git.musl-libc.org/cgit/musl/tree/arch/mips/syscall_arch.h\n\t\t// Also useful:\n\t\t// https://web.archive.org/web/20220529105937/https://www.linux-mips.org/wiki/Syscall\n\t\t// The syscall number goes in r2, the result also in r2.\n\t\t// Register r7 is both an input parameter and an output parameter: if it\n\t\t// is non-zero, the system call failed and r2 is the error code.\n\t\t// The code below implements the O32 syscall ABI, not the N32 ABI. It\n\t\t// could implement both at the same time if needed (like what appears to\n\t\t// be done in musl) by forcing arg5-arg7 into the right registers but\n\t\t// letting the compiler decide the registers should result in _slightly_\n\t\t// faster and smaller code.\n\t\targs := []llvm.Value{num}\n\t\targTypes := []llvm.Type{b.uintptrType}\n\t\tconstraints := \"={$2},={$7},0\"\n\t\tsyscallParams := call.Args[1:]\n\t\tif len(syscallParams) > 7 {\n\t\t\t// There is one syscall that uses 7 parameters: sync_file_range.\n\t\t\t// But only 7, not more. Go however only has Syscall6 and Syscall9.\n\t\t\t// Therefore, we can ignore the remaining parameters.\n\t\t\tsyscallParams = syscallParams[:7]\n\t\t}\n\t\tfor i, arg := range syscallParams {\n\t\t\tconstraints += \",\" + [...]string{\n\t\t\t\t\"{$4}\", // arg1\n\t\t\t\t\"{$5}\", // arg2\n\t\t\t\t\"{$6}\", // arg3\n\t\t\t\t\"1\",    // arg4, error return\n\t\t\t\t\"r\",    // arg5 on the stack\n\t\t\t\t\"r\",    // arg6 on the stack\n\t\t\t\t\"r\",    // arg7 on the stack\n\t\t\t}[i]\n\t\t\tllvmValue := b.getValue(arg, getPos(call))\n\t\t\targs = append(args, llvmValue)\n\t\t\targTypes = append(argTypes, llvmValue.Type())\n\t\t}\n\t\t// Create assembly code.\n\t\t// Parameters beyond the first 4 are passed on the stack instead of in\n\t\t// registers in the O32 syscall ABI.\n\t\t// We need \".set noat\" because LLVM might pick register $1 ($at) as the\n\t\t// register for a parameter and apparently this is not allowed on MIPS\n\t\t// unless you use this specific pragma.\n\t\tasm := \"syscall\"\n\t\tswitch len(syscallParams) {\n\t\tcase 5:\n\t\t\tasm = \"\" +\n\t\t\t\t\".set noat\\n\" +\n\t\t\t\t\"subu $$sp, $$sp, 32\\n\" +\n\t\t\t\t\"sw $7, 16($$sp)\\n\" + // arg5\n\t\t\t\t\"syscall\\n\" +\n\t\t\t\t\"addu $$sp, $$sp, 32\\n\" +\n\t\t\t\t\".set at\\n\"\n\t\tcase 6:\n\t\t\tasm = \"\" +\n\t\t\t\t\".set noat\\n\" +\n\t\t\t\t\"subu $$sp, $$sp, 32\\n\" +\n\t\t\t\t\"sw $7, 16($$sp)\\n\" + // arg5\n\t\t\t\t\"sw $8, 20($$sp)\\n\" + // arg6\n\t\t\t\t\"syscall\\n\" +\n\t\t\t\t\"addu $$sp, $$sp, 32\\n\" +\n\t\t\t\t\".set at\\n\"\n\t\tcase 7:\n\t\t\tasm = \"\" +\n\t\t\t\t\".set noat\\n\" +\n\t\t\t\t\"subu $$sp, $$sp, 32\\n\" +\n\t\t\t\t\"sw $7, 16($$sp)\\n\" + // arg5\n\t\t\t\t\"sw $8, 20($$sp)\\n\" + // arg6\n\t\t\t\t\"sw $9, 24($$sp)\\n\" + // arg7\n\t\t\t\t\"syscall\\n\" +\n\t\t\t\t\"addu $$sp, $$sp, 32\\n\" +\n\t\t\t\t\".set at\\n\"\n\t\t}\n\t\tconstraints += \",~{$3},~{$4},~{$5},~{$6},~{$8},~{$9},~{$10},~{$11},~{$12},~{$13},~{$14},~{$15},~{$24},~{$25},~{hi},~{lo},~{memory}\"\n\t\treturnType := b.ctx.StructType([]llvm.Type{b.uintptrType, b.uintptrType}, false)\n\t\tfnType := llvm.FunctionType(returnType, argTypes, false)\n\t\ttarget := llvm.InlineAsm(fnType, asm, constraints, true, true, 0, false)\n\t\tcall := b.CreateCall(fnType, target, args, \"\")\n\t\tresultCode := b.CreateExtractValue(call, 0, \"\") // r2\n\t\terrorFlag := b.CreateExtractValue(call, 1, \"\")  // r7\n\t\t// Pseudocode to return the result with the same convention as other\n\t\t// archs:\n\t\t//    return (errorFlag != 0) ? -resultCode : resultCode;\n\t\t// At least on QEMU with the O32 ABI, the error code is always positive.\n\t\tzero := llvm.ConstInt(b.uintptrType, 0, false)\n\t\tisError := b.CreateICmp(llvm.IntNE, errorFlag, zero, \"\")\n\t\tnegativeResult := b.CreateSub(zero, resultCode, \"\")\n\t\tresult := b.CreateSelect(isError, negativeResult, resultCode, \"\")\n\t\treturn result, nil\n\n\tdefault:\n\t\treturn llvm.Value{}, b.makeError(call.Pos(), \"unknown GOOS/GOARCH for syscall: \"+b.GOOS+\"/\"+b.GOARCH)\n\t}\n}\n\n// createSyscall emits instructions for the syscall.Syscall* family of\n// functions, depending on the target OS/arch.\nfunc (b *builder) createSyscall(call *ssa.CallCommon) (llvm.Value, error) {\n\tswitch b.GOOS {\n\tcase \"linux\":\n\t\tsyscallResult, err := b.createRawSyscall(call)\n\t\tif err != nil {\n\t\t\treturn syscallResult, err\n\t\t}\n\t\t// Return values: r0, r1 uintptr, err Errno\n\t\t// Pseudocode:\n\t\t//     var err uintptr\n\t\t//     if syscallResult < 0 && syscallResult > -4096 {\n\t\t//         err = -syscallResult\n\t\t//     }\n\t\t//     return syscallResult, 0, err\n\t\tzero := llvm.ConstInt(b.uintptrType, 0, false)\n\t\tinrange1 := b.CreateICmp(llvm.IntSLT, syscallResult, llvm.ConstInt(b.uintptrType, 0, false), \"\")\n\t\tinrange2 := b.CreateICmp(llvm.IntSGT, syscallResult, llvm.ConstInt(b.uintptrType, 0xfffffffffffff000, true), \"\") // -4096\n\t\thasError := b.CreateAnd(inrange1, inrange2, \"\")\n\t\terrResult := b.CreateSelect(hasError, b.CreateSub(zero, syscallResult, \"\"), zero, \"syscallError\")\n\t\tretval := llvm.Undef(b.ctx.StructType([]llvm.Type{b.uintptrType, b.uintptrType, b.uintptrType}, false))\n\t\tretval = b.CreateInsertValue(retval, syscallResult, 0, \"\")\n\t\tretval = b.CreateInsertValue(retval, zero, 1, \"\")\n\t\tretval = b.CreateInsertValue(retval, errResult, 2, \"\")\n\t\treturn retval, nil\n\tcase \"windows\":\n\t\t// On Windows, syscall.Syscall* is basically just a function pointer\n\t\t// call. This is complicated in gc because of stack switching and the\n\t\t// different ABI, but easy in TinyGo: just call the function pointer.\n\t\t// The signature looks like this:\n\t\t//   func Syscall(trap, nargs, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)\n\n\t\tisI386 := strings.HasPrefix(b.Triple, \"i386-\")\n\n\t\t// Prepare input values.\n\t\tvar paramTypes []llvm.Type\n\t\tvar params []llvm.Value\n\t\tfor _, val := range call.Args[2:] {\n\t\t\tparam := b.getValue(val, getPos(call))\n\t\t\tparams = append(params, param)\n\t\t\tparamTypes = append(paramTypes, param.Type())\n\t\t}\n\t\tllvmType := llvm.FunctionType(b.uintptrType, paramTypes, false)\n\t\tfn := b.getValue(call.Args[0], getPos(call))\n\t\tfnPtr := b.CreateIntToPtr(fn, b.dataPtrType, \"\")\n\n\t\t// Prepare some functions that will be called later.\n\t\tsetLastError := b.mod.NamedFunction(\"SetLastError\")\n\t\tif setLastError.IsNil() {\n\t\t\tllvmType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.ctx.Int32Type()}, false)\n\t\t\tsetLastError = llvm.AddFunction(b.mod, \"SetLastError\", llvmType)\n\t\t\tif isI386 {\n\t\t\t\tsetLastError.SetFunctionCallConv(llvm.X86StdcallCallConv)\n\t\t\t}\n\t\t}\n\t\tgetLastError := b.mod.NamedFunction(\"GetLastError\")\n\t\tif getLastError.IsNil() {\n\t\t\tllvmType := llvm.FunctionType(b.ctx.Int32Type(), nil, false)\n\t\t\tgetLastError = llvm.AddFunction(b.mod, \"GetLastError\", llvmType)\n\t\t\tif isI386 {\n\t\t\t\tgetLastError.SetFunctionCallConv(llvm.X86StdcallCallConv)\n\t\t\t}\n\t\t}\n\n\t\t// Now do the actual call. Pseudocode:\n\t\t//     SetLastError(0)\n\t\t//     r1 = trap(a1, a2, a3, ...)\n\t\t//     err = uintptr(GetLastError())\n\t\t//     return r1, 0, err\n\t\t// Note that SetLastError/GetLastError could be replaced with direct\n\t\t// access to the thread control block, which is probably smaller and\n\t\t// faster. The Go runtime does this in assembly.\n\t\t// On windows/386, we also need to save/restore the stack pointer. I'm\n\t\t// not entirely sure why this is needed, but without it these calls\n\t\t// change the stack pointer leading to a crash soon after.\n\t\tsetLastErrorCall := b.CreateCall(setLastError.GlobalValueType(), setLastError, []llvm.Value{llvm.ConstNull(b.ctx.Int32Type())}, \"\")\n\t\tvar sp llvm.Value\n\t\tif isI386 {\n\t\t\tsetLastErrorCall.SetInstructionCallConv(llvm.X86StdcallCallConv)\n\t\t\tsp = b.readStackPointer()\n\t\t}\n\t\tsyscallResult := b.CreateCall(llvmType, fnPtr, params, \"\")\n\t\tif isI386 {\n\t\t\tsyscallResult.SetInstructionCallConv(llvm.X86StdcallCallConv)\n\t\t\tb.writeStackPointer(sp)\n\t\t}\n\t\terrResult := b.CreateCall(getLastError.GlobalValueType(), getLastError, nil, \"err\")\n\t\tif isI386 {\n\t\t\terrResult.SetInstructionCallConv(llvm.X86StdcallCallConv)\n\t\t}\n\t\tif b.uintptrType != b.ctx.Int32Type() {\n\t\t\terrResult = b.CreateZExt(errResult, b.uintptrType, \"err.uintptr\")\n\t\t}\n\n\t\t// Return r1, 0, err\n\t\tretval := llvm.ConstNull(b.ctx.StructType([]llvm.Type{b.uintptrType, b.uintptrType, b.uintptrType}, false))\n\t\tretval = b.CreateInsertValue(retval, syscallResult, 0, \"\")\n\t\tretval = b.CreateInsertValue(retval, errResult, 2, \"\")\n\t\treturn retval, nil\n\n\tdefault:\n\t\treturn llvm.Value{}, b.makeError(call.Pos(), \"unknown GOOS/GOARCH for syscall: \"+b.GOOS+\"/\"+b.GOARCH)\n\t}\n}\n\n// createRawSyscallNoError emits instructions for the Linux-specific\n// syscall.rawSyscallNoError function.\nfunc (b *builder) createRawSyscallNoError(call *ssa.CallCommon) (llvm.Value, error) {\n\tsyscallResult, err := b.createRawSyscall(call)\n\tif err != nil {\n\t\treturn syscallResult, err\n\t}\n\tretval := llvm.ConstNull(b.ctx.StructType([]llvm.Type{b.uintptrType, b.uintptrType}, false))\n\tretval = b.CreateInsertValue(retval, syscallResult, 0, \"\")\n\tretval = b.CreateInsertValue(retval, llvm.ConstInt(b.uintptrType, 0, false), 1, \"\")\n\treturn retval, nil\n}\n\n// Lower a call to internal/abi.FuncPCABI0 on MacOS.\n// This function is called like this:\n//\n//\tsyscall(abi.FuncPCABI0(libc_mkdir_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)\n//\n// So we'll want to return a function pointer (as uintptr) that points to the\n// libc function. Specifically, we _don't_ want to point to the trampoline\n// function (which is implemented in Go assembly which we can't read), but\n// rather to the actually intended function. For this we're going to assume that\n// all the functions follow a specific pattern: libc_<functionname>_trampoline.\n//\n// The return value is the function pointer as an uintptr, or a nil value if\n// this isn't possible (and a regular call should be made as fallback).\nfunc (b *builder) createDarwinFuncPCABI0Call(instr *ssa.CallCommon) llvm.Value {\n\tif b.GOOS != \"darwin\" {\n\t\t// This has only been tested on MacOS (and only seems to be used there).\n\t\treturn llvm.Value{}\n\t}\n\n\t// Check that it uses a function call like syscall.libc_*_trampoline\n\titf := instr.Args[0].(*ssa.MakeInterface)\n\tcalledFn := itf.X.(*ssa.Function)\n\tif pkgName := calledFn.Pkg.Pkg.Path(); pkgName != \"syscall\" && pkgName != \"internal/syscall/unix\" {\n\t\treturn llvm.Value{}\n\t}\n\tif !strings.HasPrefix(calledFn.Name(), \"libc_\") || !strings.HasSuffix(calledFn.Name(), \"_trampoline\") {\n\n\t\treturn llvm.Value{}\n\t}\n\n\t// Extract the libc function name.\n\tname := strings.TrimPrefix(strings.TrimSuffix(calledFn.Name(), \"_trampoline\"), \"libc_\")\n\tif name == \"open\" {\n\t\t// Special case: open() is a variadic function and can't be called like\n\t\t// a regular function. Therefore, we need to use a wrapper implemented\n\t\t// in C.\n\t\tname = \"syscall_libc_open\"\n\t}\n\tif b.GOARCH == \"amd64\" {\n\t\tif name == \"fdopendir\" || name == \"readdir_r\" {\n\t\t\t// Hack to support amd64, which needs the $INODE64 suffix.\n\t\t\t// This is also done in upstream Go:\n\t\t\t// https://github.com/golang/go/commit/096ab3c21b88ccc7d411379d09fe6274e3159467\n\t\t\tname += \"$INODE64\"\n\t\t}\n\t}\n\n\t// Obtain the C function.\n\t// Use a simple function (no parameters or return value) because all we need\n\t// is the address of the function.\n\tllvmFn := b.mod.NamedFunction(name)\n\tif llvmFn.IsNil() {\n\t\tllvmFnType := llvm.FunctionType(b.ctx.VoidType(), nil, false)\n\t\tllvmFn = llvm.AddFunction(b.mod, name, llvmFnType)\n\t}\n\n\t// Cast the function pointer to a uintptr (because that's what\n\t// abi.FuncPCABI0 returns).\n\treturn b.CreatePtrToInt(llvmFn, b.uintptrType, \"\")\n}\n"
  },
  {
    "path": "compiler/testdata/basic.go",
    "content": "package main\n\n// Basic tests that don't need to be split into a separate file.\n\nfunc addInt(x, y int) int {\n\treturn x + y\n}\n\nfunc equalInt(x, y int) bool {\n\treturn x == y\n}\n\nfunc divInt(x, y int) int {\n\treturn x / y\n}\n\nfunc divUint(x, y uint) uint {\n\treturn x / y\n}\n\nfunc remInt(x, y int) int {\n\treturn x % y\n}\n\nfunc remUint(x, y uint) uint {\n\treturn x % y\n}\n\nfunc floatEQ(x, y float32) bool {\n\treturn x == y\n}\n\nfunc floatNE(x, y float32) bool {\n\treturn x != y\n}\n\nfunc floatLower(x, y float32) bool {\n\treturn x < y\n}\n\nfunc floatLowerEqual(x, y float32) bool {\n\treturn x <= y\n}\n\nfunc floatGreater(x, y float32) bool {\n\treturn x > y\n}\n\nfunc floatGreaterEqual(x, y float32) bool {\n\treturn x >= y\n}\n\nfunc complexReal(x complex64) float32 {\n\treturn real(x)\n}\n\nfunc complexImag(x complex64) float32 {\n\treturn imag(x)\n}\n\nfunc complexAdd(x, y complex64) complex64 {\n\treturn x + y\n}\n\nfunc complexSub(x, y complex64) complex64 {\n\treturn x - y\n}\n\nfunc complexMul(x, y complex64) complex64 {\n\treturn x * y\n}\n\n// TODO: complexDiv (requires runtime call)\n\n// A type 'kv' also exists in function foo. Test that these two types don't\n// conflict with each other.\ntype kv struct {\n\tv       float32\n\tx, y, z int\n}\n\nvar kvGlobal kv\n\nfunc foo() {\n\t// Define a new 'kv' type.\n\ttype kv struct {\n\t\tv       byte\n\t\tx, y, z int\n\t}\n\t// Use this type.\n\tfunc(b kv) {}(kv{})\n}\n\ntype T1 []T1\ntype T2 [2]*T2\n\nvar a T1\nvar b T2\n"
  },
  {
    "path": "compiler/testdata/basic.ll",
    "content": "; ModuleID = 'basic.go'\nsource_filename = \"basic.go\"\ntarget datalayout = \"e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20\"\ntarget triple = \"wasm32-unknown-wasi\"\n\n%main.kv = type { float, i32, i32, i32 }\n%main.kv.0 = type { i8, i32, i32, i32 }\n\n@main.kvGlobal = hidden global %main.kv zeroinitializer, align 4\n@main.a = hidden global { ptr, i32, i32 } zeroinitializer, align 4\n@main.b = hidden global [2 x ptr] zeroinitializer, align 4\n\n; Function Attrs: allockind(\"alloc,zeroed\") allocsize(0)\ndeclare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0\n\ndeclare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden void @main.init(ptr %context) unnamed_addr #2 {\nentry:\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden i32 @main.addInt(i32 %x, i32 %y, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = add i32 %x, %y\n  ret i32 %0\n}\n\n; Function Attrs: nounwind\ndefine hidden i1 @main.equalInt(i32 %x, i32 %y, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = icmp eq i32 %x, %y\n  ret i1 %0\n}\n\n; Function Attrs: nounwind\ndefine hidden i32 @main.divInt(i32 %x, i32 %y, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = icmp eq i32 %y, 0\n  br i1 %0, label %divbyzero.throw, label %divbyzero.next\n\ndivbyzero.next:                                   ; preds = %entry\n  %1 = icmp eq i32 %y, -1\n  %2 = icmp eq i32 %x, -2147483648\n  %3 = and i1 %1, %2\n  %4 = select i1 %3, i32 1, i32 %y\n  %5 = sdiv i32 %x, %4\n  ret i32 %5\n\ndivbyzero.throw:                                  ; preds = %entry\n  call void @runtime.divideByZeroPanic(ptr undef) #3\n  unreachable\n}\n\ndeclare void @runtime.divideByZeroPanic(ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden i32 @main.divUint(i32 %x, i32 %y, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = icmp eq i32 %y, 0\n  br i1 %0, label %divbyzero.throw, label %divbyzero.next\n\ndivbyzero.next:                                   ; preds = %entry\n  %1 = udiv i32 %x, %y\n  ret i32 %1\n\ndivbyzero.throw:                                  ; preds = %entry\n  call void @runtime.divideByZeroPanic(ptr undef) #3\n  unreachable\n}\n\n; Function Attrs: nounwind\ndefine hidden i32 @main.remInt(i32 %x, i32 %y, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = icmp eq i32 %y, 0\n  br i1 %0, label %divbyzero.throw, label %divbyzero.next\n\ndivbyzero.next:                                   ; preds = %entry\n  %1 = icmp eq i32 %y, -1\n  %2 = icmp eq i32 %x, -2147483648\n  %3 = and i1 %1, %2\n  %4 = select i1 %3, i32 1, i32 %y\n  %5 = srem i32 %x, %4\n  ret i32 %5\n\ndivbyzero.throw:                                  ; preds = %entry\n  call void @runtime.divideByZeroPanic(ptr undef) #3\n  unreachable\n}\n\n; Function Attrs: nounwind\ndefine hidden i32 @main.remUint(i32 %x, i32 %y, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = icmp eq i32 %y, 0\n  br i1 %0, label %divbyzero.throw, label %divbyzero.next\n\ndivbyzero.next:                                   ; preds = %entry\n  %1 = urem i32 %x, %y\n  ret i32 %1\n\ndivbyzero.throw:                                  ; preds = %entry\n  call void @runtime.divideByZeroPanic(ptr undef) #3\n  unreachable\n}\n\n; Function Attrs: nounwind\ndefine hidden i1 @main.floatEQ(float %x, float %y, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = fcmp oeq float %x, %y\n  ret i1 %0\n}\n\n; Function Attrs: nounwind\ndefine hidden i1 @main.floatNE(float %x, float %y, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = fcmp une float %x, %y\n  ret i1 %0\n}\n\n; Function Attrs: nounwind\ndefine hidden i1 @main.floatLower(float %x, float %y, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = fcmp olt float %x, %y\n  ret i1 %0\n}\n\n; Function Attrs: nounwind\ndefine hidden i1 @main.floatLowerEqual(float %x, float %y, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = fcmp ole float %x, %y\n  ret i1 %0\n}\n\n; Function Attrs: nounwind\ndefine hidden i1 @main.floatGreater(float %x, float %y, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = fcmp ogt float %x, %y\n  ret i1 %0\n}\n\n; Function Attrs: nounwind\ndefine hidden i1 @main.floatGreaterEqual(float %x, float %y, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = fcmp oge float %x, %y\n  ret i1 %0\n}\n\n; Function Attrs: nounwind\ndefine hidden float @main.complexReal(float %x.r, float %x.i, ptr %context) unnamed_addr #2 {\nentry:\n  ret float %x.r\n}\n\n; Function Attrs: nounwind\ndefine hidden float @main.complexImag(float %x.r, float %x.i, ptr %context) unnamed_addr #2 {\nentry:\n  ret float %x.i\n}\n\n; Function Attrs: nounwind\ndefine hidden { float, float } @main.complexAdd(float %x.r, float %x.i, float %y.r, float %y.i, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = fadd float %x.r, %y.r\n  %1 = fadd float %x.i, %y.i\n  %2 = insertvalue { float, float } undef, float %0, 0\n  %3 = insertvalue { float, float } %2, float %1, 1\n  ret { float, float } %3\n}\n\n; Function Attrs: nounwind\ndefine hidden { float, float } @main.complexSub(float %x.r, float %x.i, float %y.r, float %y.i, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = fsub float %x.r, %y.r\n  %1 = fsub float %x.i, %y.i\n  %2 = insertvalue { float, float } undef, float %0, 0\n  %3 = insertvalue { float, float } %2, float %1, 1\n  ret { float, float } %3\n}\n\n; Function Attrs: nounwind\ndefine hidden { float, float } @main.complexMul(float %x.r, float %x.i, float %y.r, float %y.i, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = fmul float %x.r, %y.r\n  %1 = fmul float %x.i, %y.i\n  %2 = fsub float %0, %1\n  %3 = fmul float %x.r, %y.i\n  %4 = fmul float %x.i, %y.r\n  %5 = fadd float %3, %4\n  %6 = insertvalue { float, float } undef, float %2, 0\n  %7 = insertvalue { float, float } %6, float %5, 1\n  ret { float, float } %7\n}\n\n; Function Attrs: nounwind\ndefine hidden void @main.foo(ptr %context) unnamed_addr #2 {\nentry:\n  call void @\"main.foo$1\"(%main.kv.0 zeroinitializer, ptr undef)\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine internal void @\"main.foo$1\"(%main.kv.0 %b, ptr %context) unnamed_addr #2 {\nentry:\n  ret void\n}\n\nattributes #0 = { allockind(\"alloc,zeroed\") allocsize(0) \"alloc-family\"=\"runtime.alloc\" \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #1 = { \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #2 = { nounwind \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #3 = { nounwind }\n"
  },
  {
    "path": "compiler/testdata/channel.go",
    "content": "package main\n\nfunc chanIntSend(ch chan int) {\n\tch <- 3\n}\n\nfunc chanIntRecv(ch chan int) {\n\t<-ch\n}\n\nfunc chanZeroSend(ch chan struct{}) {\n\tch <- struct{}{}\n}\n\nfunc chanZeroRecv(ch chan struct{}) {\n\t<-ch\n}\n\nfunc selectZeroRecv(ch1 chan int, ch2 chan struct{}) {\n\tselect {\n\tcase ch1 <- 1:\n\tcase <-ch2:\n\tdefault:\n\t}\n}\n"
  },
  {
    "path": "compiler/testdata/channel.ll",
    "content": "; ModuleID = 'channel.go'\nsource_filename = \"channel.go\"\ntarget datalayout = \"e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20\"\ntarget triple = \"wasm32-unknown-wasi\"\n\n%runtime.channelOp = type { ptr, ptr, i32, ptr }\n%runtime.chanSelectState = type { ptr, ptr }\n\n; Function Attrs: allockind(\"alloc,zeroed\") allocsize(0)\ndeclare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0\n\ndeclare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden void @main.init(ptr %context) unnamed_addr #2 {\nentry:\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden void @main.chanIntSend(ptr dereferenceable_or_null(36) %ch, ptr %context) unnamed_addr #2 {\nentry:\n  %chan.op = alloca %runtime.channelOp, align 8\n  %chan.value = alloca i32, align 4\n  call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %chan.value)\n  store i32 3, ptr %chan.value, align 4\n  call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %chan.op)\n  call void @runtime.chanSend(ptr %ch, ptr nonnull %chan.value, ptr nonnull %chan.op, ptr undef) #4\n  call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %chan.op)\n  call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %chan.value)\n  ret void\n}\n\n; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)\ndeclare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #3\n\ndeclare void @runtime.chanSend(ptr dereferenceable_or_null(36), ptr, ptr dereferenceable_or_null(16), ptr) #1\n\n; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)\ndeclare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #3\n\n; Function Attrs: nounwind\ndefine hidden void @main.chanIntRecv(ptr dereferenceable_or_null(36) %ch, ptr %context) unnamed_addr #2 {\nentry:\n  %chan.op = alloca %runtime.channelOp, align 8\n  %chan.value = alloca i32, align 4\n  call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %chan.value)\n  call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %chan.op)\n  %0 = call i1 @runtime.chanRecv(ptr %ch, ptr nonnull %chan.value, ptr nonnull %chan.op, ptr undef) #4\n  call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %chan.value)\n  call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %chan.op)\n  ret void\n}\n\ndeclare i1 @runtime.chanRecv(ptr dereferenceable_or_null(36), ptr, ptr dereferenceable_or_null(16), ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden void @main.chanZeroSend(ptr dereferenceable_or_null(36) %ch, ptr %context) unnamed_addr #2 {\nentry:\n  %chan.op = alloca %runtime.channelOp, align 8\n  call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %chan.op)\n  call void @runtime.chanSend(ptr %ch, ptr null, ptr nonnull %chan.op, ptr undef) #4\n  call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %chan.op)\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden void @main.chanZeroRecv(ptr dereferenceable_or_null(36) %ch, ptr %context) unnamed_addr #2 {\nentry:\n  %chan.op = alloca %runtime.channelOp, align 8\n  call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %chan.op)\n  %0 = call i1 @runtime.chanRecv(ptr %ch, ptr null, ptr nonnull %chan.op, ptr undef) #4\n  call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %chan.op)\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden void @main.selectZeroRecv(ptr dereferenceable_or_null(36) %ch1, ptr dereferenceable_or_null(36) %ch2, ptr %context) unnamed_addr #2 {\nentry:\n  %select.states.alloca = alloca [2 x %runtime.chanSelectState], align 8\n  %select.send.value = alloca i32, align 4\n  store i32 1, ptr %select.send.value, align 4\n  call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %select.states.alloca)\n  store ptr %ch1, ptr %select.states.alloca, align 4\n  %select.states.alloca.repack1 = getelementptr inbounds nuw i8, ptr %select.states.alloca, i32 4\n  store ptr %select.send.value, ptr %select.states.alloca.repack1, align 4\n  %0 = getelementptr inbounds nuw i8, ptr %select.states.alloca, i32 8\n  store ptr %ch2, ptr %0, align 4\n  %.repack3 = getelementptr inbounds nuw i8, ptr %select.states.alloca, i32 12\n  store ptr null, ptr %.repack3, align 4\n  %select.result = call { i32, i1 } @runtime.chanSelect(ptr undef, ptr nonnull %select.states.alloca, i32 2, i32 2, ptr null, i32 0, i32 0, ptr undef) #4\n  call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %select.states.alloca)\n  %1 = extractvalue { i32, i1 } %select.result, 0\n  %2 = icmp eq i32 %1, 0\n  br i1 %2, label %select.done, label %select.next\n\nselect.done:                                      ; preds = %select.body, %select.next, %entry\n  ret void\n\nselect.next:                                      ; preds = %entry\n  %3 = icmp eq i32 %1, 1\n  br i1 %3, label %select.body, label %select.done\n\nselect.body:                                      ; preds = %select.next\n  br label %select.done\n}\n\ndeclare { i32, i1 } @runtime.chanSelect(ptr, ptr, i32, i32, ptr, i32, i32, ptr) #1\n\nattributes #0 = { allockind(\"alloc,zeroed\") allocsize(0) \"alloc-family\"=\"runtime.alloc\" \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #1 = { \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #2 = { nounwind \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #3 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }\nattributes #4 = { nounwind }\n"
  },
  {
    "path": "compiler/testdata/defer-cortex-m-qemu.ll",
    "content": "; ModuleID = 'defer.go'\nsource_filename = \"defer.go\"\ntarget datalayout = \"e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64\"\ntarget triple = \"thumbv7m-unknown-unknown-eabi\"\n\n%runtime.deferFrame = type { ptr, ptr, [0 x ptr], ptr, i8, %runtime._interface }\n%runtime._interface = type { ptr, ptr }\n\n; Function Attrs: allockind(\"alloc,zeroed\") allocsize(0)\ndeclare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0\n\n; Function Attrs: nounwind\ndefine hidden void @main.init(ptr %context) unnamed_addr #1 {\nentry:\n  ret void\n}\n\ndeclare void @main.external(ptr) #2\n\n; Function Attrs: nounwind\ndefine hidden void @main.deferSimple(ptr %context) unnamed_addr #1 {\nentry:\n  %defer.alloca = alloca { i32, ptr }, align 4\n  %deferPtr = alloca ptr, align 4\n  store ptr null, ptr %deferPtr, align 4\n  %deferframe.buf = alloca %runtime.deferFrame, align 4\n  %0 = call ptr @llvm.stacksave.p0()\n  call void @runtime.setupDeferFrame(ptr nonnull %deferframe.buf, ptr %0, ptr undef) #4\n  store i32 0, ptr %defer.alloca, align 4\n  %defer.alloca.repack15 = getelementptr inbounds nuw i8, ptr %defer.alloca, i32 4\n  store ptr null, ptr %defer.alloca.repack15, align 4\n  store ptr %defer.alloca, ptr %deferPtr, align 4\n  %setjmp = call i32 asm \"\\0Amovs r0, #0\\0Amov r2, pc\\0Astr r2, [r1, #4]\", \"={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}\"(ptr nonnull %deferframe.buf) #5\n  %setjmp.result = icmp eq i32 %setjmp, 0\n  br i1 %setjmp.result, label %1, label %lpad\n\n1:                                                ; preds = %entry\n  call void @main.external(ptr undef) #4\n  br label %rundefers.block\n\nrundefers.after:                                  ; preds = %rundefers.end\n  call void @runtime.destroyDeferFrame(ptr nonnull %deferframe.buf, ptr undef) #4\n  ret void\n\nrundefers.block:                                  ; preds = %1\n  br label %rundefers.loophead\n\nrundefers.loophead:                               ; preds = %3, %rundefers.block\n  %2 = load ptr, ptr %deferPtr, align 4\n  %stackIsNil = icmp eq ptr %2, null\n  br i1 %stackIsNil, label %rundefers.end, label %rundefers.loop\n\nrundefers.loop:                                   ; preds = %rundefers.loophead\n  %stack.next.gep = getelementptr inbounds nuw i8, ptr %2, i32 4\n  %stack.next = load ptr, ptr %stack.next.gep, align 4\n  store ptr %stack.next, ptr %deferPtr, align 4\n  %callback = load i32, ptr %2, align 4\n  switch i32 %callback, label %rundefers.default [\n    i32 0, label %rundefers.callback0\n  ]\n\nrundefers.callback0:                              ; preds = %rundefers.loop\n  %setjmp1 = call i32 asm \"\\0Amovs r0, #0\\0Amov r2, pc\\0Astr r2, [r1, #4]\", \"={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}\"(ptr nonnull %deferframe.buf) #5\n  %setjmp.result2 = icmp eq i32 %setjmp1, 0\n  br i1 %setjmp.result2, label %3, label %lpad\n\n3:                                                ; preds = %rundefers.callback0\n  call void @\"main.deferSimple$1\"(ptr undef)\n  br label %rundefers.loophead\n\nrundefers.default:                                ; preds = %rundefers.loop\n  unreachable\n\nrundefers.end:                                    ; preds = %rundefers.loophead\n  br label %rundefers.after\n\nrecover:                                          ; preds = %rundefers.end3\n  call void @runtime.destroyDeferFrame(ptr nonnull %deferframe.buf, ptr undef) #4\n  ret void\n\nlpad:                                             ; preds = %rundefers.callback012, %rundefers.callback0, %entry\n  br label %rundefers.loophead6\n\nrundefers.loophead6:                              ; preds = %5, %lpad\n  %4 = load ptr, ptr %deferPtr, align 4\n  %stackIsNil7 = icmp eq ptr %4, null\n  br i1 %stackIsNil7, label %rundefers.end3, label %rundefers.loop5\n\nrundefers.loop5:                                  ; preds = %rundefers.loophead6\n  %stack.next.gep8 = getelementptr inbounds nuw i8, ptr %4, i32 4\n  %stack.next9 = load ptr, ptr %stack.next.gep8, align 4\n  store ptr %stack.next9, ptr %deferPtr, align 4\n  %callback11 = load i32, ptr %4, align 4\n  switch i32 %callback11, label %rundefers.default4 [\n    i32 0, label %rundefers.callback012\n  ]\n\nrundefers.callback012:                            ; preds = %rundefers.loop5\n  %setjmp13 = call i32 asm \"\\0Amovs r0, #0\\0Amov r2, pc\\0Astr r2, [r1, #4]\", \"={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}\"(ptr nonnull %deferframe.buf) #5\n  %setjmp.result14 = icmp eq i32 %setjmp13, 0\n  br i1 %setjmp.result14, label %5, label %lpad\n\n5:                                                ; preds = %rundefers.callback012\n  call void @\"main.deferSimple$1\"(ptr undef)\n  br label %rundefers.loophead6\n\nrundefers.default4:                               ; preds = %rundefers.loop5\n  unreachable\n\nrundefers.end3:                                   ; preds = %rundefers.loophead6\n  br label %recover\n}\n\n; Function Attrs: nocallback nofree nosync nounwind willreturn\ndeclare ptr @llvm.stacksave.p0() #3\n\ndeclare void @runtime.setupDeferFrame(ptr dereferenceable_or_null(24), ptr, ptr) #2\n\ndeclare void @runtime.destroyDeferFrame(ptr dereferenceable_or_null(24), ptr) #2\n\n; Function Attrs: nounwind\ndefine internal void @\"main.deferSimple$1\"(ptr %context) unnamed_addr #1 {\nentry:\n  call void @runtime.printlock(ptr undef) #4\n  call void @runtime.printint32(i32 3, ptr undef) #4\n  call void @runtime.printunlock(ptr undef) #4\n  ret void\n}\n\ndeclare void @runtime.printlock(ptr) #2\n\ndeclare void @runtime.printint32(i32, ptr) #2\n\ndeclare void @runtime.printunlock(ptr) #2\n\n; Function Attrs: nounwind\ndefine hidden void @main.deferMultiple(ptr %context) unnamed_addr #1 {\nentry:\n  %defer.alloca2 = alloca { i32, ptr }, align 4\n  %defer.alloca = alloca { i32, ptr }, align 4\n  %deferPtr = alloca ptr, align 4\n  store ptr null, ptr %deferPtr, align 4\n  %deferframe.buf = alloca %runtime.deferFrame, align 4\n  %0 = call ptr @llvm.stacksave.p0()\n  call void @runtime.setupDeferFrame(ptr nonnull %deferframe.buf, ptr %0, ptr undef) #4\n  store i32 0, ptr %defer.alloca, align 4\n  %defer.alloca.repack22 = getelementptr inbounds nuw i8, ptr %defer.alloca, i32 4\n  store ptr null, ptr %defer.alloca.repack22, align 4\n  store ptr %defer.alloca, ptr %deferPtr, align 4\n  store i32 1, ptr %defer.alloca2, align 4\n  %defer.alloca2.repack23 = getelementptr inbounds nuw i8, ptr %defer.alloca2, i32 4\n  store ptr %defer.alloca, ptr %defer.alloca2.repack23, align 4\n  store ptr %defer.alloca2, ptr %deferPtr, align 4\n  %setjmp = call i32 asm \"\\0Amovs r0, #0\\0Amov r2, pc\\0Astr r2, [r1, #4]\", \"={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}\"(ptr nonnull %deferframe.buf) #5\n  %setjmp.result = icmp eq i32 %setjmp, 0\n  br i1 %setjmp.result, label %1, label %lpad\n\n1:                                                ; preds = %entry\n  call void @main.external(ptr undef) #4\n  br label %rundefers.block\n\nrundefers.after:                                  ; preds = %rundefers.end\n  call void @runtime.destroyDeferFrame(ptr nonnull %deferframe.buf, ptr undef) #4\n  ret void\n\nrundefers.block:                                  ; preds = %1\n  br label %rundefers.loophead\n\nrundefers.loophead:                               ; preds = %4, %3, %rundefers.block\n  %2 = load ptr, ptr %deferPtr, align 4\n  %stackIsNil = icmp eq ptr %2, null\n  br i1 %stackIsNil, label %rundefers.end, label %rundefers.loop\n\nrundefers.loop:                                   ; preds = %rundefers.loophead\n  %stack.next.gep = getelementptr inbounds nuw i8, ptr %2, i32 4\n  %stack.next = load ptr, ptr %stack.next.gep, align 4\n  store ptr %stack.next, ptr %deferPtr, align 4\n  %callback = load i32, ptr %2, align 4\n  switch i32 %callback, label %rundefers.default [\n    i32 0, label %rundefers.callback0\n    i32 1, label %rundefers.callback1\n  ]\n\nrundefers.callback0:                              ; preds = %rundefers.loop\n  %setjmp3 = call i32 asm \"\\0Amovs r0, #0\\0Amov r2, pc\\0Astr r2, [r1, #4]\", \"={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}\"(ptr nonnull %deferframe.buf) #5\n  %setjmp.result4 = icmp eq i32 %setjmp3, 0\n  br i1 %setjmp.result4, label %3, label %lpad\n\n3:                                                ; preds = %rundefers.callback0\n  call void @\"main.deferMultiple$1\"(ptr undef)\n  br label %rundefers.loophead\n\nrundefers.callback1:                              ; preds = %rundefers.loop\n  %setjmp5 = call i32 asm \"\\0Amovs r0, #0\\0Amov r2, pc\\0Astr r2, [r1, #4]\", \"={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}\"(ptr nonnull %deferframe.buf) #5\n  %setjmp.result6 = icmp eq i32 %setjmp5, 0\n  br i1 %setjmp.result6, label %4, label %lpad\n\n4:                                                ; preds = %rundefers.callback1\n  call void @\"main.deferMultiple$2\"(ptr undef)\n  br label %rundefers.loophead\n\nrundefers.default:                                ; preds = %rundefers.loop\n  unreachable\n\nrundefers.end:                                    ; preds = %rundefers.loophead\n  br label %rundefers.after\n\nrecover:                                          ; preds = %rundefers.end7\n  call void @runtime.destroyDeferFrame(ptr nonnull %deferframe.buf, ptr undef) #4\n  ret void\n\nlpad:                                             ; preds = %rundefers.callback119, %rundefers.callback016, %rundefers.callback1, %rundefers.callback0, %entry\n  br label %rundefers.loophead10\n\nrundefers.loophead10:                             ; preds = %7, %6, %lpad\n  %5 = load ptr, ptr %deferPtr, align 4\n  %stackIsNil11 = icmp eq ptr %5, null\n  br i1 %stackIsNil11, label %rundefers.end7, label %rundefers.loop9\n\nrundefers.loop9:                                  ; preds = %rundefers.loophead10\n  %stack.next.gep12 = getelementptr inbounds nuw i8, ptr %5, i32 4\n  %stack.next13 = load ptr, ptr %stack.next.gep12, align 4\n  store ptr %stack.next13, ptr %deferPtr, align 4\n  %callback15 = load i32, ptr %5, align 4\n  switch i32 %callback15, label %rundefers.default8 [\n    i32 0, label %rundefers.callback016\n    i32 1, label %rundefers.callback119\n  ]\n\nrundefers.callback016:                            ; preds = %rundefers.loop9\n  %setjmp17 = call i32 asm \"\\0Amovs r0, #0\\0Amov r2, pc\\0Astr r2, [r1, #4]\", \"={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}\"(ptr nonnull %deferframe.buf) #5\n  %setjmp.result18 = icmp eq i32 %setjmp17, 0\n  br i1 %setjmp.result18, label %6, label %lpad\n\n6:                                                ; preds = %rundefers.callback016\n  call void @\"main.deferMultiple$1\"(ptr undef)\n  br label %rundefers.loophead10\n\nrundefers.callback119:                            ; preds = %rundefers.loop9\n  %setjmp20 = call i32 asm \"\\0Amovs r0, #0\\0Amov r2, pc\\0Astr r2, [r1, #4]\", \"={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}\"(ptr nonnull %deferframe.buf) #5\n  %setjmp.result21 = icmp eq i32 %setjmp20, 0\n  br i1 %setjmp.result21, label %7, label %lpad\n\n7:                                                ; preds = %rundefers.callback119\n  call void @\"main.deferMultiple$2\"(ptr undef)\n  br label %rundefers.loophead10\n\nrundefers.default8:                               ; preds = %rundefers.loop9\n  unreachable\n\nrundefers.end7:                                   ; preds = %rundefers.loophead10\n  br label %recover\n}\n\n; Function Attrs: nounwind\ndefine internal void @\"main.deferMultiple$1\"(ptr %context) unnamed_addr #1 {\nentry:\n  call void @runtime.printlock(ptr undef) #4\n  call void @runtime.printint32(i32 3, ptr undef) #4\n  call void @runtime.printunlock(ptr undef) #4\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine internal void @\"main.deferMultiple$2\"(ptr %context) unnamed_addr #1 {\nentry:\n  call void @runtime.printlock(ptr undef) #4\n  call void @runtime.printint32(i32 5, ptr undef) #4\n  call void @runtime.printunlock(ptr undef) #4\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden void @main.deferInfiniteLoop(ptr %context) unnamed_addr #1 {\nentry:\n  %deferPtr = alloca ptr, align 4\n  store ptr null, ptr %deferPtr, align 4\n  %deferframe.buf = alloca %runtime.deferFrame, align 4\n  %0 = call ptr @llvm.stacksave.p0()\n  call void @runtime.setupDeferFrame(ptr nonnull %deferframe.buf, ptr %0, ptr undef) #4\n  br label %for.body\n\nfor.body:                                         ; preds = %for.body, %entry\n  %defer.next = load ptr, ptr %deferPtr, align 4\n  %defer.alloc.call = call dereferenceable(12) ptr @runtime.alloc(i32 12, ptr null, ptr undef) #4\n  store i32 0, ptr %defer.alloc.call, align 4\n  %defer.alloc.call.repack1 = getelementptr inbounds nuw i8, ptr %defer.alloc.call, i32 4\n  store ptr %defer.next, ptr %defer.alloc.call.repack1, align 4\n  %defer.alloc.call.repack3 = getelementptr inbounds nuw i8, ptr %defer.alloc.call, i32 8\n  store i32 8, ptr %defer.alloc.call.repack3, align 4\n  store ptr %defer.alloc.call, ptr %deferPtr, align 4\n  br label %for.body\n\nrecover:                                          ; preds = %rundefers.end\n  ret void\n\nlpad:                                             ; No predecessors!\n  br label %rundefers.loophead\n\nrundefers.loophead:                               ; preds = %rundefers.callback0, %lpad\n  br i1 poison, label %rundefers.end, label %rundefers.loop\n\nrundefers.loop:                                   ; preds = %rundefers.loophead\n  switch i32 poison, label %rundefers.default [\n    i32 0, label %rundefers.callback0\n  ]\n\nrundefers.callback0:                              ; preds = %rundefers.loop\n  br label %rundefers.loophead\n\nrundefers.default:                                ; preds = %rundefers.loop\n  unreachable\n\nrundefers.end:                                    ; preds = %rundefers.loophead\n  br label %recover\n}\n\n; Function Attrs: nounwind\ndefine hidden void @main.deferLoop(ptr %context) unnamed_addr #1 {\nentry:\n  %deferPtr = alloca ptr, align 4\n  store ptr null, ptr %deferPtr, align 4\n  %deferframe.buf = alloca %runtime.deferFrame, align 4\n  %0 = call ptr @llvm.stacksave.p0()\n  call void @runtime.setupDeferFrame(ptr nonnull %deferframe.buf, ptr %0, ptr undef) #4\n  br label %for.loop\n\nfor.loop:                                         ; preds = %for.body, %entry\n  %1 = phi i32 [ 0, %entry ], [ %3, %for.body ]\n  %2 = icmp slt i32 %1, 10\n  br i1 %2, label %for.body, label %for.done\n\nfor.body:                                         ; preds = %for.loop\n  %defer.next = load ptr, ptr %deferPtr, align 4\n  %defer.alloc.call = call dereferenceable(12) ptr @runtime.alloc(i32 12, ptr null, ptr undef) #4\n  store i32 0, ptr %defer.alloc.call, align 4\n  %defer.alloc.call.repack13 = getelementptr inbounds nuw i8, ptr %defer.alloc.call, i32 4\n  store ptr %defer.next, ptr %defer.alloc.call.repack13, align 4\n  %defer.alloc.call.repack15 = getelementptr inbounds nuw i8, ptr %defer.alloc.call, i32 8\n  store i32 %1, ptr %defer.alloc.call.repack15, align 4\n  store ptr %defer.alloc.call, ptr %deferPtr, align 4\n  %3 = add i32 %1, 1\n  br label %for.loop\n\nfor.done:                                         ; preds = %for.loop\n  br label %rundefers.block\n\nrundefers.after:                                  ; preds = %rundefers.end\n  call void @runtime.destroyDeferFrame(ptr nonnull %deferframe.buf, ptr undef) #4\n  ret void\n\nrundefers.block:                                  ; preds = %for.done\n  br label %rundefers.loophead\n\nrundefers.loophead:                               ; preds = %rundefers.callback0, %rundefers.block\n  %4 = load ptr, ptr %deferPtr, align 4\n  %stackIsNil = icmp eq ptr %4, null\n  br i1 %stackIsNil, label %rundefers.end, label %rundefers.loop\n\nrundefers.loop:                                   ; preds = %rundefers.loophead\n  %stack.next.gep = getelementptr inbounds nuw i8, ptr %4, i32 4\n  %stack.next = load ptr, ptr %stack.next.gep, align 4\n  store ptr %stack.next, ptr %deferPtr, align 4\n  %callback = load i32, ptr %4, align 4\n  switch i32 %callback, label %rundefers.default [\n    i32 0, label %rundefers.callback0\n  ]\n\nrundefers.callback0:                              ; preds = %rundefers.loop\n  %gep = getelementptr inbounds nuw i8, ptr %4, i32 8\n  %param = load i32, ptr %gep, align 4\n  call void @runtime.printlock(ptr undef) #4\n  call void @runtime.printint32(i32 %param, ptr undef) #4\n  call void @runtime.printunlock(ptr undef) #4\n  br label %rundefers.loophead\n\nrundefers.default:                                ; preds = %rundefers.loop\n  unreachable\n\nrundefers.end:                                    ; preds = %rundefers.loophead\n  br label %rundefers.after\n\nrecover:                                          ; preds = %rundefers.end1\n  ret void\n\nlpad:                                             ; No predecessors!\n  br label %rundefers.loophead4\n\nrundefers.loophead4:                              ; preds = %rundefers.callback010, %lpad\n  br i1 poison, label %rundefers.end1, label %rundefers.loop3\n\nrundefers.loop3:                                  ; preds = %rundefers.loophead4\n  switch i32 poison, label %rundefers.default2 [\n    i32 0, label %rundefers.callback010\n  ]\n\nrundefers.callback010:                            ; preds = %rundefers.loop3\n  br label %rundefers.loophead4\n\nrundefers.default2:                               ; preds = %rundefers.loop3\n  unreachable\n\nrundefers.end1:                                   ; preds = %rundefers.loophead4\n  br label %recover\n}\n\n; Function Attrs: nounwind\ndefine hidden void @main.deferBetweenLoops(ptr %context) unnamed_addr #1 {\nentry:\n  %defer.alloca = alloca { i32, ptr, i32 }, align 4\n  %deferPtr = alloca ptr, align 4\n  store ptr null, ptr %deferPtr, align 4\n  %deferframe.buf = alloca %runtime.deferFrame, align 4\n  %0 = call ptr @llvm.stacksave.p0()\n  call void @runtime.setupDeferFrame(ptr nonnull %deferframe.buf, ptr %0, ptr undef) #4\n  br label %for.loop\n\nfor.loop:                                         ; preds = %for.body, %entry\n  %1 = phi i32 [ 0, %entry ], [ %3, %for.body ]\n  %2 = icmp slt i32 %1, 10\n  br i1 %2, label %for.body, label %for.done\n\nfor.body:                                         ; preds = %for.loop\n  %3 = add i32 %1, 1\n  br label %for.loop\n\nfor.done:                                         ; preds = %for.loop\n  %defer.next = load ptr, ptr %deferPtr, align 4\n  store i32 0, ptr %defer.alloca, align 4\n  %defer.alloca.repack16 = getelementptr inbounds nuw i8, ptr %defer.alloca, i32 4\n  store ptr %defer.next, ptr %defer.alloca.repack16, align 4\n  %defer.alloca.repack18 = getelementptr inbounds nuw i8, ptr %defer.alloca, i32 8\n  store i32 1, ptr %defer.alloca.repack18, align 4\n  store ptr %defer.alloca, ptr %deferPtr, align 4\n  br label %for.loop1\n\nfor.loop1:                                        ; preds = %for.body2, %for.done\n  %4 = phi i32 [ 0, %for.done ], [ %6, %for.body2 ]\n  %5 = icmp slt i32 %4, 10\n  br i1 %5, label %for.body2, label %for.done3\n\nfor.body2:                                        ; preds = %for.loop1\n  %6 = add i32 %4, 1\n  br label %for.loop1\n\nfor.done3:                                        ; preds = %for.loop1\n  br label %rundefers.block\n\nrundefers.after:                                  ; preds = %rundefers.end\n  call void @runtime.destroyDeferFrame(ptr nonnull %deferframe.buf, ptr undef) #4\n  ret void\n\nrundefers.block:                                  ; preds = %for.done3\n  br label %rundefers.loophead\n\nrundefers.loophead:                               ; preds = %rundefers.callback0, %rundefers.block\n  %7 = load ptr, ptr %deferPtr, align 4\n  %stackIsNil = icmp eq ptr %7, null\n  br i1 %stackIsNil, label %rundefers.end, label %rundefers.loop\n\nrundefers.loop:                                   ; preds = %rundefers.loophead\n  %stack.next.gep = getelementptr inbounds nuw i8, ptr %7, i32 4\n  %stack.next = load ptr, ptr %stack.next.gep, align 4\n  store ptr %stack.next, ptr %deferPtr, align 4\n  %callback = load i32, ptr %7, align 4\n  switch i32 %callback, label %rundefers.default [\n    i32 0, label %rundefers.callback0\n  ]\n\nrundefers.callback0:                              ; preds = %rundefers.loop\n  %gep = getelementptr inbounds nuw i8, ptr %7, i32 8\n  %param = load i32, ptr %gep, align 4\n  call void @runtime.printlock(ptr undef) #4\n  call void @runtime.printint32(i32 %param, ptr undef) #4\n  call void @runtime.printunlock(ptr undef) #4\n  br label %rundefers.loophead\n\nrundefers.default:                                ; preds = %rundefers.loop\n  unreachable\n\nrundefers.end:                                    ; preds = %rundefers.loophead\n  br label %rundefers.after\n\nrecover:                                          ; preds = %rundefers.end4\n  ret void\n\nlpad:                                             ; No predecessors!\n  br label %rundefers.loophead7\n\nrundefers.loophead7:                              ; preds = %rundefers.callback013, %lpad\n  br i1 poison, label %rundefers.end4, label %rundefers.loop6\n\nrundefers.loop6:                                  ; preds = %rundefers.loophead7\n  switch i32 poison, label %rundefers.default5 [\n    i32 0, label %rundefers.callback013\n  ]\n\nrundefers.callback013:                            ; preds = %rundefers.loop6\n  br label %rundefers.loophead7\n\nrundefers.default5:                               ; preds = %rundefers.loop6\n  unreachable\n\nrundefers.end4:                                   ; preds = %rundefers.loophead7\n  br label %recover\n}\n\nattributes #0 = { allockind(\"alloc,zeroed\") allocsize(0) \"alloc-family\"=\"runtime.alloc\" \"target-features\"=\"+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp\" }\nattributes #1 = { nounwind \"target-features\"=\"+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp\" }\nattributes #2 = { \"target-features\"=\"+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp\" }\nattributes #3 = { nocallback nofree nosync nounwind willreturn }\nattributes #4 = { nounwind }\nattributes #5 = { nounwind returns_twice }\n"
  },
  {
    "path": "compiler/testdata/defer.go",
    "content": "package main\n\nfunc external()\n\nfunc deferSimple() {\n\tdefer func() {\n\t\tprint(3)\n\t}()\n\texternal()\n}\n\nfunc deferMultiple() {\n\tdefer func() {\n\t\tprint(3)\n\t}()\n\tdefer func() {\n\t\tprint(5)\n\t}()\n\texternal()\n}\n\nfunc deferInfiniteLoop() {\n\tfor {\n\t\tdefer print(8)\n\t}\n}\n\nfunc deferLoop() {\n\tfor i := 0; i < 10; i++ {\n\t\tdefer print(i)\n\t}\n}\n\nfunc deferBetweenLoops() {\n\tfor i := 0; i < 10; i++ {\n\t}\n\tdefer print(1)\n\tfor i := 0; i < 10; i++ {\n\t}\n}\n"
  },
  {
    "path": "compiler/testdata/errors.go",
    "content": "package main\n\nimport (\n\t\"structs\"\n\t\"unsafe\"\n)\n\n//go:wasmimport modulename empty\nfunc empty()\n\n// ERROR: can only use //go:wasmimport on declarations\n//\n//go:wasmimport modulename implementation\nfunc implementation() {\n}\n\ntype Uint uint32\n\ntype S struct {\n\t_ structs.HostLayout\n\ta [4]uint32\n\tb uintptr\n\td float32\n\te float64\n}\n\n//go:wasmimport modulename validparam\nfunc validparam(a int32, b uint64, c float64, d unsafe.Pointer, e Uint, f uintptr, g string, h *int32, i *S, j *struct{}, k *[8]uint8)\n\n// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type [4]uint32\n// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type []byte\n// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type struct{a int}\n// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type chan struct{}\n// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type func()\n// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type int\n// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type uint\n// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type [8]int\n//\n//go:wasmimport modulename invalidparam\nfunc invalidparam(a [4]uint32, b []byte, c struct{ a int }, d chan struct{}, e func(), f int, g uint, h [8]int)\n\n// ERROR: //go:wasmimport modulename invalidparam_no_hostlayout: unsupported parameter type *struct{int}\n// ERROR: //go:wasmimport modulename invalidparam_no_hostlayout: unsupported parameter type *struct{string}\n//\n//go:wasmimport modulename invalidparam_no_hostlayout\nfunc invalidparam_no_hostlayout(a *struct{ int }, b *struct{ string })\n\n//go:wasmimport modulename validreturn_int32\nfunc validreturn_int32() int32\n\n//go:wasmimport modulename validreturn_ptr_int32\nfunc validreturn_ptr_int32() *int32\n\n//go:wasmimport modulename validreturn_ptr_string\nfunc validreturn_ptr_string() *string\n\n//go:wasmimport modulename validreturn_ptr_struct\nfunc validreturn_ptr_struct() *S\n\n//go:wasmimport modulename validreturn_ptr_struct\nfunc validreturn_ptr_empty_struct() *struct{}\n\n//go:wasmimport modulename validreturn_ptr_array\nfunc validreturn_ptr_array() *[8]uint8\n\n//go:wasmimport modulename validreturn_unsafe_pointer\nfunc validreturn_unsafe_pointer() unsafe.Pointer\n\n// ERROR: //go:wasmimport modulename manyreturns: too many return values\n//\n//go:wasmimport modulename manyreturns\nfunc manyreturns() (int32, int32)\n\n// ERROR: //go:wasmimport modulename invalidreturn_int: unsupported result type int\n//\n//go:wasmimport modulename invalidreturn_int\nfunc invalidreturn_int() int\n\n// ERROR: //go:wasmimport modulename invalidreturn_int: unsupported result type uint\n//\n//go:wasmimport modulename invalidreturn_int\nfunc invalidreturn_uint() uint\n\n// ERROR: //go:wasmimport modulename invalidreturn_func: unsupported result type func()\n//\n//go:wasmimport modulename invalidreturn_func\nfunc invalidreturn_func() func()\n\n// ERROR: //go:wasmimport modulename invalidreturn_pointer_array_int: unsupported result type *[8]int\n//\n//go:wasmimport modulename invalidreturn_pointer_array_int\nfunc invalidreturn_pointer_array_int() *[8]int\n\n// ERROR: //go:wasmimport modulename invalidreturn_slice_byte: unsupported result type []byte\n//\n//go:wasmimport modulename invalidreturn_slice_byte\nfunc invalidreturn_slice_byte() []byte\n\n// ERROR: //go:wasmimport modulename invalidreturn_chan_int: unsupported result type chan int\n//\n//go:wasmimport modulename invalidreturn_chan_int\nfunc invalidreturn_chan_int() chan int\n\n// ERROR: //go:wasmimport modulename invalidreturn_string: unsupported result type string\n//\n//go:wasmimport modulename invalidreturn_string\nfunc invalidreturn_string() string\n"
  },
  {
    "path": "compiler/testdata/float.go",
    "content": "package main\n\n// Test converting floats to ints.\n\nfunc f32tou32(v float32) uint32 {\n\treturn uint32(v)\n}\n\nfunc maxu32f() float32 {\n\treturn float32(^uint32(0))\n}\n\nfunc maxu32tof32() uint32 {\n\tf := float32(^uint32(0))\n\treturn uint32(f)\n}\n\nfunc inftoi32() (uint32, uint32, int32, int32) {\n\tinf := 1.0\n\tinf /= 0.0\n\n\treturn uint32(inf), uint32(-inf), int32(inf), int32(-inf)\n}\n\nfunc u32tof32tou32(v uint32) uint32 {\n\treturn uint32(float32(v))\n}\n\nfunc f32tou32tof32(v float32) float32 {\n\treturn float32(uint32(v))\n}\n\nfunc f32tou8(v float32) uint8 {\n\treturn uint8(v)\n}\n\nfunc f32toi8(v float32) int8 {\n\treturn int8(v)\n}\n"
  },
  {
    "path": "compiler/testdata/float.ll",
    "content": "; ModuleID = 'float.go'\nsource_filename = \"float.go\"\ntarget datalayout = \"e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20\"\ntarget triple = \"wasm32-unknown-wasi\"\n\n; Function Attrs: allockind(\"alloc,zeroed\") allocsize(0)\ndeclare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0\n\ndeclare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden void @main.init(ptr %context) unnamed_addr #2 {\nentry:\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden i32 @main.f32tou32(float %v, ptr %context) unnamed_addr #2 {\nentry:\n  %positive = fcmp oge float %v, 0.000000e+00\n  %withinmax = fcmp ole float %v, 0x41EFFFFFC0000000\n  %inbounds = and i1 %positive, %withinmax\n  %saturated = sext i1 %positive to i32\n  %normal = fptoui float %v to i32\n  %0 = select i1 %inbounds, i32 %normal, i32 %saturated\n  ret i32 %0\n}\n\n; Function Attrs: nounwind\ndefine hidden float @main.maxu32f(ptr %context) unnamed_addr #2 {\nentry:\n  ret float 0x41F0000000000000\n}\n\n; Function Attrs: nounwind\ndefine hidden i32 @main.maxu32tof32(ptr %context) unnamed_addr #2 {\nentry:\n  ret i32 -1\n}\n\n; Function Attrs: nounwind\ndefine hidden { i32, i32, i32, i32 } @main.inftoi32(ptr %context) unnamed_addr #2 {\nentry:\n  ret { i32, i32, i32, i32 } { i32 -1, i32 0, i32 2147483647, i32 -2147483648 }\n}\n\n; Function Attrs: nounwind\ndefine hidden i32 @main.u32tof32tou32(i32 %v, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = uitofp i32 %v to float\n  %withinmax = fcmp ole float %0, 0x41EFFFFFC0000000\n  %normal = fptoui float %0 to i32\n  %1 = select i1 %withinmax, i32 %normal, i32 -1\n  ret i32 %1\n}\n\n; Function Attrs: nounwind\ndefine hidden float @main.f32tou32tof32(float %v, ptr %context) unnamed_addr #2 {\nentry:\n  %positive = fcmp oge float %v, 0.000000e+00\n  %withinmax = fcmp ole float %v, 0x41EFFFFFC0000000\n  %inbounds = and i1 %positive, %withinmax\n  %saturated = sext i1 %positive to i32\n  %normal = fptoui float %v to i32\n  %0 = select i1 %inbounds, i32 %normal, i32 %saturated\n  %1 = uitofp i32 %0 to float\n  ret float %1\n}\n\n; Function Attrs: nounwind\ndefine hidden i8 @main.f32tou8(float %v, ptr %context) unnamed_addr #2 {\nentry:\n  %positive = fcmp oge float %v, 0.000000e+00\n  %withinmax = fcmp ole float %v, 2.550000e+02\n  %inbounds = and i1 %positive, %withinmax\n  %saturated = sext i1 %positive to i8\n  %normal = fptoui float %v to i8\n  %0 = select i1 %inbounds, i8 %normal, i8 %saturated\n  ret i8 %0\n}\n\n; Function Attrs: nounwind\ndefine hidden i8 @main.f32toi8(float %v, ptr %context) unnamed_addr #2 {\nentry:\n  %abovemin = fcmp oge float %v, -1.280000e+02\n  %belowmax = fcmp ole float %v, 1.270000e+02\n  %inbounds = and i1 %abovemin, %belowmax\n  %saturated = select i1 %abovemin, i8 127, i8 -128\n  %isnan = fcmp uno float %v, 0.000000e+00\n  %remapped = select i1 %isnan, i8 0, i8 %saturated\n  %normal = fptosi float %v to i8\n  %0 = select i1 %inbounds, i8 %normal, i8 %remapped\n  ret i8 %0\n}\n\nattributes #0 = { allockind(\"alloc,zeroed\") allocsize(0) \"alloc-family\"=\"runtime.alloc\" \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #1 = { \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #2 = { nounwind \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\n"
  },
  {
    "path": "compiler/testdata/func.go",
    "content": "package main\n\nfunc foo(callback func(int)) {\n\tcallback(3)\n}\n\nfunc bar() {\n\tfoo(someFunc)\n}\n\nfunc someFunc(int) {\n}\n"
  },
  {
    "path": "compiler/testdata/func.ll",
    "content": "; ModuleID = 'func.go'\nsource_filename = \"func.go\"\ntarget datalayout = \"e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20\"\ntarget triple = \"wasm32-unknown-wasi\"\n\n; Function Attrs: allockind(\"alloc,zeroed\") allocsize(0)\ndeclare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0\n\ndeclare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden void @main.init(ptr %context) unnamed_addr #2 {\nentry:\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden void @main.foo(ptr %callback.context, ptr %callback.funcptr, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = icmp eq ptr %callback.funcptr, null\n  br i1 %0, label %fpcall.throw, label %fpcall.next\n\nfpcall.next:                                      ; preds = %entry\n  call void %callback.funcptr(i32 3, ptr %callback.context) #3\n  ret void\n\nfpcall.throw:                                     ; preds = %entry\n  call void @runtime.nilPanic(ptr undef) #3\n  unreachable\n}\n\ndeclare void @runtime.nilPanic(ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden void @main.bar(ptr %context) unnamed_addr #2 {\nentry:\n  call void @main.foo(ptr undef, ptr nonnull @main.someFunc, ptr undef)\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden void @main.someFunc(i32 %arg0, ptr %context) unnamed_addr #2 {\nentry:\n  ret void\n}\n\nattributes #0 = { allockind(\"alloc,zeroed\") allocsize(0) \"alloc-family\"=\"runtime.alloc\" \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #1 = { \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #2 = { nounwind \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #3 = { nounwind }\n"
  },
  {
    "path": "compiler/testdata/gc.go",
    "content": "package main\n\nvar (\n\tscalar1 *byte\n\tscalar2 *int32\n\tscalar3 *int64\n\tscalar4 *float32\n\n\tarray1 *[3]byte\n\tarray2 *[71]byte\n\tarray3 *[3]*byte\n\n\tstruct1 *struct{}\n\tstruct2 *struct {\n\t\tx int\n\t\ty int\n\t}\n\tstruct3 *struct {\n\t\tx *byte\n\t\ty [60]uintptr\n\t\tz *byte\n\t}\n\tstruct4 *struct {\n\t\tx *byte\n\t\ty [61]uintptr\n\t}\n\n\tslice1 []byte\n\tslice2 []*int\n\tslice3 [][]byte\n)\n\nfunc newScalar() {\n\tscalar1 = new(byte)\n\tscalar2 = new(int32)\n\tscalar3 = new(int64)\n\tscalar4 = new(float32)\n}\n\nfunc newArray() {\n\tarray1 = new([3]byte)\n\tarray2 = new([71]byte)\n\tarray3 = new([3]*byte)\n}\n\nfunc newStruct() {\n\tstruct1 = new(struct{})\n\tstruct2 = new(struct {\n\t\tx int\n\t\ty int\n\t})\n\tstruct3 = new(struct {\n\t\tx *byte\n\t\ty [60]uintptr\n\t\tz *byte\n\t})\n\tstruct4 = new(struct {\n\t\tx *byte\n\t\ty [61]uintptr\n\t})\n}\n\nfunc newFuncValue() *func() {\n\treturn new(func())\n}\n\nfunc makeSlice() {\n\tslice1 = make([]byte, 5)\n\tslice2 = make([]*int, 5)\n\tslice3 = make([][]byte, 5)\n}\n\nfunc makeInterface(v complex128) interface{} {\n\treturn v // always stored in an allocation\n}\n"
  },
  {
    "path": "compiler/testdata/gc.ll",
    "content": "; ModuleID = 'gc.go'\nsource_filename = \"gc.go\"\ntarget datalayout = \"e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20\"\ntarget triple = \"wasm32-unknown-wasi\"\n\n%runtime._interface = type { ptr, ptr }\n\n@main.scalar1 = hidden global ptr null, align 4\n@main.scalar2 = hidden global ptr null, align 4\n@main.scalar3 = hidden global ptr null, align 4\n@main.scalar4 = hidden global ptr null, align 4\n@main.array1 = hidden global ptr null, align 4\n@main.array2 = hidden global ptr null, align 4\n@main.array3 = hidden global ptr null, align 4\n@main.struct1 = hidden global ptr null, align 4\n@main.struct2 = hidden global ptr null, align 4\n@main.struct3 = hidden global ptr null, align 4\n@main.struct4 = hidden global ptr null, align 4\n@main.slice1 = hidden global { ptr, i32, i32 } zeroinitializer, align 4\n@main.slice2 = hidden global { ptr, i32, i32 } zeroinitializer, align 4\n@main.slice3 = hidden global { ptr, i32, i32 } zeroinitializer, align 4\n@\"runtime/gc.layout:62-2000000000000001\" = linkonce_odr unnamed_addr constant { i32, [8 x i8] } { i32 62, [8 x i8] c\"\\01\\00\\00\\00\\00\\00\\00 \" }\n@\"runtime/gc.layout:62-0001\" = linkonce_odr unnamed_addr constant { i32, [8 x i8] } { i32 62, [8 x i8] c\"\\01\\00\\00\\00\\00\\00\\00\\00\" }\n@\"reflect/types.type:basic:complex128\" = linkonce_odr constant { i8, ptr } { i8 80, ptr @\"reflect/types.type:pointer:basic:complex128\" }, align 4\n@\"reflect/types.type:pointer:basic:complex128\" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @\"reflect/types.type:basic:complex128\" }, align 4\n\n; Function Attrs: allockind(\"alloc,zeroed\") allocsize(0)\ndeclare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0\n\ndeclare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden void @main.init(ptr %context) unnamed_addr #2 {\nentry:\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden void @main.newScalar(ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  %new = call align 1 dereferenceable(1) ptr @runtime.alloc(i32 1, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3\n  call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef) #3\n  store ptr %new, ptr @main.scalar1, align 4\n  %new1 = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3\n  call void @runtime.trackPointer(ptr nonnull %new1, ptr nonnull %stackalloc, ptr undef) #3\n  store ptr %new1, ptr @main.scalar2, align 4\n  %new2 = call align 8 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3\n  call void @runtime.trackPointer(ptr nonnull %new2, ptr nonnull %stackalloc, ptr undef) #3\n  store ptr %new2, ptr @main.scalar3, align 4\n  %new3 = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3\n  call void @runtime.trackPointer(ptr nonnull %new3, ptr nonnull %stackalloc, ptr undef) #3\n  store ptr %new3, ptr @main.scalar4, align 4\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden void @main.newArray(ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  %new = call align 1 dereferenceable(3) ptr @runtime.alloc(i32 3, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3\n  call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef) #3\n  store ptr %new, ptr @main.array1, align 4\n  %new1 = call align 1 dereferenceable(71) ptr @runtime.alloc(i32 71, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3\n  call void @runtime.trackPointer(ptr nonnull %new1, ptr nonnull %stackalloc, ptr undef) #3\n  store ptr %new1, ptr @main.array2, align 4\n  %new2 = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr nonnull inttoptr (i32 67 to ptr), ptr undef) #3\n  call void @runtime.trackPointer(ptr nonnull %new2, ptr nonnull %stackalloc, ptr undef) #3\n  store ptr %new2, ptr @main.array3, align 4\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden void @main.newStruct(ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  %new = call align 1 ptr @runtime.alloc(i32 0, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3\n  call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef) #3\n  store ptr %new, ptr @main.struct1, align 4\n  %new1 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3\n  call void @runtime.trackPointer(ptr nonnull %new1, ptr nonnull %stackalloc, ptr undef) #3\n  store ptr %new1, ptr @main.struct2, align 4\n  %new2 = call align 4 dereferenceable(248) ptr @runtime.alloc(i32 248, ptr nonnull @\"runtime/gc.layout:62-2000000000000001\", ptr undef) #3\n  call void @runtime.trackPointer(ptr nonnull %new2, ptr nonnull %stackalloc, ptr undef) #3\n  store ptr %new2, ptr @main.struct3, align 4\n  %new3 = call align 4 dereferenceable(248) ptr @runtime.alloc(i32 248, ptr nonnull @\"runtime/gc.layout:62-0001\", ptr undef) #3\n  call void @runtime.trackPointer(ptr nonnull %new3, ptr nonnull %stackalloc, ptr undef) #3\n  store ptr %new3, ptr @main.struct4, align 4\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden ptr @main.newFuncValue(ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  %new = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 197 to ptr), ptr undef) #3\n  call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef) #3\n  ret ptr %new\n}\n\n; Function Attrs: nounwind\ndefine hidden void @main.makeSlice(ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  %makeslice = call align 1 dereferenceable(5) ptr @runtime.alloc(i32 5, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3\n  call void @runtime.trackPointer(ptr nonnull %makeslice, ptr nonnull %stackalloc, ptr undef) #3\n  store ptr %makeslice, ptr @main.slice1, align 4\n  store i32 5, ptr getelementptr inbounds nuw (i8, ptr @main.slice1, i32 4), align 4\n  store i32 5, ptr getelementptr inbounds nuw (i8, ptr @main.slice1, i32 8), align 4\n  %makeslice1 = call align 4 dereferenceable(20) ptr @runtime.alloc(i32 20, ptr nonnull inttoptr (i32 67 to ptr), ptr undef) #3\n  call void @runtime.trackPointer(ptr nonnull %makeslice1, ptr nonnull %stackalloc, ptr undef) #3\n  store ptr %makeslice1, ptr @main.slice2, align 4\n  store i32 5, ptr getelementptr inbounds nuw (i8, ptr @main.slice2, i32 4), align 4\n  store i32 5, ptr getelementptr inbounds nuw (i8, ptr @main.slice2, i32 8), align 4\n  %makeslice3 = call align 4 dereferenceable(60) ptr @runtime.alloc(i32 60, ptr nonnull inttoptr (i32 71 to ptr), ptr undef) #3\n  call void @runtime.trackPointer(ptr nonnull %makeslice3, ptr nonnull %stackalloc, ptr undef) #3\n  store ptr %makeslice3, ptr @main.slice3, align 4\n  store i32 5, ptr getelementptr inbounds nuw (i8, ptr @main.slice3, i32 4), align 4\n  store i32 5, ptr getelementptr inbounds nuw (i8, ptr @main.slice3, i32 8), align 4\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden %runtime._interface @main.makeInterface(double %v.r, double %v.i, ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  %0 = call align 8 dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #3\n  call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #3\n  store double %v.r, ptr %0, align 8\n  %.repack1 = getelementptr inbounds nuw i8, ptr %0, i32 8\n  store double %v.i, ptr %.repack1, align 8\n  %1 = insertvalue %runtime._interface { ptr @\"reflect/types.type:basic:complex128\", ptr undef }, ptr %0, 1\n  call void @runtime.trackPointer(ptr nonnull @\"reflect/types.type:basic:complex128\", ptr nonnull %stackalloc, ptr undef) #3\n  call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #3\n  ret %runtime._interface %1\n}\n\nattributes #0 = { allockind(\"alloc,zeroed\") allocsize(0) \"alloc-family\"=\"runtime.alloc\" \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #1 = { \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #2 = { nounwind \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #3 = { nounwind }\n"
  },
  {
    "path": "compiler/testdata/generics.go",
    "content": "package main\n\nimport \"unsafe\"\n\ntype Coord interface {\n\tint | float32\n}\n\ntype Point[T Coord] struct {\n\tX, Y T\n}\n\nfunc Add[T Coord](a, b Point[T]) Point[T] {\n\tcheckSize(unsafe.Alignof(a))\n\tcheckSize(unsafe.Sizeof(a))\n\treturn Point[T]{\n\t\tX: a.X + b.X,\n\t\tY: a.Y + b.Y,\n\t}\n}\n\nfunc main() {\n\tvar af, bf Point[float32]\n\tAdd(af, bf)\n\n\tvar ai, bi Point[int]\n\tAdd(ai, bi)\n}\n\nfunc checkSize(uintptr)\n"
  },
  {
    "path": "compiler/testdata/generics.ll",
    "content": "; ModuleID = 'generics.go'\nsource_filename = \"generics.go\"\ntarget datalayout = \"e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20\"\ntarget triple = \"wasm32-unknown-wasi\"\n\n%\"main.Point[int]\" = type { i32, i32 }\n%\"main.Point[float32]\" = type { float, float }\n\ndeclare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0\n\ndeclare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0\n\n; Function Attrs: nounwind\ndefine hidden void @main.init(i8* %context) unnamed_addr #1 {\nentry:\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden void @main.main(i8* %context) unnamed_addr #1 {\nentry:\n  %bi = alloca %\"main.Point[int]\", align 8\n  %ai = alloca %\"main.Point[int]\", align 8\n  %bf = alloca %\"main.Point[float32]\", align 8\n  %af = alloca %\"main.Point[float32]\", align 8\n  %af.repack = getelementptr inbounds %\"main.Point[float32]\", %\"main.Point[float32]\"* %af, i32 0, i32 0\n  store float 0.000000e+00, float* %af.repack, align 8\n  %af.repack1 = getelementptr inbounds %\"main.Point[float32]\", %\"main.Point[float32]\"* %af, i32 0, i32 1\n  store float 0.000000e+00, float* %af.repack1, align 4\n  %0 = bitcast %\"main.Point[float32]\"* %af to i8*\n  call void @runtime.trackPointer(i8* nonnull %0, i8* undef) #2\n  %bf.repack = getelementptr inbounds %\"main.Point[float32]\", %\"main.Point[float32]\"* %bf, i32 0, i32 0\n  store float 0.000000e+00, float* %bf.repack, align 8\n  %bf.repack2 = getelementptr inbounds %\"main.Point[float32]\", %\"main.Point[float32]\"* %bf, i32 0, i32 1\n  store float 0.000000e+00, float* %bf.repack2, align 4\n  %1 = bitcast %\"main.Point[float32]\"* %bf to i8*\n  call void @runtime.trackPointer(i8* nonnull %1, i8* undef) #2\n  %.elt = getelementptr inbounds %\"main.Point[float32]\", %\"main.Point[float32]\"* %af, i32 0, i32 0\n  %.unpack = load float, float* %.elt, align 8\n  %.elt3 = getelementptr inbounds %\"main.Point[float32]\", %\"main.Point[float32]\"* %af, i32 0, i32 1\n  %.unpack4 = load float, float* %.elt3, align 4\n  %.elt5 = getelementptr inbounds %\"main.Point[float32]\", %\"main.Point[float32]\"* %bf, i32 0, i32 0\n  %.unpack6 = load float, float* %.elt5, align 8\n  %.elt7 = getelementptr inbounds %\"main.Point[float32]\", %\"main.Point[float32]\"* %bf, i32 0, i32 1\n  %.unpack8 = load float, float* %.elt7, align 4\n  %2 = call %\"main.Point[float32]\" @\"main.Add[float32]\"(float %.unpack, float %.unpack4, float %.unpack6, float %.unpack8, i8* undef)\n  %ai.repack = getelementptr inbounds %\"main.Point[int]\", %\"main.Point[int]\"* %ai, i32 0, i32 0\n  store i32 0, i32* %ai.repack, align 8\n  %ai.repack9 = getelementptr inbounds %\"main.Point[int]\", %\"main.Point[int]\"* %ai, i32 0, i32 1\n  store i32 0, i32* %ai.repack9, align 4\n  %3 = bitcast %\"main.Point[int]\"* %ai to i8*\n  call void @runtime.trackPointer(i8* nonnull %3, i8* undef) #2\n  %bi.repack = getelementptr inbounds %\"main.Point[int]\", %\"main.Point[int]\"* %bi, i32 0, i32 0\n  store i32 0, i32* %bi.repack, align 8\n  %bi.repack10 = getelementptr inbounds %\"main.Point[int]\", %\"main.Point[int]\"* %bi, i32 0, i32 1\n  store i32 0, i32* %bi.repack10, align 4\n  %4 = bitcast %\"main.Point[int]\"* %bi to i8*\n  call void @runtime.trackPointer(i8* nonnull %4, i8* undef) #2\n  %.elt11 = getelementptr inbounds %\"main.Point[int]\", %\"main.Point[int]\"* %ai, i32 0, i32 0\n  %.unpack12 = load i32, i32* %.elt11, align 8\n  %.elt13 = getelementptr inbounds %\"main.Point[int]\", %\"main.Point[int]\"* %ai, i32 0, i32 1\n  %.unpack14 = load i32, i32* %.elt13, align 4\n  %.elt15 = getelementptr inbounds %\"main.Point[int]\", %\"main.Point[int]\"* %bi, i32 0, i32 0\n  %.unpack16 = load i32, i32* %.elt15, align 8\n  %.elt17 = getelementptr inbounds %\"main.Point[int]\", %\"main.Point[int]\"* %bi, i32 0, i32 1\n  %.unpack18 = load i32, i32* %.elt17, align 4\n  %5 = call %\"main.Point[int]\" @\"main.Add[int]\"(i32 %.unpack12, i32 %.unpack14, i32 %.unpack16, i32 %.unpack18, i8* undef)\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine linkonce_odr hidden %\"main.Point[float32]\" @\"main.Add[float32]\"(float %a.X, float %a.Y, float %b.X, float %b.Y, i8* %context) unnamed_addr #1 {\nentry:\n  %complit = alloca %\"main.Point[float32]\", align 8\n  %b = alloca %\"main.Point[float32]\", align 8\n  %a = alloca %\"main.Point[float32]\", align 8\n  %a.repack = getelementptr inbounds %\"main.Point[float32]\", %\"main.Point[float32]\"* %a, i32 0, i32 0\n  store float 0.000000e+00, float* %a.repack, align 8\n  %a.repack9 = getelementptr inbounds %\"main.Point[float32]\", %\"main.Point[float32]\"* %a, i32 0, i32 1\n  store float 0.000000e+00, float* %a.repack9, align 4\n  %0 = bitcast %\"main.Point[float32]\"* %a to i8*\n  call void @runtime.trackPointer(i8* nonnull %0, i8* undef) #2\n  %a.repack10 = getelementptr inbounds %\"main.Point[float32]\", %\"main.Point[float32]\"* %a, i32 0, i32 0\n  store float %a.X, float* %a.repack10, align 8\n  %a.repack11 = getelementptr inbounds %\"main.Point[float32]\", %\"main.Point[float32]\"* %a, i32 0, i32 1\n  store float %a.Y, float* %a.repack11, align 4\n  %b.repack = getelementptr inbounds %\"main.Point[float32]\", %\"main.Point[float32]\"* %b, i32 0, i32 0\n  store float 0.000000e+00, float* %b.repack, align 8\n  %b.repack13 = getelementptr inbounds %\"main.Point[float32]\", %\"main.Point[float32]\"* %b, i32 0, i32 1\n  store float 0.000000e+00, float* %b.repack13, align 4\n  %1 = bitcast %\"main.Point[float32]\"* %b to i8*\n  call void @runtime.trackPointer(i8* nonnull %1, i8* undef) #2\n  %b.repack14 = getelementptr inbounds %\"main.Point[float32]\", %\"main.Point[float32]\"* %b, i32 0, i32 0\n  store float %b.X, float* %b.repack14, align 8\n  %b.repack15 = getelementptr inbounds %\"main.Point[float32]\", %\"main.Point[float32]\"* %b, i32 0, i32 1\n  store float %b.Y, float* %b.repack15, align 4\n  call void @main.checkSize(i32 4, i8* undef) #2\n  call void @main.checkSize(i32 8, i8* undef) #2\n  %complit.repack = getelementptr inbounds %\"main.Point[float32]\", %\"main.Point[float32]\"* %complit, i32 0, i32 0\n  store float 0.000000e+00, float* %complit.repack, align 8\n  %complit.repack17 = getelementptr inbounds %\"main.Point[float32]\", %\"main.Point[float32]\"* %complit, i32 0, i32 1\n  store float 0.000000e+00, float* %complit.repack17, align 4\n  %2 = bitcast %\"main.Point[float32]\"* %complit to i8*\n  call void @runtime.trackPointer(i8* nonnull %2, i8* undef) #2\n  %3 = getelementptr inbounds %\"main.Point[float32]\", %\"main.Point[float32]\"* %complit, i32 0, i32 0\n  br i1 false, label %deref.throw, label %deref.next\n\nderef.next:                                       ; preds = %entry\n  br i1 false, label %deref.throw1, label %deref.next2\n\nderef.next2:                                      ; preds = %deref.next\n  %4 = getelementptr inbounds %\"main.Point[float32]\", %\"main.Point[float32]\"* %b, i32 0, i32 0\n  %5 = getelementptr inbounds %\"main.Point[float32]\", %\"main.Point[float32]\"* %a, i32 0, i32 0\n  %6 = load float, float* %5, align 8\n  %7 = load float, float* %4, align 8\n  %8 = fadd float %6, %7\n  br i1 false, label %deref.throw3, label %deref.next4\n\nderef.next4:                                      ; preds = %deref.next2\n  br i1 false, label %deref.throw5, label %deref.next6\n\nderef.next6:                                      ; preds = %deref.next4\n  %9 = getelementptr inbounds %\"main.Point[float32]\", %\"main.Point[float32]\"* %b, i32 0, i32 1\n  %10 = getelementptr inbounds %\"main.Point[float32]\", %\"main.Point[float32]\"* %a, i32 0, i32 1\n  %11 = load float, float* %10, align 4\n  %12 = load float, float* %9, align 4\n  br i1 false, label %store.throw, label %store.next\n\nstore.next:                                       ; preds = %deref.next6\n  store float %8, float* %3, align 8\n  br i1 false, label %store.throw7, label %store.next8\n\nstore.next8:                                      ; preds = %store.next\n  %13 = getelementptr inbounds %\"main.Point[float32]\", %\"main.Point[float32]\"* %complit, i32 0, i32 1\n  %14 = fadd float %11, %12\n  store float %14, float* %13, align 4\n  %.elt = getelementptr inbounds %\"main.Point[float32]\", %\"main.Point[float32]\"* %complit, i32 0, i32 0\n  %.unpack = load float, float* %.elt, align 8\n  %15 = insertvalue %\"main.Point[float32]\" undef, float %.unpack, 0\n  %16 = insertvalue %\"main.Point[float32]\" %15, float %14, 1\n  ret %\"main.Point[float32]\" %16\n\nderef.throw:                                      ; preds = %entry\n  unreachable\n\nderef.throw1:                                     ; preds = %deref.next\n  unreachable\n\nderef.throw3:                                     ; preds = %deref.next2\n  unreachable\n\nderef.throw5:                                     ; preds = %deref.next4\n  unreachable\n\nstore.throw:                                      ; preds = %deref.next6\n  unreachable\n\nstore.throw7:                                     ; preds = %store.next\n  unreachable\n}\n\ndeclare void @main.checkSize(i32, i8*) #0\n\ndeclare void @runtime.nilPanic(i8*) #0\n\n; Function Attrs: nounwind\ndefine linkonce_odr hidden %\"main.Point[int]\" @\"main.Add[int]\"(i32 %a.X, i32 %a.Y, i32 %b.X, i32 %b.Y, i8* %context) unnamed_addr #1 {\nentry:\n  %complit = alloca %\"main.Point[int]\", align 8\n  %b = alloca %\"main.Point[int]\", align 8\n  %a = alloca %\"main.Point[int]\", align 8\n  %a.repack = getelementptr inbounds %\"main.Point[int]\", %\"main.Point[int]\"* %a, i32 0, i32 0\n  store i32 0, i32* %a.repack, align 8\n  %a.repack9 = getelementptr inbounds %\"main.Point[int]\", %\"main.Point[int]\"* %a, i32 0, i32 1\n  store i32 0, i32* %a.repack9, align 4\n  %0 = bitcast %\"main.Point[int]\"* %a to i8*\n  call void @runtime.trackPointer(i8* nonnull %0, i8* undef) #2\n  %a.repack10 = getelementptr inbounds %\"main.Point[int]\", %\"main.Point[int]\"* %a, i32 0, i32 0\n  store i32 %a.X, i32* %a.repack10, align 8\n  %a.repack11 = getelementptr inbounds %\"main.Point[int]\", %\"main.Point[int]\"* %a, i32 0, i32 1\n  store i32 %a.Y, i32* %a.repack11, align 4\n  %b.repack = getelementptr inbounds %\"main.Point[int]\", %\"main.Point[int]\"* %b, i32 0, i32 0\n  store i32 0, i32* %b.repack, align 8\n  %b.repack13 = getelementptr inbounds %\"main.Point[int]\", %\"main.Point[int]\"* %b, i32 0, i32 1\n  store i32 0, i32* %b.repack13, align 4\n  %1 = bitcast %\"main.Point[int]\"* %b to i8*\n  call void @runtime.trackPointer(i8* nonnull %1, i8* undef) #2\n  %b.repack14 = getelementptr inbounds %\"main.Point[int]\", %\"main.Point[int]\"* %b, i32 0, i32 0\n  store i32 %b.X, i32* %b.repack14, align 8\n  %b.repack15 = getelementptr inbounds %\"main.Point[int]\", %\"main.Point[int]\"* %b, i32 0, i32 1\n  store i32 %b.Y, i32* %b.repack15, align 4\n  call void @main.checkSize(i32 4, i8* undef) #2\n  call void @main.checkSize(i32 8, i8* undef) #2\n  %complit.repack = getelementptr inbounds %\"main.Point[int]\", %\"main.Point[int]\"* %complit, i32 0, i32 0\n  store i32 0, i32* %complit.repack, align 8\n  %complit.repack17 = getelementptr inbounds %\"main.Point[int]\", %\"main.Point[int]\"* %complit, i32 0, i32 1\n  store i32 0, i32* %complit.repack17, align 4\n  %2 = bitcast %\"main.Point[int]\"* %complit to i8*\n  call void @runtime.trackPointer(i8* nonnull %2, i8* undef) #2\n  %3 = getelementptr inbounds %\"main.Point[int]\", %\"main.Point[int]\"* %complit, i32 0, i32 0\n  br i1 false, label %deref.throw, label %deref.next\n\nderef.next:                                       ; preds = %entry\n  br i1 false, label %deref.throw1, label %deref.next2\n\nderef.next2:                                      ; preds = %deref.next\n  %4 = getelementptr inbounds %\"main.Point[int]\", %\"main.Point[int]\"* %b, i32 0, i32 0\n  %5 = getelementptr inbounds %\"main.Point[int]\", %\"main.Point[int]\"* %a, i32 0, i32 0\n  %6 = load i32, i32* %5, align 8\n  %7 = load i32, i32* %4, align 8\n  %8 = add i32 %6, %7\n  br i1 false, label %deref.throw3, label %deref.next4\n\nderef.next4:                                      ; preds = %deref.next2\n  br i1 false, label %deref.throw5, label %deref.next6\n\nderef.next6:                                      ; preds = %deref.next4\n  %9 = getelementptr inbounds %\"main.Point[int]\", %\"main.Point[int]\"* %b, i32 0, i32 1\n  %10 = getelementptr inbounds %\"main.Point[int]\", %\"main.Point[int]\"* %a, i32 0, i32 1\n  %11 = load i32, i32* %10, align 4\n  %12 = load i32, i32* %9, align 4\n  br i1 false, label %store.throw, label %store.next\n\nstore.next:                                       ; preds = %deref.next6\n  store i32 %8, i32* %3, align 8\n  br i1 false, label %store.throw7, label %store.next8\n\nstore.next8:                                      ; preds = %store.next\n  %13 = getelementptr inbounds %\"main.Point[int]\", %\"main.Point[int]\"* %complit, i32 0, i32 1\n  %14 = add i32 %11, %12\n  store i32 %14, i32* %13, align 4\n  %.elt = getelementptr inbounds %\"main.Point[int]\", %\"main.Point[int]\"* %complit, i32 0, i32 0\n  %.unpack = load i32, i32* %.elt, align 8\n  %15 = insertvalue %\"main.Point[int]\" undef, i32 %.unpack, 0\n  %16 = insertvalue %\"main.Point[int]\" %15, i32 %14, 1\n  ret %\"main.Point[int]\" %16\n\nderef.throw:                                      ; preds = %entry\n  unreachable\n\nderef.throw1:                                     ; preds = %deref.next\n  unreachable\n\nderef.throw3:                                     ; preds = %deref.next2\n  unreachable\n\nderef.throw5:                                     ; preds = %deref.next4\n  unreachable\n\nstore.throw:                                      ; preds = %deref.next6\n  unreachable\n\nstore.throw7:                                     ; preds = %store.next\n  unreachable\n}\n\nattributes #0 = { \"target-features\"=\"+bulk-memory,+nontrapping-fptoint,+sign-ext\" }\nattributes #1 = { nounwind \"target-features\"=\"+bulk-memory,+nontrapping-fptoint,+sign-ext\" }\nattributes #2 = { nounwind }\n"
  },
  {
    "path": "compiler/testdata/go1.20.go",
    "content": "package main\n\nimport \"unsafe\"\n\nfunc unsafeSliceData(s []int) *int {\n\treturn unsafe.SliceData(s)\n}\n\nfunc unsafeString(ptr *byte, len int16) string {\n\treturn unsafe.String(ptr, len)\n}\n\nfunc unsafeStringData(s string) *byte {\n\treturn unsafe.StringData(s)\n}\n"
  },
  {
    "path": "compiler/testdata/go1.20.ll",
    "content": "; ModuleID = 'go1.20.go'\nsource_filename = \"go1.20.go\"\ntarget datalayout = \"e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20\"\ntarget triple = \"wasm32-unknown-wasi\"\n\n%runtime._string = type { ptr, i32 }\n\n; Function Attrs: allockind(\"alloc,zeroed\") allocsize(0)\ndeclare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0\n\ndeclare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden void @main.init(ptr %context) unnamed_addr #2 {\nentry:\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden ptr @main.unsafeSliceData(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  call void @runtime.trackPointer(ptr %s.data, ptr nonnull %stackalloc, ptr undef) #3\n  ret ptr %s.data\n}\n\n; Function Attrs: nounwind\ndefine hidden %runtime._string @main.unsafeString(ptr dereferenceable_or_null(1) %ptr, i16 %len, ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  %0 = icmp slt i16 %len, 0\n  %1 = icmp eq ptr %ptr, null\n  %2 = icmp ne i16 %len, 0\n  %3 = and i1 %1, %2\n  %4 = or i1 %3, %0\n  br i1 %4, label %unsafe.String.throw, label %unsafe.String.next\n\nunsafe.String.next:                               ; preds = %entry\n  %5 = zext nneg i16 %len to i32\n  %6 = insertvalue %runtime._string undef, ptr %ptr, 0\n  %7 = insertvalue %runtime._string %6, i32 %5, 1\n  call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef) #3\n  ret %runtime._string %7\n\nunsafe.String.throw:                              ; preds = %entry\n  call void @runtime.unsafeSlicePanic(ptr undef) #3\n  unreachable\n}\n\ndeclare void @runtime.unsafeSlicePanic(ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden ptr @main.unsafeStringData(ptr readonly %s.data, i32 %s.len, ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  call void @runtime.trackPointer(ptr %s.data, ptr nonnull %stackalloc, ptr undef) #3\n  ret ptr %s.data\n}\n\nattributes #0 = { allockind(\"alloc,zeroed\") allocsize(0) \"alloc-family\"=\"runtime.alloc\" \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #1 = { \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #2 = { nounwind \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #3 = { nounwind }\n"
  },
  {
    "path": "compiler/testdata/go1.21.go",
    "content": "package main\n\nfunc min1(a int) int {\n\treturn min(a)\n}\n\nfunc min2(a, b int) int {\n\treturn min(a, b)\n}\n\nfunc min3(a, b, c int) int {\n\treturn min(a, b, c)\n}\n\nfunc min4(a, b, c, d int) int {\n\treturn min(a, b, c, d)\n}\n\nfunc minUint8(a, b uint8) uint8 {\n\treturn min(a, b)\n}\n\nfunc minUnsigned(a, b uint) uint {\n\treturn min(a, b)\n}\n\nfunc minFloat32(a, b float32) float32 {\n\treturn min(a, b)\n}\n\nfunc minFloat64(a, b float64) float64 {\n\treturn min(a, b)\n}\n\nfunc minString(a, b string) string {\n\treturn min(a, b)\n}\n\nfunc maxInt(a, b int) int {\n\treturn max(a, b)\n}\n\nfunc maxUint(a, b uint) uint {\n\treturn max(a, b)\n}\n\nfunc maxFloat32(a, b float32) float32 {\n\treturn max(a, b)\n}\n\nfunc maxString(a, b string) string {\n\treturn max(a, b)\n}\n\nfunc clearSlice(s []int) {\n\tclear(s)\n}\n\nfunc clearZeroSizedSlice(s []struct{}) {\n\tclear(s)\n}\n\nfunc clearMap(m map[string]int) {\n\tclear(m)\n}\n"
  },
  {
    "path": "compiler/testdata/go1.21.ll",
    "content": "; ModuleID = 'go1.21.go'\nsource_filename = \"go1.21.go\"\ntarget datalayout = \"e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20\"\ntarget triple = \"wasm32-unknown-wasi\"\n\n%runtime._string = type { ptr, i32 }\n\n; Function Attrs: allockind(\"alloc,zeroed\") allocsize(0)\ndeclare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0\n\ndeclare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden void @main.init(ptr %context) unnamed_addr #2 {\nentry:\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden i32 @main.min1(i32 %a, ptr %context) unnamed_addr #2 {\nentry:\n  ret i32 %a\n}\n\n; Function Attrs: nounwind\ndefine hidden i32 @main.min2(i32 %a, i32 %b, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = call i32 @llvm.smin.i32(i32 %a, i32 %b)\n  ret i32 %0\n}\n\n; Function Attrs: nounwind\ndefine hidden i32 @main.min3(i32 %a, i32 %b, i32 %c, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = call i32 @llvm.smin.i32(i32 %a, i32 %b)\n  %1 = call i32 @llvm.smin.i32(i32 %0, i32 %c)\n  ret i32 %1\n}\n\n; Function Attrs: nounwind\ndefine hidden i32 @main.min4(i32 %a, i32 %b, i32 %c, i32 %d, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = call i32 @llvm.smin.i32(i32 %a, i32 %b)\n  %1 = call i32 @llvm.smin.i32(i32 %0, i32 %c)\n  %2 = call i32 @llvm.smin.i32(i32 %1, i32 %d)\n  ret i32 %2\n}\n\n; Function Attrs: nounwind\ndefine hidden i8 @main.minUint8(i8 %a, i8 %b, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = call i8 @llvm.umin.i8(i8 %a, i8 %b)\n  ret i8 %0\n}\n\n; Function Attrs: nounwind\ndefine hidden i32 @main.minUnsigned(i32 %a, i32 %b, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = call i32 @llvm.umin.i32(i32 %a, i32 %b)\n  ret i32 %0\n}\n\n; Function Attrs: nounwind\ndefine hidden float @main.minFloat32(float %a, float %b, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = fcmp olt float %a, %b\n  %1 = select i1 %0, float %a, float %b\n  ret float %1\n}\n\n; Function Attrs: nounwind\ndefine hidden double @main.minFloat64(double %a, double %b, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = fcmp olt double %a, %b\n  %1 = select i1 %0, double %a, double %b\n  ret double %1\n}\n\n; Function Attrs: nounwind\ndefine hidden %runtime._string @main.minString(ptr readonly %a.data, i32 %a.len, ptr readonly %b.data, i32 %b.len, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = insertvalue %runtime._string zeroinitializer, ptr %a.data, 0\n  %1 = insertvalue %runtime._string %0, i32 %a.len, 1\n  %2 = insertvalue %runtime._string zeroinitializer, ptr %b.data, 0\n  %3 = insertvalue %runtime._string %2, i32 %b.len, 1\n  %stackalloc = alloca i8, align 1\n  %4 = call i1 @runtime.stringLess(ptr %a.data, i32 %a.len, ptr %b.data, i32 %b.len, ptr undef) #5\n  %5 = select i1 %4, %runtime._string %1, %runtime._string %3\n  %6 = select i1 %4, ptr %a.data, ptr %b.data\n  call void @runtime.trackPointer(ptr %6, ptr nonnull %stackalloc, ptr undef) #5\n  ret %runtime._string %5\n}\n\ndeclare i1 @runtime.stringLess(ptr readonly, i32, ptr readonly, i32, ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden i32 @main.maxInt(i32 %a, i32 %b, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = call i32 @llvm.smax.i32(i32 %a, i32 %b)\n  ret i32 %0\n}\n\n; Function Attrs: nounwind\ndefine hidden i32 @main.maxUint(i32 %a, i32 %b, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = call i32 @llvm.umax.i32(i32 %a, i32 %b)\n  ret i32 %0\n}\n\n; Function Attrs: nounwind\ndefine hidden float @main.maxFloat32(float %a, float %b, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = fcmp ogt float %a, %b\n  %1 = select i1 %0, float %a, float %b\n  ret float %1\n}\n\n; Function Attrs: nounwind\ndefine hidden %runtime._string @main.maxString(ptr readonly %a.data, i32 %a.len, ptr readonly %b.data, i32 %b.len, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = insertvalue %runtime._string zeroinitializer, ptr %a.data, 0\n  %1 = insertvalue %runtime._string %0, i32 %a.len, 1\n  %2 = insertvalue %runtime._string zeroinitializer, ptr %b.data, 0\n  %3 = insertvalue %runtime._string %2, i32 %b.len, 1\n  %stackalloc = alloca i8, align 1\n  %4 = call i1 @runtime.stringLess(ptr %b.data, i32 %b.len, ptr %a.data, i32 %a.len, ptr undef) #5\n  %5 = select i1 %4, %runtime._string %1, %runtime._string %3\n  %6 = select i1 %4, ptr %a.data, ptr %b.data\n  call void @runtime.trackPointer(ptr %6, ptr nonnull %stackalloc, ptr undef) #5\n  ret %runtime._string %5\n}\n\n; Function Attrs: nounwind\ndefine hidden void @main.clearSlice(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = shl i32 %s.len, 2\n  call void @llvm.memset.p0.i32(ptr align 4 %s.data, i8 0, i32 %0, i1 false)\n  ret void\n}\n\n; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)\ndeclare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg) #3\n\n; Function Attrs: nounwind\ndefine hidden void @main.clearZeroSizedSlice(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context) unnamed_addr #2 {\nentry:\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden void @main.clearMap(ptr dereferenceable_or_null(40) %m, ptr %context) unnamed_addr #2 {\nentry:\n  call void @runtime.hashmapClear(ptr %m, ptr undef) #5\n  ret void\n}\n\ndeclare void @runtime.hashmapClear(ptr dereferenceable_or_null(40), ptr) #1\n\n; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)\ndeclare i32 @llvm.smin.i32(i32, i32) #4\n\n; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)\ndeclare i8 @llvm.umin.i8(i8, i8) #4\n\n; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)\ndeclare i32 @llvm.umin.i32(i32, i32) #4\n\n; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)\ndeclare i32 @llvm.smax.i32(i32, i32) #4\n\n; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)\ndeclare i32 @llvm.umax.i32(i32, i32) #4\n\nattributes #0 = { allockind(\"alloc,zeroed\") allocsize(0) \"alloc-family\"=\"runtime.alloc\" \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #1 = { \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #2 = { nounwind \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #3 = { nocallback nofree nounwind willreturn memory(argmem: write) }\nattributes #4 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }\nattributes #5 = { nounwind }\n"
  },
  {
    "path": "compiler/testdata/goroutine-cortex-m-qemu-tasks.ll",
    "content": "; ModuleID = 'goroutine.go'\nsource_filename = \"goroutine.go\"\ntarget datalayout = \"e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64\"\ntarget triple = \"thumbv7m-unknown-unknown-eabi\"\n\n@\"main$string\" = internal unnamed_addr constant [4 x i8] c\"test\", align 1\n\n; Function Attrs: allockind(\"alloc,zeroed\") allocsize(0)\ndeclare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0\n\n; Function Attrs: nounwind\ndefine hidden void @main.init(ptr %context) unnamed_addr #1 {\nentry:\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden void @main.regularFunctionGoroutine(ptr %context) unnamed_addr #1 {\nentry:\n  %stacksize = call i32 @\"internal/task.getGoroutineStackSize\"(i32 ptrtoint (ptr @\"main.regularFunction$gowrapper\" to i32), ptr undef) #9\n  call void @\"internal/task.start\"(i32 ptrtoint (ptr @\"main.regularFunction$gowrapper\" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 %stacksize, ptr undef) #9\n  ret void\n}\n\ndeclare void @main.regularFunction(i32, ptr) #2\n\n; Function Attrs: nounwind\ndefine linkonce_odr void @\"main.regularFunction$gowrapper\"(ptr %0) unnamed_addr #3 {\nentry:\n  %unpack.int = ptrtoint ptr %0 to i32\n  call void @main.regularFunction(i32 %unpack.int, ptr undef) #9\n  ret void\n}\n\ndeclare i32 @\"internal/task.getGoroutineStackSize\"(i32, ptr) #2\n\ndeclare void @\"internal/task.start\"(i32, ptr, i32, ptr) #2\n\n; Function Attrs: nounwind\ndefine hidden void @main.inlineFunctionGoroutine(ptr %context) unnamed_addr #1 {\nentry:\n  %stacksize = call i32 @\"internal/task.getGoroutineStackSize\"(i32 ptrtoint (ptr @\"main.inlineFunctionGoroutine$1$gowrapper\" to i32), ptr undef) #9\n  call void @\"internal/task.start\"(i32 ptrtoint (ptr @\"main.inlineFunctionGoroutine$1$gowrapper\" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 %stacksize, ptr undef) #9\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine internal void @\"main.inlineFunctionGoroutine$1\"(i32 %x, ptr %context) unnamed_addr #1 {\nentry:\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine linkonce_odr void @\"main.inlineFunctionGoroutine$1$gowrapper\"(ptr %0) unnamed_addr #4 {\nentry:\n  %unpack.int = ptrtoint ptr %0 to i32\n  call void @\"main.inlineFunctionGoroutine$1\"(i32 %unpack.int, ptr undef)\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden void @main.closureFunctionGoroutine(ptr %context) unnamed_addr #1 {\nentry:\n  %n = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #9\n  store i32 3, ptr %n, align 4\n  %0 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr null, ptr undef) #9\n  store i32 5, ptr %0, align 4\n  %1 = getelementptr inbounds nuw i8, ptr %0, i32 4\n  store ptr %n, ptr %1, align 4\n  %stacksize = call i32 @\"internal/task.getGoroutineStackSize\"(i32 ptrtoint (ptr @\"main.closureFunctionGoroutine$1$gowrapper\" to i32), ptr undef) #9\n  call void @\"internal/task.start\"(i32 ptrtoint (ptr @\"main.closureFunctionGoroutine$1$gowrapper\" to i32), ptr nonnull %0, i32 %stacksize, ptr undef) #9\n  %2 = load i32, ptr %n, align 4\n  call void @runtime.printlock(ptr undef) #9\n  call void @runtime.printint32(i32 %2, ptr undef) #9\n  call void @runtime.printunlock(ptr undef) #9\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine internal void @\"main.closureFunctionGoroutine$1\"(i32 %x, ptr %context) unnamed_addr #1 {\nentry:\n  store i32 7, ptr %context, align 4\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine linkonce_odr void @\"main.closureFunctionGoroutine$1$gowrapper\"(ptr %0) unnamed_addr #5 {\nentry:\n  %1 = load i32, ptr %0, align 4\n  %2 = getelementptr inbounds nuw i8, ptr %0, i32 4\n  %3 = load ptr, ptr %2, align 4\n  call void @\"main.closureFunctionGoroutine$1\"(i32 %1, ptr %3)\n  ret void\n}\n\ndeclare void @runtime.printlock(ptr) #2\n\ndeclare void @runtime.printint32(i32, ptr) #2\n\ndeclare void @runtime.printunlock(ptr) #2\n\n; Function Attrs: nounwind\ndefine hidden void @main.funcGoroutine(ptr %fn.context, ptr %fn.funcptr, ptr %context) unnamed_addr #1 {\nentry:\n  %0 = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr null, ptr undef) #9\n  store i32 5, ptr %0, align 4\n  %1 = getelementptr inbounds nuw i8, ptr %0, i32 4\n  store ptr %fn.context, ptr %1, align 4\n  %2 = getelementptr inbounds nuw i8, ptr %0, i32 8\n  store ptr %fn.funcptr, ptr %2, align 4\n  %stacksize = call i32 @\"internal/task.getGoroutineStackSize\"(i32 ptrtoint (ptr @main.funcGoroutine.gowrapper to i32), ptr undef) #9\n  call void @\"internal/task.start\"(i32 ptrtoint (ptr @main.funcGoroutine.gowrapper to i32), ptr nonnull %0, i32 %stacksize, ptr undef) #9\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine linkonce_odr void @main.funcGoroutine.gowrapper(ptr %0) unnamed_addr #6 {\nentry:\n  %1 = load i32, ptr %0, align 4\n  %2 = getelementptr inbounds nuw i8, ptr %0, i32 4\n  %3 = load ptr, ptr %2, align 4\n  %4 = getelementptr inbounds nuw i8, ptr %0, i32 8\n  %5 = load ptr, ptr %4, align 4\n  call void %5(i32 %1, ptr %3) #9\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden void @main.recoverBuiltinGoroutine(ptr %context) unnamed_addr #1 {\nentry:\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden void @main.copyBuiltinGoroutine(ptr %dst.data, i32 %dst.len, i32 %dst.cap, ptr %src.data, i32 %src.len, i32 %src.cap, ptr %context) unnamed_addr #1 {\nentry:\n  %copy.n = call i32 @runtime.sliceCopy(ptr %dst.data, ptr %src.data, i32 %dst.len, i32 %src.len, i32 1, ptr undef) #9\n  ret void\n}\n\ndeclare i32 @runtime.sliceCopy(ptr nocapture writeonly, ptr nocapture readonly, i32, i32, i32, ptr) #2\n\n; Function Attrs: nounwind\ndefine hidden void @main.closeBuiltinGoroutine(ptr dereferenceable_or_null(36) %ch, ptr %context) unnamed_addr #1 {\nentry:\n  call void @runtime.chanClose(ptr %ch, ptr undef) #9\n  ret void\n}\n\ndeclare void @runtime.chanClose(ptr dereferenceable_or_null(36), ptr) #2\n\n; Function Attrs: nounwind\ndefine hidden void @main.startInterfaceMethod(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #1 {\nentry:\n  %0 = call align 4 dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #9\n  store ptr %itf.value, ptr %0, align 4\n  %1 = getelementptr inbounds nuw i8, ptr %0, i32 4\n  store ptr @\"main$string\", ptr %1, align 4\n  %2 = getelementptr inbounds nuw i8, ptr %0, i32 8\n  store i32 4, ptr %2, align 4\n  %3 = getelementptr inbounds nuw i8, ptr %0, i32 12\n  store ptr %itf.typecode, ptr %3, align 4\n  %stacksize = call i32 @\"internal/task.getGoroutineStackSize\"(i32 ptrtoint (ptr @\"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper\" to i32), ptr undef) #9\n  call void @\"internal/task.start\"(i32 ptrtoint (ptr @\"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper\" to i32), ptr nonnull %0, i32 %stacksize, ptr undef) #9\n  ret void\n}\n\ndeclare void @\"interface:{Print:func:{basic:string}{}}.Print$invoke\"(ptr, ptr, i32, ptr, ptr) #7\n\n; Function Attrs: nounwind\ndefine linkonce_odr void @\"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper\"(ptr %0) unnamed_addr #8 {\nentry:\n  %1 = load ptr, ptr %0, align 4\n  %2 = getelementptr inbounds nuw i8, ptr %0, i32 4\n  %3 = load ptr, ptr %2, align 4\n  %4 = getelementptr inbounds nuw i8, ptr %0, i32 8\n  %5 = load i32, ptr %4, align 4\n  %6 = getelementptr inbounds nuw i8, ptr %0, i32 12\n  %7 = load ptr, ptr %6, align 4\n  call void @\"interface:{Print:func:{basic:string}{}}.Print$invoke\"(ptr %1, ptr %3, i32 %5, ptr %7, ptr undef) #9\n  ret void\n}\n\nattributes #0 = { allockind(\"alloc,zeroed\") allocsize(0) \"alloc-family\"=\"runtime.alloc\" \"target-features\"=\"+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp\" }\nattributes #1 = { nounwind \"target-features\"=\"+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp\" }\nattributes #2 = { \"target-features\"=\"+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp\" }\nattributes #3 = { nounwind \"target-features\"=\"+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp\" \"tinygo-gowrapper\"=\"main.regularFunction\" }\nattributes #4 = { nounwind \"target-features\"=\"+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp\" \"tinygo-gowrapper\"=\"main.inlineFunctionGoroutine$1\" }\nattributes #5 = { nounwind \"target-features\"=\"+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp\" \"tinygo-gowrapper\"=\"main.closureFunctionGoroutine$1\" }\nattributes #6 = { nounwind \"target-features\"=\"+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp\" \"tinygo-gowrapper\" }\nattributes #7 = { \"target-features\"=\"+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp\" \"tinygo-invoke\"=\"reflect/methods.Print(string)\" \"tinygo-methods\"=\"reflect/methods.Print(string)\" }\nattributes #8 = { nounwind \"target-features\"=\"+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp\" \"tinygo-gowrapper\"=\"interface:{Print:func:{basic:string}{}}.Print$invoke\" }\nattributes #9 = { nounwind }\n"
  },
  {
    "path": "compiler/testdata/goroutine-wasm-asyncify.ll",
    "content": "; ModuleID = 'goroutine.go'\nsource_filename = \"goroutine.go\"\ntarget datalayout = \"e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20\"\ntarget triple = \"wasm32-unknown-wasi\"\n\n@\"main$string\" = internal unnamed_addr constant [4 x i8] c\"test\", align 1\n\n; Function Attrs: allockind(\"alloc,zeroed\") allocsize(0)\ndeclare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0\n\ndeclare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden void @main.init(ptr %context) unnamed_addr #2 {\nentry:\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden void @main.regularFunctionGoroutine(ptr %context) unnamed_addr #2 {\nentry:\n  call void @\"internal/task.start\"(i32 ptrtoint (ptr @\"main.regularFunction$gowrapper\" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 65536, ptr undef) #9\n  ret void\n}\n\ndeclare void @main.regularFunction(i32, ptr) #1\n\ndeclare void @runtime.deadlock(ptr) #1\n\n; Function Attrs: nounwind\ndefine linkonce_odr void @\"main.regularFunction$gowrapper\"(ptr %0) unnamed_addr #3 {\nentry:\n  %unpack.int = ptrtoint ptr %0 to i32\n  call void @main.regularFunction(i32 %unpack.int, ptr undef) #9\n  call void @runtime.deadlock(ptr undef) #9\n  unreachable\n}\n\ndeclare void @\"internal/task.start\"(i32, ptr, i32, ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden void @main.inlineFunctionGoroutine(ptr %context) unnamed_addr #2 {\nentry:\n  call void @\"internal/task.start\"(i32 ptrtoint (ptr @\"main.inlineFunctionGoroutine$1$gowrapper\" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 65536, ptr undef) #9\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine internal void @\"main.inlineFunctionGoroutine$1\"(i32 %x, ptr %context) unnamed_addr #2 {\nentry:\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine linkonce_odr void @\"main.inlineFunctionGoroutine$1$gowrapper\"(ptr %0) unnamed_addr #4 {\nentry:\n  %unpack.int = ptrtoint ptr %0 to i32\n  call void @\"main.inlineFunctionGoroutine$1\"(i32 %unpack.int, ptr undef)\n  call void @runtime.deadlock(ptr undef) #9\n  unreachable\n}\n\n; Function Attrs: nounwind\ndefine hidden void @main.closureFunctionGoroutine(ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  %n = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #9\n  call void @runtime.trackPointer(ptr nonnull %n, ptr nonnull %stackalloc, ptr undef) #9\n  store i32 3, ptr %n, align 4\n  call void @runtime.trackPointer(ptr nonnull %n, ptr nonnull %stackalloc, ptr undef) #9\n  call void @runtime.trackPointer(ptr nonnull @\"main.closureFunctionGoroutine$1\", ptr nonnull %stackalloc, ptr undef) #9\n  %0 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr null, ptr undef) #9\n  call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #9\n  store i32 5, ptr %0, align 4\n  %1 = getelementptr inbounds nuw i8, ptr %0, i32 4\n  store ptr %n, ptr %1, align 4\n  call void @\"internal/task.start\"(i32 ptrtoint (ptr @\"main.closureFunctionGoroutine$1$gowrapper\" to i32), ptr nonnull %0, i32 65536, ptr undef) #9\n  %2 = load i32, ptr %n, align 4\n  call void @runtime.printlock(ptr undef) #9\n  call void @runtime.printint32(i32 %2, ptr undef) #9\n  call void @runtime.printunlock(ptr undef) #9\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine internal void @\"main.closureFunctionGoroutine$1\"(i32 %x, ptr %context) unnamed_addr #2 {\nentry:\n  store i32 7, ptr %context, align 4\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine linkonce_odr void @\"main.closureFunctionGoroutine$1$gowrapper\"(ptr %0) unnamed_addr #5 {\nentry:\n  %1 = load i32, ptr %0, align 4\n  %2 = getelementptr inbounds nuw i8, ptr %0, i32 4\n  %3 = load ptr, ptr %2, align 4\n  call void @\"main.closureFunctionGoroutine$1\"(i32 %1, ptr %3)\n  call void @runtime.deadlock(ptr undef) #9\n  unreachable\n}\n\ndeclare void @runtime.printlock(ptr) #1\n\ndeclare void @runtime.printint32(i32, ptr) #1\n\ndeclare void @runtime.printunlock(ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden void @main.funcGoroutine(ptr %fn.context, ptr %fn.funcptr, ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  %0 = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr null, ptr undef) #9\n  call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #9\n  store i32 5, ptr %0, align 4\n  %1 = getelementptr inbounds nuw i8, ptr %0, i32 4\n  store ptr %fn.context, ptr %1, align 4\n  %2 = getelementptr inbounds nuw i8, ptr %0, i32 8\n  store ptr %fn.funcptr, ptr %2, align 4\n  call void @\"internal/task.start\"(i32 ptrtoint (ptr @main.funcGoroutine.gowrapper to i32), ptr nonnull %0, i32 65536, ptr undef) #9\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine linkonce_odr void @main.funcGoroutine.gowrapper(ptr %0) unnamed_addr #6 {\nentry:\n  %1 = load i32, ptr %0, align 4\n  %2 = getelementptr inbounds nuw i8, ptr %0, i32 4\n  %3 = load ptr, ptr %2, align 4\n  %4 = getelementptr inbounds nuw i8, ptr %0, i32 8\n  %5 = load ptr, ptr %4, align 4\n  call void %5(i32 %1, ptr %3) #9\n  call void @runtime.deadlock(ptr undef) #9\n  unreachable\n}\n\n; Function Attrs: nounwind\ndefine hidden void @main.recoverBuiltinGoroutine(ptr %context) unnamed_addr #2 {\nentry:\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden void @main.copyBuiltinGoroutine(ptr %dst.data, i32 %dst.len, i32 %dst.cap, ptr %src.data, i32 %src.len, i32 %src.cap, ptr %context) unnamed_addr #2 {\nentry:\n  %copy.n = call i32 @runtime.sliceCopy(ptr %dst.data, ptr %src.data, i32 %dst.len, i32 %src.len, i32 1, ptr undef) #9\n  ret void\n}\n\ndeclare i32 @runtime.sliceCopy(ptr nocapture writeonly, ptr nocapture readonly, i32, i32, i32, ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden void @main.closeBuiltinGoroutine(ptr dereferenceable_or_null(36) %ch, ptr %context) unnamed_addr #2 {\nentry:\n  call void @runtime.chanClose(ptr %ch, ptr undef) #9\n  ret void\n}\n\ndeclare void @runtime.chanClose(ptr dereferenceable_or_null(36), ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden void @main.startInterfaceMethod(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  %0 = call align 4 dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #9\n  call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #9\n  store ptr %itf.value, ptr %0, align 4\n  %1 = getelementptr inbounds nuw i8, ptr %0, i32 4\n  store ptr @\"main$string\", ptr %1, align 4\n  %2 = getelementptr inbounds nuw i8, ptr %0, i32 8\n  store i32 4, ptr %2, align 4\n  %3 = getelementptr inbounds nuw i8, ptr %0, i32 12\n  store ptr %itf.typecode, ptr %3, align 4\n  call void @\"internal/task.start\"(i32 ptrtoint (ptr @\"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper\" to i32), ptr nonnull %0, i32 65536, ptr undef) #9\n  ret void\n}\n\ndeclare void @\"interface:{Print:func:{basic:string}{}}.Print$invoke\"(ptr, ptr, i32, ptr, ptr) #7\n\n; Function Attrs: nounwind\ndefine linkonce_odr void @\"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper\"(ptr %0) unnamed_addr #8 {\nentry:\n  %1 = load ptr, ptr %0, align 4\n  %2 = getelementptr inbounds nuw i8, ptr %0, i32 4\n  %3 = load ptr, ptr %2, align 4\n  %4 = getelementptr inbounds nuw i8, ptr %0, i32 8\n  %5 = load i32, ptr %4, align 4\n  %6 = getelementptr inbounds nuw i8, ptr %0, i32 12\n  %7 = load ptr, ptr %6, align 4\n  call void @\"interface:{Print:func:{basic:string}{}}.Print$invoke\"(ptr %1, ptr %3, i32 %5, ptr %7, ptr undef) #9\n  call void @runtime.deadlock(ptr undef) #9\n  unreachable\n}\n\nattributes #0 = { allockind(\"alloc,zeroed\") allocsize(0) \"alloc-family\"=\"runtime.alloc\" \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #1 = { \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #2 = { nounwind \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #3 = { nounwind \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" \"tinygo-gowrapper\"=\"main.regularFunction\" }\nattributes #4 = { nounwind \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" \"tinygo-gowrapper\"=\"main.inlineFunctionGoroutine$1\" }\nattributes #5 = { nounwind \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" \"tinygo-gowrapper\"=\"main.closureFunctionGoroutine$1\" }\nattributes #6 = { nounwind \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" \"tinygo-gowrapper\" }\nattributes #7 = { \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" \"tinygo-invoke\"=\"reflect/methods.Print(string)\" \"tinygo-methods\"=\"reflect/methods.Print(string)\" }\nattributes #8 = { nounwind \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" \"tinygo-gowrapper\"=\"interface:{Print:func:{basic:string}{}}.Print$invoke\" }\nattributes #9 = { nounwind }\n"
  },
  {
    "path": "compiler/testdata/goroutine.go",
    "content": "package main\n\nfunc regularFunctionGoroutine() {\n\tgo regularFunction(5)\n}\n\nfunc inlineFunctionGoroutine() {\n\tgo func(x int) {\n\t}(5)\n}\n\nfunc closureFunctionGoroutine() {\n\tn := 3\n\tgo func(x int) {\n\t\tn = 7\n\t}(5)\n\tprint(n) // note: this is racy (but good enough for this test)\n}\n\nfunc funcGoroutine(fn func(x int)) {\n\tgo fn(5)\n}\n\nfunc recoverBuiltinGoroutine() {\n\t// This is a no-op.\n\tgo recover()\n}\n\nfunc copyBuiltinGoroutine(dst, src []byte) {\n\t// This is not run in a goroutine. While this copy operation can indeed take\n\t// some time (if there is a lot of data to copy), there is no race-free way\n\t// to make use of the result so it's unlikely applications will make use of\n\t// it. And doing it this way should be just within the Go specification.\n\tgo copy(dst, src)\n}\n\nfunc closeBuiltinGoroutine(ch chan int) {\n\t// This builtin is executed directly, not in a goroutine.\n\t// The observed behavior is the same.\n\tgo close(ch)\n}\n\nfunc regularFunction(x int)\n\ntype simpleInterface interface {\n\tPrint(string)\n}\n\nfunc startInterfaceMethod(itf simpleInterface) {\n\tgo itf.Print(\"test\")\n}\n"
  },
  {
    "path": "compiler/testdata/interface.go",
    "content": "// This file tests interface types and interface builtins.\n\npackage main\n\n// Test interface construction.\n\nfunc simpleType() interface{} {\n\treturn 0\n}\n\nfunc pointerType() interface{} {\n\t// Pointers have an element type, in this case int.\n\tvar v *int\n\treturn v\n}\n\nfunc interfaceType() interface{} {\n\t// Interfaces can exist in interfaces, but only indirectly (through\n\t// pointers).\n\tvar v *error\n\treturn v\n}\n\nfunc anonymousInterfaceType() interface{} {\n\tvar v *interface {\n\t\tString() string\n\t}\n\treturn v\n}\n\n// Test interface builtins.\n\nfunc isInt(itf interface{}) bool {\n\t_, ok := itf.(int)\n\treturn ok\n}\n\nfunc isError(itf interface{}) bool {\n\t// Interface assert on (builtin) named interface type.\n\t_, ok := itf.(error)\n\treturn ok\n}\n\nfunc isStringer(itf interface{}) bool {\n\t// Interface assert on anonymous interface type.\n\t_, ok := itf.(interface {\n\t\tString() string\n\t})\n\treturn ok\n}\n\ntype fooInterface interface {\n\tString() string\n\tfoo(int) byte\n}\n\nfunc callFooMethod(itf fooInterface) uint8 {\n\treturn itf.foo(3)\n}\n\nfunc callErrorMethod(itf error) string {\n\treturn itf.Error()\n}\n"
  },
  {
    "path": "compiler/testdata/interface.ll",
    "content": "; ModuleID = 'interface.go'\nsource_filename = \"interface.go\"\ntarget datalayout = \"e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20\"\ntarget triple = \"wasm32-unknown-wasi\"\n\n%runtime._interface = type { ptr, ptr }\n%runtime._string = type { ptr, i32 }\n\n@\"reflect/types.type:basic:int\" = linkonce_odr constant { i8, ptr } { i8 -62, ptr @\"reflect/types.type:pointer:basic:int\" }, align 4\n@\"reflect/types.type:pointer:basic:int\" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @\"reflect/types.type:basic:int\" }, align 4\n@\"reflect/types.type:pointer:named:error\" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @\"reflect/types.type:named:error\" }, align 4\n@\"reflect/types.type:named:error\" = linkonce_odr constant { i8, i16, ptr, ptr, ptr, [7 x i8] } { i8 116, i16 1, ptr @\"reflect/types.type:pointer:named:error\", ptr @\"reflect/types.type:interface:{Error:func:{}{basic:string}}\", ptr @\"reflect/types.type.pkgpath.empty\", [7 x i8] c\".error\\00\" }, align 4\n@\"reflect/types.type.pkgpath.empty\" = linkonce_odr unnamed_addr constant [1 x i8] zeroinitializer, align 1\n@\"reflect/types.type:interface:{Error:func:{}{basic:string}}\" = linkonce_odr constant { i8, ptr } { i8 84, ptr @\"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}\" }, align 4\n@\"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}\" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @\"reflect/types.type:interface:{Error:func:{}{basic:string}}\" }, align 4\n@\"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}\" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @\"reflect/types.type:interface:{String:func:{}{basic:string}}\" }, align 4\n@\"reflect/types.type:interface:{String:func:{}{basic:string}}\" = linkonce_odr constant { i8, ptr } { i8 84, ptr @\"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}\" }, align 4\n@\"reflect/types.typeid:basic:int\" = external constant i8\n\n; Function Attrs: allockind(\"alloc,zeroed\") allocsize(0)\ndeclare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0\n\ndeclare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden void @main.init(ptr %context) unnamed_addr #2 {\nentry:\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden %runtime._interface @main.simpleType(ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  call void @runtime.trackPointer(ptr nonnull @\"reflect/types.type:basic:int\", ptr nonnull %stackalloc, ptr undef) #7\n  call void @runtime.trackPointer(ptr null, ptr nonnull %stackalloc, ptr undef) #7\n  ret %runtime._interface { ptr @\"reflect/types.type:basic:int\", ptr null }\n}\n\n; Function Attrs: nounwind\ndefine hidden %runtime._interface @main.pointerType(ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  call void @runtime.trackPointer(ptr nonnull @\"reflect/types.type:pointer:basic:int\", ptr nonnull %stackalloc, ptr undef) #7\n  call void @runtime.trackPointer(ptr null, ptr nonnull %stackalloc, ptr undef) #7\n  ret %runtime._interface { ptr @\"reflect/types.type:pointer:basic:int\", ptr null }\n}\n\n; Function Attrs: nounwind\ndefine hidden %runtime._interface @main.interfaceType(ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  call void @runtime.trackPointer(ptr nonnull @\"reflect/types.type:pointer:named:error\", ptr nonnull %stackalloc, ptr undef) #7\n  call void @runtime.trackPointer(ptr null, ptr nonnull %stackalloc, ptr undef) #7\n  ret %runtime._interface { ptr @\"reflect/types.type:pointer:named:error\", ptr null }\n}\n\n; Function Attrs: nounwind\ndefine hidden %runtime._interface @main.anonymousInterfaceType(ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  call void @runtime.trackPointer(ptr nonnull @\"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}\", ptr nonnull %stackalloc, ptr undef) #7\n  call void @runtime.trackPointer(ptr null, ptr nonnull %stackalloc, ptr undef) #7\n  ret %runtime._interface { ptr @\"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}\", ptr null }\n}\n\n; Function Attrs: nounwind\ndefine hidden i1 @main.isInt(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #2 {\nentry:\n  %typecode = call i1 @runtime.typeAssert(ptr %itf.typecode, ptr nonnull @\"reflect/types.typeid:basic:int\", ptr undef) #7\n  br i1 %typecode, label %typeassert.ok, label %typeassert.next\n\ntypeassert.next:                                  ; preds = %typeassert.ok, %entry\n  ret i1 %typecode\n\ntypeassert.ok:                                    ; preds = %entry\n  br label %typeassert.next\n}\n\ndeclare i1 @runtime.typeAssert(ptr, ptr dereferenceable_or_null(1), ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden i1 @main.isError(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = call i1 @\"interface:{Error:func:{}{basic:string}}.$typeassert\"(ptr %itf.typecode) #7\n  br i1 %0, label %typeassert.ok, label %typeassert.next\n\ntypeassert.next:                                  ; preds = %typeassert.ok, %entry\n  ret i1 %0\n\ntypeassert.ok:                                    ; preds = %entry\n  br label %typeassert.next\n}\n\ndeclare i1 @\"interface:{Error:func:{}{basic:string}}.$typeassert\"(ptr) #3\n\n; Function Attrs: nounwind\ndefine hidden i1 @main.isStringer(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = call i1 @\"interface:{String:func:{}{basic:string}}.$typeassert\"(ptr %itf.typecode) #7\n  br i1 %0, label %typeassert.ok, label %typeassert.next\n\ntypeassert.next:                                  ; preds = %typeassert.ok, %entry\n  ret i1 %0\n\ntypeassert.ok:                                    ; preds = %entry\n  br label %typeassert.next\n}\n\ndeclare i1 @\"interface:{String:func:{}{basic:string}}.$typeassert\"(ptr) #4\n\n; Function Attrs: nounwind\ndefine hidden i8 @main.callFooMethod(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = call i8 @\"interface:{String:func:{}{basic:string},main.foo:func:{basic:int}{basic:uint8}}.foo$invoke\"(ptr %itf.value, i32 3, ptr %itf.typecode, ptr undef) #7\n  ret i8 %0\n}\n\ndeclare i8 @\"interface:{String:func:{}{basic:string},main.foo:func:{basic:int}{basic:uint8}}.foo$invoke\"(ptr, i32, ptr, ptr) #5\n\n; Function Attrs: nounwind\ndefine hidden %runtime._string @main.callErrorMethod(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  %0 = call %runtime._string @\"interface:{Error:func:{}{basic:string}}.Error$invoke\"(ptr %itf.value, ptr %itf.typecode, ptr undef) #7\n  %1 = extractvalue %runtime._string %0, 0\n  call void @runtime.trackPointer(ptr %1, ptr nonnull %stackalloc, ptr undef) #7\n  ret %runtime._string %0\n}\n\ndeclare %runtime._string @\"interface:{Error:func:{}{basic:string}}.Error$invoke\"(ptr, ptr, ptr) #6\n\nattributes #0 = { allockind(\"alloc,zeroed\") allocsize(0) \"alloc-family\"=\"runtime.alloc\" \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #1 = { \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #2 = { nounwind \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #3 = { \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" \"tinygo-methods\"=\"reflect/methods.Error() string\" }\nattributes #4 = { \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" \"tinygo-methods\"=\"reflect/methods.String() string\" }\nattributes #5 = { \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" \"tinygo-invoke\"=\"main.$methods.foo(int) uint8\" \"tinygo-methods\"=\"reflect/methods.String() string; main.$methods.foo(int) uint8\" }\nattributes #6 = { \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" \"tinygo-invoke\"=\"reflect/methods.Error() string\" \"tinygo-methods\"=\"reflect/methods.Error() string\" }\nattributes #7 = { nounwind }\n"
  },
  {
    "path": "compiler/testdata/pointer.go",
    "content": "package main\n\n// This file tests various operations on pointers, such as pointer arithmetic\n// and dereferencing pointers.\n\nimport \"unsafe\"\n\n// Dereference pointers.\n\nfunc pointerDerefZero(x *[0]int) [0]int {\n\treturn *x // This is a no-op, there is nothing to load.\n}\n\n// Unsafe pointer casts, they are sometimes a no-op.\n\nfunc pointerCastFromUnsafe(x unsafe.Pointer) *int {\n\treturn (*int)(x)\n}\n\nfunc pointerCastToUnsafe(x *int) unsafe.Pointer {\n\treturn unsafe.Pointer(x)\n}\n\nfunc pointerCastToUnsafeNoop(x *byte) unsafe.Pointer {\n\treturn unsafe.Pointer(x)\n}\n"
  },
  {
    "path": "compiler/testdata/pointer.ll",
    "content": "; ModuleID = 'pointer.go'\nsource_filename = \"pointer.go\"\ntarget datalayout = \"e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20\"\ntarget triple = \"wasm32-unknown-wasi\"\n\n; Function Attrs: allockind(\"alloc,zeroed\") allocsize(0)\ndeclare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0\n\ndeclare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden void @main.init(ptr %context) unnamed_addr #2 {\nentry:\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden [0 x i32] @main.pointerDerefZero(ptr %x, ptr %context) unnamed_addr #2 {\nentry:\n  ret [0 x i32] zeroinitializer\n}\n\n; Function Attrs: nounwind\ndefine hidden ptr @main.pointerCastFromUnsafe(ptr %x, ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  call void @runtime.trackPointer(ptr %x, ptr nonnull %stackalloc, ptr undef) #3\n  ret ptr %x\n}\n\n; Function Attrs: nounwind\ndefine hidden ptr @main.pointerCastToUnsafe(ptr dereferenceable_or_null(4) %x, ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  call void @runtime.trackPointer(ptr %x, ptr nonnull %stackalloc, ptr undef) #3\n  ret ptr %x\n}\n\n; Function Attrs: nounwind\ndefine hidden ptr @main.pointerCastToUnsafeNoop(ptr dereferenceable_or_null(1) %x, ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  call void @runtime.trackPointer(ptr %x, ptr nonnull %stackalloc, ptr undef) #3\n  ret ptr %x\n}\n\nattributes #0 = { allockind(\"alloc,zeroed\") allocsize(0) \"alloc-family\"=\"runtime.alloc\" \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #1 = { \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #2 = { nounwind \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #3 = { nounwind }\n"
  },
  {
    "path": "compiler/testdata/pragma.go",
    "content": "package main\n\nimport _ \"unsafe\"\n\n// Creates an external global with name extern_global.\n//\n//go:extern extern_global\nvar externGlobal [0]byte\n\n// Creates a\n//\n//go:align 32\nvar alignedGlobal [4]uint32\n\n// Test conflicting pragmas (the last one counts).\n//\n//go:align 64\n//go:align 16\nvar alignedGlobal16 [4]uint32\n\n// Test exported functions.\n//\n//export extern_func\nfunc externFunc() {\n}\n\n// Define a function in a different package using go:linkname.\n//\n//go:linkname withLinkageName1 somepkg.someFunction1\nfunc withLinkageName1() {\n}\n\n// Import a function from a different package using go:linkname.\n//\n//go:linkname withLinkageName2 somepkg.someFunction2\nfunc withLinkageName2()\n\n// Function has an 'inline hint', similar to the inline keyword in C.\n//\n//go:inline\nfunc inlineFunc() {\n}\n\n// Function should never be inlined, equivalent to GCC\n// __attribute__((noinline)).\n//\n//go:noinline\nfunc noinlineFunc() {\n}\n\ntype Int interface {\n\tint8 | int16\n}\n\n// Same for generic functions (but the compiler may miss the pragma due to it\n// being generic).\n//\n//go:noinline\nfunc noinlineGenericFunc[T Int]() {\n}\n\nfunc useGeneric() {\n\t// Make sure the generic function above is instantiated.\n\tnoinlineGenericFunc[int8]()\n}\n\n// This function should have the specified section.\n//\n//go:section .special_function_section\nfunc functionInSection() {\n}\n\n//export exportedFunctionInSection\n//go:section .special_function_section\nfunc exportedFunctionInSection() {\n}\n\n//go:wasmimport modulename import1\nfunc declaredImport()\n\n// Legacy way of importing a function.\n//\n//go:wasm-module foobar\n//export imported\nfunc foobarImport()\n\n// The wasm-module pragma is not functional here, but it should be safe.\n//\n//go:wasm-module foobar\n//export exported\nfunc foobarExportModule() {\n}\n\n// This function should not: it's only a declaration and not a definition.\n//\n//go:section .special_function_section\nfunc undefinedFunctionNotInSection()\n\n//go:section .special_global_section\nvar globalInSection uint32\n\n//go:section .special_global_section\n//go:extern undefinedGlobalNotInSection\nvar undefinedGlobalNotInSection uint32\n\n//go:align 1024\n//go:section .global_section\nvar multipleGlobalPragmas uint32\n\n//go:noescape\nfunc doesNotEscapeParam(a *int, b []int, c chan int, d *[0]byte)\n\n// The //go:noescape pragma only works on declarations, not definitions.\n//\n//go:noescape\nfunc stillEscapes(a *int, b []int, c chan int, d *[0]byte) {\n}\n"
  },
  {
    "path": "compiler/testdata/pragma.ll",
    "content": "; ModuleID = 'pragma.go'\nsource_filename = \"pragma.go\"\ntarget datalayout = \"e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20\"\ntarget triple = \"wasm32-unknown-wasi\"\n\n@extern_global = external global [0 x i8], align 1\n@main.alignedGlobal = hidden global [4 x i32] zeroinitializer, align 32\n@main.alignedGlobal16 = hidden global [4 x i32] zeroinitializer, align 16\n@llvm.used = appending global [3 x ptr] [ptr @extern_func, ptr @exportedFunctionInSection, ptr @exported]\n@main.globalInSection = hidden global i32 0, section \".special_global_section\", align 4\n@undefinedGlobalNotInSection = external global i32, align 4\n@main.multipleGlobalPragmas = hidden global i32 0, section \".global_section\", align 1024\n\n; Function Attrs: allockind(\"alloc,zeroed\") allocsize(0)\ndeclare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0\n\ndeclare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden void @main.init(ptr %context) unnamed_addr #2 {\nentry:\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine void @extern_func() #3 {\nentry:\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden void @somepkg.someFunction1(ptr %context) unnamed_addr #2 {\nentry:\n  ret void\n}\n\ndeclare void @somepkg.someFunction2(ptr) #1\n\n; Function Attrs: inlinehint nounwind\ndefine hidden void @main.inlineFunc(ptr %context) unnamed_addr #4 {\nentry:\n  ret void\n}\n\n; Function Attrs: noinline nounwind\ndefine hidden void @main.noinlineFunc(ptr %context) unnamed_addr #5 {\nentry:\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden void @main.useGeneric(ptr %context) unnamed_addr #2 {\nentry:\n  call void @\"main.noinlineGenericFunc[int8]\"(ptr undef)\n  ret void\n}\n\n; Function Attrs: noinline nounwind\ndefine linkonce_odr hidden void @\"main.noinlineGenericFunc[int8]\"(ptr %context) unnamed_addr #5 {\nentry:\n  ret void\n}\n\n; Function Attrs: noinline nounwind\ndefine hidden void @main.functionInSection(ptr %context) unnamed_addr #5 section \".special_function_section\" {\nentry:\n  ret void\n}\n\n; Function Attrs: noinline nounwind\ndefine void @exportedFunctionInSection() #6 section \".special_function_section\" {\nentry:\n  ret void\n}\n\ndeclare void @main.declaredImport() #7\n\ndeclare void @imported() #8\n\n; Function Attrs: nounwind\ndefine void @exported() #9 {\nentry:\n  ret void\n}\n\ndeclare void @main.undefinedFunctionNotInSection(ptr) #1\n\ndeclare void @main.doesNotEscapeParam(ptr nocapture dereferenceable_or_null(4), ptr nocapture, i32, i32, ptr nocapture dereferenceable_or_null(36), ptr nocapture, ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden void @main.stillEscapes(ptr dereferenceable_or_null(4) %a, ptr %b.data, i32 %b.len, i32 %b.cap, ptr dereferenceable_or_null(36) %c, ptr %d, ptr %context) unnamed_addr #2 {\nentry:\n  ret void\n}\n\nattributes #0 = { allockind(\"alloc,zeroed\") allocsize(0) \"alloc-family\"=\"runtime.alloc\" \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #1 = { \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #2 = { nounwind \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #3 = { nounwind \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" \"wasm-export-name\"=\"extern_func\" }\nattributes #4 = { inlinehint nounwind \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #5 = { noinline nounwind \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #6 = { noinline nounwind \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" \"wasm-export-name\"=\"exportedFunctionInSection\" }\nattributes #7 = { \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" \"wasm-import-module\"=\"modulename\" \"wasm-import-name\"=\"import1\" }\nattributes #8 = { \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" \"wasm-import-module\"=\"foobar\" \"wasm-import-name\"=\"imported\" }\nattributes #9 = { nounwind \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" \"wasm-export-name\"=\"exported\" }\n"
  },
  {
    "path": "compiler/testdata/slice.go",
    "content": "package main\n\nimport \"unsafe\"\n\nfunc sliceLen(ints []int) int {\n\treturn len(ints)\n}\n\nfunc sliceCap(ints []int) int {\n\treturn cap(ints)\n}\n\nfunc sliceElement(ints []int, index int) int {\n\treturn ints[index]\n}\n\nfunc sliceAppendValues(ints []int) []int {\n\treturn append(ints, 1, 2, 3)\n}\n\nfunc sliceAppendSlice(ints, added []int) []int {\n\treturn append(ints, added...)\n}\n\nfunc sliceCopy(dst, src []int) int {\n\treturn copy(dst, src)\n}\n\n// Test bounds checking in *ssa.MakeSlice instruction.\n\nfunc makeByteSlice(len int) []byte {\n\treturn make([]byte, len)\n}\n\nfunc makeInt16Slice(len int) []int16 {\n\treturn make([]int16, len)\n}\n\nfunc makeArraySlice(len int) [][3]byte {\n\treturn make([][3]byte, len) // slice with element size of 3\n}\n\nfunc makeInt32Slice(len int) []int32 {\n\treturn make([]int32, len)\n}\n\nfunc Add32(p unsafe.Pointer, len int) unsafe.Pointer {\n\treturn unsafe.Add(p, len)\n}\n\nfunc Add64(p unsafe.Pointer, len int64) unsafe.Pointer {\n\treturn unsafe.Add(p, len)\n}\n\nfunc SliceToArray(s []int) *[4]int {\n\treturn (*[4]int)(s)\n}\n\nfunc SliceToArrayConst() *[4]int {\n\ts := make([]int, 6)\n\treturn (*[4]int)(s)\n}\n\nfunc SliceInt(ptr *int, len int) []int {\n\treturn unsafe.Slice(ptr, len)\n}\n\nfunc SliceUint16(ptr *byte, len uint16) []byte {\n\treturn unsafe.Slice(ptr, len)\n}\n\nfunc SliceUint64(ptr *int, len uint64) []int {\n\treturn unsafe.Slice(ptr, len)\n}\n\nfunc SliceInt64(ptr *int, len int64) []int {\n\treturn unsafe.Slice(ptr, len)\n}\n"
  },
  {
    "path": "compiler/testdata/slice.ll",
    "content": "; ModuleID = 'slice.go'\nsource_filename = \"slice.go\"\ntarget datalayout = \"e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20\"\ntarget triple = \"wasm32-unknown-wasi\"\n\n; Function Attrs: allockind(\"alloc,zeroed\") allocsize(0)\ndeclare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0\n\ndeclare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden void @main.init(ptr %context) unnamed_addr #2 {\nentry:\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden i32 @main.sliceLen(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %context) unnamed_addr #2 {\nentry:\n  ret i32 %ints.len\n}\n\n; Function Attrs: nounwind\ndefine hidden i32 @main.sliceCap(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %context) unnamed_addr #2 {\nentry:\n  ret i32 %ints.cap\n}\n\n; Function Attrs: nounwind\ndefine hidden i32 @main.sliceElement(ptr %ints.data, i32 %ints.len, i32 %ints.cap, i32 %index, ptr %context) unnamed_addr #2 {\nentry:\n  %.not = icmp ult i32 %index, %ints.len\n  br i1 %.not, label %lookup.next, label %lookup.throw\n\nlookup.next:                                      ; preds = %entry\n  %0 = getelementptr inbounds i32, ptr %ints.data, i32 %index\n  %1 = load i32, ptr %0, align 4\n  ret i32 %1\n\nlookup.throw:                                     ; preds = %entry\n  call void @runtime.lookupPanic(ptr undef) #3\n  unreachable\n}\n\ndeclare void @runtime.lookupPanic(ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden { ptr, i32, i32 } @main.sliceAppendValues(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  %varargs = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3\n  call void @runtime.trackPointer(ptr nonnull %varargs, ptr nonnull %stackalloc, ptr undef) #3\n  store i32 1, ptr %varargs, align 4\n  %0 = getelementptr inbounds nuw i8, ptr %varargs, i32 4\n  store i32 2, ptr %0, align 4\n  %1 = getelementptr inbounds nuw i8, ptr %varargs, i32 8\n  store i32 3, ptr %1, align 4\n  %append.new = call { ptr, i32, i32 } @runtime.sliceAppend(ptr %ints.data, ptr nonnull %varargs, i32 %ints.len, i32 %ints.cap, i32 3, i32 4, ptr undef) #3\n  %append.newPtr = extractvalue { ptr, i32, i32 } %append.new, 0\n  %append.newLen = extractvalue { ptr, i32, i32 } %append.new, 1\n  %append.newCap = extractvalue { ptr, i32, i32 } %append.new, 2\n  %2 = insertvalue { ptr, i32, i32 } undef, ptr %append.newPtr, 0\n  %3 = insertvalue { ptr, i32, i32 } %2, i32 %append.newLen, 1\n  %4 = insertvalue { ptr, i32, i32 } %3, i32 %append.newCap, 2\n  call void @runtime.trackPointer(ptr %append.newPtr, ptr nonnull %stackalloc, ptr undef) #3\n  ret { ptr, i32, i32 } %4\n}\n\ndeclare { ptr, i32, i32 } @runtime.sliceAppend(ptr, ptr nocapture readonly, i32, i32, i32, i32, ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden { ptr, i32, i32 } @main.sliceAppendSlice(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %added.data, i32 %added.len, i32 %added.cap, ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  %append.new = call { ptr, i32, i32 } @runtime.sliceAppend(ptr %ints.data, ptr %added.data, i32 %ints.len, i32 %ints.cap, i32 %added.len, i32 4, ptr undef) #3\n  %append.newPtr = extractvalue { ptr, i32, i32 } %append.new, 0\n  %append.newLen = extractvalue { ptr, i32, i32 } %append.new, 1\n  %append.newCap = extractvalue { ptr, i32, i32 } %append.new, 2\n  %0 = insertvalue { ptr, i32, i32 } undef, ptr %append.newPtr, 0\n  %1 = insertvalue { ptr, i32, i32 } %0, i32 %append.newLen, 1\n  %2 = insertvalue { ptr, i32, i32 } %1, i32 %append.newCap, 2\n  call void @runtime.trackPointer(ptr %append.newPtr, ptr nonnull %stackalloc, ptr undef) #3\n  ret { ptr, i32, i32 } %2\n}\n\n; Function Attrs: nounwind\ndefine hidden i32 @main.sliceCopy(ptr %dst.data, i32 %dst.len, i32 %dst.cap, ptr %src.data, i32 %src.len, i32 %src.cap, ptr %context) unnamed_addr #2 {\nentry:\n  %copy.n = call i32 @runtime.sliceCopy(ptr %dst.data, ptr %src.data, i32 %dst.len, i32 %src.len, i32 4, ptr undef) #3\n  ret i32 %copy.n\n}\n\ndeclare i32 @runtime.sliceCopy(ptr nocapture writeonly, ptr nocapture readonly, i32, i32, i32, ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden { ptr, i32, i32 } @main.makeByteSlice(i32 %len, ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  %slice.maxcap = icmp slt i32 %len, 0\n  br i1 %slice.maxcap, label %slice.throw, label %slice.next\n\nslice.next:                                       ; preds = %entry\n  %makeslice.buf = call align 1 ptr @runtime.alloc(i32 %len, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3\n  %0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0\n  %1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1\n  %2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2\n  call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef) #3\n  ret { ptr, i32, i32 } %2\n\nslice.throw:                                      ; preds = %entry\n  call void @runtime.slicePanic(ptr undef) #3\n  unreachable\n}\n\ndeclare void @runtime.slicePanic(ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden { ptr, i32, i32 } @main.makeInt16Slice(i32 %len, ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  %slice.maxcap = icmp slt i32 %len, 0\n  br i1 %slice.maxcap, label %slice.throw, label %slice.next\n\nslice.next:                                       ; preds = %entry\n  %makeslice.cap = shl nuw i32 %len, 1\n  %makeslice.buf = call align 2 ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3\n  %0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0\n  %1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1\n  %2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2\n  call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef) #3\n  ret { ptr, i32, i32 } %2\n\nslice.throw:                                      ; preds = %entry\n  call void @runtime.slicePanic(ptr undef) #3\n  unreachable\n}\n\n; Function Attrs: nounwind\ndefine hidden { ptr, i32, i32 } @main.makeArraySlice(i32 %len, ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  %slice.maxcap = icmp ugt i32 %len, 1431655765\n  br i1 %slice.maxcap, label %slice.throw, label %slice.next\n\nslice.next:                                       ; preds = %entry\n  %makeslice.cap = mul i32 %len, 3\n  %makeslice.buf = call align 1 ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3\n  %0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0\n  %1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1\n  %2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2\n  call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef) #3\n  ret { ptr, i32, i32 } %2\n\nslice.throw:                                      ; preds = %entry\n  call void @runtime.slicePanic(ptr undef) #3\n  unreachable\n}\n\n; Function Attrs: nounwind\ndefine hidden { ptr, i32, i32 } @main.makeInt32Slice(i32 %len, ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  %slice.maxcap = icmp ugt i32 %len, 1073741823\n  br i1 %slice.maxcap, label %slice.throw, label %slice.next\n\nslice.next:                                       ; preds = %entry\n  %makeslice.cap = shl nuw i32 %len, 2\n  %makeslice.buf = call align 4 ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3\n  %0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0\n  %1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1\n  %2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2\n  call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef) #3\n  ret { ptr, i32, i32 } %2\n\nslice.throw:                                      ; preds = %entry\n  call void @runtime.slicePanic(ptr undef) #3\n  unreachable\n}\n\n; Function Attrs: nounwind\ndefine hidden ptr @main.Add32(ptr %p, i32 %len, ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  %0 = getelementptr i8, ptr %p, i32 %len\n  call void @runtime.trackPointer(ptr %0, ptr nonnull %stackalloc, ptr undef) #3\n  ret ptr %0\n}\n\n; Function Attrs: nounwind\ndefine hidden ptr @main.Add64(ptr %p, i64 %len, ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  %0 = trunc i64 %len to i32\n  %1 = getelementptr i8, ptr %p, i32 %0\n  call void @runtime.trackPointer(ptr %1, ptr nonnull %stackalloc, ptr undef) #3\n  ret ptr %1\n}\n\n; Function Attrs: nounwind\ndefine hidden ptr @main.SliceToArray(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = icmp ult i32 %s.len, 4\n  br i1 %0, label %slicetoarray.throw, label %slicetoarray.next\n\nslicetoarray.next:                                ; preds = %entry\n  ret ptr %s.data\n\nslicetoarray.throw:                               ; preds = %entry\n  call void @runtime.sliceToArrayPointerPanic(ptr undef) #3\n  unreachable\n}\n\ndeclare void @runtime.sliceToArrayPointerPanic(ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden ptr @main.SliceToArrayConst(ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  %makeslice = call align 4 dereferenceable(24) ptr @runtime.alloc(i32 24, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3\n  call void @runtime.trackPointer(ptr nonnull %makeslice, ptr nonnull %stackalloc, ptr undef) #3\n  br i1 false, label %slicetoarray.throw, label %slicetoarray.next\n\nslicetoarray.next:                                ; preds = %entry\n  ret ptr %makeslice\n\nslicetoarray.throw:                               ; preds = %entry\n  unreachable\n}\n\n; Function Attrs: nounwind\ndefine hidden { ptr, i32, i32 } @main.SliceInt(ptr dereferenceable_or_null(4) %ptr, i32 %len, ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  %0 = icmp ugt i32 %len, 1073741823\n  %1 = icmp eq ptr %ptr, null\n  %2 = icmp ne i32 %len, 0\n  %3 = and i1 %1, %2\n  %4 = or i1 %3, %0\n  br i1 %4, label %unsafe.Slice.throw, label %unsafe.Slice.next\n\nunsafe.Slice.next:                                ; preds = %entry\n  %5 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0\n  %6 = insertvalue { ptr, i32, i32 } %5, i32 %len, 1\n  %7 = insertvalue { ptr, i32, i32 } %6, i32 %len, 2\n  call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef) #3\n  ret { ptr, i32, i32 } %7\n\nunsafe.Slice.throw:                               ; preds = %entry\n  call void @runtime.unsafeSlicePanic(ptr undef) #3\n  unreachable\n}\n\ndeclare void @runtime.unsafeSlicePanic(ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden { ptr, i32, i32 } @main.SliceUint16(ptr dereferenceable_or_null(1) %ptr, i16 %len, ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  %0 = icmp eq ptr %ptr, null\n  %1 = icmp ne i16 %len, 0\n  %2 = and i1 %0, %1\n  br i1 %2, label %unsafe.Slice.throw, label %unsafe.Slice.next\n\nunsafe.Slice.next:                                ; preds = %entry\n  %3 = zext i16 %len to i32\n  %4 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0\n  %5 = insertvalue { ptr, i32, i32 } %4, i32 %3, 1\n  %6 = insertvalue { ptr, i32, i32 } %5, i32 %3, 2\n  call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef) #3\n  ret { ptr, i32, i32 } %6\n\nunsafe.Slice.throw:                               ; preds = %entry\n  call void @runtime.unsafeSlicePanic(ptr undef) #3\n  unreachable\n}\n\n; Function Attrs: nounwind\ndefine hidden { ptr, i32, i32 } @main.SliceUint64(ptr dereferenceable_or_null(4) %ptr, i64 %len, ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  %0 = icmp ugt i64 %len, 1073741823\n  %1 = icmp eq ptr %ptr, null\n  %2 = icmp ne i64 %len, 0\n  %3 = and i1 %1, %2\n  %4 = or i1 %3, %0\n  br i1 %4, label %unsafe.Slice.throw, label %unsafe.Slice.next\n\nunsafe.Slice.next:                                ; preds = %entry\n  %5 = trunc nuw i64 %len to i32\n  %6 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0\n  %7 = insertvalue { ptr, i32, i32 } %6, i32 %5, 1\n  %8 = insertvalue { ptr, i32, i32 } %7, i32 %5, 2\n  call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef) #3\n  ret { ptr, i32, i32 } %8\n\nunsafe.Slice.throw:                               ; preds = %entry\n  call void @runtime.unsafeSlicePanic(ptr undef) #3\n  unreachable\n}\n\n; Function Attrs: nounwind\ndefine hidden { ptr, i32, i32 } @main.SliceInt64(ptr dereferenceable_or_null(4) %ptr, i64 %len, ptr %context) unnamed_addr #2 {\nentry:\n  %stackalloc = alloca i8, align 1\n  %0 = icmp ugt i64 %len, 1073741823\n  %1 = icmp eq ptr %ptr, null\n  %2 = icmp ne i64 %len, 0\n  %3 = and i1 %1, %2\n  %4 = or i1 %3, %0\n  br i1 %4, label %unsafe.Slice.throw, label %unsafe.Slice.next\n\nunsafe.Slice.next:                                ; preds = %entry\n  %5 = trunc nuw i64 %len to i32\n  %6 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0\n  %7 = insertvalue { ptr, i32, i32 } %6, i32 %5, 1\n  %8 = insertvalue { ptr, i32, i32 } %7, i32 %5, 2\n  call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef) #3\n  ret { ptr, i32, i32 } %8\n\nunsafe.Slice.throw:                               ; preds = %entry\n  call void @runtime.unsafeSlicePanic(ptr undef) #3\n  unreachable\n}\n\nattributes #0 = { allockind(\"alloc,zeroed\") allocsize(0) \"alloc-family\"=\"runtime.alloc\" \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #1 = { \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #2 = { nounwind \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #3 = { nounwind }\n"
  },
  {
    "path": "compiler/testdata/string.go",
    "content": "package main\n\nfunc someString() string {\n\treturn \"foo\"\n}\n\nfunc zeroLengthString() string {\n\treturn \"\"\n}\n\nfunc stringLen(s string) int {\n\treturn len(s)\n}\n\nfunc stringIndex(s string, index int) byte {\n\treturn s[index]\n}\n\nfunc stringCompareEqual(s1, s2 string) bool {\n\treturn s1 == s2\n}\n\nfunc stringCompareUnequal(s1, s2 string) bool {\n\treturn s1 != s2\n}\n\nfunc stringCompareLarger(s1, s2 string) bool {\n\treturn s1 > s2\n}\n\nfunc stringLookup(s string, x uint8) byte {\n\t// Test that x is correctly extended to an uint before comparison.\n\treturn s[x]\n}\n"
  },
  {
    "path": "compiler/testdata/string.ll",
    "content": "; ModuleID = 'string.go'\nsource_filename = \"string.go\"\ntarget datalayout = \"e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20\"\ntarget triple = \"wasm32-unknown-wasi\"\n\n%runtime._string = type { ptr, i32 }\n\n@\"main$string\" = internal unnamed_addr constant [3 x i8] c\"foo\", align 1\n\n; Function Attrs: allockind(\"alloc,zeroed\") allocsize(0)\ndeclare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0\n\ndeclare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden void @main.init(ptr %context) unnamed_addr #2 {\nentry:\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden %runtime._string @main.someString(ptr %context) unnamed_addr #2 {\nentry:\n  ret %runtime._string { ptr @\"main$string\", i32 3 }\n}\n\n; Function Attrs: nounwind\ndefine hidden %runtime._string @main.zeroLengthString(ptr %context) unnamed_addr #2 {\nentry:\n  ret %runtime._string zeroinitializer\n}\n\n; Function Attrs: nounwind\ndefine hidden i32 @main.stringLen(ptr readonly %s.data, i32 %s.len, ptr %context) unnamed_addr #2 {\nentry:\n  ret i32 %s.len\n}\n\n; Function Attrs: nounwind\ndefine hidden i8 @main.stringIndex(ptr readonly %s.data, i32 %s.len, i32 %index, ptr %context) unnamed_addr #2 {\nentry:\n  %.not = icmp ult i32 %index, %s.len\n  br i1 %.not, label %lookup.next, label %lookup.throw\n\nlookup.next:                                      ; preds = %entry\n  %0 = getelementptr inbounds i8, ptr %s.data, i32 %index\n  %1 = load i8, ptr %0, align 1\n  ret i8 %1\n\nlookup.throw:                                     ; preds = %entry\n  call void @runtime.lookupPanic(ptr undef) #3\n  unreachable\n}\n\ndeclare void @runtime.lookupPanic(ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden i1 @main.stringCompareEqual(ptr readonly %s1.data, i32 %s1.len, ptr readonly %s2.data, i32 %s2.len, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = call i1 @runtime.stringEqual(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr undef) #3\n  ret i1 %0\n}\n\ndeclare i1 @runtime.stringEqual(ptr readonly, i32, ptr readonly, i32, ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden i1 @main.stringCompareUnequal(ptr readonly %s1.data, i32 %s1.len, ptr readonly %s2.data, i32 %s2.len, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = call i1 @runtime.stringEqual(ptr %s1.data, i32 %s1.len, ptr %s2.data, i32 %s2.len, ptr undef) #3\n  %1 = xor i1 %0, true\n  ret i1 %1\n}\n\n; Function Attrs: nounwind\ndefine hidden i1 @main.stringCompareLarger(ptr readonly %s1.data, i32 %s1.len, ptr readonly %s2.data, i32 %s2.len, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = call i1 @runtime.stringLess(ptr %s2.data, i32 %s2.len, ptr %s1.data, i32 %s1.len, ptr undef) #3\n  ret i1 %0\n}\n\ndeclare i1 @runtime.stringLess(ptr readonly, i32, ptr readonly, i32, ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden i8 @main.stringLookup(ptr readonly %s.data, i32 %s.len, i8 %x, ptr %context) unnamed_addr #2 {\nentry:\n  %0 = zext i8 %x to i32\n  %.not = icmp ugt i32 %s.len, %0\n  br i1 %.not, label %lookup.next, label %lookup.throw\n\nlookup.next:                                      ; preds = %entry\n  %1 = getelementptr inbounds nuw i8, ptr %s.data, i32 %0\n  %2 = load i8, ptr %1, align 1\n  ret i8 %2\n\nlookup.throw:                                     ; preds = %entry\n  call void @runtime.lookupPanic(ptr undef) #3\n  unreachable\n}\n\nattributes #0 = { allockind(\"alloc,zeroed\") allocsize(0) \"alloc-family\"=\"runtime.alloc\" \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #1 = { \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #2 = { nounwind \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #3 = { nounwind }\n"
  },
  {
    "path": "compiler/testdata/zeromap.go",
    "content": "package main\n\ntype hasPadding struct {\n\tb1 bool\n\ti  int\n\tb2 bool\n}\n\ntype nestedPadding struct {\n\tb bool\n\thasPadding\n\ti int\n}\n\n//go:noinline\nfunc testZeroGet(m map[hasPadding]int, s hasPadding) int {\n\treturn m[s]\n}\n\n//go:noinline\nfunc testZeroSet(m map[hasPadding]int, s hasPadding) {\n\tm[s] = 5\n}\n\n//go:noinline\nfunc testZeroArrayGet(m map[[2]hasPadding]int, s [2]hasPadding) int {\n\treturn m[s]\n}\n\n//go:noinline\nfunc testZeroArraySet(m map[[2]hasPadding]int, s [2]hasPadding) {\n\tm[s] = 5\n}\n\nfunc main() {\n\n}\n"
  },
  {
    "path": "compiler/testdata/zeromap.ll",
    "content": "; ModuleID = 'zeromap.go'\nsource_filename = \"zeromap.go\"\ntarget datalayout = \"e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20\"\ntarget triple = \"wasm32-unknown-wasi\"\n\n%main.hasPadding = type { i1, i32, i1 }\n\n; Function Attrs: allockind(\"alloc,zeroed\") allocsize(0)\ndeclare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0\n\ndeclare void @runtime.trackPointer(ptr nocapture readonly, ptr, ptr) #1\n\n; Function Attrs: nounwind\ndefine hidden void @main.init(ptr %context) unnamed_addr #2 {\nentry:\n  ret void\n}\n\n; Function Attrs: noinline nounwind\ndefine hidden i32 @main.testZeroGet(ptr dereferenceable_or_null(40) %m, i1 %s.b1, i32 %s.i, i1 %s.b2, ptr %context) unnamed_addr #3 {\nentry:\n  %hashmap.key = alloca %main.hasPadding, align 8\n  %hashmap.value = alloca i32, align 4\n  %0 = insertvalue %main.hasPadding zeroinitializer, i1 %s.b1, 0\n  %1 = insertvalue %main.hasPadding %0, i32 %s.i, 1\n  %2 = insertvalue %main.hasPadding %1, i1 %s.b2, 2\n  call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %hashmap.value)\n  call void @llvm.lifetime.start.p0(i64 12, ptr nonnull %hashmap.key)\n  store %main.hasPadding %2, ptr %hashmap.key, align 4\n  %3 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 1\n  call void @runtime.memzero(ptr nonnull %3, i32 3, ptr undef) #5\n  %4 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 9\n  call void @runtime.memzero(ptr nonnull %4, i32 3, ptr undef) #5\n  %5 = call i1 @runtime.hashmapBinaryGet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, i32 4, ptr undef) #5\n  call void @llvm.lifetime.end.p0(i64 12, ptr nonnull %hashmap.key)\n  %6 = load i32, ptr %hashmap.value, align 4\n  call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %hashmap.value)\n  ret i32 %6\n}\n\n; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)\ndeclare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #4\n\ndeclare void @runtime.memzero(ptr, i32, ptr) #1\n\ndeclare i1 @runtime.hashmapBinaryGet(ptr dereferenceable_or_null(40), ptr, ptr, i32, ptr) #1\n\n; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)\ndeclare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #4\n\n; Function Attrs: noinline nounwind\ndefine hidden void @main.testZeroSet(ptr dereferenceable_or_null(40) %m, i1 %s.b1, i32 %s.i, i1 %s.b2, ptr %context) unnamed_addr #3 {\nentry:\n  %hashmap.key = alloca %main.hasPadding, align 8\n  %hashmap.value = alloca i32, align 4\n  %0 = insertvalue %main.hasPadding zeroinitializer, i1 %s.b1, 0\n  %1 = insertvalue %main.hasPadding %0, i32 %s.i, 1\n  %2 = insertvalue %main.hasPadding %1, i1 %s.b2, 2\n  call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %hashmap.value)\n  store i32 5, ptr %hashmap.value, align 4\n  call void @llvm.lifetime.start.p0(i64 12, ptr nonnull %hashmap.key)\n  store %main.hasPadding %2, ptr %hashmap.key, align 4\n  %3 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 1\n  call void @runtime.memzero(ptr nonnull %3, i32 3, ptr undef) #5\n  %4 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 9\n  call void @runtime.memzero(ptr nonnull %4, i32 3, ptr undef) #5\n  call void @runtime.hashmapBinarySet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, ptr undef) #5\n  call void @llvm.lifetime.end.p0(i64 12, ptr nonnull %hashmap.key)\n  call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %hashmap.value)\n  ret void\n}\n\ndeclare void @runtime.hashmapBinarySet(ptr dereferenceable_or_null(40), ptr, ptr, ptr) #1\n\n; Function Attrs: noinline nounwind\ndefine hidden i32 @main.testZeroArrayGet(ptr dereferenceable_or_null(40) %m, [2 x %main.hasPadding] %s, ptr %context) unnamed_addr #3 {\nentry:\n  %hashmap.key = alloca [2 x %main.hasPadding], align 8\n  %hashmap.value = alloca i32, align 4\n  call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %hashmap.value)\n  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %hashmap.key)\n  %s.elt = extractvalue [2 x %main.hasPadding] %s, 0\n  store %main.hasPadding %s.elt, ptr %hashmap.key, align 4\n  %hashmap.key.repack1 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 12\n  %s.elt2 = extractvalue [2 x %main.hasPadding] %s, 1\n  store %main.hasPadding %s.elt2, ptr %hashmap.key.repack1, align 4\n  %0 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 1\n  call void @runtime.memzero(ptr nonnull %0, i32 3, ptr undef) #5\n  %1 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 9\n  call void @runtime.memzero(ptr nonnull %1, i32 3, ptr undef) #5\n  %2 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 13\n  call void @runtime.memzero(ptr nonnull %2, i32 3, ptr undef) #5\n  %3 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 21\n  call void @runtime.memzero(ptr nonnull %3, i32 3, ptr undef) #5\n  %4 = call i1 @runtime.hashmapBinaryGet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, i32 4, ptr undef) #5\n  call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %hashmap.key)\n  %5 = load i32, ptr %hashmap.value, align 4\n  call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %hashmap.value)\n  ret i32 %5\n}\n\n; Function Attrs: noinline nounwind\ndefine hidden void @main.testZeroArraySet(ptr dereferenceable_or_null(40) %m, [2 x %main.hasPadding] %s, ptr %context) unnamed_addr #3 {\nentry:\n  %hashmap.key = alloca [2 x %main.hasPadding], align 8\n  %hashmap.value = alloca i32, align 4\n  call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %hashmap.value)\n  store i32 5, ptr %hashmap.value, align 4\n  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %hashmap.key)\n  %s.elt = extractvalue [2 x %main.hasPadding] %s, 0\n  store %main.hasPadding %s.elt, ptr %hashmap.key, align 4\n  %hashmap.key.repack1 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 12\n  %s.elt2 = extractvalue [2 x %main.hasPadding] %s, 1\n  store %main.hasPadding %s.elt2, ptr %hashmap.key.repack1, align 4\n  %0 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 1\n  call void @runtime.memzero(ptr nonnull %0, i32 3, ptr undef) #5\n  %1 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 9\n  call void @runtime.memzero(ptr nonnull %1, i32 3, ptr undef) #5\n  %2 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 13\n  call void @runtime.memzero(ptr nonnull %2, i32 3, ptr undef) #5\n  %3 = getelementptr inbounds nuw i8, ptr %hashmap.key, i32 21\n  call void @runtime.memzero(ptr nonnull %3, i32 3, ptr undef) #5\n  call void @runtime.hashmapBinarySet(ptr %m, ptr nonnull %hashmap.key, ptr nonnull %hashmap.value, ptr undef) #5\n  call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %hashmap.key)\n  call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %hashmap.value)\n  ret void\n}\n\n; Function Attrs: nounwind\ndefine hidden void @main.main(ptr %context) unnamed_addr #2 {\nentry:\n  ret void\n}\n\nattributes #0 = { allockind(\"alloc,zeroed\") allocsize(0) \"alloc-family\"=\"runtime.alloc\" \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #1 = { \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #2 = { nounwind \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #3 = { noinline nounwind \"target-features\"=\"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\" }\nattributes #4 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }\nattributes #5 = { nounwind }\n"
  },
  {
    "path": "compiler/volatile.go",
    "content": "package compiler\n\nimport \"go/types\"\n\n// This file implements volatile loads/stores in runtime/volatile.LoadT and\n// runtime/volatile.StoreT as compiler builtins.\n\n// createVolatileLoad is the implementation of the intrinsic function\n// runtime/volatile.LoadT().\nfunc (b *builder) createVolatileLoad() {\n\tb.createFunctionStart(true)\n\taddr := b.getValue(b.fn.Params[0], getPos(b.fn))\n\tb.createNilCheck(b.fn.Params[0], addr, \"deref\")\n\tvalType := b.getLLVMType(b.fn.Params[0].Type().(*types.Pointer).Elem())\n\tval := b.CreateLoad(valType, addr, \"\")\n\tval.SetVolatile(true)\n\tb.CreateRet(val)\n}\n\n// createVolatileStore is the implementation of the intrinsic function\n// runtime/volatile.StoreT().\nfunc (b *builder) createVolatileStore() {\n\tb.createFunctionStart(true)\n\taddr := b.getValue(b.fn.Params[0], getPos(b.fn))\n\tval := b.getValue(b.fn.Params[1], getPos(b.fn))\n\tb.createNilCheck(b.fn.Params[0], addr, \"deref\")\n\tstore := b.CreateStore(val, addr)\n\tstore.SetVolatile(true)\n\tb.CreateRetVoid()\n}\n"
  },
  {
    "path": "corpus_test.go",
    "content": "package main\n\nimport (\n\t\"flag\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strings\"\n\t\"sync\"\n\t\"testing\"\n\n\t\"golang.org/x/tools/go/buildutil\"\n\tyaml \"gopkg.in/yaml.v2\"\n)\n\n/*\nThis contains code from https://github.com/dgryski/tinygo-test-corpus\n\nThe MIT License (MIT)\n\nCopyright (c) 2020 Damian Gryski <damian@gryski.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\nvar corpus = flag.String(\"corpus\", \"\", \"path to test corpus\")\n\nfunc TestCorpus(t *testing.T) {\n\tt.Parallel()\n\tif *corpus == \"\" {\n\t\tt.Skip()\n\t}\n\n\tvar target string\n\tif *testTarget != \"\" {\n\t\ttarget = *testTarget\n\t}\n\tisWASI := strings.HasPrefix(target, \"wasi\")\n\n\trepos, err := loadRepos(*corpus)\n\tif err != nil {\n\t\tt.Fatalf(\"loading corpus: %v\", err)\n\t}\n\n\tfor _, repo := range repos {\n\t\trepo := repo\n\t\tname := repo.Repo\n\t\tif repo.Tags != \"\" {\n\t\t\tname += \"(\" + strings.ReplaceAll(repo.Tags, \" \", \"-\") + \")\"\n\t\t}\n\t\tif repo.Version != \"\" {\n\t\t\tname += \"@\" + repo.Version\n\t\t}\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tif isWASI && repo.SkipWASI {\n\t\t\t\tt.Skip(\"skip wasi\")\n\t\t\t}\n\t\t\tif repo.Slow && testing.Short() {\n\t\t\t\tt.Skip(\"slow test\")\n\t\t\t}\n\n\t\t\tvar wg sync.WaitGroup\n\t\t\tdefer wg.Wait()\n\t\t\tout := ioLogger(t, &wg)\n\t\t\tdefer out.Close()\n\n\t\t\tdir := t.TempDir()\n\t\t\tcmd := exec.Command(\"go\", \"mod\", \"init\", \"github.com/tinygo/tinygo-corpus-test\")\n\t\t\tcmd.Dir = dir\n\t\t\tcmd.Stdout, cmd.Stderr = out, out\n\t\t\terr := cmd.Run()\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"failed to init: %s\", err.Error())\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tvar ver string\n\t\t\tif repo.Version != \"\" {\n\t\t\t\tver = \"@\" + repo.Version\n\t\t\t}\n\t\t\tcmd = exec.Command(\"go\", \"get\", \"-t\", \"-d\", repo.Repo+\"/...\"+ver)\n\t\t\tcmd.Dir = dir\n\t\t\tcmd.Stdout, cmd.Stderr = out, out\n\t\t\terr = cmd.Run()\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"failed to get: %s\", err.Error())\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tdoTest := func(t *testing.T, path string) {\n\t\t\t\tvar wg sync.WaitGroup\n\t\t\t\tdefer wg.Wait()\n\t\t\t\tout := ioLogger(t, &wg)\n\t\t\t\tdefer out.Close()\n\n\t\t\t\topts := optionsFromTarget(target, sema)\n\t\t\t\topts.Directory = dir\n\t\t\t\tvar tags buildutil.TagsFlag\n\t\t\t\ttags.Set(repo.Tags)\n\t\t\t\topts.Tags = []string(tags)\n\t\t\t\topts.TestConfig.Verbose = testing.Verbose()\n\n\t\t\t\tpassed, err := Test(path, out, out, &opts, \"\")\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Errorf(\"test error: %v\", err)\n\t\t\t\t}\n\t\t\t\tif !passed {\n\t\t\t\t\tt.Error(\"test failed\")\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(repo.Subdirs) == 0 {\n\t\t\t\tdoTest(t, repo.Repo)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tfor _, dir := range repo.Subdirs {\n\t\t\t\tdir := dir\n\t\t\t\tt.Run(dir.Pkg, func(t *testing.T) {\n\t\t\t\t\tt.Parallel()\n\n\t\t\t\t\tif isWASI && dir.SkipWASI {\n\t\t\t\t\t\tt.Skip(\"skip wasi\")\n\t\t\t\t\t}\n\t\t\t\t\tif dir.Slow && testing.Short() {\n\t\t\t\t\t\tt.Skip(\"slow test\")\n\t\t\t\t\t}\n\n\t\t\t\t\tdoTest(t, repo.Repo+\"/\"+dir.Pkg)\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\t}\n}\n\ntype T struct {\n\tRepo     string\n\tTags     string\n\tSubdirs  []Subdir\n\tSkipWASI bool\n\tSlow     bool\n\tVersion  string\n}\n\ntype Subdir struct {\n\tPkg      string\n\tSkipWASI bool\n\tSlow     bool\n}\n\nfunc loadRepos(f string) ([]T, error) {\n\n\tyf, err := os.ReadFile(f)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar repos []T\n\terr = yaml.Unmarshal(yf, &repos)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn repos, nil\n}\n"
  },
  {
    "path": "diagnostics/diagnostics.go",
    "content": "// Package diagnostics formats compiler errors and prints them in a consistent\n// way.\npackage diagnostics\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"go/scanner\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"io\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"github.com/tinygo-org/tinygo/builder\"\n\t\"github.com/tinygo-org/tinygo/goenv\"\n\t\"github.com/tinygo-org/tinygo/interp\"\n\t\"github.com/tinygo-org/tinygo/loader\"\n)\n\n// A single diagnostic.\ntype Diagnostic struct {\n\tPos token.Position\n\tMsg string\n\n\t// Start and end position, if available. For many errors these positions are\n\t// not available, but for some they are.\n\tStartPos token.Position\n\tEndPos   token.Position\n}\n\n// One or multiple errors of a particular package.\n// It can also represent whole-program errors (like linker errors) that can't\n// easily be connected to a single package.\ntype PackageDiagnostic struct {\n\tImportPath  string // the same ImportPath as in `go list -json`\n\tDiagnostics []Diagnostic\n}\n\n// Diagnostics of a whole program. This can include errors belonging to multiple\n// packages, or just a single package.\ntype ProgramDiagnostic []PackageDiagnostic\n\n// CreateDiagnostics reads the underlying errors in the error object and creates\n// a set of diagnostics that's sorted and can be readily printed.\nfunc CreateDiagnostics(err error) ProgramDiagnostic {\n\tif err == nil {\n\t\treturn nil\n\t}\n\t// Right now, the compiler will only show errors for the first package that\n\t// fails to build. This is likely to change in the future.\n\treturn ProgramDiagnostic{\n\t\tcreatePackageDiagnostic(err),\n\t}\n}\n\n// Create diagnostics for a single package (though, in practice, it may also be\n// used for whole-program diagnostics in some cases).\nfunc createPackageDiagnostic(err error) PackageDiagnostic {\n\t// Extract diagnostics for this package.\n\tvar pkgDiag PackageDiagnostic\n\tswitch err := err.(type) {\n\tcase *builder.MultiError:\n\t\tif err.ImportPath != \"\" {\n\t\t\tpkgDiag.ImportPath = err.ImportPath\n\t\t}\n\t\tfor _, err := range err.Errs {\n\t\t\tdiags := createDiagnostics(err)\n\t\t\tpkgDiag.Diagnostics = append(pkgDiag.Diagnostics, diags...)\n\t\t}\n\tcase loader.Errors:\n\t\tif err.Pkg != nil {\n\t\t\tpkgDiag.ImportPath = err.Pkg.ImportPath\n\t\t}\n\t\tfor _, err := range err.Errs {\n\t\t\tdiags := createDiagnostics(err)\n\t\t\tpkgDiag.Diagnostics = append(pkgDiag.Diagnostics, diags...)\n\t\t}\n\tcase *interp.Error:\n\t\tpkgDiag.ImportPath = err.ImportPath\n\t\tw := &bytes.Buffer{}\n\t\tfmt.Fprintln(w, err.Error())\n\t\tif len(err.Inst) != 0 {\n\t\t\tfmt.Fprintln(w, err.Inst)\n\t\t}\n\t\tif len(err.Traceback) > 0 {\n\t\t\tfmt.Fprintln(w, \"\\ntraceback:\")\n\t\t\tfor _, line := range err.Traceback {\n\t\t\t\tfmt.Fprintln(w, line.Pos.String()+\":\")\n\t\t\t\tfmt.Fprintln(w, line.Inst)\n\t\t\t}\n\t\t}\n\t\tpkgDiag.Diagnostics = append(pkgDiag.Diagnostics, Diagnostic{\n\t\t\tMsg: w.String(),\n\t\t})\n\tdefault:\n\t\tpkgDiag.Diagnostics = createDiagnostics(err)\n\t}\n\n\t// Sort these diagnostics by file/line/column.\n\tsort.SliceStable(pkgDiag.Diagnostics, func(i, j int) bool {\n\t\tposI := pkgDiag.Diagnostics[i].Pos\n\t\tposJ := pkgDiag.Diagnostics[j].Pos\n\t\tif posI.Filename != posJ.Filename {\n\t\t\treturn posI.Filename < posJ.Filename\n\t\t}\n\t\tif posI.Line != posJ.Line {\n\t\t\treturn posI.Line < posJ.Line\n\t\t}\n\t\treturn posI.Column < posJ.Column\n\t})\n\n\treturn pkgDiag\n}\n\n// Extract diagnostics from the given error message and return them as a slice\n// of errors (which in many cases will just be a single diagnostic).\nfunc createDiagnostics(err error) []Diagnostic {\n\tswitch err := err.(type) {\n\tcase types.Error:\n\t\tdiag := Diagnostic{\n\t\t\tPos: err.Fset.Position(err.Pos),\n\t\t\tMsg: err.Msg,\n\t\t}\n\t\t// There is a special unexported API since Go 1.16 that provides the\n\t\t// range (start and end position) where the type error exists.\n\t\t// There is no promise of backwards compatibility in future Go versions\n\t\t// so we have to be extra careful here to be resilient.\n\t\tv := reflect.ValueOf(err)\n\t\tstart := v.FieldByName(\"go116start\")\n\t\tend := v.FieldByName(\"go116end\")\n\t\tif start.IsValid() && end.IsValid() && start.Int() != end.Int() {\n\t\t\tdiag.StartPos = err.Fset.Position(token.Pos(start.Int()))\n\t\t\tdiag.EndPos = err.Fset.Position(token.Pos(end.Int()))\n\t\t}\n\t\treturn []Diagnostic{diag}\n\tcase scanner.Error:\n\t\treturn []Diagnostic{\n\t\t\t{\n\t\t\t\tPos: err.Pos,\n\t\t\t\tMsg: err.Msg,\n\t\t\t},\n\t\t}\n\tcase scanner.ErrorList:\n\t\tvar diags []Diagnostic\n\t\tfor _, err := range err {\n\t\t\tdiags = append(diags, createDiagnostics(*err)...)\n\t\t}\n\t\treturn diags\n\tcase loader.Error:\n\t\tif err.Err.Pos.Filename != \"\" {\n\t\t\t// Probably a syntax error in a dependency.\n\t\t\treturn createDiagnostics(err.Err)\n\t\t} else {\n\t\t\t// Probably an \"import cycle not allowed\" error.\n\t\t\tbuf := &bytes.Buffer{}\n\t\t\tfmt.Fprintln(buf, \"package\", err.ImportStack[0])\n\t\t\tfor i := 1; i < len(err.ImportStack); i++ {\n\t\t\t\tpkgPath := err.ImportStack[i]\n\t\t\t\tif i == len(err.ImportStack)-1 {\n\t\t\t\t\t// last package\n\t\t\t\t\tfmt.Fprintln(buf, \"\\timports\", pkgPath+\": \"+err.Err.Error())\n\t\t\t\t} else {\n\t\t\t\t\t// not the last package\n\t\t\t\t\tfmt.Fprintln(buf, \"\\timports\", pkgPath)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn []Diagnostic{\n\t\t\t\t{Msg: buf.String()},\n\t\t\t}\n\t\t}\n\tdefault:\n\t\treturn []Diagnostic{\n\t\t\t{Msg: err.Error()},\n\t\t}\n\t}\n}\n\n// Write program diagnostics to the given writer with 'wd' as the relative\n// working directory.\nfunc (progDiag ProgramDiagnostic) WriteTo(w io.Writer, wd string) {\n\tfor _, pkgDiag := range progDiag {\n\t\tpkgDiag.WriteTo(w, wd)\n\t}\n}\n\n// Write package diagnostics to the given writer with 'wd' as the relative\n// working directory.\nfunc (pkgDiag PackageDiagnostic) WriteTo(w io.Writer, wd string) {\n\tif pkgDiag.ImportPath != \"\" {\n\t\tfmt.Fprintln(w, \"#\", pkgDiag.ImportPath)\n\t}\n\tfor _, diag := range pkgDiag.Diagnostics {\n\t\tdiag.WriteTo(w, wd)\n\t}\n}\n\n// Write this diagnostic to the given writer with 'wd' as the relative working\n// directory.\nfunc (diag Diagnostic) WriteTo(w io.Writer, wd string) {\n\tif diag.Pos == (token.Position{}) {\n\t\tfmt.Fprintln(w, diag.Msg)\n\t\treturn\n\t}\n\tpos := RelativePosition(diag.Pos, wd)\n\tfmt.Fprintf(w, \"%s: %s\\n\", pos, diag.Msg)\n}\n\n// Convert the position in pos (assumed to have an absolute path) into a\n// relative path if possible. Paths inside GOROOT/TINYGOROOT will remain\n// absolute.\nfunc RelativePosition(pos token.Position, wd string) token.Position {\n\t// Check whether we even have a working directory.\n\tif wd == \"\" {\n\t\treturn pos\n\t}\n\n\t// Paths inside GOROOT should be printed in full.\n\tif strings.HasPrefix(pos.Filename, filepath.Join(goenv.Get(\"GOROOT\"), \"src\")) || strings.HasPrefix(pos.Filename, filepath.Join(goenv.Get(\"TINYGOROOT\"), \"src\")) {\n\t\treturn pos\n\t}\n\n\t// Make the path relative, for easier reading. Ignore any errors in the\n\t// process (falling back to the absolute path).\n\trelpath, err := filepath.Rel(wd, pos.Filename)\n\tif err == nil {\n\t\tpos.Filename = relpath\n\t}\n\treturn pos\n}\n"
  },
  {
    "path": "diff.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage main\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"sort\"\n\t\"strings\"\n)\n\n// A pair is a pair of values tracked for both the x and y side of a diff.\n// It is typically a pair of line indexes.\ntype pair struct{ x, y int }\n\n// Diff returns an anchored diff of the two texts old and new\n// in the “unified diff” format. If old and new are identical,\n// Diff returns a nil slice (no output).\n//\n// Unix diff implementations typically look for a diff with\n// the smallest number of lines inserted and removed,\n// which can in the worst case take time quadratic in the\n// number of lines in the texts. As a result, many implementations\n// either can be made to run for a long time or cut off the search\n// after a predetermined amount of work.\n//\n// In contrast, this implementation looks for a diff with the\n// smallest number of “unique” lines inserted and removed,\n// where unique means a line that appears just once in both old and new.\n// We call this an “anchored diff” because the unique lines anchor\n// the chosen matching regions. An anchored diff is usually clearer\n// than a standard diff, because the algorithm does not try to\n// reuse unrelated blank lines or closing braces.\n// The algorithm also guarantees to run in O(n log n) time\n// instead of the standard O(n²) time.\n//\n// Some systems call this approach a “patience diff,” named for\n// the “patience sorting” algorithm, itself named for a solitaire card game.\n// We avoid that name for two reasons. First, the name has been used\n// for a few different variants of the algorithm, so it is imprecise.\n// Second, the name is frequently interpreted as meaning that you have\n// to wait longer (to be patient) for the diff, meaning that it is a slower algorithm,\n// when in fact the algorithm is faster than the standard one.\nfunc Diff(oldName string, old []byte, newName string, new []byte) []byte {\n\tif bytes.Equal(old, new) {\n\t\treturn nil\n\t}\n\tx := lines(old)\n\ty := lines(new)\n\n\t// Print diff header.\n\tvar out bytes.Buffer\n\tfmt.Fprintf(&out, \"diff %s %s\\n\", oldName, newName)\n\tfmt.Fprintf(&out, \"--- %s\\n\", oldName)\n\tfmt.Fprintf(&out, \"+++ %s\\n\", newName)\n\n\t// Loop over matches to consider,\n\t// expanding each match to include surrounding lines,\n\t// and then printing diff chunks.\n\t// To avoid setup/teardown cases outside the loop,\n\t// tgs returns a leading {0,0} and trailing {len(x), len(y)} pair\n\t// in the sequence of matches.\n\tvar (\n\t\tdone  pair     // printed up to x[:done.x] and y[:done.y]\n\t\tchunk pair     // start lines of current chunk\n\t\tcount pair     // number of lines from each side in current chunk\n\t\tctext []string // lines for current chunk\n\t)\n\tfor _, m := range tgs(x, y) {\n\t\tif m.x < done.x {\n\t\t\t// Already handled scanning forward from earlier match.\n\t\t\tcontinue\n\t\t}\n\n\t\t// Expand matching lines as far as possible,\n\t\t// establishing that x[start.x:end.x] == y[start.y:end.y].\n\t\t// Note that on the first (or last) iteration we may (or definitely do)\n\t\t// have an empty match: start.x==end.x and start.y==end.y.\n\t\tstart := m\n\t\tfor start.x > done.x && start.y > done.y && x[start.x-1] == y[start.y-1] {\n\t\t\tstart.x--\n\t\t\tstart.y--\n\t\t}\n\t\tend := m\n\t\tfor end.x < len(x) && end.y < len(y) && x[end.x] == y[end.y] {\n\t\t\tend.x++\n\t\t\tend.y++\n\t\t}\n\n\t\t// Emit the mismatched lines before start into this chunk.\n\t\t// (No effect on first sentinel iteration, when start = {0,0}.)\n\t\tfor _, s := range x[done.x:start.x] {\n\t\t\tctext = append(ctext, \"-\"+s)\n\t\t\tcount.x++\n\t\t}\n\t\tfor _, s := range y[done.y:start.y] {\n\t\t\tctext = append(ctext, \"+\"+s)\n\t\t\tcount.y++\n\t\t}\n\n\t\t// If we're not at EOF and have too few common lines,\n\t\t// the chunk includes all the common lines and continues.\n\t\tconst C = 3 // number of context lines\n\t\tif (end.x < len(x) || end.y < len(y)) &&\n\t\t\t(end.x-start.x < C || (len(ctext) > 0 && end.x-start.x < 2*C)) {\n\t\t\tfor _, s := range x[start.x:end.x] {\n\t\t\t\tctext = append(ctext, \" \"+s)\n\t\t\t\tcount.x++\n\t\t\t\tcount.y++\n\t\t\t}\n\t\t\tdone = end\n\t\t\tcontinue\n\t\t}\n\n\t\t// End chunk with common lines for context.\n\t\tif len(ctext) > 0 {\n\t\t\tn := end.x - start.x\n\t\t\tif n > C {\n\t\t\t\tn = C\n\t\t\t}\n\t\t\tfor _, s := range x[start.x : start.x+n] {\n\t\t\t\tctext = append(ctext, \" \"+s)\n\t\t\t\tcount.x++\n\t\t\t\tcount.y++\n\t\t\t}\n\t\t\tdone = pair{start.x + n, start.y + n}\n\n\t\t\t// Format and emit chunk.\n\t\t\t// Convert line numbers to 1-indexed.\n\t\t\t// Special case: empty file shows up as 0,0 not 1,0.\n\t\t\tif count.x > 0 {\n\t\t\t\tchunk.x++\n\t\t\t}\n\t\t\tif count.y > 0 {\n\t\t\t\tchunk.y++\n\t\t\t}\n\t\t\tfmt.Fprintf(&out, \"@@ -%d,%d +%d,%d @@\\n\", chunk.x, count.x, chunk.y, count.y)\n\t\t\tfor _, s := range ctext {\n\t\t\t\tout.WriteString(s)\n\t\t\t}\n\t\t\tcount.x = 0\n\t\t\tcount.y = 0\n\t\t\tctext = ctext[:0]\n\t\t}\n\n\t\t// If we reached EOF, we're done.\n\t\tif end.x >= len(x) && end.y >= len(y) {\n\t\t\tbreak\n\t\t}\n\n\t\t// Otherwise start a new chunk.\n\t\tchunk = pair{end.x - C, end.y - C}\n\t\tfor _, s := range x[chunk.x:end.x] {\n\t\t\tctext = append(ctext, \" \"+s)\n\t\t\tcount.x++\n\t\t\tcount.y++\n\t\t}\n\t\tdone = end\n\t}\n\n\treturn out.Bytes()\n}\n\n// lines returns the lines in the file x, including newlines.\n// If the file does not end in a newline, one is supplied\n// along with a warning about the missing newline.\nfunc lines(x []byte) []string {\n\tl := strings.SplitAfter(string(x), \"\\n\")\n\tif l[len(l)-1] == \"\" {\n\t\tl = l[:len(l)-1]\n\t} else {\n\t\t// Treat last line as having a message about the missing newline attached,\n\t\t// using the same text as BSD/GNU diff (including the leading backslash).\n\t\tl[len(l)-1] += \"\\n\\\\ No newline at end of file\\n\"\n\t}\n\treturn l\n}\n\n// tgs returns the pairs of indexes of the longest common subsequence\n// of unique lines in x and y, where a unique line is one that appears\n// once in x and once in y.\n//\n// The longest common subsequence algorithm is as described in\n// Thomas G. Szymanski, “A Special Case of the Maximal Common\n// Subsequence Problem,” Princeton TR #170 (January 1975),\n// available at https://research.swtch.com/tgs170.pdf.\nfunc tgs(x, y []string) []pair {\n\t// Count the number of times each string appears in a and b.\n\t// We only care about 0, 1, many, counted as 0, -1, -2\n\t// for the x side and 0, -4, -8 for the y side.\n\t// Using negative numbers now lets us distinguish positive line numbers later.\n\tm := make(map[string]int)\n\tfor _, s := range x {\n\t\tif c := m[s]; c > -2 {\n\t\t\tm[s] = c - 1\n\t\t}\n\t}\n\tfor _, s := range y {\n\t\tif c := m[s]; c > -8 {\n\t\t\tm[s] = c - 4\n\t\t}\n\t}\n\n\t// Now unique strings can be identified by m[s] = -1+-4.\n\t//\n\t// Gather the indexes of those strings in x and y, building:\n\t//\txi[i] = increasing indexes of unique strings in x.\n\t//\tyi[i] = increasing indexes of unique strings in y.\n\t//\tinv[i] = index j such that x[xi[i]] = y[yi[j]].\n\tvar xi, yi, inv []int\n\tfor i, s := range y {\n\t\tif m[s] == -1+-4 {\n\t\t\tm[s] = len(yi)\n\t\t\tyi = append(yi, i)\n\t\t}\n\t}\n\tfor i, s := range x {\n\t\tif j, ok := m[s]; ok && j >= 0 {\n\t\t\txi = append(xi, i)\n\t\t\tinv = append(inv, j)\n\t\t}\n\t}\n\n\t// Apply Algorithm A from Szymanski's paper.\n\t// In those terms, A = J = inv and B = [0, n).\n\t// We add sentinel pairs {0,0}, and {len(x),len(y)}\n\t// to the returned sequence, to help the processing loop.\n\tJ := inv\n\tn := len(xi)\n\tT := make([]int, n)\n\tL := make([]int, n)\n\tfor i := range T {\n\t\tT[i] = n + 1\n\t}\n\tfor i := 0; i < n; i++ {\n\t\tk := sort.Search(n, func(k int) bool {\n\t\t\treturn T[k] >= J[i]\n\t\t})\n\t\tT[k] = J[i]\n\t\tL[i] = k + 1\n\t}\n\tk := 0\n\tfor _, v := range L {\n\t\tif k < v {\n\t\t\tk = v\n\t\t}\n\t}\n\tseq := make([]pair, 2+k)\n\tseq[1+k] = pair{len(x), len(y)} // sentinel at end\n\tlastj := n\n\tfor i := n - 1; i >= 0; i-- {\n\t\tif L[i] == k && J[i] < lastj {\n\t\t\tseq[k] = pair{xi[i], yi[J[i]]}\n\t\t\tk--\n\t\t}\n\t}\n\tseq[0] = pair{0, 0} // sentinel at start\n\treturn seq\n}\n"
  },
  {
    "path": "docs/GNUmakefile",
    "content": "# Makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line.\nSPHINXOPTS    =\nSPHINXBUILD   = sphinx-build\nPAPER         =\nBUILDDIR      = _build\n\n# Internal variables.\nPAPEROPT_a4     = -D latex_paper_size=a4\nPAPEROPT_letter = -D latex_paper_size=letter\nALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .\n# the i18n builder cannot share the environment and doctrees with the others\nI18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .\n\n.PHONY: help\nhelp:\n\t@echo \"Please use \\`$(MAKE) <target>' where <target> is one of\"\n\t@echo \"  html       to make standalone HTML files\"\n\t@echo \"  dirhtml    to make HTML files named index.html in directories\"\n\t@echo \"  singlehtml to make a single large HTML file\"\n\t@echo \"  pickle     to make pickle files\"\n\t@echo \"  json       to make JSON files\"\n\t@echo \"  htmlhelp   to make HTML files and a HTML help project\"\n\t@echo \"  qthelp     to make HTML files and a qthelp project\"\n\t@echo \"  applehelp  to make an Apple Help Book\"\n\t@echo \"  devhelp    to make HTML files and a Devhelp project\"\n\t@echo \"  epub       to make an epub\"\n\t@echo \"  epub3      to make an epub3\"\n\t@echo \"  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter\"\n\t@echo \"  latexpdf   to make LaTeX files and run them through pdflatex\"\n\t@echo \"  latexpdfja to make LaTeX files and run them through platex/dvipdfmx\"\n\t@echo \"  text       to make text files\"\n\t@echo \"  man        to make manual pages\"\n\t@echo \"  texinfo    to make Texinfo files\"\n\t@echo \"  info       to make Texinfo files and run them through makeinfo\"\n\t@echo \"  gettext    to make PO message catalogs\"\n\t@echo \"  changes    to make an overview of all changed/added/deprecated items\"\n\t@echo \"  xml        to make Docutils-native XML files\"\n\t@echo \"  pseudoxml  to make pseudoxml-XML files for display purposes\"\n\t@echo \"  linkcheck  to check all external links for integrity\"\n\t@echo \"  doctest    to run all doctests embedded in the documentation (if enabled)\"\n\t@echo \"  coverage   to run coverage check of the documentation (if enabled)\"\n\t@echo \"  dummy      to check syntax errors of document sources\"\n\n.PHONY: clean\nclean:\n\trm -rf $(BUILDDIR)/*\n\n.PHONY: html\nhtml:\n\t$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html\n\t@echo\n\t@echo \"Build finished. The HTML pages are in $(BUILDDIR)/html.\"\n\n.PHONY: dirhtml\ndirhtml:\n\t$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml\n\t@echo\n\t@echo \"Build finished. The HTML pages are in $(BUILDDIR)/dirhtml.\"\n\n.PHONY: singlehtml\nsinglehtml:\n\t$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml\n\t@echo\n\t@echo \"Build finished. The HTML page is in $(BUILDDIR)/singlehtml.\"\n\n.PHONY: pickle\npickle:\n\t$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle\n\t@echo\n\t@echo \"Build finished; now you can process the pickle files.\"\n\n.PHONY: json\njson:\n\t$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json\n\t@echo\n\t@echo \"Build finished; now you can process the JSON files.\"\n\n.PHONY: htmlhelp\nhtmlhelp:\n\t$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp\n\t@echo\n\t@echo \"Build finished; now you can run HTML Help Workshop with the\" \\\n\t      \".hhp project file in $(BUILDDIR)/htmlhelp.\"\n\n.PHONY: qthelp\nqthelp:\n\t$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp\n\t@echo\n\t@echo \"Build finished; now you can run \"qcollectiongenerator\" with the\" \\\n\t      \".qhcp project file in $(BUILDDIR)/qthelp, like this:\"\n\t@echo \"# qcollectiongenerator $(BUILDDIR)/qthelp/TinyGo.qhcp\"\n\t@echo \"To view the help file:\"\n\t@echo \"# assistant -collectionFile $(BUILDDIR)/qthelp/TinyGo.qhc\"\n\n.PHONY: applehelp\napplehelp:\n\t$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp\n\t@echo\n\t@echo \"Build finished. The help book is in $(BUILDDIR)/applehelp.\"\n\t@echo \"N.B. You won't be able to view it unless you put it in\" \\\n\t      \"~/Library/Documentation/Help or install it in your application\" \\\n\t      \"bundle.\"\n\n.PHONY: devhelp\ndevhelp:\n\t$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp\n\t@echo\n\t@echo \"Build finished.\"\n\t@echo \"To view the help file:\"\n\t@echo \"# mkdir -p $$HOME/.local/share/devhelp/TinyGo\"\n\t@echo \"# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/TinyGo\"\n\t@echo \"# devhelp\"\n\n.PHONY: epub\nepub:\n\t$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub\n\t@echo\n\t@echo \"Build finished. The epub file is in $(BUILDDIR)/epub.\"\n\n.PHONY: epub3\nepub3:\n\t$(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3\n\t@echo\n\t@echo \"Build finished. The epub3 file is in $(BUILDDIR)/epub3.\"\n\n.PHONY: latex\nlatex:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo\n\t@echo \"Build finished; the LaTeX files are in $(BUILDDIR)/latex.\"\n\t@echo \"Run \\`make' in that directory to run these through (pdf)latex\" \\\n\t      \"(use \\`make latexpdf' here to do that automatically).\"\n\n.PHONY: latexpdf\nlatexpdf:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo \"Running LaTeX files through pdflatex...\"\n\t$(MAKE) -C $(BUILDDIR)/latex all-pdf\n\t@echo \"pdflatex finished; the PDF files are in $(BUILDDIR)/latex.\"\n\n.PHONY: latexpdfja\nlatexpdfja:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo \"Running LaTeX files through platex and dvipdfmx...\"\n\t$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja\n\t@echo \"pdflatex finished; the PDF files are in $(BUILDDIR)/latex.\"\n\n.PHONY: text\ntext:\n\t$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text\n\t@echo\n\t@echo \"Build finished. The text files are in $(BUILDDIR)/text.\"\n\n.PHONY: man\nman:\n\t$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man\n\t@echo\n\t@echo \"Build finished. The manual pages are in $(BUILDDIR)/man.\"\n\n.PHONY: texinfo\ntexinfo:\n\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo\n\t@echo\n\t@echo \"Build finished. The Texinfo files are in $(BUILDDIR)/texinfo.\"\n\t@echo \"Run \\`make' in that directory to run these through makeinfo\" \\\n\t      \"(use \\`make info' here to do that automatically).\"\n\n.PHONY: info\ninfo:\n\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo\n\t@echo \"Running Texinfo files through makeinfo...\"\n\tmake -C $(BUILDDIR)/texinfo info\n\t@echo \"makeinfo finished; the Info files are in $(BUILDDIR)/texinfo.\"\n\n.PHONY: gettext\ngettext:\n\t$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale\n\t@echo\n\t@echo \"Build finished. The message catalogs are in $(BUILDDIR)/locale.\"\n\n.PHONY: changes\nchanges:\n\t$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes\n\t@echo\n\t@echo \"The overview file is in $(BUILDDIR)/changes.\"\n\n.PHONY: linkcheck\nlinkcheck:\n\t$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck\n\t@echo\n\t@echo \"Link check complete; look for any errors in the above output \" \\\n\t      \"or in $(BUILDDIR)/linkcheck/output.txt.\"\n\n.PHONY: doctest\ndoctest:\n\t$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest\n\t@echo \"Testing of doctests in the sources finished, look at the \" \\\n\t      \"results in $(BUILDDIR)/doctest/output.txt.\"\n\n.PHONY: coverage\ncoverage:\n\t$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage\n\t@echo \"Testing of coverage in the sources finished, look at the \" \\\n\t      \"results in $(BUILDDIR)/coverage/python.txt.\"\n\n.PHONY: xml\nxml:\n\t$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml\n\t@echo\n\t@echo \"Build finished. The XML files are in $(BUILDDIR)/xml.\"\n\n.PHONY: pseudoxml\npseudoxml:\n\t$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml\n\t@echo\n\t@echo \"Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml.\"\n\n.PHONY: dummy\ndummy:\n\t$(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy\n\t@echo\n\t@echo \"Build finished. Dummy builder generates no files.\"\n"
  },
  {
    "path": "docs/conf.py",
    "content": "# -*- coding: utf-8 -*-\n#\n# TinyGo documentation build configuration file, created by\n# sphinx-quickstart on Sat Sep 22 15:05:19 2018.\n#\n# This file is execfile()d with the current directory set to its\n# containing dir.\n#\n# Note that not all possible configuration values are present in this\n# autogenerated file.\n#\n# All configuration values have a default; values that are commented out\n# serve to show the default.\n\n# If extensions (or modules to document with autodoc) are in another directory,\n# add these directories to sys.path here. If the directory is relative to the\n# documentation root, use os.path.abspath to make it absolute, like shown here.\n#\n# import os\n# import sys\n# sys.path.insert(0, os.path.abspath('.'))\n\n# -- General configuration ------------------------------------------------\n\n# If your documentation needs a minimal Sphinx version, state it here.\n#\n# needs_sphinx = '1.0'\n\n# Add any Sphinx extension module names here, as strings. They can be\n# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom\n# ones.\nextensions = []\n\n# Add any paths that contain templates here, relative to this directory.\ntemplates_path = ['templates']\n\n# The suffix(es) of source filenames.\n# You can specify multiple suffix as a list of string:\n#\n# source_suffix = ['.rst', '.md']\nsource_suffix = '.rst'\n\n# The encoding of source files.\n#\n# source_encoding = 'utf-8-sig'\n\n# The master toctree document.\nmaster_doc = 'index'\n\n# General information about the project.\nproject = u'TinyGo'\ncopyright = u'2018, Ayke van Laethem'\nauthor = u'Ayke van Laethem'\n\n# The version info for the project you're documenting, acts as replacement for\n# |version| and |release|, also used in various other places throughout the\n# built documents.\n#\n# The short X.Y version.\nversion = u'master'\n# The full version, including alpha/beta/rc tags.\nrelease = u'master'\n\n# The language for content autogenerated by Sphinx. Refer to documentation\n# for a list of supported languages.\n#\n# This is also used if you do content translation via gettext catalogs.\n# Usually you set \"language\" from the command line for these cases.\nlanguage = None\n\n# There are two options for replacing |today|: either, you set today to some\n# non-false value, then it is used:\n#\n# today = ''\n#\n# Else, today_fmt is used as the format for a strftime call.\n#\n# today_fmt = '%B %d, %Y'\n\n# List of patterns, relative to source directory, that match files and\n# directories to ignore when looking for source files.\n# This patterns also effect to html_static_path and html_extra_path\nexclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']\n\n# The reST default role (used for this markup: `text`) to use for all\n# documents.\n#\n# default_role = None\n\n# If true, '()' will be appended to :func: etc. cross-reference text.\n#\n# add_function_parentheses = True\n\n# If true, the current module name will be prepended to all description\n# unit titles (such as .. function::).\n#\n# add_module_names = True\n\n# If true, sectionauthor and moduleauthor directives will be shown in the\n# output. They are ignored by default.\n#\n# show_authors = False\n\n# The name of the Pygments (syntax highlighting) style to use.\npygments_style = 'sphinx'\n\n# A list of ignored prefixes for module index sorting.\n# modindex_common_prefix = []\n\n# If true, keep warnings as \"system message\" paragraphs in the built documents.\n# keep_warnings = False\n\n# If true, `todo` and `todoList` produce output, else they produce nothing.\ntodo_include_todos = False\n\n\n# -- Options for HTML output ----------------------------------------------\n\n# The theme to use for HTML and HTML Help pages.  See the documentation for\n# a list of builtin themes.\n#\ntry:\n    import sphinx_rtd_theme\n    html_theme = 'sphinx_rtd_theme'\nexcept:\n    html_theme = 'alabaster'\n\n# Theme options are theme-specific and customize the look and feel of a theme\n# further.  For a list of options available for each theme, see the\n# documentation.\n#\n# html_theme_options = {}\n\n# Add any paths that contain custom themes here, relative to this directory.\n# html_theme_path = []\n\n# The name for this set of Sphinx documents.\n# \"<project> v<release> documentation\" by default.\n#\n# html_title = u'TinyGo vmaster'\n\n# A shorter title for the navigation bar.  Default is the same as html_title.\n#\n# html_short_title = None\n\n# The name of an image file (relative to this directory) to place at the top\n# of the sidebar.\n#\n# html_logo = None\n\n# The name of an image file (relative to this directory) to use as a favicon of\n# the docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32\n# pixels large.\n#\n# html_favicon = None\n\n# Add any paths that contain custom static files (such as style sheets) here,\n# relative to this directory. They are copied after the builtin static files,\n# so a file named \"default.css\" will overwrite the builtin \"default.css\".\nhtml_static_path = ['static']\n\n# Add any extra paths that contain custom files (such as robots.txt or\n# .htaccess) here, relative to this directory. These files are copied\n# directly to the root of the documentation.\n#\n# html_extra_path = []\n\n# If not None, a 'Last updated on:' timestamp is inserted at every page\n# bottom, using the given strftime format.\n# The empty string is equivalent to '%b %d, %Y'.\n#\n# html_last_updated_fmt = None\n\n# If true, SmartyPants will be used to convert quotes and dashes to\n# typographically correct entities.\n#\n# html_use_smartypants = True\n\n# Custom sidebar templates, maps document names to template names.\n#\n# html_sidebars = {}\n\n# Additional templates that should be rendered to pages, maps page names to\n# template names.\n#\n# html_additional_pages = {}\n\n# If false, no module index is generated.\n#\n# html_domain_indices = True\n\n# If false, no index is generated.\n#\n# html_use_index = True\n\n# If true, the index is split into individual pages for each letter.\n#\n# html_split_index = False\n\n# If true, links to the reST sources are added to the pages.\n#\n# html_show_sourcelink = True\n\n# If true, \"Created using Sphinx\" is shown in the HTML footer. Default is True.\n#\n# html_show_sphinx = True\n\n# If true, \"(C) Copyright ...\" is shown in the HTML footer. Default is True.\n#\n# html_show_copyright = True\n\n# If true, an OpenSearch description file will be output, and all pages will\n# contain a <link> tag referring to it.  The value of this option must be the\n# base URL from which the finished HTML is served.\n#\n# html_use_opensearch = ''\n\n# This is the file name suffix for HTML files (e.g. \".xhtml\").\n# html_file_suffix = None\n\n# Language to be used for generating the HTML full-text search index.\n# Sphinx supports the following languages:\n#   'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'\n#   'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh'\n#\n# html_search_language = 'en'\n\n# A dictionary with options for the search language support, empty by default.\n# 'ja' uses this config value.\n# 'zh' user can custom change `jieba` dictionary path.\n#\n# html_search_options = {'type': 'default'}\n\n# The name of a javascript file (relative to the configuration directory) that\n# implements a search results scorer. If empty, the default will be used.\n#\n# html_search_scorer = 'scorer.js'\n\n# Output file base name for HTML help builder.\nhtmlhelp_basename = 'TinyGodoc'\n\n# -- Options for LaTeX output ---------------------------------------------\n\nlatex_elements = {\n     # The paper size ('letterpaper' or 'a4paper').\n     #\n     # 'papersize': 'letterpaper',\n\n     # The font size ('10pt', '11pt' or '12pt').\n     #\n     # 'pointsize': '10pt',\n\n     # Additional stuff for the LaTeX preamble.\n     #\n     # 'preamble': '',\n\n     # Latex figure (float) alignment\n     #\n     # 'figure_align': 'htbp',\n}\n\n# Grouping the document tree into LaTeX files. List of tuples\n# (source start file, target name, title,\n#  author, documentclass [howto, manual, or own class]).\nlatex_documents = [\n    (master_doc, 'TinyGo.tex', u'TinyGo Documentation',\n     u'Ayke van Laethem', 'manual'),\n]\n\n# The name of an image file (relative to this directory) to place at the top of\n# the title page.\n#\n# latex_logo = None\n\n# For \"manual\" documents, if this is true, then toplevel headings are parts,\n# not chapters.\n#\n# latex_use_parts = False\n\n# If true, show page references after internal links.\n#\n# latex_show_pagerefs = False\n\n# If true, show URL addresses after external links.\n#\n# latex_show_urls = False\n\n# Documents to append as an appendix to all manuals.\n#\n# latex_appendices = []\n\n# It false, will not define \\strong, \\code, \titleref, \\crossref ... but only\n# \\sphinxstrong, ..., \\sphinxtitleref, ... To help avoid clash with user added\n# packages.\n#\n# latex_keep_old_macro_names = True\n\n# If false, no module index is generated.\n#\n# latex_domain_indices = True\n\n\n# -- Options for manual page output ---------------------------------------\n\n# One entry per manual page. List of tuples\n# (source start file, name, description, authors, manual section).\nman_pages = [\n    (master_doc, 'tinygo', u'TinyGo Documentation',\n     [author], 1)\n]\n\n# If true, show URL addresses after external links.\n#\n# man_show_urls = False\n\n\n# -- Options for Texinfo output -------------------------------------------\n\n# Grouping the document tree into Texinfo files. List of tuples\n# (source start file, target name, title, author,\n#  dir menu entry, description, category)\ntexinfo_documents = [\n    (master_doc, 'TinyGo', u'TinyGo Documentation',\n     author, 'TinyGo', 'One line description of project.',\n     'Miscellaneous'),\n]\n\n# Documents to append as an appendix to all manuals.\n#\n# texinfo_appendices = []\n\n# If false, no module index is generated.\n#\n# texinfo_domain_indices = True\n\n# How to display URL addresses: 'footnote', 'no', or 'inline'.\n#\n# texinfo_show_urls = 'footnote'\n\n# If true, do not generate a @detailmenu in the \"Top\" node's menu.\n#\n# texinfo_no_detailmenu = False\n"
  },
  {
    "path": "docs/index.rst",
    "content": ".. TinyGo documentation master file, created by\n   sphinx-quickstart on Sat Sep 22 15:05:19 2018.\n   You can adapt this file completely to your liking, but it should at least\n   contain the root `toctree` directive.\n\nThe TinyGo site has moved!\n==================================\n\nContents:\n\n.. toctree::\n   :maxdepth: 2\n\n   moved\n"
  },
  {
    "path": "docs/make.bat",
    "content": "@ECHO OFF\r\n\r\nREM Command file for Sphinx documentation\r\n\r\nif \"%SPHINXBUILD%\" == \"\" (\r\n\tset SPHINXBUILD=sphinx-build\r\n)\r\nset BUILDDIR=_build\r\nset ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .\r\nset I18NSPHINXOPTS=%SPHINXOPTS% .\r\nif NOT \"%PAPER%\" == \"\" (\r\n\tset ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%\r\n\tset I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%\r\n)\r\n\r\nif \"%1\" == \"\" goto help\r\n\r\nif \"%1\" == \"help\" (\r\n\t:help\r\n\techo.Please use `make ^<target^>` where ^<target^> is one of\r\n\techo.  html       to make standalone HTML files\r\n\techo.  dirhtml    to make HTML files named index.html in directories\r\n\techo.  singlehtml to make a single large HTML file\r\n\techo.  pickle     to make pickle files\r\n\techo.  json       to make JSON files\r\n\techo.  htmlhelp   to make HTML files and a HTML help project\r\n\techo.  qthelp     to make HTML files and a qthelp project\r\n\techo.  devhelp    to make HTML files and a Devhelp project\r\n\techo.  epub       to make an epub\r\n\techo.  epub3      to make an epub3\r\n\techo.  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter\r\n\techo.  text       to make text files\r\n\techo.  man        to make manual pages\r\n\techo.  texinfo    to make Texinfo files\r\n\techo.  gettext    to make PO message catalogs\r\n\techo.  changes    to make an overview over all changed/added/deprecated items\r\n\techo.  xml        to make Docutils-native XML files\r\n\techo.  pseudoxml  to make pseudoxml-XML files for display purposes\r\n\techo.  linkcheck  to check all external links for integrity\r\n\techo.  doctest    to run all doctests embedded in the documentation if enabled\r\n\techo.  coverage   to run coverage check of the documentation if enabled\r\n\techo.  dummy      to check syntax errors of document sources\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"clean\" (\r\n\tfor /d %%i in (%BUILDDIR%\\*) do rmdir /q /s %%i\r\n\tdel /q /s %BUILDDIR%\\*\r\n\tgoto end\r\n)\r\n\r\n\r\nREM Check if sphinx-build is available and fallback to Python version if any\r\n%SPHINXBUILD% 1>NUL 2>NUL\r\nif errorlevel 9009 goto sphinx_python\r\ngoto sphinx_ok\r\n\r\n:sphinx_python\r\n\r\nset SPHINXBUILD=python -m sphinx.__init__\r\n%SPHINXBUILD% 2> nul\r\nif errorlevel 9009 (\r\n\techo.\r\n\techo.The 'sphinx-build' command was not found. Make sure you have Sphinx\r\n\techo.installed, then set the SPHINXBUILD environment variable to point\r\n\techo.to the full path of the 'sphinx-build' executable. Alternatively you\r\n\techo.may add the Sphinx directory to PATH.\r\n\techo.\r\n\techo.If you don't have Sphinx installed, grab it from\r\n\techo.http://sphinx-doc.org/\r\n\texit /b 1\r\n)\r\n\r\n:sphinx_ok\r\n\r\n\r\nif \"%1\" == \"html\" (\r\n\t%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The HTML pages are in %BUILDDIR%/html.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"dirhtml\" (\r\n\t%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"singlehtml\" (\r\n\t%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"pickle\" (\r\n\t%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished; now you can process the pickle files.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"json\" (\r\n\t%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished; now you can process the JSON files.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"htmlhelp\" (\r\n\t%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished; now you can run HTML Help Workshop with the ^\r\n.hhp project file in %BUILDDIR%/htmlhelp.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"qthelp\" (\r\n\t%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished; now you can run \"qcollectiongenerator\" with the ^\r\n.qhcp project file in %BUILDDIR%/qthelp, like this:\r\n\techo.^> qcollectiongenerator %BUILDDIR%\\qthelp\\TinyGo.qhcp\r\n\techo.To view the help file:\r\n\techo.^> assistant -collectionFile %BUILDDIR%\\qthelp\\TinyGo.ghc\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"devhelp\" (\r\n\t%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"epub\" (\r\n\t%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The epub file is in %BUILDDIR%/epub.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"epub3\" (\r\n\t%SPHINXBUILD% -b epub3 %ALLSPHINXOPTS% %BUILDDIR%/epub3\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The epub3 file is in %BUILDDIR%/epub3.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"latex\" (\r\n\t%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished; the LaTeX files are in %BUILDDIR%/latex.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"latexpdf\" (\r\n\t%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex\r\n\tcd %BUILDDIR%/latex\r\n\tmake all-pdf\r\n\tcd %~dp0\r\n\techo.\r\n\techo.Build finished; the PDF files are in %BUILDDIR%/latex.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"latexpdfja\" (\r\n\t%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex\r\n\tcd %BUILDDIR%/latex\r\n\tmake all-pdf-ja\r\n\tcd %~dp0\r\n\techo.\r\n\techo.Build finished; the PDF files are in %BUILDDIR%/latex.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"text\" (\r\n\t%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The text files are in %BUILDDIR%/text.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"man\" (\r\n\t%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The manual pages are in %BUILDDIR%/man.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"texinfo\" (\r\n\t%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"gettext\" (\r\n\t%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The message catalogs are in %BUILDDIR%/locale.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"changes\" (\r\n\t%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.The overview file is in %BUILDDIR%/changes.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"linkcheck\" (\r\n\t%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Link check complete; look for any errors in the above output ^\r\nor in %BUILDDIR%/linkcheck/output.txt.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"doctest\" (\r\n\t%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Testing of doctests in the sources finished, look at the ^\r\nresults in %BUILDDIR%/doctest/output.txt.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"coverage\" (\r\n\t%SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Testing of coverage in the sources finished, look at the ^\r\nresults in %BUILDDIR%/coverage/python.txt.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"xml\" (\r\n\t%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The XML files are in %BUILDDIR%/xml.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"pseudoxml\" (\r\n\t%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"dummy\" (\r\n\t%SPHINXBUILD% -b dummy %ALLSPHINXOPTS% %BUILDDIR%/dummy\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. Dummy builder generates no files.\r\n\tgoto end\r\n)\r\n\r\n:end\r\n"
  },
  {
    "path": "docs/moved.rst",
    "content": ".. _moved:\n\n.. highlight:: none\n\nThe TinyGo Docs Site Has Moved\n=========================\n\nThe documentation web site for TinyGo has moved. \n\nYou can find the new web site at `tinygo.org <https://tinygo.org/>`_\n\nThank you!\n"
  },
  {
    "path": "errors_test.go",
    "content": "package main\n\nimport (\n\t\"bytes\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/tinygo-org/tinygo/builder\"\n\t\"github.com/tinygo-org/tinygo/compileopts\"\n\t\"github.com/tinygo-org/tinygo/diagnostics\"\n)\n\n// Test the error messages of the TinyGo compiler.\nfunc TestErrors(t *testing.T) {\n\t// TODO: nicely formatted error messages for:\n\t//   - duplicate symbols in ld.lld (currently only prints bitcode file)\n\ttype errorTest struct {\n\t\tname   string\n\t\ttarget string\n\t}\n\tfor _, tc := range []errorTest{\n\t\t{name: \"cgo\"},\n\t\t{name: \"compiler\"},\n\t\t{name: \"interp\"},\n\t\t{name: \"invalidmain\"},\n\t\t{name: \"invalidname\"},\n\t\t{name: \"linker-flashoverflow\", target: \"cortex-m-qemu\"},\n\t\t{name: \"linker-ramoverflow\", target: \"cortex-m-qemu\"},\n\t\t{name: \"linker-undefined\", target: \"darwin/arm64\"},\n\t\t{name: \"linker-undefined\", target: \"linux/amd64\"},\n\t\t//{name: \"linker-undefined\", target: \"windows/amd64\"}, // TODO: no source location\n\t\t{name: \"linker-undefined\", target: \"cortex-m-qemu\"},\n\t\t//{name: \"linker-undefined\", target: \"wasip1\"}, // TODO: no source location\n\t\t{name: \"loader-importcycle\"},\n\t\t{name: \"loader-invaliddep\"},\n\t\t{name: \"loader-invalidpackage\"},\n\t\t{name: \"loader-nopackage\"},\n\t\t{name: \"optimizer\"},\n\t\t{name: \"syntax\"},\n\t\t{name: \"types\"},\n\t} {\n\t\tname := tc.name\n\t\tif tc.target != \"\" {\n\t\t\tname += \"#\" + tc.target\n\t\t}\n\t\ttarget := tc.target\n\t\tif target == \"\" {\n\t\t\ttarget = \"wasip1\"\n\t\t}\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\toptions := optionsFromTarget(target, sema)\n\t\t\ttestErrorMessages(t, \"./testdata/errors/\"+tc.name+\".go\", &options)\n\t\t})\n\t}\n}\n\nfunc testErrorMessages(t *testing.T, filename string, options *compileopts.Options) {\n\tt.Parallel()\n\n\t// Parse expected error messages.\n\texpected := readErrorMessages(t, filename)\n\n\t// Try to build a binary (this should fail with an error).\n\ttmpdir := t.TempDir()\n\tconfig, err := builder.NewConfig(options)\n\tif err != nil {\n\t\tt.Fatal(\"expected to get a compiler error\")\n\t}\n\terr = Build(filename, tmpdir+\"/out\", config)\n\tif err == nil {\n\t\tt.Fatal(\"expected to get a compiler error\")\n\t}\n\n\t// Get the full ./testdata/errors directory.\n\twd, absErr := filepath.Abs(\"testdata/errors\")\n\tif absErr != nil {\n\t\tt.Fatal(absErr)\n\t}\n\n\t// Write error message out as plain text.\n\tvar buf bytes.Buffer\n\tdiagnostics.CreateDiagnostics(err).WriteTo(&buf, wd)\n\tactual := strings.TrimRight(buf.String(), \"\\n\")\n\n\t// Check whether the error is as expected.\n\tif !matchErrors(t, expected, actual) {\n\t\tt.Errorf(\"expected error:\\n%s\\ngot:\\n%s\", indentText(expected, \"> \"), indentText(actual, \"> \"))\n\t}\n}\n\nfunc matchErrors(t *testing.T, pattern, actual string) bool {\n\tpatternLines := strings.Split(pattern, \"\\n\")\n\tactualLines := strings.Split(actual, \"\\n\")\n\tif len(patternLines) != len(actualLines) {\n\t\treturn false\n\t}\n\tfor i, patternLine := range patternLines {\n\t\tindices := regexp.MustCompile(`\\{\\{.*?\\}\\}`).FindAllStringIndex(patternLine, -1)\n\t\tpatternParts := []string{\"^\"}\n\t\tlastStop := 0\n\t\tfor _, startstop := range indices {\n\t\t\tstart := startstop[0]\n\t\t\tstop := startstop[1]\n\t\t\tpatternParts = append(patternParts,\n\t\t\t\tregexp.QuoteMeta(patternLine[lastStop:start]),\n\t\t\t\tpatternLine[start+2:stop-2])\n\t\t\tlastStop = stop\n\t\t}\n\t\tpatternParts = append(patternParts, regexp.QuoteMeta(patternLine[lastStop:]), \"$\")\n\t\tpattern := strings.Join(patternParts, \"\")\n\t\tre, err := regexp.Compile(pattern)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"could not compile regexp for %#v: %v\", patternLine, err)\n\t\t}\n\t\tif !re.MatchString(actualLines[i]) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// Indent the given text with a given indentation string.\nfunc indentText(text, indent string) string {\n\treturn indent + strings.ReplaceAll(text, \"\\n\", \"\\n\"+indent)\n}\n\n// Read \"// ERROR:\" prefixed messages from the given file.\nfunc readErrorMessages(t *testing.T, file string) string {\n\tdata, err := os.ReadFile(file)\n\tif err != nil {\n\t\tt.Fatal(\"could not read input file:\", err)\n\t}\n\n\tvar errors []string\n\tfor _, line := range strings.Split(string(data), \"\\n\") {\n\t\tif strings.HasPrefix(line, \"// ERROR: \") {\n\t\t\terrors = append(errors, strings.TrimRight(line[len(\"// ERROR: \"):], \"\\r\\n\"))\n\t\t}\n\t}\n\treturn strings.Join(errors, \"\\n\")\n}\n"
  },
  {
    "path": "flake.nix",
    "content": "# A Nix flake file, mainly intended for developing TinyGo.\n# You can download Nix here, for use on your Linux or macOS system:\n#   https://nixos.org/download.html\n# After you have installed Nix, you can enter the development environment as\n# follows:\n#\n#   nix develop\n#\n# This drops you into a bash shell, where you can install TinyGo simply using\n# the following command:\n#\n#   go install\n#\n# That's all! Assuming you've set up your $PATH correctly, you can now use the\n# tinygo command as usual:\n#\n#   tinygo version\n#\n# But you'll need a bit more to make TinyGo actually able to compile code:\n#\n#   make llvm-source            # fetch compiler-rt\n#   git submodule update --init # fetch lots of other libraries and SVD files\n#   make gen-device -j4         # build src/device/*/*.go files\n#\n# With this, you should have an environment that can compile anything - except\n# for the Xtensa architecture (ESP8266/ESP32) because support for that lives in\n# a separate LLVM fork.\n#\n# You can also do many other things from this environment. Building and flashing\n# should work as you're used to: it's not a VM or container so there are no\n# access restrictions and you're running in the same host environment - just\n# with a slightly different set of tools available.\n{\n  inputs = {\n    # Use a recent stable release, but fix the version to make it reproducible.\n    # This version should be updated from time to time.\n    nixpkgs.url = \"nixpkgs/nixos-25.05\";\n    flake-utils.url = \"github:numtide/flake-utils\";\n  };\n  outputs = { self, nixpkgs, flake-utils }:\n    flake-utils.lib.eachDefaultSystem (system:\n      let\n        pkgs = nixpkgs.legacyPackages.${system};\n      in\n      with pkgs;\n      {\n        devShells.default = mkShell {\n          buildInputs = [\n            # These dependencies are required for building tinygo (go install).\n            go\n            llvmPackages_20.llvm\n            llvmPackages_20.libclang\n            # Additional dependencies needed at runtime, for building and/or\n            # flashing.\n            llvmPackages_20.lld\n            avrdude\n            binaryen\n            # Additional dependencies needed for on-chip debugging.\n            # These tools are rather big (especially GDB) and not frequently\n            # used, so are commented out. On-chip debugging is still possible if\n            # these tools are available in the host environment.\n            #gdb\n            #openocd\n          ];\n          shellHook= ''\n            # Make `make smoketest` work (the default is `md5`, while Nix only\n            # has `md5sum`).\n            export MD5SUM=md5sum\n\n            # Ugly hack to make the Clang resources directory available.\n            export GOFLAGS=\"\\\"-ldflags=-X github.com/tinygo-org/tinygo/goenv.clangResourceDir=${llvmPackages_20.clang.cc.lib}/lib/clang/20\\\" -tags=llvm20\"\n          '';\n        };\n      }\n    );\n}\n"
  },
  {
    "path": "go.mod",
    "content": "module github.com/tinygo-org/tinygo\n\ngo 1.22.0\n\nrequire (\n\tgithub.com/aykevl/go-wasm v0.0.2-0.20250317121156-42b86c494139\n\tgithub.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2\n\tgithub.com/gofrs/flock v0.8.1\n\tgithub.com/google/shlex v0.0.0-20181106134648-c34317bd91bf\n\tgithub.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf\n\tgithub.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892\n\tgithub.com/mattn/go-colorable v0.1.13\n\tgithub.com/mattn/go-tty v0.0.4\n\tgithub.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3\n\tgithub.com/tetratelabs/wazero v1.6.0\n\tgo.bug.st/serial v1.6.0\n\tgolang.org/x/net v0.35.0\n\tgolang.org/x/sys v0.30.0\n\tgolang.org/x/tools v0.30.0\n\tgopkg.in/yaml.v2 v2.4.0\n\ttinygo.org/x/go-llvm v0.0.0-20250422114502-b8f170971e74\n)\n\nrequire (\n\tgithub.com/creack/goselect v0.1.2 // indirect\n\tgithub.com/mattn/go-isatty v0.0.20 // indirect\n\tgithub.com/stretchr/testify v1.8.4 // indirect\n\tgolang.org/x/text v0.22.0 // indirect\n)\n"
  },
  {
    "path": "go.sum",
    "content": "github.com/aykevl/go-wasm v0.0.2-0.20250317121156-42b86c494139 h1:2O/WuAt8J5id3khcAtVB90czG80m+v0sfkLE07GrCVg=\ngithub.com/aykevl/go-wasm v0.0.2-0.20250317121156-42b86c494139/go.mod h1:7sXyiaA0WtSogCu67R2252fQpVmJMh9JWJ9ddtGkpWw=\ngithub.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2 h1:oMCHnXa6CCCafdPDbMh/lWRhRByN0VFLvv+g+ayx1SI=\ngithub.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=\ngithub.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0=\ngithub.com/creack/goselect v0.1.2/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY=\ngithub.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=\ngithub.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=\ngithub.com/google/shlex v0.0.0-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg=\ngithub.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE=\ngithub.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s=\ngithub.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4=\ngithub.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892 h1:6J+qramlHVLmiBOgRiBOnQkno8uprqG6YFFQTt6uYIw=\ngithub.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892/go.mod h1:Pb6XcsXyropB9LNHhnqaknG/vEwYztLkQzVCHv8sQ3M=\ngithub.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=\ngithub.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=\ngithub.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=\ngithub.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=\ngithub.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=\ngithub.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=\ngithub.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=\ngithub.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=\ngithub.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=\ngithub.com/mattn/go-tty v0.0.4 h1:NVikla9X8MN0SQAqCYzpGyXv0jY7MNl3HOWD2dkle7E=\ngithub.com/mattn/go-tty v0.0.4/go.mod h1:u5GGXBtZU6RQoKV8gY5W6UhMudbR5vXnUe7j3pxse28=\ngithub.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3 h1:aQKxg3+2p+IFXXg97McgDGT5zcMrQoi0EICZs8Pgchs=\ngithub.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3/go.mod h1:9/etS5gpQq9BJsJMWg1wpLbfuSnkm8dPF6FdW2JXVhA=\ngithub.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=\ngithub.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=\ngithub.com/tetratelabs/wazero v1.6.0 h1:z0H1iikCdP8t+q341xqepY4EWvHEw8Es7tlqiVzlP3g=\ngithub.com/tetratelabs/wazero v1.6.0/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A=\ngo.bug.st/serial v1.6.0 h1:mAbRGN4cKE2J5gMwsMHC2KQisdLRQssO9WSM+rbZJ8A=\ngo.bug.st/serial v1.6.0/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE=\ngolang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=\ngolang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=\ngolang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=\ngolang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=\ngolang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=\ngolang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=\ngolang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=\ngolang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=\ngolang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=\ngolang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=\ngolang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY=\ngolang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=\ngopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=\ngopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=\ngopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ntinygo.org/x/go-llvm v0.0.0-20250422114502-b8f170971e74 h1:ovavgTdIBWCH8YWlcfq9gkpoyT1+IxMKSn+Df27QwE8=\ntinygo.org/x/go-llvm v0.0.0-20250422114502-b8f170971e74/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=\n"
  },
  {
    "path": "goenv/goenv.go",
    "content": "// Package goenv returns environment variables that are used in various parts of\n// the compiler. You can query it manually with the `tinygo env` subcommand.\npackage goenv\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io/fs\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// Keys is a slice of all available environment variable keys.\nvar Keys = []string{\n\t\"GOOS\",\n\t\"GOARCH\",\n\t\"GOROOT\",\n\t\"GOPATH\",\n\t\"GOCACHE\",\n\t\"CGO_ENABLED\",\n\t\"TINYGOROOT\",\n}\n\nfunc init() {\n\tswitch Get(\"GOARCH\") {\n\tcase \"arm\":\n\t\tKeys = append(Keys, \"GOARM\")\n\tcase \"mips\", \"mipsle\":\n\t\tKeys = append(Keys, \"GOMIPS\")\n\t}\n}\n\n// Set to true if we're linking statically against LLVM.\nvar hasBuiltinTools = false\n\n// TINYGOROOT is the path to the final location for checking tinygo files. If\n// unset (by a -X ldflag), then sourceDir() will fallback to the original build\n// directory.\nvar TINYGOROOT string\n\n// If a particular Clang resource dir must always be used and TinyGo can't\n// figure out the directory using heuristics, this global can be set using a\n// linker flag.\n// This is needed for Nix.\nvar clangResourceDir string\n\n// Variables read from a `go env` command invocation.\nvar goEnvVars struct {\n\tGOPATH    string\n\tGOROOT    string\n\tGOVERSION string\n}\n\nvar goEnvVarsOnce sync.Once\nvar goEnvVarsErr error // error returned from cmd.Run\n\n// Make sure goEnvVars is fresh. This can be called multiple times, the first\n// time will update all environment variables in goEnvVars.\nfunc readGoEnvVars() error {\n\tgoEnvVarsOnce.Do(func() {\n\t\tcmd := exec.Command(\"go\", \"env\", \"-json\", \"GOPATH\", \"GOROOT\", \"GOVERSION\")\n\t\toutput, err := cmd.Output()\n\t\tif err != nil {\n\t\t\t// Check for \"command not found\" error.\n\t\t\tif execErr, ok := err.(*exec.Error); ok {\n\t\t\t\tgoEnvVarsErr = fmt.Errorf(\"could not find '%s' command: %w\", execErr.Name, execErr.Err)\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// It's perhaps a bit ugly to handle this error here, but I couldn't\n\t\t\t// think of a better place further up in the call chain.\n\t\t\tif exitErr, ok := err.(*exec.ExitError); ok && exitErr.ExitCode() != 0 {\n\t\t\t\tif len(exitErr.Stderr) != 0 {\n\t\t\t\t\t// The 'go' command exited with an error message. Print that\n\t\t\t\t\t// message and exit, so we behave in a similar way.\n\t\t\t\t\tos.Stderr.Write(exitErr.Stderr)\n\t\t\t\t\tos.Exit(exitErr.ExitCode())\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Other errors. Not sure whether there are any, but just in case.\n\t\t\tgoEnvVarsErr = err\n\t\t\treturn\n\t\t}\n\t\terr = json.Unmarshal(output, &goEnvVars)\n\t\tif err != nil {\n\t\t\t// This should never happen if we have a sane Go toolchain\n\t\t\t// installed.\n\t\t\tgoEnvVarsErr = fmt.Errorf(\"unexpected error while unmarshalling `go env` output: %w\", err)\n\t\t}\n\t})\n\n\treturn goEnvVarsErr\n}\n\n// Get returns a single environment variable, possibly calculating it on-demand.\n// The empty string is returned for unknown environment variables.\nfunc Get(name string) string {\n\tswitch name {\n\tcase \"GOOS\":\n\t\tgoos := os.Getenv(\"GOOS\")\n\t\tif goos == \"\" {\n\t\t\tgoos = runtime.GOOS\n\t\t}\n\t\tif goos == \"android\" {\n\t\t\tgoos = \"linux\"\n\t\t}\n\t\treturn goos\n\tcase \"GOARCH\":\n\t\tif dir := os.Getenv(\"GOARCH\"); dir != \"\" {\n\t\t\treturn dir\n\t\t}\n\t\treturn runtime.GOARCH\n\tcase \"GOARM\":\n\t\tif goarm := os.Getenv(\"GOARM\"); goarm != \"\" {\n\t\t\treturn goarm\n\t\t}\n\t\tif goos := Get(\"GOOS\"); goos == \"windows\" || goos == \"android\" {\n\t\t\t// Assume Windows and Android are running on modern CPU cores.\n\t\t\t// This matches upstream Go.\n\t\t\treturn \"7\"\n\t\t}\n\t\t// Default to ARMv6 on other devices.\n\t\t// The difference between ARMv5 and ARMv6 is big, much bigger than the\n\t\t// difference between ARMv6 and ARMv7. ARMv6 binaries are much smaller,\n\t\t// especially when floating point instructions are involved.\n\t\treturn \"6\"\n\tcase \"GOMIPS\":\n\t\tgomips := os.Getenv(\"GOMIPS\")\n\t\tif gomips == \"\" {\n\t\t\t// Default to hardfloat (this matches the Go toolchain).\n\t\t\tgomips = \"hardfloat\"\n\t\t}\n\t\treturn gomips\n\tcase \"GOROOT\":\n\t\treadGoEnvVars()\n\t\treturn goEnvVars.GOROOT\n\tcase \"GOPATH\":\n\t\treadGoEnvVars()\n\t\treturn goEnvVars.GOPATH\n\tcase \"GOCACHE\":\n\t\t// Get the cache directory, usually ~/.cache/tinygo\n\t\tdir, err := os.UserCacheDir()\n\t\tif err != nil {\n\t\t\tpanic(\"could not find cache dir: \" + err.Error())\n\t\t}\n\t\treturn filepath.Join(dir, \"tinygo\")\n\tcase \"CGO_ENABLED\":\n\t\t// Always enable CGo. It is required by a number of targets, including\n\t\t// macOS and the rp2040.\n\t\treturn \"1\"\n\tcase \"TINYGOROOT\":\n\t\treturn sourceDir()\n\tcase \"WASMOPT\":\n\t\tif path := os.Getenv(\"WASMOPT\"); path != \"\" {\n\t\t\terr := wasmOptCheckVersion(path)\n\t\t\tif err != nil {\n\t\t\t\tfmt.Fprintf(os.Stderr, \"cannot use %q as wasm-opt (from WASMOPT environment variable): %s\", path, err.Error())\n\t\t\t\tos.Exit(1)\n\t\t\t}\n\n\t\t\treturn path\n\t\t}\n\n\t\treturn findWasmOpt()\n\tcase \"WASMTOOLS\":\n\t\tif path := os.Getenv(\"WASMTOOLS\"); path != \"\" {\n\t\t\treturn path\n\t\t}\n\t\treturn \"wasm-tools\"\n\tdefault:\n\t\treturn \"\"\n\t}\n}\n\n// Find wasm-opt, or exit with an error.\nfunc findWasmOpt() string {\n\ttinygoroot := sourceDir()\n\tsearchPaths := []string{\n\t\ttinygoroot + \"/bin/wasm-opt\",\n\t\ttinygoroot + \"/build/wasm-opt\",\n\t}\n\n\tvar paths []string\n\tfor _, path := range searchPaths {\n\t\tif runtime.GOOS == \"windows\" {\n\t\t\tpath += \".exe\"\n\t\t}\n\n\t\t_, err := os.Stat(path)\n\t\tif err != nil && errors.Is(err, fs.ErrNotExist) {\n\t\t\tcontinue\n\t\t}\n\n\t\tpaths = append(paths, path)\n\t}\n\n\tif path, err := exec.LookPath(\"wasm-opt\"); err == nil {\n\t\tpaths = append(paths, path)\n\t}\n\n\tif len(paths) == 0 {\n\t\tfmt.Fprintln(os.Stderr, \"error: could not find wasm-opt, set the WASMOPT environment variable to override\")\n\t\tos.Exit(1)\n\t}\n\n\terrs := make([]error, len(paths))\n\tfor i, path := range paths {\n\t\terr := wasmOptCheckVersion(path)\n\t\tif err == nil {\n\t\t\treturn path\n\t\t}\n\n\t\terrs[i] = err\n\t}\n\tfmt.Fprintln(os.Stderr, \"no usable wasm-opt found, update or run \\\"make binaryen\\\"\")\n\tfor i, path := range paths {\n\t\tfmt.Fprintf(os.Stderr, \"\\t%s: %s\\n\", path, errs[i].Error())\n\t}\n\tos.Exit(1)\n\tpanic(\"unreachable\")\n}\n\n// wasmOptCheckVersion checks if a copy of wasm-opt is usable.\nfunc wasmOptCheckVersion(path string) error {\n\tcmd := exec.Command(path, \"--version\")\n\tvar buf bytes.Buffer\n\tcmd.Stdout = &buf\n\tcmd.Stderr = os.Stderr\n\terr := cmd.Run()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tstr := buf.String()\n\tif strings.Contains(str, \"(\") {\n\t\t// The git tag may be placed in parentheses after the main version string.\n\t\tstr = strings.Split(str, \"(\")[0]\n\t}\n\n\tstr = strings.TrimSpace(str)\n\tvar ver uint\n\t_, err = fmt.Sscanf(str, \"wasm-opt version %d\", &ver)\n\tif err != nil || ver < 102 {\n\t\treturn errors.New(\"incompatible wasm-opt (need 102 or newer)\")\n\t}\n\n\treturn nil\n}\n\n// Return the TINYGOROOT, or exit with an error.\nfunc sourceDir() string {\n\t// Use $TINYGOROOT as root, if available.\n\troot := os.Getenv(\"TINYGOROOT\")\n\tif root != \"\" {\n\t\tif !isSourceDir(root) {\n\t\t\tfmt.Fprintln(os.Stderr, \"error: $TINYGOROOT was not set to the correct root\")\n\t\t\tos.Exit(1)\n\t\t}\n\t\treturn root\n\t}\n\n\tif TINYGOROOT != \"\" {\n\t\tif !isSourceDir(TINYGOROOT) {\n\t\t\tfmt.Fprintln(os.Stderr, \"error: TINYGOROOT was not set to the correct root\")\n\t\t\tos.Exit(1)\n\t\t}\n\t\treturn TINYGOROOT\n\t}\n\n\t// Find root from executable path.\n\tpath, err := os.Executable()\n\tif err != nil {\n\t\t// Very unlikely. Bail out if it happens.\n\t\tpanic(\"could not get executable path: \" + err.Error())\n\t}\n\troot = filepath.Dir(filepath.Dir(path))\n\tif isSourceDir(root) {\n\t\treturn root\n\t}\n\n\t// Fallback: use the original directory from where it was built\n\t// https://stackoverflow.com/a/32163888/559350\n\t_, path, _, _ = runtime.Caller(0)\n\troot = filepath.Dir(filepath.Dir(path))\n\tif isSourceDir(root) {\n\t\treturn root\n\t}\n\n\tfmt.Fprintln(os.Stderr, \"error: could not autodetect root directory, set the TINYGOROOT environment variable to override\")\n\tos.Exit(1)\n\tpanic(\"unreachable\")\n}\n\n// isSourceDir returns true if the directory looks like a TinyGo source directory.\nfunc isSourceDir(root string) bool {\n\t_, err := os.Stat(filepath.Join(root, \"src/runtime/internal/sys/zversion.go\"))\n\tif err != nil {\n\t\treturn false\n\t}\n\t_, err = os.Stat(filepath.Join(root, \"src/device/arm/arm.go\"))\n\treturn err == nil\n}\n\n// ClangResourceDir returns the clang resource dir if available. This is the\n// -resource-dir flag. If it isn't available, an empty string is returned and\n// -resource-dir should be left unset.\n// The libclang flag must be set if the resource dir is read for use by\n// libclang.\n// In that case, the resource dir is always returned (even when linking\n// dynamically against LLVM) because libclang always needs this directory.\nfunc ClangResourceDir(libclang bool) string {\n\tif clangResourceDir != \"\" {\n\t\t// The resource dir is forced to a particular value at build time.\n\t\t// This is needed on Nix for example, where Clang and libclang don't\n\t\t// know their own resource dir.\n\t\t// Also see:\n\t\t// https://discourse.nixos.org/t/why-is-the-clang-resource-dir-split-in-a-separate-package/34114\n\t\treturn clangResourceDir\n\t}\n\n\tif !hasBuiltinTools && !libclang {\n\t\t// Using external tools, so the resource dir doesn't need to be\n\t\t// specified. Clang knows where to find it.\n\t\treturn \"\"\n\t}\n\n\t// Check whether we're running from a TinyGo release directory.\n\t// This is the case for release binaries on GitHub.\n\troot := Get(\"TINYGOROOT\")\n\treleaseHeaderDir := filepath.Join(root, \"lib\", \"clang\")\n\tif _, err := os.Stat(releaseHeaderDir); !errors.Is(err, fs.ErrNotExist) {\n\t\treturn releaseHeaderDir\n\t}\n\n\tif hasBuiltinTools {\n\t\t// We are statically linked to LLVM.\n\t\t// Check whether we're running from the source directory.\n\t\t// This typically happens when TinyGo was built using `make` as part of\n\t\t// development.\n\t\tllvmMajor := strings.Split(llvm.Version, \".\")[0]\n\t\tbuildResourceDir := filepath.Join(root, \"llvm-build\", \"lib\", \"clang\", llvmMajor)\n\t\tif _, err := os.Stat(buildResourceDir); !errors.Is(err, fs.ErrNotExist) {\n\t\t\treturn buildResourceDir\n\t\t}\n\t} else {\n\t\t// We use external tools, either when installed using `go install` or\n\t\t// when packaged in a Linux distribution (Linux distros typically prefer\n\t\t// dynamic linking).\n\t\t// Try to detect the system clang resources directory.\n\t\tresourceDir := findSystemClangResources(root)\n\t\tif resourceDir != \"\" {\n\t\t\treturn resourceDir\n\t\t}\n\t}\n\n\t// Resource directory not found.\n\treturn \"\"\n}\n\n// Find the Clang resource dir on this particular system.\n// Return the empty string when they aren't found.\nfunc findSystemClangResources(TINYGOROOT string) string {\n\tllvmMajor := strings.Split(llvm.Version, \".\")[0]\n\n\tswitch runtime.GOOS {\n\tcase \"linux\", \"android\":\n\t\t// Header files are typically stored in /usr/lib/clang/<version>/include.\n\t\t// Tested on Fedora 39, Debian 12, and Arch Linux.\n\t\tpath := filepath.Join(\"/usr/lib/clang\", llvmMajor)\n\t\t_, err := os.Stat(filepath.Join(path, \"include\", \"stdint.h\"))\n\t\tif err == nil {\n\t\t\treturn path\n\t\t}\n\tcase \"darwin\":\n\t\t// This assumes a Homebrew installation, like in builder/commands.go.\n\t\tvar prefix string\n\t\tswitch runtime.GOARCH {\n\t\tcase \"amd64\":\n\t\t\tprefix = \"/usr/local/opt/llvm@\" + llvmMajor\n\t\tcase \"arm64\":\n\t\t\tprefix = \"/opt/homebrew/opt/llvm@\" + llvmMajor\n\t\tdefault:\n\t\t\treturn \"\" // very unlikely for now\n\t\t}\n\t\tpath := fmt.Sprintf(\"%s/lib/clang/%s\", prefix, llvmMajor)\n\t\t_, err := os.Stat(path + \"/include/stdint.h\")\n\t\tif err == nil {\n\t\t\treturn path\n\t\t}\n\t}\n\n\t// Could not find it.\n\treturn \"\"\n}\n"
  },
  {
    "path": "goenv/tools-builtin.go",
    "content": "//go:build byollvm\n\npackage goenv\n\nfunc init() {\n\thasBuiltinTools = true\n}\n"
  },
  {
    "path": "goenv/version.go",
    "content": "package goenv\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"runtime/debug\"\n\t\"strings\"\n)\n\n// Version of TinyGo.\n// Update this value before release of new version of software.\nconst version = \"0.40.1\"\n\n// Return TinyGo version, either in the form 0.30.0 or as a development version\n// (like 0.30.0-dev-abcd012).\nfunc Version() string {\n\tv := version\n\tif strings.HasSuffix(version, \"-dev\") {\n\t\tif hash := readGitHash(); hash != \"\" {\n\t\t\tv += \"-\" + hash\n\t\t}\n\t}\n\treturn v\n}\n\nfunc readGitHash() string {\n\tif info, ok := debug.ReadBuildInfo(); ok {\n\t\tfor _, setting := range info.Settings {\n\t\t\tif setting.Key == \"vcs.revision\" {\n\t\t\t\treturn setting.Value[:8]\n\t\t\t}\n\t\t}\n\t}\n\treturn \"\"\n}\n\n// GetGorootVersion returns the major and minor version for a given GOROOT path.\n// If the goroot cannot be determined, (0, 0) is returned.\nfunc GetGorootVersion() (major, minor int, err error) {\n\ts, err := GorootVersionString()\n\tif err != nil {\n\t\treturn 0, 0, err\n\t}\n\tmajor, minor, _, err = Parse(s)\n\treturn major, minor, err\n}\n\n// Parse parses the Go version (like \"go1.3.2\") in the parameter and return the\n// major, minor, and patch version: 1, 3, and 2 in this example.\n// If there is an error, (0, 0, 0) and an error will be returned.\nfunc Parse(version string) (major, minor, patch int, err error) {\n\tif strings.HasPrefix(version, \"devel \") {\n\t\tversion = strings.Split(strings.TrimPrefix(version, \"devel \"), version)[0]\n\t}\n\tif version == \"\" || version[:2] != \"go\" {\n\t\treturn 0, 0, 0, errors.New(\"could not parse Go version: version does not start with 'go' prefix\")\n\t}\n\n\tparts := strings.Split(version[2:], \".\")\n\tif len(parts) < 2 {\n\t\treturn 0, 0, 0, errors.New(\"could not parse Go version: version has less than two parts\")\n\t}\n\n\t// Ignore the errors, we don't really handle errors here anyway.\n\tvar trailing string\n\tn, err := fmt.Sscanf(version, \"go%d.%d.%d%s\", &major, &minor, &patch, &trailing)\n\tif n == 2 {\n\t\tn, err = fmt.Sscanf(version, \"go%d.%d%s\", &major, &minor, &trailing)\n\t}\n\tif n >= 2 && err == io.EOF {\n\t\t// Means there were no trailing characters (i.e., not an alpha/beta)\n\t\terr = nil\n\t}\n\tif err != nil {\n\t\treturn 0, 0, 0, fmt.Errorf(\"failed to parse version: %s\", err)\n\t}\n\n\treturn major, minor, patch, nil\n}\n\n// Compare compares two Go version strings.\n// The result will be 0 if a == b, -1 if a < b, and +1 if a > b.\n// If either a or b is not a valid Go version, it is treated as \"go0.0\"\n// and compared lexicographically.\n// See [Parse] for more information.\nfunc Compare(a, b string) int {\n\taMajor, aMinor, aPatch, _ := Parse(a)\n\tbMajor, bMinor, bPatch, _ := Parse(b)\n\tswitch {\n\tcase aMajor < bMajor:\n\t\treturn -1\n\tcase aMajor > bMajor:\n\t\treturn +1\n\tcase aMinor < bMinor:\n\t\treturn -1\n\tcase aMinor > bMinor:\n\t\treturn +1\n\tcase aPatch < bPatch:\n\t\treturn -1\n\tcase aPatch > bPatch:\n\t\treturn +1\n\tdefault:\n\t\treturn strings.Compare(a, b)\n\t}\n}\n\n// GorootVersionString returns the version string as reported by the Go\n// toolchain. It is usually of the form `go1.x.y` but can have some variations\n// (for beta releases, for example).\nfunc GorootVersionString() (string, error) {\n\terr := readGoEnvVars()\n\treturn goEnvVars.GOVERSION, err\n}\n"
  },
  {
    "path": "goenv/version_test.go",
    "content": "package goenv\n\nimport \"testing\"\n\nfunc TestParse(t *testing.T) {\n\ttests := []struct {\n\t\tv       string\n\t\tmajor   int\n\t\tminor   int\n\t\tpatch   int\n\t\twantErr bool\n\t}{\n\t\t{\"\", 0, 0, 0, true},\n\t\t{\"go\", 0, 0, 0, true},\n\t\t{\"go1\", 0, 0, 0, true},\n\t\t{\"go.0\", 0, 0, 0, true},\n\t\t{\"go1.0\", 1, 0, 0, false},\n\t\t{\"go1.1\", 1, 1, 0, false},\n\t\t{\"go1.23\", 1, 23, 0, false},\n\t\t{\"go1.23.5\", 1, 23, 5, false},\n\t\t{\"go1.23.5-rc6\", 1, 23, 5, false},\n\t\t{\"go2.0\", 2, 0, 0, false},\n\t\t{\"go2.0.15\", 2, 0, 15, false},\n\t\t{\"devel go1.24-f99f5da18f Thu Nov 14 22:29:26 2024 +0000 darwin/arm64\", 1, 24, 0, false},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.v, func(t *testing.T) {\n\t\t\tmajor, minor, patch, err := Parse(tt.v)\n\t\t\tif err == nil && tt.wantErr {\n\t\t\t\tt.Errorf(\"Parse(%q): expected err != nil\", tt.v)\n\t\t\t}\n\t\t\tif err != nil && !tt.wantErr {\n\t\t\t\tt.Errorf(\"Parse(%q): expected err == nil\", tt.v)\n\t\t\t}\n\t\t\tif major != tt.major || minor != tt.minor || patch != tt.patch {\n\t\t\t\tt.Errorf(\"Parse(%q): expected %d, %d, %d, nil; got %d, %d, %d, %v\",\n\t\t\t\t\ttt.v, tt.major, tt.minor, tt.patch, major, minor, patch, err)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestCompare(t *testing.T) {\n\ttests := []struct {\n\t\ta    string\n\t\tb    string\n\t\twant int\n\t}{\n\t\t{\"\", \"\", 0},\n\t\t{\"go0\", \"go0\", 0},\n\t\t{\"go0\", \"go1\", -1},\n\t\t{\"go1\", \"go0\", 1},\n\t\t{\"go1\", \"go2\", -1},\n\t\t{\"go2\", \"go1\", 1},\n\t\t{\"go1.1\", \"go1.2\", -1},\n\t\t{\"go1.2\", \"go1.1\", 1},\n\t\t{\"go1.1.0\", \"go1.2.0\", -1},\n\t\t{\"go1.2.0\", \"go1.1.0\", 1},\n\t\t{\"go1.2.0\", \"go2.3.0\", -1},\n\t\t{\"go1.23.2\", \"go1.23.10\", -1},\n\t\t{\"go0.1.22\", \"go1.23.101\", -1},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.a+\" \"+tt.b, func(t *testing.T) {\n\t\t\tgot := Compare(tt.a, tt.b)\n\t\t\tif got != tt.want {\n\t\t\t\tt.Errorf(\"Compare(%q, %q): expected %d; got %d\",\n\t\t\t\t\ttt.a, tt.b, tt.want, got)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "hooks/README.md",
    "content": "# Hooks for Docker Hub\n\nFiles in this directory are custom commands to be run during the different Docker Hub build phases.\n\nSee https://docs.docker.com/docker-hub/builds/advanced/#custom-build-phase-hooks\n"
  },
  {
    "path": "hooks/post_checkout",
    "content": "#!/bin/bash\n# Docker hub does a recursive clone, then checks the branch out,\n# so when a PR adds a submodule (or updates it), it fails.\ngit submodule update --init\n"
  },
  {
    "path": "internal/tools/go.mod",
    "content": "// TODO: remove this (by merging it into the top-level go.mod)\n// once the top level go.mod specifies a go new enough to make our version of misspell happy.\n\nmodule tools\n\ngo 1.21\n\nrequire (\n\tgithub.com/golangci/misspell v0.6.0\n\tgithub.com/mgechev/revive v1.3.9\n)\n\nrequire (\n\tgithub.com/BurntSushi/toml v1.4.0 // indirect\n\tgithub.com/chavacava/garif v0.1.0 // indirect\n\tgithub.com/fatih/color v1.17.0 // indirect\n\tgithub.com/fatih/structtag v1.2.0 // indirect\n\tgithub.com/hashicorp/go-version v1.7.0 // indirect\n\tgithub.com/mattn/go-colorable v0.1.13 // indirect\n\tgithub.com/mattn/go-isatty v0.0.20 // indirect\n\tgithub.com/mattn/go-runewidth v0.0.9 // indirect\n\tgithub.com/mgechev/dots v0.0.0-20210922191527-e955255bf517 // indirect\n\tgithub.com/mitchellh/go-homedir v1.1.0 // indirect\n\tgithub.com/olekukonko/tablewriter v0.0.5 // indirect\n\tgithub.com/pkg/errors v0.9.1 // indirect\n\tgithub.com/spf13/afero v1.11.0 // indirect\n\tgolang.org/x/sys v0.22.0 // indirect\n\tgolang.org/x/text v0.14.0 // indirect\n\tgolang.org/x/tools v0.23.0 // indirect\n)\n"
  },
  {
    "path": "internal/tools/go.sum",
    "content": "github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=\ngithub.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=\ngithub.com/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc=\ngithub.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=\ngithub.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=\ngithub.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=\ngithub.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=\ngithub.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs=\ngithub.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo=\ngithub.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=\ngithub.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=\ngithub.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=\ngithub.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=\ngithub.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=\ngithub.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=\ngithub.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=\ngithub.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=\ngithub.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=\ngithub.com/mgechev/dots v0.0.0-20210922191527-e955255bf517 h1:zpIH83+oKzcpryru8ceC6BxnoG8TBrhgAvRg8obzup0=\ngithub.com/mgechev/dots v0.0.0-20210922191527-e955255bf517/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg=\ngithub.com/mgechev/revive v1.3.9 h1:18Y3R4a2USSBF+QZKFQwVkBROUda7uoBlkEuBD+YD1A=\ngithub.com/mgechev/revive v1.3.9/go.mod h1:+uxEIr5UH0TjXWHTno3xh4u7eg6jDpXKzQccA9UGhHU=\ngithub.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=\ngithub.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=\ngithub.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=\ngithub.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=\ngithub.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=\ngithub.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=\ngithub.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=\ngithub.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=\ngithub.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=\ngithub.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=\ngithub.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=\ngithub.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=\ngolang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=\ngolang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=\ngolang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=\ngolang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=\ngolang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=\ngolang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=\ngopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\n"
  },
  {
    "path": "internal/tools/tools.go",
    "content": "//go:build tools\n\n// Install tools specified in go.mod.\n// See https://marcofranssen.nl/manage-go-tools-via-go-modules for idiom.\npackage tools\n\nimport (\n\t_ \"github.com/golangci/misspell\"\n\t_ \"github.com/mgechev/revive\"\n)\n\n//go:generate go install github.com/golangci/misspell/cmd/misspell\n//go:generate go install github.com/mgechev/revive\n"
  },
  {
    "path": "internal/wasm-tools/README.md",
    "content": "# wasm-tools directory\n\nThis directory has a separate `go.mod` file because the `wasm-tools-go` module requires Go 1.22, while TinyGo itself supports Go 1.19.\n\nWhen the minimum Go version for TinyGo is 1.22, this directory can be folded into `internal/tools` and the `go.mod` and `go.sum` files deleted.\n"
  },
  {
    "path": "internal/wasm-tools/go.mod",
    "content": "module github.com/tinygo-org/tinygo/internal/wasm-tools\n\ngo 1.23.0\n\nrequire (\n\tgo.bytecodealliance.org v0.6.2\n\tgo.bytecodealliance.org/cm v0.2.2\n)\n\nrequire (\n\tgithub.com/coreos/go-semver v0.3.1 // indirect\n\tgithub.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect\n\tgithub.com/klauspost/compress v1.18.0 // indirect\n\tgithub.com/opencontainers/go-digest v1.0.0 // indirect\n\tgithub.com/regclient/regclient v0.8.2 // indirect\n\tgithub.com/sirupsen/logrus v1.9.3 // indirect\n\tgithub.com/tetratelabs/wazero v1.9.0 // indirect\n\tgithub.com/ulikunitz/xz v0.5.12 // indirect\n\tgithub.com/urfave/cli/v3 v3.0.0-beta1 // indirect\n\tgolang.org/x/mod v0.24.0 // indirect\n\tgolang.org/x/sys v0.31.0 // indirect\n)\n"
  },
  {
    "path": "internal/wasm-tools/go.sum",
    "content": "github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=\ngithub.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4=\ngithub.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=\ngithub.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=\ngithub.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=\ngithub.com/olareg/olareg v0.1.1 h1:Ui7q93zjcoF+U9U71sgqgZWByDoZOpqHitUXEu2xV+g=\ngithub.com/olareg/olareg v0.1.1/go.mod h1:w8NP4SWrHHtxsFaUiv1lnCnYPm4sN1seCd2h7FK/dc0=\ngithub.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=\ngithub.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=\ngithub.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/regclient/regclient v0.8.2 h1:23BQ3jWgKYHHIXUhp/S9laVJDHDoOQaQCzXMJ4undVE=\ngithub.com/regclient/regclient v0.8.2/go.mod h1:uGyetv0o6VLyRDjtfeBqp/QBwRLJ3Hcn07/+8QbhNcM=\ngithub.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=\ngithub.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=\ngithub.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=\ngithub.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=\ngithub.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=\ngithub.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I=\ngithub.com/tetratelabs/wazero v1.9.0/go.mod h1:TSbcXCfFP0L2FGkRPxHphadXPjo1T6W+CseNNY7EkjM=\ngithub.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=\ngithub.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=\ngithub.com/urfave/cli/v3 v3.0.0-beta1 h1:6DTaaUarcM0wX7qj5Hcvs+5Dm3dyUTBbEwIWAjcw9Zg=\ngithub.com/urfave/cli/v3 v3.0.0-beta1/go.mod h1:FnIeEMYu+ko8zP1F9Ypr3xkZMIDqW3DR92yUtY39q1Y=\ngo.bytecodealliance.org v0.6.2 h1:Jy4u5DVmSkXgsnwojBhJ+AD/YsJsR3VzVnxF0xRCqTQ=\ngo.bytecodealliance.org v0.6.2/go.mod h1:gqjTJm0y9NSksG4py/lSjIQ/SNuIlOQ+hCIEPQwtJgA=\ngo.bytecodealliance.org/cm v0.2.2 h1:M9iHS6qs884mbQbIjtLX1OifgyPG9DuMs2iwz8G4WQA=\ngo.bytecodealliance.org/cm v0.2.2/go.mod h1:JD5vtVNZv7sBoQQkvBvAAVKJPhR/bqBH7yYXTItMfZI=\ngolang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=\ngolang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=\ngolang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=\ngolang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=\ngolang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=\ngolang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=\ngolang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY=\ngolang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=\ngopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\n"
  },
  {
    "path": "internal/wasm-tools/tools.go",
    "content": "//go:build tools\n\n// Install tools specified in go.mod.\n// See https://marcofranssen.nl/manage-go-tools-via-go-modules for idiom.\npackage tools\n\nimport (\n\t_ \"go.bytecodealliance.org/cm\"\n\t_ \"go.bytecodealliance.org/cmd/wit-bindgen-go\"\n)\n\n//go:generate go install go.bytecodealliance.org/cmd/wit-bindgen-go\n"
  },
  {
    "path": "interp/README.md",
    "content": "# Partial evaluation of initialization code in Go\n\nFor several reasons related to code size and memory consumption (see below), it\nis best to try to evaluate as much initialization code at compile time as\npossible and only run unknown expressions (e.g. external calls) at runtime. This\nis in practice a partial evaluator of the `runtime.initAll` function, which\ncalls each package initializer.\n\nThis package is a rewrite of a previous partial evaluator that worked\ndirectly on LLVM IR and used the module and LLVM constants as intermediate\nvalues. This newer version instead uses a mostly Go intermediate form. It\ncompiles functions and extracts relevant data first (compiler.go), then\nexecutes those functions (interpreter.go) in a memory space that can be\nrolled back per function (memory.go). This means that it is not necessary to\nscan functions to see whether they can be run at compile time, which was very\nerror prone. Instead it just tries to execute everything and if it hits\nsomething it cannot interpret (such as a store to memory-mapped I/O) it rolls\nback the execution of that function and runs the function at runtime instead.\nAll in all, this design provides several benefits:\n\n  * Much better error handling. By being able to revert to runtime execution\n    without the need for scanning functions, this version is able to\n    automatically work around many bugs in the previous implementation.\n  * More correct memory model. This is not inherent to the new design, but the\n    new design also made the memory model easier to reason about.\n  * Faster execution of initialization code. While it is not much faster for\n    normal interpretation (maybe 25% or so) due to the compilation overhead,\n    it should be a whole lot faster for loops as it doesn't have to call into\n    LLVM (via CGo) for every operation.\n\nAs mentioned, this partial evaluator comes in three parts: a compiler, an\ninterpreter, and a memory manager.\n\n## Compiler\n\nThe main task of the compiler is that it extracts all necessary data from\nevery instruction in a function so that when this instruction is interpreted,\nno additional CGo calls are necessary. This is not currently done for all\ninstructions (`runtime.alloc` is a notable exception), but at least it does\nso for the vast majority of instructions.\n\n## Interpreter\n\nThe interpreter runs an instruction just like it would if it were executed\n'for real'. The vast majority of instructions can be executed at compile\ntime. As indicated above, some instructions need to be executed at runtime\ninstead.\n\n## Memory\n\nMemory is represented as objects (the `object` type) that contains data that\nwill eventually be stored in a global and values (the `value` interface) that\ncan be worked with while running the interpreter. Values therefore are only\nused locally and are always passed by value (just like most LLVM constants)\nwhile objects represent the backing storage (like LLVM globals). Some values\nare pointer values, and point to an object.\n\nImportantly, this partial evaluator can roll back the execution of a\nfunction. This is implemented by creating a new memory view per function\nactivation, which makes sure that any change to a global (such as a store\ninstruction) is stored in the memory view. It creates a copy of the object\nand stores that in the memory view to be modified. Once the function has\nexecuted successfully, all these modified objects are then copied into the\nparent function, up to the root function invocation which (on successful\nexecution) writes the values back into the LLVM module. This way, function\ninvocations can be rolled back without leaving a trace.\n\nPointer values point to memory objects, but not to a particular memory\nobject. Every memory object is given an index, and pointers use that index to\nlook up the current active object for the pointer to load from or to copy\nwhen storing to it.\n\nRolling back a function should roll back everything, including the few\ninstructions emitted at runtime. This is done by treating instructions much\nlike memory objects and removing the created instructions when necessary.\n\n## Why is this necessary?\n\nA partial evaluator is hard to get right, so why go through all the trouble of\nwriting one?\n\nThe answer is that globals with initializers are much easier to optimize by\nLLVM than initialization code. Also, there are a few other benefits:\n\n  * Dead globals are trivial to optimize away.\n  * Constant globals are easier to detect. Remember that Go does not have global\n    constants in the same sense as that C has them. Constants are useful because\n    they can be propagated and provide some opportunities for other\n    optimizations (like dead code elimination when branching on the contents of\n    a global).\n  * Constants are much more efficient on microcontrollers, as they can be\n    allocated in flash instead of RAM.\n\nThe Go SSA package does not create constant initializers for globals.\nInstead, it emits initialization functions, so if you write the following:\n\n```go\nvar foo = []byte{1, 2, 3, 4}\n```\n\nIt would generate something like this:\n\n```go\nvar foo []byte\n\nfunc init() {\n    foo = make([]byte, 4)\n    foo[0] = 1\n    foo[1] = 2\n    foo[2] = 3\n    foo[3] = 4\n}\n```\n\nThis is of course hugely wasteful, it's much better to create `foo` as a\nglobal array instead of initializing it at runtime.\n\nFor more details, see [this section of the\ndocumentation](https://tinygo.org/compiler-internals/differences-from-go/).\n"
  },
  {
    "path": "interp/compiler.go",
    "content": "package interp\n\n// This file compiles the LLVM IR to a form that's easy to efficiently\n// interpret.\n\nimport (\n\t\"strings\"\n\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// A function is a compiled LLVM function, which means that interpreting it\n// avoids most CGo calls necessary. This is done in a separate step so the\n// result can be cached.\n// Functions are in SSA form, just like the LLVM version if it. The first block\n// (blocks[0]) is the entry block.\ntype function struct {\n\tllvmFn llvm.Value\n\tname   string       // precalculated llvmFn.Name()\n\tparams []llvm.Value // precalculated llvmFn.Params()\n\tblocks []*basicBlock\n\tlocals map[llvm.Value]int\n}\n\n// basicBlock represents a LLVM basic block and contains a slice of\n// instructions. The last instruction must be a terminator instruction.\ntype basicBlock struct {\n\tphiNodes     []instruction\n\tinstructions []instruction\n}\n\n// instruction is a precompiled LLVM IR instruction. The operands can be either\n// an already known value (such as literalValue or pointerValue) but can also be\n// the special localValue, which means that the value is a function parameter or\n// is produced by another instruction in the function. In that case, the\n// interpreter will replace the operand with that local value.\ntype instruction struct {\n\topcode     llvm.Opcode\n\tlocalIndex int\n\toperands   []value\n\tllvmInst   llvm.Value\n\tname       string\n}\n\n// String returns a nice human-readable version of this instruction.\nfunc (inst *instruction) String() string {\n\toperands := make([]string, len(inst.operands))\n\tfor i, op := range inst.operands {\n\t\toperands[i] = op.String()\n\t}\n\n\tname := \"\"\n\tif int(inst.opcode) < len(instructionNameMap) {\n\t\tname = instructionNameMap[inst.opcode]\n\t}\n\tif name == \"\" {\n\t\tname = \"<unknown op>\"\n\t}\n\treturn name + \" \" + strings.Join(operands, \" \")\n}\n\n// compileFunction compiles a given LLVM function to an easier to interpret\n// version of the function. As far as possible, all operands are preprocessed so\n// that the interpreter doesn't have to call into LLVM.\nfunc (r *runner) compileFunction(llvmFn llvm.Value) *function {\n\tfn := &function{\n\t\tllvmFn: llvmFn,\n\t\tname:   llvmFn.Name(),\n\t\tparams: llvmFn.Params(),\n\t\tlocals: make(map[llvm.Value]int),\n\t}\n\tif llvmFn.IsDeclaration() {\n\t\t// Nothing to do.\n\t\treturn fn\n\t}\n\n\tfor i, param := range fn.params {\n\t\tfn.locals[param] = i\n\t}\n\n\t// Make a map of all the blocks, to quickly find the block number for a\n\t// given branch instruction.\n\tblockIndices := make(map[llvm.Value]int)\n\tfor llvmBB := llvmFn.FirstBasicBlock(); !llvmBB.IsNil(); llvmBB = llvm.NextBasicBlock(llvmBB) {\n\t\tindex := len(blockIndices)\n\t\tblockIndices[llvmBB.AsValue()] = index\n\t}\n\n\t// Compile every block.\n\tfor llvmBB := llvmFn.FirstBasicBlock(); !llvmBB.IsNil(); llvmBB = llvm.NextBasicBlock(llvmBB) {\n\t\tbb := &basicBlock{}\n\t\tfn.blocks = append(fn.blocks, bb)\n\n\t\t// Compile every instruction in the block.\n\t\tfor llvmInst := llvmBB.FirstInstruction(); !llvmInst.IsNil(); llvmInst = llvm.NextInstruction(llvmInst) {\n\t\t\t// Create instruction skeleton.\n\t\t\topcode := llvmInst.InstructionOpcode()\n\t\t\tinst := instruction{\n\t\t\t\topcode:     opcode,\n\t\t\t\tlocalIndex: len(fn.locals),\n\t\t\t\tllvmInst:   llvmInst,\n\t\t\t}\n\t\t\tfn.locals[llvmInst] = len(fn.locals)\n\n\t\t\t// Add operands specific for this instruction.\n\t\t\tswitch opcode {\n\t\t\tcase llvm.Ret:\n\t\t\t\t// Return instruction, which can either be a `ret void` (no\n\t\t\t\t// return value) or return a value.\n\t\t\t\tnumOperands := llvmInst.OperandsCount()\n\t\t\t\tif numOperands != 0 {\n\t\t\t\t\tinst.operands = []value{\n\t\t\t\t\t\tr.getValue(llvmInst.Operand(0)),\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tcase llvm.Br:\n\t\t\t\t// Branch instruction. Can be either a conditional branch (with\n\t\t\t\t// 3 operands) or unconditional branch (with just one basic\n\t\t\t\t// block operand).\n\t\t\t\tnumOperands := llvmInst.OperandsCount()\n\t\t\t\tswitch numOperands {\n\t\t\t\tcase 3:\n\t\t\t\t\t// Conditional jump to one of two blocks. Comparable to an\n\t\t\t\t\t// if/else in procedural languages.\n\t\t\t\t\tthenBB := llvmInst.Operand(2)\n\t\t\t\t\telseBB := llvmInst.Operand(1)\n\t\t\t\t\tinst.operands = []value{\n\t\t\t\t\t\tr.getValue(llvmInst.Operand(0)),\n\t\t\t\t\t\tliteralValue{uint32(blockIndices[thenBB])},\n\t\t\t\t\t\tliteralValue{uint32(blockIndices[elseBB])},\n\t\t\t\t\t}\n\t\t\t\tcase 1:\n\t\t\t\t\t// Unconditional jump to a target basic block. Comparable to\n\t\t\t\t\t// a jump in C and Go.\n\t\t\t\t\tjumpBB := llvmInst.Operand(0)\n\t\t\t\t\tinst.operands = []value{\n\t\t\t\t\t\tliteralValue{uint32(blockIndices[jumpBB])},\n\t\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\tpanic(\"unknown number of operands\")\n\t\t\t\t}\n\t\t\tcase llvm.Switch:\n\t\t\t\t// A switch is an array of (value, label) pairs, of which the\n\t\t\t\t// first one indicates the to-switch value and the default\n\t\t\t\t// label.\n\t\t\t\tnumOperands := llvmInst.OperandsCount()\n\t\t\t\tfor i := 0; i < numOperands; i += 2 {\n\t\t\t\t\tinst.operands = append(inst.operands, r.getValue(llvmInst.Operand(i)))\n\t\t\t\t\tinst.operands = append(inst.operands, literalValue{uint32(blockIndices[llvmInst.Operand(i+1)])})\n\t\t\t\t}\n\t\t\tcase llvm.PHI:\n\t\t\t\tinst.name = llvmInst.Name()\n\t\t\t\tincomingCount := inst.llvmInst.IncomingCount()\n\t\t\t\tfor i := 0; i < incomingCount; i++ {\n\t\t\t\t\tincomingBB := inst.llvmInst.IncomingBlock(i)\n\t\t\t\t\tincomingValue := inst.llvmInst.IncomingValue(i)\n\t\t\t\t\tinst.operands = append(inst.operands,\n\t\t\t\t\t\tliteralValue{uint32(blockIndices[incomingBB.AsValue()])},\n\t\t\t\t\t\tr.getValue(incomingValue),\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\tcase llvm.Select:\n\t\t\t\t// Select is a special instruction that is much like a ternary\n\t\t\t\t// operator. It produces operand 1 or 2 based on the boolean\n\t\t\t\t// that is operand 0.\n\t\t\t\tinst.name = llvmInst.Name()\n\t\t\t\tinst.operands = []value{\n\t\t\t\t\tr.getValue(llvmInst.Operand(0)),\n\t\t\t\t\tr.getValue(llvmInst.Operand(1)),\n\t\t\t\t\tr.getValue(llvmInst.Operand(2)),\n\t\t\t\t}\n\t\t\tcase llvm.Call:\n\t\t\t\t// Call is a regular function call but could also be a runtime\n\t\t\t\t// intrinsic. Some runtime intrinsics are treated specially by\n\t\t\t\t// the interpreter, such as runtime.alloc. We don't\n\t\t\t\t// differentiate between them here because these calls may also\n\t\t\t\t// need to be run at runtime, in which case they should all be\n\t\t\t\t// created in the same way.\n\t\t\t\tllvmCalledValue := llvmInst.CalledValue()\n\t\t\t\tif !llvmCalledValue.IsAFunction().IsNil() {\n\t\t\t\t\tname := llvmCalledValue.Name()\n\t\t\t\t\tif name == \"llvm.dbg.value\" || strings.HasPrefix(name, \"llvm.lifetime.\") {\n\t\t\t\t\t\t// These intrinsics should not be interpreted, they are not\n\t\t\t\t\t\t// relevant to the execution of this function.\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tinst.name = llvmInst.Name()\n\t\t\t\tnumOperands := llvmInst.OperandsCount()\n\t\t\t\tinst.operands = append(inst.operands, r.getValue(llvmCalledValue))\n\t\t\t\tfor i := 0; i < numOperands-1; i++ {\n\t\t\t\t\tinst.operands = append(inst.operands, r.getValue(llvmInst.Operand(i)))\n\t\t\t\t}\n\t\t\tcase llvm.Load:\n\t\t\t\t// Load instruction. The interpreter will load from the\n\t\t\t\t// appropriate memory view.\n\t\t\t\t// Also provide the memory size to be loaded, which is necessary\n\t\t\t\t// with a lack of type information.\n\t\t\t\tinst.name = llvmInst.Name()\n\t\t\t\tinst.operands = []value{\n\t\t\t\t\tr.getValue(llvmInst.Operand(0)),\n\t\t\t\t\tliteralValue{r.targetData.TypeAllocSize(llvmInst.Type())},\n\t\t\t\t}\n\t\t\tcase llvm.Store:\n\t\t\t\t// Store instruction. The interpreter will create a new object\n\t\t\t\t// in the memory view of the function invocation and store to\n\t\t\t\t// that, to make it possible to roll back this store.\n\t\t\t\tinst.operands = []value{\n\t\t\t\t\tr.getValue(llvmInst.Operand(0)),\n\t\t\t\t\tr.getValue(llvmInst.Operand(1)),\n\t\t\t\t}\n\t\t\tcase llvm.Alloca:\n\t\t\t\t// Alloca allocates stack space for local variables.\n\t\t\t\tnumElements := r.getValue(inst.llvmInst.Operand(0)).(literalValue).value.(uint32)\n\t\t\t\telementSize := r.targetData.TypeAllocSize(inst.llvmInst.AllocatedType())\n\t\t\t\tinst.operands = []value{\n\t\t\t\t\tliteralValue{elementSize * uint64(numElements)},\n\t\t\t\t}\n\t\t\tcase llvm.GetElementPtr:\n\t\t\t\t// GetElementPtr does pointer arithmetic.\n\t\t\t\tinst.name = llvmInst.Name()\n\t\t\t\tptr := llvmInst.Operand(0)\n\t\t\t\tn := llvmInst.OperandsCount()\n\t\t\t\telementType := llvmInst.GEPSourceElementType()\n\t\t\t\t// gep: [source ptr, dest value size, pairs of indices...]\n\t\t\t\tinst.operands = []value{\n\t\t\t\t\tr.getValue(ptr),\n\t\t\t\t\tr.getValue(llvmInst.Operand(1)),\n\t\t\t\t\tliteralValue{r.targetData.TypeAllocSize(elementType)},\n\t\t\t\t}\n\t\t\t\tfor i := 2; i < n; i++ {\n\t\t\t\t\toperand := r.getValue(llvmInst.Operand(i))\n\t\t\t\t\tswitch elementType.TypeKind() {\n\t\t\t\t\tcase llvm.StructTypeKind:\n\t\t\t\t\t\tindex := operand.(literalValue).value.(uint32)\n\t\t\t\t\t\telementOffset := r.targetData.ElementOffset(elementType, int(index))\n\t\t\t\t\t\t// Encode operands in a special way. The elementOffset\n\t\t\t\t\t\t// is just the offset in bytes. The elementSize is a\n\t\t\t\t\t\t// negative number (when cast to a int64) by flipping\n\t\t\t\t\t\t// all the bits. This allows the interpreter to detect\n\t\t\t\t\t\t// this is a struct field and that it should not\n\t\t\t\t\t\t// multiply it with the elementOffset to get the offset.\n\t\t\t\t\t\t// It is important for the interpreter to know the\n\t\t\t\t\t\t// struct field index for when the GEP must be done at\n\t\t\t\t\t\t// runtime.\n\t\t\t\t\t\tinst.operands = append(inst.operands, literalValue{elementOffset}, literalValue{^uint64(index)})\n\t\t\t\t\t\telementType = elementType.StructElementTypes()[index]\n\t\t\t\t\tcase llvm.ArrayTypeKind:\n\t\t\t\t\t\telementType = elementType.ElementType()\n\t\t\t\t\t\telementSize := r.targetData.TypeAllocSize(elementType)\n\t\t\t\t\t\telementSizeOperand := literalValue{elementSize}\n\t\t\t\t\t\t// Add operand * elementSizeOperand bytes to the pointer.\n\t\t\t\t\t\tinst.operands = append(inst.operands, operand, elementSizeOperand)\n\t\t\t\t\tdefault:\n\t\t\t\t\t\t// This should be unreachable.\n\t\t\t\t\t\tpanic(\"unknown type: \" + elementType.String())\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tcase llvm.BitCast, llvm.IntToPtr, llvm.PtrToInt:\n\t\t\t\t// Bitcasts are usually used to cast a pointer from one type to\n\t\t\t\t// another leaving the pointer itself intact.\n\t\t\t\tinst.name = llvmInst.Name()\n\t\t\t\tinst.operands = []value{\n\t\t\t\t\tr.getValue(llvmInst.Operand(0)),\n\t\t\t\t}\n\t\t\tcase llvm.ExtractValue:\n\t\t\t\tinst.name = llvmInst.Name()\n\t\t\t\tagg := llvmInst.Operand(0)\n\t\t\t\tvar offset uint64\n\t\t\t\tindexingType := agg.Type()\n\t\t\t\tfor _, index := range inst.llvmInst.Indices() {\n\t\t\t\t\tswitch indexingType.TypeKind() {\n\t\t\t\t\tcase llvm.StructTypeKind:\n\t\t\t\t\t\toffset += r.targetData.ElementOffset(indexingType, int(index))\n\t\t\t\t\t\tindexingType = indexingType.StructElementTypes()[index]\n\t\t\t\t\tcase llvm.ArrayTypeKind:\n\t\t\t\t\t\tindexingType = indexingType.ElementType()\n\t\t\t\t\t\telementSize := r.targetData.TypeAllocSize(indexingType)\n\t\t\t\t\t\toffset += elementSize * uint64(index)\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tpanic(\"unknown type kind\") // unreachable\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tsize := r.targetData.TypeAllocSize(inst.llvmInst.Type())\n\t\t\t\t// extractvalue [agg, byteOffset, byteSize]\n\t\t\t\tinst.operands = []value{\n\t\t\t\t\tr.getValue(agg),\n\t\t\t\t\tliteralValue{offset},\n\t\t\t\t\tliteralValue{size},\n\t\t\t\t}\n\t\t\tcase llvm.InsertValue:\n\t\t\t\tinst.name = llvmInst.Name()\n\t\t\t\tagg := llvmInst.Operand(0)\n\t\t\t\tvar offset uint64\n\t\t\t\tindexingType := agg.Type()\n\t\t\t\tfor _, index := range inst.llvmInst.Indices() {\n\t\t\t\t\tswitch indexingType.TypeKind() {\n\t\t\t\t\tcase llvm.StructTypeKind:\n\t\t\t\t\t\toffset += r.targetData.ElementOffset(indexingType, int(index))\n\t\t\t\t\t\tindexingType = indexingType.StructElementTypes()[index]\n\t\t\t\t\tcase llvm.ArrayTypeKind:\n\t\t\t\t\t\tindexingType = indexingType.ElementType()\n\t\t\t\t\t\telementSize := r.targetData.TypeAllocSize(indexingType)\n\t\t\t\t\t\toffset += elementSize * uint64(index)\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tpanic(\"unknown type kind\") // unreachable\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// insertvalue [agg, elt, byteOffset]\n\t\t\t\tinst.operands = []value{\n\t\t\t\t\tr.getValue(agg),\n\t\t\t\t\tr.getValue(llvmInst.Operand(1)),\n\t\t\t\t\tliteralValue{offset},\n\t\t\t\t}\n\t\t\tcase llvm.ICmp:\n\t\t\t\tinst.name = llvmInst.Name()\n\t\t\t\tinst.operands = []value{\n\t\t\t\t\tr.getValue(llvmInst.Operand(0)),\n\t\t\t\t\tr.getValue(llvmInst.Operand(1)),\n\t\t\t\t\tliteralValue{uint8(llvmInst.IntPredicate())},\n\t\t\t\t}\n\t\t\tcase llvm.FCmp:\n\t\t\t\tinst.name = llvmInst.Name()\n\t\t\t\tinst.operands = []value{\n\t\t\t\t\tr.getValue(llvmInst.Operand(0)),\n\t\t\t\t\tr.getValue(llvmInst.Operand(1)),\n\t\t\t\t\tliteralValue{uint8(llvmInst.FloatPredicate())},\n\t\t\t\t}\n\t\t\tcase llvm.Add, llvm.Sub, llvm.Mul, llvm.UDiv, llvm.SDiv, llvm.URem, llvm.SRem, llvm.Shl, llvm.LShr, llvm.AShr, llvm.And, llvm.Or, llvm.Xor:\n\t\t\t\t// Integer binary operations.\n\t\t\t\tinst.name = llvmInst.Name()\n\t\t\t\tinst.operands = []value{\n\t\t\t\t\tr.getValue(llvmInst.Operand(0)),\n\t\t\t\t\tr.getValue(llvmInst.Operand(1)),\n\t\t\t\t}\n\t\t\tcase llvm.SExt, llvm.ZExt, llvm.Trunc:\n\t\t\t\t// Extend or shrink an integer size.\n\t\t\t\t// No sign extension going on so easy to do.\n\t\t\t\t// zext: [value, bitwidth]\n\t\t\t\t// trunc: [value, bitwidth]\n\t\t\t\tinst.name = llvmInst.Name()\n\t\t\t\tinst.operands = []value{\n\t\t\t\t\tr.getValue(llvmInst.Operand(0)),\n\t\t\t\t\tliteralValue{uint64(llvmInst.Type().IntTypeWidth())},\n\t\t\t\t}\n\t\t\tcase llvm.SIToFP, llvm.UIToFP:\n\t\t\t\t// Convert an integer to a floating point instruction.\n\t\t\t\t// opcode: [value, bitwidth]\n\t\t\t\tinst.name = llvmInst.Name()\n\t\t\t\tinst.operands = []value{\n\t\t\t\t\tr.getValue(llvmInst.Operand(0)),\n\t\t\t\t\tliteralValue{uint64(r.targetData.TypeAllocSize(llvmInst.Type()) * 8)},\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\t// Unknown instruction, which is already set in inst.opcode so\n\t\t\t\t// is detectable.\n\t\t\t\t// This error is handled when actually trying to interpret this\n\t\t\t\t// instruction (to not trigger on code that won't be executed).\n\t\t\t}\n\t\t\tif inst.opcode == llvm.PHI {\n\t\t\t\t// PHI nodes need to be treated specially, see the comment in\n\t\t\t\t// interpreter.go for an explanation.\n\t\t\t\tbb.phiNodes = append(bb.phiNodes, inst)\n\t\t\t} else {\n\t\t\t\tbb.instructions = append(bb.instructions, inst)\n\t\t\t}\n\t\t}\n\t}\n\treturn fn\n}\n\n// instructionNameMap maps from instruction opcodes to instruction names. This\n// can be useful for debug logging.\nvar instructionNameMap = [...]string{\n\tllvm.Ret:         \"ret\",\n\tllvm.Br:          \"br\",\n\tllvm.Switch:      \"switch\",\n\tllvm.IndirectBr:  \"indirectbr\",\n\tllvm.Invoke:      \"invoke\",\n\tllvm.Unreachable: \"unreachable\",\n\n\t// Standard Binary Operators\n\tllvm.Add:  \"add\",\n\tllvm.FAdd: \"fadd\",\n\tllvm.Sub:  \"sub\",\n\tllvm.FSub: \"fsub\",\n\tllvm.Mul:  \"mul\",\n\tllvm.FMul: \"fmul\",\n\tllvm.UDiv: \"udiv\",\n\tllvm.SDiv: \"sdiv\",\n\tllvm.FDiv: \"fdiv\",\n\tllvm.URem: \"urem\",\n\tllvm.SRem: \"srem\",\n\tllvm.FRem: \"frem\",\n\n\t// Logical Operators\n\tllvm.Shl:  \"shl\",\n\tllvm.LShr: \"lshr\",\n\tllvm.AShr: \"ashr\",\n\tllvm.And:  \"and\",\n\tllvm.Or:   \"or\",\n\tllvm.Xor:  \"xor\",\n\n\t// Memory Operators\n\tllvm.Alloca:        \"alloca\",\n\tllvm.Load:          \"load\",\n\tllvm.Store:         \"store\",\n\tllvm.GetElementPtr: \"getelementptr\",\n\n\t// Cast Operators\n\tllvm.Trunc:    \"trunc\",\n\tllvm.ZExt:     \"zext\",\n\tllvm.SExt:     \"sext\",\n\tllvm.FPToUI:   \"fptoui\",\n\tllvm.FPToSI:   \"fptosi\",\n\tllvm.UIToFP:   \"uitofp\",\n\tllvm.SIToFP:   \"sitofp\",\n\tllvm.FPTrunc:  \"fptrunc\",\n\tllvm.FPExt:    \"fpext\",\n\tllvm.PtrToInt: \"ptrtoint\",\n\tllvm.IntToPtr: \"inttoptr\",\n\tllvm.BitCast:  \"bitcast\",\n\n\t// Other Operators\n\tllvm.ICmp:           \"icmp\",\n\tllvm.FCmp:           \"fcmp\",\n\tllvm.PHI:            \"phi\",\n\tllvm.Call:           \"call\",\n\tllvm.Select:         \"select\",\n\tllvm.VAArg:          \"vaarg\",\n\tllvm.ExtractElement: \"extractelement\",\n\tllvm.InsertElement:  \"insertelement\",\n\tllvm.ShuffleVector:  \"shufflevector\",\n\tllvm.ExtractValue:   \"extractvalue\",\n\tllvm.InsertValue:    \"insertvalue\",\n}\n"
  },
  {
    "path": "interp/errors.go",
    "content": "package interp\n\n// This file provides useful types for errors encountered during IR evaluation.\n\nimport (\n\t\"errors\"\n\t\"go/scanner\"\n\t\"go/token\"\n\t\"path/filepath\"\n\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// These errors are expected during normal execution and can be recovered from\n// by running the affected function at runtime instead of compile time.\nvar (\n\terrIntegerAsPointer       = errors.New(\"interp: trying to use an integer as a pointer (memory-mapped I/O?)\")\n\terrUnsupportedInst        = errors.New(\"interp: unsupported instruction\")\n\terrUnsupportedRuntimeInst = errors.New(\"interp: unsupported instruction (to be emitted at runtime)\")\n\terrMapAlreadyCreated      = errors.New(\"interp: map already created\")\n\terrLoopUnrolled           = errors.New(\"interp: loop unrolled\")\n)\n\n// This is one of the errors that can be returned from toLLVMValue when the\n// passed type does not fit the data to serialize. It is recoverable by\n// serializing without a type (using rawValue.rawLLVMValue).\nvar errInvalidPtrToIntSize = errors.New(\"interp: ptrtoint integer size does not equal pointer size\")\n\nfunc isRecoverableError(err error) bool {\n\treturn err == errIntegerAsPointer || err == errUnsupportedInst ||\n\t\terr == errUnsupportedRuntimeInst || err == errMapAlreadyCreated ||\n\t\terr == errLoopUnrolled\n}\n\n// ErrorLine is one line in a traceback. The position may be missing.\ntype ErrorLine struct {\n\tPos  token.Position\n\tInst string\n}\n\n// Error encapsulates compile-time interpretation errors with an associated\n// import path. The errors may not have a precise location attached.\ntype Error struct {\n\tImportPath string\n\tInst       string\n\tPos        token.Position\n\tErr        error\n\tTraceback  []ErrorLine\n}\n\n// Error returns the string of the first error in the list of errors.\nfunc (e *Error) Error() string {\n\treturn e.Pos.String() + \": \" + e.Err.Error()\n}\n\n// errorAt returns an error value for the currently interpreted package at the\n// location of the instruction. The location information may not be complete as\n// it depends on debug information in the IR.\nfunc (r *runner) errorAt(inst instruction, err error) *Error {\n\tpos := getPosition(inst.llvmInst)\n\treturn &Error{\n\t\tImportPath: r.pkgName,\n\t\tInst:       inst.llvmInst.String(),\n\t\tPos:        pos,\n\t\tErr:        err,\n\t\tTraceback:  []ErrorLine{{pos, inst.llvmInst.String()}},\n\t}\n}\n\n// errorAt returns an error value at the location of the instruction.\n// The location information may not be complete as it depends on debug\n// information in the IR.\nfunc errorAt(inst llvm.Value, msg string) scanner.Error {\n\treturn scanner.Error{\n\t\tPos: getPosition(inst),\n\t\tMsg: msg,\n\t}\n}\n\n// getPosition returns the position information for the given instruction, as\n// far as it is available.\nfunc getPosition(inst llvm.Value) token.Position {\n\tif inst.IsAInstruction().IsNil() {\n\t\treturn token.Position{}\n\t}\n\tloc := inst.InstructionDebugLoc()\n\tif loc.IsNil() {\n\t\treturn token.Position{}\n\t}\n\tfile := loc.LocationScope().ScopeFile()\n\treturn token.Position{\n\t\tFilename: filepath.Join(file.FileDirectory(), file.FileFilename()),\n\t\tLine:     int(loc.LocationLine()),\n\t\tColumn:   int(loc.LocationColumn()),\n\t}\n}\n"
  },
  {
    "path": "interp/interp.go",
    "content": "// Package interp is a partial evaluator of code run at package init time. See\n// the README in this package for details.\npackage interp\n\nimport (\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/tinygo-org/tinygo/compiler/llvmutil\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// Enable extra checks, which should be disabled by default.\n// This may help track down bugs by adding a few more sanity checks.\nconst checks = true\n\n// runner contains all state related to one interp run.\ntype runner struct {\n\tmod           llvm.Module\n\ttargetData    llvm.TargetData\n\tbuilder       llvm.Builder\n\tpointerSize   uint32                   // cached pointer size from the TargetData\n\tdataPtrType   llvm.Type                // often used type so created in advance\n\tuintptrType   llvm.Type                // equivalent to uintptr in Go\n\tmaxAlign      int                      // maximum alignment of an object, alignment of runtime.alloc() result\n\tbyteOrder     binary.ByteOrder         // big-endian or little-endian\n\tdebug         bool                     // log debug messages\n\tpkgName       string                   // package name of the currently executing package\n\tfunctionCache map[llvm.Value]*function // cache of compiled functions\n\tobjects       []object                 // slice of objects in memory\n\tglobals       map[llvm.Value]int       // map from global to index in objects slice\n\tstart         time.Time\n\ttimeout       time.Duration\n\tcallsExecuted uint64\n}\n\nfunc newRunner(mod llvm.Module, timeout time.Duration, debug bool) *runner {\n\tr := runner{\n\t\tmod:           mod,\n\t\ttargetData:    llvm.NewTargetData(mod.DataLayout()),\n\t\tbyteOrder:     llvmutil.ByteOrder(mod.Target()),\n\t\tdebug:         debug,\n\t\tfunctionCache: make(map[llvm.Value]*function),\n\t\tobjects:       []object{{}},\n\t\tglobals:       make(map[llvm.Value]int),\n\t\tstart:         time.Now(),\n\t\ttimeout:       timeout,\n\t}\n\tr.pointerSize = uint32(r.targetData.PointerSize())\n\tr.dataPtrType = llvm.PointerType(mod.Context().Int8Type(), 0)\n\tr.uintptrType = mod.Context().IntType(r.targetData.PointerSize() * 8)\n\tr.maxAlign = r.targetData.PrefTypeAlignment(r.dataPtrType) // assume pointers are maximally aligned (this is not always the case)\n\treturn &r\n}\n\n// Dispose deallocates all allocated LLVM resources.\nfunc (r *runner) dispose() {\n\tr.targetData.Dispose()\n\tr.targetData = llvm.TargetData{}\n}\n\n// Run evaluates runtime.initAll function as much as possible at compile time.\n// Set debug to true if it should print output while running.\nfunc Run(mod llvm.Module, timeout time.Duration, debug bool) error {\n\tr := newRunner(mod, timeout, debug)\n\tdefer r.dispose()\n\n\tinitAll := mod.NamedFunction(\"runtime.initAll\")\n\tbb := initAll.EntryBasicBlock()\n\n\t// Create a builder, to insert instructions that could not be evaluated at\n\t// compile time.\n\tr.builder = mod.Context().NewBuilder()\n\tdefer r.builder.Dispose()\n\n\t// Create a dummy alloca in the entry block that we can set the insert point\n\t// to. This is necessary because otherwise we might be removing the\n\t// instruction (init call) that we are removing after successful\n\t// interpretation.\n\tr.builder.SetInsertPointBefore(bb.FirstInstruction())\n\tdummy := r.builder.CreateAlloca(r.mod.Context().Int8Type(), \"dummy\")\n\tr.builder.SetInsertPointBefore(dummy)\n\tdefer dummy.EraseFromParentAsInstruction()\n\n\t// Get a list if init calls. A runtime.initAll might look something like this:\n\t// func initAll() {\n\t//     unsafe.init()\n\t//     machine.init()\n\t//     runtime.init()\n\t// }\n\t// This function gets a list of these call instructions.\n\tvar initCalls []llvm.Value\n\tfor inst := bb.FirstInstruction(); !inst.IsNil(); inst = llvm.NextInstruction(inst) {\n\t\tif inst == dummy {\n\t\t\tcontinue\n\t\t}\n\t\tif !inst.IsAReturnInst().IsNil() {\n\t\t\tbreak // ret void\n\t\t}\n\t\tif inst.IsACallInst().IsNil() || inst.CalledValue().IsAFunction().IsNil() {\n\t\t\treturn errorAt(inst, \"interp: expected all instructions in \"+initAll.Name()+\" to be direct calls\")\n\t\t}\n\t\tinitCalls = append(initCalls, inst)\n\t}\n\n\t// Run initializers for each package. Once the package initializer is\n\t// finished, the call to the package initializer can be removed.\n\tfor _, call := range initCalls {\n\t\tinitName := call.CalledValue().Name()\n\t\tif !strings.HasSuffix(initName, \".init\") {\n\t\t\treturn errorAt(call, \"interp: expected all instructions in \"+initAll.Name()+\" to be *.init() calls\")\n\t\t}\n\t\tr.pkgName = initName[:len(initName)-len(\".init\")]\n\t\tfn := call.CalledValue()\n\t\tif r.debug {\n\t\t\tfmt.Fprintln(os.Stderr, \"call:\", fn.Name())\n\t\t}\n\t\t_, mem, callErr := r.run(r.getFunction(fn), nil, nil, \"    \")\n\t\tcall.EraseFromParentAsInstruction()\n\t\tif callErr != nil {\n\t\t\tif isRecoverableError(callErr.Err) {\n\t\t\t\tif r.debug {\n\t\t\t\t\tfmt.Fprintln(os.Stderr, \"not interpreting\", r.pkgName, \"because of error:\", callErr.Error())\n\t\t\t\t}\n\t\t\t\t// Remove instructions that were created as part of interpreting\n\t\t\t\t// the package.\n\t\t\t\tmem.revert()\n\t\t\t\t// Create a call to the package initializer (which was\n\t\t\t\t// previously deleted).\n\t\t\t\ti8undef := llvm.Undef(r.dataPtrType)\n\t\t\t\tr.builder.CreateCall(fn.GlobalValueType(), fn, []llvm.Value{i8undef}, \"\")\n\t\t\t\t// Make sure that any globals touched by the package\n\t\t\t\t// initializer, won't be accessed by later package initializers.\n\t\t\t\terr := r.markExternalLoad(fn)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"failed to interpret package %s: %w\", r.pkgName, err)\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn callErr\n\t\t}\n\t\tfor index, obj := range mem.objects {\n\t\t\tr.objects[index] = obj\n\t\t}\n\t}\n\tr.pkgName = \"\"\n\n\t// Update all global variables in the LLVM module.\n\tmem := memoryView{r: r}\n\tfor i, obj := range r.objects {\n\t\tif obj.llvmGlobal.IsNil() {\n\t\t\tcontinue\n\t\t}\n\t\tif obj.buffer == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif obj.constant {\n\t\t\tcontinue // constant buffers can't have been modified\n\t\t}\n\t\tinitializer, err := obj.buffer.toLLVMValue(obj.llvmGlobal.GlobalValueType(), &mem)\n\t\tif err == errInvalidPtrToIntSize {\n\t\t\t// This can happen when a previous interp run did not have the\n\t\t\t// correct LLVM type for a global and made something up. In that\n\t\t\t// case, some fields could be written out as a series of (null)\n\t\t\t// bytes even though they actually contain a pointer value.\n\t\t\t// As a fallback, use asRawValue to get something of the correct\n\t\t\t// memory layout.\n\t\t\tinitializer, err := obj.buffer.asRawValue(r).rawLLVMValue(&mem)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tinitializerType := initializer.Type()\n\t\t\tnewGlobal := llvm.AddGlobal(mod, initializerType, obj.llvmGlobal.Name()+\".tmp\")\n\t\t\tnewGlobal.SetInitializer(initializer)\n\t\t\tnewGlobal.SetLinkage(obj.llvmGlobal.Linkage())\n\t\t\tnewGlobal.SetAlignment(obj.llvmGlobal.Alignment())\n\t\t\t// TODO: copy debug info, unnamed_addr, ...\n\t\t\tobj.llvmGlobal.ReplaceAllUsesWith(newGlobal)\n\t\t\tname := obj.llvmGlobal.Name()\n\t\t\tobj.llvmGlobal.EraseFromParentAsGlobal()\n\t\t\tnewGlobal.SetName(name)\n\n\t\t\t// Update interp-internal references.\n\t\t\tdelete(r.globals, obj.llvmGlobal)\n\t\t\tobj.llvmGlobal = newGlobal\n\t\t\tr.globals[newGlobal] = i\n\t\t\tr.objects[i] = obj\n\t\t\tcontinue\n\t\t}\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif checks && initializer.Type() != obj.llvmGlobal.GlobalValueType() {\n\t\t\tpanic(\"initializer type mismatch\")\n\t\t}\n\t\tobj.llvmGlobal.SetInitializer(initializer)\n\t}\n\n\treturn nil\n}\n\n// RunFunc evaluates a single package initializer at compile time.\n// Set debug to true if it should print output while running.\nfunc RunFunc(fn llvm.Value, timeout time.Duration, debug bool) error {\n\t// Create and initialize *runner object.\n\tmod := fn.GlobalParent()\n\tr := newRunner(mod, timeout, debug)\n\tdefer r.dispose()\n\tinitName := fn.Name()\n\tif !strings.HasSuffix(initName, \".init\") {\n\t\treturn errorAt(fn, \"interp: unexpected function name (expected *.init)\")\n\t}\n\tr.pkgName = initName[:len(initName)-len(\".init\")]\n\n\t// Create new function with the interp result.\n\tnewFn := llvm.AddFunction(mod, fn.Name()+\".tmp\", fn.GlobalValueType())\n\tnewFn.SetLinkage(fn.Linkage())\n\tnewFn.SetVisibility(fn.Visibility())\n\tentry := mod.Context().AddBasicBlock(newFn, \"entry\")\n\n\t// Create a builder, to insert instructions that could not be evaluated at\n\t// compile time.\n\tr.builder = mod.Context().NewBuilder()\n\tdefer r.builder.Dispose()\n\tr.builder.SetInsertPointAtEnd(entry)\n\n\t// Copy debug information.\n\tsubprogram := fn.Subprogram()\n\tif !subprogram.IsNil() {\n\t\tnewFn.SetSubprogram(subprogram)\n\t\tr.builder.SetCurrentDebugLocation(subprogram.SubprogramLine(), 0, subprogram, llvm.Metadata{})\n\t}\n\n\t// Run the initializer, filling the .init.tmp function.\n\tif r.debug {\n\t\tfmt.Fprintln(os.Stderr, \"interp:\", fn.Name())\n\t}\n\t_, pkgMem, callErr := r.run(r.getFunction(fn), nil, nil, \"    \")\n\tif callErr != nil {\n\t\tif isRecoverableError(callErr.Err) {\n\t\t\t// Could not finish, but could recover from it.\n\t\t\tif r.debug {\n\t\t\t\tfmt.Fprintln(os.Stderr, \"not interpreting\", r.pkgName, \"because of error:\", callErr.Error())\n\t\t\t}\n\t\t\tnewFn.EraseFromParentAsFunction()\n\t\t\treturn nil\n\t\t}\n\t\treturn callErr\n\t}\n\tfor index, obj := range pkgMem.objects {\n\t\tr.objects[index] = obj\n\t}\n\n\t// Update globals with values determined while running the initializer above.\n\tmem := memoryView{r: r}\n\tfor _, obj := range r.objects {\n\t\tif obj.llvmGlobal.IsNil() {\n\t\t\tcontinue\n\t\t}\n\t\tif obj.buffer == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif obj.constant {\n\t\t\tcontinue // constant, so can't have been modified\n\t\t}\n\t\tinitializer, err := obj.buffer.toLLVMValue(obj.llvmGlobal.GlobalValueType(), &mem)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif checks && initializer.Type() != obj.llvmGlobal.GlobalValueType() {\n\t\t\tpanic(\"initializer type mismatch\")\n\t\t}\n\t\tobj.llvmGlobal.SetInitializer(initializer)\n\t}\n\n\t// Finalize: remove the old init function and replace it with the new\n\t// (.init.tmp) function.\n\tr.builder.CreateRetVoid()\n\tfnName := fn.Name()\n\tfn.ReplaceAllUsesWith(newFn)\n\tfn.EraseFromParentAsFunction()\n\tnewFn.SetName(fnName)\n\n\treturn nil\n}\n\n// getFunction returns the compiled version of the given LLVM function. It\n// compiles the function if necessary and caches the result.\nfunc (r *runner) getFunction(llvmFn llvm.Value) *function {\n\tif fn, ok := r.functionCache[llvmFn]; ok {\n\t\treturn fn\n\t}\n\tfn := r.compileFunction(llvmFn)\n\tr.functionCache[llvmFn] = fn\n\treturn fn\n}\n\n// markExternalLoad marks the given llvmValue as being loaded externally. This\n// is primarily used to mark package initializers that could not be run at\n// compile time. As an example, a package initialize might store to a global\n// variable. Another package initializer might read from the same global\n// variable. By marking this function as being run at runtime, that load\n// instruction will need to be run at runtime instead of at compile time.\nfunc (r *runner) markExternalLoad(llvmValue llvm.Value) error {\n\tmem := memoryView{r: r}\n\terr := mem.markExternalLoad(llvmValue)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfor index, obj := range mem.objects {\n\t\tif obj.marked > r.objects[index].marked {\n\t\t\tr.objects[index].marked = obj.marked\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "interp/interp_test.go",
    "content": "package interp\n\nimport (\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"tinygo.org/x/go-llvm\"\n)\n\nfunc TestInterp(t *testing.T) {\n\tllvmVersion, err := strconv.Atoi(strings.Split(llvm.Version, \".\")[0])\n\tif err != nil {\n\t\t// Note: this should never happen and if it does, it will always happen\n\t\t// for a particular build because llvm.Version is a constant.\n\t\tpanic(err)\n\t}\n\tfor _, name := range []string{\n\t\t\"basic\",\n\t\t\"phi\",\n\t\t\"slice-copy\",\n\t\t\"consteval\",\n\t\t\"interface\",\n\t\t\"revert\",\n\t\t\"alloc\",\n\t} {\n\t\tname := name // make local to this closure\n\t\tif name == \"slice-copy\" && llvmVersion < 14 {\n\t\t\tcontinue\n\t\t}\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\trunTest(t, \"testdata/\"+name)\n\t\t})\n\t}\n}\n\nfunc runTest(t *testing.T, pathPrefix string) {\n\t// Read the input IR.\n\tctx := llvm.NewContext()\n\tdefer ctx.Dispose()\n\tbuf, err := llvm.NewMemoryBufferFromFile(pathPrefix + \".ll\")\n\tos.Stat(pathPrefix + \".ll\") // make sure this file is tracked by `go test` caching\n\tif err != nil {\n\t\tt.Fatalf(\"could not read file %s: %v\", pathPrefix+\".ll\", err)\n\t}\n\tmod, err := ctx.ParseIR(buf)\n\tif err != nil {\n\t\tt.Fatalf(\"could not load module:\\n%v\", err)\n\t}\n\tdefer mod.Dispose()\n\n\t// Perform the transform.\n\terr = Run(mod, 10*time.Minute, false)\n\tif err != nil {\n\t\tif err, match := err.(*Error); match {\n\t\t\tprintln(err.Error())\n\t\t\tif len(err.Inst) != 0 {\n\t\t\t\tprintln(err.Inst)\n\t\t\t}\n\t\t\tif len(err.Traceback) > 0 {\n\t\t\t\tprintln(\"\\ntraceback:\")\n\t\t\t\tfor _, line := range err.Traceback {\n\t\t\t\t\tprintln(line.Pos.String() + \":\")\n\t\t\t\t\tprintln(line.Inst)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tt.Fatal(err)\n\t}\n\n\t// To be sure, verify that the module is still valid.\n\tif llvm.VerifyModule(mod, llvm.PrintMessageAction) != nil {\n\t\tt.FailNow()\n\t}\n\n\t// Run some cleanup passes to get easy-to-read outputs.\n\tto := llvm.NewPassBuilderOptions()\n\tdefer to.Dispose()\n\tmod.RunPasses(\"globalopt,dse,adce\", llvm.TargetMachine{}, to)\n\n\t// Read the expected output IR.\n\tout, err := os.ReadFile(pathPrefix + \".out.ll\")\n\tif err != nil {\n\t\tt.Fatalf(\"could not read output file %s: %v\", pathPrefix+\".out.ll\", err)\n\t}\n\n\t// See whether the transform output matches with the expected output IR.\n\texpected := string(out)\n\tactual := mod.String()\n\tif !fuzzyEqualIR(expected, actual) {\n\t\tt.Logf(\"output does not match expected output:\\n%s\", actual)\n\t\tt.Fail()\n\t}\n}\n\n// fuzzyEqualIR returns true if the two LLVM IR strings passed in are roughly\n// equal. That means, only relevant lines are compared (excluding comments\n// etc.).\nfunc fuzzyEqualIR(s1, s2 string) bool {\n\tlines1 := filterIrrelevantIRLines(strings.Split(s1, \"\\n\"))\n\tlines2 := filterIrrelevantIRLines(strings.Split(s2, \"\\n\"))\n\tif len(lines1) != len(lines2) {\n\t\treturn false\n\t}\n\tfor i, line1 := range lines1 {\n\t\tline2 := lines2[i]\n\t\tif line1 != line2 {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\n// filterIrrelevantIRLines removes lines from the input slice of strings that\n// are not relevant in comparing IR. For example, empty lines and comments are\n// stripped out.\nfunc filterIrrelevantIRLines(lines []string) []string {\n\tvar out []string\n\tfor _, line := range lines {\n\t\tline = strings.TrimSpace(line) // drop '\\r' on Windows\n\t\tif line == \"\" || line[0] == ';' {\n\t\t\tcontinue\n\t\t}\n\t\tif strings.HasPrefix(line, \"source_filename = \") {\n\t\t\tcontinue\n\t\t}\n\t\tout = append(out, line)\n\t}\n\treturn out\n}\n"
  },
  {
    "path": "interp/interpreter.go",
    "content": "package interp\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"math\"\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"tinygo.org/x/go-llvm\"\n)\n\nfunc (r *runner) run(fn *function, params []value, parentMem *memoryView, indent string) (value, memoryView, *Error) {\n\tmem := memoryView{r: r, parent: parentMem}\n\tlocals := make([]value, len(fn.locals))\n\tr.callsExecuted++\n\n\t// Parameters are considered a kind of local values.\n\tfor i, param := range params {\n\t\tlocals[i] = param\n\t}\n\n\t// Track what blocks have run instructions at runtime.\n\t// This is used to prevent unrolling.\n\tvar runtimeBlocks map[int]struct{}\n\n\t// Start with the first basic block and the first instruction.\n\t// Branch instructions may modify both bb and instIndex when branching.\n\tbb := fn.blocks[0]\n\tcurrentBB := 0\n\tlastBB := -1 // last basic block is undefined, only defined after a branch\n\tvar operands []value\n\tstartRTInsts := len(mem.instructions)\n\tfor instIndex := 0; instIndex < len(bb.instructions); instIndex++ {\n\t\tif instIndex == 0 {\n\t\t\t// This is the start of a new basic block.\n\t\t\tif len(mem.instructions) != startRTInsts {\n\t\t\t\tif _, ok := runtimeBlocks[lastBB]; ok {\n\t\t\t\t\t// This loop has been unrolled.\n\t\t\t\t\t// Avoid doing this, as it can result in a large amount of extra machine code.\n\t\t\t\t\t// This currently uses the branch from the last block, as there is no available information to give a better location.\n\t\t\t\t\tlastBBInsts := fn.blocks[lastBB].instructions\n\t\t\t\t\treturn nil, mem, r.errorAt(lastBBInsts[len(lastBBInsts)-1], errLoopUnrolled)\n\t\t\t\t}\n\n\t\t\t\t// Flag the last block as having run stuff at runtime.\n\t\t\t\tif runtimeBlocks == nil {\n\t\t\t\t\truntimeBlocks = make(map[int]struct{})\n\t\t\t\t}\n\t\t\t\truntimeBlocks[lastBB] = struct{}{}\n\n\t\t\t\t// Reset the block-start runtime instructions counter.\n\t\t\t\tstartRTInsts = len(mem.instructions)\n\t\t\t}\n\n\t\t\t// There may be PHI nodes that need to be resolved. Resolve all PHI\n\t\t\t// nodes before continuing with regular instructions.\n\t\t\t// PHI nodes need to be treated specially because they can have a\n\t\t\t// mutual dependency:\n\t\t\t//   for.loop:\n\t\t\t//     %a = phi i8 [ 1, %entry ], [ %b, %for.loop ]\n\t\t\t//     %b = phi i8 [ 3, %entry ], [ %a, %for.loop ]\n\t\t\t// If these PHI nodes are processed like a regular instruction, %a\n\t\t\t// and %b are both 3 on the second iteration of the loop because %b\n\t\t\t// loads the value of %a from the second iteration, while it should\n\t\t\t// load the value from the previous iteration. The correct behavior\n\t\t\t// is that these two values swap each others place on each\n\t\t\t// iteration.\n\t\t\tvar phiValues []value\n\t\t\tvar phiIndices []int\n\t\t\tfor _, inst := range bb.phiNodes {\n\t\t\t\tvar result value\n\t\t\t\tfor i := 0; i < len(inst.operands); i += 2 {\n\t\t\t\t\tif int(inst.operands[i].(literalValue).value.(uint32)) == lastBB {\n\t\t\t\t\t\tincoming := inst.operands[i+1]\n\t\t\t\t\t\tif local, ok := incoming.(localValue); ok {\n\t\t\t\t\t\t\tresult = locals[fn.locals[local.value]]\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresult = incoming\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif r.debug {\n\t\t\t\t\tfmt.Fprintln(os.Stderr, indent+\"phi\", inst.operands, \"->\", result)\n\t\t\t\t}\n\t\t\t\tif result == nil {\n\t\t\t\t\tpanic(\"could not find PHI input\")\n\t\t\t\t}\n\t\t\t\tphiValues = append(phiValues, result)\n\t\t\t\tphiIndices = append(phiIndices, inst.localIndex)\n\t\t\t}\n\t\t\tfor i, value := range phiValues {\n\t\t\t\tlocals[phiIndices[i]] = value\n\t\t\t}\n\t\t}\n\n\t\tinst := bb.instructions[instIndex]\n\t\toperands = operands[:0]\n\t\tisRuntimeInst := false\n\t\tif inst.opcode != llvm.PHI {\n\t\t\tfor _, v := range inst.operands {\n\t\t\t\tif v, ok := v.(localValue); ok {\n\t\t\t\t\tindex, ok := fn.locals[v.value]\n\t\t\t\t\tif !ok {\n\t\t\t\t\t\t// This is a localValue that is not local to the\n\t\t\t\t\t\t// function. An example would be an inline assembly call\n\t\t\t\t\t\t// operand.\n\t\t\t\t\t\tisRuntimeInst = true\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tlocalVal := locals[index]\n\t\t\t\t\tif localVal == nil {\n\t\t\t\t\t\t// Trying to read a function-local value before it is\n\t\t\t\t\t\t// set.\n\t\t\t\t\t\treturn nil, mem, r.errorAt(inst, errors.New(\"interp: local not defined\"))\n\t\t\t\t\t} else {\n\t\t\t\t\t\toperands = append(operands, localVal)\n\t\t\t\t\t\tif _, ok := localVal.(localValue); ok {\n\t\t\t\t\t\t\t// The function-local value is still just a\n\t\t\t\t\t\t\t// localValue (which can't be interpreted at compile\n\t\t\t\t\t\t\t// time). Not sure whether this ever happens in\n\t\t\t\t\t\t\t// practice.\n\t\t\t\t\t\t\tisRuntimeInst = true\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\toperands = append(operands, v)\n\t\t\t}\n\t\t}\n\t\tif isRuntimeInst {\n\t\t\terr := r.runAtRuntime(fn, inst, locals, &mem, indent)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, mem, err\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tswitch inst.opcode {\n\t\tcase llvm.Ret:\n\t\t\tif time.Since(r.start) > r.timeout {\n\t\t\t\t// Running for more than the allowed timeout; This shouldn't happen, but it does.\n\t\t\t\t// See github.com/tinygo-org/tinygo/issues/2124\n\t\t\t\treturn nil, mem, r.errorAt(fn.blocks[0].instructions[0], fmt.Errorf(\"interp: running for more than %s, timing out (executed calls: %d)\", r.timeout, r.callsExecuted))\n\t\t\t}\n\n\t\t\tif len(operands) != 0 {\n\t\t\t\tif r.debug {\n\t\t\t\t\tfmt.Fprintln(os.Stderr, indent+\"ret\", operands[0])\n\t\t\t\t}\n\t\t\t\t// Return instruction has a value to return.\n\t\t\t\treturn operands[0], mem, nil\n\t\t\t}\n\t\t\tif r.debug {\n\t\t\t\tfmt.Fprintln(os.Stderr, indent+\"ret\")\n\t\t\t}\n\t\t\t// Return instruction doesn't return anything, it's just 'ret void'.\n\t\t\treturn nil, mem, nil\n\t\tcase llvm.Br:\n\t\t\tswitch len(operands) {\n\t\t\tcase 1:\n\t\t\t\t// Unconditional branch: [nextBB]\n\t\t\t\tlastBB = currentBB\n\t\t\t\tcurrentBB = int(operands[0].(literalValue).value.(uint32))\n\t\t\t\tbb = fn.blocks[currentBB]\n\t\t\t\tinstIndex = -1 // start at 0 the next cycle\n\t\t\t\tif r.debug {\n\t\t\t\t\tfmt.Fprintln(os.Stderr, indent+\"br\", operands, \"->\", currentBB)\n\t\t\t\t}\n\t\t\tcase 3:\n\t\t\t\t// Conditional branch: [cond, thenBB, elseBB]\n\t\t\t\tlastBB = currentBB\n\t\t\t\tswitch operands[0].Uint(r) {\n\t\t\t\tcase 1: // true -> thenBB\n\t\t\t\t\tcurrentBB = int(operands[1].(literalValue).value.(uint32))\n\t\t\t\tcase 0: // false -> elseBB\n\t\t\t\t\tcurrentBB = int(operands[2].(literalValue).value.(uint32))\n\t\t\t\tdefault:\n\t\t\t\t\tpanic(\"bool should be 0 or 1\")\n\t\t\t\t}\n\t\t\t\tif r.debug {\n\t\t\t\t\tfmt.Fprintln(os.Stderr, indent+\"br\", operands, \"->\", currentBB)\n\t\t\t\t}\n\t\t\t\tbb = fn.blocks[currentBB]\n\t\t\t\tinstIndex = -1 // start at 0 the next cycle\n\t\t\tdefault:\n\t\t\t\tpanic(\"unknown operands length\")\n\t\t\t}\n\t\tcase llvm.Switch:\n\t\t\t// Switch statement: [value, defaultLabel, case0, label0, case1, label1, ...]\n\t\t\tvalue := operands[0].Uint(r)\n\t\t\ttargetLabel := operands[1].Uint(r) // default label\n\t\t\t// Do a lazy switch by iterating over all cases.\n\t\t\tfor i := 2; i < len(operands); i += 2 {\n\t\t\t\tif value == operands[i].Uint(r) {\n\t\t\t\t\ttargetLabel = operands[i+1].Uint(r)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tlastBB = currentBB\n\t\t\tcurrentBB = int(targetLabel)\n\t\t\tbb = fn.blocks[currentBB]\n\t\t\tinstIndex = -1 // start at 0 the next cycle\n\t\t\tif r.debug {\n\t\t\t\tfmt.Fprintln(os.Stderr, indent+\"switch\", operands, \"->\", currentBB)\n\t\t\t}\n\t\tcase llvm.Select:\n\t\t\t// Select is much like a ternary operator: it picks a result from\n\t\t\t// the second and third operand based on the boolean first operand.\n\t\t\tvar result value\n\t\t\tswitch operands[0].Uint(r) {\n\t\t\tcase 1:\n\t\t\t\tresult = operands[1]\n\t\t\tcase 0:\n\t\t\t\tresult = operands[2]\n\t\t\tdefault:\n\t\t\t\tpanic(\"boolean must be 0 or 1\")\n\t\t\t}\n\t\t\tlocals[inst.localIndex] = result\n\t\t\tif r.debug {\n\t\t\t\tfmt.Fprintln(os.Stderr, indent+\"select\", operands, \"->\", result)\n\t\t\t}\n\t\tcase llvm.Call:\n\t\t\t// A call instruction can either be a regular call or a runtime intrinsic.\n\t\t\tfnPtr, err := operands[0].asPointer(r)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, mem, r.errorAt(inst, err)\n\t\t\t}\n\t\t\tcallFn := r.getFunction(fnPtr.llvmValue(&mem))\n\t\t\tswitch {\n\t\t\tcase callFn.name == \"runtime.trackPointer\":\n\t\t\t\t// Allocas and such are created as globals, so don't need a\n\t\t\t\t// runtime.trackPointer.\n\t\t\t\t// Unless the object is allocated at runtime for example, in\n\t\t\t\t// which case this call won't even get to this point but will\n\t\t\t\t// already be emitted in initAll.\n\t\t\t\tcontinue\n\t\t\tcase strings.HasPrefix(callFn.name, \"runtime.print\") || callFn.name == \"runtime._panic\" || callFn.name == \"runtime.hashmapGet\" || callFn.name == \"runtime.hashmapInterfaceHash\" ||\n\t\t\t\tcallFn.name == \"os.runtime_args\" || callFn.name == \"internal/task.start\" || callFn.name == \"internal/task.Current\" ||\n\t\t\t\tcallFn.name == \"time.startTimer\" || callFn.name == \"time.stopTimer\" || callFn.name == \"time.resetTimer\":\n\t\t\t\t// These functions should be run at runtime. Specifically:\n\t\t\t\t//   * Print and panic functions are best emitted directly without\n\t\t\t\t//     interpreting them, otherwise we get a ton of putchar (etc.)\n\t\t\t\t//     calls.\n\t\t\t\t//   * runtime.hashmapGet tries to access the map value directly.\n\t\t\t\t//     This is not possible as the map value is treated as a special\n\t\t\t\t//     kind of object in this package.\n\t\t\t\t//   * os.runtime_args reads globals that are initialized outside\n\t\t\t\t//     the view of the interp package so it always needs to be run\n\t\t\t\t//     at runtime.\n\t\t\t\t//   * internal/task.start, internal/task.Current: start and read shcheduler state,\n\t\t\t\t//     which is modified elsewhere.\n\t\t\t\t//   * Timer functions access runtime internal state which may\n\t\t\t\t//     not be initialized.\n\t\t\t\terr := r.runAtRuntime(fn, inst, locals, &mem, indent)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, mem, err\n\t\t\t\t}\n\t\t\tcase callFn.name == \"internal/task.Pause\":\n\t\t\t\t// Task scheduling isn't possible at compile time.\n\t\t\t\treturn nil, mem, r.errorAt(inst, errUnsupportedRuntimeInst)\n\t\t\tcase callFn.name == \"runtime.nanotime\" && r.pkgName == \"time\":\n\t\t\t\t// The time package contains a call to runtime.nanotime.\n\t\t\t\t// This appears to be to work around a limitation in Windows\n\t\t\t\t// Server 2008:\n\t\t\t\t//   > Monotonic times are reported as offsets from startNano.\n\t\t\t\t//   > We initialize startNano to runtimeNano() - 1 so that on systems where\n\t\t\t\t//   > monotonic time resolution is fairly low (e.g. Windows 2008\n\t\t\t\t//   > which appears to have a default resolution of 15ms),\n\t\t\t\t//   > we avoid ever reporting a monotonic time of 0.\n\t\t\t\t//   > (Callers may want to use 0 as \"time not set\".)\n\t\t\t\t// Simply let runtime.nanotime return 0 in this case, which\n\t\t\t\t// should be fine and avoids a call to runtime.nanotime. It\n\t\t\t\t// means that monotonic time in the time package is counted from\n\t\t\t\t// time.Time{}.Sub(1), which should be fine.\n\t\t\t\tlocals[inst.localIndex] = literalValue{uint64(0)}\n\t\t\tcase callFn.name == \"runtime.alloc\":\n\t\t\t\t// Allocate heap memory. At compile time, this is instead done\n\t\t\t\t// by creating a global variable.\n\n\t\t\t\t// Get the requested memory size to be allocated.\n\t\t\t\tsize := operands[1].Uint(r)\n\n\t\t\t\t// Get the object layout, if it is available.\n\t\t\t\tllvmLayoutType := r.getLLVMTypeFromLayout(operands[2])\n\n\t\t\t\t// Get the alignment of the memory to be allocated.\n\t\t\t\talignment := 0 // use default alignment if unset\n\t\t\t\talignAttr := inst.llvmInst.GetCallSiteEnumAttribute(0, llvm.AttributeKindID(\"align\"))\n\t\t\t\tif !alignAttr.IsNil() {\n\t\t\t\t\talignment = int(alignAttr.GetEnumValue())\n\t\t\t\t}\n\n\t\t\t\t// Create the object.\n\t\t\t\talloc := object{\n\t\t\t\t\tglobalName:     r.pkgName + \"$alloc\",\n\t\t\t\t\talign:          alignment,\n\t\t\t\t\tllvmLayoutType: llvmLayoutType,\n\t\t\t\t\tbuffer:         newRawValue(uint32(size)),\n\t\t\t\t\tsize:           uint32(size),\n\t\t\t\t}\n\t\t\t\tindex := len(r.objects)\n\t\t\t\tr.objects = append(r.objects, alloc)\n\n\t\t\t\t// And create a pointer to this object, for working with it (so\n\t\t\t\t// that stores to it copy it, etc).\n\t\t\t\tptr := newPointerValue(r, index, 0)\n\t\t\t\tif r.debug {\n\t\t\t\t\tfmt.Fprintln(os.Stderr, indent+\"runtime.alloc:\", size, \"->\", ptr)\n\t\t\t\t}\n\t\t\t\tlocals[inst.localIndex] = ptr\n\t\t\tcase callFn.name == \"runtime.sliceCopy\":\n\t\t\t\t// sliceCopy implements the built-in copy function for slices.\n\t\t\t\t// It is implemented here so that it can be used even if the\n\t\t\t\t// runtime implementation is not available. Doing it this way\n\t\t\t\t// may also be faster.\n\t\t\t\t// Code:\n\t\t\t\t// func sliceCopy(dst, src unsafe.Pointer, dstLen, srcLen uintptr, elemSize uintptr) int {\n\t\t\t\t//     n := srcLen\n\t\t\t\t//     if n > dstLen {\n\t\t\t\t//         n = dstLen\n\t\t\t\t//     }\n\t\t\t\t//     memmove(dst, src, n*elemSize)\n\t\t\t\t//     return int(n)\n\t\t\t\t// }\n\t\t\t\tdstLen := operands[3].Uint(r)\n\t\t\t\tsrcLen := operands[4].Uint(r)\n\t\t\t\telemSize := operands[5].Uint(r)\n\t\t\t\tn := srcLen\n\t\t\t\tif n > dstLen {\n\t\t\t\t\tn = dstLen\n\t\t\t\t}\n\t\t\t\tif r.debug {\n\t\t\t\t\tfmt.Fprintln(os.Stderr, indent+\"copy:\", operands[1], operands[2], n)\n\t\t\t\t}\n\t\t\t\tif n != 0 {\n\t\t\t\t\t// Only try to copy bytes when there are any bytes to copy.\n\t\t\t\t\t// This is not just an optimization. If one of the slices\n\t\t\t\t\t// (or both) are nil, the asPointer method call will fail\n\t\t\t\t\t// even though copying a nil slice is allowed.\n\t\t\t\t\tdst, err := operands[1].asPointer(r)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn nil, mem, r.errorAt(inst, err)\n\t\t\t\t\t}\n\t\t\t\t\tsrc, err := operands[2].asPointer(r)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn nil, mem, r.errorAt(inst, err)\n\t\t\t\t\t}\n\t\t\t\t\tif mem.hasExternalStore(src) || mem.hasExternalLoadOrStore(dst) {\n\t\t\t\t\t\t// These are the same checks as there are on llvm.Load\n\t\t\t\t\t\t// and llvm.Store in the interpreter. Copying is\n\t\t\t\t\t\t// essentially loading from the source array and storing\n\t\t\t\t\t\t// to the destination array, hence why we need to do the\n\t\t\t\t\t\t// same checks here.\n\t\t\t\t\t\t// This fixes the following bug:\n\t\t\t\t\t\t// https://github.com/tinygo-org/tinygo/issues/3890\n\t\t\t\t\t\terr := r.runAtRuntime(fn, inst, locals, &mem, indent)\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn nil, mem, err\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tnBytes := uint32(n * elemSize)\n\t\t\t\t\tsrcObj := mem.get(src.index())\n\t\t\t\t\tdstObj := mem.getWritable(dst.index())\n\t\t\t\t\tif srcObj.buffer == nil || dstObj.buffer == nil {\n\t\t\t\t\t\t// If the buffer is nil, it means the slice is external.\n\t\t\t\t\t\t// This can happen for example when copying data out of\n\t\t\t\t\t\t// a //go:embed slice, which is not available at interp\n\t\t\t\t\t\t// time.\n\t\t\t\t\t\t// See: https://github.com/tinygo-org/tinygo/issues/4895\n\t\t\t\t\t\terr := r.runAtRuntime(fn, inst, locals, &mem, indent)\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn nil, mem, err\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tdstBuf := dstObj.buffer.asRawValue(r)\n\t\t\t\t\tsrcBuf := srcObj.buffer.asRawValue(r)\n\t\t\t\t\tcopy(dstBuf.buf[dst.offset():dst.offset()+nBytes], srcBuf.buf[src.offset():])\n\t\t\t\t\tdstObj.buffer = dstBuf\n\t\t\t\t\tmem.put(dst.index(), dstObj)\n\t\t\t\t}\n\t\t\t\tlocals[inst.localIndex] = makeLiteralInt(n, inst.llvmInst.Type().IntTypeWidth())\n\t\t\tcase strings.HasPrefix(callFn.name, \"llvm.memcpy.p0\") || strings.HasPrefix(callFn.name, \"llvm.memmove.p0\"):\n\t\t\t\t// Copy a block of memory from one pointer to another.\n\t\t\t\tdst, err := operands[1].asPointer(r)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, mem, r.errorAt(inst, err)\n\t\t\t\t}\n\t\t\t\tsrc, err := operands[2].asPointer(r)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, mem, r.errorAt(inst, err)\n\t\t\t\t}\n\t\t\t\tnBytes := uint32(operands[3].Uint(r))\n\t\t\t\tdstObj := mem.getWritable(dst.index())\n\t\t\t\tdstBuf := dstObj.buffer.asRawValue(r)\n\t\t\t\tif mem.get(src.index()).buffer == nil {\n\t\t\t\t\t// Looks like the source buffer is not defined.\n\t\t\t\t\t// This can happen with //extern or //go:embed.\n\t\t\t\t\treturn nil, mem, r.errorAt(inst, errUnsupportedRuntimeInst)\n\t\t\t\t}\n\t\t\t\tsrcBuf := mem.get(src.index()).buffer.asRawValue(r)\n\t\t\t\tcopy(dstBuf.buf[dst.offset():dst.offset()+nBytes], srcBuf.buf[src.offset():])\n\t\t\t\tdstObj.buffer = dstBuf\n\t\t\t\tmem.put(dst.index(), dstObj)\n\t\t\tcase callFn.name == \"runtime.typeAssert\":\n\t\t\t\t// This function must be implemented manually as it is normally\n\t\t\t\t// implemented by the interface lowering pass.\n\t\t\t\tif r.debug {\n\t\t\t\t\tfmt.Fprintln(os.Stderr, indent+\"typeassert:\", operands[1:])\n\t\t\t\t}\n\t\t\t\tassertedType, err := operands[2].toLLVMValue(inst.llvmInst.Operand(1).Type(), &mem)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, mem, r.errorAt(inst, err)\n\t\t\t\t}\n\t\t\t\tactualType, err := operands[1].toLLVMValue(inst.llvmInst.Operand(0).Type(), &mem)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, mem, r.errorAt(inst, err)\n\t\t\t\t}\n\t\t\t\tif !actualType.IsAConstantInt().IsNil() && actualType.ZExtValue() == 0 {\n\t\t\t\t\tlocals[inst.localIndex] = literalValue{uint8(0)}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\t// Strip pointer casts (bitcast, getelementptr).\n\t\t\t\tfor !actualType.IsAConstantExpr().IsNil() {\n\t\t\t\t\topcode := actualType.Opcode()\n\t\t\t\t\tif opcode != llvm.GetElementPtr && opcode != llvm.BitCast {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tactualType = actualType.Operand(0)\n\t\t\t\t}\n\t\t\t\tif strings.TrimPrefix(actualType.Name(), \"reflect/types.type:\") == strings.TrimPrefix(assertedType.Name(), \"reflect/types.typeid:\") {\n\t\t\t\t\tlocals[inst.localIndex] = literalValue{uint8(1)}\n\t\t\t\t} else {\n\t\t\t\t\tlocals[inst.localIndex] = literalValue{uint8(0)}\n\t\t\t\t}\n\t\t\tcase callFn.name == \"__tinygo_interp_raise_test_error\":\n\t\t\t\t// Special function that will trigger an error.\n\t\t\t\t// This is used to test error reporting.\n\t\t\t\treturn nil, mem, r.errorAt(inst, errors.New(\"test error\"))\n\t\t\tcase strings.HasSuffix(callFn.name, \".$typeassert\"):\n\t\t\t\tif r.debug {\n\t\t\t\t\tfmt.Fprintln(os.Stderr, indent+\"interface assert:\", operands[1:])\n\t\t\t\t}\n\n\t\t\t\t// Load various values for the interface implements check below.\n\t\t\t\ttypecodePtr, err := operands[1].asPointer(r)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, mem, r.errorAt(inst, err)\n\t\t\t\t}\n\t\t\t\t// typecodePtr always point to the numMethod field in the type\n\t\t\t\t// description struct. The methodSet, when present, comes right\n\t\t\t\t// before the numMethod field (the compiler doesn't generate\n\t\t\t\t// method sets for concrete types without methods).\n\t\t\t\t// Considering that the compiler doesn't emit interface type\n\t\t\t\t// asserts for interfaces with no methods (as the always succeed)\n\t\t\t\t// then if the offset is zero, this assert must always fail.\n\t\t\t\tif typecodePtr.offset() == 0 {\n\t\t\t\t\tlocals[inst.localIndex] = literalValue{uint8(0)}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\ttypecodePtrOffset, err := typecodePtr.addOffset(-int64(r.pointerSize))\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, mem, r.errorAt(inst, err)\n\t\t\t\t}\n\t\t\t\tmethodSetPtr, err := mem.load(typecodePtrOffset, r.pointerSize).asPointer(r)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, mem, r.errorAt(inst, err)\n\t\t\t\t}\n\t\t\t\tmethodSet := mem.get(methodSetPtr.index()).llvmGlobal.Initializer()\n\t\t\t\tnumMethods := int(r.builder.CreateExtractValue(methodSet, 0, \"\").ZExtValue())\n\t\t\t\tllvmFn := inst.llvmInst.CalledValue()\n\t\t\t\tmethodSetAttr := llvmFn.GetStringAttributeAtIndex(-1, \"tinygo-methods\")\n\t\t\t\tmethodSetString := methodSetAttr.GetStringValue()\n\n\t\t\t\t// Make a set of all the methods on the concrete type, for\n\t\t\t\t// easier checking in the next step.\n\t\t\t\tconcreteTypeMethods := map[string]struct{}{}\n\t\t\t\tfor i := 0; i < numMethods; i++ {\n\t\t\t\t\tmethodInfo := r.builder.CreateExtractValue(methodSet, 1, \"\")\n\t\t\t\t\tname := r.builder.CreateExtractValue(methodInfo, i, \"\").Name()\n\t\t\t\t\tconcreteTypeMethods[name] = struct{}{}\n\t\t\t\t}\n\n\t\t\t\t// Check whether all interface methods are also in the list\n\t\t\t\t// of defined methods calculated above. This is the interface\n\t\t\t\t// assert itself.\n\t\t\t\tassertOk := uint8(1) // i1 true\n\t\t\t\tfor _, name := range strings.Split(methodSetString, \"; \") {\n\t\t\t\t\tif _, ok := concreteTypeMethods[name]; !ok {\n\t\t\t\t\t\t// There is a method on the interface that is not\n\t\t\t\t\t\t// implemented by the type. The assertion will fail.\n\t\t\t\t\t\tassertOk = 0 // i1 false\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// If assertOk is still 1, the assertion succeeded.\n\t\t\t\tlocals[inst.localIndex] = literalValue{assertOk}\n\t\t\tcase strings.HasSuffix(callFn.name, \"$invoke\"):\n\t\t\t\t// This thunk is the interface method dispatcher: it is called\n\t\t\t\t// with all regular parameters and a type code. It will then\n\t\t\t\t// call the concrete method for it.\n\t\t\t\tif r.debug {\n\t\t\t\t\tfmt.Fprintln(os.Stderr, indent+\"invoke method:\", operands[1:])\n\t\t\t\t}\n\n\t\t\t\t// Load the type code and method set of the interface value.\n\t\t\t\ttypecodePtr, err := operands[len(operands)-2].asPointer(r)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, mem, r.errorAt(inst, err)\n\t\t\t\t}\n\t\t\t\ttypecodePtrOffset, err := typecodePtr.addOffset(-int64(r.pointerSize))\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, mem, r.errorAt(inst, err)\n\t\t\t\t}\n\t\t\t\tmethodSetPtr, err := mem.load(typecodePtrOffset, r.pointerSize).asPointer(r)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, mem, r.errorAt(inst, err)\n\t\t\t\t}\n\t\t\t\tmethodSet := mem.get(methodSetPtr.index()).llvmGlobal.Initializer()\n\n\t\t\t\t// We don't need to load the interface method set.\n\n\t\t\t\t// Load the signature of the to-be-called function.\n\t\t\t\tllvmFn := inst.llvmInst.CalledValue()\n\t\t\t\tinvokeAttr := llvmFn.GetStringAttributeAtIndex(-1, \"tinygo-invoke\")\n\t\t\t\tinvokeName := invokeAttr.GetStringValue()\n\t\t\t\tsignature := r.mod.NamedGlobal(invokeName)\n\n\t\t\t\t// Iterate through all methods, looking for the one method that\n\t\t\t\t// should be returned.\n\t\t\t\tnumMethods := int(r.builder.CreateExtractValue(methodSet, 0, \"\").ZExtValue())\n\t\t\t\tvar method llvm.Value\n\t\t\t\tfor i := 0; i < numMethods; i++ {\n\t\t\t\t\tmethodSignatureAgg := r.builder.CreateExtractValue(methodSet, 1, \"\")\n\t\t\t\t\tmethodSignature := r.builder.CreateExtractValue(methodSignatureAgg, i, \"\")\n\t\t\t\t\tif methodSignature == signature {\n\t\t\t\t\t\tmethodAgg := r.builder.CreateExtractValue(methodSet, 2, \"\")\n\t\t\t\t\t\tmethod = r.builder.CreateExtractValue(methodAgg, i, \"\")\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif method.IsNil() {\n\t\t\t\t\treturn nil, mem, r.errorAt(inst, errors.New(\"could not find method: \"+invokeName))\n\t\t\t\t}\n\n\t\t\t\t// Change the to-be-called function to the underlying method to\n\t\t\t\t// be called and fall through to the default case.\n\t\t\t\tcallFn = r.getFunction(method)\n\t\t\t\tfallthrough\n\t\t\tdefault:\n\t\t\t\tif len(callFn.blocks) == 0 {\n\t\t\t\t\t// Call to a function declaration without a definition\n\t\t\t\t\t// available.\n\t\t\t\t\terr := r.runAtRuntime(fn, inst, locals, &mem, indent)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn nil, mem, err\n\t\t\t\t\t}\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t// Call a function with a definition available. Run it as usual,\n\t\t\t\t// possibly trying to recover from it if it failed to execute.\n\t\t\t\tif r.debug {\n\t\t\t\t\targStrings := make([]string, len(operands)-1)\n\t\t\t\t\tfor i, v := range operands[1:] {\n\t\t\t\t\t\targStrings[i] = v.String()\n\t\t\t\t\t}\n\t\t\t\t\tfmt.Fprintln(os.Stderr, indent+\"call:\", callFn.name+\"(\"+strings.Join(argStrings, \", \")+\")\")\n\t\t\t\t}\n\t\t\t\tretval, callMem, callErr := r.run(callFn, operands[1:], &mem, indent+\"    \")\n\t\t\t\tif callErr != nil {\n\t\t\t\t\tif isRecoverableError(callErr.Err) {\n\t\t\t\t\t\t// This error can be recovered by doing the call at\n\t\t\t\t\t\t// runtime instead of at compile time. But we need to\n\t\t\t\t\t\t// revert any changes made by the call first.\n\t\t\t\t\t\tif r.debug {\n\t\t\t\t\t\t\tfmt.Fprintln(os.Stderr, indent+\"!! revert because of error:\", callErr.Error())\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcallMem.revert()\n\t\t\t\t\t\terr := r.runAtRuntime(fn, inst, locals, &mem, indent)\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn nil, mem, err\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\t// Add to the traceback, so that error handling code can see\n\t\t\t\t\t// how this function got called.\n\t\t\t\t\tcallErr.Traceback = append(callErr.Traceback, ErrorLine{\n\t\t\t\t\t\tPos:  getPosition(inst.llvmInst),\n\t\t\t\t\t\tInst: inst.llvmInst.String(),\n\t\t\t\t\t})\n\t\t\t\t\treturn nil, mem, callErr\n\t\t\t\t}\n\t\t\t\tlocals[inst.localIndex] = retval\n\t\t\t\tmem.extend(callMem)\n\t\t\t}\n\t\tcase llvm.Load:\n\t\t\t// Load instruction, loading some data from the topmost memory view.\n\t\t\tptr, err := operands[0].asPointer(r)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, mem, r.errorAt(inst, err)\n\t\t\t}\n\t\t\tsize := operands[1].(literalValue).value.(uint64)\n\t\t\tif inst.llvmInst.IsVolatile() || inst.llvmInst.Ordering() != llvm.AtomicOrderingNotAtomic || mem.hasExternalStore(ptr) {\n\t\t\t\t// If there could be an external store (for example, because a\n\t\t\t\t// pointer to the object was passed to a function that could not\n\t\t\t\t// be interpreted at compile time) then the load must be done at\n\t\t\t\t// runtime.\n\t\t\t\terr := r.runAtRuntime(fn, inst, locals, &mem, indent)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, mem, err\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tresult := mem.load(ptr, uint32(size))\n\t\t\tif result == nil {\n\t\t\t\terr := r.runAtRuntime(fn, inst, locals, &mem, indent)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, mem, err\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif r.debug {\n\t\t\t\tfmt.Fprintln(os.Stderr, indent+\"load:\", ptr, \"->\", result)\n\t\t\t}\n\t\t\tlocals[inst.localIndex] = result\n\t\tcase llvm.Store:\n\t\t\t// Store instruction. Create a new object in the memory view and\n\t\t\t// store to that, to make it possible to roll back this store.\n\t\t\tptr, err := operands[1].asPointer(r)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, mem, r.errorAt(inst, err)\n\t\t\t}\n\t\t\tif inst.llvmInst.IsVolatile() || inst.llvmInst.Ordering() != llvm.AtomicOrderingNotAtomic || mem.hasExternalLoadOrStore(ptr) {\n\t\t\t\terr := r.runAtRuntime(fn, inst, locals, &mem, indent)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, mem, err\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tval := operands[0]\n\t\t\tif r.debug {\n\t\t\t\tfmt.Fprintln(os.Stderr, indent+\"store:\", val, ptr)\n\t\t\t}\n\t\t\tok := mem.store(val, ptr)\n\t\t\tif !ok {\n\t\t\t\t// Could not store the value, do it at runtime.\n\t\t\t\terr := r.runAtRuntime(fn, inst, locals, &mem, indent)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, mem, err\n\t\t\t\t}\n\t\t\t}\n\t\tcase llvm.Alloca:\n\t\t\t// Alloca normally allocates some stack memory. In the interpreter,\n\t\t\t// it allocates a global instead.\n\t\t\t// This can likely be optimized, as all it really needs is an alloca\n\t\t\t// in the initAll function and creating a global is wasteful for\n\t\t\t// this purpose.\n\n\t\t\t// Create the new object.\n\t\t\tsize := operands[0].(literalValue).value.(uint64)\n\t\t\talloca := object{\n\t\t\t\tllvmType:   inst.llvmInst.AllocatedType(),\n\t\t\t\tglobalName: r.pkgName + \"$alloca\",\n\t\t\t\tbuffer:     newRawValue(uint32(size)),\n\t\t\t\tsize:       uint32(size),\n\t\t\t\talign:      inst.llvmInst.Alignment(),\n\t\t\t}\n\t\t\tindex := len(r.objects)\n\t\t\tr.objects = append(r.objects, alloca)\n\n\t\t\t// Create a pointer to this object (an alloca produces a pointer).\n\t\t\tptr := newPointerValue(r, index, 0)\n\t\t\tif r.debug {\n\t\t\t\tfmt.Fprintln(os.Stderr, indent+\"alloca:\", operands, \"->\", ptr)\n\t\t\t}\n\t\t\tlocals[inst.localIndex] = ptr\n\t\tcase llvm.GetElementPtr:\n\t\t\t// GetElementPtr does pointer arithmetic, changing the offset of the\n\t\t\t// pointer into the underlying object.\n\t\t\tvar offset int64\n\t\t\tfor i := 1; i < len(operands); i += 2 {\n\t\t\t\tindex := operands[i].Int(r)\n\t\t\t\telementSize := operands[i+1].Int(r)\n\t\t\t\tif elementSize < 0 {\n\t\t\t\t\t// This is a struct field.\n\t\t\t\t\toffset += index\n\t\t\t\t} else {\n\t\t\t\t\t// This is a normal GEP, probably an array index.\n\t\t\t\t\toffset += elementSize * index\n\t\t\t\t}\n\t\t\t}\n\t\t\tptr, err := operands[0].asPointer(r)\n\t\t\tif err != nil {\n\t\t\t\tif err != errIntegerAsPointer {\n\t\t\t\t\treturn nil, mem, r.errorAt(inst, err)\n\t\t\t\t}\n\t\t\t\t// GEP on fixed pointer value (for example, memory-mapped I/O).\n\t\t\t\tptrValue := operands[0].Uint(r) + uint64(offset)\n\t\t\t\tlocals[inst.localIndex] = makeLiteralInt(ptrValue, int(operands[0].len(r)*8))\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tptr, err = ptr.addOffset(int64(offset))\n\t\t\tif err != nil {\n\t\t\t\treturn nil, mem, r.errorAt(inst, err)\n\t\t\t}\n\t\t\tlocals[inst.localIndex] = ptr\n\t\t\tif r.debug {\n\t\t\t\tfmt.Fprintln(os.Stderr, indent+\"gep:\", operands, \"->\", ptr)\n\t\t\t}\n\t\tcase llvm.BitCast, llvm.IntToPtr, llvm.PtrToInt:\n\t\t\t// Various bitcast-like instructions that all keep the same bits\n\t\t\t// while changing the LLVM type.\n\t\t\t// Because interp doesn't preserve the type, these operations are\n\t\t\t// identity operations.\n\t\t\tif r.debug {\n\t\t\t\tfmt.Fprintln(os.Stderr, indent+instructionNameMap[inst.opcode]+\":\", operands[0])\n\t\t\t}\n\t\t\tlocals[inst.localIndex] = operands[0]\n\t\tcase llvm.ExtractValue:\n\t\t\tagg := operands[0].asRawValue(r)\n\t\t\toffset := operands[1].(literalValue).value.(uint64)\n\t\t\tsize := operands[2].(literalValue).value.(uint64)\n\t\t\telt := rawValue{\n\t\t\t\tbuf: agg.buf[offset : offset+size],\n\t\t\t}\n\t\t\tif r.debug {\n\t\t\t\tfmt.Fprintln(os.Stderr, indent+\"extractvalue:\", operands, \"->\", elt)\n\t\t\t}\n\t\t\tlocals[inst.localIndex] = elt\n\t\tcase llvm.InsertValue:\n\t\t\tagg := operands[0].asRawValue(r)\n\t\t\telt := operands[1].asRawValue(r)\n\t\t\toffset := int(operands[2].(literalValue).value.(uint64))\n\t\t\tnewagg := newRawValue(uint32(len(agg.buf)))\n\t\t\tcopy(newagg.buf, agg.buf)\n\t\t\tcopy(newagg.buf[offset:], elt.buf)\n\t\t\tif r.debug {\n\t\t\t\tfmt.Fprintln(os.Stderr, indent+\"insertvalue:\", operands, \"->\", newagg)\n\t\t\t}\n\t\t\tlocals[inst.localIndex] = newagg\n\t\tcase llvm.ICmp:\n\t\t\tpredicate := llvm.IntPredicate(operands[2].(literalValue).value.(uint8))\n\t\t\tlhs := operands[0]\n\t\t\trhs := operands[1]\n\t\t\tresult := r.interpretICmp(lhs, rhs, predicate)\n\t\t\tif result {\n\t\t\t\tlocals[inst.localIndex] = literalValue{uint8(1)}\n\t\t\t} else {\n\t\t\t\tlocals[inst.localIndex] = literalValue{uint8(0)}\n\t\t\t}\n\t\t\tif r.debug {\n\t\t\t\tfmt.Fprintln(os.Stderr, indent+\"icmp:\", operands[0], intPredicateString(predicate), operands[1], \"->\", result)\n\t\t\t}\n\t\tcase llvm.FCmp:\n\t\t\tpredicate := llvm.FloatPredicate(operands[2].(literalValue).value.(uint8))\n\t\t\tvar result bool\n\t\t\tvar lhs, rhs float64\n\t\t\tswitch operands[0].len(r) {\n\t\t\tcase 8:\n\t\t\t\tlhs = math.Float64frombits(operands[0].Uint(r))\n\t\t\t\trhs = math.Float64frombits(operands[1].Uint(r))\n\t\t\tcase 4:\n\t\t\t\tlhs = float64(math.Float32frombits(uint32(operands[0].Uint(r))))\n\t\t\t\trhs = float64(math.Float32frombits(uint32(operands[1].Uint(r))))\n\t\t\tdefault:\n\t\t\t\tpanic(\"unknown float type\")\n\t\t\t}\n\t\t\tswitch predicate {\n\t\t\tcase llvm.FloatOEQ:\n\t\t\t\tresult = lhs == rhs\n\t\t\tcase llvm.FloatUNE:\n\t\t\t\tresult = lhs != rhs\n\t\t\tcase llvm.FloatOGT:\n\t\t\t\tresult = lhs > rhs\n\t\t\tcase llvm.FloatOGE:\n\t\t\t\tresult = lhs >= rhs\n\t\t\tcase llvm.FloatOLT:\n\t\t\t\tresult = lhs < rhs\n\t\t\tcase llvm.FloatOLE:\n\t\t\t\tresult = lhs <= rhs\n\t\t\tdefault:\n\t\t\t\treturn nil, mem, r.errorAt(inst, errors.New(\"interp: unsupported fcmp\"))\n\t\t\t}\n\t\t\tif result {\n\t\t\t\tlocals[inst.localIndex] = literalValue{uint8(1)}\n\t\t\t} else {\n\t\t\t\tlocals[inst.localIndex] = literalValue{uint8(0)}\n\t\t\t}\n\t\t\tif r.debug {\n\t\t\t\tfmt.Fprintln(os.Stderr, indent+\"fcmp:\", operands[0], predicate, operands[1], \"->\", result)\n\t\t\t}\n\t\tcase llvm.Add, llvm.Sub, llvm.Mul, llvm.UDiv, llvm.SDiv, llvm.URem, llvm.SRem, llvm.Shl, llvm.LShr, llvm.AShr, llvm.And, llvm.Or, llvm.Xor:\n\t\t\t// Integer binary operations.\n\t\t\tlhs := operands[0]\n\t\t\trhs := operands[1]\n\t\t\tlhsPtr, err := lhs.asPointer(r)\n\t\t\tif err == nil {\n\t\t\t\t// The lhs is a pointer. This sometimes happens for particular\n\t\t\t\t// pointer tricks.\n\t\t\t\tif inst.opcode == llvm.Add {\n\t\t\t\t\t// This likely means this is part of a\n\t\t\t\t\t// unsafe.Pointer(uintptr(ptr) + offset) pattern.\n\t\t\t\t\tlhsPtr, err = lhsPtr.addOffset(int64(rhs.Uint(r)))\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn nil, mem, r.errorAt(inst, err)\n\t\t\t\t\t}\n\t\t\t\t\tlocals[inst.localIndex] = lhsPtr\n\t\t\t\t} else if inst.opcode == llvm.Xor && rhs.Uint(r) == 0 {\n\t\t\t\t\t// Special workaround for strings.noescape, see\n\t\t\t\t\t// src/strings/builder.go in the Go source tree. This is\n\t\t\t\t\t// the identity operator, so we can return the input.\n\t\t\t\t\tlocals[inst.localIndex] = lhs\n\t\t\t\t} else if inst.opcode == llvm.And && rhs.Uint(r) < 8 {\n\t\t\t\t\t// This is probably part of a pattern to get the lower bits\n\t\t\t\t\t// of a pointer for pointer tagging, like this:\n\t\t\t\t\t//     uintptr(unsafe.Pointer(t)) & 0b11\n\t\t\t\t\t// We can actually support this easily by ANDing with the\n\t\t\t\t\t// pointer offset.\n\t\t\t\t\tresult := uint64(lhsPtr.offset()) & rhs.Uint(r)\n\t\t\t\t\tlocals[inst.localIndex] = makeLiteralInt(result, int(lhs.len(r)*8))\n\t\t\t\t} else {\n\t\t\t\t\t// Catch-all for weird operations that should just be done\n\t\t\t\t\t// at runtime.\n\t\t\t\t\terr := r.runAtRuntime(fn, inst, locals, &mem, indent)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn nil, mem, err\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tvar result uint64\n\t\t\tswitch inst.opcode {\n\t\t\tcase llvm.Add:\n\t\t\t\tresult = lhs.Uint(r) + rhs.Uint(r)\n\t\t\tcase llvm.Sub:\n\t\t\t\tresult = lhs.Uint(r) - rhs.Uint(r)\n\t\t\tcase llvm.Mul:\n\t\t\t\tresult = lhs.Uint(r) * rhs.Uint(r)\n\t\t\tcase llvm.UDiv:\n\t\t\t\tresult = lhs.Uint(r) / rhs.Uint(r)\n\t\t\tcase llvm.SDiv:\n\t\t\t\tresult = uint64(lhs.Int(r) / rhs.Int(r))\n\t\t\tcase llvm.URem:\n\t\t\t\tresult = lhs.Uint(r) % rhs.Uint(r)\n\t\t\tcase llvm.SRem:\n\t\t\t\tresult = uint64(lhs.Int(r) % rhs.Int(r))\n\t\t\tcase llvm.Shl:\n\t\t\t\tresult = lhs.Uint(r) << rhs.Uint(r)\n\t\t\tcase llvm.LShr:\n\t\t\t\tresult = lhs.Uint(r) >> rhs.Uint(r)\n\t\t\tcase llvm.AShr:\n\t\t\t\tresult = uint64(lhs.Int(r) >> rhs.Uint(r))\n\t\t\tcase llvm.And:\n\t\t\t\tresult = lhs.Uint(r) & rhs.Uint(r)\n\t\t\tcase llvm.Or:\n\t\t\t\tresult = lhs.Uint(r) | rhs.Uint(r)\n\t\t\tcase llvm.Xor:\n\t\t\t\tresult = lhs.Uint(r) ^ rhs.Uint(r)\n\t\t\tdefault:\n\t\t\t\tpanic(\"unreachable\")\n\t\t\t}\n\t\t\tlocals[inst.localIndex] = makeLiteralInt(result, int(lhs.len(r)*8))\n\t\t\tif r.debug {\n\t\t\t\tfmt.Fprintln(os.Stderr, indent+instructionNameMap[inst.opcode]+\":\", lhs, rhs, \"->\", result)\n\t\t\t}\n\t\tcase llvm.SExt, llvm.ZExt, llvm.Trunc:\n\t\t\t// Change the size of an integer to a larger or smaller bit width.\n\t\t\t// We make use of the fact that the Uint() function already\n\t\t\t// zero-extends the value and that Int() already sign-extends the\n\t\t\t// value, so we only need to truncate it to the appropriate bit\n\t\t\t// width. This means we can implement sext, zext and trunc in the\n\t\t\t// same way, by first {zero,sign}extending all the way up to uint64\n\t\t\t// and then truncating it as necessary.\n\t\t\tvar value uint64\n\t\t\tif inst.opcode == llvm.SExt {\n\t\t\t\tvalue = uint64(operands[0].Int(r))\n\t\t\t} else {\n\t\t\t\tvalue = operands[0].Uint(r)\n\t\t\t}\n\t\t\tbitwidth := operands[1].Uint(r)\n\t\t\tif r.debug {\n\t\t\t\tfmt.Fprintln(os.Stderr, indent+instructionNameMap[inst.opcode]+\":\", value, bitwidth)\n\t\t\t}\n\t\t\tlocals[inst.localIndex] = makeLiteralInt(value, int(bitwidth))\n\t\tcase llvm.SIToFP, llvm.UIToFP:\n\t\t\tvar value float64\n\t\t\tswitch inst.opcode {\n\t\t\tcase llvm.SIToFP:\n\t\t\t\tvalue = float64(operands[0].Int(r))\n\t\t\tcase llvm.UIToFP:\n\t\t\t\tvalue = float64(operands[0].Uint(r))\n\t\t\t}\n\t\t\tbitwidth := operands[1].Uint(r)\n\t\t\tif r.debug {\n\t\t\t\tfmt.Fprintln(os.Stderr, indent+instructionNameMap[inst.opcode]+\":\", value, bitwidth)\n\t\t\t}\n\t\t\tswitch bitwidth {\n\t\t\tcase 64:\n\t\t\t\tlocals[inst.localIndex] = literalValue{math.Float64bits(value)}\n\t\t\tcase 32:\n\t\t\t\tlocals[inst.localIndex] = literalValue{math.Float32bits(float32(value))}\n\t\t\tdefault:\n\t\t\t\tpanic(\"unknown integer size in sitofp/uitofp\")\n\t\t\t}\n\t\tdefault:\n\t\t\tif r.debug {\n\t\t\t\tfmt.Fprintln(os.Stderr, indent+inst.String())\n\t\t\t}\n\t\t\treturn nil, mem, r.errorAt(inst, errUnsupportedInst)\n\t\t}\n\t}\n\treturn nil, mem, r.errorAt(bb.instructions[len(bb.instructions)-1], errors.New(\"interp: reached end of basic block without terminator\"))\n}\n\n// Interpret an icmp instruction. Doesn't have side effects, only returns the\n// output of the comparison.\nfunc (r *runner) interpretICmp(lhs, rhs value, predicate llvm.IntPredicate) bool {\n\tswitch predicate {\n\tcase llvm.IntEQ, llvm.IntNE:\n\t\tvar result bool\n\t\tlhsPointer, lhsErr := lhs.asPointer(r)\n\t\trhsPointer, rhsErr := rhs.asPointer(r)\n\t\tif (lhsErr == nil) != (rhsErr == nil) {\n\t\t\t// Fast path: only one is a pointer, so they can't be equal.\n\t\t\tresult = false\n\t\t} else if lhsErr == nil {\n\t\t\t// Both must be nil, so both are pointers.\n\t\t\t// Compare them directly.\n\t\t\tresult = lhsPointer.equal(rhsPointer)\n\t\t} else {\n\t\t\t// Fall back to generic comparison.\n\t\t\tresult = lhs.asRawValue(r).equal(rhs.asRawValue(r))\n\t\t}\n\t\tif predicate == llvm.IntNE {\n\t\t\tresult = !result\n\t\t}\n\t\treturn result\n\tcase llvm.IntUGT:\n\t\treturn lhs.Uint(r) > rhs.Uint(r)\n\tcase llvm.IntUGE:\n\t\treturn lhs.Uint(r) >= rhs.Uint(r)\n\tcase llvm.IntULT:\n\t\treturn lhs.Uint(r) < rhs.Uint(r)\n\tcase llvm.IntULE:\n\t\treturn lhs.Uint(r) <= rhs.Uint(r)\n\tcase llvm.IntSGT:\n\t\treturn lhs.Int(r) > rhs.Int(r)\n\tcase llvm.IntSGE:\n\t\treturn lhs.Int(r) >= rhs.Int(r)\n\tcase llvm.IntSLT:\n\t\treturn lhs.Int(r) < rhs.Int(r)\n\tcase llvm.IntSLE:\n\t\treturn lhs.Int(r) <= rhs.Int(r)\n\tdefault:\n\t\t// _should_ be unreachable, until LLVM adds new icmp operands (unlikely)\n\t\tpanic(\"interp: unsupported icmp\")\n\t}\n}\n\nfunc (r *runner) runAtRuntime(fn *function, inst instruction, locals []value, mem *memoryView, indent string) *Error {\n\tnumOperands := inst.llvmInst.OperandsCount()\n\toperands := make([]llvm.Value, numOperands)\n\tfor i := 0; i < numOperands; i++ {\n\t\toperand := inst.llvmInst.Operand(i)\n\t\tif !operand.IsAInstruction().IsNil() || !operand.IsAArgument().IsNil() {\n\t\t\tvar err error\n\t\t\toperand, err = locals[fn.locals[operand]].toLLVMValue(operand.Type(), mem)\n\t\t\tif err != nil {\n\t\t\t\treturn r.errorAt(inst, err)\n\t\t\t}\n\t\t}\n\t\toperands[i] = operand\n\t}\n\tif r.debug {\n\t\tfmt.Fprintln(os.Stderr, indent+inst.String())\n\t}\n\tvar result llvm.Value\n\tswitch inst.opcode {\n\tcase llvm.Call:\n\t\tllvmFn := operands[len(operands)-1]\n\t\targs := operands[:len(operands)-1]\n\t\tfor _, op := range operands {\n\t\t\tif op.Type().TypeKind() == llvm.PointerTypeKind {\n\t\t\t\terr := mem.markExternalStore(op)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn r.errorAt(inst, err)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tresult = r.builder.CreateCall(inst.llvmInst.CalledFunctionType(), llvmFn, args, inst.name)\n\tcase llvm.Load:\n\t\terr := mem.markExternalLoad(operands[0])\n\t\tif err != nil {\n\t\t\treturn r.errorAt(inst, err)\n\t\t}\n\t\tresult = r.builder.CreateLoad(inst.llvmInst.Type(), operands[0], inst.name)\n\t\tif inst.llvmInst.IsVolatile() {\n\t\t\tresult.SetVolatile(true)\n\t\t}\n\t\tif ordering := inst.llvmInst.Ordering(); ordering != llvm.AtomicOrderingNotAtomic {\n\t\t\tresult.SetOrdering(ordering)\n\t\t}\n\tcase llvm.Store:\n\t\terr := mem.markExternalStore(operands[1])\n\t\tif err != nil {\n\t\t\treturn r.errorAt(inst, err)\n\t\t}\n\t\tresult = r.builder.CreateStore(operands[0], operands[1])\n\t\tif inst.llvmInst.IsVolatile() {\n\t\t\tresult.SetVolatile(true)\n\t\t}\n\t\tif ordering := inst.llvmInst.Ordering(); ordering != llvm.AtomicOrderingNotAtomic {\n\t\t\tresult.SetOrdering(ordering)\n\t\t}\n\tcase llvm.BitCast:\n\t\tresult = r.builder.CreateBitCast(operands[0], inst.llvmInst.Type(), inst.name)\n\tcase llvm.ExtractValue:\n\t\tindices := inst.llvmInst.Indices()\n\t\t// Note: the Go LLVM API doesn't support multiple indices, so simulate\n\t\t// this operation with some extra extractvalue instructions. Hopefully\n\t\t// this is optimized to a single instruction.\n\t\tagg := operands[0]\n\t\tfor i := 0; i < len(indices)-1; i++ {\n\t\t\tagg = r.builder.CreateExtractValue(agg, int(indices[i]), inst.name+\".agg\")\n\t\t\tmem.instructions = append(mem.instructions, agg)\n\t\t}\n\t\tresult = r.builder.CreateExtractValue(agg, int(indices[len(indices)-1]), inst.name)\n\tcase llvm.InsertValue:\n\t\tindices := inst.llvmInst.Indices()\n\t\t// Similar to extractvalue, we're working around a limitation in the Go\n\t\t// LLVM API here by splitting the insertvalue into multiple instructions\n\t\t// if there is more than one operand.\n\t\tagg := operands[0]\n\t\taggregates := []llvm.Value{agg}\n\t\tfor i := 0; i < len(indices)-1; i++ {\n\t\t\tagg = r.builder.CreateExtractValue(agg, int(indices[i]), inst.name+\".agg\"+strconv.Itoa(i))\n\t\t\taggregates = append(aggregates, agg)\n\t\t\tmem.instructions = append(mem.instructions, agg)\n\t\t}\n\t\tresult = operands[1]\n\t\tfor i := len(indices) - 1; i >= 0; i-- {\n\t\t\tagg := aggregates[i]\n\t\t\tresult = r.builder.CreateInsertValue(agg, result, int(indices[i]), inst.name+\".insertvalue\"+strconv.Itoa(i))\n\t\t\tif i != 0 { // don't add last result to mem.instructions as it will be done at the end already\n\t\t\t\tmem.instructions = append(mem.instructions, result)\n\t\t\t}\n\t\t}\n\n\tcase llvm.Add:\n\t\tresult = r.builder.CreateAdd(operands[0], operands[1], inst.name)\n\tcase llvm.Sub:\n\t\tresult = r.builder.CreateSub(operands[0], operands[1], inst.name)\n\tcase llvm.Mul:\n\t\tresult = r.builder.CreateMul(operands[0], operands[1], inst.name)\n\tcase llvm.UDiv:\n\t\tresult = r.builder.CreateUDiv(operands[0], operands[1], inst.name)\n\tcase llvm.SDiv:\n\t\tresult = r.builder.CreateSDiv(operands[0], operands[1], inst.name)\n\tcase llvm.URem:\n\t\tresult = r.builder.CreateURem(operands[0], operands[1], inst.name)\n\tcase llvm.SRem:\n\t\tresult = r.builder.CreateSRem(operands[0], operands[1], inst.name)\n\tcase llvm.ZExt:\n\t\tresult = r.builder.CreateZExt(operands[0], inst.llvmInst.Type(), inst.name)\n\tdefault:\n\t\treturn r.errorAt(inst, errUnsupportedRuntimeInst)\n\t}\n\tlocals[inst.localIndex] = localValue{result}\n\tmem.instructions = append(mem.instructions, result)\n\treturn nil\n}\n\nfunc intPredicateString(predicate llvm.IntPredicate) string {\n\tswitch predicate {\n\tcase llvm.IntEQ:\n\t\treturn \"eq\"\n\tcase llvm.IntNE:\n\t\treturn \"ne\"\n\tcase llvm.IntUGT:\n\t\treturn \"ugt\"\n\tcase llvm.IntUGE:\n\t\treturn \"uge\"\n\tcase llvm.IntULT:\n\t\treturn \"ult\"\n\tcase llvm.IntULE:\n\t\treturn \"ule\"\n\tcase llvm.IntSGT:\n\t\treturn \"sgt\"\n\tcase llvm.IntSGE:\n\t\treturn \"sge\"\n\tcase llvm.IntSLT:\n\t\treturn \"slt\"\n\tcase llvm.IntSLE:\n\t\treturn \"sle\"\n\tdefault:\n\t\treturn \"cmp?\"\n\t}\n}\n"
  },
  {
    "path": "interp/memory.go",
    "content": "package interp\n\n// This file implements memory as used by interp in a reversible way.\n// Each new function call creates a new layer which is merged in the parent on\n// successful return and is thrown away when the function couldn't complete (in\n// which case the function call is done at runtime).\n// Memory is not typed, except that there is a difference between pointer and\n// non-pointer data. A pointer always points to an object. This implies:\n//   * Nil pointers are zero, and are not considered a pointer.\n//   * Pointers for memory-mapped I/O point to numeric pointer values, and are\n//     thus not considered pointers but regular values. Dereferencing them cannot be\n//     done in interp and results in a revert.\n//\n// Right now the memory is assumed to be little endian. This will need an update\n// for big endian architectures, if TinyGo ever adds support for one.\n\nimport (\n\t\"encoding/binary\"\n\t\"errors\"\n\t\"fmt\"\n\t\"math\"\n\t\"math/big\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// An object is a memory buffer that may be an already existing global or a\n// global created with runtime.alloc or the alloca instruction. If llvmGlobal is\n// set, that's the global for this object, otherwise it needs to be created (if\n// it is still reachable when the package initializer returns). The\n// llvmLayoutType is not necessarily a complete type: it may need to be\n// repeated (for example, for a slice value).\n//\n// Objects are copied in a memory view when they are stored to, to provide the\n// ability to roll back interpreting a function.\ntype object struct {\n\tllvmGlobal     llvm.Value\n\tllvmType       llvm.Type // must match llvmGlobal.GlobalValueType() if both are set, may be unset if llvmGlobal is set\n\tllvmLayoutType llvm.Type // LLVM type based on runtime.alloc layout parameter, if available\n\tglobalName     string    // name, if not yet created (not guaranteed to be the final name)\n\tbuffer         value     // buffer with value as given by interp, nil if external\n\tsize           uint32    // must match buffer.len(), if available\n\talign          int       // alignment of the object (may be 0 if unknown)\n\tconstant       bool      // true if this is a constant global\n\tmarked         uint8     // 0 means unmarked, 1 means external read, 2 means external write\n}\n\n// clone() returns a cloned version of this object, for when an object needs to\n// be written to for example.\nfunc (obj object) clone() object {\n\tif obj.buffer != nil {\n\t\tobj.buffer = obj.buffer.clone()\n\t}\n\treturn obj\n}\n\n// A memoryView is bound to a function activation. Loads are done from this view\n// or a parent view (up to the *runner if it isn't included in a view). Stores\n// copy the object to the current view.\n//\n// For details, see the README in the package.\ntype memoryView struct {\n\tr       *runner\n\tparent  *memoryView\n\tobjects map[uint32]object\n\n\t// These instructions were added to runtime.initAll while interpreting a\n\t// function. They are stored here in a list so they can be removed if the\n\t// execution of the function needs to be rolled back.\n\tinstructions []llvm.Value\n}\n\n// extend integrates the changes done by the sub-memoryView into this memory\n// view. This happens when a function is successfully interpreted and returns to\n// the parent, in which case all changed objects should be included in this\n// memory view.\nfunc (mv *memoryView) extend(sub memoryView) {\n\tif mv.objects == nil && len(sub.objects) != 0 {\n\t\tmv.objects = make(map[uint32]object)\n\t}\n\tfor key, value := range sub.objects {\n\t\tmv.objects[key] = value\n\t}\n\tmv.instructions = append(mv.instructions, sub.instructions...)\n}\n\n// revert undoes changes done in this memory view: it removes all instructions\n// created in this memoryView. Do not reuse this memoryView.\nfunc (mv *memoryView) revert() {\n\t// Erase instructions in reverse order.\n\tfor i := len(mv.instructions) - 1; i >= 0; i-- {\n\t\tllvmInst := mv.instructions[i]\n\t\tif llvmInst.IsAInstruction().IsNil() {\n\t\t\t// The IR builder will try to create constant versions of\n\t\t\t// instructions whenever possible. If it does this, it's not an\n\t\t\t// instruction and thus shouldn't be removed.\n\t\t\tcontinue\n\t\t}\n\t\tllvmInst.EraseFromParentAsInstruction()\n\t}\n}\n\n// markExternalLoad marks the given LLVM value as having an external read. That\n// means that the interpreter can still read from it, but cannot write to it as\n// that would mean the external read (done at runtime) reads from a state that\n// would not exist had the whole initialization been done at runtime.\nfunc (mv *memoryView) markExternalLoad(llvmValue llvm.Value) error {\n\treturn mv.markExternal(llvmValue, 1)\n}\n\n// markExternalStore marks the given LLVM value as having an external write.\n// This means that the interpreter can no longer read from it or write to it, as\n// that would happen in a different order than if all initialization were\n// happening at runtime.\nfunc (mv *memoryView) markExternalStore(llvmValue llvm.Value) error {\n\treturn mv.markExternal(llvmValue, 2)\n}\n\n// markExternal is a helper for markExternalLoad and markExternalStore, and\n// should not be called directly.\nfunc (mv *memoryView) markExternal(llvmValue llvm.Value, mark uint8) error {\n\tif llvmValue.IsUndef() || llvmValue.IsNull() {\n\t\t// Null and undef definitely don't contain (valid) pointers.\n\t\treturn nil\n\t}\n\tif !llvmValue.IsAInstruction().IsNil() || !llvmValue.IsAArgument().IsNil() {\n\t\t// These are considered external by default, there is nothing to mark.\n\t\treturn nil\n\t}\n\n\tif !llvmValue.IsAGlobalValue().IsNil() {\n\t\tobjectIndex := mv.r.getValue(llvmValue).(pointerValue).index()\n\t\tobj := mv.get(objectIndex)\n\t\tif obj.marked < mark {\n\t\t\tobj = obj.clone()\n\t\t\tobj.marked = mark\n\t\t\tif mv.objects == nil {\n\t\t\t\tmv.objects = make(map[uint32]object)\n\t\t\t}\n\t\t\tmv.objects[objectIndex] = obj\n\t\t\tif !llvmValue.IsAGlobalVariable().IsNil() {\n\t\t\t\tinitializer := llvmValue.Initializer()\n\t\t\t\tif !initializer.IsNil() {\n\t\t\t\t\t// Using mark '2' (which means read/write access) because\n\t\t\t\t\t// even from an object that is only read from, the resulting\n\t\t\t\t\t// loaded pointer can be written to.\n\t\t\t\t\terr := mv.markExternal(initializer, 2)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// This is a function. Go through all instructions and mark all\n\t\t\t\t// objects in there.\n\t\t\t\tfor bb := llvmValue.FirstBasicBlock(); !bb.IsNil(); bb = llvm.NextBasicBlock(bb) {\n\t\t\t\t\tfor inst := bb.FirstInstruction(); !inst.IsNil(); inst = llvm.NextInstruction(inst) {\n\t\t\t\t\t\topcode := inst.InstructionOpcode()\n\t\t\t\t\t\tif opcode == llvm.Call {\n\t\t\t\t\t\t\tcalledValue := inst.CalledValue()\n\t\t\t\t\t\t\tif !calledValue.IsAFunction().IsNil() {\n\t\t\t\t\t\t\t\tfunctionName := calledValue.Name()\n\t\t\t\t\t\t\t\tif functionName == \"llvm.dbg.value\" || strings.HasPrefix(functionName, \"llvm.lifetime.\") {\n\t\t\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif opcode == llvm.Br || opcode == llvm.Switch {\n\t\t\t\t\t\t\t// These don't affect memory. Skipped here because\n\t\t\t\t\t\t\t// they also have a label as operand.\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t\tnumOperands := inst.OperandsCount()\n\t\t\t\t\t\tfor i := 0; i < numOperands; i++ {\n\t\t\t\t\t\t\t// Using mark '2' (which means read/write access)\n\t\t\t\t\t\t\t// because this might be a store instruction.\n\t\t\t\t\t\t\terr := mv.markExternal(inst.Operand(i), 2)\n\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\treturn err\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else if !llvmValue.IsAConstantExpr().IsNil() {\n\t\tswitch llvmValue.Opcode() {\n\t\tcase llvm.IntToPtr, llvm.PtrToInt, llvm.BitCast, llvm.GetElementPtr:\n\t\t\terr := mv.markExternal(llvmValue.Operand(0), mark)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\tcase llvm.Add, llvm.Sub, llvm.Mul, llvm.UDiv, llvm.SDiv, llvm.URem, llvm.SRem, llvm.Shl, llvm.LShr, llvm.AShr, llvm.And, llvm.Or, llvm.Xor:\n\t\t\t// Integer binary operators. Mark both operands.\n\t\t\terr := mv.markExternal(llvmValue.Operand(0), mark)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\terr = mv.markExternal(llvmValue.Operand(1), mark)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"interp: unknown constant expression '%s'\", instructionNameMap[llvmValue.Opcode()])\n\t\t}\n\t} else if !llvmValue.IsAInlineAsm().IsNil() {\n\t\t// Inline assembly can modify globals but only exported globals. Let's\n\t\t// hope the author knows what they're doing.\n\t} else {\n\t\tllvmType := llvmValue.Type()\n\t\tswitch llvmType.TypeKind() {\n\t\tcase llvm.IntegerTypeKind, llvm.FloatTypeKind, llvm.DoubleTypeKind:\n\t\t\t// Nothing to do here. Integers and floats aren't pointers so don't\n\t\t\t// need any marking.\n\t\tcase llvm.StructTypeKind:\n\t\t\tnumElements := llvmType.StructElementTypesCount()\n\t\t\tfor i := 0; i < numElements; i++ {\n\t\t\t\telement := mv.r.builder.CreateExtractValue(llvmValue, i, \"\")\n\t\t\t\terr := mv.markExternal(element, mark)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\tcase llvm.ArrayTypeKind:\n\t\t\tnumElements := llvmType.ArrayLength()\n\t\t\tfor i := 0; i < numElements; i++ {\n\t\t\t\telement := mv.r.builder.CreateExtractValue(llvmValue, i, \"\")\n\t\t\t\terr := mv.markExternal(element, mark)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\tdefault:\n\t\t\treturn errors.New(\"interp: unknown type kind in markExternalValue\")\n\t\t}\n\t}\n\treturn nil\n}\n\n// hasExternalLoadOrStore returns true if this object has an external load or\n// store. If this has happened, it is not possible for the interpreter to load\n// from the object or store to it without affecting the behavior of the program.\nfunc (mv *memoryView) hasExternalLoadOrStore(v pointerValue) bool {\n\tobj := mv.get(v.index())\n\treturn obj.marked >= 1\n}\n\n// hasExternalStore returns true if this object has an external store. If this\n// is true, stores to this object are no longer allowed by the interpreter.\n// It returns false if it only has an external load, in which case it is still\n// possible for the interpreter to read from the object.\nfunc (mv *memoryView) hasExternalStore(v pointerValue) bool {\n\tobj := mv.get(v.index())\n\treturn obj.marked >= 2 && !obj.constant\n}\n\n// get returns an object that can only be read from, as it may return an object\n// of a parent view.\nfunc (mv *memoryView) get(index uint32) object {\n\tif obj, ok := mv.objects[index]; ok {\n\t\treturn obj\n\t}\n\tif mv.parent != nil {\n\t\treturn mv.parent.get(index)\n\t}\n\treturn mv.r.objects[index]\n}\n\n// getWritable returns an object that can be written to.\nfunc (mv *memoryView) getWritable(index uint32) object {\n\tif obj, ok := mv.objects[index]; ok {\n\t\t// Object is already in the current memory view, so can be modified.\n\t\treturn obj\n\t}\n\t// Object is not currently in this view. Get it, and clone it for use.\n\tobj := mv.get(index).clone()\n\tmv.r.objects[index] = obj\n\treturn obj\n}\n\n// Replace the object (indicated with index) with the given object. This put is\n// only done at the current memory view, so that if this memory view is reverted\n// the object is not changed.\nfunc (mv *memoryView) put(index uint32, obj object) {\n\tif mv.objects == nil {\n\t\tmv.objects = make(map[uint32]object)\n\t}\n\tif checks && mv.get(index).buffer == nil {\n\t\tpanic(\"writing to external object\")\n\t}\n\tif checks && mv.get(index).buffer.len(mv.r) != obj.buffer.len(mv.r) {\n\t\tpanic(\"put() with a differently-sized object\")\n\t}\n\tif checks && obj.constant {\n\t\tpanic(\"interp: store to a constant\")\n\t}\n\tmv.objects[index] = obj\n}\n\n// Load the value behind the given pointer. Returns nil if the pointer points to\n// an external global.\nfunc (mv *memoryView) load(p pointerValue, size uint32) value {\n\tif checks && mv.hasExternalStore(p) {\n\t\tpanic(\"interp: load from object with external store\")\n\t}\n\tobj := mv.get(p.index())\n\tif obj.buffer == nil {\n\t\t// External global, return nil.\n\t\treturn nil\n\t}\n\tif p.offset() == 0 && size == obj.size {\n\t\treturn obj.buffer.clone()\n\t}\n\tif checks && p.offset()+size > obj.size {\n\t\tpanic(\"interp: load out of bounds\")\n\t}\n\tv := obj.buffer.asRawValue(mv.r)\n\tloadedValue := rawValue{\n\t\tbuf: v.buf[p.offset() : p.offset()+size],\n\t}\n\treturn loadedValue\n}\n\n// Store to the value behind the given pointer. This overwrites the value in the\n// memory view, so that the changed value is discarded when the memory view is\n// reverted. Returns true on success, false if the object to store to is\n// external.\nfunc (mv *memoryView) store(v value, p pointerValue) bool {\n\tif checks && mv.hasExternalLoadOrStore(p) {\n\t\tpanic(\"interp: store to object with external load/store\")\n\t}\n\tobj := mv.get(p.index())\n\tif obj.buffer == nil {\n\t\t// External global, return false (for a failure).\n\t\treturn false\n\t}\n\tif checks && p.offset()+v.len(mv.r) > obj.size {\n\t\tpanic(\"interp: store out of bounds\")\n\t}\n\tif p.offset() == 0 && v.len(mv.r) == obj.buffer.len(mv.r) {\n\t\tobj.buffer = v\n\t} else {\n\t\tobj = obj.clone()\n\t\tbuffer := obj.buffer.asRawValue(mv.r)\n\t\tobj.buffer = buffer\n\t\tv := v.asRawValue(mv.r)\n\t\tfor i := uint32(0); i < v.len(mv.r); i++ {\n\t\t\tbuffer.buf[p.offset()+i] = v.buf[i]\n\t\t}\n\t}\n\tmv.put(p.index(), obj)\n\treturn true // success\n}\n\n// value is some sort of value, comparable to a LLVM constant. It can be\n// implemented in various ways for efficiency, but the fallback value (that all\n// implementations can be converted to except for localValue) is rawValue.\ntype value interface {\n\t// len returns the length in bytes.\n\tlen(r *runner) uint32\n\tclone() value\n\tasPointer(*runner) (pointerValue, error)\n\tasRawValue(*runner) rawValue\n\tUint(*runner) uint64\n\tInt(*runner) int64\n\ttoLLVMValue(llvm.Type, *memoryView) (llvm.Value, error)\n\tString() string\n}\n\n// literalValue contains simple integer values that don't need to be stored in a\n// buffer.\ntype literalValue struct {\n\tvalue interface{}\n}\n\n// Make a literalValue given the number of bits.\nfunc makeLiteralInt(value uint64, bits int) literalValue {\n\tswitch bits {\n\tcase 64:\n\t\treturn literalValue{value}\n\tcase 32:\n\t\treturn literalValue{uint32(value)}\n\tcase 16:\n\t\treturn literalValue{uint16(value)}\n\tcase 8:\n\t\treturn literalValue{uint8(value)}\n\tdefault:\n\t\tpanic(\"unknown integer size\")\n\t}\n}\n\nfunc (v literalValue) len(r *runner) uint32 {\n\tswitch v.value.(type) {\n\tcase uint64:\n\t\treturn 8\n\tcase uint32:\n\t\treturn 4\n\tcase uint16:\n\t\treturn 2\n\tcase uint8:\n\t\treturn 1\n\tdefault:\n\t\tpanic(\"unknown value type\")\n\t}\n}\n\nfunc (v literalValue) String() string {\n\t// Note: passing a nil *runner to v.Int because we know it won't use it.\n\treturn strconv.FormatInt(v.Int(nil), 10)\n}\n\nfunc (v literalValue) clone() value {\n\treturn v\n}\n\nfunc (v literalValue) asPointer(r *runner) (pointerValue, error) {\n\treturn pointerValue{}, errIntegerAsPointer\n}\n\nfunc (v literalValue) asRawValue(r *runner) rawValue {\n\tvar buf []byte\n\tswitch value := v.value.(type) {\n\tcase uint64:\n\t\tbuf = make([]byte, 8)\n\t\tr.byteOrder.PutUint64(buf, value)\n\tcase uint32:\n\t\tbuf = make([]byte, 4)\n\t\tr.byteOrder.PutUint32(buf, uint32(value))\n\tcase uint16:\n\t\tbuf = make([]byte, 2)\n\t\tr.byteOrder.PutUint16(buf, uint16(value))\n\tcase uint8:\n\t\tbuf = []byte{uint8(value)}\n\tdefault:\n\t\tpanic(\"unknown value type\")\n\t}\n\traw := newRawValue(uint32(len(buf)))\n\tfor i, b := range buf {\n\t\traw.buf[i] = uint64(b)\n\t}\n\treturn raw\n}\n\nfunc (v literalValue) Uint(r *runner) uint64 {\n\tswitch value := v.value.(type) {\n\tcase uint64:\n\t\treturn value\n\tcase uint32:\n\t\treturn uint64(value)\n\tcase uint16:\n\t\treturn uint64(value)\n\tcase uint8:\n\t\treturn uint64(value)\n\tdefault:\n\t\tpanic(\"inpterp: unknown literal type\")\n\t}\n}\n\nfunc (v literalValue) Int(r *runner) int64 {\n\tswitch value := v.value.(type) {\n\tcase uint64:\n\t\treturn int64(value)\n\tcase uint32:\n\t\treturn int64(int32(value))\n\tcase uint16:\n\t\treturn int64(int16(value))\n\tcase uint8:\n\t\treturn int64(int8(value))\n\tdefault:\n\t\tpanic(\"inpterp: unknown literal type\")\n\t}\n}\n\nfunc (v literalValue) toLLVMValue(llvmType llvm.Type, mem *memoryView) (llvm.Value, error) {\n\tswitch llvmType.TypeKind() {\n\tcase llvm.IntegerTypeKind:\n\t\tswitch value := v.value.(type) {\n\t\tcase uint64:\n\t\t\treturn llvm.ConstInt(llvmType, value, false), nil\n\t\tcase uint32:\n\t\t\treturn llvm.ConstInt(llvmType, uint64(value), false), nil\n\t\tcase uint16:\n\t\t\treturn llvm.ConstInt(llvmType, uint64(value), false), nil\n\t\tcase uint8:\n\t\t\treturn llvm.ConstInt(llvmType, uint64(value), false), nil\n\t\tdefault:\n\t\t\treturn llvm.Value{}, errors.New(\"interp: unknown literal type\")\n\t\t}\n\tcase llvm.DoubleTypeKind:\n\t\treturn llvm.ConstFloat(llvmType, math.Float64frombits(v.value.(uint64))), nil\n\tcase llvm.FloatTypeKind:\n\t\treturn llvm.ConstFloat(llvmType, float64(math.Float32frombits(v.value.(uint32)))), nil\n\tdefault:\n\t\treturn v.asRawValue(mem.r).toLLVMValue(llvmType, mem)\n\t}\n}\n\n// pointerValue contains a single pointer, with an offset into the underlying\n// object.\ntype pointerValue struct {\n\tpointer uint64 // low 32 bits are offset, high 32 bits are index\n}\n\nfunc newPointerValue(r *runner, index, offset int) pointerValue {\n\treturn pointerValue{\n\t\tpointer: uint64(index)<<32 | uint64(offset),\n\t}\n}\n\nfunc (v pointerValue) index() uint32 {\n\treturn uint32(v.pointer >> 32)\n}\n\nfunc (v pointerValue) offset() uint32 {\n\treturn uint32(v.pointer)\n}\n\n// addOffset essentially does a GEP operation (pointer arithmetic): it adds the\n// offset to the pointer. It also checks that the offset doesn't overflow the\n// maximum offset size (which is 4GB).\nfunc (v pointerValue) addOffset(offset int64) (pointerValue, error) {\n\tresult := pointerValue{v.pointer + uint64(offset)}\n\tif checks && v.index() != result.index() {\n\t\treturn result, fmt.Errorf(\"interp: offset %d out of range for object %v\", offset, v)\n\t}\n\treturn result, nil\n}\n\nfunc (v pointerValue) len(r *runner) uint32 {\n\treturn r.pointerSize\n}\n\nfunc (v pointerValue) String() string {\n\tname := strconv.Itoa(int(v.index()))\n\tif v.offset() == 0 {\n\t\treturn \"<\" + name + \">\"\n\t}\n\treturn \"<\" + name + \"+\" + strconv.Itoa(int(v.offset())) + \">\"\n}\n\nfunc (v pointerValue) clone() value {\n\treturn v\n}\n\nfunc (v pointerValue) asPointer(r *runner) (pointerValue, error) {\n\treturn v, nil\n}\n\nfunc (v pointerValue) asRawValue(r *runner) rawValue {\n\trv := newRawValue(r.pointerSize)\n\tfor i := range rv.buf {\n\t\trv.buf[i] = v.pointer\n\t}\n\treturn rv\n}\n\nfunc (v pointerValue) Uint(r *runner) uint64 {\n\tpanic(\"cannot convert pointer to integer\")\n}\n\nfunc (v pointerValue) Int(r *runner) int64 {\n\tpanic(\"cannot convert pointer to integer\")\n}\n\nfunc (v pointerValue) equal(rhs pointerValue) bool {\n\treturn v.pointer == rhs.pointer\n}\n\nfunc (v pointerValue) llvmValue(mem *memoryView) llvm.Value {\n\treturn mem.get(v.index()).llvmGlobal\n}\n\n// toLLVMValue returns the LLVM value for this pointer, which may be a GEP or\n// bitcast. The llvm.Type parameter is optional, if omitted the pointer type may\n// be different than expected.\nfunc (v pointerValue) toLLVMValue(llvmType llvm.Type, mem *memoryView) (llvm.Value, error) {\n\t// If a particular LLVM type is requested, cast to it.\n\tif !llvmType.IsNil() && llvmType.TypeKind() != llvm.PointerTypeKind {\n\t\t// The LLVM value has (or should have) the same bytes once compiled, but\n\t\t// does not have the right LLVM type. This can happen for example when\n\t\t// storing to a struct with a single pointer field: this pointer may\n\t\t// then become the value even though the pointer should be wrapped in a\n\t\t// struct.\n\t\t// This can be worked around by simply converting to a raw value,\n\t\t// rawValue knows how to create such structs.\n\t\treturn v.asRawValue(mem.r).toLLVMValue(llvmType, mem)\n\t}\n\n\t// Obtain the llvmValue, creating it if it doesn't exist yet.\n\tllvmValue := v.llvmValue(mem)\n\tif llvmValue.IsNil() {\n\t\t// The global does not yet exist. Probably this is the result of a\n\t\t// runtime.alloc.\n\t\t// First allocate a new global for this object.\n\t\tobj := mem.get(v.index())\n\t\talignment := obj.align\n\t\tif alignment == 0 {\n\t\t\t// Unknown alignment, perhaps from a direct call to runtime.alloc in\n\t\t\t// the runtime. Use a conservative default instead.\n\t\t\talignment = mem.r.maxAlign\n\t\t}\n\t\tif obj.llvmType.IsNil() && obj.llvmLayoutType.IsNil() {\n\t\t\t// Create an initializer without knowing the global type.\n\t\t\t// This is probably the result of a runtime.alloc call.\n\t\t\tinitializer, err := obj.buffer.asRawValue(mem.r).rawLLVMValue(mem)\n\t\t\tif err != nil {\n\t\t\t\treturn llvm.Value{}, err\n\t\t\t}\n\t\t\tglobalType := initializer.Type()\n\t\t\tllvmValue = llvm.AddGlobal(mem.r.mod, globalType, obj.globalName)\n\t\t\tllvmValue.SetInitializer(initializer)\n\t\t\tllvmValue.SetAlignment(alignment)\n\t\t\tobj.llvmGlobal = llvmValue\n\t\t\tmem.put(v.index(), obj)\n\t\t} else {\n\t\t\t// The global type is known, or at least its structure.\n\t\t\tvar globalType llvm.Type\n\t\t\tif !obj.llvmType.IsNil() {\n\t\t\t\t// The exact type is known.\n\t\t\t\tglobalType = obj.llvmType\n\t\t\t} else { // !obj.llvmLayoutType.IsNil()\n\t\t\t\t// The exact type isn't known, but the object layout is known.\n\t\t\t\tglobalType = obj.llvmLayoutType\n\t\t\t\t// The layout may not span the full size of the global because\n\t\t\t\t// of repetition. One example would be make([]string, 5) which\n\t\t\t\t// would be 10 words in size but the layout would only be two\n\t\t\t\t// words (for the string type).\n\t\t\t\ttypeSize := mem.r.targetData.TypeAllocSize(globalType)\n\t\t\t\tif typeSize != uint64(obj.size) {\n\t\t\t\t\tglobalType = llvm.ArrayType(globalType, int(uint64(obj.size)/typeSize))\n\t\t\t\t}\n\t\t\t}\n\t\t\tif checks && mem.r.targetData.TypeAllocSize(globalType) != uint64(obj.size) {\n\t\t\t\tpanic(\"size of the globalType isn't the same as the object size\")\n\t\t\t}\n\t\t\tllvmValue = llvm.AddGlobal(mem.r.mod, globalType, obj.globalName)\n\t\t\tobj.llvmGlobal = llvmValue\n\t\t\tmem.put(v.index(), obj)\n\n\t\t\t// Set the initializer for the global. Do this after creation to avoid\n\t\t\t// infinite recursion between creating the global and creating the\n\t\t\t// contents of the global (if the global contains itself).\n\t\t\tinitializer, err := obj.buffer.toLLVMValue(globalType, mem)\n\t\t\tif err != nil {\n\t\t\t\treturn llvm.Value{}, err\n\t\t\t}\n\t\t\tif checks && initializer.Type() != globalType {\n\t\t\t\treturn llvm.Value{}, errors.New(\"interp: allocated value does not match allocated type\")\n\t\t\t}\n\t\t\tllvmValue.SetInitializer(initializer)\n\t\t\tllvmValue.SetAlignment(alignment)\n\t\t}\n\n\t\t// It should be included in r.globals because otherwise markExternal\n\t\t// would consider it a new global (and would fail to mark this global as\n\t\t// having an externa load/store).\n\t\tmem.r.globals[llvmValue] = int(v.index())\n\t\tllvmValue.SetLinkage(llvm.InternalLinkage)\n\t}\n\n\tif v.offset() != 0 {\n\t\t// If there is an offset, make sure to use a GEP to index into the\n\t\t// pointer.\n\t\tllvmValue = llvm.ConstInBoundsGEP(mem.r.mod.Context().Int8Type(), llvmValue, []llvm.Value{\n\t\t\tllvm.ConstInt(mem.r.mod.Context().Int32Type(), uint64(v.offset()), false),\n\t\t})\n\t}\n\n\treturn llvmValue, nil\n}\n\n// rawValue is a raw memory buffer that can store either pointers or regular\n// data. This is the fallback data for everything that isn't clearly a\n// literalValue or pointerValue.\ntype rawValue struct {\n\t// An integer in buf contains either pointers or bytes.\n\t// If it is a byte, it is smaller than 256.\n\t// If it is a pointer, the index is contained in the upper 32 bits and the\n\t// offset is contained in the lower 32 bits.\n\tbuf []uint64\n}\n\nfunc newRawValue(size uint32) rawValue {\n\treturn rawValue{make([]uint64, size)}\n}\n\nfunc (v rawValue) len(r *runner) uint32 {\n\treturn uint32(len(v.buf))\n}\n\nfunc (v rawValue) String() string {\n\tif len(v.buf) == 2 || len(v.buf) == 4 || len(v.buf) == 8 {\n\t\t// Format as a pointer if the entire buf is this pointer.\n\t\tif v.buf[0] > 255 {\n\t\t\tisPointer := true\n\t\t\tfor _, p := range v.buf {\n\t\t\t\tif p != v.buf[0] {\n\t\t\t\t\tisPointer = false\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif isPointer {\n\t\t\t\treturn pointerValue{v.buf[0]}.String()\n\t\t\t}\n\t\t}\n\t\t// Format as number if none of the buf is a pointer.\n\t\tif !v.hasPointer() {\n\t\t\t// Construct a fake runner, which is little endian.\n\t\t\t// We only use String() for debugging, so this is is good enough\n\t\t\t// (the printed value will just be slightly wrong when debugging the\n\t\t\t// interp package with GOOS=mips for example).\n\t\t\tr := &runner{byteOrder: binary.LittleEndian}\n\t\t\treturn strconv.FormatInt(v.Int(r), 10)\n\t\t}\n\t}\n\treturn \"<[…\" + strconv.Itoa(len(v.buf)) + \"]>\"\n}\n\nfunc (v rawValue) clone() value {\n\tnewValue := v\n\tnewValue.buf = make([]uint64, len(v.buf))\n\tcopy(newValue.buf, v.buf)\n\treturn newValue\n}\n\nfunc (v rawValue) asPointer(r *runner) (pointerValue, error) {\n\tif v.buf[0] <= 255 {\n\t\t// Probably a null pointer or memory-mapped I/O.\n\t\treturn pointerValue{}, errIntegerAsPointer\n\t}\n\treturn pointerValue{v.buf[0]}, nil\n}\n\nfunc (v rawValue) asRawValue(r *runner) rawValue {\n\treturn v\n}\n\nfunc (v rawValue) bytes() []byte {\n\tbuf := make([]byte, len(v.buf))\n\tfor i, p := range v.buf {\n\t\tif p > 255 {\n\t\t\tpanic(\"cannot convert pointer value to byte\")\n\t\t}\n\t\tbuf[i] = byte(p)\n\t}\n\treturn buf\n}\n\nfunc (v rawValue) Uint(r *runner) uint64 {\n\tbuf := v.bytes()\n\n\tswitch len(v.buf) {\n\tcase 1:\n\t\treturn uint64(buf[0])\n\tcase 2:\n\t\treturn uint64(r.byteOrder.Uint16(buf))\n\tcase 4:\n\t\treturn uint64(r.byteOrder.Uint32(buf))\n\tcase 8:\n\t\treturn r.byteOrder.Uint64(buf)\n\tdefault:\n\t\tpanic(\"unknown integer size\")\n\t}\n}\n\nfunc (v rawValue) Int(r *runner) int64 {\n\tswitch len(v.buf) {\n\tcase 1:\n\t\treturn int64(int8(v.Uint(r)))\n\tcase 2:\n\t\treturn int64(int16(v.Uint(r)))\n\tcase 4:\n\t\treturn int64(int32(v.Uint(r)))\n\tcase 8:\n\t\treturn int64(int64(v.Uint(r)))\n\tdefault:\n\t\tpanic(\"unknown integer size\")\n\t}\n}\n\n// equal returns true if (and only if) the value matches rhs.\nfunc (v rawValue) equal(rhs rawValue) bool {\n\tif len(v.buf) != len(rhs.buf) {\n\t\tpanic(\"comparing values of different size\")\n\t}\n\tfor i, p := range v.buf {\n\t\tif rhs.buf[i] != p {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// rawLLVMValue returns a llvm.Value for this rawValue, making up a type as it\n// goes. The resulting value does not have a specified type, but it will be the\n// same size and have the same bytes if it was created with a provided LLVM type\n// (through toLLVMValue).\nfunc (v rawValue) rawLLVMValue(mem *memoryView) (llvm.Value, error) {\n\tvar structFields []llvm.Value\n\tctx := mem.r.mod.Context()\n\tint8Type := ctx.Int8Type()\n\n\tvar bytesBuf []llvm.Value\n\t// addBytes can be called after adding to bytesBuf to flush remaining bytes\n\t// to a new array in structFields.\n\taddBytes := func() {\n\t\tif len(bytesBuf) == 0 {\n\t\t\treturn\n\t\t}\n\t\tif len(bytesBuf) == 1 {\n\t\t\tstructFields = append(structFields, bytesBuf[0])\n\t\t} else {\n\t\t\tstructFields = append(structFields, llvm.ConstArray(int8Type, bytesBuf))\n\t\t}\n\t\tbytesBuf = nil\n\t}\n\n\t// Create structFields, converting the rawValue to a LLVM value.\n\tfor i := uint32(0); i < uint32(len(v.buf)); {\n\t\tif v.buf[i] > 255 {\n\t\t\taddBytes()\n\t\t\tfield, err := pointerValue{v.buf[i]}.toLLVMValue(llvm.Type{}, mem)\n\t\t\tif err != nil {\n\t\t\t\treturn llvm.Value{}, err\n\t\t\t}\n\t\t\tstructFields = append(structFields, field)\n\t\t\ti += mem.r.pointerSize\n\t\t\tcontinue\n\t\t}\n\t\tval := llvm.ConstInt(int8Type, uint64(v.buf[i]), false)\n\t\tbytesBuf = append(bytesBuf, val)\n\t\ti++\n\t}\n\taddBytes()\n\n\t// Return the created data.\n\tif len(structFields) == 1 {\n\t\treturn structFields[0], nil\n\t}\n\treturn ctx.ConstStruct(structFields, false), nil\n}\n\nfunc (v rawValue) toLLVMValue(llvmType llvm.Type, mem *memoryView) (llvm.Value, error) {\n\tisZero := true\n\tfor _, p := range v.buf {\n\t\tif p != 0 {\n\t\t\tisZero = false\n\t\t\tbreak\n\t\t}\n\t}\n\tif isZero {\n\t\treturn llvm.ConstNull(llvmType), nil\n\t}\n\tswitch llvmType.TypeKind() {\n\tcase llvm.IntegerTypeKind:\n\t\tif v.buf[0] > 255 {\n\t\t\tptr, err := v.asPointer(mem.r)\n\t\t\tif err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\t\t\tif checks && mem.r.targetData.TypeAllocSize(llvmType) != mem.r.targetData.TypeAllocSize(mem.r.dataPtrType) {\n\t\t\t\t// Probably trying to serialize a pointer to a byte array,\n\t\t\t\t// perhaps as a result of rawLLVMValue() in a previous interp\n\t\t\t\t// run.\n\t\t\t\treturn llvm.Value{}, errInvalidPtrToIntSize\n\t\t\t}\n\t\t\tv, err := ptr.toLLVMValue(llvm.Type{}, mem)\n\t\t\tif err != nil {\n\t\t\t\treturn llvm.Value{}, err\n\t\t\t}\n\t\t\treturn llvm.ConstPtrToInt(v, llvmType), nil\n\t\t}\n\t\tvar n uint64\n\t\tswitch llvmType.IntTypeWidth() {\n\t\tcase 64:\n\t\t\tn = rawValue{v.buf[:8]}.Uint(mem.r)\n\t\tcase 32:\n\t\t\tn = rawValue{v.buf[:4]}.Uint(mem.r)\n\t\tcase 16:\n\t\t\tn = rawValue{v.buf[:2]}.Uint(mem.r)\n\t\tcase 8:\n\t\t\tn = uint64(v.buf[0])\n\t\tcase 1:\n\t\t\tn = uint64(v.buf[0])\n\t\t\tif n != 0 && n != 1 {\n\t\t\t\tpanic(\"bool must be 0 or 1\")\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(\"unknown integer size\")\n\t\t}\n\t\treturn llvm.ConstInt(llvmType, n, false), nil\n\tcase llvm.StructTypeKind:\n\t\tfieldTypes := llvmType.StructElementTypes()\n\t\tfields := make([]llvm.Value, len(fieldTypes))\n\t\tfor i, fieldType := range fieldTypes {\n\t\t\toffset := mem.r.targetData.ElementOffset(llvmType, i)\n\t\t\tfield := rawValue{\n\t\t\t\tbuf: v.buf[offset:],\n\t\t\t}\n\t\t\tvar err error\n\t\t\tfields[i], err = field.toLLVMValue(fieldType, mem)\n\t\t\tif err != nil {\n\t\t\t\treturn llvm.Value{}, err\n\t\t\t}\n\t\t}\n\t\tif llvmType.StructName() != \"\" {\n\t\t\treturn llvm.ConstNamedStruct(llvmType, fields), nil\n\t\t}\n\t\treturn llvmType.Context().ConstStruct(fields, false), nil\n\tcase llvm.ArrayTypeKind:\n\t\tnumElements := llvmType.ArrayLength()\n\t\tchildType := llvmType.ElementType()\n\t\tchildTypeSize := mem.r.targetData.TypeAllocSize(childType)\n\t\tfields := make([]llvm.Value, numElements)\n\t\tfor i := range fields {\n\t\t\toffset := i * int(childTypeSize)\n\t\t\tfield := rawValue{\n\t\t\t\tbuf: v.buf[offset:],\n\t\t\t}\n\t\t\tvar err error\n\t\t\tfields[i], err = field.toLLVMValue(childType, mem)\n\t\t\tif err != nil {\n\t\t\t\treturn llvm.Value{}, err\n\t\t\t}\n\t\t\tif checks && fields[i].Type() != childType {\n\t\t\t\tpanic(\"child type doesn't match\")\n\t\t\t}\n\t\t}\n\t\treturn llvm.ConstArray(childType, fields), nil\n\tcase llvm.PointerTypeKind:\n\t\tif v.buf[0] > 255 {\n\t\t\t// This is a regular pointer.\n\t\t\tllvmValue, err := pointerValue{v.buf[0]}.toLLVMValue(llvm.Type{}, mem)\n\t\t\tif err != nil {\n\t\t\t\treturn llvm.Value{}, err\n\t\t\t}\n\t\t\tif llvmValue.Type() != llvmType {\n\t\t\t\tif llvmValue.Type().PointerAddressSpace() != llvmType.PointerAddressSpace() {\n\t\t\t\t\t// Special case for AVR function pointers.\n\t\t\t\t\t// Because go-llvm doesn't have addrspacecast at the moment,\n\t\t\t\t\t// do it indirectly with a ptrtoint/inttoptr pair.\n\t\t\t\t\tllvmValue = llvm.ConstIntToPtr(llvm.ConstPtrToInt(llvmValue, mem.r.uintptrType), llvmType)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn llvmValue, nil\n\t\t}\n\t\t// This is either a null pointer or a raw pointer for memory-mapped I/O\n\t\t// (such as 0xe000ed00).\n\t\tptr := rawValue{v.buf[:mem.r.pointerSize]}.Uint(mem.r)\n\t\tif ptr == 0 {\n\t\t\t// Null pointer.\n\t\t\treturn llvm.ConstNull(llvmType), nil\n\t\t}\n\t\tvar ptrValue llvm.Value // the underlying int\n\t\tswitch mem.r.pointerSize {\n\t\tcase 8:\n\t\t\tptrValue = llvm.ConstInt(llvmType.Context().Int64Type(), ptr, false)\n\t\tcase 4:\n\t\t\tptrValue = llvm.ConstInt(llvmType.Context().Int32Type(), ptr, false)\n\t\tcase 2:\n\t\t\tptrValue = llvm.ConstInt(llvmType.Context().Int16Type(), ptr, false)\n\t\tdefault:\n\t\t\treturn llvm.Value{}, errors.New(\"interp: unknown pointer size\")\n\t\t}\n\t\treturn llvm.ConstIntToPtr(ptrValue, llvmType), nil\n\tcase llvm.DoubleTypeKind:\n\t\tb := rawValue{v.buf[:8]}.Uint(mem.r)\n\t\tf := math.Float64frombits(b)\n\t\treturn llvm.ConstFloat(llvmType, f), nil\n\tcase llvm.FloatTypeKind:\n\t\tb := uint32(rawValue{v.buf[:4]}.Uint(mem.r))\n\t\tf := math.Float32frombits(b)\n\t\treturn llvm.ConstFloat(llvmType, float64(f)), nil\n\tdefault:\n\t\treturn llvm.Value{}, errors.New(\"interp: todo: raw value to LLVM value: \" + llvmType.String())\n\t}\n}\n\nfunc (v *rawValue) set(llvmValue llvm.Value, r *runner) {\n\tif llvmValue.IsNull() {\n\t\t// A zero value is common so check that first.\n\t\treturn\n\t}\n\tif !llvmValue.IsAGlobalValue().IsNil() {\n\t\tptrSize := r.pointerSize\n\t\tptr, err := r.getValue(llvmValue).asPointer(r)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\tfor i := uint32(0); i < ptrSize; i++ {\n\t\t\tv.buf[i] = ptr.pointer\n\t\t}\n\t} else if !llvmValue.IsAConstantExpr().IsNil() {\n\t\tswitch llvmValue.Opcode() {\n\t\tcase llvm.IntToPtr, llvm.PtrToInt, llvm.BitCast:\n\t\t\t// All these instructions effectively just reinterprets the bits\n\t\t\t// (like a bitcast) while no bits change and keeping the same\n\t\t\t// length, so just read its contents.\n\t\t\tv.set(llvmValue.Operand(0), r)\n\t\tcase llvm.GetElementPtr:\n\t\t\tptr := llvmValue.Operand(0)\n\t\t\tindex := llvmValue.Operand(1)\n\t\t\tnumOperands := llvmValue.OperandsCount()\n\t\t\telementType := llvmValue.GEPSourceElementType()\n\t\t\ttotalOffset := r.targetData.TypeAllocSize(elementType) * index.ZExtValue()\n\t\t\tfor i := 2; i < numOperands; i++ {\n\t\t\t\tindexValue := llvmValue.Operand(i)\n\t\t\t\tif checks && indexValue.IsAConstantInt().IsNil() {\n\t\t\t\t\tpanic(\"expected const gep index to be a constant integer\")\n\t\t\t\t}\n\t\t\t\tindex := indexValue.ZExtValue()\n\t\t\t\tswitch elementType.TypeKind() {\n\t\t\t\tcase llvm.StructTypeKind:\n\t\t\t\t\t// Indexing into a struct field.\n\t\t\t\t\toffsetInBytes := r.targetData.ElementOffset(elementType, int(index))\n\t\t\t\t\ttotalOffset += offsetInBytes\n\t\t\t\t\telementType = elementType.StructElementTypes()[index]\n\t\t\t\tdefault:\n\t\t\t\t\t// Indexing into an array.\n\t\t\t\t\telementType = elementType.ElementType()\n\t\t\t\t\telementSize := r.targetData.TypeAllocSize(elementType)\n\t\t\t\t\ttotalOffset += index * elementSize\n\t\t\t\t}\n\t\t\t}\n\t\t\tptrSize := r.pointerSize\n\t\t\tptrValue, err := r.getValue(ptr).asPointer(r)\n\t\t\tif err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\t\t\tptrValue.pointer += totalOffset\n\t\t\tfor i := uint32(0); i < ptrSize; i++ {\n\t\t\t\tv.buf[i] = ptrValue.pointer\n\t\t\t}\n\t\tcase llvm.ICmp:\n\t\t\t// Note: constant icmp isn't supported anymore in LLVM 19.\n\t\t\t// Once we drop support for LLVM 18, this can be removed.\n\t\t\tsize := r.targetData.TypeAllocSize(llvmValue.Operand(0).Type())\n\t\t\tlhs := newRawValue(uint32(size))\n\t\t\trhs := newRawValue(uint32(size))\n\t\t\tlhs.set(llvmValue.Operand(0), r)\n\t\t\trhs.set(llvmValue.Operand(1), r)\n\t\t\tif r.interpretICmp(lhs, rhs, llvmValue.IntPredicate()) {\n\t\t\t\tv.buf[0] = 1 // result is true\n\t\t\t} else {\n\t\t\t\tv.buf[0] = 0 // result is false\n\t\t\t}\n\t\tdefault:\n\t\t\tllvmValue.Dump()\n\t\t\tprintln()\n\t\t\tpanic(\"unknown constant expr\")\n\t\t}\n\t} else if llvmValue.IsUndef() {\n\t\t// Let undef be zero, by lack of an explicit 'undef' marker.\n\t} else {\n\t\tif checks && llvmValue.IsAConstant().IsNil() {\n\t\t\tpanic(\"expected a constant\")\n\t\t}\n\t\tllvmType := llvmValue.Type()\n\t\tswitch llvmType.TypeKind() {\n\t\tcase llvm.IntegerTypeKind:\n\t\t\tn := llvmValue.ZExtValue()\n\t\t\tswitch llvmValue.Type().IntTypeWidth() {\n\t\t\tcase 64:\n\t\t\t\tvar buf [8]byte\n\t\t\t\tr.byteOrder.PutUint64(buf[:], n)\n\t\t\t\tfor i, b := range buf {\n\t\t\t\t\tv.buf[i] = uint64(b)\n\t\t\t\t}\n\t\t\tcase 32:\n\t\t\t\tvar buf [4]byte\n\t\t\t\tr.byteOrder.PutUint32(buf[:], uint32(n))\n\t\t\t\tfor i, b := range buf {\n\t\t\t\t\tv.buf[i] = uint64(b)\n\t\t\t\t}\n\t\t\tcase 16:\n\t\t\t\tvar buf [2]byte\n\t\t\t\tr.byteOrder.PutUint16(buf[:], uint16(n))\n\t\t\t\tfor i, b := range buf {\n\t\t\t\t\tv.buf[i] = uint64(b)\n\t\t\t\t}\n\t\t\tcase 8, 1:\n\t\t\t\tv.buf[0] = n\n\t\t\tdefault:\n\t\t\t\tpanic(\"unknown integer size\")\n\t\t\t}\n\t\tcase llvm.StructTypeKind:\n\t\t\tnumElements := llvmType.StructElementTypesCount()\n\t\t\tfor i := 0; i < numElements; i++ {\n\t\t\t\toffset := r.targetData.ElementOffset(llvmType, i)\n\t\t\t\tfield := rawValue{\n\t\t\t\t\tbuf: v.buf[offset:],\n\t\t\t\t}\n\t\t\t\tfield.set(r.builder.CreateExtractValue(llvmValue, i, \"\"), r)\n\t\t\t}\n\t\tcase llvm.ArrayTypeKind:\n\t\t\tnumElements := llvmType.ArrayLength()\n\t\t\tchildType := llvmType.ElementType()\n\t\t\tchildTypeSize := r.targetData.TypeAllocSize(childType)\n\t\t\tfor i := 0; i < numElements; i++ {\n\t\t\t\toffset := i * int(childTypeSize)\n\t\t\t\tfield := rawValue{\n\t\t\t\t\tbuf: v.buf[offset:],\n\t\t\t\t}\n\t\t\t\tfield.set(r.builder.CreateExtractValue(llvmValue, i, \"\"), r)\n\t\t\t}\n\t\tcase llvm.DoubleTypeKind:\n\t\t\tf, _ := llvmValue.DoubleValue()\n\t\t\tvar buf [8]byte\n\t\t\tr.byteOrder.PutUint64(buf[:], math.Float64bits(f))\n\t\t\tfor i, b := range buf {\n\t\t\t\tv.buf[i] = uint64(b)\n\t\t\t}\n\t\tcase llvm.FloatTypeKind:\n\t\t\tf, _ := llvmValue.DoubleValue()\n\t\t\tvar buf [4]byte\n\t\t\tr.byteOrder.PutUint32(buf[:], math.Float32bits(float32(f)))\n\t\t\tfor i, b := range buf {\n\t\t\t\tv.buf[i] = uint64(b)\n\t\t\t}\n\t\tdefault:\n\t\t\tllvmValue.Dump()\n\t\t\tprintln()\n\t\t\tpanic(\"unknown constant\")\n\t\t}\n\t}\n}\n\n// hasPointer returns true if this raw value contains a pointer somewhere in the\n// buffer.\nfunc (v rawValue) hasPointer() bool {\n\tfor _, p := range v.buf {\n\t\tif p > 255 {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// localValue is a special implementation of the value interface. It is a\n// placeholder for other values in instruction operands, and is replaced with\n// one of the others before executing.\ntype localValue struct {\n\tvalue llvm.Value\n}\n\nfunc (v localValue) len(r *runner) uint32 {\n\tpanic(\"interp: localValue.len\")\n}\n\nfunc (v localValue) String() string {\n\treturn \"<!>\"\n}\n\nfunc (v localValue) clone() value {\n\tpanic(\"interp: localValue.clone()\")\n}\n\nfunc (v localValue) asPointer(r *runner) (pointerValue, error) {\n\treturn pointerValue{}, errors.New(\"interp: localValue.asPointer called\")\n}\n\nfunc (v localValue) asRawValue(r *runner) rawValue {\n\tpanic(\"interp: localValue.asRawValue\")\n}\n\nfunc (v localValue) Uint(r *runner) uint64 {\n\tpanic(\"interp: localValue.Uint\")\n}\n\nfunc (v localValue) Int(r *runner) int64 {\n\tpanic(\"interp: localValue.Int\")\n}\n\nfunc (v localValue) toLLVMValue(llvmType llvm.Type, mem *memoryView) (llvm.Value, error) {\n\treturn v.value, nil\n}\n\nfunc (r *runner) getValue(llvmValue llvm.Value) value {\n\tif checks && llvmValue.IsNil() {\n\t\tpanic(\"nil llvmValue\")\n\t}\n\tif !llvmValue.IsAGlobalValue().IsNil() {\n\t\tindex, ok := r.globals[llvmValue]\n\t\tif !ok {\n\t\t\tobj := object{\n\t\t\t\tllvmGlobal: llvmValue,\n\t\t\t}\n\t\t\tindex = len(r.objects)\n\t\t\tr.globals[llvmValue] = index\n\t\t\tr.objects = append(r.objects, obj)\n\t\t\tif !llvmValue.IsAGlobalVariable().IsNil() {\n\t\t\t\tobj.size = uint32(r.targetData.TypeAllocSize(llvmValue.GlobalValueType()))\n\t\t\t\tif initializer := llvmValue.Initializer(); !initializer.IsNil() {\n\t\t\t\t\tobj.buffer = r.getValue(initializer)\n\t\t\t\t\tobj.constant = llvmValue.IsGlobalConstant()\n\t\t\t\t}\n\t\t\t} else if !llvmValue.IsAFunction().IsNil() {\n\t\t\t\t// OK\n\t\t\t} else {\n\t\t\t\tpanic(\"interp: unknown global value\")\n\t\t\t}\n\t\t\t// Update the object after it has been created. This avoids an\n\t\t\t// infinite recursion when using getValue on a global that contains\n\t\t\t// a reference to itself.\n\t\t\tr.objects[index] = obj\n\t\t}\n\t\treturn newPointerValue(r, index, 0)\n\t} else if !llvmValue.IsAConstant().IsNil() {\n\t\tif !llvmValue.IsAConstantInt().IsNil() {\n\t\t\tn := llvmValue.ZExtValue()\n\t\t\tswitch llvmValue.Type().IntTypeWidth() {\n\t\t\tcase 64:\n\t\t\t\treturn literalValue{n}\n\t\t\tcase 32:\n\t\t\t\treturn literalValue{uint32(n)}\n\t\t\tcase 16:\n\t\t\t\treturn literalValue{uint16(n)}\n\t\t\tcase 8, 1:\n\t\t\t\treturn literalValue{uint8(n)}\n\t\t\tdefault:\n\t\t\t\tpanic(\"unknown integer size\")\n\t\t\t}\n\t\t}\n\t\tsize := r.targetData.TypeAllocSize(llvmValue.Type())\n\t\tv := newRawValue(uint32(size))\n\t\tv.set(llvmValue, r)\n\t\treturn v\n\t} else if !llvmValue.IsAInstruction().IsNil() || !llvmValue.IsAArgument().IsNil() {\n\t\treturn localValue{llvmValue}\n\t} else if !llvmValue.IsAInlineAsm().IsNil() {\n\t\treturn localValue{llvmValue}\n\t} else {\n\t\tllvmValue.Dump()\n\t\tprintln()\n\t\tpanic(\"unknown value\")\n\t}\n}\n\n// readObjectLayout reads the object layout as it is stored by the compiler. It\n// returns the size in the number of words and the bitmap.\n//\n// For details on this format, see src/runtime/gc_precise.go.\nfunc (r *runner) readObjectLayout(layoutValue value) (uint64, *big.Int) {\n\tpointerSize := layoutValue.len(r)\n\tif checks && uint64(pointerSize) != r.targetData.TypeAllocSize(r.dataPtrType) {\n\t\tpanic(\"inconsistent pointer size\")\n\t}\n\n\t// The object layout can be stored in a global variable, directly as an\n\t// integer value, or can be nil.\n\tptr, err := layoutValue.asPointer(r)\n\tif err == errIntegerAsPointer {\n\t\t// It's an integer, which means it's a small object or unknown.\n\t\tlayout := layoutValue.Uint(r)\n\t\tif layout == 0 {\n\t\t\t// Nil pointer, which means the layout is unknown.\n\t\t\treturn 0, nil\n\t\t}\n\t\tif layout%2 != 1 {\n\t\t\t// Sanity check: the least significant bit must be set. This is how\n\t\t\t// the runtime can separate pointers from integers.\n\t\t\tpanic(\"unexpected layout\")\n\t\t}\n\n\t\t// Determine format of bitfields in the integer.\n\t\tpointerBits := uint64(pointerSize * 8)\n\t\tvar sizeFieldBits uint64\n\t\tswitch pointerBits {\n\t\tcase 16:\n\t\t\tsizeFieldBits = 4\n\t\tcase 32:\n\t\t\tsizeFieldBits = 5\n\t\tcase 64:\n\t\t\tsizeFieldBits = 6\n\t\tdefault:\n\t\t\tpanic(\"unknown pointer size\")\n\t\t}\n\n\t\t// Extract fields.\n\t\tobjectSizeWords := (layout >> 1) & (1<<sizeFieldBits - 1)\n\t\tbitmap := new(big.Int).SetUint64(layout >> (1 + sizeFieldBits))\n\t\treturn objectSizeWords, bitmap\n\t}\n\n\t// Read the object size in words and the bitmap from the global.\n\tbuf := r.objects[ptr.index()].buffer.(rawValue)\n\tobjectSizeWords := rawValue{buf: buf.buf[:r.pointerSize]}.Uint(r)\n\trawByteValues := buf.buf[r.pointerSize:]\n\trawBytes := make([]byte, len(rawByteValues))\n\tfor i, v := range rawByteValues {\n\t\tif uint64(byte(v)) != v {\n\t\t\tpanic(\"found pointer in data array?\") // sanity check\n\t\t}\n\t\trawBytes[i] = byte(v)\n\t}\n\treverseBytes(rawBytes) // little-endian to big-endian\n\tbitmap := new(big.Int).SetBytes(rawBytes)\n\treturn objectSizeWords, bitmap\n}\n\n// getLLVMTypeFromLayout returns the 'layout type', which is an approximation of\n// the real type. Pointers are in the correct location but the actual object may\n// have some additional repetition, for example in the buffer of a slice.\nfunc (r *runner) getLLVMTypeFromLayout(layoutValue value) llvm.Type {\n\tobjectSizeWords, bitmap := r.readObjectLayout(layoutValue)\n\tif bitmap == nil {\n\t\t// No information available.\n\t\treturn llvm.Type{}\n\t}\n\n\tif bitmap.BitLen() == 0 {\n\t\t// There are no pointers in this object, so treat this as a raw byte\n\t\t// buffer. This is important because objects without pointers may have\n\t\t// lower alignment.\n\t\treturn r.mod.Context().Int8Type()\n\t}\n\n\t// Create the LLVM type.\n\tpointerSize := layoutValue.len(r)\n\tpointerAlignment := r.targetData.PrefTypeAlignment(r.dataPtrType)\n\tvar fields []llvm.Type\n\tfor i := 0; i < int(objectSizeWords); {\n\t\tif bitmap.Bit(i) != 0 {\n\t\t\t// Pointer field.\n\t\t\tfields = append(fields, r.dataPtrType)\n\t\t\ti += int(pointerSize / uint32(pointerAlignment))\n\t\t} else {\n\t\t\t// Byte/word field.\n\t\t\tfields = append(fields, r.mod.Context().IntType(pointerAlignment*8))\n\t\t\ti += 1\n\t\t}\n\t}\n\tvar llvmLayoutType llvm.Type\n\tif len(fields) == 1 {\n\t\tllvmLayoutType = fields[0]\n\t} else {\n\t\tllvmLayoutType = r.mod.Context().StructType(fields, false)\n\t}\n\n\tobjectSizeBytes := objectSizeWords * uint64(pointerAlignment)\n\tif checks && r.targetData.TypeAllocSize(llvmLayoutType) != objectSizeBytes {\n\t\tpanic(\"unexpected size\") // sanity check\n\t}\n\treturn llvmLayoutType\n}\n\n// Reverse a slice of bytes. From the wiki:\n// https://github.com/golang/go/wiki/SliceTricks#reversing\nfunc reverseBytes(buf []byte) {\n\tfor i := len(buf)/2 - 1; i >= 0; i-- {\n\t\topp := len(buf) - 1 - i\n\t\tbuf[i], buf[opp] = buf[opp], buf[i]\n\t}\n}\n"
  },
  {
    "path": "interp/testdata/alloc.ll",
    "content": "target datalayout = \"e-m:e-p:32:32-i64:64-n32:64-S128\"\ntarget triple = \"wasm32--wasi\"\n\n@\"runtime/gc.layout:62-2000000000000001\" = linkonce_odr unnamed_addr constant { i32, [8 x i8] } { i32 62, [8 x i8] c\"\\01\\00\\00\\00\\00\\00\\00 \" }\n@pointerFree12 = global ptr null\n@pointerFree7 = global ptr null\n@pointerFree3 = global ptr null\n@pointerFree0 = global ptr null\n@layout1 = global ptr null\n@layout2 = global ptr null\n@layout3 = global ptr null\n@layout4 = global ptr null\n@bigobj1 = global ptr null\n\ndeclare ptr @runtime.alloc(i32, ptr) unnamed_addr\n\ndefine void @runtime.initAll() unnamed_addr {\n  call void @main.init()\n  ret void\n}\n\ndefine internal void @main.init() unnamed_addr {\n  ; Object that's word-aligned.\n  %pointerFree12 = call ptr @runtime.alloc(i32 12, ptr inttoptr (i32 3 to ptr))\n  store ptr %pointerFree12, ptr @pointerFree12\n  ; Object larger than a word but not word-aligned.\n  %pointerFree7 = call ptr @runtime.alloc(i32 7, ptr inttoptr (i32 3 to ptr))\n  store ptr %pointerFree7, ptr @pointerFree7\n  ; Object smaller than a word (and of course not word-aligned).\n  %pointerFree3 = call ptr @runtime.alloc(i32 3, ptr inttoptr (i32 3 to ptr))\n  store ptr %pointerFree3, ptr @pointerFree3\n  ; Zero-sized object.\n  %pointerFree0 = call ptr @runtime.alloc(i32 0, ptr inttoptr (i32 3 to ptr))\n  store ptr %pointerFree0, ptr @pointerFree0\n\n  ; Object made out of 3 pointers.\n  %layout1 = call ptr @runtime.alloc(i32 12, ptr inttoptr (i32 67 to ptr))\n  store ptr %layout1, ptr @layout1\n  ; Array (or slice) of 5 slices.\n  %layout2 = call ptr @runtime.alloc(i32 60, ptr inttoptr (i32 71 to ptr))\n  store ptr %layout2, ptr @layout2\n  ; Oddly shaped object, using all bits in the layout integer.\n  %layout3 = call ptr @runtime.alloc(i32 104, ptr inttoptr (i32 2467830261 to ptr))\n  store ptr %layout3, ptr @layout3\n  ; ...repeated.\n  %layout4 = call ptr @runtime.alloc(i32 312, ptr inttoptr (i32 2467830261 to ptr))\n  store ptr %layout4, ptr @layout4\n\n  ; Large object that needs to be stored in a separate global.\n  %bigobj1 = call ptr @runtime.alloc(i32 248, ptr @\"runtime/gc.layout:62-2000000000000001\")\n  store ptr %bigobj1, ptr @bigobj1\n  ret void\n}\n"
  },
  {
    "path": "interp/testdata/alloc.out.ll",
    "content": "target datalayout = \"e-m:e-p:32:32-i64:64-n32:64-S128\"\ntarget triple = \"wasm32--wasi\"\n\n@pointerFree12 = local_unnamed_addr global ptr @\"main$alloc\"\n@pointerFree7 = local_unnamed_addr global ptr @\"main$alloc.1\"\n@pointerFree3 = local_unnamed_addr global ptr @\"main$alloc.2\"\n@pointerFree0 = local_unnamed_addr global ptr @\"main$alloc.3\"\n@layout1 = local_unnamed_addr global ptr @\"main$alloc.4\"\n@layout2 = local_unnamed_addr global ptr @\"main$alloc.5\"\n@layout3 = local_unnamed_addr global ptr @\"main$alloc.6\"\n@layout4 = local_unnamed_addr global ptr @\"main$alloc.7\"\n@bigobj1 = local_unnamed_addr global ptr @\"main$alloc.8\"\n@\"main$alloc\" = internal global [12 x i8] zeroinitializer, align 4\n@\"main$alloc.1\" = internal global [7 x i8] zeroinitializer, align 4\n@\"main$alloc.2\" = internal global [3 x i8] zeroinitializer, align 4\n@\"main$alloc.3\" = internal global [0 x i8] zeroinitializer, align 4\n@\"main$alloc.4\" = internal global [3 x ptr] zeroinitializer, align 4\n@\"main$alloc.5\" = internal global [5 x { ptr, i32, i32 }] zeroinitializer, align 4\n@\"main$alloc.6\" = internal global { ptr, ptr, ptr, i32, i32, ptr, ptr, i32, i32, i32, i32, i32, i32, ptr, ptr, i32, i32, i32, ptr, ptr, i32, i32, ptr, i32, i32, ptr } zeroinitializer, align 4\n@\"main$alloc.7\" = internal global [3 x { ptr, ptr, ptr, i32, i32, ptr, ptr, i32, i32, i32, i32, i32, i32, ptr, ptr, i32, i32, i32, ptr, ptr, i32, i32, ptr, i32, i32, ptr }] zeroinitializer, align 4\n@\"main$alloc.8\" = internal global { ptr, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, ptr } zeroinitializer, align 4\n\ndefine void @runtime.initAll() unnamed_addr {\n  ret void\n}\n"
  },
  {
    "path": "interp/testdata/basic.ll",
    "content": "target datalayout = \"e-m:e-i64:64-f80:128-n8:16:32:64-S128\"\ntarget triple = \"x86_64--linux\"\n\n@main.v1 = internal global i64 0\n@main.nonConst1 = global [4 x i64] zeroinitializer\n@main.nonConst2 = global i64 0\n@main.someArray = global [8 x {i16, i32}] zeroinitializer\n@main.exportedValue = global [1 x ptr] [ptr @main.exposedValue1]\n@main.exportedConst = constant i64 42\n@main.exposedValue1 = global i16 0\n@main.exposedValue2 = global i16 0\n@main.insertedValue = global {i8, i32, {float, {i64, i16}}} zeroinitializer\n@main.gepArray = global [8 x i8] zeroinitializer\n@main.negativeGEP = global ptr null\n\ndeclare void @runtime.printint64(i64) unnamed_addr\n\ndeclare void @runtime.printnl() unnamed_addr\n\ndefine void @runtime.initAll() unnamed_addr {\nentry:\n  call void @runtime.init()\n  call void @main.init()\n  ret void\n}\n\ndefine void @main() unnamed_addr {\nentry:\n  %0 = load i64, ptr @main.v1\n  call void @runtime.printint64(i64 %0)\n  call void @runtime.printnl()\n  ret void\n}\n\ndefine internal void @runtime.init() unnamed_addr {\nentry:\n  ret void\n}\n\ndefine internal void @main.init() unnamed_addr {\nentry:\n  store i64 3, ptr @main.v1\n  call void @\"main.init#1\"()\n\n  ; test the following pattern:\n  ;     func someValue() int // extern function\n  ;     var nonConst1 = [4]int{someValue(), 0, 0, 0}\n  %value1 = call i64 @someValue()\n  %gep1 = getelementptr [4 x i64], ptr @main.nonConst1, i32 0, i32 0\n  store i64 %value1, ptr %gep1\n\n  ; Test that the global really is marked dirty:\n  ;     var nonConst2 = nonConst1[0]\n  %gep2 = getelementptr [4 x i64], ptr @main.nonConst1, i32 0, i32 0\n  %value2 = load i64, ptr %gep2\n  store i64 %value2, ptr @main.nonConst2\n\n  ; Test that the following GEP works:\n  ;     var someArray\n  ;     modifyExternal(&someArray[3].field1)\n  %gep3 = getelementptr [8 x {i16, i32}], ptr @main.someArray, i32 0, i32 3, i32 1\n  call void @modifyExternal(ptr %gep3)\n\n  ; Test that marking a value as external also marks all referenced values.\n  call void @modifyExternal(ptr @main.exportedValue)\n  store i16 5, ptr @main.exposedValue1\n\n  ; Test that marking a constant as external still allows loading from it.\n  call void @readExternal(ptr @main.exportedConst)\n  %constLoad = load i64, ptr @main.exportedConst\n  call void @runtime.printint64(i64 %constLoad)\n\n  ; Test that this even propagates through functions.\n  call void @modifyExternal(ptr @willModifyGlobal)\n  store i16 7, ptr @main.exposedValue2\n\n  ; Test that inline assembly is ignored.\n  call void @modifyExternal(ptr @hasInlineAsm)\n\n  ; Test switch statement.\n  %switch1 = call i64 @testSwitch(i64 1) ; 1 returns 6\n  %switch2 = call i64 @testSwitch(i64 9) ; 9 returns the default value -1\n  call void @runtime.printint64(i64 %switch1)\n  call void @runtime.printint64(i64 %switch2)\n\n  ; Test extractvalue/insertvalue with multiple operands.\n  %agg = call {i8, i32, {float, {i64, i16}}} @nestedStruct()\n  %elt = extractvalue {i8, i32, {float, {i64, i16}}} %agg, 2, 1, 0\n  call void @runtime.printint64(i64 %elt)\n  %agg2 = insertvalue {i8, i32, {float, {i64, i16}}} %agg, i64 5, 2, 1, 0\n  store {i8, i32, {float, {i64, i16}}} %agg2, ptr @main.insertedValue\n\n  ; negative GEP instruction\n  %ngep1 = getelementptr [8 x i8], ptr @main.negativeGEP, i32 0, i32 5\n  %ngep2 = getelementptr [8 x i8], ptr %ngep1, i32 0, i32 -3\n  store ptr %ngep2, ptr @main.negativeGEP\n\n  ret void\n}\n\ndefine internal void @\"main.init#1\"() unnamed_addr {\nentry:\n  call void @runtime.printint64(i64 5)\n  call void @runtime.printnl()\n  ret void\n}\n\ndeclare i64 @someValue()\n\ndeclare void @modifyExternal(ptr)\n\ndeclare void @readExternal(ptr)\n\n; This function will modify an external value. By passing this function as a\n; function pointer to an external function, @main.exposedValue2 should be\n; marked as external.\ndefine void @willModifyGlobal() {\nentry:\n  store i16 8, ptr @main.exposedValue2\n  ret void\n}\n\n; Inline assembly should be ignored in the interp package. While it is possible\n; to modify other globals that way, usually that's not the case and there is no\n; real way to check.\ndefine void @hasInlineAsm() {\nentry:\n  call void asm sideeffect \"\", \"\"()\n  ret void\n}\n\ndefine i64 @testSwitch(i64 %val) {\nentry:\n  ; Test switch statement.\n  switch i64 %val, label %otherwise [ i64 0, label %zero\n                                      i64 1, label %one\n                                      i64 2, label %two ]\nzero:\n  ret i64 5\n\none:\n  ret i64 6\n\ntwo:\n  ret i64 7\n\notherwise:\n  ret i64 -1\n}\n\ndeclare {i8, i32, {float, {i64, i16}}} @nestedStruct()\n"
  },
  {
    "path": "interp/testdata/basic.out.ll",
    "content": "target datalayout = \"e-m:e-i64:64-f80:128-n8:16:32:64-S128\"\ntarget triple = \"x86_64--linux\"\n\n@main.nonConst1 = local_unnamed_addr global [4 x i64] zeroinitializer\n@main.nonConst2 = local_unnamed_addr global i64 0\n@main.someArray = global [8 x { i16, i32 }] zeroinitializer\n@main.exportedValue = global [1 x ptr] [ptr @main.exposedValue1]\n@main.exportedConst = constant i64 42\n@main.exposedValue1 = global i16 0\n@main.exposedValue2 = local_unnamed_addr global i16 0\n@main.insertedValue = local_unnamed_addr global { i8, i32, { float, { i64, i16 } } } zeroinitializer\n@main.gepArray = local_unnamed_addr global [8 x i8] zeroinitializer\n@main.negativeGEP = global ptr getelementptr inbounds nuw (i8, ptr @main.negativeGEP, i64 2)\n\ndeclare void @runtime.printint64(i64) unnamed_addr\n\ndeclare void @runtime.printnl() unnamed_addr\n\ndefine void @runtime.initAll() unnamed_addr {\nentry:\n  call void @runtime.printint64(i64 5)\n  call void @runtime.printnl()\n  %value1 = call i64 @someValue()\n  store i64 %value1, ptr @main.nonConst1, align 8\n  %value2 = load i64, ptr @main.nonConst1, align 8\n  store i64 %value2, ptr @main.nonConst2, align 8\n  call void @modifyExternal(ptr getelementptr inbounds (i8, ptr @main.someArray, i32 28))\n  call void @modifyExternal(ptr @main.exportedValue)\n  store i16 5, ptr @main.exposedValue1, align 2\n  call void @readExternal(ptr @main.exportedConst)\n  call void @runtime.printint64(i64 42)\n  call void @modifyExternal(ptr @willModifyGlobal)\n  store i16 7, ptr @main.exposedValue2, align 2\n  call void @modifyExternal(ptr @hasInlineAsm)\n  call void @runtime.printint64(i64 6)\n  call void @runtime.printint64(i64 -1)\n  %agg = call { i8, i32, { float, { i64, i16 } } } @nestedStruct()\n  %elt.agg = extractvalue { i8, i32, { float, { i64, i16 } } } %agg, 2\n  %elt.agg1 = extractvalue { float, { i64, i16 } } %elt.agg, 1\n  %elt = extractvalue { i64, i16 } %elt.agg1, 0\n  call void @runtime.printint64(i64 %elt)\n  %agg2.agg0 = extractvalue { i8, i32, { float, { i64, i16 } } } %agg, 2\n  %agg2.agg1 = extractvalue { float, { i64, i16 } } %agg2.agg0, 1\n  %agg2.insertvalue2 = insertvalue { i64, i16 } %agg2.agg1, i64 5, 0\n  %agg2.insertvalue1 = insertvalue { float, { i64, i16 } } %agg2.agg0, { i64, i16 } %agg2.insertvalue2, 1\n  %agg2.insertvalue0 = insertvalue { i8, i32, { float, { i64, i16 } } } %agg, { float, { i64, i16 } } %agg2.insertvalue1, 2\n  store { i8, i32, { float, { i64, i16 } } } %agg2.insertvalue0, ptr @main.insertedValue, align 8\n  ret void\n}\n\ndefine void @main() unnamed_addr {\nentry:\n  call void @runtime.printint64(i64 3)\n  call void @runtime.printnl()\n  ret void\n}\n\ndeclare i64 @someValue() local_unnamed_addr\n\ndeclare void @modifyExternal(ptr) local_unnamed_addr\n\ndeclare void @readExternal(ptr) local_unnamed_addr\n\ndefine void @willModifyGlobal() {\nentry:\n  store i16 8, ptr @main.exposedValue2, align 2\n  ret void\n}\n\ndefine void @hasInlineAsm() {\nentry:\n  call void asm sideeffect \"\", \"\"()\n  ret void\n}\n\ndefine i64 @testSwitch(i64 %val) local_unnamed_addr {\nentry:\n  switch i64 %val, label %otherwise [\n    i64 0, label %zero\n    i64 1, label %one\n    i64 2, label %two\n  ]\n\nzero:                                             ; preds = %entry\n  ret i64 5\n\none:                                              ; preds = %entry\n  ret i64 6\n\ntwo:                                              ; preds = %entry\n  ret i64 7\n\notherwise:                                        ; preds = %entry\n  ret i64 -1\n}\n\ndeclare { i8, i32, { float, { i64, i16 } } } @nestedStruct() local_unnamed_addr\n"
  },
  {
    "path": "interp/testdata/consteval.ll",
    "content": "target datalayout = \"e-m:e-i64:64-f80:128-n8:16:32:64-S128\"\ntarget triple = \"x86_64--linux\"\n\n@intToPtrResult = global i8 0\n@ptrToIntResult = global i8 0\n@pointerTagResult = global i64 0\n@someArray = internal global {i16, i8, i8} zeroinitializer\n@someArrayPointer = global ptr zeroinitializer\n\ndefine void @runtime.initAll() {\n  call void @main.init()\n  ret void\n}\n\ndefine internal void @main.init() {\n  call void @testIntToPtr()\n  call void @testPtrToInt()\n  call void @testConstGEP()\n  call void @testPointerTag()\n  ret void\n}\n\ndefine internal void @testIntToPtr() {\n  %nil = icmp eq ptr inttoptr (i64 1024 to ptr), null\n  br i1 %nil, label %a, label %b\na:\n  ; should not be reached\n  store i8 1, ptr @intToPtrResult\n  ret void\nb:\n  ; should be reached\n  store i8 2, ptr @intToPtrResult\n  ret void\n}\n\ndefine internal void @testPtrToInt() {\n  %zero = icmp eq i64 ptrtoint (ptr @ptrToIntResult to i64), 0\n  br i1 %zero, label %a, label %b\na:\n  ; should not be reached\n  store i8 1, ptr @ptrToIntResult\n  ret void\nb:\n  ; should be reached\n  store i8 2, ptr @ptrToIntResult\n  ret void\n}\n\ndefine internal void @testConstGEP() {\n  store ptr getelementptr inbounds (i8, ptr @someArray, i32 2), ptr @someArrayPointer\n  ret void\n}\n\ndefine internal void @testPointerTag() {\n  %val = and i64 ptrtoint (ptr getelementptr inbounds (i8, ptr @someArray, i32 2) to i64), 3\n  store i64 %val, ptr @pointerTagResult\n  ret void\n}\n"
  },
  {
    "path": "interp/testdata/consteval.out.ll",
    "content": "target datalayout = \"e-m:e-i64:64-f80:128-n8:16:32:64-S128\"\ntarget triple = \"x86_64--linux\"\n\n@intToPtrResult = local_unnamed_addr global i8 2\n@ptrToIntResult = local_unnamed_addr global i8 2\n@pointerTagResult = local_unnamed_addr global i64 2\n@someArray = internal global { i16, i8, i8 } zeroinitializer\n@someArrayPointer = local_unnamed_addr global ptr getelementptr inbounds nuw (i8, ptr @someArray, i64 2)\n\ndefine void @runtime.initAll() local_unnamed_addr {\n  ret void\n}\n"
  },
  {
    "path": "interp/testdata/interface.ll",
    "content": "target datalayout = \"e-m:e-i64:64-f80:128-n8:16:32:64-S128\"\ntarget triple = \"x86_64--linux\"\n\n@main.v1 = global i1 0\n@main.v2 = global i1 0\n@\"reflect/types.type:named:main.foo\" = private constant { i8, ptr, ptr } { i8 34, ptr @\"reflect/types.type:pointer:named:main.foo\", ptr @\"reflect/types.type:basic:int\" }, align 4\n@\"reflect/types.type:pointer:named:main.foo\" = external constant { i8, ptr }\n@\"reflect/types.typeid:named:main.foo\" = external constant i8\n@\"reflect/types.type:basic:int\" = private constant { i8, ptr } { i8 2, ptr @\"reflect/types.type:pointer:basic:int\" }, align 4\n@\"reflect/types.type:pointer:basic:int\" = external constant { i8, ptr }\n\n\ndeclare i1 @runtime.typeAssert(ptr, ptr, ptr, ptr)\n\ndefine void @runtime.initAll() unnamed_addr {\nentry:\n  call void @main.init()\n  ret void\n}\n\ndefine internal void @main.init() unnamed_addr {\nentry:\n  ; Test type asserts.\n  %typecode = call i1 @runtime.typeAssert(ptr @\"reflect/types.type:named:main.foo\", ptr @\"reflect/types.typeid:named:main.foo\", ptr undef, ptr null)\n  store i1 %typecode, ptr @main.v1\n  %typecode2 = call i1 @runtime.typeAssert(ptr null, ptr @\"reflect/types.typeid:named:main.foo\", ptr undef, ptr null)\n  store i1 %typecode2, ptr @main.v2\n  ret void\n}\n"
  },
  {
    "path": "interp/testdata/interface.out.ll",
    "content": "target datalayout = \"e-m:e-i64:64-f80:128-n8:16:32:64-S128\"\ntarget triple = \"x86_64--linux\"\n\n@main.v1 = local_unnamed_addr global i1 true\n@main.v2 = local_unnamed_addr global i1 false\n\ndefine void @runtime.initAll() unnamed_addr {\nentry:\n  ret void\n}\n"
  },
  {
    "path": "interp/testdata/phi.ll",
    "content": "target datalayout = \"e-m:e-i64:64-f80:128-n8:16:32:64-S128\"\ntarget triple = \"x86_64--linux\"\n\n@main.phiNodesResultA = global i8 0\n@main.phiNodesResultB = global i8 0\n\ndefine void @runtime.initAll() {\n  call void @main.init()\n  ret void\n}\n\n; PHI nodes always use the value from the previous block, even in a loop. This\n; means that the loop below should swap the values %a and %b on each iteration.\n; Previously there was a bug which resulted in %b getting the value 3 on the\n; second iteration while it should have gotten 1 (from the first iteration of\n; %for.loop).\ndefine internal void @main.init() {\nentry:\n  br label %for.loop\n\nfor.loop:\n  %a = phi i8 [ 1, %entry ], [ %b, %for.loop ]\n  %b = phi i8 [ 3, %entry ], [ %a, %for.loop ]\n  %icmp = icmp eq i8 %a, 3\n  br i1 %icmp, label %for.done, label %for.loop\n\nfor.done:\n  store i8 %a, ptr @main.phiNodesResultA\n  store i8 %b, ptr @main.phiNodesResultB\n  ret void\n}\n"
  },
  {
    "path": "interp/testdata/phi.out.ll",
    "content": "target datalayout = \"e-m:e-i64:64-f80:128-n8:16:32:64-S128\"\ntarget triple = \"x86_64--linux\"\n\n@main.phiNodesResultA = local_unnamed_addr global i8 3\n@main.phiNodesResultB = local_unnamed_addr global i8 1\n\ndefine void @runtime.initAll() local_unnamed_addr {\n  ret void\n}\n"
  },
  {
    "path": "interp/testdata/revert.ll",
    "content": "target datalayout = \"e-m:e-i64:64-f80:128-n8:16:32:64-S128\"\ntarget triple = \"x86_64--linux\"\n\ndeclare void @externalCall(i64)\n\ndeclare i64 @ptrHash(ptr nocapture)\n\n@foo.knownAtRuntime = global i64 0\n@bar.knownAtRuntime = global i64 0\n@baz.someGlobal = external global [3 x {i64, i32}]\n@baz.someInt = global i32 0\n@x.atomicNum = global i32 0\n@x.volatileNum = global i32 0\n@y.ready = global i32 0\n@z.bloom = global i64 0\n@z.arr = global [32 x i8] zeroinitializer\n\ndefine void @runtime.initAll() unnamed_addr {\nentry:\n  call void @baz.init(ptr undef)\n  call void @foo.init(ptr undef)\n  call void @bar.init(ptr undef)\n  call void @main.init(ptr undef)\n  call void @x.init(ptr undef)\n  call void @y.init(ptr undef)\n  call void @z.init(ptr undef)\n  ret void\n}\n\ndefine internal void @foo.init(ptr %context) unnamed_addr {\n  store i64 5, ptr @foo.knownAtRuntime\n  unreachable ; this triggers a revert of @foo.init.\n}\n\ndefine internal void @bar.init(ptr %context) unnamed_addr {\n  %val = load i64, ptr @foo.knownAtRuntime\n  store i64 %val, ptr @bar.knownAtRuntime\n  ret void\n}\n\ndefine internal void @baz.init(ptr %context) unnamed_addr {\n  ; Test extractvalue/insertvalue with more than one index.\n  %val = load [3 x {i64, i32}], ptr @baz.someGlobal\n  %part = extractvalue [3 x {i64, i32}] %val, 0, 1\n  %val2 = insertvalue [3 x {i64, i32}] %val, i32 5, 2, 1\n  unreachable ; trigger revert\n}\n\ndefine internal void @main.init(ptr %context) unnamed_addr {\nentry:\n  call void @externalCall(i64 3)\n  ret void\n}\n\n\ndefine internal void @x.init(ptr %context) unnamed_addr {\n  ; Test atomic and volatile memory accesses.\n  store atomic i32 1, ptr @x.atomicNum seq_cst, align 4\n  %x = load atomic i32, ptr @x.atomicNum seq_cst, align 4\n  store i32 %x, ptr @x.atomicNum\n  %y = load volatile i32, ptr @x.volatileNum\n  store volatile i32 %y, ptr @x.volatileNum\n  ret void\n}\n\ndefine internal void @y.init(ptr %context) unnamed_addr {\nentry:\n  br label %loop\n\nloop:\n  ; Test a wait-loop.\n  ; This function must be reverted.\n  %val = load atomic i32, ptr @y.ready seq_cst, align 4\n  %ready = icmp eq i32 %val, 1\n  br i1 %ready, label %end, label %loop\n\nend:\n  ret void\n}\n\ndefine internal void @z.init(ptr %context) unnamed_addr {\n  ; This can be safely expanded.\n  call void @z.setArr(ptr @z.bloom, i64 1, ptr @z.bloom)\n\n  ; This call should be reverted to prevent unrolling.\n  call void @z.setArr(ptr @z.arr, i64 32, ptr @z.bloom)\n\n  ret void\n}\n\ndefine internal void @z.setArr(ptr %arr, i64 %n, ptr %context) unnamed_addr {\nentry:\n  br label %loop\n\nloop:\n  %prev = phi i64 [ %n, %entry ], [ %idx, %loop ]\n  %idx = sub i64 %prev, 1\n  %elem = getelementptr i8, ptr %arr, i64 %idx\n  call void @z.set(ptr %elem, ptr %context)\n  %done = icmp eq i64 %idx, 0\n  br i1 %done, label %end, label %loop\n\nend:\n  ret void\n}\n\ndefine internal void @z.set(ptr %ptr, ptr %context) unnamed_addr {\n  ; Insert the pointer into the Bloom filter.\n  %hash = call i64 @ptrHash(ptr %ptr)\n  %index = lshr i64 %hash, 58\n  %bit = shl i64 1, %index\n  %old = load i64, ptr %context\n  %new = or i64 %old, %bit\n  store i64 %new, ptr %context\n  ret void\n}\n"
  },
  {
    "path": "interp/testdata/revert.out.ll",
    "content": "target datalayout = \"e-m:e-i64:64-f80:128-n8:16:32:64-S128\"\ntarget triple = \"x86_64--linux\"\n\n@foo.knownAtRuntime = local_unnamed_addr global i64 0\n@bar.knownAtRuntime = local_unnamed_addr global i64 0\n@baz.someGlobal = external local_unnamed_addr global [3 x { i64, i32 }]\n@baz.someInt = local_unnamed_addr global i32 0\n@x.atomicNum = local_unnamed_addr global i32 0\n@x.volatileNum = global i32 0\n@y.ready = local_unnamed_addr global i32 0\n@z.bloom = global i64 0\n@z.arr = global [32 x i8] zeroinitializer\n\ndeclare void @externalCall(i64) local_unnamed_addr\n\ndeclare i64 @ptrHash(ptr nocapture) local_unnamed_addr\n\ndefine void @runtime.initAll() unnamed_addr {\nentry:\n  call fastcc void @baz.init(ptr undef)\n  call fastcc void @foo.init(ptr undef)\n  %val = load i64, ptr @foo.knownAtRuntime, align 8\n  store i64 %val, ptr @bar.knownAtRuntime, align 8\n  call void @externalCall(i64 3)\n  store atomic i32 1, ptr @x.atomicNum seq_cst, align 4\n  %x = load atomic i32, ptr @x.atomicNum seq_cst, align 4\n  store i32 %x, ptr @x.atomicNum, align 4\n  %y = load volatile i32, ptr @x.volatileNum, align 4\n  store volatile i32 %y, ptr @x.volatileNum, align 4\n  call fastcc void @y.init(ptr undef)\n  call fastcc void @z.set(ptr @z.bloom, ptr @z.bloom)\n  call fastcc void @z.setArr(ptr @z.arr, i64 32, ptr @z.bloom)\n  ret void\n}\n\ndefine internal fastcc void @foo.init(ptr %context) unnamed_addr {\n  store i64 5, ptr @foo.knownAtRuntime, align 8\n  unreachable\n}\n\ndefine internal fastcc void @baz.init(ptr %context) unnamed_addr {\n  unreachable\n}\n\ndefine internal fastcc void @y.init(ptr %context) unnamed_addr {\nentry:\n  br label %loop\n\nloop:                                             ; preds = %loop, %entry\n  %val = load atomic i32, ptr @y.ready seq_cst, align 4\n  %ready = icmp eq i32 %val, 1\n  br i1 %ready, label %end, label %loop\n\nend:                                              ; preds = %loop\n  ret void\n}\n\ndefine internal fastcc void @z.setArr(ptr %arr, i64 %n, ptr %context) unnamed_addr {\nentry:\n  br label %loop\n\nloop:                                             ; preds = %loop, %entry\n  %prev = phi i64 [ %n, %entry ], [ %idx, %loop ]\n  %idx = sub i64 %prev, 1\n  %elem = getelementptr i8, ptr %arr, i64 %idx\n  call fastcc void @z.set(ptr %elem, ptr %context)\n  %done = icmp eq i64 %idx, 0\n  br i1 %done, label %end, label %loop\n\nend:                                              ; preds = %loop\n  ret void\n}\n\ndefine internal fastcc void @z.set(ptr %ptr, ptr %context) unnamed_addr {\n  %hash = call i64 @ptrHash(ptr %ptr)\n  %index = lshr i64 %hash, 58\n  %bit = shl i64 1, %index\n  %old = load i64, ptr %context, align 8\n  %new = or i64 %old, %bit\n  store i64 %new, ptr %context, align 8\n  ret void\n}\n"
  },
  {
    "path": "interp/testdata/slice-copy.ll",
    "content": "target datalayout = \"e-m:e-i64:64-f80:128-n8:16:32:64-S128\"\ntarget triple = \"x86_64--linux\"\n\n@main.uint8SliceSrc.buf = internal global [2 x i8] c\"\\03d\"\n@main.uint8SliceSrc = internal unnamed_addr global { ptr, i64, i64 } { ptr @main.uint8SliceSrc.buf, i64 2, i64 2 }\n@main.uint8SliceDst = internal unnamed_addr global { ptr, i64, i64 } zeroinitializer\n@main.int16SliceSrc.buf = internal global [3 x i16] [i16 5, i16 123, i16 1024]\n@main.int16SliceSrc = internal unnamed_addr global { ptr, i64, i64 } { ptr @main.int16SliceSrc.buf, i64 3, i64 3 }\n@main.int16SliceDst = internal unnamed_addr global { ptr, i64, i64 } zeroinitializer\n@main.sliceSrcUntaint.buf = internal global [2 x i8] c\"ab\"\n@main.sliceDstUntaint.buf = internal global [2 x i8] zeroinitializer\n@main.sliceSrcTaint.buf = internal global [2 x i8] c\"cd\"\n@main.sliceDstTaint.buf = internal global [2 x i8] zeroinitializer\n@main.sliceSrcExternal1.buf = external global [2 x i8]\n@main.sliceDstExternal1.buf = internal global [2 x i8] zeroinitializer\n@main.sliceSrcExternal2.buf = internal global [2 x i8] zeroinitializer\n@main.sliceDstExternal2.buf = external global [2 x i8]\n\ndeclare i64 @runtime.sliceCopy(ptr %dst, ptr %src, i64 %dstLen, i64 %srcLen, i64 %elemSize) unnamed_addr\n\ndeclare ptr @runtime.alloc(i64, ptr) unnamed_addr\n\ndeclare void @runtime.printuint8(i8)\n\ndeclare void @runtime.printint16(i16)\n\ndeclare void @use(ptr)\n\ndefine void @runtime.initAll() unnamed_addr {\nentry:\n  call void @main.init()\n  ret void\n}\n\ndefine void @main() unnamed_addr {\nentry:\n  ; print(uintSliceSrc[0])\n  %uint8SliceSrc.buf = load ptr, ptr @main.uint8SliceSrc\n  %uint8SliceSrc.val = load i8, ptr %uint8SliceSrc.buf\n  call void @runtime.printuint8(i8 %uint8SliceSrc.val)\n\n  ; print(uintSliceDst[0])\n  %uint8SliceDst.buf = load ptr, ptr @main.uint8SliceDst\n  %uint8SliceDst.val = load i8, ptr %uint8SliceDst.buf\n  call void @runtime.printuint8(i8 %uint8SliceDst.val)\n\n  ; print(int16SliceSrc[0])\n  %int16SliceSrc.buf = load ptr, ptr @main.int16SliceSrc\n  %int16SliceSrc.val = load i16, ptr %int16SliceSrc.buf\n  call void @runtime.printint16(i16 %int16SliceSrc.val)\n\n  ; print(int16SliceDst[0])\n  %int16SliceDst.buf = load ptr, ptr @main.int16SliceDst\n  %int16SliceDst.val = load i16, ptr %int16SliceDst.buf\n  call void @runtime.printint16(i16 %int16SliceDst.val)\n\n  ; print(sliceDstUntaint[0])\n  %sliceDstUntaint.val = load i8, ptr getelementptr inbounds (i8, ptr @main.sliceDstUntaint.buf, i32 0)\n  call void @runtime.printuint8(i8 %sliceDstUntaint.val)\n\n  ; print(sliceDstTaint[0])\n  %sliceDstTaint.val = load i8, ptr getelementptr inbounds (i8, ptr @main.sliceDstTaint.buf, i32 0)\n  call void @runtime.printuint8(i8 %sliceDstTaint.val)\n\n  ; print(sliceDstExternal1[0])\n  %sliceDstExternal1.val = load i8, ptr getelementptr inbounds (i8, ptr @main.sliceDstExternal1.buf, i32 0)\n  call void @runtime.printuint8(i8 %sliceDstExternal1.val)\n\n  ; print(sliceDstExternal2[0])\n  %sliceDstExternal2.val = load i8, ptr getelementptr inbounds (i8, ptr @main.sliceDstExternal2.buf, i32 0)\n  call void @runtime.printuint8(i8 %sliceDstExternal2.val)\n\n  ret void\n}\n\ndefine internal void @main.init() unnamed_addr {\nentry:\n  ; equivalent of:\n  ;     uint8SliceDst = make([]uint8, len(uint8SliceSrc))\n  %uint8SliceSrc = load { ptr, i64, i64 }, ptr @main.uint8SliceSrc\n  %uint8SliceSrc.len = extractvalue { ptr, i64, i64 } %uint8SliceSrc, 1\n  %uint8SliceDst.buf = call ptr @runtime.alloc(i64 %uint8SliceSrc.len, ptr null)\n  %0 = insertvalue { ptr, i64, i64 } undef, ptr %uint8SliceDst.buf, 0\n  %1 = insertvalue { ptr, i64, i64 } %0, i64 %uint8SliceSrc.len, 1\n  %2 = insertvalue { ptr, i64, i64 } %1, i64 %uint8SliceSrc.len, 2\n  store { ptr, i64, i64 } %2, ptr @main.uint8SliceDst\n\n  ; equivalent of:\n  ;     copy(uint8SliceDst, uint8SliceSrc)\n  %uint8SliceSrc.buf = extractvalue { ptr, i64, i64 } %uint8SliceSrc, 0\n  %copy.n = call i64 @runtime.sliceCopy(ptr %uint8SliceDst.buf, ptr %uint8SliceSrc.buf, i64 %uint8SliceSrc.len, i64 %uint8SliceSrc.len, i64 1)\n\n  ; equivalent of:\n  ;     int16SliceDst = make([]int16, len(int16SliceSrc))\n  %int16SliceSrc = load { ptr, i64, i64 }, ptr @main.int16SliceSrc\n  %int16SliceSrc.len = extractvalue { ptr, i64, i64 } %int16SliceSrc, 1\n  %int16SliceSrc.len.bytes = mul i64 %int16SliceSrc.len, 2\n  %int16SliceDst.buf = call ptr @runtime.alloc(i64 %int16SliceSrc.len.bytes, ptr null)\n  %3 = insertvalue { ptr, i64, i64 } undef, ptr %int16SliceDst.buf, 0\n  %4 = insertvalue { ptr, i64, i64 } %3, i64 %int16SliceSrc.len, 1\n  %5 = insertvalue { ptr, i64, i64 } %4, i64 %int16SliceSrc.len, 2\n  store { ptr, i64, i64 } %5, ptr @main.int16SliceDst\n\n  ; equivalent of:\n  ;     copy(int16SliceDst, int16SliceSrc)\n  %int16SliceSrc.buf = extractvalue { ptr, i64, i64 } %int16SliceSrc, 0\n  %copy.n2 = call i64 @runtime.sliceCopy(ptr %int16SliceDst.buf, ptr %int16SliceSrc.buf, i64 %int16SliceSrc.len, i64 %int16SliceSrc.len, i64 2)\n\n  ; Copy slice that has a known value.\n  %copy.n3 = call i64 @runtime.sliceCopy(ptr @main.sliceDstUntaint.buf, ptr @main.sliceSrcUntaint.buf, i64 2, i64 2, i64 1)\n\n  ; Copy slice that might have been modified by the external @use call.\n  ; This is a fix for https://github.com/tinygo-org/tinygo/issues/3890.\n  call void @use(ptr @main.sliceSrcTaint.buf)\n  %copy.n4 = call i64 @runtime.sliceCopy(ptr @main.sliceDstTaint.buf, ptr @main.sliceSrcTaint.buf, i64 2, i64 2, i64 1)\n\n  ; Test that copying from or into external buffers works correctly.\n  ; These copy operations must be done at runtime.\n  ; https://github.com/tinygo-org/tinygo/issues/4895\n  %copy.n5 = call i64 @runtime.sliceCopy(ptr @main.sliceDstExternal1.buf, ptr @main.sliceSrcExternal1.buf, i64 2, i64 2, i64 1)\n  %copy.n6 = call i64 @runtime.sliceCopy(ptr @main.sliceDstExternal2.buf, ptr @main.sliceSrcExternal2.buf, i64 2, i64 2, i64 1)\n\n  ret void\n}\n"
  },
  {
    "path": "interp/testdata/slice-copy.out.ll",
    "content": "target datalayout = \"e-m:e-i64:64-f80:128-n8:16:32:64-S128\"\ntarget triple = \"x86_64--linux\"\n\n@main.sliceSrcTaint.buf = internal global [2 x i8] c\"cd\"\n@main.sliceDstTaint.buf = internal global [2 x i8] zeroinitializer\n@main.sliceSrcExternal1.buf = external global [2 x i8]\n@main.sliceDstExternal1.buf = internal global [2 x i8] zeroinitializer\n@main.sliceSrcExternal2.buf = internal global [2 x i8] zeroinitializer\n@main.sliceDstExternal2.buf = external global [2 x i8]\n\ndeclare i64 @runtime.sliceCopy(ptr, ptr, i64, i64, i64) unnamed_addr\n\ndeclare void @runtime.printuint8(i8) local_unnamed_addr\n\ndeclare void @runtime.printint16(i16) local_unnamed_addr\n\ndeclare void @use(ptr) local_unnamed_addr\n\ndefine void @runtime.initAll() unnamed_addr {\nentry:\n  call void @use(ptr @main.sliceSrcTaint.buf)\n  %copy.n4 = call i64 @runtime.sliceCopy(ptr @main.sliceDstTaint.buf, ptr @main.sliceSrcTaint.buf, i64 2, i64 2, i64 1)\n  %copy.n5 = call i64 @runtime.sliceCopy(ptr @main.sliceDstExternal1.buf, ptr @main.sliceSrcExternal1.buf, i64 2, i64 2, i64 1)\n  %copy.n6 = call i64 @runtime.sliceCopy(ptr @main.sliceDstExternal2.buf, ptr @main.sliceSrcExternal2.buf, i64 2, i64 2, i64 1)\n  ret void\n}\n\ndefine void @main() unnamed_addr {\nentry:\n  call void @runtime.printuint8(i8 3)\n  call void @runtime.printuint8(i8 3)\n  call void @runtime.printint16(i16 5)\n  call void @runtime.printint16(i16 5)\n  call void @runtime.printuint8(i8 97)\n  %sliceDstTaint.val = load i8, ptr @main.sliceDstTaint.buf, align 1\n  call void @runtime.printuint8(i8 %sliceDstTaint.val)\n  %sliceDstExternal1.val = load i8, ptr @main.sliceDstExternal1.buf, align 1\n  call void @runtime.printuint8(i8 %sliceDstExternal1.val)\n  %sliceDstExternal2.val = load i8, ptr @main.sliceDstExternal2.buf, align 1\n  call void @runtime.printuint8(i8 %sliceDstExternal2.val)\n  ret void\n}\n"
  },
  {
    "path": "lib/picolibc-stdio.c",
    "content": "// This file is included in the picolibc build.\n// It makes stdio functions available to the C library.\n\n#include <stdio.h>\n#include <sys/cdefs.h>\n\n// Defined in the runtime package. Writes to the default console (usually, the\n// first UART or an USB-CDC device).\nint runtime_putchar(char, FILE*);\n\n// Define stdin, stdout, and stderr as a single object.\n// This object must not reside in ROM.\nstatic FILE __stdio = FDEV_SETUP_STREAM(runtime_putchar, NULL, NULL, _FDEV_SETUP_WRITE);\n\n// Define the underlying structs for stdin, stdout, and stderr.\nFILE *const stdin = &__stdio;\n__strong_reference(stdin, stdout);\n__strong_reference(stdin, stderr);\n"
  },
  {
    "path": "loader/errors.go",
    "content": "package loader\n\nimport \"go/scanner\"\n\n// Errors contains a list of parser errors or a list of typechecker errors for\n// the given package.\ntype Errors struct {\n\tPkg  *Package\n\tErrs []error\n}\n\nfunc (e Errors) Error() string {\n\treturn \"could not compile: \" + e.Errs[0].Error()\n}\n\n// Error is a regular error but with an added import stack. This is especially\n// useful for debugging import cycle errors.\ntype Error struct {\n\tImportStack []string\n\tErr         scanner.Error\n}\n\nfunc (e Error) Error() string {\n\treturn e.Err.Error()\n}\n\n// Error returned when loading a *Program for a test binary but no test files\n// are present.\ntype NoTestFilesError struct {\n\tImportPath string\n}\n\nfunc (e NoTestFilesError) Error() string {\n\treturn \"no test files\"\n}\n"
  },
  {
    "path": "loader/goroot.go",
    "content": "package loader\n\n// This file constructs a new temporary GOROOT directory by merging both the\n// standard Go GOROOT and the GOROOT from TinyGo using symlinks.\n//\n// The goal is to replace specific packages from Go with a TinyGo version. It's\n// never a partial replacement, either a package is fully replaced or it is not.\n// This is important because if we did allow to merge packages (e.g. by adding\n// files to a package), it would lead to a dependency on implementation details\n// with all the maintenance burden that results in. Only allowing to replace\n// packages as a whole avoids this as packages are already designed to have a\n// public (backwards-compatible) API.\n\nimport (\n\t\"crypto/sha512\"\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"io\"\n\t\"io/fs\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"sort\"\n\t\"sync\"\n\n\t\"github.com/tinygo-org/tinygo/compileopts\"\n\t\"github.com/tinygo-org/tinygo/goenv\"\n)\n\nvar gorootCreateMutex sync.Mutex\n\n// GetCachedGoroot creates a new GOROOT by merging both the standard GOROOT and\n// the GOROOT from TinyGo using lots of symbolic links.\nfunc GetCachedGoroot(config *compileopts.Config) (string, error) {\n\tgoroot := goenv.Get(\"GOROOT\")\n\tif goroot == \"\" {\n\t\treturn \"\", errors.New(\"could not determine GOROOT\")\n\t}\n\ttinygoroot := goenv.Get(\"TINYGOROOT\")\n\tif tinygoroot == \"\" {\n\t\treturn \"\", errors.New(\"could not determine TINYGOROOT\")\n\t}\n\n\t// Find the overrides needed for the goroot.\n\toverrides := pathsToOverride(config.GoMinorVersion, needsSyscallPackage(config.BuildTags()))\n\n\t// Resolve the merge links within the goroot.\n\tmerge, err := listGorootMergeLinks(goroot, tinygoroot, overrides)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\t// Hash the merge links to create a cache key.\n\tdata, err := json.Marshal(merge)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\thash := sha512.Sum512_256(data)\n\n\t// Do not try to create the cached GOROOT in parallel, that's only a waste\n\t// of I/O bandwidth and thus speed. Instead, use a mutex to make sure only\n\t// one goroutine does it at a time.\n\t// This is not a way to ensure atomicity (a different TinyGo invocation\n\t// could be creating the same directory), but instead a way to avoid\n\t// creating it many times in parallel when running tests in parallel.\n\tgorootCreateMutex.Lock()\n\tdefer gorootCreateMutex.Unlock()\n\n\t// Check if the goroot already exists.\n\tcachedGorootName := \"goroot-\" + hex.EncodeToString(hash[:])\n\tcachedgoroot := filepath.Join(goenv.Get(\"GOCACHE\"), cachedGorootName)\n\tif _, err := os.Stat(cachedgoroot); err == nil {\n\t\treturn cachedgoroot, nil\n\t}\n\n\t// Create the cache directory if it does not already exist.\n\terr = os.MkdirAll(goenv.Get(\"GOCACHE\"), 0777)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\t// Create a temporary directory to construct the goroot within.\n\ttmpgoroot, err := os.MkdirTemp(goenv.Get(\"GOCACHE\"), cachedGorootName+\".tmp\")\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\t// Remove the temporary directory if it wasn't moved to the right place\n\t// (for example, when there was an error).\n\tdefer os.RemoveAll(tmpgoroot)\n\n\t// Create the directory structure.\n\t// The directories are created in sorted order so that nested directories are created without extra work.\n\t{\n\t\tvar dirs []string\n\t\tfor dir, merge := range overrides {\n\t\t\tif merge {\n\t\t\t\tdirs = append(dirs, filepath.Join(tmpgoroot, \"src\", dir))\n\t\t\t}\n\t\t}\n\t\tsort.Strings(dirs)\n\n\t\tfor _, dir := range dirs {\n\t\t\terr := os.Mkdir(dir, 0777)\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", err\n\t\t\t}\n\t\t}\n\t}\n\n\t// Create all symlinks.\n\tfor dst, src := range merge {\n\t\terr := symlink(src, filepath.Join(tmpgoroot, dst))\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t}\n\n\t// Rename the new merged gorooot into place.\n\terr = os.Rename(tmpgoroot, cachedgoroot)\n\tif err != nil {\n\t\tif errors.Is(err, fs.ErrExist) {\n\t\t\t// Another invocation of TinyGo also seems to have created a GOROOT.\n\t\t\t// Use that one instead. Our new GOROOT will be automatically\n\t\t\t// deleted by the defer above.\n\t\t\treturn cachedgoroot, nil\n\t\t}\n\t\tif runtime.GOOS == \"windows\" && errors.Is(err, fs.ErrPermission) {\n\t\t\t// On Windows, a rename with a destination directory that already\n\t\t\t// exists does not result in an IsExist error, but rather in an\n\t\t\t// access denied error. To be sure, check for this case by checking\n\t\t\t// whether the target directory exists.\n\t\t\tif _, err := os.Stat(cachedgoroot); err == nil {\n\t\t\t\treturn cachedgoroot, nil\n\t\t\t}\n\t\t}\n\t\treturn \"\", err\n\t}\n\treturn cachedgoroot, nil\n}\n\n// listGorootMergeLinks searches goroot and tinygoroot for all symlinks that must be created within the merged goroot.\nfunc listGorootMergeLinks(goroot, tinygoroot string, overrides map[string]bool) (map[string]string, error) {\n\tgoSrc := filepath.Join(goroot, \"src\")\n\ttinygoSrc := filepath.Join(tinygoroot, \"src\")\n\tmerges := make(map[string]string)\n\tfor dir, merge := range overrides {\n\t\tif !merge {\n\t\t\t// Use the TinyGo version.\n\t\t\tmerges[filepath.Join(\"src\", dir)] = filepath.Join(tinygoSrc, dir)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Add files from TinyGo.\n\t\ttinygoDir := filepath.Join(tinygoSrc, dir)\n\t\ttinygoEntries, err := os.ReadDir(tinygoDir)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tvar hasTinyGoFiles bool\n\t\tfor _, e := range tinygoEntries {\n\t\t\tif e.IsDir() {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Link this file.\n\t\t\tname := e.Name()\n\t\t\tmerges[filepath.Join(\"src\", dir, name)] = filepath.Join(tinygoDir, name)\n\n\t\t\thasTinyGoFiles = true\n\t\t}\n\n\t\t// Add all directories from $GOROOT that are not part of the TinyGo\n\t\t// overrides.\n\t\tgoDir := filepath.Join(goSrc, dir)\n\t\tgoEntries, err := os.ReadDir(goDir)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tfor _, e := range goEntries {\n\t\t\tisDir := e.IsDir()\n\t\t\tif hasTinyGoFiles && !isDir {\n\t\t\t\t// Only merge files from Go if TinyGo does not have any files.\n\t\t\t\t// Otherwise we'd end up with a weird mix from both Go\n\t\t\t\t// implementations.\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tname := e.Name()\n\t\t\tif _, ok := overrides[path.Join(dir, name)+\"/\"]; ok {\n\t\t\t\t// This entry is overridden by TinyGo.\n\t\t\t\t// It has/will be merged elsewhere.\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Add a link to this entry\n\t\t\tmerges[filepath.Join(\"src\", dir, name)] = filepath.Join(goDir, name)\n\t\t}\n\t}\n\n\t// Merge the special directories from goroot.\n\tfor _, dir := range []string{\"bin\", \"lib\", \"pkg\"} {\n\t\tmerges[dir] = filepath.Join(goroot, dir)\n\t}\n\n\t// Required starting in Go 1.21 due to https://github.com/golang/go/issues/61928\n\tif _, err := os.Stat(filepath.Join(goroot, \"go.env\")); err == nil {\n\t\tmerges[\"go.env\"] = filepath.Join(goroot, \"go.env\")\n\t}\n\n\treturn merges, nil\n}\n\n// needsSyscallPackage returns whether the syscall package should be overridden\n// with the TinyGo version. This is the case on some targets.\nfunc needsSyscallPackage(buildTags []string) bool {\n\tfor _, tag := range buildTags {\n\t\tif tag == \"baremetal\" || tag == \"nintendoswitch\" || tag == \"tinygo.wasm\" {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// The boolean indicates whether to merge the subdirs. True means merge, false\n// means use the TinyGo version.\nfunc pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {\n\tpaths := map[string]bool{\n\t\t\"\":                            true,\n\t\t\"crypto/\":                     true,\n\t\t\"crypto/rand/\":                false,\n\t\t\"crypto/tls/\":                 false,\n\t\t\"crypto/x509/\":                true,\n\t\t\"crypto/x509/internal/\":       true,\n\t\t\"crypto/x509/internal/macos/\": false,\n\t\t\"device/\":                     false,\n\t\t\"examples/\":                   false,\n\t\t\"internal/\":                   true,\n\t\t\"internal/abi/\":               false,\n\t\t\"internal/binary/\":            false,\n\t\t\"internal/bytealg/\":           false,\n\t\t\"internal/cm/\":                false,\n\t\t\"internal/futex/\":             false,\n\t\t\"internal/fuzz/\":              false,\n\t\t\"internal/reflectlite/\":       false,\n\t\t\"internal/gclayout\":           false,\n\t\t\"internal/task/\":              false,\n\t\t\"internal/wasi/\":              false,\n\t\t\"machine/\":                    false,\n\t\t\"net/\":                        true,\n\t\t\"net/http/\":                   false,\n\t\t\"os/\":                         true,\n\t\t\"reflect/\":                    false,\n\t\t\"runtime/\":                    false,\n\t\t\"sync/\":                       true,\n\t\t\"testing/\":                    true,\n\t\t\"tinygo/\":                     false,\n\t\t\"unique/\":                     false,\n\t}\n\n\tif goMinor >= 19 {\n\t\tpaths[\"crypto/internal/\"] = true\n\t\tpaths[\"crypto/internal/boring/\"] = true\n\t\tpaths[\"crypto/internal/boring/sig/\"] = false\n\t}\n\n\tif needsSyscallPackage {\n\t\tpaths[\"syscall/\"] = true // include syscall/js\n\t\tpaths[\"internal/syscall/\"] = true\n\t\tpaths[\"internal/syscall/unix/\"] = false\n\t}\n\treturn paths\n}\n\n// symlink creates a symlink or something similar. On Unix-like systems, it\n// always creates a symlink. On Windows, it tries to create a symlink and if\n// that fails, creates a hardlink or directory junction instead.\n//\n// Note that while Windows 10 does support symlinks and allows them to be\n// created using os.Symlink, it requires developer mode to be enabled.\n// Therefore provide a fallback for when symlinking is not possible.\n// Unfortunately this fallback only works when TinyGo is installed on the same\n// filesystem as the TinyGo cache and the Go installation (which is usually the\n// C drive).\nfunc symlink(oldname, newname string) error {\n\tsymlinkErr := os.Symlink(oldname, newname)\n\tif runtime.GOOS == \"windows\" && symlinkErr != nil {\n\t\t// Fallback for when developer mode is disabled.\n\t\t// Note that we return the symlink error even if something else fails\n\t\t// later on. This is because symlinks are the easiest to support\n\t\t// (they're also used on Linux and MacOS) and enabling them is easy:\n\t\t// just enable developer mode.\n\t\tst, err := os.Stat(oldname)\n\t\tif err != nil {\n\t\t\treturn symlinkErr\n\t\t}\n\t\tif st.IsDir() {\n\t\t\t// Make a directory junction. There may be a way to do this\n\t\t\t// programmatically, but it involves a lot of magic. Use the mklink\n\t\t\t// command built into cmd instead (mklink is a builtin, not an\n\t\t\t// external command).\n\t\t\terr := exec.Command(\"cmd\", \"/k\", \"mklink\", \"/J\", newname, oldname).Run()\n\t\t\tif err != nil {\n\t\t\t\treturn symlinkErr\n\t\t\t}\n\t\t} else {\n\t\t\t// Try making a hard link.\n\t\t\terr := os.Link(oldname, newname)\n\t\t\tif err != nil {\n\t\t\t\t// Making a hardlink failed. Try copying the file as a last\n\t\t\t\t// fallback.\n\t\t\t\tinf, err := os.Open(oldname)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tdefer inf.Close()\n\t\t\t\toutf, err := os.Create(newname)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tdefer outf.Close()\n\t\t\t\t_, err = io.Copy(outf, inf)\n\t\t\t\tif err != nil {\n\t\t\t\t\tos.Remove(newname)\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\t// File was copied.\n\t\t\t}\n\t\t}\n\t\treturn nil // success\n\t}\n\treturn symlinkErr\n}\n"
  },
  {
    "path": "loader/list.go",
    "content": "package loader\n\nimport (\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/tinygo-org/tinygo/compileopts\"\n\t\"github.com/tinygo-org/tinygo/goenv\"\n)\n\n// List returns a ready-to-run *exec.Cmd for running the `go list` command with\n// the configuration used for TinyGo.\nfunc List(config *compileopts.Config, extraArgs, pkgs []string) (*exec.Cmd, error) {\n\tgoroot, err := GetCachedGoroot(config)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\targs := append([]string{\"list\"}, extraArgs...)\n\tif len(config.BuildTags()) != 0 {\n\t\targs = append(args, \"-tags\", strings.Join(config.BuildTags(), \" \"))\n\t}\n\targs = append(args, pkgs...)\n\tcmd := exec.Command(filepath.Join(goenv.Get(\"GOROOT\"), \"bin\", \"go\"), args...)\n\tcmd.Env = append(os.Environ(), \"GOROOT=\"+goroot, \"GOOS=\"+config.GOOS(), \"GOARCH=\"+config.GOARCH(), \"CGO_ENABLED=1\")\n\tif config.Options.Directory != \"\" {\n\t\tcmd.Dir = config.Options.Directory\n\t}\n\treturn cmd, nil\n}\n"
  },
  {
    "path": "loader/loader.go",
    "content": "package loader\n\nimport (\n\t\"bytes\"\n\t\"crypto/sha512\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"go/constant\"\n\t\"go/parser\"\n\t\"go/scanner\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"io\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"strings\"\n\t\"unicode\"\n\n\t\"github.com/tinygo-org/tinygo/cgo\"\n\t\"github.com/tinygo-org/tinygo/compileopts\"\n\t\"github.com/tinygo-org/tinygo/goenv\"\n)\n\nvar initFileVersions = func(info *types.Info) {}\n\n// Program holds all packages and some metadata about the program as a whole.\ntype Program struct {\n\tconfig      *compileopts.Config\n\ttypeChecker types.Config\n\tgoroot      string // synthetic GOROOT\n\tworkingDir  string\n\n\tPackages map[string]*Package\n\tsorted   []*Package\n\tfset     *token.FileSet\n\n\t// Information obtained during parsing.\n\tLDFlags []string\n}\n\n// PackageJSON is a subset of the JSON struct returned from `go list`.\ntype PackageJSON struct {\n\tDir        string\n\tImportPath string\n\tName       string\n\tForTest    string\n\tRoot       string\n\tModule     struct {\n\t\tPath      string\n\t\tMain      bool\n\t\tDir       string\n\t\tGoMod     string\n\t\tGoVersion string\n\t}\n\n\t// Source files\n\tGoFiles  []string\n\tCgoFiles []string\n\tCFiles   []string\n\n\t// Embedded files\n\tEmbedFiles []string\n\n\t// Dependency information\n\tImports   []string\n\tImportMap map[string]string\n\n\t// Error information\n\tError *struct {\n\t\tImportStack []string\n\t\tPos         string\n\t\tErr         string\n\t}\n}\n\n// Package holds a loaded package, its imports, and its parsed files.\ntype Package struct {\n\tPackageJSON\n\n\tprogram      *Program\n\tFiles        []*ast.File\n\tFileHashes   map[string][]byte\n\tCFlags       []string // CFlags used during CGo preprocessing (only set if CGo is used)\n\tCGoHeaders   []string // text above 'import \"C\"' lines\n\tEmbedGlobals map[string][]*EmbedFile\n\tPkg          *types.Package\n\tinfo         types.Info\n}\n\ntype EmbedFile struct {\n\tName      string\n\tSize      uint64\n\tHash      string // hash of the file (as a hex string)\n\tNeedsData bool   // true if this file is embedded as a byte slice\n\tData      []byte // contents of this file (only if NeedsData is set)\n}\n\n// Load loads the given package with all dependencies (including the runtime\n// package). Call .Parse() afterwards to parse all Go files (including CGo\n// processing, if necessary).\nfunc Load(config *compileopts.Config, inputPkg string, typeChecker types.Config) (*Program, error) {\n\tgoroot, err := GetCachedGoroot(config)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar wd string\n\tif config.Options.Directory != \"\" {\n\t\twd = config.Options.Directory\n\t} else {\n\t\twd, err = os.Getwd()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\tp := &Program{\n\t\tconfig:      config,\n\t\ttypeChecker: typeChecker,\n\t\tgoroot:      goroot,\n\t\tworkingDir:  wd,\n\t\tPackages:    make(map[string]*Package),\n\t\tfset:        token.NewFileSet(),\n\t}\n\n\t// List the dependencies of this package, in raw JSON format.\n\textraArgs := []string{\"-json\", \"-deps\", \"-e\"}\n\tif config.TestConfig.CompileTestBinary {\n\t\textraArgs = append(extraArgs, \"-test\")\n\t}\n\tcmd, err := List(config, extraArgs, []string{inputPkg})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tbuf := &bytes.Buffer{}\n\tcmd.Stdout = buf\n\tcmd.Stderr = os.Stderr\n\terr = cmd.Run()\n\tif err != nil {\n\t\tif exitErr, ok := err.(*exec.ExitError); ok {\n\t\t\tos.Exit(exitErr.ExitCode())\n\t\t}\n\t\treturn nil, fmt.Errorf(\"failed to run `go list`: %s\", err)\n\t}\n\n\t// Parse the returned json from `go list`.\n\tdecoder := json.NewDecoder(buf)\n\tvar pkgErrors []error\n\tfor {\n\t\tpkg := &Package{\n\t\t\tprogram:      p,\n\t\t\tFileHashes:   make(map[string][]byte),\n\t\t\tEmbedGlobals: make(map[string][]*EmbedFile),\n\t\t\tinfo: types.Info{\n\t\t\t\tTypes:      make(map[ast.Expr]types.TypeAndValue),\n\t\t\t\tInstances:  make(map[*ast.Ident]types.Instance),\n\t\t\t\tDefs:       make(map[*ast.Ident]types.Object),\n\t\t\t\tUses:       make(map[*ast.Ident]types.Object),\n\t\t\t\tImplicits:  make(map[ast.Node]types.Object),\n\t\t\t\tScopes:     make(map[ast.Node]*types.Scope),\n\t\t\t\tSelections: make(map[*ast.SelectorExpr]*types.Selection),\n\t\t\t},\n\t\t}\n\t\terr := decoder.Decode(&pkg.PackageJSON)\n\t\tif err != nil {\n\t\t\tif err == io.EOF {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\treturn nil, err\n\t\t}\n\t\tif pkg.Error != nil {\n\t\t\t// There was an error while importing (for example, a circular\n\t\t\t// dependency).\n\t\t\tpos := token.Position{}\n\t\t\tfields := strings.Split(pkg.Error.Pos, \":\")\n\t\t\tif len(fields) >= 2 {\n\t\t\t\t// There is some file/line/column information.\n\t\t\t\tif n, err := strconv.Atoi(fields[len(fields)-2]); err == nil {\n\t\t\t\t\t// Format: filename.go:line:column\n\t\t\t\t\tpos.Filename = strings.Join(fields[:len(fields)-2], \":\")\n\t\t\t\t\tpos.Line = n\n\t\t\t\t\tpos.Column, _ = strconv.Atoi(fields[len(fields)-1])\n\t\t\t\t} else {\n\t\t\t\t\t// Format: filename.go:line\n\t\t\t\t\tpos.Filename = strings.Join(fields[:len(fields)-1], \":\")\n\t\t\t\t\tpos.Line, _ = strconv.Atoi(fields[len(fields)-1])\n\t\t\t\t}\n\t\t\t\tif abs, err := filepath.Abs(pos.Filename); err == nil {\n\t\t\t\t\t// Make the path absolute, so that error messages will be\n\t\t\t\t\t// prettier (it will be turned back into a relative path\n\t\t\t\t\t// when printing the error).\n\t\t\t\t\tpos.Filename = abs\n\t\t\t\t}\n\t\t\t\tpos.Filename = p.getOriginalPath(pos.Filename)\n\t\t\t}\n\t\t\terr := scanner.Error{\n\t\t\t\tPos: pos,\n\t\t\t\tMsg: pkg.Error.Err,\n\t\t\t}\n\t\t\tif len(pkg.Error.ImportStack) != 0 {\n\t\t\t\tpkgErrors = append(pkgErrors, Error{\n\t\t\t\t\tImportStack: pkg.Error.ImportStack,\n\t\t\t\t\tErr:         err,\n\t\t\t\t})\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn nil, err\n\t\t}\n\t\tif config.TestConfig.CompileTestBinary {\n\t\t\t// When creating a test binary, `go list` will list two or three\n\t\t\t// packages used for testing the package. The first is the original\n\t\t\t// package as if it were built normally, the second is the same\n\t\t\t// package but with the *_test.go files included. A possible third\n\t\t\t// may be included for _test packages (such as math_test), used to\n\t\t\t// test the external API with no access to internal functions.\n\t\t\t// All packages that are necessary for testing (including the to be\n\t\t\t// tested package with *_test.go files, but excluding the original\n\t\t\t// unmodified package) have a suffix added to the import path, for\n\t\t\t// example the math package has import path \"math [math.test]\" and\n\t\t\t// test dependencies such as fmt will have an import path of the\n\t\t\t// form \"fmt [math.test]\".\n\t\t\t// The code below removes this suffix, and if this results in a\n\t\t\t// duplicate (which happens with the to-be-tested package without\n\t\t\t// *.test.go files) the previous package is removed from the list of\n\t\t\t// packages included in this build.\n\t\t\t// This is necessary because the change in import paths results in\n\t\t\t// breakage to //go:linkname. Additionally, the duplicated package\n\t\t\t// slows down the build and so is best removed.\n\t\t\tif pkg.ForTest != \"\" && strings.HasSuffix(pkg.ImportPath, \" [\"+pkg.ForTest+\".test]\") {\n\t\t\t\tnewImportPath := pkg.ImportPath[:len(pkg.ImportPath)-len(\" [\"+pkg.ForTest+\".test]\")]\n\t\t\t\tif _, ok := p.Packages[newImportPath]; ok {\n\t\t\t\t\t// Delete the previous package (that this package overrides).\n\t\t\t\t\tdelete(p.Packages, newImportPath)\n\t\t\t\t\tfor i, pkg := range p.sorted {\n\t\t\t\t\t\tif pkg.ImportPath == newImportPath {\n\t\t\t\t\t\t\tp.sorted = append(p.sorted[:i], p.sorted[i+1:]...) // remove element from slice\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tpkg.ImportPath = newImportPath\n\t\t\t}\n\t\t}\n\t\tp.sorted = append(p.sorted, pkg)\n\t\tp.Packages[pkg.ImportPath] = pkg\n\t}\n\n\tif len(pkgErrors) != 0 {\n\t\t// TODO: use errors.Join in Go 1.20.\n\t\treturn nil, Errors{\n\t\t\tErrs: pkgErrors,\n\t\t}\n\t}\n\n\tif config.TestConfig.CompileTestBinary && !strings.HasSuffix(p.sorted[len(p.sorted)-1].ImportPath, \".test\") {\n\t\t// Trying to compile a test binary but there are no test files in this\n\t\t// package.\n\t\treturn p, NoTestFilesError{p.sorted[len(p.sorted)-1].ImportPath}\n\t}\n\n\treturn p, nil\n}\n\n// getOriginalPath looks whether this path is in the generated GOROOT and if so,\n// replaces the path with the original path (in GOROOT or TINYGOROOT). Otherwise\n// the input path is returned.\nfunc (p *Program) getOriginalPath(path string) string {\n\toriginalPath := path\n\tif strings.HasPrefix(path, p.goroot+string(filepath.Separator)) {\n\t\t// If this file is part of the synthetic GOROOT, try to infer the\n\t\t// original path.\n\t\trelpath := path[len(filepath.Join(p.goroot, \"src\"))+1:]\n\t\trealgorootPath := filepath.Join(goenv.Get(\"GOROOT\"), \"src\", relpath)\n\t\tif _, err := os.Stat(realgorootPath); err == nil {\n\t\t\toriginalPath = realgorootPath\n\t\t}\n\t\tmaybeInTinyGoRoot := false\n\t\tfor prefix := range pathsToOverride(p.config.GoMinorVersion, needsSyscallPackage(p.config.BuildTags())) {\n\t\t\tif runtime.GOOS == \"windows\" {\n\t\t\t\tprefix = strings.ReplaceAll(prefix, \"/\", \"\\\\\")\n\t\t\t}\n\t\t\tif !strings.HasPrefix(relpath, prefix) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tmaybeInTinyGoRoot = true\n\t\t}\n\t\tif maybeInTinyGoRoot {\n\t\t\ttinygoPath := filepath.Join(goenv.Get(\"TINYGOROOT\"), \"src\", relpath)\n\t\t\tif _, err := os.Stat(tinygoPath); err == nil {\n\t\t\t\toriginalPath = tinygoPath\n\t\t\t}\n\t\t}\n\t}\n\treturn originalPath\n}\n\n// Sorted returns a list of all packages, sorted in a way that no packages come\n// before the packages they depend upon.\nfunc (p *Program) Sorted() []*Package {\n\treturn p.sorted\n}\n\n// MainPkg returns the last package in the Sorted() slice. This is the main\n// package of the program.\nfunc (p *Program) MainPkg() *Package {\n\treturn p.sorted[len(p.sorted)-1]\n}\n\n// Parse parses all packages and typechecks them.\n//\n// The returned error may be an Errors error, which contains a list of errors.\n//\n// Idempotent.\nfunc (p *Program) Parse() error {\n\t// Parse all packages.\n\t// TODO: do this in parallel.\n\tfor _, pkg := range p.sorted {\n\t\terr := pkg.Parse()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// Typecheck all packages.\n\tfor _, pkg := range p.sorted {\n\t\terr := pkg.Check()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// OriginalDir returns the real directory name. It is the same as p.Dir except\n// that if it is part of the cached GOROOT, its real location is returned.\nfunc (p *Package) OriginalDir() string {\n\treturn strings.TrimSuffix(p.program.getOriginalPath(p.Dir+string(os.PathSeparator)), string(os.PathSeparator))\n}\n\n// parseFile is a wrapper around parser.ParseFile.\nfunc (p *Package) parseFile(path string, mode parser.Mode) (*ast.File, error) {\n\toriginalPath := p.program.getOriginalPath(path)\n\tdata, err := os.ReadFile(path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tsum := sha512.Sum512_224(data)\n\tp.FileHashes[originalPath] = sum[:]\n\treturn parser.ParseFile(p.program.fset, originalPath, data, mode)\n}\n\n// Parse parses and typechecks this package.\n//\n// Idempotent.\nfunc (p *Package) Parse() error {\n\tif len(p.Files) != 0 {\n\t\treturn nil // nothing to do (?)\n\t}\n\n\t// Load the AST.\n\tif p.ImportPath == \"unsafe\" {\n\t\t// Special case for the unsafe package, which is defined internally by\n\t\t// the types package.\n\t\tp.Pkg = types.Unsafe\n\t\treturn nil\n\t}\n\n\tfiles, err := p.parseFiles()\n\tif err != nil {\n\t\treturn err\n\t}\n\tp.Files = files\n\n\treturn nil\n}\n\n// Check runs the package through the typechecker. The package must already be\n// loaded and all dependencies must have been checked already.\n//\n// Idempotent.\nfunc (p *Package) Check() error {\n\tif p.Pkg != nil {\n\t\treturn nil // already typechecked\n\t}\n\n\t// Prepare some state used during type checking.\n\tvar typeErrors []error\n\tchecker := p.program.typeChecker // make a copy, because it will be modified\n\tchecker.Error = func(err error) {\n\t\ttypeErrors = append(typeErrors, err)\n\t}\n\tchecker.Importer = p\n\tif p.Module.GoVersion != \"\" {\n\t\t// Setting the Go version for a module makes sure the type checker\n\t\t// errors out on language features not supported in that particular\n\t\t// version.\n\t\tchecker.GoVersion = \"go\" + p.Module.GoVersion\n\t} else {\n\t\t// Version is not known, so use the currently installed Go version.\n\t\t// This is needed for `tinygo run` for example.\n\t\t// Normally we'd use goenv.GorootVersionString(), but for compatibility\n\t\t// with Go 1.20 and below we need a version in the form of \"go1.12\" (no\n\t\t// patch version).\n\t\tmajor, minor, err := goenv.GetGorootVersion()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tchecker.GoVersion = fmt.Sprintf(\"go%d.%d\", major, minor)\n\t}\n\tinitFileVersions(&p.info)\n\n\t// Do typechecking of the package.\n\tpackageName := p.ImportPath\n\tif p == p.program.MainPkg() {\n\t\tif p.Name != \"main\" {\n\t\t\treturn Errors{p, []error{\n\t\t\t\tscanner.Error{\n\t\t\t\t\tPos: p.program.fset.Position(p.Files[0].Name.Pos()),\n\t\t\t\t\tMsg: fmt.Sprintf(\"expected main package to have name \\\"main\\\", not %#v\", p.Name),\n\t\t\t\t},\n\t\t\t}}\n\t\t}\n\t\tpackageName = \"main\"\n\t}\n\ttypesPkg, err := checker.Check(packageName, p.program.fset, p.Files, &p.info)\n\tif err != nil {\n\t\tif err, ok := err.(Errors); ok {\n\t\t\treturn err\n\t\t}\n\t\tif len(typeErrors) != 0 {\n\t\t\t// Got type errors, so return them.\n\t\t\treturn Errors{p, typeErrors}\n\t\t}\n\t\t// This can happen in some weird cases.\n\t\t// The only case I know is when compiling a Go 1.23 program, with a\n\t\t// TinyGo version that supports Go 1.23 but is compiled using Go 1.22.\n\t\t// So this should be pretty rare.\n\t\treturn Errors{p, []error{err}}\n\t}\n\tp.Pkg = typesPkg\n\n\tp.extractEmbedLines(checker.Error)\n\tif len(typeErrors) != 0 {\n\t\treturn Errors{p, typeErrors}\n\t}\n\n\treturn nil\n}\n\n// parseFiles parses the loaded list of files and returns this list.\nfunc (p *Package) parseFiles() ([]*ast.File, error) {\n\tvar files []*ast.File\n\tvar fileErrs []error\n\n\t// Parse all files (including CgoFiles).\n\tparseFile := func(file string) {\n\t\tif !filepath.IsAbs(file) {\n\t\t\tfile = filepath.Join(p.Dir, file)\n\t\t}\n\t\tf, err := p.parseFile(file, parser.ParseComments)\n\t\tif err != nil {\n\t\t\tfileErrs = append(fileErrs, err)\n\t\t\treturn\n\t\t}\n\t\tfiles = append(files, f)\n\t}\n\tfor _, file := range p.GoFiles {\n\t\tparseFile(file)\n\t}\n\tfor _, file := range p.CgoFiles {\n\t\tparseFile(file)\n\t}\n\n\t// Do CGo processing.\n\t// This is done when there are any CgoFiles at all. In that case, len(files)\n\t// should be non-zero. However, if len(GoFiles) == 0 and len(CgoFiles) == 1\n\t// and there is a syntax error in a CGo file, len(files) may be 0. Don't try\n\t// to call cgo.Process in that case as it will only cause issues.\n\tif len(p.CgoFiles) != 0 && len(files) != 0 {\n\t\tvar initialCFlags []string\n\t\tinitialCFlags = append(initialCFlags, p.program.config.CFlags(true)...)\n\t\tinitialCFlags = append(initialCFlags, \"-I\"+p.Dir)\n\t\tgenerated, headerCode, cflags, ldflags, accessedFiles, errs := cgo.Process(files, p.program.workingDir, p.ImportPath, p.program.fset, initialCFlags, p.program.config.GOOS())\n\t\tp.CFlags = append(initialCFlags, cflags...)\n\t\tp.CGoHeaders = headerCode\n\t\tfor path, hash := range accessedFiles {\n\t\t\tp.FileHashes[path] = hash\n\t\t}\n\t\tif errs != nil {\n\t\t\tfileErrs = append(fileErrs, errs...)\n\t\t}\n\t\tfiles = append(files, generated...)\n\t\tp.program.LDFlags = append(p.program.LDFlags, ldflags...)\n\t}\n\n\t// Only return an error after CGo processing, so that errors in parsing and\n\t// CGo can be reported together.\n\tif len(fileErrs) != 0 {\n\t\treturn nil, Errors{p, fileErrs}\n\t}\n\n\treturn files, nil\n}\n\n// extractEmbedLines finds all //go:embed lines in the package and matches them\n// against EmbedFiles from `go list`.\nfunc (p *Package) extractEmbedLines(addError func(error)) {\n\tfor _, file := range p.Files {\n\t\t// Check for an `import \"embed\"` line at the start of the file.\n\t\t// //go:embed lines are only valid if the given file itself imports the\n\t\t// embed package. It is not valid if it is only imported in a separate\n\t\t// Go file.\n\t\thasEmbed := false\n\t\tfor _, importSpec := range file.Imports {\n\t\t\tif importSpec.Path.Value == `\"embed\"` {\n\t\t\t\thasEmbed = true\n\t\t\t}\n\t\t}\n\n\t\tfor _, decl := range file.Decls {\n\t\t\tswitch decl := decl.(type) {\n\t\t\tcase *ast.GenDecl:\n\t\t\t\tif decl.Tok != token.VAR {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tfor _, spec := range decl.Specs {\n\t\t\t\t\tspec := spec.(*ast.ValueSpec)\n\t\t\t\t\tvar doc *ast.CommentGroup\n\t\t\t\t\tif decl.Lparen == token.NoPos {\n\t\t\t\t\t\t// Plain 'var' declaration, like:\n\t\t\t\t\t\t//   //go:embed hello.txt\n\t\t\t\t\t\t//   var hello string\n\t\t\t\t\t\tdoc = decl.Doc\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Bigger 'var' declaration like:\n\t\t\t\t\t\t//   var (\n\t\t\t\t\t\t//       //go:embed hello.txt\n\t\t\t\t\t\t//       hello string\n\t\t\t\t\t\t//   )\n\t\t\t\t\t\tdoc = spec.Doc\n\t\t\t\t\t}\n\t\t\t\t\tif doc == nil {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\n\t\t\t\t\t// Look for //go:embed comments.\n\t\t\t\t\tvar allPatterns []string\n\t\t\t\t\tfor _, comment := range doc.List {\n\t\t\t\t\t\tif comment.Text != \"//go:embed\" && !strings.HasPrefix(comment.Text, \"//go:embed \") {\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif !hasEmbed {\n\t\t\t\t\t\t\taddError(types.Error{\n\t\t\t\t\t\t\t\tFset: p.program.fset,\n\t\t\t\t\t\t\t\tPos:  comment.Pos() + 2,\n\t\t\t\t\t\t\t\tMsg:  \"//go:embed only allowed in Go files that import \\\"embed\\\"\",\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t// Continue, because otherwise we might run into\n\t\t\t\t\t\t\t// issues below.\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpatterns, err := p.parseGoEmbed(comment.Text[len(\"//go:embed\"):], comment.Slash)\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\taddError(err)\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif len(patterns) == 0 {\n\t\t\t\t\t\t\taddError(types.Error{\n\t\t\t\t\t\t\t\tFset: p.program.fset,\n\t\t\t\t\t\t\t\tPos:  comment.Pos() + 2,\n\t\t\t\t\t\t\t\tMsg:  \"usage: //go:embed pattern...\",\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor _, pattern := range patterns {\n\t\t\t\t\t\t\t// Check that the pattern is well-formed.\n\t\t\t\t\t\t\t// It must be valid: the Go toolchain has already\n\t\t\t\t\t\t\t// checked for invalid patterns. But let's check\n\t\t\t\t\t\t\t// anyway to be sure.\n\t\t\t\t\t\t\tif _, err := path.Match(pattern, \"\"); err != nil {\n\t\t\t\t\t\t\t\taddError(types.Error{\n\t\t\t\t\t\t\t\t\tFset: p.program.fset,\n\t\t\t\t\t\t\t\t\tPos:  comment.Pos(),\n\t\t\t\t\t\t\t\t\tMsg:  \"invalid pattern syntax\",\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tallPatterns = append(allPatterns, pattern)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif len(allPatterns) != 0 {\n\t\t\t\t\t\t// This is a //go:embed global. Do a few more checks.\n\t\t\t\t\t\tif len(spec.Names) != 1 {\n\t\t\t\t\t\t\taddError(types.Error{\n\t\t\t\t\t\t\t\tFset: p.program.fset,\n\t\t\t\t\t\t\t\tPos:  spec.Names[1].NamePos,\n\t\t\t\t\t\t\t\tMsg:  \"//go:embed cannot apply to multiple vars\",\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif spec.Values != nil {\n\t\t\t\t\t\t\taddError(types.Error{\n\t\t\t\t\t\t\t\tFset: p.program.fset,\n\t\t\t\t\t\t\t\tPos:  spec.Values[0].Pos(),\n\t\t\t\t\t\t\t\tMsg:  \"//go:embed cannot apply to var with initializer\",\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t\tglobalName := spec.Names[0].Name\n\t\t\t\t\t\tglobalType := p.Pkg.Scope().Lookup(globalName).Type()\n\t\t\t\t\t\tvalid, byteSlice := isValidEmbedType(globalType)\n\t\t\t\t\t\tif !valid {\n\t\t\t\t\t\t\taddError(types.Error{\n\t\t\t\t\t\t\t\tFset: p.program.fset,\n\t\t\t\t\t\t\t\tPos:  spec.Type.Pos(),\n\t\t\t\t\t\t\t\tMsg:  \"//go:embed cannot apply to var of type \" + globalType.String(),\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Match all //go:embed patterns against the embed files\n\t\t\t\t\t\t// provided by `go list`.\n\t\t\t\t\t\tfor _, name := range p.EmbedFiles {\n\t\t\t\t\t\t\tfor _, pattern := range allPatterns {\n\t\t\t\t\t\t\t\tif matchPattern(pattern, name) {\n\t\t\t\t\t\t\t\t\tp.EmbedGlobals[globalName] = append(p.EmbedGlobals[globalName], &EmbedFile{\n\t\t\t\t\t\t\t\t\t\tName:      name,\n\t\t\t\t\t\t\t\t\t\tNeedsData: byteSlice,\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// matchPattern returns true if (and only if) the given pattern would match the\n// filename. The pattern could also match a parent directory of name, in which\n// case hidden files do not match.\nfunc matchPattern(pattern, name string) bool {\n\t// Match this file.\n\tmatched, _ := path.Match(pattern, name)\n\tif matched {\n\t\treturn true\n\t}\n\n\t// Match parent directories.\n\tdir := name\n\tfor {\n\t\tdir, _ = path.Split(dir)\n\t\tif dir == \"\" {\n\t\t\treturn false\n\t\t}\n\t\tdir = path.Clean(dir)\n\t\tif matched, _ := path.Match(pattern, dir); matched {\n\t\t\t// Pattern matches the directory.\n\t\t\tsuffix := name[len(dir):]\n\t\t\tif strings.Contains(suffix, \"/_\") || strings.Contains(suffix, \"/.\") {\n\t\t\t\t// Pattern matches a hidden file.\n\t\t\t\t// Hidden files are included when listed directly as a\n\t\t\t\t// pattern, but not when they are part of a directory tree.\n\t\t\t\t// Source:\n\t\t\t\t// > If a pattern names a directory, all files in the\n\t\t\t\t// > subtree rooted at that directory are embedded\n\t\t\t\t// > (recursively), except that files with names beginning\n\t\t\t\t// > with ‘.’ or ‘_’ are excluded.\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn true\n\t\t}\n\t}\n}\n\n// parseGoEmbed is like strings.Fields but for a //go:embed line. It parses\n// regular fields and quoted fields (that may contain spaces).\nfunc (p *Package) parseGoEmbed(args string, pos token.Pos) (patterns []string, err error) {\n\targs = strings.TrimSpace(args)\n\tinitialLen := len(args)\n\tfor args != \"\" {\n\t\tpatternPos := pos + token.Pos(initialLen-len(args))\n\t\tswitch args[0] {\n\t\tcase '`', '\"', '\\\\':\n\t\t\t// Parse the next pattern using the Go scanner.\n\t\t\t// This is perhaps a bit overkill, but it does correctly implement\n\t\t\t// parsing of the various Go strings.\n\t\t\tvar sc scanner.Scanner\n\t\t\tfset := &token.FileSet{}\n\t\t\tfile := fset.AddFile(\"\", 0, len(args))\n\t\t\tsc.Init(file, []byte(args), nil, 0)\n\t\t\t_, tok, lit := sc.Scan()\n\t\t\tif tok != token.STRING || sc.ErrorCount != 0 {\n\t\t\t\t// Calculate start of token\n\t\t\t\treturn nil, types.Error{\n\t\t\t\t\tFset: p.program.fset,\n\t\t\t\t\tPos:  patternPos,\n\t\t\t\t\tMsg:  \"invalid quoted string in //go:embed\",\n\t\t\t\t}\n\t\t\t}\n\t\t\tpattern := constant.StringVal(constant.MakeFromLiteral(lit, tok, 0))\n\t\t\tpatterns = append(patterns, pattern)\n\t\t\targs = strings.TrimLeftFunc(args[len(lit):], unicode.IsSpace)\n\t\tdefault:\n\t\t\t// The value is just a regular value.\n\t\t\t// Split it at the first white space.\n\t\t\tindex := strings.IndexFunc(args, unicode.IsSpace)\n\t\t\tif index < 0 {\n\t\t\t\tindex = len(args)\n\t\t\t}\n\t\t\tpattern := args[:index]\n\t\t\tpatterns = append(patterns, pattern)\n\t\t\targs = strings.TrimLeftFunc(args[len(pattern):], unicode.IsSpace)\n\t\t}\n\t\tif _, err := path.Match(patterns[len(patterns)-1], \"\"); err != nil {\n\t\t\treturn nil, types.Error{\n\t\t\t\tFset: p.program.fset,\n\t\t\t\tPos:  patternPos,\n\t\t\t\tMsg:  \"invalid pattern syntax\",\n\t\t\t}\n\t\t}\n\t}\n\treturn patterns, nil\n}\n\n// isValidEmbedType returns whether the given Go type can be used as a\n// //go:embed type. This is only true for embed.FS, strings, and byte slices.\n// The second return value indicates that this is a byte slice, and therefore\n// the contents of the file needs to be passed to the compiler.\nfunc isValidEmbedType(typ types.Type) (valid, byteSlice bool) {\n\tif typ.Underlying() == types.Typ[types.String] {\n\t\t// string type\n\t\treturn true, false\n\t}\n\tif sliceType, ok := typ.Underlying().(*types.Slice); ok {\n\t\tif elemType, ok := sliceType.Elem().Underlying().(*types.Basic); ok && elemType.Kind() == types.Byte {\n\t\t\t// byte slice type\n\t\t\treturn true, true\n\t\t}\n\t}\n\tif namedType, ok := typ.(*types.Named); ok && namedType.String() == \"embed.FS\" {\n\t\t// embed.FS type\n\t\treturn true, false\n\t}\n\treturn false, false\n}\n\n// Import implements types.Importer. It loads and parses packages it encounters\n// along the way, if needed.\nfunc (p *Package) Import(to string) (*types.Package, error) {\n\tif to == \"unsafe\" {\n\t\treturn types.Unsafe, nil\n\t}\n\tif newTo, ok := p.ImportMap[to]; ok && !strings.HasSuffix(newTo, \".test]\") {\n\t\tto = newTo\n\t}\n\tif imported, ok := p.program.Packages[to]; ok {\n\t\treturn imported.Pkg, nil\n\t} else {\n\t\treturn nil, errors.New(\"package not imported: \" + to)\n\t}\n}\n"
  },
  {
    "path": "loader/loader_go122.go",
    "content": "//go:build go1.22\n\n// types.Info.FileVersions was added in Go 1.22, so we can only initialize it\n// when built with Go 1.22.\n\npackage loader\n\nimport (\n\t\"go/ast\"\n\t\"go/types\"\n)\n\nfunc init() {\n\tinitFileVersions = func(info *types.Info) {\n\t\tinfo.FileVersions = make(map[*ast.File]string)\n\t}\n}\n"
  },
  {
    "path": "loader/ssa.go",
    "content": "package loader\n\nimport (\n\t\"golang.org/x/tools/go/ssa\"\n)\n\n// LoadSSA constructs the SSA form of the loaded packages.\n//\n// The program must already be parsed and type-checked with the .Parse() method.\nfunc (p *Program) LoadSSA() *ssa.Program {\n\t// TODO: re-enable SanityCheckFunctions when x/tools is upgraded to\n\t// a version with a fix for https://golang.org/issues/73594.\n\tprog := ssa.NewProgram(p.fset /*ssa.SanityCheckFunctions|*/, ssa.BareInits|ssa.GlobalDebug|ssa.InstantiateGenerics)\n\n\tfor _, pkg := range p.sorted {\n\t\tprog.CreatePackage(pkg.Pkg, pkg.Files, &pkg.info, true)\n\t}\n\n\treturn prog\n}\n\n// LoadSSA constructs the SSA form of this package.\n//\n// The program must already be parsed and type-checked with the .Parse() method.\nfunc (p *Package) LoadSSA() *ssa.Package {\n\tprog := ssa.NewProgram(p.program.fset, ssa.SanityCheckFunctions|ssa.BareInits|ssa.GlobalDebug)\n\treturn prog.CreatePackage(p.Pkg, p.Files, &p.info, true)\n}\n"
  },
  {
    "path": "main.go",
    "content": "package main\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"os/exec\"\n\t\"os/signal\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"runtime\"\n\t\"runtime/pprof\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"github.com/google/shlex\"\n\t\"github.com/inhies/go-bytesize\"\n\t\"github.com/mattn/go-colorable\"\n\t\"github.com/tinygo-org/tinygo/builder\"\n\t\"github.com/tinygo-org/tinygo/compileopts\"\n\t\"github.com/tinygo-org/tinygo/diagnostics\"\n\t\"github.com/tinygo-org/tinygo/goenv\"\n\t\"github.com/tinygo-org/tinygo/loader\"\n\t\"golang.org/x/tools/go/buildutil\"\n\t\"tinygo.org/x/go-llvm\"\n\n\t\"go.bug.st/serial\"\n\t\"go.bug.st/serial/enumerator\"\n)\n\n// commandError is an error type to wrap os/exec.Command errors. This provides\n// some more information regarding what went wrong while running a command.\ntype commandError struct {\n\tMsg  string\n\tFile string\n\tErr  error\n}\n\nfunc (e *commandError) Error() string {\n\treturn e.Msg + \" \" + e.File + \": \" + e.Err.Error()\n}\n\n// moveFile renames the file from src to dst. If renaming doesn't work (for\n// example, the rename crosses a filesystem boundary), the file is copied and\n// the old file is removed.\nfunc moveFile(src, dst string) error {\n\terr := os.Rename(src, dst)\n\tif err == nil {\n\t\t// Success!\n\t\treturn nil\n\t}\n\t// Failed to move, probably a different filesystem.\n\t// Do a copy + remove.\n\terr = copyFile(src, dst)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn os.Remove(src)\n}\n\n// copyFile copies the given file or directory from src to dst. It can copy over\n// a possibly already existing file (but not directory) at the destination.\nfunc copyFile(src, dst string) error {\n\tsource, err := os.Open(src)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer source.Close()\n\n\tst, err := source.Stat()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif st.IsDir() {\n\t\terr := os.Mkdir(dst, st.Mode().Perm())\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tnames, err := source.Readdirnames(0)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfor _, name := range names {\n\t\t\terr := copyFile(filepath.Join(src, name), filepath.Join(dst, name))\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t} else {\n\t\tdestination, err := os.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, st.Mode())\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdefer destination.Close()\n\n\t\t_, err = io.Copy(destination, source)\n\t\treturn err\n\t}\n}\n\n// executeCommand is a simple wrapper to exec.Cmd\nfunc executeCommand(options *compileopts.Options, name string, arg ...string) *exec.Cmd {\n\tif options.PrintCommands != nil {\n\t\toptions.PrintCommands(name, arg...)\n\t}\n\treturn exec.Command(name, arg...)\n}\n\n// printCommand prints a command to stdout while formatting it like a real\n// command (escaping characters etc). The resulting command should be easy to\n// run directly in a shell, although it is not guaranteed to be a safe shell\n// escape. That's not a problem as the primary use case is printing the command,\n// not running it.\nfunc printCommand(cmd string, args ...string) {\n\tcommand := append([]string{cmd}, args...)\n\tfor i, arg := range command {\n\t\t// Source: https://www.oreilly.com/library/view/learning-the-bash/1565923472/ch01s09.html\n\t\tconst specialChars = \"~`#$&*()\\\\|[]{};'\\\"<>?! \"\n\t\tif strings.ContainsAny(arg, specialChars) {\n\t\t\t// See: https://stackoverflow.com/questions/15783701/which-characters-need-to-be-escaped-when-using-bash\n\t\t\targ = \"'\" + strings.ReplaceAll(arg, `'`, `'\\''`) + \"'\"\n\t\t\tcommand[i] = arg\n\t\t}\n\t}\n\tfmt.Fprintln(os.Stderr, strings.Join(command, \" \"))\n}\n\n// Build compiles and links the given package and writes it to outpath.\nfunc Build(pkgName, outpath string, config *compileopts.Config) error {\n\t// Create a temporary directory for intermediary files.\n\ttmpdir, err := os.MkdirTemp(\"\", \"tinygo\")\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !config.Options.Work {\n\t\tdefer os.RemoveAll(tmpdir)\n\t}\n\n\t// Do the build.\n\tresult, err := builder.Build(pkgName, outpath, tmpdir, config)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif result.Binary != \"\" {\n\t\t// If result.Binary is set, it means there is a build output (elf, hex,\n\t\t// etc) that we need to move to the outpath. If it isn't set, it means\n\t\t// the build output was a .ll, .bc or .o file that has already been\n\t\t// written to outpath and so we don't need to do anything.\n\n\t\tif outpath == \"\" {\n\t\t\tif strings.HasSuffix(pkgName, \".go\") {\n\t\t\t\t// A Go file was specified directly on the command line.\n\t\t\t\t// Base the binary name off of it.\n\t\t\t\toutpath = filepath.Base(pkgName[:len(pkgName)-3]) + config.DefaultBinaryExtension()\n\t\t\t} else {\n\t\t\t\t// Pick a default output path based on the main directory.\n\t\t\t\toutpath = filepath.Base(result.MainDir) + config.DefaultBinaryExtension()\n\t\t\t}\n\t\t}\n\n\t\tif err := os.Rename(result.Binary, outpath); err != nil {\n\t\t\t// Moving failed. Do a file copy.\n\t\t\tinf, err := os.Open(result.Binary)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tdefer inf.Close()\n\t\t\toutf, err := os.OpenFile(outpath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0777)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\t// Copy data to output file.\n\t\t\t_, err = io.Copy(outf, inf)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\t// Check whether file writing was successful.\n\t\t\treturn outf.Close()\n\t\t}\n\t}\n\n\t// Move was successful.\n\treturn nil\n}\n\n// Test runs the tests in the given package. Returns whether the test passed and\n// possibly an error if the test failed to run.\nfunc Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options, outpath string) (bool, error) {\n\toptions.TestConfig.CompileTestBinary = true\n\tconfig, err := builder.NewConfig(options)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\ttestConfig := &options.TestConfig\n\n\t// Pass test flags to the test binary.\n\tvar flags []string\n\tif testConfig.Verbose {\n\t\tflags = append(flags, \"-test.v\")\n\t}\n\tif testConfig.Short {\n\t\tflags = append(flags, \"-test.short\")\n\t}\n\tif testConfig.RunRegexp != \"\" {\n\t\tflags = append(flags, \"-test.run=\"+testConfig.RunRegexp)\n\t}\n\tif testConfig.SkipRegexp != \"\" {\n\t\tflags = append(flags, \"-test.skip=\"+testConfig.SkipRegexp)\n\t}\n\tif testConfig.BenchRegexp != \"\" {\n\t\tflags = append(flags, \"-test.bench=\"+testConfig.BenchRegexp)\n\t}\n\tif testConfig.BenchTime != \"\" {\n\t\tflags = append(flags, \"-test.benchtime=\"+testConfig.BenchTime)\n\t}\n\tif testConfig.BenchMem {\n\t\tflags = append(flags, \"-test.benchmem\")\n\t}\n\tif testConfig.Count != nil && *testConfig.Count != 1 {\n\t\tflags = append(flags, \"-test.count=\"+strconv.Itoa(*testConfig.Count))\n\t}\n\tif testConfig.Shuffle != \"\" {\n\t\tflags = append(flags, \"-test.shuffle=\"+testConfig.Shuffle)\n\t}\n\n\tlogToStdout := testConfig.Verbose || testConfig.BenchRegexp != \"\"\n\n\tvar buf bytes.Buffer\n\tvar output io.Writer = &buf\n\t// Send the test output to stdout if -v or -bench\n\tif logToStdout {\n\t\toutput = os.Stdout\n\t}\n\n\tpassed := false\n\tvar duration time.Duration\n\tresult, err := buildAndRun(pkgName, config, output, flags, nil, 0, func(cmd *exec.Cmd, result builder.BuildResult) error {\n\t\tif testConfig.CompileOnly || outpath != \"\" {\n\t\t\t// Write test binary to the specified file name.\n\t\t\tif outpath == \"\" {\n\t\t\t\t// No -o path was given, so create one now.\n\t\t\t\t// This matches the behavior of go test.\n\t\t\t\toutpath = filepath.Base(result.MainDir) + \".test\"\n\t\t\t}\n\t\t\tcopyFile(result.Binary, outpath)\n\t\t}\n\t\tif testConfig.CompileOnly {\n\t\t\t// Do not run the test.\n\t\t\tpassed = true\n\t\t\treturn nil\n\t\t}\n\n\t\t// Tests are always run in the package directory.\n\t\tcmd.Dir = result.MainDir\n\n\t\t// Run the test.\n\t\tstart := time.Now()\n\t\terr = cmd.Run()\n\t\tduration = time.Since(start)\n\t\tpassed = err == nil\n\n\t\t// if verbose or benchmarks, then output is already going to stdout\n\t\t// However, if we failed and weren't printing to stdout, print the output we accumulated.\n\t\tif !passed && !logToStdout {\n\t\t\tbuf.WriteTo(stdout)\n\t\t}\n\n\t\tif _, ok := err.(*exec.ExitError); ok {\n\t\t\t// Binary exited with a non-zero exit code, which means the test\n\t\t\t// failed. Return nil to avoid printing a useless \"exited with\n\t\t\t// error\" error message.\n\t\t\treturn nil\n\t\t}\n\t\treturn err\n\t})\n\n\tif testConfig.CompileOnly {\n\t\t// Return the compiler error, if there is one.\n\t\treturn true, err\n\t}\n\n\timportPath := strings.TrimSuffix(result.ImportPath, \".test\")\n\n\tvar w io.Writer = stdout\n\tif logToStdout {\n\t\tw = os.Stdout\n\t}\n\tif err, ok := err.(loader.NoTestFilesError); ok {\n\t\tfmt.Fprintf(w, \"?   \\t%s\\t[no test files]\\n\", err.ImportPath)\n\t\t// Pretend the test passed - it at least didn't fail.\n\t\treturn true, nil\n\t} else if passed {\n\t\tfmt.Fprintf(w, \"ok  \\t%s\\t%.3fs\\n\", importPath, duration.Seconds())\n\t} else {\n\t\tfmt.Fprintf(w, \"FAIL\\t%s\\t%.3fs\\n\", importPath, duration.Seconds())\n\t}\n\treturn passed, err\n}\n\nfunc dirsToModuleRootRel(maindir, modroot string) []string {\n\tvar dirs []string\n\tlast := \"..\"\n\t// strip off path elements until we hit the module root\n\t// adding `..`, `../..`, `../../..` until we're done\n\tfor maindir != modroot {\n\t\tdirs = append(dirs, last)\n\t\tlast = filepath.Join(last, \"..\")\n\t\tmaindir = filepath.Dir(maindir)\n\t}\n\tdirs = append(dirs, \".\")\n\treturn dirs\n}\n\nfunc dirsToModuleRootAbs(maindir, modroot string) []string {\n\tvar dirs = []string{maindir}\n\tlast := filepath.Join(maindir, \"..\")\n\t// strip off path elements until we hit the module root\n\t// adding `..`, `../..`, `../../..` until we're done\n\tfor maindir != modroot {\n\t\tdirs = append(dirs, last)\n\t\tlast = filepath.Join(last, \"..\")\n\t\tmaindir = filepath.Dir(maindir)\n\t}\n\treturn dirs\n}\n\n// validateOutputFormat checks if the output file extension matches the expected format\nfunc validateOutputFormat(outpath, expectedExt string) error {\n\tactualExt := filepath.Ext(outpath)\n\tif actualExt != expectedExt {\n\t\treturn fmt.Errorf(\"output format %s does not match target format %s\", actualExt, expectedExt)\n\t}\n\treturn nil\n}\n\n// Flash builds and flashes the built binary to the given serial port.\nfunc Flash(pkgName, port, outpath string, options *compileopts.Options) error {\n\tconfig, err := builder.NewConfig(options)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// determine the type of file to compile\n\tvar fileExt string\n\n\tflashMethod, _ := config.Programmer()\n\tswitch flashMethod {\n\tcase \"command\", \"\":\n\t\tswitch {\n\t\tcase strings.Contains(config.Target.FlashCommand, \"{hex}\"):\n\t\t\tfileExt = \".hex\"\n\t\tcase strings.Contains(config.Target.FlashCommand, \"{elf}\"):\n\t\t\tfileExt = \".elf\"\n\t\tcase strings.Contains(config.Target.FlashCommand, \"{bin}\"):\n\t\t\tfileExt = \".bin\"\n\t\tcase strings.Contains(config.Target.FlashCommand, \"{uf2}\"):\n\t\t\tfileExt = \".uf2\"\n\t\tcase strings.Contains(config.Target.FlashCommand, \"{zip}\"):\n\t\t\tfileExt = \".zip\"\n\t\tdefault:\n\t\t\treturn errors.New(\"invalid target file - did you forget the {hex} token in the 'flash-command' section?\")\n\t\t}\n\tcase \"msd\":\n\t\tif config.Target.FlashFilename == \"\" {\n\t\t\treturn errors.New(\"invalid target file: flash-method was set to \\\"msd\\\" but no msd-firmware-name was set\")\n\t\t}\n\t\tfileExt = filepath.Ext(config.Target.FlashFilename)\n\tcase \"openocd\":\n\t\tfileExt = \".hex\"\n\tcase \"bmp\":\n\t\tfileExt = \".elf\"\n\tcase \"native\":\n\t\treturn errors.New(\"unknown flash method \\\"native\\\" - did you miss a -target flag?\")\n\tdefault:\n\t\treturn errors.New(\"unknown flash method: \" + flashMethod)\n\t}\n\n\t// Create a temporary directory for intermediary files.\n\ttmpdir, err := os.MkdirTemp(\"\", \"tinygo\")\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !options.Work {\n\t\tdefer os.RemoveAll(tmpdir)\n\t}\n\t// Validate output format before building\n\tif outpath != \"\" {\n\t\tif err := validateOutputFormat(outpath, fileExt); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\t// Build the binary.\n\tresult, err := builder.Build(pkgName, fileExt, tmpdir, config)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Save output file if specified (after build, before flashing)\n\tif outpath != \"\" {\n\t\tif err := copyFile(result.Binary, outpath); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to save output file: %v\", err)\n\t\t}\n\t}\n\t// do we need port reset to put MCU into bootloader mode?\n\tif config.Target.PortReset == \"true\" && flashMethod != \"openocd\" {\n\t\tport, err := getDefaultPort(port, config.Target.SerialPort)\n\t\tif err == nil {\n\t\t\terr = touchSerialPortAt1200bps(port)\n\t\t\tif err != nil {\n\t\t\t\treturn &commandError{\"failed to reset port\", port, err}\n\t\t\t}\n\t\t\t// give the target MCU a chance to restart into bootloader\n\t\t\ttime.Sleep(3 * time.Second)\n\t\t}\n\t}\n\n\t// Flash the binary to the MCU.\n\tswitch flashMethod {\n\tcase \"\", \"command\":\n\t\t// Create the command.\n\t\tflashCmd := config.Target.FlashCommand\n\t\tflashCmdList, err := shlex.Split(flashCmd)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"could not parse flash command %#v: %w\", flashCmd, err)\n\t\t}\n\n\t\tif strings.Contains(flashCmd, \"{port}\") {\n\t\t\tvar err error\n\t\t\tport, err = getDefaultPort(port, config.Target.SerialPort)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\n\t\t// Fill in fields in the command template.\n\t\tfileToken := \"{\" + fileExt[1:] + \"}\"\n\t\tfor i, arg := range flashCmdList {\n\t\t\targ = strings.ReplaceAll(arg, fileToken, result.Binary)\n\t\t\targ = strings.ReplaceAll(arg, \"{port}\", port)\n\t\t\tflashCmdList[i] = arg\n\t\t}\n\n\t\t// Execute the command.\n\t\tif len(flashCmdList) < 2 {\n\t\t\treturn fmt.Errorf(\"invalid flash command: %#v\", flashCmd)\n\t\t}\n\t\tcmd := executeCommand(config.Options, flashCmdList[0], flashCmdList[1:]...)\n\t\tcmd.Stdout = os.Stdout\n\t\tcmd.Stderr = os.Stderr\n\t\tcmd.Dir = goenv.Get(\"TINYGOROOT\")\n\t\terr = cmd.Run()\n\t\tif err != nil {\n\t\t\treturn &commandError{\"failed to flash\", result.Binary, err}\n\t\t}\n\tcase \"msd\":\n\t\t// this flashing method copies the binary data to a Mass Storage Device (msd)\n\t\tswitch fileExt {\n\t\tcase \".uf2\":\n\t\t\terr := flashUF2UsingMSD(config.Target.FlashVolume, result.Binary, config.Options)\n\t\t\tif err != nil {\n\t\t\t\treturn &commandError{\"failed to flash\", result.Binary, err}\n\t\t\t}\n\t\tcase \".hex\":\n\t\t\terr := flashHexUsingMSD(config.Target.FlashVolume, result.Binary, config.Options)\n\t\t\tif err != nil {\n\t\t\t\treturn &commandError{\"failed to flash\", result.Binary, err}\n\t\t\t}\n\t\tdefault:\n\t\t\treturn errors.New(\"mass storage device flashing currently only supports uf2 and hex\")\n\t\t}\n\tcase \"openocd\":\n\t\targs, err := config.OpenOCDConfiguration()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\texit := \" reset exit\"\n\t\tif config.Target.OpenOCDVerify != nil && *config.Target.OpenOCDVerify {\n\t\t\texit = \" verify\" + exit\n\t\t}\n\t\targs = append(args, \"-c\", \"program \"+filepath.ToSlash(result.Binary)+exit)\n\t\tcmd := executeCommand(config.Options, \"openocd\", args...)\n\t\tcmd.Stdout = os.Stdout\n\t\tcmd.Stderr = os.Stderr\n\t\terr = cmd.Run()\n\t\tif err != nil {\n\t\t\treturn &commandError{\"failed to flash\", result.Binary, err}\n\t\t}\n\tcase \"bmp\":\n\t\tgdb, err := config.Target.LookupGDB()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tvar bmpGDBPort string\n\t\tbmpGDBPort, _, err = getBMPPorts()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\targs := []string{\"-ex\", \"target extended-remote \" + bmpGDBPort, \"-ex\", \"monitor swdp_scan\", \"-ex\", \"attach 1\", \"-ex\", \"load\", filepath.ToSlash(result.Binary)}\n\t\tcmd := executeCommand(config.Options, gdb, args...)\n\t\tcmd.Stdout = os.Stdout\n\t\tcmd.Stderr = os.Stderr\n\t\terr = cmd.Run()\n\t\tif err != nil {\n\t\t\treturn &commandError{\"failed to flash\", result.Binary, err}\n\t\t}\n\tdefault:\n\t\treturn fmt.Errorf(\"unknown flash method: %s\", flashMethod)\n\t}\n\tif options.Monitor {\n\t\treturn Monitor(result.Executable, \"\", config)\n\t}\n\treturn nil\n}\n\n// Debug compiles and flashes a program to a microcontroller (just like Flash)\n// but instead of resetting the target, it will drop into a debug shell like GDB\n// or LLDB. You can then set breakpoints, run the `continue` command to start,\n// hit Ctrl+C to break the running program, etc.\n//\n// Note: this command is expected to execute just before exiting, as it\n// modifies global state.\nfunc Debug(debugger, pkgName string, ocdOutput bool, options *compileopts.Options) error {\n\tconfig, err := builder.NewConfig(options)\n\tif err != nil {\n\t\treturn err\n\t}\n\tvar cmdName string\n\tswitch debugger {\n\tcase \"gdb\":\n\t\tcmdName, err = config.Target.LookupGDB()\n\tcase \"lldb\":\n\t\tcmdName, err = builder.LookupCommand(\"lldb\")\n\t}\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Create a temporary directory for intermediary files.\n\ttmpdir, err := os.MkdirTemp(\"\", \"tinygo\")\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !options.Work {\n\t\tdefer os.RemoveAll(tmpdir)\n\t}\n\n\t// Build the binary to debug.\n\tformat, fileExt := config.EmulatorFormat()\n\tresult, err := builder.Build(pkgName, fileExt, tmpdir, config)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Find a good way to run GDB.\n\tgdbInterface, openocdInterface := config.Programmer()\n\tswitch gdbInterface {\n\tcase \"msd\", \"command\", \"\":\n\t\temulator := config.EmulatorName()\n\t\tif emulator != \"\" {\n\t\t\tif emulator == \"mgba\" {\n\t\t\t\tgdbInterface = \"mgba\"\n\t\t\t} else if emulator == \"simavr\" {\n\t\t\t\tgdbInterface = \"simavr\"\n\t\t\t} else if strings.HasPrefix(emulator, \"qemu-system-\") {\n\t\t\t\tgdbInterface = \"qemu\"\n\t\t\t} else {\n\t\t\t\t// Assume QEMU as an emulator.\n\t\t\t\tgdbInterface = \"qemu-user\"\n\t\t\t}\n\t\t} else if openocdInterface != \"\" && config.Target.OpenOCDTarget != \"\" {\n\t\t\tgdbInterface = \"openocd\"\n\t\t} else if config.Target.JLinkDevice != \"\" {\n\t\t\tgdbInterface = \"jlink\"\n\t\t} else {\n\t\t\tgdbInterface = \"native\"\n\t\t}\n\t}\n\n\t// Run the GDB server, if necessary.\n\tport := \"\"\n\tvar gdbCommands []string\n\tvar daemon *exec.Cmd\n\temulator, err := config.Emulator(format, result.Binary)\n\tif err != nil {\n\t\treturn err\n\t}\n\tswitch gdbInterface {\n\tcase \"native\":\n\t\t// Run GDB directly.\n\tcase \"bmp\":\n\t\tvar bmpGDBPort string\n\t\tbmpGDBPort, _, err = getBMPPorts()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tport = bmpGDBPort\n\t\tgdbCommands = append(gdbCommands, \"monitor swdp_scan\", \"compare-sections\", \"attach 1\", \"load\")\n\tcase \"openocd\":\n\t\tport = \":3333\"\n\t\tgdbCommands = append(gdbCommands, \"monitor halt\", \"load\", \"monitor reset halt\")\n\n\t\t// We need a separate debugging daemon for on-chip debugging.\n\t\targs, err := config.OpenOCDConfiguration()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdaemon = executeCommand(config.Options, \"openocd\", args...)\n\t\tif ocdOutput {\n\t\t\t// Make it clear which output is from the daemon.\n\t\t\tw := &ColorWriter{\n\t\t\t\tOut:    colorable.NewColorableStderr(),\n\t\t\t\tPrefix: \"openocd: \",\n\t\t\t\tColor:  TermColorYellow,\n\t\t\t}\n\t\t\tdaemon.Stdout = w\n\t\t\tdaemon.Stderr = w\n\t\t}\n\tcase \"jlink\":\n\t\tport = \":2331\"\n\t\tgdbCommands = append(gdbCommands, \"load\", \"monitor reset halt\")\n\n\t\t// We need a separate debugging daemon for on-chip debugging.\n\t\tdaemon = executeCommand(config.Options, \"JLinkGDBServer\", \"-device\", config.Target.JLinkDevice)\n\t\tif ocdOutput {\n\t\t\t// Make it clear which output is from the daemon.\n\t\t\tw := &ColorWriter{\n\t\t\t\tOut:    colorable.NewColorableStderr(),\n\t\t\t\tPrefix: \"jlink: \",\n\t\t\t\tColor:  TermColorYellow,\n\t\t\t}\n\t\t\tdaemon.Stdout = w\n\t\t\tdaemon.Stderr = w\n\t\t}\n\tcase \"qemu\":\n\t\tport = \":1234\"\n\t\t// Run in an emulator.\n\t\targs := append(emulator[1:], \"-s\", \"-S\")\n\t\tdaemon = executeCommand(config.Options, emulator[0], args...)\n\t\tdaemon.Stdout = os.Stdout\n\t\tdaemon.Stderr = os.Stderr\n\tcase \"qemu-user\":\n\t\tport = \":1234\"\n\t\t// Run in an emulator.\n\t\targs := append([]string{\"-g\", \"1234\"}, emulator[1:]...)\n\t\tdaemon = executeCommand(config.Options, emulator[0], args...)\n\t\tdaemon.Stdout = os.Stdout\n\t\tdaemon.Stderr = os.Stderr\n\tcase \"mgba\":\n\t\tport = \":2345\"\n\t\t// Run in an emulator.\n\t\targs := append(emulator[1:], \"-g\")\n\t\tdaemon = executeCommand(config.Options, emulator[0], args...)\n\t\tdaemon.Stdout = os.Stdout\n\t\tdaemon.Stderr = os.Stderr\n\tcase \"simavr\":\n\t\tport = \":1234\"\n\t\t// Run in an emulator.\n\t\targs := append(emulator[1:], \"-g\")\n\t\tdaemon = executeCommand(config.Options, emulator[0], args...)\n\t\tdaemon.Stdout = os.Stdout\n\t\tdaemon.Stderr = os.Stderr\n\tcase \"msd\":\n\t\treturn errors.New(\"gdb is not supported for drag-and-drop programmable devices\")\n\tdefault:\n\t\treturn fmt.Errorf(\"gdb is not supported with interface %#v\", gdbInterface)\n\t}\n\n\tif daemon != nil {\n\t\t// Make sure the daemon doesn't receive Ctrl-C that is intended for\n\t\t// GDB (to break the currently executing program).\n\t\tsetCommandAsDaemon(daemon)\n\n\t\t// Start now, and kill it on exit.\n\t\terr = daemon.Start()\n\t\tif err != nil {\n\t\t\treturn &commandError{\"failed to run\", daemon.Path, err}\n\t\t}\n\t\tdefer func() {\n\t\t\tdaemon.Process.Signal(os.Interrupt)\n\t\t\tvar stopped uint32\n\t\t\tgo func() {\n\t\t\t\ttime.Sleep(time.Millisecond * 100)\n\t\t\t\tif atomic.LoadUint32(&stopped) == 0 {\n\t\t\t\t\tdaemon.Process.Kill()\n\t\t\t\t}\n\t\t\t}()\n\t\t\tdaemon.Wait()\n\t\t\tatomic.StoreUint32(&stopped, 1)\n\t\t}()\n\t}\n\n\t// Ignore Ctrl-C, it must be passed on to GDB.\n\tc := make(chan os.Signal, 1)\n\tsignal.Notify(c, os.Interrupt)\n\tgo func() {\n\t\tfor range c {\n\t\t}\n\t}()\n\n\t// Construct and execute a gdb or lldb command.\n\t// By default: gdb -ex run <binary>\n\t// Exit the debugger with Ctrl-D.\n\tparams := []string{result.Executable}\n\tswitch debugger {\n\tcase \"gdb\":\n\t\tif port != \"\" {\n\t\t\tparams = append(params, \"-ex\", \"target extended-remote \"+port)\n\t\t}\n\t\tfor _, cmd := range gdbCommands {\n\t\t\tparams = append(params, \"-ex\", cmd)\n\t\t}\n\tcase \"lldb\":\n\t\tparams = append(params, \"--arch\", config.Triple())\n\t\tif port != \"\" {\n\t\t\tif strings.HasPrefix(port, \":\") {\n\t\t\t\tparams = append(params, \"-o\", \"gdb-remote \"+port[1:])\n\t\t\t} else {\n\t\t\t\treturn fmt.Errorf(\"cannot use LLDB over a gdb-remote that isn't a TCP port: %s\", port)\n\t\t\t}\n\t\t}\n\t\tfor _, cmd := range gdbCommands {\n\t\t\tif strings.HasPrefix(cmd, \"monitor \") {\n\t\t\t\tparams = append(params, \"-o\", \"process plugin packet \"+cmd)\n\t\t\t} else if cmd == \"load\" {\n\t\t\t\tparams = append(params, \"-o\", \"target modules load --load --slide 0\")\n\t\t\t} else {\n\t\t\t\treturn fmt.Errorf(\"don't know how to convert GDB command %#v to LLDB\", cmd)\n\t\t\t}\n\t\t}\n\t}\n\tcmd := executeCommand(config.Options, cmdName, params...)\n\tcmd.Stdin = os.Stdin\n\tcmd.Stdout = os.Stdout\n\tcmd.Stderr = os.Stderr\n\terr = cmd.Run()\n\tif err != nil {\n\t\treturn &commandError{\"failed to run \" + cmdName + \" with\", result.Executable, err}\n\t}\n\treturn nil\n}\n\n// Run compiles and runs the given program. Depending on the target provided in\n// the options, it will run the program directly on the host or will run it in\n// an emulator. For example, -target=wasm will cause the binary to be run inside\n// of a WebAssembly VM.\nfunc Run(pkgName string, options *compileopts.Options, cmdArgs []string) error {\n\tconfig, err := builder.NewConfig(options)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t_, err = buildAndRun(pkgName, config, os.Stdout, cmdArgs, nil, 0, func(cmd *exec.Cmd, result builder.BuildResult) error {\n\t\treturn cmd.Run()\n\t})\n\treturn err\n}\n\n// buildAndRun builds and runs the given program, writing output to stdout and\n// errors to os.Stderr. It takes care of emulators (qemu, wasmtime, etc) and\n// passes command line arguments and environment variables in a way appropriate\n// for the given emulator.\nfunc buildAndRun(pkgName string, config *compileopts.Config, stdout io.Writer, cmdArgs, environmentVars []string, timeout time.Duration, run func(cmd *exec.Cmd, result builder.BuildResult) error) (builder.BuildResult, error) {\n\t// Determine whether we're on a system that supports environment variables\n\t// and command line parameters (operating systems, WASI) or not (baremetal,\n\t// WebAssembly in the browser). If we're on a system without an environment,\n\t// we need to pass command line arguments and environment variables through\n\t// global variables (built into the binary directly) instead of the\n\t// conventional way.\n\tneedsEnvInVars := config.GOOS() == \"js\"\n\tfor _, tag := range config.BuildTags() {\n\t\tif tag == \"baremetal\" {\n\t\t\tneedsEnvInVars = true\n\t\t}\n\t}\n\tvar args, env []string\n\tvar extraCmdEnv []string\n\tif needsEnvInVars {\n\t\truntimeGlobals := make(map[string]string)\n\t\tif len(cmdArgs) != 0 {\n\t\t\truntimeGlobals[\"osArgs\"] = strings.Join(cmdArgs, \"\\x00\")\n\t\t}\n\t\tif len(environmentVars) != 0 {\n\t\t\truntimeGlobals[\"osEnv\"] = strings.Join(environmentVars, \"\\x00\")\n\t\t}\n\t\tif len(runtimeGlobals) != 0 {\n\t\t\t// This sets the global variables like they would be set with\n\t\t\t// `-ldflags=\"-X=runtime.osArgs=first\\x00second`.\n\t\t\t// The runtime package has two variables (osArgs and osEnv) that are\n\t\t\t// both strings, from which the parameters and environment variables\n\t\t\t// are read.\n\t\t\tconfig.Options.GlobalValues = map[string]map[string]string{\n\t\t\t\t\"runtime\": runtimeGlobals,\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// Pass environment variables and command line parameters as usual.\n\t\t// This also works on qemu-aarch64 etc.\n\t\targs = cmdArgs\n\t\tenv = environmentVars\n\t}\n\n\t// Create a temporary directory for intermediary files.\n\ttmpdir, err := os.MkdirTemp(\"\", \"tinygo\")\n\tif err != nil {\n\t\treturn builder.BuildResult{}, err\n\t}\n\tif !config.Options.Work {\n\t\tdefer os.RemoveAll(tmpdir)\n\t}\n\n\t// Build the binary to be run.\n\tformat, fileExt := config.EmulatorFormat()\n\tresult, err := builder.Build(pkgName, fileExt, tmpdir, config)\n\tif err != nil {\n\t\treturn result, err\n\t}\n\n\t// If needed, set a timeout on the command. This is done in tests so\n\t// they don't waste resources on a stalled test.\n\tvar ctx context.Context\n\tif timeout != 0 {\n\t\tvar cancel context.CancelFunc\n\t\tctx, cancel = context.WithTimeout(context.Background(), timeout)\n\t\tdefer cancel()\n\t}\n\n\t// Set up the command.\n\tvar name string\n\tif config.Target.Emulator == \"\" {\n\t\tname = result.Binary\n\t} else {\n\t\temulator, err := config.Emulator(format, result.Binary)\n\t\tif err != nil {\n\t\t\treturn result, err\n\t\t}\n\n\t\tname, emulator = emulator[0], emulator[1:]\n\n\t\t// wasmtime is a WebAssembly runtime CLI with WASI enabled by default.\n\t\t// By default, only stdio is allowed. For example, while STDOUT routes\n\t\t// to the host, other files don't. It also does not inherit environment\n\t\t// variables from the host. Some tests read testdata files, often from\n\t\t// outside the package directory. Other tests require temporary\n\t\t// writeable directories. We allow this by adding wasmtime flags below.\n\t\tif name == \"wasmtime\" {\n\t\t\tvar emuArgs []string\n\n\t\t\t// Extract the wasmtime subcommand (e.g. \"run\" or \"serve\")\n\t\t\tif len(emulator) > 1 {\n\t\t\t\temuArgs = append(emuArgs, emulator[0])\n\t\t\t\temulator = emulator[1:]\n\t\t\t}\n\n\t\t\twd, _ := os.Getwd()\n\n\t\t\t// Below adds additional wasmtime flags in case a test reads files\n\t\t\t// outside its directory, like \"../testdata/e.txt\". This allows any\n\t\t\t// relative directory up to the module root, even if the test never\n\t\t\t// reads any files.\n\t\t\tif config.TestConfig.CompileTestBinary {\n\t\t\t\t// Set working directory to package dir\n\t\t\t\twd = result.MainDir\n\n\t\t\t\t// Add relative dirs (../, ../..) up to module root (for wasip1)\n\t\t\t\tdirs := dirsToModuleRootRel(result.MainDir, result.ModuleRoot)\n\n\t\t\t\t// Add absolute dirs up to module root (for wasip2)\n\t\t\t\tdirs = append(dirs, dirsToModuleRootAbs(result.MainDir, result.ModuleRoot)...)\n\n\t\t\t\tfor _, d := range dirs {\n\t\t\t\t\temuArgs = append(emuArgs, \"--dir=\"+d)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\temuArgs = append(emuArgs, \"--dir=.\")\n\t\t\t}\n\n\t\t\temuArgs = append(emuArgs, \"--dir=\"+wd)\n\t\t\temuArgs = append(emuArgs, \"--env=PWD=\"+wd)\n\t\t\tfor _, v := range environmentVars {\n\t\t\t\temuArgs = append(emuArgs, \"--env\", v)\n\t\t\t}\n\n\t\t\t// Set this for nicer backtraces during tests, but don't override the user.\n\t\t\tif _, ok := os.LookupEnv(\"WASMTIME_BACKTRACE_DETAILS\"); !ok {\n\t\t\t\textraCmdEnv = append(extraCmdEnv, \"WASMTIME_BACKTRACE_DETAILS=1\")\n\t\t\t}\n\n\t\t\temulator = append(emuArgs, emulator...)\n\t\t}\n\n\t\targs = append(emulator, args...)\n\t}\n\tvar cmd *exec.Cmd\n\tif ctx != nil {\n\t\tcmd = exec.CommandContext(ctx, name, args...)\n\t} else {\n\t\tcmd = exec.Command(name, args...)\n\t}\n\tcmd.Env = append(cmd.Env, env...)\n\tcmd.Env = append(cmd.Env, extraCmdEnv...)\n\n\t// Configure stdout/stderr. The stdout may go to a buffer, not a real\n\t// stdout.\n\tcmd.Stdout = newOutputWriter(stdout, result.Executable)\n\tcmd.Stderr = os.Stderr\n\tif config.EmulatorName() == \"simavr\" {\n\t\tcmd.Stdout = nil // don't print initial load commands\n\t\tcmd.Stderr = stdout\n\t}\n\n\t// If this is a test, reserve CPU time for it so that increased\n\t// parallelism doesn't blow up memory usage. If this isn't a test but\n\t// simply `tinygo run`, then it is practically a no-op.\n\tconfig.Options.Semaphore <- struct{}{}\n\tdefer func() {\n\t\t<-config.Options.Semaphore\n\t}()\n\n\t// Run binary.\n\tif config.Options.PrintCommands != nil {\n\t\tconfig.Options.PrintCommands(cmd.Path, cmd.Args[1:]...)\n\t}\n\terr = run(cmd, result)\n\tif err != nil {\n\t\tif ctx != nil && ctx.Err() == context.DeadlineExceeded {\n\t\t\tfmt.Fprintf(stdout, \"--- timeout of %s exceeded, terminating...\\n\", timeout)\n\t\t\terr = ctx.Err()\n\t\t}\n\t\treturn result, &commandError{\"failed to run compiled binary\", result.Binary, err}\n\t}\n\treturn result, nil\n}\n\nfunc touchSerialPortAt1200bps(port string) (err error) {\n\tretryCount := 3\n\tfor i := 0; i < retryCount; i++ {\n\t\t// Open port\n\t\tp, e := serial.Open(port, &serial.Mode{BaudRate: 1200})\n\t\tif e != nil {\n\t\t\tif runtime.GOOS == `windows` {\n\t\t\t\tse, ok := e.(*serial.PortError)\n\t\t\t\tif ok && se.Code() == serial.InvalidSerialPort {\n\t\t\t\t\t// InvalidSerialPort error occurs when transitioning to boot\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\t\t\t}\n\t\t\ttime.Sleep(1 * time.Second)\n\t\t\terr = e\n\t\t\tcontinue\n\t\t}\n\t\tdefer p.Close()\n\n\t\tp.SetDTR(false)\n\t\treturn nil\n\t}\n\treturn fmt.Errorf(\"opening port: %s\", err)\n}\n\nfunc flashUF2UsingMSD(volumes []string, tmppath string, options *compileopts.Options) error {\n\tfor start := time.Now(); time.Since(start) < options.Timeout; {\n\t\t// Find a UF2 mount point.\n\t\tmounts, err := findFATMounts(options)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfor _, mount := range mounts {\n\t\t\tfor _, volume := range volumes {\n\t\t\t\tif mount.name != volume {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif _, err := os.Stat(filepath.Join(mount.path, \"INFO_UF2.TXT\")); err != nil {\n\t\t\t\t\t// No INFO_UF2.TXT found, which is expected on a UF2\n\t\t\t\t\t// filesystem.\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t// Found the filesystem, so flash the device!\n\t\t\t\treturn moveFile(tmppath, filepath.Join(mount.path, \"flash.uf2\"))\n\t\t\t}\n\t\t}\n\t\ttime.Sleep(500 * time.Millisecond)\n\t}\n\treturn errors.New(\"unable to locate any volume: [\" + strings.Join(volumes, \",\") + \"]\")\n}\n\nfunc flashHexUsingMSD(volumes []string, tmppath string, options *compileopts.Options) error {\n\tfor start := time.Now(); time.Since(start) < options.Timeout; {\n\t\t// Find all mount points.\n\t\tmounts, err := findFATMounts(options)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfor _, mount := range mounts {\n\t\t\tfor _, volume := range volumes {\n\t\t\t\tif mount.name != volume {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t// Found the filesystem, so flash the device!\n\t\t\t\treturn moveFile(tmppath, filepath.Join(mount.path, \"flash.hex\"))\n\t\t\t}\n\t\t}\n\t\ttime.Sleep(500 * time.Millisecond)\n\t}\n\treturn errors.New(\"unable to locate any volume: [\" + strings.Join(volumes, \",\") + \"]\")\n}\n\ntype mountPoint struct {\n\tname string\n\tpath string\n}\n\n// Find all the mount points on the system that use the FAT filesystem.\nfunc findFATMounts(options *compileopts.Options) ([]mountPoint, error) {\n\tvar points []mountPoint\n\tswitch runtime.GOOS {\n\tcase \"darwin\":\n\t\tlist, err := os.ReadDir(\"/Volumes\")\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"could not list mount points: %w\", err)\n\t\t}\n\t\tfor _, elem := range list {\n\t\t\tvolumePath := filepath.Join(\"/Volumes\", elem.Name())\n\t\t\tif _, err := os.Stat(volumePath); err != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tcmd := exec.Command(\"diskutil\", \"info\", volumePath)\n\t\t\tvar out bytes.Buffer\n\t\t\tcmd.Stdout = &out\n\t\t\tif err := cmd.Run(); err != nil {\n\t\t\t\tcontinue // skip if diskutil failed\n\t\t\t}\n\n\t\t\tdiskInfo := map[string]string{}\n\t\t\tscanner := bufio.NewScanner(&out)\n\t\t\tfor scanner.Scan() {\n\t\t\t\tline := scanner.Text()\n\t\t\t\tparts := strings.SplitN(line, \":\", 2)\n\t\t\t\tif len(parts) != 2 {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tkey := strings.TrimSpace(parts[0])\n\t\t\t\tvalue := strings.TrimSpace(parts[1])\n\t\t\t\tdiskInfo[key] = value\n\t\t\t}\n\t\t\tif err := scanner.Err(); err != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tvolName, okv := diskInfo[\"Volume Name\"]\n\t\t\tfsType, okf := diskInfo[\"File System Personality\"]\n\t\t\tif !okv || !okf {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Check if a filesystem type is FAT-based\n\t\t\tif strings.Contains(strings.ToUpper(fsType), \"FAT\") {\n\t\t\t\tpoints = append(points, mountPoint{\n\t\t\t\t\tname: volName,\n\t\t\t\t\tpath: volumePath,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\tsort.Slice(points, func(i, j int) bool {\n\t\t\treturn points[i].path < points[j].path\n\t\t})\n\t\treturn points, nil\n\tcase \"linux\":\n\t\ttab, err := os.ReadFile(\"/proc/mounts\") // symlink to /proc/self/mounts on my system\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"could not list mount points: %w\", err)\n\t\t}\n\t\tfor _, line := range strings.Split(string(tab), \"\\n\") {\n\t\t\tfields := strings.Fields(line)\n\t\t\tif len(fields) <= 2 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfstype := fields[2]\n\t\t\t// chromeos bind mounts use 9p\n\t\t\tif !(fstype == \"vfat\" || fstype == \"9p\") {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfspath := strings.ReplaceAll(fields[1], \"\\\\040\", \" \")\n\t\t\tpoints = append(points, mountPoint{\n\t\t\t\tname: filepath.Base(fspath),\n\t\t\t\tpath: fspath,\n\t\t\t})\n\t\t}\n\t\treturn points, nil\n\tcase \"windows\":\n\t\t// Obtain a list of all currently mounted volumes.\n\t\tcmd := executeCommand(options, \"powershell\", \"-c\",\n\t\t\t\"Get-CimInstance -ClassName Win32_LogicalDisk | Select-Object DeviceID, DriveType, FileSystem, VolumeName\")\n\t\tvar out bytes.Buffer\n\t\tcmd.Stdout = &out\n\t\terr := cmd.Run()\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"could not list mount points: %w\", err)\n\t\t}\n\n\t\t// Extract data to convert to a []mountPoint slice.\n\t\tfor _, line := range strings.Split(out.String(), \"\\n\") {\n\t\t\twords := strings.Fields(line)\n\t\t\tif len(words) < 3 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif words[1] != \"2\" || words[2] != \"FAT\" {\n\t\t\t\t// - DriveType 2 is removable (which we're looking for).\n\t\t\t\t// - We only want to return FAT filesystems.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpoints = append(points, mountPoint{\n\t\t\t\tname: words[3],\n\t\t\t\tpath: words[0],\n\t\t\t})\n\t\t}\n\t\treturn points, nil\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unknown GOOS for listing mount points: %s\", runtime.GOOS)\n\t}\n}\n\n// getDefaultPort returns the default serial port depending on the operating system.\nfunc getDefaultPort(portFlag string, usbInterfaces []string) (port string, err error) {\n\tportCandidates := strings.FieldsFunc(portFlag, func(c rune) bool { return c == ',' })\n\tif len(portCandidates) == 1 {\n\t\treturn portCandidates[0], nil\n\t}\n\n\tvar ports []string\n\tswitch runtime.GOOS {\n\tcase \"freebsd\":\n\t\tports, err = filepath.Glob(\"/dev/cuaU*\")\n\tcase \"darwin\", \"linux\", \"windows\":\n\t\tvar portsList []*enumerator.PortDetails\n\t\tportsList, err = enumerator.GetDetailedPortsList()\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\n\t\tvar preferredPortIDs [][2]uint16\n\t\tfor _, s := range usbInterfaces {\n\t\t\tparts := strings.Split(s, \":\")\n\t\t\tif len(parts) != 2 {\n\t\t\t\treturn \"\", fmt.Errorf(\"could not parse USB VID/PID pair %q\", s)\n\t\t\t}\n\t\t\tvid, err := strconv.ParseUint(parts[0], 16, 16)\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", fmt.Errorf(\"could not parse USB vendor ID %q: %w\", parts[1], err)\n\t\t\t}\n\t\t\tpid, err := strconv.ParseUint(parts[1], 16, 16)\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", fmt.Errorf(\"could not parse USB product ID %q: %w\", parts[1], err)\n\t\t\t}\n\t\t\tpreferredPortIDs = append(preferredPortIDs, [2]uint16{uint16(vid), uint16(pid)})\n\t\t}\n\n\t\tvar primaryPorts []string   // ports picked from preferred USB VID/PID\n\t\tvar secondaryPorts []string // other ports (as a fallback)\n\t\tfor _, p := range portsList {\n\t\t\tif !p.IsUSB {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif p.VID != \"\" && p.PID != \"\" {\n\t\t\t\tfoundPort := false\n\t\t\t\tvid, vidErr := strconv.ParseUint(p.VID, 16, 16)\n\t\t\t\tpid, pidErr := strconv.ParseUint(p.PID, 16, 16)\n\t\t\t\tif vidErr == nil && pidErr == nil {\n\t\t\t\t\tfor _, id := range preferredPortIDs {\n\t\t\t\t\t\tif uint16(vid) == id[0] && uint16(pid) == id[1] {\n\t\t\t\t\t\t\tprimaryPorts = append(primaryPorts, p.Name)\n\t\t\t\t\t\t\tfoundPort = true\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif foundPort {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsecondaryPorts = append(secondaryPorts, p.Name)\n\t\t}\n\t\tif len(primaryPorts) == 1 {\n\t\t\t// There is exactly one match in the set of preferred ports. Use\n\t\t\t// this port, even if there may be others available. This allows\n\t\t\t// flashing a specific board even if there are multiple available.\n\t\t\treturn primaryPorts[0], nil\n\t\t} else if len(primaryPorts) > 1 {\n\t\t\t// There are multiple preferred ports, probably because more than\n\t\t\t// one device of the same type are connected (e.g. two Arduino\n\t\t\t// Unos).\n\t\t\tports = primaryPorts\n\t\t} else {\n\t\t\t// No preferred ports found. Fall back to other serial ports\n\t\t\t// available in the system.\n\t\t\tports = secondaryPorts\n\t\t}\n\tdefault:\n\t\treturn \"\", errors.New(\"unable to search for a default USB device to be flashed on this OS\")\n\t}\n\n\tif err != nil {\n\t\treturn \"\", err\n\t} else if ports == nil {\n\t\treturn \"\", errors.New(\"unable to locate a serial port\")\n\t} else if len(ports) == 0 {\n\t\treturn \"\", errors.New(\"no serial ports available\")\n\t}\n\n\tif len(portCandidates) == 0 {\n\t\tif len(usbInterfaces) > 0 {\n\t\t\treturn \"\", errors.New(\"unable to search for a default USB device - use -port flag, available ports are \" + strings.Join(ports, \", \"))\n\t\t} else if len(ports) == 1 {\n\t\t\treturn ports[0], nil\n\t\t} else {\n\t\t\treturn \"\", errors.New(\"multiple serial ports available - use -port flag, available ports are \" + strings.Join(ports, \", \"))\n\t\t}\n\t}\n\n\tfor _, ps := range portCandidates {\n\t\tfor _, p := range ports {\n\t\t\tif p == ps {\n\t\t\t\treturn p, nil\n\t\t\t}\n\t\t}\n\t}\n\n\treturn \"\", errors.New(\"port you specified '\" + strings.Join(portCandidates, \",\") + \"' does not exist, available ports are \" + strings.Join(ports, \", \"))\n}\n\n// getBMPPorts returns BlackMagicProbe's serial ports if any\nfunc getBMPPorts() (gdbPort, uartPort string, err error) {\n\tvar portsList []*enumerator.PortDetails\n\tportsList, err = enumerator.GetDetailedPortsList()\n\tif err != nil {\n\t\treturn \"\", \"\", err\n\t}\n\tvar ports []string\n\tfor _, p := range portsList {\n\t\tif !p.IsUSB {\n\t\t\tcontinue\n\t\t}\n\t\tif p.VID != \"\" && p.PID != \"\" {\n\t\t\tvid, vidErr := strconv.ParseUint(p.VID, 16, 16)\n\t\t\tpid, pidErr := strconv.ParseUint(p.PID, 16, 16)\n\t\t\tif vidErr == nil && pidErr == nil && vid == 0x1d50 && pid == 0x6018 {\n\t\t\t\tports = append(ports, p.Name)\n\t\t\t}\n\t\t}\n\t}\n\tif len(ports) == 2 {\n\t\treturn ports[0], ports[1], nil\n\t} else if len(ports) == 0 {\n\t\treturn \"\", \"\", errors.New(\"no BMP detected\")\n\t} else {\n\t\treturn \"\", \"\", fmt.Errorf(\"expected 2 BMP serial ports, found %d - did you perhaps connect more than one BMP?\", len(ports))\n\t}\n}\n\nconst (\n\tusageBuild = `Build compiles the packages named by the import paths, along with their\ndependencies, but it does not install the results. The output binary is\nspecified using the -o parameter. The generated file type depends on the\nextension:\n\n\t.o:\n\t\t\tCreate a relocatable object file. You can use this option if you\n\t\t\tdon't want to use the TinyGo build system or want to do other custom\n\t\t\tthings.\n\n\t.ll:\n\t\t\tCreate textual LLVM IR, after optimization. This is mainly useful\n\t\t\tfor debugging.\n\n\t.bc:\n\t\t\tCreate LLVM bitcode, after optimization. This may be useful for\n\t\t\tdebugging or for linking into other programs using LTO.\n\n\t.hex:\n\t\t\tCreate an Intel HEX file to flash it to a microcontroller.\n\n\t.bin:\n\t\t\tSimilar, but create a binary file.\n\n\t.wasm:\n\t\t\tCompile and link a WebAssembly file.\n\n(all other) Compile and link the program into a regular executable. For\nmicrocontrollers, it is common to use the .elf file extension to indicate a\nlinked ELF file is generated. For Linux, it is common to build binaries with no\nextension at all.`\n\n\tusageRun = `Run the program, either directly on the host or in an emulated environment \n(depending on -target).`\n\n\tusageFlash = `Flash the program to a microcontroller. Some common flags are described below.\n\n\t-target={name}: \n\t\t\tSpecifies the type of microcontroller that is used. The name of the\n\t\t\tmicrocontroller is given on the individual pages for each board type\n\t\t\tlisted under Microcontrollers\n\t\t\t(https://tinygo.org/docs/reference/microcontrollers/).\n\t\t\tExamples: \"arduino-nano\", \"d1mini\", \"xiao\".\n\n\t-o={filename}:\n\t\t\tSave the built binary to the specified output file. The file\n\t\t\tformat must match the target's expected format (e.g., .hex,\n\t\t\t.uf2). Both flashing and saving will be performed.\n\n\t-monitor: \n\t\t\tStart the serial monitor (see below) immediately after\n\t\t\tflashing. However, some microcontrollers need a split second\n\t\t\tor two to configure the serial port after flashing, and\n\t\t\tusing the \"-monitor\" flag can fail because the serial\n\t\t\tmonitor starts too quickly. In that case, use the \"tinygo\n\t\t\tmonitor\" command explicitly.`\n\n\tusageMonitor = `Start the serial monitor on the serial port that is connected to the\nmicrocontroller. If there is only a single board attached to the host computer,\nthe default values for various options should be sufficient. In other\nsituations, particularly if you have multiple microcontrollers attached, some\nparameters may need to be overridden using the following flags:\n\n\t-port={port}:\n\t\t\tIf there are multiple microcontroller attached, an error\n\t\t\tmessage will display a list of potential serial ports. The\n\t\t\tappropriate port can be specified by this flag. On Linux,\n\t\t\tthe port will be something like /dev/ttyUSB0 or /dev/ttyACM1.\n\t\t\tOn MacOS, the port will look like /dev/cu.usbserial-1420. On\n\t\t\tWindows, the port will be something like COM1 or COM31.\n\n\t-baudrate={rate}:\n\t\t\tThe default baud rate is 115200. Boards using the AVR\n\t\t\tprocessor (e.g. Arduino Nano, Arduino Mega 2560) use 9600\n\t\t\tinstead.\n\n\t-target={name}:\n\t\t\tIf you have more than one microcontrollers attached, you can\n\t\t\tsometimes just specify the target name and let tinygo\n\t\t\tmonitor figure out the port. Sometimes, this does not work\n\t\t\tand you have to explicitly use the -port flag.\n\nThe serial monitor intercepts several control characters for its own use instead of sending them\nto the microcontroller:\n\n\tControl-C: terminates the tinygo monitor\n\tControl-Z: suspends the tinygo monitor and drops back into shell\n\tControl-\\: terminates the tinygo monitor with a stack trace\n\tControl-S: flow control, suspends output to the console\n\tControl-Q: flow control, resumes output to the console\n\tControl-@: thrown away by tinygo monitor\n\nNote: If you are using os.Stdin on the microcontroller, you may find that a CR\ncharacter on the host computer (also known as Enter, ^M, or \\r) is transmitted\nto the microcontroller without conversion, so os.Stdin returns a \\r character\ninstead of the expected \\n (also known as ^J, NL, or LF) to indicate\nend-of-line. You may be able to get around this problem by hitting Control-J in\ntinygo monitor to transmit the \\n end-of-line character.`\n\n\tusageGdb = `Build the program, optionally flash it to a microcontroller if it is a remote \ntarget, and drop into a GDB shell. From there you can set breakpoints, start the\nprogram with \"run\" or \"continue\" (\"run\" for a local program, continue for\non-chip debugging), single-step, show a backtrace, break and resume the program\nwith Ctrl-C/\"continue\", etc. You may need to install extra tools (like openocd\nand arm-none-eabi-gdb) to be able to do this. Also, you may need a dedicated\ndebugger to be able to debug certain boards if no debugger is integrated. Some\nboards (like the BBC micro:bit and most professional evaluation boards) have an\nintegrated debugger.`\n\n\tusageClean = `Clean the cache directory, normally stored in $HOME/.cache/tinygo. This is not\nnormally needed.`\n\n\tusageHelp    = `Print a short summary of the available commands, plus a list of command flags.`\n\tusageVersion = `Print the version of the command and the version of the used $GOROOT.`\n\tusageEnv     = `Print a list of environment variables that affect TinyGo (as a shell script).\nIf one or more variable names are given as arguments, env prints the value of\neach on a new line.`\n\n\tusageDefault = `TinyGo is a Go compiler for small places.\nversion: %s\nusage: %s <command> [arguments]\ncommands:\n\t\tbuild:\t\tcompile packages and dependencies\n\t\trun:\t\tcompile and run immediately\n\t\ttest:\t\ttest packages\n\t\tflash:\t\tcompile and flash to the device\n\t\tgdb:\t\trun/flash and immediately enter GDB\n\t\tlldb:\t\trun/flash and immediately enter LLDB\n\t\tmonitor:\topen communication port\n\t\tports:\t\tlist available serial ports\n\t\tenv:\t\tlist environment variables used during build\n\t\tlist:\t\trun go list using the TinyGo root\n\t\tclean:\t\tempty cache directory (%s)\n\t\ttargets:\tlist targets\n\t\tinfo:\t\tshow info for specified target\n\t\tversion:\tshow version\n\t\thelp:\t\tprint this help text`\n)\n\nvar (\n\tcommandHelp = map[string]string{\n\t\t\"build\":   usageBuild,\n\t\t\"run\":     usageRun,\n\t\t\"flash\":   usageFlash,\n\t\t\"monitor\": usageMonitor,\n\t\t\"gdb\":     usageGdb,\n\t\t\"clean\":   usageClean,\n\t\t\"help\":    usageHelp,\n\t\t\"version\": usageVersion,\n\t\t\"env\":     usageEnv,\n\t}\n)\n\nfunc usage(command string) {\n\tval, ok := commandHelp[command]\n\tif !ok {\n\t\tfmt.Fprintf(os.Stderr, usageDefault, goenv.Version(), os.Args[0], goenv.Get(\"GOCACHE\"))\n\t\tif flag.Parsed() {\n\t\t\tfmt.Fprintln(os.Stderr, \"\\nflags:\")\n\t\t\tflag.PrintDefaults()\n\t\t}\n\n\t\tfmt.Fprintln(os.Stderr, \"\\nfor more details, see https://tinygo.org/docs/reference/usage/\")\n\t} else {\n\t\tfmt.Fprintln(os.Stderr, val)\n\t}\n\n}\n\n// Print diagnostics very similar to the -json flag in Go.\nfunc printBuildOutput(err error, jsonDiagnostics bool) {\n\tif err == nil {\n\t\treturn // nothing to report\n\t}\n\n\tif jsonDiagnostics {\n\t\tworkingDir, getwdErr := os.Getwd()\n\t\tif getwdErr != nil {\n\t\t\tworkingDir = \"\"\n\t\t}\n\n\t\ttype jsonDiagnosticOutput struct {\n\t\t\tImportPath string\n\t\t\tAction     string\n\t\t\tOutput     string `json:\",omitempty\"`\n\t\t\tStartPos   string `json:\",omitempty\"` // non-standard\n\t\t\tEndPos     string `json:\",omitempty\"` // non-standard\n\t\t}\n\n\t\tfor _, diags := range diagnostics.CreateDiagnostics(err) {\n\t\t\tif diags.ImportPath != \"\" {\n\t\t\t\toutput, _ := json.Marshal(jsonDiagnosticOutput{\n\t\t\t\t\tImportPath: diags.ImportPath,\n\t\t\t\t\tAction:     \"build-output\",\n\t\t\t\t\tOutput:     \"# \" + diags.ImportPath + \"\\n\",\n\t\t\t\t})\n\t\t\t\tos.Stdout.Write(append(output, '\\n'))\n\t\t\t}\n\t\t\tfor _, diag := range diags.Diagnostics {\n\t\t\t\tw := &bytes.Buffer{}\n\t\t\t\tdiag.WriteTo(w, workingDir)\n\t\t\t\tdata := jsonDiagnosticOutput{\n\t\t\t\t\tImportPath: diags.ImportPath,\n\t\t\t\t\tAction:     \"build-output\",\n\t\t\t\t\tOutput:     w.String(),\n\t\t\t\t}\n\t\t\t\tif diag.StartPos.IsValid() && diag.EndPos.IsValid() {\n\t\t\t\t\t// Include the non-standard StartPos/EndPos values. These\n\t\t\t\t\t// are useful for the TinyGo Playground to show better error\n\t\t\t\t\t// messages.\n\t\t\t\t\tdata.StartPos = diagnostics.RelativePosition(diag.StartPos, workingDir).String()\n\t\t\t\t\tdata.EndPos = diagnostics.RelativePosition(diag.EndPos, workingDir).String()\n\t\t\t\t}\n\t\t\t\toutput, _ := json.Marshal(data)\n\t\t\t\tos.Stdout.Write(append(output, '\\n'))\n\t\t\t}\n\n\t\t\t// Emit the \"Action\":\"build-fail\" JSON.\n\t\t\toutput, _ := json.Marshal(jsonDiagnosticOutput{\n\t\t\t\tImportPath: diags.ImportPath,\n\t\t\t\tAction:     \"build-fail\",\n\t\t\t})\n\t\t\tos.Stdout.Write(append(output, '\\n'))\n\t\t}\n\t\tos.Exit(1)\n\t}\n\n\t// Regular diagnostic handling.\n\thandleCompilerError(err)\n}\n\nfunc handleCompilerError(err error) {\n\tif err != nil {\n\t\twd, getwdErr := os.Getwd()\n\t\tif getwdErr != nil {\n\t\t\twd = \"\"\n\t\t}\n\t\tdiagnostics.CreateDiagnostics(err).WriteTo(os.Stderr, wd)\n\t\tos.Exit(1)\n\t}\n}\n\n// This is a special type for the -X flag to parse the pkgpath.Var=stringVal\n// format. It has to be a special type to allow multiple variables to be defined\n// this way.\ntype globalValuesFlag map[string]map[string]string\n\nfunc (m globalValuesFlag) String() string {\n\treturn \"pkgpath.Var=value\"\n}\n\nfunc (m globalValuesFlag) Set(value string) error {\n\tequalsIndex := strings.IndexByte(value, '=')\n\tif equalsIndex < 0 {\n\t\treturn errors.New(\"expected format pkgpath.Var=value\")\n\t}\n\tpathAndName := value[:equalsIndex]\n\tpointIndex := strings.LastIndexByte(pathAndName, '.')\n\tif pointIndex < 0 {\n\t\treturn errors.New(\"expected format pkgpath.Var=value\")\n\t}\n\tpath := pathAndName[:pointIndex]\n\tname := pathAndName[pointIndex+1:]\n\tstringValue := value[equalsIndex+1:]\n\tif m[path] == nil {\n\t\tm[path] = make(map[string]string)\n\t}\n\tm[path][name] = stringValue\n\treturn nil\n}\n\n// parseGoLinkFlag parses the -ldflags parameter. Its primary purpose right now\n// is the -X flag, for setting the value of global string variables.\nfunc parseGoLinkFlag(flagsString string) (map[string]map[string]string, string, error) {\n\tset := flag.NewFlagSet(\"link\", flag.ExitOnError)\n\tglobalVarValues := make(globalValuesFlag)\n\tset.Var(globalVarValues, \"X\", \"Set the value of the string variable to the given value.\")\n\textLDFlags := set.String(\"extldflags\", \"\", \"additional flags to pass to external linker\")\n\tflags, err := shlex.Split(flagsString)\n\tif err != nil {\n\t\treturn nil, \"\", err\n\t}\n\terr = set.Parse(flags)\n\tif err != nil {\n\t\treturn nil, \"\", err\n\t}\n\treturn map[string]map[string]string(globalVarValues), *extLDFlags, nil\n}\n\n// getListOfPackages returns a standard list of packages for a given list that might\n// include wildards using `go list`.\n// For example [./...] => [\"pkg1\", \"pkg1/pkg12\", \"pkg2\"]\nfunc getListOfPackages(pkgs []string, options *compileopts.Options) ([]string, error) {\n\tconfig, err := builder.NewConfig(options)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tcmd, err := loader.List(config, nil, pkgs)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to run `go list`: %w\", err)\n\t}\n\toutputBuf := bytes.NewBuffer(nil)\n\tcmd.Stdout = outputBuf\n\tcmd.Stderr = os.Stderr\n\terr = cmd.Run()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar pkgNames []string\n\tsc := bufio.NewScanner(outputBuf)\n\tfor sc.Scan() {\n\t\tpkgNames = append(pkgNames, sc.Text())\n\t}\n\n\treturn pkgNames, nil\n}\n\nfunc main() {\n\tif len(os.Args) < 2 {\n\t\tfmt.Fprintln(os.Stderr, \"No command-line arguments supplied.\")\n\t\tusage(\"\")\n\t\tos.Exit(1)\n\t}\n\tcommand := os.Args[1]\n\n\topt := flag.String(\"opt\", \"z\", \"optimization level: 0, 1, 2, s, z\")\n\tgc := flag.String(\"gc\", \"\", \"garbage collector to use (none, leaking, conservative, custom, precise, boehm)\")\n\tpanicStrategy := flag.String(\"panic\", \"print\", \"panic strategy (print, trap)\")\n\tscheduler := flag.String(\"scheduler\", \"\", \"which scheduler to use (none, tasks, cores, threads, asyncify)\")\n\tserial := flag.String(\"serial\", \"\", \"which serial output to use (none, uart, usb, rtt)\")\n\twork := flag.Bool(\"work\", false, \"print the name of the temporary build directory and do not delete this directory on exit\")\n\tinterpTimeout := flag.Duration(\"interp-timeout\", 180*time.Second, \"interp optimization pass timeout\")\n\tvar tags buildutil.TagsFlag\n\tflag.Var(&tags, \"tags\", \"a space-separated list of extra build tags\")\n\ttarget := flag.String(\"target\", \"\", \"chip/board name or JSON target specification file\")\n\tbuildMode := flag.String(\"buildmode\", \"\", \"build mode to use (default, c-shared, wasi-legacy)\")\n\tvar stackSize uint64\n\tflag.Func(\"stack-size\", \"goroutine stack size (if unknown at compile time)\", func(s string) error {\n\t\tsize, err := bytesize.Parse(s)\n\t\tstackSize = uint64(size)\n\t\treturn err\n\t})\n\tprintSize := flag.String(\"size\", \"\", \"print sizes (none, short, full, html)\")\n\tprintStacks := flag.Bool(\"print-stacks\", false, \"print stack sizes of goroutines\")\n\tprintAllocsString := flag.String(\"print-allocs\", \"\", \"regular expression of functions for which heap allocations should be printed\")\n\tprintCommands := flag.Bool(\"x\", false, \"Print commands\")\n\tflagJSON := flag.Bool(\"json\", false, \"print output in JSON format\")\n\tparallelism := flag.Int(\"p\", runtime.GOMAXPROCS(0), \"the number of build jobs that can run in parallel\")\n\tnodebug := flag.Bool(\"no-debug\", false, \"strip debug information\")\n\tnobounds := flag.Bool(\"nobounds\", false, \"do not emit bounds checks\")\n\tocdCommandsString := flag.String(\"ocd-commands\", \"\", \"OpenOCD commands, overriding target spec (can specify multiple separated by commas)\")\n\tocdOutput := flag.Bool(\"ocd-output\", false, \"print OCD daemon output during debug\")\n\tport := flag.String(\"port\", \"\", \"flash port (can specify multiple candidates separated by commas)\")\n\ttimeout := flag.Duration(\"timeout\", 20*time.Second, \"the length of time to retry locating the MSD volume to be used for flashing\")\n\tprogrammer := flag.String(\"programmer\", \"\", \"which hardware programmer to use\")\n\tldflags := flag.String(\"ldflags\", \"\", \"Go link tool compatible ldflags\")\n\tllvmFeatures := flag.String(\"llvm-features\", \"\", \"comma separated LLVM features to enable\")\n\tcpuprofile := flag.String(\"cpuprofile\", \"\", \"cpuprofile output\")\n\tmonitor := flag.Bool(\"monitor\", false, \"enable serial monitor\")\n\tbaudrate := flag.Int(\"baudrate\", 115200, \"baudrate of serial monitor\")\n\tgocompatibility := flag.Bool(\"go-compatibility\", true, \"enable to check for Go versions compatibility, you can also configure this by setting the TINYGO_GOCOMPATIBILITY environment variable\")\n\n\t// Internal flags, that are only intended for TinyGo development.\n\tprintIR := flag.Bool(\"internal-printir\", false, \"print LLVM IR\")\n\tdumpSSA := flag.Bool(\"internal-dumpssa\", false, \"dump internal Go SSA\")\n\tverifyIR := flag.Bool(\"internal-verifyir\", false, \"run extra verification steps on LLVM IR\")\n\t// Don't generate debug information in the IR, to make IR more readable.\n\t// You generally want debug information in IR for various features, like\n\t// stack size calculation and features like -size=short, -print-allocs=,\n\t// etc. The -no-debug flag is used to strip it at link time. But for TinyGo\n\t// development it can be useful to not emit debug information at all.\n\tskipDwarf := flag.Bool(\"internal-nodwarf\", false, \"internal flag, use -no-debug instead\")\n\n\tvar flagDeps, flagTest bool\n\tif command == \"help\" || command == \"list\" {\n\t\tflag.BoolVar(&flagDeps, \"deps\", false, \"supply -deps flag to go list\")\n\t\tflag.BoolVar(&flagTest, \"test\", false, \"supply -test flag to go list\")\n\t}\n\tvar outpath string\n\tif command == \"help\" || command == \"build\" || command == \"test\" || command == \"flash\" {\n\t\tflag.StringVar(&outpath, \"o\", \"\", \"output filename\")\n\t}\n\n\tvar witPackage, witWorld string\n\tif command == \"help\" || command == \"build\" || command == \"test\" || command == \"run\" {\n\t\tflag.StringVar(&witPackage, \"wit-package\", \"\", \"wit package for wasm component embedding\")\n\t\tflag.StringVar(&witWorld, \"wit-world\", \"\", \"wit world for wasm component embedding\")\n\t}\n\n\tvar testConfig compileopts.TestConfig\n\tif command == \"help\" || command == \"test\" {\n\t\tflag.BoolVar(&testConfig.CompileOnly, \"c\", false, \"compile the test binary but do not run it\")\n\t\tflag.BoolVar(&testConfig.Verbose, \"v\", false, \"verbose: print additional output\")\n\t\tflag.BoolVar(&testConfig.Short, \"short\", false, \"short: run smaller test suite to save time\")\n\t\tflag.StringVar(&testConfig.RunRegexp, \"run\", \"\", \"run: regexp of tests to run\")\n\t\tflag.StringVar(&testConfig.SkipRegexp, \"skip\", \"\", \"skip: regexp of tests to skip\")\n\t\ttestConfig.Count = flag.Int(\"count\", 1, \"count: number of times to run tests/benchmarks `count` times\")\n\t\tflag.StringVar(&testConfig.BenchRegexp, \"bench\", \"\", \"bench: regexp of benchmarks to run\")\n\t\tflag.StringVar(&testConfig.BenchTime, \"benchtime\", \"\", \"run each benchmark for duration `d`\")\n\t\tflag.BoolVar(&testConfig.BenchMem, \"benchmem\", false, \"show memory stats for benchmarks\")\n\t\tflag.StringVar(&testConfig.Shuffle, \"shuffle\", \"\", \"shuffle the order the tests and benchmarks run\")\n\t}\n\n\t// Early command processing, before commands are interpreted by the Go flag\n\t// library.\n\thandleChdirFlag()\n\tswitch command {\n\tcase \"clang\", \"ld.lld\", \"wasm-ld\":\n\t\terr := builder.RunTool(command, os.Args[2:]...)\n\t\tif err != nil {\n\t\t\t// The tool should have printed an error message already.\n\t\t\t// Don't print another error message here.\n\t\t\tos.Exit(1)\n\t\t}\n\t\tos.Exit(0)\n\t}\n\n\tflag.CommandLine.Parse(os.Args[2:])\n\tglobalVarValues, extLDFlags, err := parseGoLinkFlag(*ldflags)\n\tif err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\tos.Exit(1)\n\t}\n\n\tvar printAllocs *regexp.Regexp\n\tif *printAllocsString != \"\" {\n\t\tprintAllocs, err = regexp.Compile(*printAllocsString)\n\t\tif err != nil {\n\t\t\tfmt.Fprintln(os.Stderr, err)\n\t\t\tos.Exit(1)\n\t\t}\n\t}\n\n\tvar ocdCommands []string\n\tif *ocdCommandsString != \"\" {\n\t\tocdCommands = strings.Split(*ocdCommandsString, \",\")\n\t}\n\n\tval, ok := os.LookupEnv(\"TINYGO_GOCOMPATIBILITY\")\n\tif ok {\n\t\tb, err := strconv.ParseBool(val)\n\t\tif err != nil {\n\t\t\tfmt.Fprintf(os.Stderr, \"could not parse TINYGO_GOCOMPATIBILITY value %q: %v\\n\", val, err)\n\t\t\tos.Exit(1)\n\t\t}\n\t\t*gocompatibility = b\n\t}\n\n\toptions := &compileopts.Options{\n\t\tGOOS:            goenv.Get(\"GOOS\"),\n\t\tGOARCH:          goenv.Get(\"GOARCH\"),\n\t\tGOARM:           goenv.Get(\"GOARM\"),\n\t\tGOMIPS:          goenv.Get(\"GOMIPS\"),\n\t\tTarget:          *target,\n\t\tBuildMode:       *buildMode,\n\t\tStackSize:       stackSize,\n\t\tOpt:             *opt,\n\t\tGC:              *gc,\n\t\tPanicStrategy:   *panicStrategy,\n\t\tScheduler:       *scheduler,\n\t\tSerial:          *serial,\n\t\tWork:            *work,\n\t\tInterpTimeout:   *interpTimeout,\n\t\tPrintIR:         *printIR,\n\t\tDumpSSA:         *dumpSSA,\n\t\tVerifyIR:        *verifyIR,\n\t\tSkipDWARF:       *skipDwarf,\n\t\tSemaphore:       make(chan struct{}, *parallelism),\n\t\tDebug:           !*nodebug,\n\t\tNobounds:        *nobounds,\n\t\tPrintSizes:      *printSize,\n\t\tPrintStacks:     *printStacks,\n\t\tPrintAllocs:     printAllocs,\n\t\tTags:            []string(tags),\n\t\tTestConfig:      testConfig,\n\t\tGlobalValues:    globalVarValues,\n\t\tProgrammer:      *programmer,\n\t\tOpenOCDCommands: ocdCommands,\n\t\tLLVMFeatures:    *llvmFeatures,\n\t\tMonitor:         *monitor,\n\t\tBaudRate:        *baudrate,\n\t\tTimeout:         *timeout,\n\t\tWITPackage:      witPackage,\n\t\tWITWorld:        witWorld,\n\t\tGoCompatibility: *gocompatibility,\n\t}\n\tif *printCommands {\n\t\toptions.PrintCommands = printCommand\n\t}\n\n\tif extLDFlags != \"\" {\n\t\toptions.ExtLDFlags, err = shlex.Split(extLDFlags)\n\t\tif err != nil {\n\t\t\tfmt.Fprintln(os.Stderr, \"could not parse -extldflags:\", err)\n\t\t\tos.Exit(1)\n\t\t}\n\t}\n\n\terr = options.Verify()\n\tif err != nil {\n\t\tfmt.Fprintln(os.Stderr, err.Error())\n\t\tusage(command)\n\t\tos.Exit(1)\n\t}\n\n\tif *cpuprofile != \"\" {\n\t\tf, err := os.Create(*cpuprofile)\n\t\tif err != nil {\n\t\t\tfmt.Fprintln(os.Stderr, \"could not create CPU profile: \", err)\n\t\t\tos.Exit(1)\n\t\t}\n\t\tdefer f.Close()\n\t\tif err := pprof.StartCPUProfile(f); err != nil {\n\t\t\tfmt.Fprintln(os.Stderr, \"could not start CPU profile: \", err)\n\t\t\tos.Exit(1)\n\t\t}\n\t\tdefer pprof.StopCPUProfile()\n\t}\n\n\tswitch command {\n\tcase \"build\":\n\t\tpkgName := \".\"\n\t\tif flag.NArg() == 1 {\n\t\t\tpkgName = filepath.ToSlash(flag.Arg(0))\n\t\t} else if flag.NArg() > 1 {\n\t\t\tfmt.Fprintln(os.Stderr, \"build only accepts a single positional argument: package name, but multiple were specified\")\n\t\t\tusage(command)\n\t\t\tos.Exit(1)\n\t\t}\n\t\tif filepath.Ext(outpath) == \".wasm\" && options.GOARCH != \"wasm\" && options.Target == \"\" {\n\t\t\tfmt.Fprintln(os.Stderr, \"you appear to want to build a wasm file, but have not specified either a target flag, or the GOARCH/GOOS to use.\")\n\t\t\tos.Exit(1)\n\t\t}\n\n\t\tconfig, err := builder.NewConfig(options)\n\t\thandleCompilerError(err)\n\t\terr = Build(pkgName, outpath, config)\n\t\tprintBuildOutput(err, *flagJSON)\n\tcase \"flash\", \"gdb\", \"lldb\":\n\t\tpkgName := filepath.ToSlash(flag.Arg(0))\n\t\tif command == \"flash\" {\n\t\t\terr := Flash(pkgName, *port, outpath, options)\n\t\t\tprintBuildOutput(err, *flagJSON)\n\t\t} else {\n\t\t\tif !options.Debug {\n\t\t\t\tfmt.Fprintln(os.Stderr, \"Debug disabled while running debugger?\")\n\t\t\t\tusage(command)\n\t\t\t\tos.Exit(1)\n\t\t\t}\n\t\t\terr := Debug(command, pkgName, *ocdOutput, options)\n\t\t\tprintBuildOutput(err, *flagJSON)\n\t\t}\n\tcase \"run\":\n\t\tif flag.NArg() < 1 {\n\t\t\tfmt.Fprintln(os.Stderr, \"No package specified.\")\n\t\t\tusage(command)\n\t\t\tos.Exit(1)\n\t\t}\n\t\tpkgName := filepath.ToSlash(flag.Arg(0))\n\t\terr := Run(pkgName, options, flag.Args()[1:])\n\t\tprintBuildOutput(err, *flagJSON)\n\tcase \"test\":\n\t\tvar pkgNames []string\n\t\tfor i := 0; i < flag.NArg(); i++ {\n\t\t\tpkgNames = append(pkgNames, filepath.ToSlash(flag.Arg(i)))\n\t\t}\n\t\tif len(pkgNames) == 0 {\n\t\t\tpkgNames = []string{\".\"}\n\t\t}\n\n\t\texplicitPkgNames, err := getListOfPackages(pkgNames, options)\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"cannot resolve packages: %v\\n\", err)\n\t\t\tos.Exit(1)\n\t\t}\n\n\t\tif outpath != \"\" && len(explicitPkgNames) > 1 {\n\t\t\tfmt.Println(\"cannot use -o flag with multiple packages\")\n\t\t\tos.Exit(1)\n\t\t}\n\n\t\tfail := make(chan struct{}, 1)\n\t\tvar wg sync.WaitGroup\n\t\tbufs := make([]testOutputBuf, len(explicitPkgNames))\n\t\tfor i := range bufs {\n\t\t\tbufs[i].done = make(chan struct{})\n\t\t}\n\n\t\twg.Add(1)\n\t\tgo func() {\n\t\t\tdefer wg.Done()\n\n\t\t\t// Flush the output one test at a time.\n\t\t\t// This ensures that outputs from different tests are not mixed together.\n\t\t\tfor i := range bufs {\n\t\t\t\terr := bufs[i].flush(os.Stdout, os.Stderr)\n\t\t\t\tif err != nil {\n\t\t\t\t\t// There was an error writing to stdout or stderr, so we probably cannot print this.\n\t\t\t\t\tselect {\n\t\t\t\t\tcase fail <- struct{}{}:\n\t\t\t\t\tdefault:\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}()\n\n\t\t// Build and run the tests concurrently.\n\t\t// This uses an additional semaphore to reduce the memory usage.\n\t\ttestSema := make(chan struct{}, cap(options.Semaphore))\n\t\tfor i, pkgName := range explicitPkgNames {\n\t\t\tpkgName := pkgName\n\t\t\tbuf := &bufs[i]\n\t\t\ttestSema <- struct{}{}\n\t\t\twg.Add(1)\n\t\t\tgo func() {\n\t\t\t\tdefer wg.Done()\n\t\t\t\tdefer func() { <-testSema }()\n\t\t\t\tdefer close(buf.done)\n\t\t\t\tstdout := (*testStdout)(buf)\n\t\t\t\tstderr := (*testStderr)(buf)\n\t\t\t\tpassed, err := Test(pkgName, stdout, stderr, options, outpath)\n\t\t\t\tif err != nil {\n\t\t\t\t\twd, getwdErr := os.Getwd()\n\t\t\t\t\tif getwdErr != nil {\n\t\t\t\t\t\twd = \"\"\n\t\t\t\t\t}\n\t\t\t\t\tdiagnostics.CreateDiagnostics(err).WriteTo(os.Stderr, wd)\n\t\t\t\t\tos.Exit(1)\n\t\t\t\t}\n\t\t\t\tif !passed {\n\t\t\t\t\tselect {\n\t\t\t\t\tcase fail <- struct{}{}:\n\t\t\t\t\tdefault:\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}()\n\t\t}\n\n\t\t// Wait for all tests to finish.\n\t\twg.Wait()\n\t\tclose(fail)\n\t\tif _, fail := <-fail; fail {\n\t\t\tos.Exit(1)\n\t\t}\n\tcase \"monitor\":\n\t\tconfig, err := builder.NewConfig(options)\n\t\thandleCompilerError(err)\n\t\terr = Monitor(\"\", *port, config)\n\t\thandleCompilerError(err)\n\tcase \"ports\":\n\t\tserialPortInfo, err := ListSerialPorts()\n\t\thandleCompilerError(err)\n\t\tif len(serialPortInfo) == 0 {\n\t\t\tfmt.Println(\"No serial ports found.\")\n\t\t}\n\t\tfmt.Printf(\"%-20s %-9s %s\\n\", \"Port\", \"ID\", \"Boards\")\n\t\tfor _, s := range serialPortInfo {\n\t\t\tfmt.Printf(\"%-20s %4s:%4s %s\\n\", s.Name, s.VID, s.PID, s.Target)\n\t\t}\n\tcase \"targets\":\n\t\tspecs, err := compileopts.GetTargetSpecs()\n\t\tif err != nil {\n\t\t\tfmt.Fprintln(os.Stderr, \"could not list targets:\", err)\n\t\t\tos.Exit(1)\n\t\t\treturn\n\t\t}\n\t\tnames := []string{}\n\t\tfor key := range specs {\n\t\t\tnames = append(names, key)\n\t\t}\n\t\tsort.Strings(names)\n\t\tfor _, name := range names {\n\t\t\tfmt.Println(name)\n\t\t}\n\tcase \"info\":\n\t\tif flag.NArg() == 1 {\n\t\t\toptions.Target = flag.Arg(0)\n\t\t} else if flag.NArg() > 1 {\n\t\t\tfmt.Fprintln(os.Stderr, \"only one target name is accepted\")\n\t\t\tusage(command)\n\t\t\tos.Exit(1)\n\t\t}\n\t\tconfig, err := builder.NewConfig(options)\n\t\tif err != nil {\n\t\t\tfmt.Fprintln(os.Stderr, err)\n\t\t\tusage(command)\n\t\t\tos.Exit(1)\n\t\t}\n\t\tconfig.GoMinorVersion = 0 // this avoids creating the list of Go1.x build tags.\n\n\t\tcachedGOROOT, err := loader.GetCachedGoroot(config)\n\t\tif err != nil {\n\t\t\tfmt.Fprintln(os.Stderr, err)\n\t\t\tos.Exit(1)\n\t\t}\n\t\tif *flagJSON {\n\t\t\tjson, _ := json.MarshalIndent(struct {\n\t\t\t\tTarget     *compileopts.TargetSpec `json:\"target\"`\n\t\t\t\tGOROOT     string                  `json:\"goroot\"`\n\t\t\t\tGOOS       string                  `json:\"goos\"`\n\t\t\t\tGOARCH     string                  `json:\"goarch\"`\n\t\t\t\tGOARM      string                  `json:\"goarm\"`\n\t\t\t\tGOMIPS     string                  `json:\"gomips\"`\n\t\t\t\tBuildTags  []string                `json:\"build_tags\"`\n\t\t\t\tGC         string                  `json:\"garbage_collector\"`\n\t\t\t\tScheduler  string                  `json:\"scheduler\"`\n\t\t\t\tLLVMTriple string                  `json:\"llvm_triple\"`\n\t\t\t}{\n\t\t\t\tTarget:     config.Target,\n\t\t\t\tGOROOT:     cachedGOROOT,\n\t\t\t\tGOOS:       config.GOOS(),\n\t\t\t\tGOARCH:     config.GOARCH(),\n\t\t\t\tGOARM:      config.GOARM(),\n\t\t\t\tGOMIPS:     config.GOMIPS(),\n\t\t\t\tBuildTags:  config.BuildTags(),\n\t\t\t\tGC:         config.GC(),\n\t\t\t\tScheduler:  config.Scheduler(),\n\t\t\t\tLLVMTriple: config.Triple(),\n\t\t\t}, \"\", \"  \")\n\t\t\tfmt.Println(string(json))\n\t\t} else {\n\t\t\tfmt.Printf(\"LLVM triple:       %s\\n\", config.Triple())\n\t\t\tfmt.Printf(\"GOOS:              %s\\n\", config.GOOS())\n\t\t\tfmt.Printf(\"GOARCH:            %s\\n\", config.GOARCH())\n\t\t\tfmt.Printf(\"build tags:        %s\\n\", strings.Join(config.BuildTags(), \" \"))\n\t\t\tfmt.Printf(\"garbage collector: %s\\n\", config.GC())\n\t\t\tfmt.Printf(\"scheduler:         %s\\n\", config.Scheduler())\n\t\t\tfmt.Printf(\"cached GOROOT:     %s\\n\", cachedGOROOT)\n\t\t}\n\tcase \"list\":\n\t\tconfig, err := builder.NewConfig(options)\n\t\tif err != nil {\n\t\t\tfmt.Fprintln(os.Stderr, err)\n\t\t\tusage(command)\n\t\t\tos.Exit(1)\n\t\t}\n\t\tvar extraArgs []string\n\t\tif *flagJSON {\n\t\t\textraArgs = append(extraArgs, \"-json\")\n\t\t}\n\t\tif flagDeps {\n\t\t\textraArgs = append(extraArgs, \"-deps\")\n\t\t}\n\t\tif flagTest {\n\t\t\textraArgs = append(extraArgs, \"-test\")\n\t\t}\n\t\tcmd, err := loader.List(config, extraArgs, flag.Args())\n\t\tif err != nil {\n\t\t\tfmt.Fprintln(os.Stderr, \"failed to run `go list`:\", err)\n\t\t\tos.Exit(1)\n\t\t}\n\t\tcmd.Stdout = os.Stdout\n\t\tcmd.Stderr = os.Stderr\n\t\terr = cmd.Run()\n\t\tif err != nil {\n\t\t\tif exitErr, ok := err.(*exec.ExitError); ok {\n\t\t\t\tos.Exit(exitErr.ExitCode())\n\t\t\t}\n\t\t\tfmt.Fprintln(os.Stderr, \"failed to run `go list`:\", err)\n\t\t\tos.Exit(1)\n\t\t}\n\tcase \"clean\":\n\t\t// remove cache directory\n\t\terr := os.RemoveAll(goenv.Get(\"GOCACHE\"))\n\t\tif err != nil {\n\t\t\tfmt.Fprintln(os.Stderr, \"cannot clean cache:\", err)\n\t\t\tos.Exit(1)\n\t\t}\n\tcase \"help\":\n\t\tcommand := \"\"\n\t\tif flag.NArg() >= 1 {\n\t\t\tcommand = flag.Arg(0)\n\t\t}\n\t\tusage(command)\n\tcase \"version\":\n\t\tgoversion := \"<unknown>\"\n\t\tif s, err := goenv.GorootVersionString(); err == nil {\n\t\t\tgoversion = s\n\t\t}\n\t\tfmt.Printf(\"tinygo version %s %s/%s (using go version %s and LLVM version %s)\\n\", goenv.Version(), runtime.GOOS, runtime.GOARCH, goversion, llvm.Version)\n\tcase \"env\":\n\t\tif flag.NArg() == 0 {\n\t\t\t// Show all environment variables.\n\t\t\tfor _, key := range goenv.Keys {\n\t\t\t\tfmt.Printf(\"%s=%#v\\n\", key, goenv.Get(key))\n\t\t\t}\n\t\t} else {\n\t\t\t// Show only one (or a few) environment variables.\n\t\t\tfor i := 0; i < flag.NArg(); i++ {\n\t\t\t\tfmt.Println(goenv.Get(flag.Arg(i)))\n\t\t\t}\n\t\t}\n\tdefault:\n\t\tfmt.Fprintln(os.Stderr, \"Unknown command:\", command)\n\t\tusage(\"\")\n\t\tos.Exit(1)\n\t}\n}\n\n// testOutputBuf is used to buffer the output of concurrent tests.\ntype testOutputBuf struct {\n\tmu             sync.Mutex\n\toutput         []outputEntry\n\tstdout, stderr io.Writer\n\touterr, errerr error\n\tdone           chan struct{}\n}\n\n// flush the output to stdout and stderr.\n// This waits until done is closed.\nfunc (b *testOutputBuf) flush(stdout, stderr io.Writer) error {\n\tb.mu.Lock()\n\n\tvar err error\n\tb.stdout = stdout\n\tb.stderr = stderr\n\tfor _, e := range b.output {\n\t\tvar w io.Writer\n\t\tvar errDst *error\n\t\tif e.stderr {\n\t\t\tw = stderr\n\t\t\terrDst = &b.errerr\n\t\t} else {\n\t\t\tw = stdout\n\t\t\terrDst = &b.outerr\n\t\t}\n\t\tif *errDst != nil {\n\t\t\tcontinue\n\t\t}\n\n\t\t_, werr := w.Write(e.data)\n\t\tif werr != nil {\n\t\t\tif err == nil {\n\t\t\t\terr = werr\n\t\t\t}\n\t\t\t*errDst = err\n\t\t}\n\t}\n\n\tb.mu.Unlock()\n\n\t<-b.done\n\n\treturn err\n}\n\n// testStdout writes stdout from a test to the output buffer.\ntype testStdout testOutputBuf\n\nfunc (out *testStdout) Write(data []byte) (int, error) {\n\tbuf := (*testOutputBuf)(out)\n\tbuf.mu.Lock()\n\n\tif buf.stdout != nil {\n\t\t// Write the output directly.\n\t\terr := out.outerr\n\t\tbuf.mu.Unlock()\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t\treturn buf.stdout.Write(data)\n\t}\n\n\tdefer buf.mu.Unlock()\n\n\t// Append the output.\n\tif len(buf.output) == 0 || buf.output[len(buf.output)-1].stderr {\n\t\tbuf.output = append(buf.output, outputEntry{\n\t\t\tstderr: false,\n\t\t})\n\t}\n\tlast := &buf.output[len(buf.output)-1]\n\tlast.data = append(last.data, data...)\n\n\treturn len(data), nil\n}\n\n// testStderr writes stderr from a test to the output buffer.\ntype testStderr testOutputBuf\n\nfunc (out *testStderr) Write(data []byte) (int, error) {\n\tbuf := (*testOutputBuf)(out)\n\tbuf.mu.Lock()\n\n\tif buf.stderr != nil {\n\t\t// Write the output directly.\n\t\terr := out.errerr\n\t\tbuf.mu.Unlock()\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t\treturn buf.stderr.Write(data)\n\t}\n\n\tdefer buf.mu.Unlock()\n\n\t// Append the output.\n\tif len(buf.output) == 0 || !buf.output[len(buf.output)-1].stderr {\n\t\tbuf.output = append(buf.output, outputEntry{\n\t\t\tstderr: true,\n\t\t})\n\t}\n\tlast := &buf.output[len(buf.output)-1]\n\tlast.data = append(last.data, data...)\n\n\treturn len(data), nil\n}\n\ntype outputEntry struct {\n\tstderr bool\n\tdata   []byte\n}\n\n// handleChdirFlag handles the -C flag before doing anything else.\n// The -C flag must be the first flag on the command line, to make it easy to find\n// even with commands that have custom flag parsing.\n// handleChdirFlag handles the flag by chdir'ing to the directory\n// and then removing that flag from the command line entirely.\n//\n// We have to handle the -C flag this way for two reasons:\n//\n//  1. Toolchain selection needs to be in the right directory to look for go.mod and go.work.\n//\n//  2. A toolchain switch later on reinvokes the new go command with the same arguments.\n//     The parent toolchain has already done the chdir; the child must not try to do it again.\n\nfunc handleChdirFlag() {\n\tused := 2 // b.c. command at os.Args[1]\n\tif used >= len(os.Args) {\n\t\treturn\n\t}\n\n\tvar dir string\n\tswitch a := os.Args[used]; {\n\tdefault:\n\t\treturn\n\n\tcase a == \"-C\", a == \"--C\":\n\t\tif used+1 >= len(os.Args) {\n\t\t\treturn\n\t\t}\n\t\tdir = os.Args[used+1]\n\t\tos.Args = slicesDelete(os.Args, used, used+2)\n\n\tcase strings.HasPrefix(a, \"-C=\"), strings.HasPrefix(a, \"--C=\"):\n\t\t_, dir, _ = strings.Cut(a, \"=\")\n\t\tos.Args = slicesDelete(os.Args, used, used+1)\n\t}\n\n\tif err := os.Chdir(dir); err != nil {\n\t\tfmt.Fprintln(os.Stderr, \"cannot chdir:\", err)\n\t\tos.Exit(1)\n\t}\n}\n\n// go1.19 compatibility: lacks slices package\nfunc slicesDelete[S ~[]E, E any](s S, i, j int) S {\n\t_ = s[i:j:len(s)] // bounds check\n\n\tif i == j {\n\t\treturn s\n\t}\n\n\treturn append(s[:i], s[j:]...)\n}\n"
  },
  {
    "path": "main_test.go",
    "content": "package main\n\n// This file tests the compiler by running Go files in testdata/*.go and\n// comparing their output with the expected output in testdata/*.txt.\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"flag\"\n\t\"io\"\n\t\"os\"\n\t\"os/exec\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"runtime\"\n\t\"strings\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/aykevl/go-wasm\"\n\t\"github.com/tetratelabs/wazero\"\n\t\"github.com/tetratelabs/wazero/api\"\n\t\"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1\"\n\t\"github.com/tetratelabs/wazero/sys\"\n\t\"github.com/tinygo-org/tinygo/builder\"\n\t\"github.com/tinygo-org/tinygo/compileopts\"\n\t\"github.com/tinygo-org/tinygo/diagnostics\"\n\t\"github.com/tinygo-org/tinygo/goenv\"\n)\n\nconst TESTDATA = \"testdata\"\n\nvar testTarget = flag.String(\"target\", \"\", \"override test target\")\n\nvar testOnlyCurrentOS = flag.Bool(\"only-current-os\", false, \"\")\n\nvar supportedLinuxArches = map[string]string{\n\t\"AMD64Linux\": \"linux/amd64\",\n\t\"X86Linux\":   \"linux/386\",\n\t\"ARMLinux\":   \"linux/arm/6\",\n\t\"ARM64Linux\": \"linux/arm64\",\n\t\"MIPSLinux\":  \"linux/mips/hardfloat\",\n\t\"WASIp1\":     \"wasip1/wasm\",\n}\n\nfunc init() {\n\tmajor, _, _ := goenv.GetGorootVersion()\n\tif major < 21 {\n\t\t// Go 1.20 backwards compatibility.\n\t\t// Should be removed once we drop support for Go 1.20.\n\t\tdelete(supportedLinuxArches, \"WASIp1\")\n\t}\n}\n\nvar sema = make(chan struct{}, runtime.NumCPU())\n\nfunc TestBuild(t *testing.T) {\n\tt.Parallel()\n\n\ttests := []string{\n\t\t\"alias.go\",\n\t\t\"atomic.go\",\n\t\t\"binop.go\",\n\t\t\"calls.go\",\n\t\t\"cgo/\",\n\t\t\"channel.go\",\n\t\t\"embed/\",\n\t\t\"float.go\",\n\t\t\"gc.go\",\n\t\t\"generics.go\",\n\t\t\"goroutines.go\",\n\t\t\"init.go\",\n\t\t\"init_multi.go\",\n\t\t\"interface.go\",\n\t\t\"json.go\",\n\t\t\"map.go\",\n\t\t\"math.go\",\n\t\t\"oldgo/\",\n\t\t\"print.go\",\n\t\t\"reflect.go\",\n\t\t\"signal.go\",\n\t\t\"slice.go\",\n\t\t\"sort.go\",\n\t\t\"stdlib.go\",\n\t\t\"string.go\",\n\t\t\"structs.go\",\n\t\t\"testing.go\",\n\t\t\"timers.go\",\n\t\t\"zeroalloc.go\",\n\t}\n\n\t// Go 1.21 made some changes to the language, which we can only test when\n\t// we're actually on Go 1.21.\n\t_, minor, err := goenv.GetGorootVersion()\n\tif err != nil {\n\t\tt.Fatal(\"could not get version:\", minor)\n\t}\n\tif minor >= 21 {\n\t\ttests = append(tests, \"go1.21.go\")\n\t}\n\tif minor >= 22 {\n\t\ttests = append(tests, \"go1.22/\")\n\t}\n\tif minor >= 23 {\n\t\ttests = append(tests, \"go1.23/\")\n\t}\n\n\tif *testTarget != \"\" {\n\t\t// This makes it possible to run one specific test (instead of all),\n\t\t// which is especially useful to quickly check whether some changes\n\t\t// affect a particular target architecture.\n\t\trunPlatTests(optionsFromTarget(*testTarget, sema), tests, t)\n\t\treturn\n\t}\n\n\tt.Run(\"Host\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\trunPlatTests(optionsFromTarget(\"\", sema), tests, t)\n\t})\n\n\t// Test a few build options.\n\tt.Run(\"build-options\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\t// Test with few optimizations enabled (no inlining, etc).\n\t\tt.Run(\"opt=1\", func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\topts := optionsFromTarget(\"\", sema)\n\t\t\topts.Opt = \"1\"\n\t\t\trunTestWithConfig(\"stdlib.go\", t, opts, nil, nil)\n\t\t})\n\n\t\t// Test with only the bare minimum of optimizations enabled.\n\t\t// TODO: fix this for stdlib.go, which currently fails.\n\t\tt.Run(\"opt=0\", func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\topts := optionsFromTarget(\"\", sema)\n\t\t\topts.Opt = \"0\"\n\t\t\trunTestWithConfig(\"print.go\", t, opts, nil, nil)\n\t\t})\n\n\t\tt.Run(\"ldflags\", func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\topts := optionsFromTarget(\"\", sema)\n\t\t\topts.GlobalValues = map[string]map[string]string{\n\t\t\t\t\"main\": {\n\t\t\t\t\t\"someGlobal\": \"foobar\",\n\t\t\t\t},\n\t\t\t}\n\t\t\trunTestWithConfig(\"ldflags.go\", t, opts, nil, nil)\n\t\t})\n\t})\n\n\tif testing.Short() {\n\t\t// Don't test other targets when the -short flag is used. Only test the\n\t\t// host system.\n\t\treturn\n\t}\n\n\tif !*testOnlyCurrentOS {\n\t\tt.Run(\"EmulatedCortexM3\", func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\trunPlatTests(optionsFromTarget(\"cortex-m-qemu\", sema), tests, t)\n\t\t})\n\n\t\tt.Run(\"EmulatedRISCV\", func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\trunPlatTests(optionsFromTarget(\"riscv-qemu\", sema), tests, t)\n\t\t})\n\n\t\tt.Run(\"AVR\", func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\trunPlatTests(optionsFromTarget(\"simavr\", sema), tests, t)\n\t\t})\n\n\t\tt.Run(\"WebAssembly\", func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\trunPlatTests(optionsFromTarget(\"wasm\", sema), tests, t)\n\t\t\t// Test with -gc=boehm.\n\t\t\tt.Run(\"gc.go-boehm\", func(t *testing.T) {\n\t\t\t\tt.Parallel()\n\t\t\t\toptionsBoehm := optionsFromTarget(\"wasm\", sema)\n\t\t\t\toptionsBoehm.GC = \"boehm\"\n\t\t\t\trunTest(\"gc.go\", optionsBoehm, t, nil, nil)\n\t\t\t})\n\t\t})\n\t\tt.Run(\"WASIp1\", func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\trunPlatTests(optionsFromTarget(\"wasip1\", sema), tests, t)\n\n\t\t\t// Test with -gc=boehm.\n\t\t\tt.Run(\"gc.go-boehm\", func(t *testing.T) {\n\t\t\t\tt.Parallel()\n\t\t\t\toptionsBoehm := optionsFromTarget(\"wasip1\", sema)\n\t\t\t\toptionsBoehm.GC = \"boehm\"\n\t\t\t\trunTest(\"gc.go\", optionsBoehm, t, nil, nil)\n\t\t\t})\n\t\t})\n\t\tt.Run(\"WASIp2\", func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\trunPlatTests(optionsFromTarget(\"wasip2\", sema), tests, t)\n\t\t})\n\t}\n\n\tif runtime.GOOS == \"linux\" {\n\t\tfor name, osArch := range supportedLinuxArches {\n\t\t\toptions := optionsFromOSARCH(osArch, sema)\n\t\t\tif options.GOARCH != runtime.GOARCH { // Native architecture already run above.\n\t\t\t\tt.Run(name, func(t *testing.T) {\n\t\t\t\t\trunPlatTests(options, tests, t)\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\tt.Run(\"MIPS little-endian\", func(t *testing.T) {\n\t\t\t// Run a single test for GOARCH=mipsle to see whether it works at\n\t\t\t// all. It is already mostly tested because GOARCH=mips and\n\t\t\t// GOARCH=mipsle are so similar, but it's good to have an extra test\n\t\t\t// to be sure.\n\t\t\tt.Parallel()\n\t\t\toptions := optionsFromOSARCH(\"linux/mipsle/softfloat\", sema)\n\t\t\trunTest(\"cgo/\", options, t, nil, nil)\n\t\t})\n\t} else if runtime.GOOS == \"windows\" {\n\t\tif runtime.GOARCH != \"386\" {\n\t\t\tt.Run(\"Windows386\", func(t *testing.T) {\n\t\t\t\tt.Parallel()\n\t\t\t\trunPlatTests(optionsFromOSARCH(\"windows/386\", sema), tests, t)\n\t\t\t})\n\t\t}\n\t}\n}\n\nfunc runPlatTests(options compileopts.Options, tests []string, t *testing.T) {\n\temuCheck(t, options)\n\n\tspec, err := compileopts.LoadTarget(&options)\n\tif err != nil {\n\t\tt.Fatal(\"failed to load target spec:\", err)\n\t}\n\n\t// FIXME: this should really be:\n\t// isWebAssembly := strings.HasPrefix(spec.Triple, \"wasm\")\n\tisWASI := strings.HasPrefix(options.Target, \"wasi\")\n\tisWebAssembly := isWASI || strings.HasPrefix(options.Target, \"wasm\") || (options.Target == \"\" && strings.HasPrefix(options.GOARCH, \"wasm\"))\n\tisBaremetal := options.Target == \"simavr\" || options.Target == \"cortex-m-qemu\" || options.Target == \"riscv-qemu\"\n\n\tfor _, name := range tests {\n\t\tif options.GOOS == \"linux\" && (options.GOARCH == \"arm\" || options.GOARCH == \"386\") {\n\t\t\tswitch name {\n\t\t\tcase \"timers.go\":\n\t\t\t\t// Timer tests do not work because syscall.seek is implemented\n\t\t\t\t// as Assembly in mainline Go and causes linker failure\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tif options.GOOS == \"linux\" && (options.GOARCH == \"mips\" || options.GOARCH == \"mipsle\") {\n\t\t\tif name == \"atomic.go\" || name == \"timers.go\" {\n\t\t\t\t// 64-bit atomic operations aren't currently supported on MIPS.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tif options.GOOS == \"linux\" && options.GOARCH == \"mips\" {\n\t\t\tif name == \"cgo/\" {\n\t\t\t\t// CGo isn't supported yet on big-endian systems (needs updates\n\t\t\t\t// to bitfield access methods).\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tif options.Target == \"simavr\" {\n\t\t\t// Not all tests are currently supported on AVR.\n\t\t\t// Skip the ones that aren't.\n\t\t\tswitch name {\n\t\t\tcase \"reflect.go\":\n\t\t\t\t// Reflect tests do not run correctly, probably because of the\n\t\t\t\t// limited amount of memory.\n\t\t\t\tcontinue\n\n\t\t\tcase \"gc.go\":\n\t\t\t\t// Does not pass due to high mark false positive rate.\n\t\t\t\tcontinue\n\n\t\t\tcase \"json.go\", \"stdlib.go\", \"testing.go\":\n\t\t\t\t// Too big for AVR. Doesn't fit in flash/RAM.\n\t\t\t\tcontinue\n\n\t\t\tcase \"math.go\":\n\t\t\t\t// Needs newer picolibc version (for sqrt).\n\t\t\t\tcontinue\n\n\t\t\tcase \"cgo/\":\n\t\t\t\t// CGo function pointers don't work on AVR (needs LLVM 16 and\n\t\t\t\t// some compiler changes).\n\t\t\t\tcontinue\n\n\t\t\tcase \"timers.go\":\n\t\t\t\t// Crashes starting with Go 1.23.\n\t\t\t\t// Bug: https://github.com/llvm/llvm-project/issues/104032\n\t\t\t\tcontinue\n\n\t\t\tdefault:\n\t\t\t}\n\t\t}\n\t\tif options.Target == \"wasip2\" {\n\t\t\tswitch name {\n\t\t\tcase \"cgo/\":\n\t\t\t\t// waisp2 use our own libc; cgo tests fail\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tif isWebAssembly || isBaremetal || options.GOOS == \"windows\" {\n\t\t\tswitch name {\n\t\t\tcase \"signal.go\":\n\t\t\t\t// Signals only work on POSIX-like systems.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\n\t\tname := name // redefine to avoid race condition\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\trunTest(name, options, t, nil, nil)\n\t\t})\n\t}\n\tif !strings.HasPrefix(spec.Emulator, \"simavr \") {\n\t\tt.Run(\"env.go\", func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\trunTest(\"env.go\", options, t, []string{\"first\", \"second\"}, []string{\"ENV1=VALUE1\", \"ENV2=VALUE2\"})\n\t\t})\n\t}\n\tif isWebAssembly {\n\t\tt.Run(\"alias.go-scheduler-none\", func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\toptions := compileopts.Options(options)\n\t\t\toptions.Scheduler = \"none\"\n\t\t\trunTest(\"alias.go\", options, t, nil, nil)\n\t\t})\n\t}\n\tif options.Target == \"\" || isWASI {\n\t\tt.Run(\"filesystem.go\", func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\trunTest(\"filesystem.go\", options, t, nil, nil)\n\t\t})\n\t}\n\tif options.Target == \"\" || options.Target == \"wasm\" || isWASI {\n\t\tt.Run(\"rand.go\", func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\trunTest(\"rand.go\", options, t, nil, nil)\n\t\t})\n\t}\n\tif !isWebAssembly {\n\t\t// The recover() builtin isn't supported yet on WebAssembly and Windows.\n\t\tt.Run(\"recover.go\", func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\trunTest(\"recover.go\", options, t, nil, nil)\n\t\t})\n\t}\n}\n\nfunc emuCheck(t *testing.T, options compileopts.Options) {\n\t// Check if the emulator is installed.\n\tspec, err := compileopts.LoadTarget(&options)\n\tif err != nil {\n\t\tt.Fatal(\"failed to load target spec:\", err)\n\t}\n\tif spec.Emulator != \"\" {\n\t\temulatorCommand := strings.SplitN(spec.Emulator, \" \", 2)[0]\n\t\t_, err := exec.LookPath(emulatorCommand)\n\t\tif err != nil {\n\t\t\tif errors.Is(err, exec.ErrNotFound) {\n\t\t\t\tt.Skipf(\"emulator not installed: %q\", emulatorCommand)\n\t\t\t}\n\n\t\t\tt.Errorf(\"searching for emulator: %v\", err)\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc optionsFromTarget(target string, sema chan struct{}) compileopts.Options {\n\tseparators := strings.Count(target, \"/\")\n\tif (separators == 1 || separators == 2) && !strings.HasSuffix(target, \".json\") {\n\t\treturn optionsFromOSARCH(target, sema)\n\t}\n\treturn compileopts.Options{\n\t\t// GOOS/GOARCH are only used if target == \"\"\n\t\tGOOS:          goenv.Get(\"GOOS\"),\n\t\tGOARCH:        goenv.Get(\"GOARCH\"),\n\t\tGOARM:         goenv.Get(\"GOARM\"),\n\t\tGOMIPS:        goenv.Get(\"GOMIPS\"),\n\t\tTarget:        target,\n\t\tSemaphore:     sema,\n\t\tInterpTimeout: 180 * time.Second,\n\t\tDebug:         true,\n\t\tVerifyIR:      true,\n\t\tOpt:           \"z\",\n\t}\n}\n\n// optionsFromOSARCH returns a set of options based on the \"osarch\" string. This\n// string is in the form of \"os/arch/subarch\", with the subarch only sometimes\n// being necessary. Examples are \"darwin/amd64\" or \"linux/arm/7\".\nfunc optionsFromOSARCH(osarch string, sema chan struct{}) compileopts.Options {\n\tparts := strings.Split(osarch, \"/\")\n\toptions := compileopts.Options{\n\t\tGOOS:          parts[0],\n\t\tGOARCH:        parts[1],\n\t\tSemaphore:     sema,\n\t\tInterpTimeout: 180 * time.Second,\n\t\tDebug:         true,\n\t\tVerifyIR:      true,\n\t\tOpt:           \"z\",\n\t}\n\tswitch options.GOARCH {\n\tcase \"arm\":\n\t\toptions.GOARM = parts[2]\n\tcase \"mips\", \"mipsle\":\n\t\toptions.GOMIPS = parts[2]\n\t}\n\treturn options\n}\n\nfunc runTest(name string, options compileopts.Options, t *testing.T, cmdArgs, environmentVars []string) {\n\tt.Helper()\n\trunTestWithConfig(name, t, options, cmdArgs, environmentVars)\n}\n\nfunc runTestWithConfig(name string, t *testing.T, options compileopts.Options, cmdArgs, environmentVars []string) {\n\tt.Helper()\n\t// Get the expected output for this test.\n\t// Note: not using filepath.Join as it strips the path separator at the end\n\t// of the path.\n\tpath := TESTDATA + \"/\" + name\n\t// Get the expected output for this test.\n\texpectedOutputPath := path[:len(path)-3] + \".txt\"\n\tpkgName := \"./\" + path\n\tif path[len(path)-1] == '/' {\n\t\texpectedOutputPath = path + \"out.txt\"\n\t\toptions.Directory = path\n\t\tpkgName = \".\"\n\t}\n\n\tconfig, err := builder.NewConfig(&options)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Build the test binary.\n\tstdout := &bytes.Buffer{}\n\t_, err = buildAndRun(pkgName, config, stdout, cmdArgs, environmentVars, time.Minute, func(cmd *exec.Cmd, result builder.BuildResult) error {\n\t\treturn cmd.Run()\n\t})\n\tif err != nil {\n\t\tw := &bytes.Buffer{}\n\t\tdiagnostics.CreateDiagnostics(err).WriteTo(w, \"\")\n\t\tfor _, line := range strings.Split(strings.TrimRight(w.String(), \"\\n\"), \"\\n\") {\n\t\t\tt.Log(line)\n\t\t}\n\t\tif stdout.Len() != 0 {\n\t\t\tt.Logf(\"output:\\n%s\", stdout.String())\n\t\t}\n\t\tt.Fail()\n\t\treturn\n\t}\n\n\tactual := stdout.Bytes()\n\tif config.EmulatorName() == \"simavr\" {\n\t\t// Strip simavr log formatting.\n\t\tactual = bytes.Replace(actual, []byte{0x1b, '[', '3', '2', 'm'}, nil, -1)\n\t\tactual = bytes.Replace(actual, []byte{0x1b, '[', '0', 'm'}, nil, -1)\n\t\tactual = bytes.Replace(actual, []byte{'.', '.', '\\n'}, []byte{'\\n'}, -1)\n\t\tactual = bytes.Replace(actual, []byte{'\\n', '.', '\\n'}, []byte{'\\n', '\\n'}, -1)\n\t}\n\tif name == \"testing.go\" {\n\t\t// Strip actual time.\n\t\tre := regexp.MustCompile(`\\([0-9]\\.[0-9][0-9]s\\)`)\n\t\tactual = re.ReplaceAllLiteral(actual, []byte{'(', '0', '.', '0', '0', 's', ')'})\n\t}\n\n\t// Check whether the command ran successfully.\n\tif err != nil {\n\t\tt.Error(\"failed to run:\", err)\n\t}\n\tcheckOutput(t, expectedOutputPath, actual)\n\n\tif t.Failed() {\n\t\tr := bufio.NewReader(bytes.NewReader(actual))\n\t\tfor {\n\t\t\tline, err := r.ReadString('\\n')\n\t\t\tif err != nil {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tt.Log(\"stdout:\", line[:len(line)-1])\n\t\t}\n\t\tt.Fail()\n\t}\n}\n\n// Test WebAssembly files for certain properties.\nfunc TestWebAssembly(t *testing.T) {\n\tt.Parallel()\n\ttype testCase struct {\n\t\tname          string\n\t\ttarget        string\n\t\tpanicStrategy string\n\t\timports       []string\n\t}\n\tfor _, tc := range []testCase{\n\t\t// Test whether there really are no imports when using -panic=trap. This\n\t\t// tests the bugfix for https://github.com/tinygo-org/tinygo/issues/4161.\n\t\t{name: \"panic-default\", target: \"wasip1\", imports: []string{\"wasi_snapshot_preview1.fd_write\", \"wasi_snapshot_preview1.random_get\"}},\n\t\t{name: \"panic-trap\", target: \"wasm-unknown\", panicStrategy: \"trap\", imports: []string{}},\n\t} {\n\t\ttc := tc\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\ttmpdir := t.TempDir()\n\t\t\toptions := optionsFromTarget(tc.target, sema)\n\t\t\toptions.PanicStrategy = tc.panicStrategy\n\t\t\tconfig, err := builder.NewConfig(&options)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tresult, err := builder.Build(\"testdata/trivialpanic.go\", \".wasm\", tmpdir, config)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(\"failed to build binary:\", err)\n\t\t\t}\n\t\t\tf, err := os.Open(result.Binary)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(\"could not open output binary:\", err)\n\t\t\t}\n\t\t\tdefer f.Close()\n\t\t\tmodule, err := wasm.Parse(f)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(\"could not parse output binary:\", err)\n\t\t\t}\n\n\t\t\t// Test the list of imports.\n\t\t\tif tc.imports != nil {\n\t\t\t\tvar imports []string\n\t\t\t\tfor _, section := range module.Sections {\n\t\t\t\t\tswitch section := section.(type) {\n\t\t\t\t\tcase *wasm.SectionImport:\n\t\t\t\t\t\tfor _, symbol := range section.Entries {\n\t\t\t\t\t\t\timports = append(imports, symbol.Module+\".\"+symbol.Field)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif !stringSlicesEqual(imports, tc.imports) {\n\t\t\t\t\tt.Errorf(\"import list not as expected!\\nexpected: %v\\nactual:   %v\", tc.imports, imports)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc stringSlicesEqual(s1, s2 []string) bool {\n\t// We can use slices.Equal once we drop support for Go 1.20 (it was added in\n\t// Go 1.21).\n\tif len(s1) != len(s2) {\n\t\treturn false\n\t}\n\tfor i, s := range s1 {\n\t\tif s != s2[i] {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\nfunc TestWasmExport(t *testing.T) {\n\tt.Parallel()\n\n\ttype testCase struct {\n\t\tname      string\n\t\ttarget    string\n\t\tbuildMode string\n\t\tscheduler string\n\t\tfile      string\n\t\tnoOutput  bool\n\t\tcommand   bool // call _start (command mode) instead of _initialize\n\t}\n\n\ttests := []testCase{\n\t\t// \"command mode\" WASI\n\t\t{\n\t\t\tname:    \"WASIp1-command\",\n\t\t\ttarget:  \"wasip1\",\n\t\t\tcommand: true,\n\t\t},\n\t\t// \"reactor mode\" WASI (with -buildmode=c-shared)\n\t\t{\n\t\t\tname:      \"WASIp1-reactor\",\n\t\t\ttarget:    \"wasip1\",\n\t\t\tbuildMode: \"c-shared\",\n\t\t},\n\t\t// Make sure reactor mode also works without a scheduler.\n\t\t{\n\t\t\tname:      \"WASIp1-reactor-noscheduler\",\n\t\t\ttarget:    \"wasip1\",\n\t\t\tbuildMode: \"c-shared\",\n\t\t\tscheduler: \"none\",\n\t\t\tfile:      \"wasmexport-noscheduler.go\",\n\t\t},\n\t\t// Test -target=wasm-unknown with the default build mode (which is\n\t\t// c-shared).\n\t\t{\n\t\t\tname:     \"wasm-unknown-reactor\",\n\t\t\ttarget:   \"wasm-unknown\",\n\t\t\tfile:     \"wasmexport-noscheduler.go\",\n\t\t\tnoOutput: true, // wasm-unknown cannot produce output\n\t\t},\n\t\t// Test -target=wasm-unknown with -buildmode=default, which makes it run\n\t\t// in command mode.\n\t\t{\n\t\t\tname:      \"wasm-unknown-command\",\n\t\t\ttarget:    \"wasm-unknown\",\n\t\t\tbuildMode: \"default\",\n\t\t\tfile:      \"wasmexport-noscheduler.go\",\n\t\t\tnoOutput:  true, // wasm-unknown cannot produce output\n\t\t\tcommand:   true,\n\t\t},\n\t\t// Test buildmode=wasi-legacy with WASI.\n\t\t{\n\t\t\tname:      \"WASIp1-legacy\",\n\t\t\ttarget:    \"wasip1\",\n\t\t\tbuildMode: \"wasi-legacy\",\n\t\t\tscheduler: \"none\",\n\t\t\tfile:      \"wasmexport-noscheduler.go\",\n\t\t\tcommand:   true,\n\t\t},\n\t}\n\n\tfor _, tc := range tests {\n\t\ttc := tc\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\t// Build the wasm binary.\n\t\t\ttmpdir := t.TempDir()\n\t\t\toptions := optionsFromTarget(tc.target, sema)\n\t\t\toptions.BuildMode = tc.buildMode\n\t\t\toptions.Scheduler = tc.scheduler\n\t\t\tbuildConfig, err := builder.NewConfig(&options)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tfilename := \"wasmexport.go\"\n\t\t\tif tc.file != \"\" {\n\t\t\t\tfilename = tc.file\n\t\t\t}\n\t\t\tresult, err := builder.Build(\"testdata/\"+filename, \".wasm\", tmpdir, buildConfig)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(\"failed to build binary:\", err)\n\t\t\t}\n\n\t\t\t// Read the wasm binary back into memory.\n\t\t\tdata, err := os.ReadFile(result.Binary)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(\"could not read wasm binary: \", err)\n\t\t\t}\n\n\t\t\t// Set up the wazero runtime.\n\t\t\toutput := &bytes.Buffer{}\n\t\t\tctx := context.Background()\n\t\t\tr := wazero.NewRuntimeWithConfig(ctx, wazero.NewRuntimeConfigInterpreter())\n\t\t\tdefer r.Close(ctx)\n\t\t\tconfig := wazero.NewModuleConfig().\n\t\t\t\tWithStdout(output).WithStderr(output).\n\t\t\t\tWithStartFunctions()\n\n\t\t\t// Prepare for testing.\n\t\t\tvar mod api.Module\n\t\t\tmustCall := func(results []uint64, err error) []uint64 {\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Error(\"failed to run function:\", err)\n\t\t\t\t}\n\t\t\t\treturn results\n\t\t\t}\n\t\t\tcheckResult := func(name string, results []uint64, expected []uint64) {\n\t\t\t\tif len(results) != len(expected) {\n\t\t\t\t\tt.Errorf(\"%s: expected %v but got %v\", name, expected, results)\n\t\t\t\t}\n\t\t\t\tfor i, result := range results {\n\t\t\t\t\tif result != expected[i] {\n\t\t\t\t\t\tt.Errorf(\"%s: expected %v but got %v\", name, expected, results)\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\trunTests := func() {\n\t\t\t\t// Test an exported function without params or return value.\n\t\t\t\tcheckResult(\"hello()\", mustCall(mod.ExportedFunction(\"hello\").Call(ctx)), nil)\n\n\t\t\t\t// Test that we can call an exported function more than once.\n\t\t\t\tcheckResult(\"add(3, 5)\", mustCall(mod.ExportedFunction(\"add\").Call(ctx, 3, 5)), []uint64{8})\n\t\t\t\tcheckResult(\"add(7, 9)\", mustCall(mod.ExportedFunction(\"add\").Call(ctx, 7, 9)), []uint64{16})\n\t\t\t\tcheckResult(\"add(6, 1)\", mustCall(mod.ExportedFunction(\"add\").Call(ctx, 6, 1)), []uint64{7})\n\n\t\t\t\t// Test that imported functions can call exported functions\n\t\t\t\t// again.\n\t\t\t\tcheckResult(\"reentrantCall(2, 3)\", mustCall(mod.ExportedFunction(\"reentrantCall\").Call(ctx, 2, 3)), []uint64{5})\n\t\t\t\tcheckResult(\"reentrantCall(1, 8)\", mustCall(mod.ExportedFunction(\"reentrantCall\").Call(ctx, 1, 8)), []uint64{9})\n\n\t\t\t\t// Check that goroutines started inside //go:wasmexport don't\n\t\t\t\t// block the called function from returning.\n\t\t\t\tcheckResult(\"goroutineExit()\", mustCall(mod.ExportedFunction(\"goroutineExit\").Call(ctx)), nil)\n\t\t\t}\n\n\t\t\t// Add wasip1 module.\n\t\t\twasi_snapshot_preview1.MustInstantiate(ctx, r)\n\n\t\t\t// Add custom \"tester\" module.\n\t\t\tcallOutside := func(a, b int32) int32 {\n\t\t\t\tresults, err := mod.ExportedFunction(\"add\").Call(ctx, uint64(a), uint64(b))\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Error(\"could not call exported add function:\", err)\n\t\t\t\t}\n\t\t\t\treturn int32(results[0])\n\t\t\t}\n\t\t\tcallTestMain := func() {\n\t\t\t\trunTests()\n\t\t\t}\n\t\t\tbuilder := r.NewHostModuleBuilder(\"tester\")\n\t\t\tbuilder.NewFunctionBuilder().WithFunc(callOutside).Export(\"callOutside\")\n\t\t\tbuilder.NewFunctionBuilder().WithFunc(callTestMain).Export(\"callTestMain\")\n\t\t\t_, err = builder.Instantiate(ctx)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\t// Parse and instantiate the wasm.\n\t\t\tmod, err = r.InstantiateWithConfig(ctx, data, config)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(\"could not instantiate wasm module:\", err)\n\t\t\t}\n\n\t\t\t// Initialize the module and run the tests.\n\t\t\tif tc.command {\n\t\t\t\t// Call _start (the entry point), which calls\n\t\t\t\t// tester.callTestMain, which then runs all the tests.\n\t\t\t\t_, err := mod.ExportedFunction(\"_start\").Call(ctx)\n\t\t\t\tif err != nil {\n\t\t\t\t\tif exitErr, ok := err.(*sys.ExitError); ok && exitErr.ExitCode() == 0 {\n\t\t\t\t\t\t// Exited with code 0. Nothing to worry about.\n\t\t\t\t\t} else {\n\t\t\t\t\t\tt.Error(\"failed to run _start:\", err)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Run the _initialize call, because this is reactor mode wasm.\n\t\t\t\tmustCall(mod.ExportedFunction(\"_initialize\").Call(ctx))\n\t\t\t\trunTests()\n\t\t\t}\n\n\t\t\t// Check that the output matches the expected output.\n\t\t\t// (Skip this for wasm-unknown because it can't produce output).\n\t\t\tif !tc.noOutput {\n\t\t\t\tcheckOutput(t, \"testdata/wasmexport.txt\", output.Bytes())\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test js.FuncOf (for syscall/js).\n// This test might be extended in the future to cover more cases in syscall/js.\nfunc TestWasmFuncOf(t *testing.T) {\n\t// Build the wasm binary.\n\ttmpdir := t.TempDir()\n\toptions := optionsFromTarget(\"wasm\", sema)\n\tbuildConfig, err := builder.NewConfig(&options)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tresult, err := builder.Build(\"testdata/wasmfunc.go\", \".wasm\", tmpdir, buildConfig)\n\tif err != nil {\n\t\tt.Fatal(\"failed to build binary:\", err)\n\t}\n\n\t// Test the resulting binary using NodeJS.\n\toutput := &bytes.Buffer{}\n\tcmd := exec.Command(\"node\", \"testdata/wasmfunc.js\", result.Binary, buildConfig.BuildMode())\n\tcmd.Stdout = output\n\tcmd.Stderr = output\n\terr = cmd.Run()\n\tif err != nil {\n\t\tt.Error(\"failed to run node:\", err)\n\t}\n\tcheckOutput(t, \"testdata/wasmfunc.txt\", output.Bytes())\n}\n\n// Test //go:wasmexport in JavaScript (using NodeJS).\nfunc TestWasmExportJS(t *testing.T) {\n\tt.Parallel()\n\ttype testCase struct {\n\t\tname      string\n\t\tbuildMode string\n\t}\n\n\ttests := []testCase{\n\t\t{name: \"default\"},\n\t\t{name: \"c-shared\", buildMode: \"c-shared\"},\n\t}\n\tfor _, tc := range tests {\n\t\ttc := tc\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\t// Build the wasm binary.\n\t\t\ttmpdir := t.TempDir()\n\t\t\toptions := optionsFromTarget(\"wasm\", sema)\n\t\t\toptions.BuildMode = tc.buildMode\n\t\t\tbuildConfig, err := builder.NewConfig(&options)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tresult, err := builder.Build(\"testdata/wasmexport-noscheduler.go\", \".wasm\", tmpdir, buildConfig)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(\"failed to build binary:\", err)\n\t\t\t}\n\n\t\t\t// Test the resulting binary using NodeJS.\n\t\t\toutput := &bytes.Buffer{}\n\t\t\tcmd := exec.Command(\"node\", \"testdata/wasmexport.js\", result.Binary, buildConfig.BuildMode())\n\t\t\tcmd.Stdout = output\n\t\t\tcmd.Stderr = output\n\t\t\terr = cmd.Run()\n\t\t\tif err != nil {\n\t\t\t\tt.Error(\"failed to run node:\", err)\n\t\t\t}\n\t\t\tcheckOutput(t, \"testdata/wasmexport.txt\", output.Bytes())\n\t\t})\n\t}\n}\n\n// Test whether Go.run() (in wasm_exec.js) normally returns and returns the\n// right exit code.\nfunc TestWasmExit(t *testing.T) {\n\tt.Parallel()\n\n\ttype testCase struct {\n\t\tname   string\n\t\toutput string\n\t}\n\n\ttests := []testCase{\n\t\t{name: \"normal\", output: \"exit code: 0\\n\"},\n\t\t{name: \"exit-0\", output: \"exit code: 0\\n\"},\n\t\t{name: \"exit-0-sleep\", output: \"slept\\nexit code: 0\\n\"},\n\t\t{name: \"exit-1\", output: \"exit code: 1\\n\"},\n\t\t{name: \"exit-1-sleep\", output: \"slept\\nexit code: 1\\n\"},\n\t}\n\tfor _, tc := range tests {\n\t\ttc := tc\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\toptions := optionsFromTarget(\"wasm\", sema)\n\t\t\tbuildConfig, err := builder.NewConfig(&options)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tbuildConfig.Target.Emulator = \"node testdata/wasmexit.js {}\"\n\t\t\toutput := &bytes.Buffer{}\n\t\t\t_, err = buildAndRun(\"testdata/wasmexit.go\", buildConfig, output, []string{tc.name}, nil, time.Minute, func(cmd *exec.Cmd, result builder.BuildResult) error {\n\t\t\t\treturn cmd.Run()\n\t\t\t})\n\t\t\tif err != nil {\n\t\t\t\tt.Error(err)\n\t\t\t}\n\t\t\texpected := \"wasmexit test: \" + tc.name + \"\\n\" + tc.output\n\t\t\tcheckOutputData(t, []byte(expected), output.Bytes())\n\t\t})\n\t}\n}\n\n// Check whether the output of a test equals the expected output.\nfunc checkOutput(t *testing.T, filename string, actual []byte) {\n\tt.Helper()\n\texpectedOutput, err := os.ReadFile(filename)\n\tif err != nil {\n\t\tt.Fatal(\"could not read output file:\", err)\n\t}\n\tcheckOutputData(t, expectedOutput, actual)\n}\n\nfunc checkOutputData(t *testing.T, expectedOutput, actual []byte) {\n\tt.Helper()\n\texpectedOutput = bytes.ReplaceAll(expectedOutput, []byte(\"\\r\\n\"), []byte(\"\\n\"))\n\tactual = bytes.ReplaceAll(actual, []byte(\"\\r\\n\"), []byte(\"\\n\"))\n\n\tif !bytes.Equal(actual, expectedOutput) {\n\t\tt.Errorf(\"output did not match (expected %d bytes, got %d bytes):\", len(expectedOutput), len(actual))\n\t\tt.Error(string(Diff(\"expected\", expectedOutput, \"actual\", actual)))\n\t}\n}\n\nfunc TestTest(t *testing.T) {\n\tt.Parallel()\n\n\ttype targ struct {\n\t\tname string\n\t\topts compileopts.Options\n\t}\n\ttargs := []targ{\n\t\t// Host\n\t\t{\"Host\", optionsFromTarget(\"\", sema)},\n\t}\n\tif !testing.Short() {\n\t\tif runtime.GOOS == \"linux\" {\n\t\t\tfor name, osArch := range supportedLinuxArches {\n\t\t\t\toptions := optionsFromOSARCH(osArch, sema)\n\t\t\t\tif options.GOARCH != runtime.GOARCH { // Native architecture already run above.\n\t\t\t\t\ttargs = append(targs, targ{name, options})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ttargs = append(targs,\n\t\t\t// QEMU microcontrollers\n\t\t\ttarg{\"EmulatedCortexM3\", optionsFromTarget(\"cortex-m-qemu\", sema)},\n\t\t\ttarg{\"EmulatedRISCV\", optionsFromTarget(\"riscv-qemu\", sema)},\n\n\t\t\t// Node/Wasmtime\n\t\t\ttarg{\"WASM\", optionsFromTarget(\"wasm\", sema)},\n\t\t\ttarg{\"WASI\", optionsFromTarget(\"wasip1\", sema)},\n\t\t)\n\t}\n\tfor _, targ := range targs {\n\t\ttarg := targ\n\t\tt.Run(targ.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\temuCheck(t, targ.opts)\n\n\t\t\tt.Run(\"Pass\", func(t *testing.T) {\n\t\t\t\tt.Parallel()\n\n\t\t\t\t// Test a package which builds and passes normally.\n\n\t\t\t\tvar wg sync.WaitGroup\n\t\t\t\tdefer wg.Wait()\n\n\t\t\t\tout := ioLogger(t, &wg)\n\t\t\t\tdefer out.Close()\n\n\t\t\t\topts := targ.opts\n\t\t\t\tpassed, err := Test(\"github.com/tinygo-org/tinygo/tests/testing/pass\", out, out, &opts, \"\")\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Errorf(\"test error: %v\", err)\n\t\t\t\t}\n\t\t\t\tif !passed {\n\t\t\t\t\tt.Error(\"test failed\")\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tt.Run(\"Fail\", func(t *testing.T) {\n\t\t\t\tt.Parallel()\n\n\t\t\t\t// Test a package which builds fine but fails.\n\n\t\t\t\tvar wg sync.WaitGroup\n\t\t\t\tdefer wg.Wait()\n\n\t\t\t\tout := ioLogger(t, &wg)\n\t\t\t\tdefer out.Close()\n\n\t\t\t\topts := targ.opts\n\t\t\t\tpassed, err := Test(\"github.com/tinygo-org/tinygo/tests/testing/fail\", out, out, &opts, \"\")\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Errorf(\"test error: %v\", err)\n\t\t\t\t}\n\t\t\t\tif passed {\n\t\t\t\t\tt.Error(\"test passed\")\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tif targ.name != \"Host\" {\n\t\t\t\t// Emulated tests are somewhat slow, and these do not need to be run across every platform.\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tt.Run(\"Nothing\", func(t *testing.T) {\n\t\t\t\tt.Parallel()\n\n\t\t\t\t// Test a package with no test files.\n\n\t\t\t\tvar wg sync.WaitGroup\n\t\t\t\tdefer wg.Wait()\n\n\t\t\t\tout := ioLogger(t, &wg)\n\t\t\t\tdefer out.Close()\n\n\t\t\t\tvar output bytes.Buffer\n\t\t\t\topts := targ.opts\n\t\t\t\tpassed, err := Test(\"github.com/tinygo-org/tinygo/tests/testing/nothing\", io.MultiWriter(&output, out), out, &opts, \"\")\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Errorf(\"test error: %v\", err)\n\t\t\t\t}\n\t\t\t\tif !passed {\n\t\t\t\t\tt.Error(\"test failed\")\n\t\t\t\t}\n\t\t\t\tif !strings.Contains(output.String(), \"[no test files]\") {\n\t\t\t\t\tt.Error(\"missing [no test files] in output\")\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tt.Run(\"BuildErr\", func(t *testing.T) {\n\t\t\t\tt.Parallel()\n\n\t\t\t\t// Test a package which fails to build.\n\n\t\t\t\tvar wg sync.WaitGroup\n\t\t\t\tdefer wg.Wait()\n\n\t\t\t\tout := ioLogger(t, &wg)\n\t\t\t\tdefer out.Close()\n\n\t\t\t\topts := targ.opts\n\t\t\t\tpassed, err := Test(\"github.com/tinygo-org/tinygo/tests/testing/builderr\", out, out, &opts, \"\")\n\t\t\t\tif err == nil {\n\t\t\t\t\tt.Error(\"test did not error\")\n\t\t\t\t}\n\t\t\t\tif passed {\n\t\t\t\t\tt.Error(\"test passed\")\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\nfunc ioLogger(t *testing.T, wg *sync.WaitGroup) io.WriteCloser {\n\tr, w := io.Pipe()\n\twg.Add(1)\n\tgo func() {\n\t\tdefer wg.Done()\n\t\tdefer r.Close()\n\n\t\tscanner := bufio.NewScanner(r)\n\t\tfor scanner.Scan() {\n\t\t\tt.Log(scanner.Text())\n\t\t}\n\t}()\n\n\treturn w\n}\n\nfunc TestGetListOfPackages(t *testing.T) {\n\topts := optionsFromTarget(\"\", sema)\n\ttests := []struct {\n\t\tpkgs          []string\n\t\texpectedPkgs  []string\n\t\texpectesError bool\n\t}{\n\t\t{\n\t\t\tpkgs: []string{\"./tests/testing/recurse/...\"},\n\t\t\texpectedPkgs: []string{\n\t\t\t\t\"github.com/tinygo-org/tinygo/tests/testing/recurse\",\n\t\t\t\t\"github.com/tinygo-org/tinygo/tests/testing/recurse/subdir\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tpkgs: []string{\"./tests/testing/pass\"},\n\t\t\texpectedPkgs: []string{\n\t\t\t\t\"github.com/tinygo-org/tinygo/tests/testing/pass\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tpkgs:          []string{\"./tests/testing\"},\n\t\t\texpectesError: true,\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tactualPkgs, err := getListOfPackages(test.pkgs, &opts)\n\t\tif err != nil && !test.expectesError {\n\t\t\tt.Errorf(\"unexpected error: %v\", err)\n\t\t} else if err == nil && test.expectesError {\n\t\t\tt.Error(\"expected error, but got none\")\n\t\t}\n\n\t\tif !reflect.DeepEqual(test.expectedPkgs, actualPkgs) {\n\t\t\tt.Errorf(\"expected two slices to be equal, expected %v got %v\", test.expectedPkgs, actualPkgs)\n\t\t}\n\t}\n}\n\n// This TestMain is necessary because TinyGo may also be invoked to run certain\n// LLVM tools in a separate process. Not capturing these invocations would lead\n// to recursive tests.\nfunc TestMain(m *testing.M) {\n\tif len(os.Args) >= 2 {\n\t\tswitch os.Args[1] {\n\t\tcase \"clang\", \"ld.lld\", \"wasm-ld\":\n\t\t\t// Invoke a specific tool.\n\t\t\terr := builder.RunTool(os.Args[1], os.Args[2:]...)\n\t\t\tif err != nil {\n\t\t\t\t// The tool should have printed an error message already.\n\t\t\t\t// Don't print another error message here.\n\t\t\t\tos.Exit(1)\n\t\t\t}\n\t\t\tos.Exit(0)\n\t\t}\n\t}\n\n\t// Run normal tests.\n\tos.Exit(m.Run())\n}\n"
  },
  {
    "path": "misspell.csv",
    "content": "acces,access\nacuire,acquire\naddess,address\nadust,adjust\nallcoate,allocate\nalloated,allocated\narchtecture,architecture\narcive,archive\nardiuno,arduino\nbeconfigured,be configured\ncalcluate,calculate\ncolum,column\nconfigration,configuration\ncontants,constants\ncricital,critical\ndeffered,deferred\nevaulator,evaluator\nevironment,environment\nfreqency,frequency\nfrquency,frequency\nimplmented,implemented\ninterrput,interrupt\ninterrut,interrupt\ninterupt,interrupt\nmeasuing,measuring\nnumer of,number of\norignal,original\noverrided,overridden\npoiners,pointers\npoitner,pointer\nprobbably,probably\nrecogized,recognized\nrefection,reflection\nrequries,requires\nsatisifying,satisfying\nsimulataneously,simultaneously\nsuggets,suggests\ntransmition,transmission\nundefied,undefined\nunecessary,unnecessary\nunsiged,unsigned\n"
  },
  {
    "path": "monitor.go",
    "content": "package main\n\nimport (\n\t\"bufio\"\n\t\"debug/dwarf\"\n\t\"debug/elf\"\n\t\"debug/macho\"\n\t\"debug/pe\"\n\t\"errors\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"io\"\n\t\"net\"\n\t\"os\"\n\t\"os/signal\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/mattn/go-tty\"\n\t\"github.com/tinygo-org/tinygo/compileopts\"\n\n\t\"go.bug.st/serial\"\n\t\"go.bug.st/serial/enumerator\"\n)\n\n// Monitor connects to the given port and reads/writes the serial port.\nfunc Monitor(executable, port string, config *compileopts.Config) error {\n\tconst timeout = time.Second * 3\n\tvar exit func() // function to be called before exiting\n\tvar serialConn io.ReadWriter\n\n\tif config.Options.Serial == \"rtt\" {\n\t\t// Use the RTT interface, which is documented (in part) here:\n\t\t// https://wiki.segger.com/RTT\n\n\t\t// Try to find the \"_SEGGER_RTT\" symbol (machine.rttSerialInstance)\n\t\t// symbol, which is the RTT control block.\n\t\tfile, err := elf.Open(executable)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"could not open ELF file to determine RTT control block: %w\", err)\n\t\t}\n\t\tdefer file.Close()\n\t\tsymbols, err := file.Symbols()\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"could not read ELF symbol table to determine RTT control block: %w\", err)\n\t\t}\n\t\tvar address uint64\n\t\tfor _, symbol := range symbols {\n\t\t\tif symbol.Name == \"_SEGGER_RTT\" {\n\t\t\t\taddress = symbol.Value\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif address == 0 {\n\t\t\treturn fmt.Errorf(\"could not find RTT control block in ELF file\")\n\t\t}\n\n\t\t// Start an openocd process in the background.\n\t\targs, err := config.OpenOCDConfiguration()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\targs = append(args,\n\t\t\t\"-c\", fmt.Sprintf(\"rtt setup 0x%x 16 \\\"SEGGER RTT\\\"\", address),\n\t\t\t\"-c\", \"init\",\n\t\t\t\"-c\", \"rtt server start 0 0\")\n\t\tcmd := executeCommand(config.Options, \"openocd\", args...)\n\t\tstderr, err := cmd.StderrPipe()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tcmd.Stdout = os.Stdout\n\t\terr = cmd.Start()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdefer cmd.Process.Kill()\n\t\texit = func() {\n\t\t\t// Make sure the openocd process is terminated at exit.\n\t\t\t// This does not happen through the defer above when exiting through\n\t\t\t// os.Exit.\n\t\t\tcmd.Process.Kill()\n\t\t}\n\n\t\t// Read the stderr, which logs various important messages we need.\n\t\tr := bufio.NewReader(stderr)\n\t\tvar telnet net.Conn\n\t\tvar timeoutAt time.Time\n\t\tfor {\n\t\t\t// Read the next line from the openocd process.\n\t\t\tlineBytes, err := r.ReadBytes('\\n')\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tline := string(lineBytes)\n\n\t\t\tif line == \"Info : rtt: No control block found\\n\" {\n\t\t\t\t// Message that is sent back when OpenOCD can't find the control\n\t\t\t\t// block after a 'rtt start' message.\n\t\t\t\tif time.Now().After(timeoutAt) {\n\t\t\t\t\treturn fmt.Errorf(\"RTT timeout (could not locate RTT control block at 0x%08x)\", address)\n\t\t\t\t}\n\t\t\t\ttime.Sleep(time.Millisecond * 100)\n\t\t\t\ttelnet.Write([]byte(\"rtt start\\r\\n\"))\n\t\t\t} else if strings.HasPrefix(line, \"Info : Listening on port\") {\n\t\t\t\t// We need two different ports for controlling OpenOCD\n\t\t\t\t// (typically port 4444) and the RTT channel 0 socket (arbitrary\n\t\t\t\t// port).\n\t\t\t\tvar port int\n\t\t\t\tvar protocol string\n\t\t\t\tfmt.Sscanf(line, \"Info : Listening on port %d for %s connections\\n\", &port, &protocol)\n\t\t\t\tif protocol == \"telnet\" && telnet == nil {\n\t\t\t\t\t// Connect to the \"telnet\" command line interface.\n\t\t\t\t\ttelnet, err = net.Dial(\"tcp4\", fmt.Sprintf(\"localhost:%d\", port))\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t\t// Tell OpenOCD to start scanning for the RTT control block.\n\t\t\t\t\ttelnet.Write([]byte(\"rtt start\\r\\n\"))\n\t\t\t\t\t// Also make sure we will time out if the control block just\n\t\t\t\t\t// can't be found.\n\t\t\t\t\ttimeoutAt = time.Now().Add(timeout)\n\t\t\t\t} else if protocol == \"rtt\" {\n\t\t\t\t\t// Connect to the RTT channel, for both stdin and stdout.\n\t\t\t\t\tconn, err := net.Dial(\"tcp4\", fmt.Sprintf(\"localhost:%d\", port))\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t\tserialConn = conn\n\t\t\t\t}\n\t\t\t} else if strings.HasPrefix(line, \"Info : rtt: Control block found at\") {\n\t\t\t\t// Connection established!\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t} else { // -serial=uart or -serial=usb\n\t\tvar err error\n\t\twait := 300\n\t\tfor i := 0; i <= wait; i++ {\n\t\t\tport, err = getDefaultPort(port, config.Target.SerialPort)\n\t\t\tif err != nil {\n\t\t\t\tif i < wait {\n\t\t\t\t\ttime.Sleep(10 * time.Millisecond)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\n\t\tbr := config.Options.BaudRate\n\t\tif br <= 0 {\n\t\t\tbr = 115200\n\t\t}\n\n\t\twait = 300\n\t\tvar p serial.Port\n\t\tfor i := 0; i <= wait; i++ {\n\t\t\tp, err = serial.Open(port, &serial.Mode{BaudRate: br})\n\t\t\tif err != nil {\n\t\t\t\tif i < wait {\n\t\t\t\t\ttime.Sleep(10 * time.Millisecond)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tserialConn = p\n\t\t\tbreak\n\t\t}\n\t\tdefer p.Close()\n\t}\n\n\ttty, err := tty.Open()\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer tty.Close()\n\n\tsig := make(chan os.Signal, 1)\n\tsignal.Notify(sig, os.Interrupt)\n\tdefer signal.Stop(sig)\n\n\tgo func() {\n\t\t<-sig\n\t\ttty.Close()\n\t\tif exit != nil {\n\t\t\texit()\n\t\t}\n\t\tos.Exit(0)\n\t}()\n\n\tfmt.Printf(\"Connected to %s. Press Ctrl-C to exit.\\n\", port)\n\n\terrCh := make(chan error, 1)\n\n\tgo func() {\n\t\tbuf := make([]byte, 100*1024)\n\t\twriter := newOutputWriter(os.Stdout, executable)\n\t\tfor {\n\t\t\tn, err := serialConn.Read(buf)\n\t\t\tif err != nil {\n\t\t\t\terrCh <- fmt.Errorf(\"read error: %w\", err)\n\t\t\t\treturn\n\t\t\t}\n\t\t\twriter.Write(buf[:n])\n\t\t}\n\t}()\n\n\tgo func() {\n\t\tfor {\n\t\t\tr, err := tty.ReadRune()\n\t\t\tif err != nil {\n\t\t\t\terrCh <- err\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif r == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tserialConn.Write([]byte(string(r)))\n\t\t}\n\t}()\n\n\treturn <-errCh\n}\n\n// SerialPortInfo is a structure that holds information about the port and its\n// associated TargetSpec.\ntype SerialPortInfo struct {\n\tName   string\n\tIsUSB  bool\n\tVID    string\n\tPID    string\n\tTarget string\n\tSpec   *compileopts.TargetSpec\n}\n\n// ListSerialPort returns serial port information and any detected TinyGo\n// target.\nfunc ListSerialPorts() ([]SerialPortInfo, error) {\n\tmaps, err := compileopts.GetTargetSpecs()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tportsList, err := enumerator.GetDetailedPortsList()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tserialPortInfo := []SerialPortInfo{}\n\tfor _, p := range portsList {\n\t\tinfo := SerialPortInfo{\n\t\t\tName:  p.Name,\n\t\t\tIsUSB: p.IsUSB,\n\t\t\tVID:   p.VID,\n\t\t\tPID:   p.PID,\n\t\t}\n\t\tvid := strings.ToLower(p.VID)\n\t\tpid := strings.ToLower(p.PID)\n\t\tfor k, v := range maps {\n\t\t\tusbInterfaces := v.SerialPort\n\t\t\tfor _, s := range usbInterfaces {\n\t\t\t\tparts := strings.Split(s, \":\")\n\t\t\t\tif len(parts) != 2 {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif vid == strings.ToLower(parts[0]) && pid == strings.ToLower(parts[1]) {\n\t\t\t\t\tinfo.Target = k\n\t\t\t\t\tinfo.Spec = v\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tserialPortInfo = append(serialPortInfo, info)\n\t}\n\n\treturn serialPortInfo, nil\n}\n\nvar addressMatch = regexp.MustCompile(`^panic: runtime error at 0x([0-9a-f]+): `)\n\n// Extract the address from the \"panic: runtime error at\" message.\nfunc extractPanicAddress(line []byte) uint64 {\n\tmatches := addressMatch.FindSubmatch(line)\n\tif matches != nil {\n\t\taddress, err := strconv.ParseUint(string(matches[1]), 16, 64)\n\t\tif err == nil {\n\t\t\treturn address\n\t\t}\n\t}\n\treturn 0\n}\n\n// Convert an address in the binary to a source address location.\nfunc addressToLine(executable string, address uint64) (token.Position, error) {\n\tdata, err := readDWARF(executable)\n\tif err != nil {\n\t\treturn token.Position{}, err\n\t}\n\tr := data.Reader()\n\n\tfor {\n\t\te, err := r.Next()\n\t\tif err != nil {\n\t\t\treturn token.Position{}, err\n\t\t}\n\t\tif e == nil {\n\t\t\tbreak\n\t\t}\n\t\tswitch e.Tag {\n\t\tcase dwarf.TagCompileUnit:\n\t\t\tr.SkipChildren()\n\t\t\tlr, err := data.LineReader(e)\n\t\t\tif err != nil {\n\t\t\t\treturn token.Position{}, err\n\t\t\t}\n\t\t\tvar lineEntry = dwarf.LineEntry{\n\t\t\t\tEndSequence: true,\n\t\t\t}\n\t\t\tfor {\n\t\t\t\t// Read the next .debug_line entry.\n\t\t\t\tprevLineEntry := lineEntry\n\t\t\t\terr := lr.Next(&lineEntry)\n\t\t\t\tif err != nil {\n\t\t\t\t\tif err == io.EOF {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\treturn token.Position{}, err\n\t\t\t\t}\n\n\t\t\t\tif prevLineEntry.EndSequence && lineEntry.Address == 0 {\n\t\t\t\t\t// Tombstone value. This symbol has been removed, for\n\t\t\t\t\t// example by the --gc-sections linker flag. It is still\n\t\t\t\t\t// here in the debug information because the linker can't\n\t\t\t\t\t// just remove this reference.\n\t\t\t\t\t// Read until the next EndSequence so that this sequence is\n\t\t\t\t\t// skipped.\n\t\t\t\t\t// For more details, see (among others):\n\t\t\t\t\t// https://reviews.llvm.org/D84825\n\t\t\t\t\tfor {\n\t\t\t\t\t\terr := lr.Next(&lineEntry)\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn token.Position{}, err\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif lineEntry.EndSequence {\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif !prevLineEntry.EndSequence {\n\t\t\t\t\t// The chunk describes the code from prevLineEntry to\n\t\t\t\t\t// lineEntry.\n\t\t\t\t\tif prevLineEntry.Address <= address && lineEntry.Address > address {\n\t\t\t\t\t\treturn token.Position{\n\t\t\t\t\t\t\tFilename: prevLineEntry.File.Name,\n\t\t\t\t\t\t\tLine:     prevLineEntry.Line,\n\t\t\t\t\t\t\tColumn:   prevLineEntry.Column,\n\t\t\t\t\t\t}, nil\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn token.Position{}, nil // location not found\n}\n\n// Read the DWARF debug information from a given file (in various formats).\nfunc readDWARF(executable string) (*dwarf.Data, error) {\n\tf, err := os.Open(executable)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif file, err := elf.NewFile(f); err == nil {\n\t\treturn file.DWARF()\n\t} else if file, err := macho.NewFile(f); err == nil {\n\t\treturn file.DWARF()\n\t} else if file, err := pe.NewFile(f); err == nil {\n\t\treturn file.DWARF()\n\t} else {\n\t\treturn nil, errors.New(\"unknown binary format\")\n\t}\n}\n\ntype outputWriter struct {\n\tout        io.Writer\n\texecutable string\n\tline       []byte\n}\n\n// newOutputWriter returns an io.Writer that will intercept panic addresses and\n// will try to insert a source location in the output if the source location can\n// be found in the executable.\nfunc newOutputWriter(out io.Writer, executable string) *outputWriter {\n\treturn &outputWriter{\n\t\tout:        out,\n\t\texecutable: executable,\n\t}\n}\n\nfunc (w *outputWriter) Write(p []byte) (n int, err error) {\n\tstart := 0\n\tfor i, c := range p {\n\t\tif c == '\\n' {\n\t\t\tw.out.Write(p[start : i+1])\n\t\t\tstart = i + 1\n\t\t\taddress := extractPanicAddress(w.line)\n\t\t\tif address != 0 {\n\t\t\t\tloc, err := addressToLine(w.executable, address)\n\t\t\t\tif err == nil && loc.Filename != \"\" {\n\t\t\t\t\tfmt.Printf(\"[tinygo: panic at %s]\\n\", loc.String())\n\t\t\t\t}\n\t\t\t}\n\t\t\tw.line = w.line[:0]\n\t\t} else {\n\t\t\tw.line = append(w.line, c)\n\t\t}\n\t}\n\tw.out.Write(p[start:])\n\tn = len(p)\n\treturn\n}\n"
  },
  {
    "path": "monitor_test.go",
    "content": "package main\n\nimport (\n\t\"bytes\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/tinygo-org/tinygo/builder\"\n\t\"github.com/tinygo-org/tinygo/compileopts\"\n)\n\nfunc TestTraceback(t *testing.T) {\n\tif runtime.GOOS != \"linux\" {\n\t\t// We care about testing the ELF format, which is only used on Linux\n\t\t// (not on MacOS or Windows).\n\t\tt.Skip(\"Test only works on Linux\")\n\t}\n\n\t// Build a small binary that only panics.\n\ttmpdir := t.TempDir()\n\tconfig, err := builder.NewConfig(&compileopts.Options{\n\t\tGOOS:          runtime.GOOS,\n\t\tGOARCH:        runtime.GOARCH,\n\t\tOpt:           \"z\",\n\t\tInterpTimeout: time.Minute,\n\t\tDebug:         true,\n\t})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tresult, err := builder.Build(\"testdata/trivialpanic.go\", \".elf\", tmpdir, config)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Run this binary, and capture the output.\n\tbuf := &bytes.Buffer{}\n\tcmd := exec.Command(result.Binary)\n\tcmd.Stdout = buf\n\tcmd.Stderr = buf\n\tcmd.Run() // this will return an error because of the panic, ignore it\n\n\t// Extract the \"runtime error at\" address.\n\tline := bytes.TrimSpace(buf.Bytes())\n\taddress := extractPanicAddress(line)\n\tif address == 0 {\n\t\tt.Fatalf(\"could not extract panic address from %#v\", string(line))\n\t}\n\n\t// Look up the source location for this address.\n\tlocation, err := addressToLine(result.Executable, address)\n\tif err != nil {\n\t\tt.Fatal(\"could not read source location:\", err)\n\t}\n\n\t// Verify that the source location is as expected.\n\tif filepath.Base(location.Filename) != \"trivialpanic.go\" {\n\t\tt.Errorf(\"expected path to end with trivialpanic.go, got %#v\", location.Filename)\n\t}\n\tif location.Line != 6 {\n\t\tt.Errorf(\"expected panic location to be line 6, got line %d\", location.Line)\n\t}\n}\n"
  },
  {
    "path": "revive.toml",
    "content": "ignoreGeneratedHeader = false\nseverity = \"warning\"\nconfidence = 0.8\nerrorCode = 0\nwarningCode = 0\n\n# Enable these as we fix them\n[rule.blank-imports]\n  Exclude=[\"src/os/file_other.go\"]\n[rule.context-as-argument]\n[rule.context-keys-type]\n[rule.dot-imports]\n  Exclude=[\"**/*_test.go\"]\n[rule.error-return]\n[rule.error-strings]\n[rule.error-naming]\n[rule.exported]\n  Exclude=[\"src/reflect/*.go\"]\n[rule.increment-decrement]\n[rule.var-naming]\n  Exclude=[\"src/os/*.go\"]\n[rule.var-declaration]\n#[rule.package-comments]\n[rule.range]\n[rule.receiver-naming]\n[rule.time-naming]\n[rule.unexported-return]\n#[rule.indent-error-flow]\n[rule.errorf]\n#[rule.empty-block]\n[rule.superfluous-else]\n#[rule.unused-parameter]\n[rule.unreachable-code]\n  Exclude=[\"src/reflect/visiblefields_test.go\", \"src/reflect/all_test.go\"]\n#[rule.redefines-builtin-id]\n"
  },
  {
    "path": "src/crypto/internal/boring/sig/sig_other.go",
    "content": "// Package sig stubs crypto/internal/boring/sig\npackage sig\n\n// BoringCrypto indicates that the BoringCrypto module is present.\nfunc BoringCrypto() {\n\n}\n\n// FIPSOnly indicates that package crypto/tls/fipsonly is present.\nfunc FIPSOnly() {\n\n}\n\n// StandardCrypto indicates that standard Go crypto is present.\nfunc StandardCrypto() {\n\n}\n"
  },
  {
    "path": "src/crypto/rand/rand.go",
    "content": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package rand implements a cryptographically secure\n// random number generator.\npackage rand\n\nimport \"io\"\n\n// Reader is a global, shared instance of a cryptographically\n// secure random number generator.\nvar Reader io.Reader\n\n// Read is a helper function that calls Reader.Read using io.ReadFull.\n// On return, n == len(b) if and only if err == nil.\nfunc Read(b []byte) (n int, err error) {\n\tif Reader == nil {\n\t\tpanic(\"no rng\")\n\t}\n\n\treturn io.ReadFull(Reader, b)\n}\n"
  },
  {
    "path": "src/crypto/rand/rand_arc4random.go",
    "content": "//go:build darwin || wasip1 || wasip2 || wasm\n\n// This implementation of crypto/rand uses the arc4random_buf function\n// (available on both MacOS and WASI) to generate random numbers.\n//\n// Note: arc4random_buf (unlike what the name suggests) does not use the insecure\n// RC4 cipher. Instead, it uses a high-quality cipher, varying by the libc\n// implementation.\n\npackage rand\n\nimport \"unsafe\"\n\nfunc init() {\n\tReader = &reader{}\n}\n\ntype reader struct {\n}\n\nfunc (r *reader) Read(b []byte) (n int, err error) {\n\tif len(b) != 0 {\n\t\tlibc_arc4random_buf(unsafe.Pointer(&b[0]), uint(len(b)))\n\t}\n\treturn len(b), nil\n}\n\n// void arc4random_buf(void *buf, size_t buflen);\n//\n//export arc4random_buf\nfunc libc_arc4random_buf(buf unsafe.Pointer, buflen uint)\n"
  },
  {
    "path": "src/crypto/rand/rand_baremetal.go",
    "content": "//go:build nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3 || tkey || (tinygo.riscv32 && virt)\n\n// If you update the above build constraint, you'll probably also need to update\n// src/runtime/rand_hwrng.go.\n\npackage rand\n\nimport (\n\t\"machine\"\n)\n\nfunc init() {\n\tReader = &reader{}\n}\n\ntype reader struct {\n}\n\nfunc (r *reader) Read(b []byte) (n int, err error) {\n\tif len(b) == 0 {\n\t\treturn\n\t}\n\n\tvar randomByte uint32\n\tfor i := range b {\n\t\tif i%4 == 0 {\n\t\t\trandomByte, err = machine.GetRNG()\n\t\t\tif err != nil {\n\t\t\t\treturn n, err\n\t\t\t}\n\t\t} else {\n\t\t\trandomByte >>= 8\n\t\t}\n\t\tb[i] = byte(randomByte)\n\t}\n\n\treturn len(b), nil\n}\n"
  },
  {
    "path": "src/crypto/rand/rand_urandom.go",
    "content": "//go:build linux && !baremetal && !wasip1 && !wasip2\n\n// This implementation of crypto/rand uses the /dev/urandom pseudo-file to\n// generate random numbers.\n// TODO: convert to the getentropy or getrandom libc function on Linux once it\n// is more widely supported.\n\npackage rand\n\nimport (\n\t\"syscall\"\n)\n\nfunc init() {\n\tReader = &reader{}\n}\n\ntype reader struct {\n\tfd int\n}\n\nfunc (r *reader) Read(b []byte) (n int, err error) {\n\tif len(b) == 0 {\n\t\treturn\n\t}\n\n\t// Open /dev/urandom first if needed.\n\tif r.fd == 0 {\n\t\tfd, err := syscall.Open(\"/dev/urandom\", syscall.O_RDONLY, 0)\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t\tr.fd = fd\n\t}\n\n\t// Read from the file.\n\treturn syscall.Read(r.fd, b)\n}\n"
  },
  {
    "path": "src/crypto/rand/rand_windows.go",
    "content": "package rand\n\nimport (\n\t\"errors\"\n\t\"unsafe\"\n)\n\nfunc init() {\n\tReader = &reader{}\n}\n\ntype reader struct {\n}\n\nvar errRandom = errors.New(\"failed to obtain random data from rand_s\")\n\nfunc (r *reader) Read(b []byte) (n int, err error) {\n\tif len(b) == 0 {\n\t\treturn\n\t}\n\n\t// Use the old RtlGenRandom, introduced in Windows XP.\n\t// Even though the documentation says it is deprecated, it is widely used\n\t// and probably won't go away anytime soon.\n\t// See for example: https://github.com/golang/go/issues/33542\n\t// For Windows 7 and newer, we might switch to ProcessPrng in the future\n\t// (which is a documented function and might be a tiny bit faster).\n\tok := libc_RtlGenRandom(unsafe.Pointer(&b[0]), len(b))\n\tif !ok {\n\t\treturn 0, errRandom\n\t}\n\treturn len(b), nil\n}\n\n// This function is part of advapi32.dll, and is called SystemFunction036 for\n// some reason. It's available on Windows XP and newer.\n// See: https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom\n//\n//export SystemFunction036\nfunc libc_RtlGenRandom(buf unsafe.Pointer, len int) bool\n"
  },
  {
    "path": "src/crypto/rand/util.go",
    "content": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage rand\n\nimport (\n\t\"errors\"\n\t\"io\"\n\t\"math/big\"\n)\n\n// smallPrimes is a list of small, prime numbers that allows us to rapidly\n// exclude some fraction of composite candidates when searching for a random\n// prime. This list is truncated at the point where smallPrimesProduct exceeds\n// a uint64. It does not include two because we ensure that the candidates are\n// odd by construction.\nvar smallPrimes = []uint8{\n\t3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53,\n}\n\n// smallPrimesProduct is the product of the values in smallPrimes and allows us\n// to reduce a candidate prime by this number and then determine whether it's\n// coprime to all the elements of smallPrimes without further big.Int\n// operations.\nvar smallPrimesProduct = new(big.Int).SetUint64(16294579238595022365)\n\n// Prime returns a number, p, of the given size, such that p is prime\n// with high probability.\n// Prime will return error for any error returned by rand.Read or if bits < 2.\nfunc Prime(rand io.Reader, bits int) (p *big.Int, err error) {\n\tif bits < 2 {\n\t\terr = errors.New(\"crypto/rand: prime size must be at least 2-bit\")\n\t\treturn\n\t}\n\n\tb := uint(bits % 8)\n\tif b == 0 {\n\t\tb = 8\n\t}\n\n\tbytes := make([]byte, (bits+7)/8)\n\tp = new(big.Int)\n\n\tbigMod := new(big.Int)\n\n\tfor {\n\t\t_, err = io.ReadFull(rand, bytes)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\t// Clear bits in the first byte to make sure the candidate has a size <= bits.\n\t\tbytes[0] &= uint8(int(1<<b) - 1)\n\t\t// Don't let the value be too small, i.e, set the most significant two bits.\n\t\t// Setting the top two bits, rather than just the top bit,\n\t\t// means that when two of these values are multiplied together,\n\t\t// the result isn't ever one bit short.\n\t\tif b >= 2 {\n\t\t\tbytes[0] |= 3 << (b - 2)\n\t\t} else {\n\t\t\t// Here b==1, because b cannot be zero.\n\t\t\tbytes[0] |= 1\n\t\t\tif len(bytes) > 1 {\n\t\t\t\tbytes[1] |= 0x80\n\t\t\t}\n\t\t}\n\t\t// Make the value odd since an even number this large certainly isn't prime.\n\t\tbytes[len(bytes)-1] |= 1\n\n\t\tp.SetBytes(bytes)\n\n\t\t// Calculate the value mod the product of smallPrimes. If it's\n\t\t// a multiple of any of these primes we add two until it isn't.\n\t\t// The probability of overflowing is minimal and can be ignored\n\t\t// because we still perform Miller-Rabin tests on the result.\n\t\tbigMod.Mod(p, smallPrimesProduct)\n\t\tmod := bigMod.Uint64()\n\n\tNextDelta:\n\t\tfor delta := uint64(0); delta < 1<<20; delta += 2 {\n\t\t\tm := mod + delta\n\t\t\tfor _, prime := range smallPrimes {\n\t\t\t\tif m%uint64(prime) == 0 && (bits > 6 || m != uint64(prime)) {\n\t\t\t\t\tcontinue NextDelta\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif delta > 0 {\n\t\t\t\tbigMod.SetUint64(delta)\n\t\t\t\tp.Add(p, bigMod)\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\n\t\t// There is a tiny possibility that, by adding delta, we caused\n\t\t// the number to be one bit too long. Thus we check BitLen\n\t\t// here.\n\t\tif p.ProbablyPrime(20) && p.BitLen() == bits {\n\t\t\treturn\n\t\t}\n\t}\n}\n\n// Int returns a uniform random value in [0, max). It panics if max <= 0.\nfunc Int(rand io.Reader, max *big.Int) (n *big.Int, err error) {\n\tif max.Sign() <= 0 {\n\t\tpanic(\"crypto/rand: argument to Int is <= 0\")\n\t}\n\tn = new(big.Int)\n\tn.Sub(max, n.SetUint64(1))\n\t// bitLen is the maximum bit length needed to encode a value < max.\n\tbitLen := n.BitLen()\n\tif bitLen == 0 {\n\t\t// the only valid result is 0\n\t\treturn\n\t}\n\t// k is the maximum byte length needed to encode a value < max.\n\tk := (bitLen + 7) / 8\n\t// b is the number of bits in the most significant byte of max-1.\n\tb := uint(bitLen % 8)\n\tif b == 0 {\n\t\tb = 8\n\t}\n\n\tbytes := make([]byte, k)\n\n\tfor {\n\t\t_, err = io.ReadFull(rand, bytes)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\t// Clear bits in the first byte to increase the probability\n\t\t// that the candidate is < max.\n\t\tbytes[0] &= uint8(int(1<<b) - 1)\n\n\t\tn.SetBytes(bytes)\n\t\tif n.Cmp(max) < 0 {\n\t\t\treturn\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/crypto/tls/common.go",
    "content": "// TINYGO: The following is copied and modified from Go 1.19.3 official implementation.\n\n// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage tls\n\nimport (\n\t\"context\"\n\t\"crypto\"\n\t\"crypto/x509\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"sync\"\n\t\"time\"\n)\n\nconst (\n\tVersionTLS10 = 0x0301\n\tVersionTLS11 = 0x0302\n\tVersionTLS12 = 0x0303\n\tVersionTLS13 = 0x0304\n\n\t// Deprecated: SSLv3 is cryptographically broken, and is no longer\n\t// supported by this package. See golang.org/issue/32716.\n\tVersionSSL30 = 0x0300\n)\n\n// VersionName returns the name for the provided TLS version number\n// (e.g. \"TLS 1.3\"), or a fallback representation of the value if the\n// version is not implemented by this package.\nfunc VersionName(version uint16) string {\n\tswitch version {\n\tcase VersionSSL30:\n\t\treturn \"SSLv3\"\n\tcase VersionTLS10:\n\t\treturn \"TLS 1.0\"\n\tcase VersionTLS11:\n\t\treturn \"TLS 1.1\"\n\tcase VersionTLS12:\n\t\treturn \"TLS 1.2\"\n\tcase VersionTLS13:\n\t\treturn \"TLS 1.3\"\n\tdefault:\n\t\treturn fmt.Sprintf(\"0x%04X\", version)\n\t}\n}\n\n// CurveID is the type of a TLS identifier for an elliptic curve. See\n// https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8.\n//\n// In TLS 1.3, this type is called NamedGroup, but at this time this library\n// only supports Elliptic Curve based groups. See RFC 8446, Section 4.2.7.\ntype CurveID uint16\n\n// CipherSuiteName returns the standard name for the passed cipher suite ID\n//\n// Not Implemented.\nfunc CipherSuiteName(id uint16) string {\n\treturn fmt.Sprintf(\"0x%04X\", id)\n}\n\n// ConnectionState records basic TLS details about the connection.\ntype ConnectionState struct {\n\t// TINYGO: empty; TLS connection offloaded to device\n\t//\n\t// Minimum (empty) fields for fortio.org/log http logging and others\n\t// to compile and run.\n\tPeerCertificates []*x509.Certificate\n\tCipherSuite      uint16\n}\n\n// ClientAuthType declares the policy the server will follow for\n// TLS Client Authentication.\ntype ClientAuthType int\n\n// ClientSessionCache is a cache of ClientSessionState objects that can be used\n// by a client to resume a TLS session with a given server. ClientSessionCache\n// implementations should expect to be called concurrently from different\n// goroutines. Up to TLS 1.2, only ticket-based resumption is supported, not\n// SessionID-based resumption. In TLS 1.3 they were merged into PSK modes, which\n// are supported via this interface.\ntype ClientSessionCache interface {\n\t// Get searches for a ClientSessionState associated with the given key.\n\t// On return, ok is true if one was found.\n\tGet(sessionKey string) (session *ClientSessionState, ok bool)\n\n\t// Put adds the ClientSessionState to the cache with the given key. It might\n\t// get called multiple times in a connection if a TLS 1.3 server provides\n\t// more than one session ticket. If called with a nil *ClientSessionState,\n\t// it should remove the cache entry.\n\tPut(sessionKey string, cs *ClientSessionState)\n}\n\n//go:generate stringer -type=SignatureScheme,CurveID,ClientAuthType -output=common_string.go\n\n// SignatureScheme identifies a signature algorithm supported by TLS. See\n// RFC 8446, Section 4.2.3.\ntype SignatureScheme uint16\n\n// ClientHelloInfo contains information from a ClientHello message in order to\n// guide application logic in the GetCertificate and GetConfigForClient callbacks.\ntype ClientHelloInfo struct {\n\t// CipherSuites lists the CipherSuites supported by the client (e.g.\n\t// TLS_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256).\n\tCipherSuites []uint16\n\n\t// ServerName indicates the name of the server requested by the client\n\t// in order to support virtual hosting. ServerName is only set if the\n\t// client is using SNI (see RFC 4366, Section 3.1).\n\tServerName string\n\n\t// SupportedCurves lists the elliptic curves supported by the client.\n\t// SupportedCurves is set only if the Supported Elliptic Curves\n\t// Extension is being used (see RFC 4492, Section 5.1.1).\n\tSupportedCurves []CurveID\n\n\t// SupportedPoints lists the point formats supported by the client.\n\t// SupportedPoints is set only if the Supported Point Formats Extension\n\t// is being used (see RFC 4492, Section 5.1.2).\n\tSupportedPoints []uint8\n\n\t// SignatureSchemes lists the signature and hash schemes that the client\n\t// is willing to verify. SignatureSchemes is set only if the Signature\n\t// Algorithms Extension is being used (see RFC 5246, Section 7.4.1.4.1).\n\tSignatureSchemes []SignatureScheme\n\n\t// SupportedProtos lists the application protocols supported by the client.\n\t// SupportedProtos is set only if the Application-Layer Protocol\n\t// Negotiation Extension is being used (see RFC 7301, Section 3.1).\n\t//\n\t// Servers can select a protocol by setting Config.NextProtos in a\n\t// GetConfigForClient return value.\n\tSupportedProtos []string\n\n\t// SupportedVersions lists the TLS versions supported by the client.\n\t// For TLS versions less than 1.3, this is extrapolated from the max\n\t// version advertised by the client, so values other than the greatest\n\t// might be rejected if used.\n\tSupportedVersions []uint16\n\n\t// Conn is the underlying net.Conn for the connection. Do not read\n\t// from, or write to, this connection; that will cause the TLS\n\t// connection to fail.\n\tConn net.Conn\n\n\t// config is embedded by the GetCertificate or GetConfigForClient caller,\n\t// for use with SupportsCertificate.\n\tconfig *Config\n\n\t// ctx is the context of the handshake that is in progress.\n\tctx context.Context\n}\n\n// CertificateRequestInfo contains information from a server's\n// CertificateRequest message, which is used to demand a certificate and proof\n// of control from a client.\ntype CertificateRequestInfo struct {\n\t// AcceptableCAs contains zero or more, DER-encoded, X.501\n\t// Distinguished Names. These are the names of root or intermediate CAs\n\t// that the server wishes the returned certificate to be signed by. An\n\t// empty slice indicates that the server has no preference.\n\tAcceptableCAs [][]byte\n\n\t// SignatureSchemes lists the signature schemes that the server is\n\t// willing to verify.\n\tSignatureSchemes []SignatureScheme\n\n\t// Version is the TLS version that was negotiated for this connection.\n\tVersion uint16\n\n\t// ctx is the context of the handshake that is in progress.\n\tctx context.Context\n}\n\n// RenegotiationSupport enumerates the different levels of support for TLS\n// renegotiation. TLS renegotiation is the act of performing subsequent\n// handshakes on a connection after the first. This significantly complicates\n// the state machine and has been the source of numerous, subtle security\n// issues. Initiating a renegotiation is not supported, but support for\n// accepting renegotiation requests may be enabled.\n//\n// Even when enabled, the server may not change its identity between handshakes\n// (i.e. the leaf certificate must be the same). Additionally, concurrent\n// handshake and application data flow is not permitted so renegotiation can\n// only be used with protocols that synchronise with the renegotiation, such as\n// HTTPS.\n//\n// Renegotiation is not defined in TLS 1.3.\ntype RenegotiationSupport int\n\n// A Config structure is used to configure a TLS client or server.\n// After one has been passed to a TLS function it must not be\n// modified. A Config may be reused; the tls package will also not\n// modify it.\ntype Config struct {\n\t// Rand provides the source of entropy for nonces and RSA blinding.\n\t// If Rand is nil, TLS uses the cryptographic random reader in package\n\t// crypto/rand.\n\t// The Reader must be safe for use by multiple goroutines.\n\tRand io.Reader\n\n\t// Time returns the current time as the number of seconds since the epoch.\n\t// If Time is nil, TLS uses time.Now.\n\tTime func() time.Time\n\n\t// Certificates contains one or more certificate chains to present to the\n\t// other side of the connection. The first certificate compatible with the\n\t// peer's requirements is selected automatically.\n\t//\n\t// Server configurations must set one of Certificates, GetCertificate or\n\t// GetConfigForClient. Clients doing client-authentication may set either\n\t// Certificates or GetClientCertificate.\n\t//\n\t// Note: if there are multiple Certificates, and they don't have the\n\t// optional field Leaf set, certificate selection will incur a significant\n\t// per-handshake performance cost.\n\tCertificates []Certificate\n\n\t// NameToCertificate maps from a certificate name to an element of\n\t// Certificates. Note that a certificate name can be of the form\n\t// '*.example.com' and so doesn't have to be a domain name as such.\n\t//\n\t// Deprecated: NameToCertificate only allows associating a single\n\t// certificate with a given name. Leave this field nil to let the library\n\t// select the first compatible chain from Certificates.\n\tNameToCertificate map[string]*Certificate\n\n\t// GetCertificate returns a Certificate based on the given\n\t// ClientHelloInfo. It will only be called if the client supplies SNI\n\t// information or if Certificates is empty.\n\t//\n\t// If GetCertificate is nil or returns nil, then the certificate is\n\t// retrieved from NameToCertificate. If NameToCertificate is nil, the\n\t// best element of Certificates will be used.\n\t//\n\t// Once a Certificate is returned it should not be modified.\n\tGetCertificate func(*ClientHelloInfo) (*Certificate, error)\n\n\t// GetClientCertificate, if not nil, is called when a server requests a\n\t// certificate from a client. If set, the contents of Certificates will\n\t// be ignored.\n\t//\n\t// If GetClientCertificate returns an error, the handshake will be\n\t// aborted and that error will be returned. Otherwise\n\t// GetClientCertificate must return a non-nil Certificate. If\n\t// Certificate.Certificate is empty then no certificate will be sent to\n\t// the server. If this is unacceptable to the server then it may abort\n\t// the handshake.\n\t//\n\t// GetClientCertificate may be called multiple times for the same\n\t// connection if renegotiation occurs or if TLS 1.3 is in use.\n\t//\n\t// Once a Certificate is returned it should not be modified.\n\tGetClientCertificate func(*CertificateRequestInfo) (*Certificate, error)\n\n\t// GetConfigForClient, if not nil, is called after a ClientHello is\n\t// received from a client. It may return a non-nil Config in order to\n\t// change the Config that will be used to handle this connection. If\n\t// the returned Config is nil, the original Config will be used. The\n\t// Config returned by this callback may not be subsequently modified.\n\t//\n\t// If GetConfigForClient is nil, the Config passed to Server() will be\n\t// used for all connections.\n\t//\n\t// If SessionTicketKey was explicitly set on the returned Config, or if\n\t// SetSessionTicketKeys was called on the returned Config, those keys will\n\t// be used. Otherwise, the original Config keys will be used (and possibly\n\t// rotated if they are automatically managed).\n\tGetConfigForClient func(*ClientHelloInfo) (*Config, error)\n\n\t// VerifyPeerCertificate, if not nil, is called after normal\n\t// certificate verification by either a TLS client or server. It\n\t// receives the raw ASN.1 certificates provided by the peer and also\n\t// any verified chains that normal processing found. If it returns a\n\t// non-nil error, the handshake is aborted and that error results.\n\t//\n\t// If normal verification fails then the handshake will abort before\n\t// considering this callback. If normal verification is disabled (on the\n\t// client when InsecureSkipVerify is set, or on a server when ClientAuth is\n\t// RequestClientCert or RequireAnyClientCert), then this callback will be\n\t// considered but the verifiedChains argument will always be nil. When\n\t// ClientAuth is NoClientCert, this callback is not called on the server.\n\t// rawCerts may be empty on the server if ClientAuth is RequestClientCert or\n\t// VerifyClientCertIfGiven.\n\t//\n\t// This callback is not invoked on resumed connections, as certificates are\n\t// not re-verified on resumption.\n\t//\n\t// verifiedChains and its contents should not be modified.\n\tVerifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error\n\n\t// VerifyConnection, if not nil, is called after normal certificate\n\t// verification and after VerifyPeerCertificate by either a TLS client\n\t// or server. If it returns a non-nil error, the handshake is aborted\n\t// and that error results.\n\t//\n\t// If normal verification fails then the handshake will abort before\n\t// considering this callback. This callback will run for all connections,\n\t// including resumptions, regardless of InsecureSkipVerify or ClientAuth\n\t// settings.\n\tVerifyConnection func(ConnectionState) error\n\n\t// RootCAs defines the set of root certificate authorities\n\t// that clients use when verifying server certificates.\n\t// If RootCAs is nil, TLS uses the host's root CA set.\n\tRootCAs *x509.CertPool\n\n\t// NextProtos is a list of supported application level protocols, in\n\t// order of preference. If both peers support ALPN, the selected\n\t// protocol will be one from this list, and the connection will fail\n\t// if there is no mutually supported protocol. If NextProtos is empty\n\t// or the peer doesn't support ALPN, the connection will succeed and\n\t// ConnectionState.NegotiatedProtocol will be empty.\n\tNextProtos []string\n\n\t// ServerName is used to verify the hostname on the returned\n\t// certificates unless InsecureSkipVerify is given. It is also included\n\t// in the client's handshake to support virtual hosting unless it is\n\t// an IP address.\n\tServerName string\n\n\t// ClientAuth determines the server's policy for\n\t// TLS Client Authentication. The default is NoClientCert.\n\tClientAuth ClientAuthType\n\n\t// ClientCAs defines the set of root certificate authorities\n\t// that servers use if required to verify a client certificate\n\t// by the policy in ClientAuth.\n\tClientCAs *x509.CertPool\n\n\t// InsecureSkipVerify controls whether a client verifies the server's\n\t// certificate chain and host name. If InsecureSkipVerify is true, crypto/tls\n\t// accepts any certificate presented by the server and any host name in that\n\t// certificate. In this mode, TLS is susceptible to machine-in-the-middle\n\t// attacks unless custom verification is used. This should be used only for\n\t// testing or in combination with VerifyConnection or VerifyPeerCertificate.\n\tInsecureSkipVerify bool\n\n\t// CipherSuites is a list of enabled TLS 1.0–1.2 cipher suites. The order of\n\t// the list is ignored. Note that TLS 1.3 ciphersuites are not configurable.\n\t//\n\t// If CipherSuites is nil, a safe default list is used. The default cipher\n\t// suites might change over time.\n\tCipherSuites []uint16\n\n\t// PreferServerCipherSuites is a legacy field and has no effect.\n\t//\n\t// It used to control whether the server would follow the client's or the\n\t// server's preference. Servers now select the best mutually supported\n\t// cipher suite based on logic that takes into account inferred client\n\t// hardware, server hardware, and security.\n\t//\n\t// Deprecated: PreferServerCipherSuites is ignored.\n\tPreferServerCipherSuites bool\n\n\t// SessionTicketsDisabled may be set to true to disable session ticket and\n\t// PSK (resumption) support. Note that on clients, session ticket support is\n\t// also disabled if ClientSessionCache is nil.\n\tSessionTicketsDisabled bool\n\n\t// SessionTicketKey is used by TLS servers to provide session resumption.\n\t// See RFC 5077 and the PSK mode of RFC 8446. If zero, it will be filled\n\t// with random data before the first server handshake.\n\t//\n\t// Deprecated: if this field is left at zero, session ticket keys will be\n\t// automatically rotated every day and dropped after seven days. For\n\t// customizing the rotation schedule or synchronizing servers that are\n\t// terminating connections for the same host, use SetSessionTicketKeys.\n\tSessionTicketKey [32]byte\n\n\t// ClientSessionCache is a cache of ClientSessionState entries for TLS\n\t// session resumption. It is only used by clients.\n\tClientSessionCache ClientSessionCache\n\n\t// UnwrapSession is called on the server to turn a ticket/identity\n\t// previously produced by [WrapSession] into a usable session.\n\t//\n\t// UnwrapSession will usually either decrypt a session state in the ticket\n\t// (for example with [Config.EncryptTicket]), or use the ticket as a handle\n\t// to recover a previously stored state. It must use [ParseSessionState] to\n\t// deserialize the session state.\n\t//\n\t// If UnwrapSession returns an error, the connection is terminated. If it\n\t// returns (nil, nil), the session is ignored. crypto/tls may still choose\n\t// not to resume the returned session.\n\tUnwrapSession func(identity []byte, cs ConnectionState) (*SessionState, error)\n\n\t// WrapSession is called on the server to produce a session ticket/identity.\n\t//\n\t// WrapSession must serialize the session state with [SessionState.Bytes].\n\t// It may then encrypt the serialized state (for example with\n\t// [Config.DecryptTicket]) and use it as the ticket, or store the state and\n\t// return a handle for it.\n\t//\n\t// If WrapSession returns an error, the connection is terminated.\n\t//\n\t// Warning: the return value will be exposed on the wire and to clients in\n\t// plaintext. The application is in charge of encrypting and authenticating\n\t// it (and rotating keys) or returning high-entropy identifiers. Failing to\n\t// do so correctly can compromise current, previous, and future connections\n\t// depending on the protocol version.\n\tWrapSession func(ConnectionState, *SessionState) ([]byte, error)\n\n\t// MinVersion contains the minimum TLS version that is acceptable.\n\t//\n\t// By default, TLS 1.2 is currently used as the minimum when acting as a\n\t// client, and TLS 1.0 when acting as a server. TLS 1.0 is the minimum\n\t// supported by this package, both as a client and as a server.\n\t//\n\t// The client-side default can temporarily be reverted to TLS 1.0 by\n\t// including the value \"x509sha1=1\" in the GODEBUG environment variable.\n\t// Note that this option will be removed in Go 1.19 (but it will still be\n\t// possible to set this field to VersionTLS10 explicitly).\n\tMinVersion uint16\n\n\t// MaxVersion contains the maximum TLS version that is acceptable.\n\t//\n\t// By default, the maximum version supported by this package is used,\n\t// which is currently TLS 1.3.\n\tMaxVersion uint16\n\n\t// CurvePreferences contains the elliptic curves that will be used in\n\t// an ECDHE handshake, in preference order. If empty, the default will\n\t// be used. The client will use the first preference as the type for\n\t// its key share in TLS 1.3. This may change in the future.\n\tCurvePreferences []CurveID\n\n\t// DynamicRecordSizingDisabled disables adaptive sizing of TLS records.\n\t// When true, the largest possible TLS record size is always used. When\n\t// false, the size of TLS records may be adjusted in an attempt to\n\t// improve latency.\n\tDynamicRecordSizingDisabled bool\n\n\t// Renegotiation controls what types of renegotiation are supported.\n\t// The default, none, is correct for the vast majority of applications.\n\tRenegotiation RenegotiationSupport\n\n\t// KeyLogWriter optionally specifies a destination for TLS master secrets\n\t// in NSS key log format that can be used to allow external programs\n\t// such as Wireshark to decrypt TLS connections.\n\t// See https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format.\n\t// Use of KeyLogWriter compromises security and should only be\n\t// used for debugging.\n\tKeyLogWriter io.Writer\n\n\t// mutex protects sessionTicketKeys and autoSessionTicketKeys.\n\tmutex sync.RWMutex\n\t// sessionTicketKeys contains zero or more ticket keys. If set, it means\n\t// the keys were set with SessionTicketKey or SetSessionTicketKeys. The\n\t// first key is used for new tickets and any subsequent keys can be used to\n\t// decrypt old tickets. The slice contents are not protected by the mutex\n\t// and are immutable.\n\tsessionTicketKeys []ticketKey\n\t// autoSessionTicketKeys is like sessionTicketKeys but is owned by the\n\t// auto-rotation logic. See Config.ticketKeys.\n\tautoSessionTicketKeys []ticketKey\n}\n\n// ticketKey is the internal representation of a session ticket key.\ntype ticketKey struct {\n\taesKey  [16]byte\n\thmacKey [16]byte\n\t// created is the time at which this ticket key was created. See Config.ticketKeys.\n\tcreated time.Time\n}\n\n// A Certificate is a chain of one or more certificates, leaf first.\ntype Certificate struct {\n\tCertificate [][]byte\n\t// PrivateKey contains the private key corresponding to the public key in\n\t// Leaf. This must implement crypto.Signer with an RSA, ECDSA or Ed25519 PublicKey.\n\t// For a server up to TLS 1.2, it can also implement crypto.Decrypter with\n\t// an RSA PublicKey.\n\tPrivateKey crypto.PrivateKey\n\t// SupportedSignatureAlgorithms is an optional list restricting what\n\t// signature algorithms the PrivateKey can be used for.\n\tSupportedSignatureAlgorithms []SignatureScheme\n\t// OCSPStaple contains an optional OCSP response which will be served\n\t// to clients that request it.\n\tOCSPStaple []byte\n\t// SignedCertificateTimestamps contains an optional list of Signed\n\t// Certificate Timestamps which will be served to clients that request it.\n\tSignedCertificateTimestamps [][]byte\n\t// Leaf is the parsed form of the leaf certificate, which may be initialized\n\t// using x509.ParseCertificate to reduce per-handshake processing. If nil,\n\t// the leaf certificate will be parsed as needed.\n\tLeaf *x509.Certificate\n}\n"
  },
  {
    "path": "src/crypto/tls/ticket.go",
    "content": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage tls\n\n// A SessionState is a resumable session.\ntype SessionState struct {\n}\n\n// ClientSessionState contains the state needed by a client to\n// resume a previous TLS session.\ntype ClientSessionState struct {\n\tticket  []byte\n\tsession *SessionState\n}\n"
  },
  {
    "path": "src/crypto/tls/tls.go",
    "content": "// TINYGO: The following is copied and modified from Go 1.21.4 official implementation.\n\n// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package tls partially implements TLS 1.2, as specified in RFC 5246,\n// and TLS 1.3, as specified in RFC 8446.\npackage tls\n\n// BUG(agl): The crypto/tls package only implements some countermeasures\n// against Lucky13 attacks on CBC-mode encryption, and only on SHA1\n// variants. See http://www.isg.rhul.ac.uk/tls/TLStiming.pdf and\n// https://www.imperialviolet.org/2013/02/04/luckythirteen.html.\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net\"\n)\n\n// Client returns a new TLS client side connection\n// using conn as the underlying transport.\n// The config cannot be nil: users must set either ServerName or\n// InsecureSkipVerify in the config.\nfunc Client(conn net.Conn, config *Config) *net.TLSConn {\n\tpanic(\"tls.Client() not implemented\")\n\treturn nil\n}\n\n// A listener implements a network listener (net.Listener) for TLS connections.\ntype listener struct {\n\tnet.Listener\n\tconfig *Config\n}\n\n// NewListener creates a Listener which accepts connections from an inner\n// Listener and wraps each connection with Server.\n// The configuration config must be non-nil and must include\n// at least one certificate or else set GetCertificate.\nfunc NewListener(inner net.Listener, config *Config) net.Listener {\n\tl := new(listener)\n\tl.Listener = inner\n\tl.config = config\n\treturn l\n}\n\n// DialWithDialer connects to the given network address using dialer.Dial and\n// then initiates a TLS handshake, returning the resulting TLS connection. Any\n// timeout or deadline given in the dialer apply to connection and TLS\n// handshake as a whole.\n//\n// DialWithDialer interprets a nil configuration as equivalent to the zero\n// configuration; see the documentation of Config for the defaults.\n//\n// DialWithDialer uses context.Background internally; to specify the context,\n// use Dialer.DialContext with NetDialer set to the desired dialer.\nfunc DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*net.TLSConn, error) {\n\tswitch network {\n\tcase \"tcp\", \"tcp4\":\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"Network %s not supported\", network)\n\t}\n\n\treturn net.DialTLS(addr)\n}\n\n// Dial connects to the given network address using net.Dial\n// and then initiates a TLS handshake, returning the resulting\n// TLS connection.\n// Dial interprets a nil configuration as equivalent to\n// the zero configuration; see the documentation of Config\n// for the defaults.\nfunc Dial(network, addr string, config *Config) (*net.TLSConn, error) {\n\treturn DialWithDialer(new(net.Dialer), network, addr, config)\n}\n\n// Dialer dials TLS connections given a configuration and a Dialer for the\n// underlying connection.\ntype Dialer struct {\n\t// NetDialer is the optional dialer to use for the TLS connections'\n\t// underlying TCP connections.\n\t// A nil NetDialer is equivalent to the net.Dialer zero value.\n\tNetDialer *net.Dialer\n\n\t// Config is the TLS configuration to use for new connections.\n\t// A nil configuration is equivalent to the zero\n\t// configuration; see the documentation of Config for the\n\t// defaults.\n\tConfig *Config\n}\n\n// DialContext connects to the given network address and initiates a TLS\n// handshake, returning the resulting TLS connection.\n//\n// The provided Context must be non-nil. If the context expires before\n// the connection is complete, an error is returned. Once successfully\n// connected, any expiration of the context will not affect the\n// connection.\n//\n// The returned Conn, if any, will always be of type *Conn.\nfunc (d *Dialer) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {\n\tswitch network {\n\tcase \"tcp\", \"tcp4\":\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"Network %s not supported\", network)\n\t}\n\n\treturn net.DialTLS(addr)\n}\n\n// LoadX509KeyPair reads and parses a public/private key pair from a pair\n// of files. The files must contain PEM encoded data. The certificate file\n// may contain intermediate certificates following the leaf certificate to\n// form a certificate chain. On successful return, Certificate.Leaf will\n// be nil because the parsed form of the certificate is not retained.\nfunc LoadX509KeyPair(certFile, keyFile string) (Certificate, error) {\n\treturn Certificate{}, errors.New(\"tls:LoadX509KeyPair not implemented\")\n}\n"
  },
  {
    "path": "src/crypto/x509/internal/macos/macos.go",
    "content": "package macos\n\nimport (\n\t\"errors\"\n\t\"time\"\n)\n\n// Exported symbols copied from Big Go, but stripped of functionality.\n// Allows building of crypto/x509 on macOS.\n\nconst (\n\tErrSecCertificateExpired = -67818\n\tErrSecHostNameMismatch   = -67602\n\tErrSecNotTrusted         = -67843\n)\n\nvar ErrNoTrustSettings = errors.New(\"no trust settings found\")\nvar SecPolicyAppleSSL = StringToCFString(\"1.2.840.113635.100.1.3\") // defined by POLICYMACRO\nvar SecPolicyOid = StringToCFString(\"SecPolicyOid\")\nvar SecTrustSettingsPolicy = StringToCFString(\"kSecTrustSettingsPolicy\")\nvar SecTrustSettingsPolicyString = StringToCFString(\"kSecTrustSettingsPolicyString\")\nvar SecTrustSettingsResultKey = StringToCFString(\"kSecTrustSettingsResult\")\n\nfunc CFArrayAppendValue(array CFRef, val CFRef) {}\n\nfunc CFArrayGetCount(array CFRef) int {\n\treturn 0\n}\n\nfunc CFDataGetBytePtr(data CFRef) uintptr {\n\treturn 0\n}\n\nfunc CFDataGetLength(data CFRef) int {\n\treturn 0\n}\n\nfunc CFDataToSlice(data CFRef) []byte {\n\treturn nil\n}\n\nfunc CFEqual(a, b CFRef) bool {\n\treturn false\n}\n\nfunc CFErrorGetCode(errRef CFRef) int {\n\treturn 0\n}\n\nfunc CFNumberGetValue(num CFRef) (int32, error) {\n\treturn 0, errors.New(\"not implemented\")\n}\n\nfunc CFRelease(ref CFRef) {}\n\nfunc CFStringToString(ref CFRef) string {\n\treturn \"\"\n}\n\nfunc ReleaseCFArray(array CFRef) {}\n\nfunc SecCertificateCopyData(cert CFRef) ([]byte, error) {\n\treturn nil, errors.New(\"not implemented\")\n}\n\nfunc SecTrustCopyCertificateChain(trustObj CFRef) (CFRef, error) {\n\treturn 0, errors.New(\"not implemented\")\n}\n\nfunc SecTrustEvaluateWithError(trustObj CFRef) (int, error) {\n\treturn 0, errors.New(\"not implemented\")\n}\n\nfunc SecTrustGetCertificateCount(trustObj CFRef) int {\n\treturn 0\n}\n\nfunc SecTrustGetResult(trustObj CFRef, result CFRef) (CFRef, CFRef, error) {\n\treturn 0, 0, errors.New(\"not implemented\")\n}\n\nfunc SecTrustSetVerifyDate(trustObj CFRef, dateRef CFRef) error {\n\treturn errors.New(\"not implemented\")\n}\n\ntype CFRef uintptr\n\nfunc BytesToCFData(b []byte) CFRef {\n\treturn 0\n}\n\nfunc CFArrayCreateMutable() CFRef {\n\treturn 0\n}\n\nfunc CFArrayGetValueAtIndex(array CFRef, index int) CFRef {\n\treturn 0\n}\n\nfunc CFDateCreate(seconds float64) CFRef {\n\treturn 0\n}\n\nfunc CFDictionaryGetValueIfPresent(dict CFRef, key CFString) (value CFRef, ok bool) {\n\treturn 0, false\n}\n\nfunc CFErrorCopyDescription(errRef CFRef) CFRef {\n\treturn 0\n}\n\nfunc CFStringCreateExternalRepresentation(strRef CFRef) (CFRef, error) {\n\treturn 0, errors.New(\"not implemented\")\n}\n\nfunc SecCertificateCreateWithData(b []byte) (CFRef, error) {\n\treturn 0, errors.New(\"not implemented\")\n}\n\nfunc SecPolicyCreateSSL(name string) (CFRef, error) {\n\treturn 0, errors.New(\"not implemented\")\n}\n\nfunc SecTrustCreateWithCertificates(certs CFRef, policies CFRef) (CFRef, error) {\n\treturn 0, errors.New(\"not implemented\")\n}\n\nfunc SecTrustEvaluate(trustObj CFRef) (CFRef, error) {\n\treturn 0, errors.New(\"not implemented\")\n}\n\nfunc SecTrustGetCertificateAtIndex(trustObj CFRef, i int) (CFRef, error) {\n\treturn 0, errors.New(\"not implemented\")\n}\n\nfunc SecTrustSettingsCopyCertificates(domain SecTrustSettingsDomain) (certArray CFRef, err error) {\n\treturn 0, errors.New(\"not implemented\")\n}\n\nfunc SecTrustSettingsCopyTrustSettings(cert CFRef, domain SecTrustSettingsDomain) (trustSettings CFRef, err error) {\n\treturn 0, errors.New(\"not implemented\")\n}\n\nfunc TimeToCFDateRef(t time.Time) CFRef {\n\treturn 0\n}\n\ntype CFString CFRef\n\nfunc StringToCFString(s string) CFString {\n\treturn 0\n}\n\ntype OSStatus struct {\n\t// Has unexported fields.\n}\n\nfunc (s OSStatus) Error() string\n\ntype SecTrustResultType int32\n\nconst (\n\tSecTrustResultInvalid SecTrustResultType = iota\n\tSecTrustResultProceed\n\tSecTrustResultConfirm // deprecated\n\tSecTrustResultDeny\n\tSecTrustResultUnspecified\n\tSecTrustResultRecoverableTrustFailure\n\tSecTrustResultFatalTrustFailure\n\tSecTrustResultOtherError\n)\n\ntype SecTrustSettingsDomain int32\n\nconst (\n\tSecTrustSettingsDomainUser SecTrustSettingsDomain = iota\n\tSecTrustSettingsDomainAdmin\n\tSecTrustSettingsDomainSystem\n)\n\ntype SecTrustSettingsResult int32\n\nconst (\n\tSecTrustSettingsResultInvalid SecTrustSettingsResult = iota\n\tSecTrustSettingsResultTrustRoot\n\tSecTrustSettingsResultTrustAsRoot\n\tSecTrustSettingsResultDeny\n\tSecTrustSettingsResultUnspecified\n)\n"
  },
  {
    "path": "src/device/arm/arm.go",
    "content": "// CMSIS abstraction functions.\n//\n// Original copyright:\n//\n//\tCopyright (c) 2009 - 2015 ARM LIMITED\n//\n//\tAll rights reserved.\n//\tRedistribution and use in source and binary forms, with or without\n//\tmodification, are permitted provided that the following conditions are met:\n//\t- Redistributions of source code must retain the above copyright\n//\t  notice, this list of conditions and the following disclaimer.\n//\t- Redistributions in binary form must reproduce the above copyright\n//\t  notice, this list of conditions and the following disclaimer in the\n//\t  documentation and/or other materials provided with the distribution.\n//\t- Neither the name of ARM nor the names of its contributors may be used\n//\t  to endorse or promote products derived from this software without\n//\t  specific prior written permission.\n//\n//\tTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n//\tAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n//\tIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n//\tARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE\n//\tLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n//\tCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n//\tSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n//\tINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n//\tCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n//\tARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n//\tPOSSIBILITY OF SUCH DAMAGE.\npackage arm\n\nimport \"C\"\nimport (\n\t\"errors\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nvar errCycleCountTooLarge = errors.New(\"requested cycle count is too large, overflows 24 bit counter\")\n\n// Run the given assembly code. The code will be marked as having side effects,\n// as it doesn't produce output and thus would normally be eliminated by the\n// optimizer.\nfunc Asm(asm string)\n\n// Run the given inline assembly. The code will be marked as having side\n// effects, as it would otherwise be optimized away. The inline assembly string\n// recognizes template values in the form {name}, like so:\n//\n//\tarm.AsmFull(\n//\t    \"str {value}, [{result}]\",\n//\t    map[string]interface{}{\n//\t        \"value\":  1,\n//\t        \"result\": uintptr(unsafe.Pointer(&dest)),\n//\t    })\n//\n// You can use {} in the asm string (which expands to a register) to set the\n// return value.\nfunc AsmFull(asm string, regs map[string]interface{}) uintptr\n\n// Run the following system call (SVCall) with 0 arguments.\nfunc SVCall0(num uintptr) uintptr\n\n// Run the following system call (SVCall) with 1 argument.\nfunc SVCall1(num uintptr, a1 interface{}) uintptr\n\n// Run the following system call (SVCall) with 2 arguments.\nfunc SVCall2(num uintptr, a1, a2 interface{}) uintptr\n\n// Run the following system call (SVCall) with 3 arguments.\nfunc SVCall3(num uintptr, a1, a2, a3 interface{}) uintptr\n\n// Run the following system call (SVCall) with 4 arguments.\nfunc SVCall4(num uintptr, a1, a2, a3, a4 interface{}) uintptr\n\nconst (\n\tSCS_BASE  = 0xE000E000\n\tSYST_BASE = SCS_BASE + 0x0010\n\tNVIC_BASE = SCS_BASE + 0x0100\n)\n\n// Nested Vectored Interrupt Controller (NVIC).\n//\n// Source:\n// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0553a/CIHIGCIF.html\ntype NVIC_Type struct {\n\tISER [8]volatile.Register32 // Interrupt Set-enable Registers\n\t_    [24]uint32\n\tICER [8]volatile.Register32 // Interrupt Clear-enable Registers\n\t_    [24]uint32\n\tISPR [8]volatile.Register32 // Interrupt Set-pending Registers\n\t_    [24]uint32\n\tICPR [8]volatile.Register32 // Interrupt Clear-pending Registers\n\t_    [24]uint32\n\tIABR [8]volatile.Register32 // Interrupt Active Bit Registers\n\t_    [56]uint32\n\tIPR  [60]volatile.Register32 // Interrupt Priority Registers\n}\n\nvar NVIC = (*NVIC_Type)(unsafe.Pointer(uintptr(NVIC_BASE)))\n\n// System Timer (SYST)\n//\n// Source: https://static.docs.arm.com/ddi0403/e/DDI0403E_d_armv7m_arm.pdf B3.3\ntype SYST_Type struct {\n\tSYST_CSR   volatile.Register32\n\tSYST_RVR   volatile.Register32\n\tSYST_CVR   volatile.Register32\n\tSYST_CALIB volatile.Register32\n}\n\nvar SYST = (*SYST_Type)(unsafe.Pointer(uintptr(SYST_BASE)))\n\n// Bitfields for SYST: System Timer\nconst (\n\t// SYST.SYST_CSR: SysTick Control and Status Register\n\tSYST_CSR_ENABLE_Pos    = 0x0     // Position of ENABLE field.\n\tSYST_CSR_ENABLE_Msk    = 0x1     // Bit mask of ENABLE field.\n\tSYST_CSR_ENABLE        = 0x1     // Bit ENABLE.\n\tSYST_CSR_TICKINT_Pos   = 0x1     // Position of TICKINT field.\n\tSYST_CSR_TICKINT_Msk   = 0x2     // Bit mask of TICKINT field.\n\tSYST_CSR_TICKINT       = 0x2     // Bit TICKINT.\n\tSYST_CSR_CLKSOURCE_Pos = 0x2     // Position of CLKSOURCE field.\n\tSYST_CSR_CLKSOURCE_Msk = 0x4     // Bit mask of CLKSOURCE field.\n\tSYST_CSR_CLKSOURCE     = 0x4     // Bit CLKSOURCE.\n\tSYST_CSR_COUNTFLAG_Pos = 0x10    // Position of COUNTFLAG field.\n\tSYST_CSR_COUNTFLAG_Msk = 0x10000 // Bit mask of COUNTFLAG field.\n\tSYST_CSR_COUNTFLAG     = 0x10000 // Bit COUNTFLAG.\n\n\t// SYST.SYST_RVR: SysTick Reload Value Register\n\tSYST_RVR_RELOAD_Pos = 0x0      // Position of RELOAD field.\n\tSYST_RVR_RELOAD_Msk = 0xffffff // Bit mask of RELOAD field.\n\n\t// SYST.SYST_CVR: SysTick Current Value Register\n\tSYST_CVR_CURRENT_Pos = 0x0      // Position of CURRENT field.\n\tSYST_CVR_CURRENT_Msk = 0xffffff // Bit mask of CURRENT field.\n\n\t// SYST.SYST_CALIB: SysTick Calibration Value Register\n\tSYST_CALIB_TENMS_Pos = 0x0        // Position of TENMS field.\n\tSYST_CALIB_TENMS_Msk = 0xffffff   // Bit mask of TENMS field.\n\tSYST_CALIB_SKEW_Pos  = 0x1e       // Position of SKEW field.\n\tSYST_CALIB_SKEW_Msk  = 0x40000000 // Bit mask of SKEW field.\n\tSYST_CALIB_SKEW      = 0x40000000 // Bit SKEW.\n\tSYST_CALIB_NOREF_Pos = 0x1f       // Position of NOREF field.\n\tSYST_CALIB_NOREF_Msk = 0x80000000 // Bit mask of NOREF field.\n\tSYST_CALIB_NOREF     = 0x80000000 // Bit NOREF.\n)\n\n// ClearPendingIRQ clears the pending status of the interrupt.\nfunc ClearPendingIRQ(irq uint32) {\n\tNVIC.ICPR[irq>>5].Set(1 << (irq & 0x1F))\n}\n\n// Enable the given interrupt number.\nfunc EnableIRQ(irq uint32) {\n\tNVIC.ISER[irq>>5].Set(1 << (irq & 0x1F))\n}\n\n// Disable the given interrupt number.\nfunc DisableIRQ(irq uint32) {\n\tNVIC.ICER[irq>>5].Set(1 << (irq & 0x1F))\n}\n\n// Set the priority of the given interrupt number.\n// Note that the priority is given as a 0-255 number, where some of the lower\n// bits are not implemented by the hardware. For example, to set a low interrupt\n// priority, use 0xc0, which is equivalent to using priority level 5 when the\n// hardware has 8 priority levels. Also note that the priority level is inverted\n// in ARM: a lower number means it is a more important interrupt and will\n// interrupt ISRs with a higher interrupt priority.\nfunc SetPriority(irq uint32, priority uint32) {\n\t// Details:\n\t// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0553a/Cihgjeed.html\n\tregnum := irq / 4\n\tregpos := irq % 4\n\tmask := uint32(0xff) << (regpos * 8) // bits to clear\n\tpriority = priority << (regpos * 8)  // bits to set\n\tNVIC.IPR[regnum].Set((uint32(NVIC.IPR[regnum].Get()) &^ mask) | priority)\n}\n\n// DisableInterrupts disables all interrupts, and returns the old interrupt\n// state.\n//\n//export DisableInterrupts\nfunc DisableInterrupts() uintptr\n\n// EnableInterrupts enables all interrupts again. The value passed in must be\n// the mask returned by DisableInterrupts.\n//\n//export EnableInterrupts\nfunc EnableInterrupts(mask uintptr)\n\n// Set up the system timer to generate periodic tick events.\n// This will cause SysTick_Handler to fire once per tick.\n// The cyclecount parameter is a counter value which can range from 0 to\n// 0xffffff.  A value of 0 disables the timer.\nfunc SetupSystemTimer(cyclecount uint32) error {\n\t// turn it off\n\tSYST.SYST_CSR.ClearBits(SYST_CSR_TICKINT | SYST_CSR_ENABLE)\n\tif cyclecount == 0 {\n\t\t// leave the system timer turned off.\n\t\treturn nil\n\t}\n\tif cyclecount&SYST_RVR_RELOAD_Msk != cyclecount {\n\t\t// The cycle refresh register is only 24 bits wide.  The user-specified value will overflow.\n\t\treturn errCycleCountTooLarge\n\t}\n\n\t// set refresh count\n\tSYST.SYST_RVR.Set(cyclecount)\n\t// set current counter value\n\tSYST.SYST_CVR.Set(cyclecount)\n\t// enable clock, enable SysTick interrupt when clock reaches 0, run it off of the processor clock\n\tSYST.SYST_CSR.SetBits(SYST_CSR_TICKINT | SYST_CSR_ENABLE | SYST_CSR_CLKSOURCE)\n\treturn nil\n}\n"
  },
  {
    "path": "src/device/arm/cortexm.S",
    "content": ".syntax unified\n.cfi_sections .debug_frame\n\n// This is a convenience function for semihosting support.\n// At some point, this should be replaced by inline assembly.\n.section .text.SemihostingCall\n.global  SemihostingCall\n.type    SemihostingCall, %function\nSemihostingCall:\n    .cfi_startproc\n    bkpt 0xab\n    bx   lr\n    .cfi_endproc\n.size SemihostingCall, .-SemihostingCall\n"
  },
  {
    "path": "src/device/arm/interrupts.c",
    "content": "#include <stdint.h>\n\nvoid EnableInterrupts(uintptr_t mask) {\n    asm volatile(\n        \"msr PRIMASK, %0\"\n        :\n        : \"r\"(mask)\n        : \"memory\"\n    );\n}\n\nuintptr_t DisableInterrupts() {\n    uintptr_t mask;\n    asm volatile(\n        \"mrs %0, PRIMASK\\n\\t\"\n        \"cpsid i\"\n        : \"=r\"(mask)\n        :\n        : \"memory\"\n    );\n\treturn mask;\n}"
  },
  {
    "path": "src/device/arm/scb.go",
    "content": "// Hand created file. DO NOT DELETE.\n// Cortex-M System Control Block-related definitions.\n\n//go:build cortexm\n\npackage arm\n\nimport (\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nconst SCB_BASE = SCS_BASE + 0x0D00\n\n// System Control Block (SCB)\n//\n// SCB_Type provides the definitions for the System Control Block Registers.\ntype SCB_Type struct {\n\tCPUID volatile.Register32 // 0xD00: CPUID Base Register\n\tICSR  volatile.Register32 // 0xD04: Interrupt Control and State Register\n\tVTOR  volatile.Register32 // 0xD08: Vector Table Offset Register\n\tAIRCR volatile.Register32 // 0xD0C: Application Interrupt and Reset Control Register\n\tSCR   volatile.Register32 // 0xD10: System Control Register\n\tCCR   volatile.Register32 // 0xD14: Configuration and Control Register\n\tSHPR1 volatile.Register32 // 0xD18: System Handler Priority Register 1 (Cortex-M3/M33/M4/M7 only)\n\tSHPR2 volatile.Register32 // 0xD1C: System Handler Priority Register 2\n\tSHPR3 volatile.Register32 // 0xD20: System Handler Priority Register 3\n\t// the following are only applicable for Cortex-M3/M33/M4/M7\n\tSHCSR volatile.Register32    // 0xD24: System Handler Control and State Register\n\tCFSR  volatile.Register32    // 0xD28: Configurable Fault Status Register\n\tHFSR  volatile.Register32    // 0xD2C: HardFault Status Register\n\tDFSR  volatile.Register32    // 0xD30: Debug Fault Status Register\n\tMMFAR volatile.Register32    // 0xD34: MemManage Fault Address Register\n\tBFAR  volatile.Register32    // 0xD38: BusFault Address Register\n\tAFSR  volatile.Register32    // 0xD3C: Auxiliary Fault Status Register\n\tPFR   [2]volatile.Register32 // 0xD40: Processor Feature Register\n\tDFR   volatile.Register32    // 0xD48: Debug Feature Register\n\tADR   volatile.Register32    // 0xD4C: Auxiliary Feature Register\n\tMMFR  [4]volatile.Register32 // 0xD50: Memory Model Feature Register\n\tISAR  [5]volatile.Register32 // 0xD60: Instruction Set Attributes Register\n\t_     [5]uint32              // reserved\n\tCPACR volatile.Register32    // 0xD88: Coprocessor Access Control Register\n\n}\n\nvar SCB = (*SCB_Type)(unsafe.Pointer(uintptr(SCB_BASE)))\n\n// SystemReset performs a hard system reset.\nfunc SystemReset() {\n\tSCB.AIRCR.Set((0x5FA << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_SYSRESETREQ_Msk)\n\tfor {\n\t\tAsm(\"wfi\")\n\t}\n}\n\nconst (\n\t// CPUID: CPUID Base Register\n\tSCB_CPUID_REVISION_Pos     = 0x0        // Position of REVISION field.\n\tSCB_CPUID_REVISION_Msk     = 0xf        // Bit mask of REVISION field.\n\tSCB_CPUID_PARTNO_Pos       = 0x4        // Position of PARTNO field.\n\tSCB_CPUID_PARTNO_Msk       = 0xfff0     // Bit mask of PARTNO field.\n\tSCB_CPUID_ARCHITECTURE_Pos = 0x10       // Position of ARCHITECTURE field.\n\tSCB_CPUID_ARCHITECTURE_Msk = 0xf0000    // Bit mask of ARCHITECTURE field.\n\tSCB_CPUID_VARIANT_Pos      = 0x14       // Position of VARIANT field.\n\tSCB_CPUID_VARIANT_Msk      = 0xf00000   // Bit mask of VARIANT field.\n\tSCB_CPUID_IMPLEMENTER_Pos  = 0x18       // Position of IMPLEMENTER field.\n\tSCB_CPUID_IMPLEMENTER_Msk  = 0xff000000 // Bit mask of IMPLEMENTER field.\n\n\t// ICSR: Interrupt Control and State Register\n\tSCB_ICSR_VECTACTIVE_Pos          = 0x0        // Position of VECTACTIVE field.\n\tSCB_ICSR_VECTACTIVE_Msk          = 0x1ff      // Bit mask of VECTACTIVE field.\n\tSCB_ICSR_RETTOBASE_Pos           = 0xb        // Position of RETTOBASE field.\n\tSCB_ICSR_RETTOBASE_Msk           = 0x800      // Bit mask of RETTOBASE field.\n\tSCB_ICSR_RETTOBASE               = 0x800      // Bit RETTOBASE.\n\tSCB_ICSR_RETTOBASE_RETTOBASE_0   = 0x0        // there are preempted active exceptions to execute\n\tSCB_ICSR_RETTOBASE_RETTOBASE_1   = 0x1        // there are no active exceptions, or the currently-executing exception is the only active exception\n\tSCB_ICSR_VECTPENDING_Pos         = 0xc        // Position of VECTPENDING field.\n\tSCB_ICSR_VECTPENDING_Msk         = 0x1ff000   // Bit mask of VECTPENDING field.\n\tSCB_ICSR_ISRPENDING_Pos          = 0x16       // Position of ISRPENDING field.\n\tSCB_ICSR_ISRPENDING_Msk          = 0x400000   // Bit mask of ISRPENDING field.\n\tSCB_ICSR_ISRPENDING              = 0x400000   // Bit ISRPENDING.\n\tSCB_ICSR_ISRPENDING_ISRPENDING_0 = 0x0        // No external interrupt pending.\n\tSCB_ICSR_ISRPENDING_ISRPENDING_1 = 0x1        // External interrupt pending.\n\tSCB_ICSR_PENDSTCLR_Pos           = 0x19       // Position of PENDSTCLR field.\n\tSCB_ICSR_PENDSTCLR_Msk           = 0x2000000  // Bit mask of PENDSTCLR field.\n\tSCB_ICSR_PENDSTCLR               = 0x2000000  // Bit PENDSTCLR.\n\tSCB_ICSR_PENDSTCLR_PENDSTCLR_0   = 0x0        // no effect\n\tSCB_ICSR_PENDSTCLR_PENDSTCLR_1   = 0x1        // removes the pending state from the SysTick exception\n\tSCB_ICSR_PENDSTSET_Pos           = 0x1a       // Position of PENDSTSET field.\n\tSCB_ICSR_PENDSTSET_Msk           = 0x4000000  // Bit mask of PENDSTSET field.\n\tSCB_ICSR_PENDSTSET               = 0x4000000  // Bit PENDSTSET.\n\tSCB_ICSR_PENDSTSET_PENDSTSET_0   = 0x0        // write: no effect; read: SysTick exception is not pending\n\tSCB_ICSR_PENDSTSET_PENDSTSET_1   = 0x1        // write: changes SysTick exception state to pending; read: SysTick exception is pending\n\tSCB_ICSR_PENDSVCLR_Pos           = 0x1b       // Position of PENDSVCLR field.\n\tSCB_ICSR_PENDSVCLR_Msk           = 0x8000000  // Bit mask of PENDSVCLR field.\n\tSCB_ICSR_PENDSVCLR               = 0x8000000  // Bit PENDSVCLR.\n\tSCB_ICSR_PENDSVCLR_PENDSVCLR_0   = 0x0        // no effect\n\tSCB_ICSR_PENDSVCLR_PENDSVCLR_1   = 0x1        // removes the pending state from the PendSV exception\n\tSCB_ICSR_PENDSVSET_Pos           = 0x1c       // Position of PENDSVSET field.\n\tSCB_ICSR_PENDSVSET_Msk           = 0x10000000 // Bit mask of PENDSVSET field.\n\tSCB_ICSR_PENDSVSET               = 0x10000000 // Bit PENDSVSET.\n\tSCB_ICSR_PENDSVSET_PENDSVSET_0   = 0x0        // write: no effect; read: PendSV exception is not pending\n\tSCB_ICSR_PENDSVSET_PENDSVSET_1   = 0x1        // write: changes PendSV exception state to pending; read: PendSV exception is pending\n\tSCB_ICSR_NMIPENDSET_Pos          = 0x1f       // Position of NMIPENDSET field.\n\tSCB_ICSR_NMIPENDSET_Msk          = 0x80000000 // Bit mask of NMIPENDSET field.\n\tSCB_ICSR_NMIPENDSET              = 0x80000000 // Bit NMIPENDSET.\n\tSCB_ICSR_NMIPENDSET_NMIPENDSET_0 = 0x0        // write: no effect; read: NMI exception is not pending\n\tSCB_ICSR_NMIPENDSET_NMIPENDSET_1 = 0x1        // write: changes NMI exception state to pending; read: NMI exception is pending\n\n\t// VTOR: Vector Table Offset Register\n\tSCB_VTOR_TBLOFF_Pos = 0x7        // Position of TBLOFF field.\n\tSCB_VTOR_TBLOFF_Msk = 0xffffff80 // Bit mask of TBLOFF field.\n\n\t// AIRCR: Application Interrupt and Reset Control Register\n\tSCB_AIRCR_VECTRESET_Pos                 = 0x0        // Position of VECTRESET field.\n\tSCB_AIRCR_VECTRESET_Msk                 = 0x1        // Bit mask of VECTRESET field.\n\tSCB_AIRCR_VECTRESET                     = 0x1        // Bit VECTRESET.\n\tSCB_AIRCR_VECTRESET_VECTRESET_0         = 0x0        // No change\n\tSCB_AIRCR_VECTRESET_VECTRESET_1         = 0x1        // Causes a local system reset\n\tSCB_AIRCR_VECTCLRACTIVE_Pos             = 0x1        // Position of VECTCLRACTIVE field.\n\tSCB_AIRCR_VECTCLRACTIVE_Msk             = 0x2        // Bit mask of VECTCLRACTIVE field.\n\tSCB_AIRCR_VECTCLRACTIVE                 = 0x2        // Bit VECTCLRACTIVE.\n\tSCB_AIRCR_VECTCLRACTIVE_VECTCLRACTIVE_0 = 0x0        // No change\n\tSCB_AIRCR_VECTCLRACTIVE_VECTCLRACTIVE_1 = 0x1        // Clears all active state information for fixed and configurable exceptions\n\tSCB_AIRCR_SYSRESETREQ_Pos               = 0x2        // Position of SYSRESETREQ field.\n\tSCB_AIRCR_SYSRESETREQ_Msk               = 0x4        // Bit mask of SYSRESETREQ field.\n\tSCB_AIRCR_SYSRESETREQ                   = 0x4        // Bit SYSRESETREQ.\n\tSCB_AIRCR_SYSRESETREQ_SYSRESETREQ_0     = 0x0        // no system reset request\n\tSCB_AIRCR_SYSRESETREQ_SYSRESETREQ_1     = 0x1        // asserts a signal to the outer system that requests a reset\n\tSCB_AIRCR_PRIGROUP_Pos                  = 0x8        // Position of PRIGROUP field.\n\tSCB_AIRCR_PRIGROUP_Msk                  = 0x700      // Bit mask of PRIGROUP field.\n\tSCB_AIRCR_ENDIANNESS_Pos                = 0xf        // Position of ENDIANNESS field.\n\tSCB_AIRCR_ENDIANNESS_Msk                = 0x8000     // Bit mask of ENDIANNESS field.\n\tSCB_AIRCR_ENDIANNESS                    = 0x8000     // Bit ENDIANNESS.\n\tSCB_AIRCR_ENDIANNESS_ENDIANNESS_0       = 0x0        // Little-endian\n\tSCB_AIRCR_ENDIANNESS_ENDIANNESS_1       = 0x1        // Big-endian\n\tSCB_AIRCR_VECTKEY_Pos                   = 0x10       // Position of VECTKEY field.\n\tSCB_AIRCR_VECTKEY_Msk                   = 0xffff0000 // Bit mask of VECTKEY field.\n\n\t// SCR: System Control Register\n\tSCB_SCR_SLEEPONEXIT_Pos           = 0x1  // Position of SLEEPONEXIT field.\n\tSCB_SCR_SLEEPONEXIT_Msk           = 0x2  // Bit mask of SLEEPONEXIT field.\n\tSCB_SCR_SLEEPONEXIT               = 0x2  // Bit SLEEPONEXIT.\n\tSCB_SCR_SLEEPONEXIT_SLEEPONEXIT_0 = 0x0  // o not sleep when returning to Thread mode\n\tSCB_SCR_SLEEPONEXIT_SLEEPONEXIT_1 = 0x1  // enter sleep, or deep sleep, on return from an ISR\n\tSCB_SCR_SLEEPDEEP_Pos             = 0x2  // Position of SLEEPDEEP field.\n\tSCB_SCR_SLEEPDEEP_Msk             = 0x4  // Bit mask of SLEEPDEEP field.\n\tSCB_SCR_SLEEPDEEP                 = 0x4  // Bit SLEEPDEEP.\n\tSCB_SCR_SLEEPDEEP_SLEEPDEEP_0     = 0x0  // sleep\n\tSCB_SCR_SLEEPDEEP_SLEEPDEEP_1     = 0x1  // deep sleep\n\tSCB_SCR_SEVONPEND_Pos             = 0x4  // Position of SEVONPEND field.\n\tSCB_SCR_SEVONPEND_Msk             = 0x10 // Bit mask of SEVONPEND field.\n\tSCB_SCR_SEVONPEND                 = 0x10 // Bit SEVONPEND.\n\tSCB_SCR_SEVONPEND_SEVONPEND_0     = 0x0  // only enabled interrupts or events can wakeup the processor, disabled interrupts are excluded\n\tSCB_SCR_SEVONPEND_SEVONPEND_1     = 0x1  // enabled events and all interrupts, including disabled interrupts, can wakeup the processor\n\n\t// CCR: Configuration and Control Register\n\tSCB_CCR_NONBASETHRDENA_Pos              = 0x0     // Position of NONBASETHRDENA field.\n\tSCB_CCR_NONBASETHRDENA_Msk              = 0x1     // Bit mask of NONBASETHRDENA field.\n\tSCB_CCR_NONBASETHRDENA                  = 0x1     // Bit NONBASETHRDENA.\n\tSCB_CCR_NONBASETHRDENA_NONBASETHRDENA_0 = 0x0     // processor can enter Thread mode only when no exception is active\n\tSCB_CCR_NONBASETHRDENA_NONBASETHRDENA_1 = 0x1     // processor can enter Thread mode from any level under the control of an EXC_RETURN value\n\tSCB_CCR_USERSETMPEND_Pos                = 0x1     // Position of USERSETMPEND field.\n\tSCB_CCR_USERSETMPEND_Msk                = 0x2     // Bit mask of USERSETMPEND field.\n\tSCB_CCR_USERSETMPEND                    = 0x2     // Bit USERSETMPEND.\n\tSCB_CCR_USERSETMPEND_USERSETMPEND_0     = 0x0     // disable\n\tSCB_CCR_USERSETMPEND_USERSETMPEND_1     = 0x1     // enable\n\tSCB_CCR_UNALIGN_TRP_Pos                 = 0x3     // Position of UNALIGN_TRP field.\n\tSCB_CCR_UNALIGN_TRP_Msk                 = 0x8     // Bit mask of UNALIGN_TRP field.\n\tSCB_CCR_UNALIGN_TRP                     = 0x8     // Bit UNALIGN_TRP.\n\tSCB_CCR_UNALIGN_TRP_UNALIGN_TRP_0       = 0x0     // do not trap unaligned halfword and word accesses\n\tSCB_CCR_UNALIGN_TRP_UNALIGN_TRP_1       = 0x1     // trap unaligned halfword and word accesses\n\tSCB_CCR_DIV_0_TRP_Pos                   = 0x4     // Position of DIV_0_TRP field.\n\tSCB_CCR_DIV_0_TRP_Msk                   = 0x10    // Bit mask of DIV_0_TRP field.\n\tSCB_CCR_DIV_0_TRP                       = 0x10    // Bit DIV_0_TRP.\n\tSCB_CCR_DIV_0_TRP_DIV_0_TRP_0           = 0x0     // do not trap divide by 0\n\tSCB_CCR_DIV_0_TRP_DIV_0_TRP_1           = 0x1     // trap divide by 0\n\tSCB_CCR_BFHFNMIGN_Pos                   = 0x8     // Position of BFHFNMIGN field.\n\tSCB_CCR_BFHFNMIGN_Msk                   = 0x100   // Bit mask of BFHFNMIGN field.\n\tSCB_CCR_BFHFNMIGN                       = 0x100   // Bit BFHFNMIGN.\n\tSCB_CCR_BFHFNMIGN_BFHFNMIGN_0           = 0x0     // data bus faults caused by load and store instructions cause a lock-up\n\tSCB_CCR_BFHFNMIGN_BFHFNMIGN_1           = 0x1     // handlers running at priority -1 and -2 ignore data bus faults caused by load and store instructions\n\tSCB_CCR_STKALIGN_Pos                    = 0x9     // Position of STKALIGN field.\n\tSCB_CCR_STKALIGN_Msk                    = 0x200   // Bit mask of STKALIGN field.\n\tSCB_CCR_STKALIGN                        = 0x200   // Bit STKALIGN.\n\tSCB_CCR_STKALIGN_STKALIGN_0             = 0x0     // 4-byte aligned\n\tSCB_CCR_STKALIGN_STKALIGN_1             = 0x1     // 8-byte aligned\n\tSCB_CCR_DC_Pos                          = 0x10    // Position of DC field.\n\tSCB_CCR_DC_Msk                          = 0x10000 // Bit mask of DC field.\n\tSCB_CCR_DC                              = 0x10000 // Bit DC.\n\tSCB_CCR_DC_DC_0                         = 0x0     // L1 data cache disabled\n\tSCB_CCR_DC_DC_1                         = 0x1     // L1 data cache enabled\n\tSCB_CCR_IC_Pos                          = 0x11    // Position of IC field.\n\tSCB_CCR_IC_Msk                          = 0x20000 // Bit mask of IC field.\n\tSCB_CCR_IC                              = 0x20000 // Bit IC.\n\tSCB_CCR_IC_IC_0                         = 0x0     // L1 instruction cache disabled\n\tSCB_CCR_IC_IC_1                         = 0x1     // L1 instruction cache enabled\n\tSCB_CCR_BP_Pos                          = 0x12    // Position of BP field.\n\tSCB_CCR_BP_Msk                          = 0x40000 // Bit mask of BP field.\n\tSCB_CCR_BP                              = 0x40000 // Bit BP.\n\n\t// SHPR1: System Handler Priority Register 1\n\tSCB_SHPR1_PRI_4_Pos = 0x0      // Position of PRI_4 field.\n\tSCB_SHPR1_PRI_4_Msk = 0xff     // Bit mask of PRI_4 field.\n\tSCB_SHPR1_PRI_5_Pos = 0x8      // Position of PRI_5 field.\n\tSCB_SHPR1_PRI_5_Msk = 0xff00   // Bit mask of PRI_5 field.\n\tSCB_SHPR1_PRI_6_Pos = 0x10     // Position of PRI_6 field.\n\tSCB_SHPR1_PRI_6_Msk = 0xff0000 // Bit mask of PRI_6 field.\n\n\t// SHPR2: System Handler Priority Register 2\n\tSCB_SHPR2_PRI_11_Pos = 0x18       // Position of PRI_11 field.\n\tSCB_SHPR2_PRI_11_Msk = 0xff000000 // Bit mask of PRI_11 field.\n\n\t// SHPR3: System Handler Priority Register 3\n\tSCB_SHPR3_PRI_14_Pos = 0x10       // Position of PRI_14 field.\n\tSCB_SHPR3_PRI_14_Msk = 0xff0000   // Bit mask of PRI_14 field.\n\tSCB_SHPR3_PRI_15_Pos = 0x18       // Position of PRI_15 field.\n\tSCB_SHPR3_PRI_15_Msk = 0xff000000 // Bit mask of PRI_15 field.\n\n\t// SHCSR: System Handler Control and State Register\n\tSCB_SHCSR_MEMFAULTACT_Pos                 = 0x0     // Position of MEMFAULTACT field.\n\tSCB_SHCSR_MEMFAULTACT_Msk                 = 0x1     // Bit mask of MEMFAULTACT field.\n\tSCB_SHCSR_MEMFAULTACT                     = 0x1     // Bit MEMFAULTACT.\n\tSCB_SHCSR_MEMFAULTACT_MEMFAULTACT_0       = 0x0     // exception is not active\n\tSCB_SHCSR_MEMFAULTACT_MEMFAULTACT_1       = 0x1     // exception is active\n\tSCB_SHCSR_BUSFAULTACT_Pos                 = 0x1     // Position of BUSFAULTACT field.\n\tSCB_SHCSR_BUSFAULTACT_Msk                 = 0x2     // Bit mask of BUSFAULTACT field.\n\tSCB_SHCSR_BUSFAULTACT                     = 0x2     // Bit BUSFAULTACT.\n\tSCB_SHCSR_BUSFAULTACT_BUSFAULTACT_0       = 0x0     // exception is not active\n\tSCB_SHCSR_BUSFAULTACT_BUSFAULTACT_1       = 0x1     // exception is active\n\tSCB_SHCSR_USGFAULTACT_Pos                 = 0x3     // Position of USGFAULTACT field.\n\tSCB_SHCSR_USGFAULTACT_Msk                 = 0x8     // Bit mask of USGFAULTACT field.\n\tSCB_SHCSR_USGFAULTACT                     = 0x8     // Bit USGFAULTACT.\n\tSCB_SHCSR_USGFAULTACT_USGFAULTACT_0       = 0x0     // exception is not active\n\tSCB_SHCSR_USGFAULTACT_USGFAULTACT_1       = 0x1     // exception is active\n\tSCB_SHCSR_SVCALLACT_Pos                   = 0x7     // Position of SVCALLACT field.\n\tSCB_SHCSR_SVCALLACT_Msk                   = 0x80    // Bit mask of SVCALLACT field.\n\tSCB_SHCSR_SVCALLACT                       = 0x80    // Bit SVCALLACT.\n\tSCB_SHCSR_SVCALLACT_SVCALLACT_0           = 0x0     // exception is not active\n\tSCB_SHCSR_SVCALLACT_SVCALLACT_1           = 0x1     // exception is active\n\tSCB_SHCSR_MONITORACT_Pos                  = 0x8     // Position of MONITORACT field.\n\tSCB_SHCSR_MONITORACT_Msk                  = 0x100   // Bit mask of MONITORACT field.\n\tSCB_SHCSR_MONITORACT                      = 0x100   // Bit MONITORACT.\n\tSCB_SHCSR_MONITORACT_MONITORACT_0         = 0x0     // exception is not active\n\tSCB_SHCSR_MONITORACT_MONITORACT_1         = 0x1     // exception is active\n\tSCB_SHCSR_PENDSVACT_Pos                   = 0xa     // Position of PENDSVACT field.\n\tSCB_SHCSR_PENDSVACT_Msk                   = 0x400   // Bit mask of PENDSVACT field.\n\tSCB_SHCSR_PENDSVACT                       = 0x400   // Bit PENDSVACT.\n\tSCB_SHCSR_PENDSVACT_PENDSVACT_0           = 0x0     // exception is not active\n\tSCB_SHCSR_PENDSVACT_PENDSVACT_1           = 0x1     // exception is active\n\tSCB_SHCSR_SYSTICKACT_Pos                  = 0xb     // Position of SYSTICKACT field.\n\tSCB_SHCSR_SYSTICKACT_Msk                  = 0x800   // Bit mask of SYSTICKACT field.\n\tSCB_SHCSR_SYSTICKACT                      = 0x800   // Bit SYSTICKACT.\n\tSCB_SHCSR_SYSTICKACT_SYSTICKACT_0         = 0x0     // exception is not active\n\tSCB_SHCSR_SYSTICKACT_SYSTICKACT_1         = 0x1     // exception is active\n\tSCB_SHCSR_USGFAULTPENDED_Pos              = 0xc     // Position of USGFAULTPENDED field.\n\tSCB_SHCSR_USGFAULTPENDED_Msk              = 0x1000  // Bit mask of USGFAULTPENDED field.\n\tSCB_SHCSR_USGFAULTPENDED                  = 0x1000  // Bit USGFAULTPENDED.\n\tSCB_SHCSR_USGFAULTPENDED_USGFAULTPENDED_0 = 0x0     // exception is not pending\n\tSCB_SHCSR_USGFAULTPENDED_USGFAULTPENDED_1 = 0x1     // exception is pending\n\tSCB_SHCSR_MEMFAULTPENDED_Pos              = 0xd     // Position of MEMFAULTPENDED field.\n\tSCB_SHCSR_MEMFAULTPENDED_Msk              = 0x2000  // Bit mask of MEMFAULTPENDED field.\n\tSCB_SHCSR_MEMFAULTPENDED                  = 0x2000  // Bit MEMFAULTPENDED.\n\tSCB_SHCSR_MEMFAULTPENDED_MEMFAULTPENDED_0 = 0x0     // exception is not pending\n\tSCB_SHCSR_MEMFAULTPENDED_MEMFAULTPENDED_1 = 0x1     // exception is pending\n\tSCB_SHCSR_BUSFAULTPENDED_Pos              = 0xe     // Position of BUSFAULTPENDED field.\n\tSCB_SHCSR_BUSFAULTPENDED_Msk              = 0x4000  // Bit mask of BUSFAULTPENDED field.\n\tSCB_SHCSR_BUSFAULTPENDED                  = 0x4000  // Bit BUSFAULTPENDED.\n\tSCB_SHCSR_BUSFAULTPENDED_BUSFAULTPENDED_0 = 0x0     // exception is not pending\n\tSCB_SHCSR_BUSFAULTPENDED_BUSFAULTPENDED_1 = 0x1     // exception is pending\n\tSCB_SHCSR_SVCALLPENDED_Pos                = 0xf     // Position of SVCALLPENDED field.\n\tSCB_SHCSR_SVCALLPENDED_Msk                = 0x8000  // Bit mask of SVCALLPENDED field.\n\tSCB_SHCSR_SVCALLPENDED                    = 0x8000  // Bit SVCALLPENDED.\n\tSCB_SHCSR_SVCALLPENDED_SVCALLPENDED_0     = 0x0     // exception is not pending\n\tSCB_SHCSR_SVCALLPENDED_SVCALLPENDED_1     = 0x1     // exception is pending\n\tSCB_SHCSR_MEMFAULTENA_Pos                 = 0x10    // Position of MEMFAULTENA field.\n\tSCB_SHCSR_MEMFAULTENA_Msk                 = 0x10000 // Bit mask of MEMFAULTENA field.\n\tSCB_SHCSR_MEMFAULTENA                     = 0x10000 // Bit MEMFAULTENA.\n\tSCB_SHCSR_MEMFAULTENA_MEMFAULTENA_0       = 0x0     // disable the exception\n\tSCB_SHCSR_MEMFAULTENA_MEMFAULTENA_1       = 0x1     // enable the exception\n\tSCB_SHCSR_BUSFAULTENA_Pos                 = 0x11    // Position of BUSFAULTENA field.\n\tSCB_SHCSR_BUSFAULTENA_Msk                 = 0x20000 // Bit mask of BUSFAULTENA field.\n\tSCB_SHCSR_BUSFAULTENA                     = 0x20000 // Bit BUSFAULTENA.\n\tSCB_SHCSR_BUSFAULTENA_BUSFAULTENA_0       = 0x0     // disable the exception\n\tSCB_SHCSR_BUSFAULTENA_BUSFAULTENA_1       = 0x1     // enable the exception\n\tSCB_SHCSR_USGFAULTENA_Pos                 = 0x12    // Position of USGFAULTENA field.\n\tSCB_SHCSR_USGFAULTENA_Msk                 = 0x40000 // Bit mask of USGFAULTENA field.\n\tSCB_SHCSR_USGFAULTENA                     = 0x40000 // Bit USGFAULTENA.\n\tSCB_SHCSR_USGFAULTENA_USGFAULTENA_0       = 0x0     // disable the exception\n\tSCB_SHCSR_USGFAULTENA_USGFAULTENA_1       = 0x1     // enable the exception\n\n\t// CFSR: Configurable Fault Status Register\n\tSCB_CFSR_IACCVIOL_Pos              = 0x0       // Position of IACCVIOL field.\n\tSCB_CFSR_IACCVIOL_Msk              = 0x1       // Bit mask of IACCVIOL field.\n\tSCB_CFSR_IACCVIOL                  = 0x1       // Bit IACCVIOL.\n\tSCB_CFSR_IACCVIOL_IACCVIOL_0       = 0x0       // no instruction access violation fault\n\tSCB_CFSR_IACCVIOL_IACCVIOL_1       = 0x1       // the processor attempted an instruction fetch from a location that does not permit execution\n\tSCB_CFSR_DACCVIOL_Pos              = 0x1       // Position of DACCVIOL field.\n\tSCB_CFSR_DACCVIOL_Msk              = 0x2       // Bit mask of DACCVIOL field.\n\tSCB_CFSR_DACCVIOL                  = 0x2       // Bit DACCVIOL.\n\tSCB_CFSR_DACCVIOL_DACCVIOL_0       = 0x0       // no data access violation fault\n\tSCB_CFSR_DACCVIOL_DACCVIOL_1       = 0x1       // the processor attempted a load or store at a location that does not permit the operation\n\tSCB_CFSR_MUNSTKERR_Pos             = 0x3       // Position of MUNSTKERR field.\n\tSCB_CFSR_MUNSTKERR_Msk             = 0x8       // Bit mask of MUNSTKERR field.\n\tSCB_CFSR_MUNSTKERR                 = 0x8       // Bit MUNSTKERR.\n\tSCB_CFSR_MUNSTKERR_MUNSTKERR_0     = 0x0       // no unstacking fault\n\tSCB_CFSR_MUNSTKERR_MUNSTKERR_1     = 0x1       // unstack for an exception return has caused one or more access violations\n\tSCB_CFSR_MSTKERR_Pos               = 0x4       // Position of MSTKERR field.\n\tSCB_CFSR_MSTKERR_Msk               = 0x10      // Bit mask of MSTKERR field.\n\tSCB_CFSR_MSTKERR                   = 0x10      // Bit MSTKERR.\n\tSCB_CFSR_MSTKERR_MSTKERR_0         = 0x0       // no stacking fault\n\tSCB_CFSR_MSTKERR_MSTKERR_1         = 0x1       // stacking for an exception entry has caused one or more access violations\n\tSCB_CFSR_MLSPERR_Pos               = 0x5       // Position of MLSPERR field.\n\tSCB_CFSR_MLSPERR_Msk               = 0x20      // Bit mask of MLSPERR field.\n\tSCB_CFSR_MLSPERR                   = 0x20      // Bit MLSPERR.\n\tSCB_CFSR_MLSPERR_MLSPERR_0         = 0x0       // No MemManage fault occurred during floating-point lazy state preservation\n\tSCB_CFSR_MLSPERR_MLSPERR_1         = 0x1       // A MemManage fault occurred during floating-point lazy state preservation\n\tSCB_CFSR_MMARVALID_Pos             = 0x7       // Position of MMARVALID field.\n\tSCB_CFSR_MMARVALID_Msk             = 0x80      // Bit mask of MMARVALID field.\n\tSCB_CFSR_MMARVALID                 = 0x80      // Bit MMARVALID.\n\tSCB_CFSR_MMARVALID_MMARVALID_0     = 0x0       // value in MMAR is not a valid fault address\n\tSCB_CFSR_MMARVALID_MMARVALID_1     = 0x1       // MMAR holds a valid fault address\n\tSCB_CFSR_IBUSERR_Pos               = 0x8       // Position of IBUSERR field.\n\tSCB_CFSR_IBUSERR_Msk               = 0x100     // Bit mask of IBUSERR field.\n\tSCB_CFSR_IBUSERR                   = 0x100     // Bit IBUSERR.\n\tSCB_CFSR_IBUSERR_IBUSERR_0         = 0x0       // no instruction bus error\n\tSCB_CFSR_IBUSERR_IBUSERR_1         = 0x1       // instruction bus error\n\tSCB_CFSR_PRECISERR_Pos             = 0x9       // Position of PRECISERR field.\n\tSCB_CFSR_PRECISERR_Msk             = 0x200     // Bit mask of PRECISERR field.\n\tSCB_CFSR_PRECISERR                 = 0x200     // Bit PRECISERR.\n\tSCB_CFSR_PRECISERR_PRECISERR_0     = 0x0       // no precise data bus error\n\tSCB_CFSR_PRECISERR_PRECISERR_1     = 0x1       // a data bus error has occurred, and the PC value stacked for the exception return points to the instruction that caused the fault\n\tSCB_CFSR_IMPRECISERR_Pos           = 0xa       // Position of IMPRECISERR field.\n\tSCB_CFSR_IMPRECISERR_Msk           = 0x400     // Bit mask of IMPRECISERR field.\n\tSCB_CFSR_IMPRECISERR               = 0x400     // Bit IMPRECISERR.\n\tSCB_CFSR_IMPRECISERR_IMPRECISERR_0 = 0x0       // no imprecise data bus error\n\tSCB_CFSR_IMPRECISERR_IMPRECISERR_1 = 0x1       // a data bus error has occurred, but the return address in the stack frame is not related to the instruction that caused the error\n\tSCB_CFSR_UNSTKERR_Pos              = 0xb       // Position of UNSTKERR field.\n\tSCB_CFSR_UNSTKERR_Msk              = 0x800     // Bit mask of UNSTKERR field.\n\tSCB_CFSR_UNSTKERR                  = 0x800     // Bit UNSTKERR.\n\tSCB_CFSR_UNSTKERR_UNSTKERR_0       = 0x0       // no unstacking fault\n\tSCB_CFSR_UNSTKERR_UNSTKERR_1       = 0x1       // unstack for an exception return has caused one or more BusFaults\n\tSCB_CFSR_STKERR_Pos                = 0xc       // Position of STKERR field.\n\tSCB_CFSR_STKERR_Msk                = 0x1000    // Bit mask of STKERR field.\n\tSCB_CFSR_STKERR                    = 0x1000    // Bit STKERR.\n\tSCB_CFSR_STKERR_STKERR_0           = 0x0       // no stacking fault\n\tSCB_CFSR_STKERR_STKERR_1           = 0x1       // stacking for an exception entry has caused one or more BusFaults\n\tSCB_CFSR_LSPERR_Pos                = 0xd       // Position of LSPERR field.\n\tSCB_CFSR_LSPERR_Msk                = 0x2000    // Bit mask of LSPERR field.\n\tSCB_CFSR_LSPERR                    = 0x2000    // Bit LSPERR.\n\tSCB_CFSR_LSPERR_LSPERR_0           = 0x0       // No bus fault occurred during floating-point lazy state preservation\n\tSCB_CFSR_LSPERR_LSPERR_1           = 0x1       // A bus fault occurred during floating-point lazy state preservation\n\tSCB_CFSR_BFARVALID_Pos             = 0xf       // Position of BFARVALID field.\n\tSCB_CFSR_BFARVALID_Msk             = 0x8000    // Bit mask of BFARVALID field.\n\tSCB_CFSR_BFARVALID                 = 0x8000    // Bit BFARVALID.\n\tSCB_CFSR_BFARVALID_BFARVALID_0     = 0x0       // value in BFAR is not a valid fault address\n\tSCB_CFSR_BFARVALID_BFARVALID_1     = 0x1       // BFAR holds a valid fault address\n\tSCB_CFSR_UNDEFINSTR_Pos            = 0x10      // Position of UNDEFINSTR field.\n\tSCB_CFSR_UNDEFINSTR_Msk            = 0x10000   // Bit mask of UNDEFINSTR field.\n\tSCB_CFSR_UNDEFINSTR                = 0x10000   // Bit UNDEFINSTR.\n\tSCB_CFSR_UNDEFINSTR_UNDEFINSTR_0   = 0x0       // no undefined instruction UsageFault\n\tSCB_CFSR_UNDEFINSTR_UNDEFINSTR_1   = 0x1       // the processor has attempted to execute an undefined instruction\n\tSCB_CFSR_INVSTATE_Pos              = 0x11      // Position of INVSTATE field.\n\tSCB_CFSR_INVSTATE_Msk              = 0x20000   // Bit mask of INVSTATE field.\n\tSCB_CFSR_INVSTATE                  = 0x20000   // Bit INVSTATE.\n\tSCB_CFSR_INVSTATE_INVSTATE_0       = 0x0       // no invalid state UsageFault\n\tSCB_CFSR_INVSTATE_INVSTATE_1       = 0x1       // the processor has attempted to execute an instruction that makes illegal use of the EPSR\n\tSCB_CFSR_INVPC_Pos                 = 0x12      // Position of INVPC field.\n\tSCB_CFSR_INVPC_Msk                 = 0x40000   // Bit mask of INVPC field.\n\tSCB_CFSR_INVPC                     = 0x40000   // Bit INVPC.\n\tSCB_CFSR_INVPC_INVPC_0             = 0x0       // no invalid PC load UsageFault\n\tSCB_CFSR_INVPC_INVPC_1             = 0x1       // the processor has attempted an illegal load of EXC_RETURN to the PC\n\tSCB_CFSR_NOCP_Pos                  = 0x13      // Position of NOCP field.\n\tSCB_CFSR_NOCP_Msk                  = 0x80000   // Bit mask of NOCP field.\n\tSCB_CFSR_NOCP                      = 0x80000   // Bit NOCP.\n\tSCB_CFSR_NOCP_NOCP_0               = 0x0       // no UsageFault caused by attempting to access a coprocessor\n\tSCB_CFSR_NOCP_NOCP_1               = 0x1       // the processor has attempted to access a coprocessor\n\tSCB_CFSR_UNALIGNED_Pos             = 0x18      // Position of UNALIGNED field.\n\tSCB_CFSR_UNALIGNED_Msk             = 0x1000000 // Bit mask of UNALIGNED field.\n\tSCB_CFSR_UNALIGNED                 = 0x1000000 // Bit UNALIGNED.\n\tSCB_CFSR_UNALIGNED_UNALIGNED_0     = 0x0       // no unaligned access fault, or unaligned access trapping not enabled\n\tSCB_CFSR_UNALIGNED_UNALIGNED_1     = 0x1       // the processor has made an unaligned memory access\n\tSCB_CFSR_DIVBYZERO_Pos             = 0x19      // Position of DIVBYZERO field.\n\tSCB_CFSR_DIVBYZERO_Msk             = 0x2000000 // Bit mask of DIVBYZERO field.\n\tSCB_CFSR_DIVBYZERO                 = 0x2000000 // Bit DIVBYZERO.\n\tSCB_CFSR_DIVBYZERO_DIVBYZERO_0     = 0x0       // no divide by zero fault, or divide by zero trapping not enabled\n\tSCB_CFSR_DIVBYZERO_DIVBYZERO_1     = 0x1       // the processor has executed an SDIV or UDIV instruction with a divisor of 0\n\n\t// HFSR: HardFault Status register\n\tSCB_HFSR_VECTTBL_Pos         = 0x1        // Position of VECTTBL field.\n\tSCB_HFSR_VECTTBL_Msk         = 0x2        // Bit mask of VECTTBL field.\n\tSCB_HFSR_VECTTBL             = 0x2        // Bit VECTTBL.\n\tSCB_HFSR_VECTTBL_VECTTBL_0   = 0x0        // no BusFault on vector table read\n\tSCB_HFSR_VECTTBL_VECTTBL_1   = 0x1        // BusFault on vector table read\n\tSCB_HFSR_FORCED_Pos          = 0x1e       // Position of FORCED field.\n\tSCB_HFSR_FORCED_Msk          = 0x40000000 // Bit mask of FORCED field.\n\tSCB_HFSR_FORCED              = 0x40000000 // Bit FORCED.\n\tSCB_HFSR_FORCED_FORCED_0     = 0x0        // no forced HardFault\n\tSCB_HFSR_FORCED_FORCED_1     = 0x1        // forced HardFault\n\tSCB_HFSR_DEBUGEVT_Pos        = 0x1f       // Position of DEBUGEVT field.\n\tSCB_HFSR_DEBUGEVT_Msk        = 0x80000000 // Bit mask of DEBUGEVT field.\n\tSCB_HFSR_DEBUGEVT            = 0x80000000 // Bit DEBUGEVT.\n\tSCB_HFSR_DEBUGEVT_DEBUGEVT_0 = 0x0        // No Debug event has occurred.\n\tSCB_HFSR_DEBUGEVT_DEBUGEVT_1 = 0x1        // Debug event has occurred. The Debug Fault Status Register has been updated.\n\n\t// DFSR: Debug Fault Status Register\n\tSCB_DFSR_HALTED_Pos          = 0x0  // Position of HALTED field.\n\tSCB_DFSR_HALTED_Msk          = 0x1  // Bit mask of HALTED field.\n\tSCB_DFSR_HALTED              = 0x1  // Bit HALTED.\n\tSCB_DFSR_HALTED_HALTED_0     = 0x0  // No active halt request debug event\n\tSCB_DFSR_HALTED_HALTED_1     = 0x1  // Halt request debug event active\n\tSCB_DFSR_BKPT_Pos            = 0x1  // Position of BKPT field.\n\tSCB_DFSR_BKPT_Msk            = 0x2  // Bit mask of BKPT field.\n\tSCB_DFSR_BKPT                = 0x2  // Bit BKPT.\n\tSCB_DFSR_BKPT_BKPT_0         = 0x0  // No current breakpoint debug event\n\tSCB_DFSR_BKPT_BKPT_1         = 0x1  // At least one current breakpoint debug event\n\tSCB_DFSR_DWTTRAP_Pos         = 0x2  // Position of DWTTRAP field.\n\tSCB_DFSR_DWTTRAP_Msk         = 0x4  // Bit mask of DWTTRAP field.\n\tSCB_DFSR_DWTTRAP             = 0x4  // Bit DWTTRAP.\n\tSCB_DFSR_DWTTRAP_DWTTRAP_0   = 0x0  // No current debug events generated by the DWT\n\tSCB_DFSR_DWTTRAP_DWTTRAP_1   = 0x1  // At least one current debug event generated by the DWT\n\tSCB_DFSR_VCATCH_Pos          = 0x3  // Position of VCATCH field.\n\tSCB_DFSR_VCATCH_Msk          = 0x8  // Bit mask of VCATCH field.\n\tSCB_DFSR_VCATCH              = 0x8  // Bit VCATCH.\n\tSCB_DFSR_VCATCH_VCATCH_0     = 0x0  // No Vector catch triggered\n\tSCB_DFSR_VCATCH_VCATCH_1     = 0x1  // Vector catch triggered\n\tSCB_DFSR_EXTERNAL_Pos        = 0x4  // Position of EXTERNAL field.\n\tSCB_DFSR_EXTERNAL_Msk        = 0x10 // Bit mask of EXTERNAL field.\n\tSCB_DFSR_EXTERNAL            = 0x10 // Bit EXTERNAL.\n\tSCB_DFSR_EXTERNAL_EXTERNAL_0 = 0x0  // No external debug request debug event\n\tSCB_DFSR_EXTERNAL_EXTERNAL_1 = 0x1  // External debug request debug event\n\n\t// MMFAR: MemManage Fault Address Register\n\tSCB_MMFAR_ADDRESS_Pos = 0x0        // Position of ADDRESS field.\n\tSCB_MMFAR_ADDRESS_Msk = 0xffffffff // Bit mask of ADDRESS field.\n\n\t// BFAR: BusFault Address Register\n\tSCB_BFAR_ADDRESS_Pos = 0x0        // Position of ADDRESS field.\n\tSCB_BFAR_ADDRESS_Msk = 0xffffffff // Bit mask of ADDRESS field.\n)\n"
  },
  {
    "path": "src/device/arm/semihosting.go",
    "content": "package arm\n\n// Semihosting commands.\n// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0471c/Bgbjhiea.html\nconst (\n\t// Regular semihosting calls\n\tSemihostingClock      = 0x10\n\tSemihostingClose      = 0x02\n\tSemihostingElapsed    = 0x30\n\tSemihostingErrno      = 0x13\n\tSemihostingFileLen    = 0x0C\n\tSemihostingGetCmdline = 0x15\n\tSemihostingHeapInfo   = 0x16\n\tSemihostingIsError    = 0x08\n\tSemihostingIsTTY      = 0x09\n\tSemihostingOpen       = 0x01\n\tSemihostingRead       = 0x06\n\tSemihostingReadByte   = 0x07\n\tSemihostingRemove     = 0x0E\n\tSemihostingRename     = 0x0F\n\tSemihostingSeek       = 0x0A\n\tSemihostingSystem     = 0x12\n\tSemihostingTickFreq   = 0x31\n\tSemihostingTime       = 0x11\n\tSemihostingTmpName    = 0x0D\n\tSemihostingWrite      = 0x05\n\tSemihostingWrite0     = 0x04\n\tSemihostingWriteByte  = 0x03\n\n\t// Angel semihosting calls\n\tSemihostingEnterSVC        = 0x17\n\tSemihostingReportException = 0x18\n)\n\n// Special codes for the Angel Semihosting interface.\n// https://www.keil.com/support/man/docs/armcc/armcc_pge1358787050566.htm\nconst (\n\t// Hardware vector reason codes\n\tSemihostingBranchThroughZero = 0x20000\n\tSemihostingUndefinedInstr    = 0x20001\n\tSemihostingSoftwareInterrupt = 0x20002\n\tSemihostingPrefetchAbort     = 0x20003\n\tSemihostingDataAbort         = 0x20004\n\tSemihostingAddressException  = 0x20005\n\tSemihostingIRQ               = 0x20006\n\tSemihostingFIQ               = 0x20007\n\n\t// Software reason codes\n\tSemihostingBreakPoint          = 0x20020\n\tSemihostingWatchPoint          = 0x20021\n\tSemihostingStepComplete        = 0x20022\n\tSemihostingRunTimeErrorUnknown = 0x20023\n\tSemihostingInternalError       = 0x20024\n\tSemihostingUserInterruption    = 0x20025\n\tSemihostingApplicationExit     = 0x20026\n\tSemihostingStackOverflow       = 0x20027\n\tSemihostingDivisionByZero      = 0x20028\n\tSemihostingOSSpecific          = 0x20029\n)\n\n// Call a semihosting function.\n// TODO: implement it here using inline assembly.\n//\n//go:linkname SemihostingCall SemihostingCall\nfunc SemihostingCall(num int, arg uintptr) int\n"
  },
  {
    "path": "src/device/arm64/arm64.go",
    "content": "package arm64\n\n// Run the given assembly code. The code will be marked as having side effects,\n// as it doesn't produce output and thus would normally be eliminated by the\n// optimizer.\nfunc Asm(asm string)\n\n// Run the given inline assembly. The code will be marked as having side\n// effects, as it would otherwise be optimized away. The inline assembly string\n// recognizes template values in the form {name}, like so:\n//\n//\tarm.AsmFull(\n//\t    \"str {value}, [{result}]\",\n//\t    map[string]interface{}{\n//\t        \"value\":  1,\n//\t        \"result\": uintptr(unsafe.Pointer(&dest)),\n//\t    })\n//\n// You can use {} in the asm string (which expands to a register) to set the\n// return value.\nfunc AsmFull(asm string, regs map[string]interface{}) uintptr\n\n// Run the following system call (SVCall) with 0 arguments.\nfunc SVCall0(num uintptr) uintptr\n\n// Run the following system call (SVCall) with 1 argument.\nfunc SVCall1(num uintptr, a1 interface{}) uintptr\n\n// Run the following system call (SVCall) with 2 arguments.\nfunc SVCall2(num uintptr, a1, a2 interface{}) uintptr\n\n// Run the following system call (SVCall) with 3 arguments.\nfunc SVCall3(num uintptr, a1, a2, a3 interface{}) uintptr\n\n// Run the following system call (SVCall) with 4 arguments.\nfunc SVCall4(num uintptr, a1, a2, a3, a4 interface{}) uintptr\n"
  },
  {
    "path": "src/device/asm.go",
    "content": "package device\n\n// Run the given assembly code. The code will be marked as having side effects,\n// as it doesn't produce output and thus would normally be eliminated by the\n// optimizer.\nfunc Asm(asm string)\n\n// Run the given inline assembly. The code will be marked as having side\n// effects, as it would otherwise be optimized away. The inline assembly string\n// recognizes template values in the form {name}, like so:\n//\n//\tarm.AsmFull(\n//\t    \"str {value}, [{result}]\",\n//\t    map[string]interface{}{\n//\t        \"value\":  1,\n//\t        \"result\": uintptr(unsafe.Pointer(&dest)),\n//\t    })\n//\n// You can use {} in the asm string (which expands to a register) to set the\n// return value.\nfunc AsmFull(asm string, regs map[string]interface{}) uintptr\n"
  },
  {
    "path": "src/device/esp/esp32.S",
    "content": "\n// The following definitions were copied from:\n// esp-idf/components/xtensa/include/xtensa/corebits.h\n#define PS_WOE_MASK                0x00040000\n#define PS_OWB_MASK                0x00000F00\n#define PS_CALLINC_MASK            0x00030000\n#define PS_WOE                     PS_WOE_MASK\n\n// Only calling it call_start_cpu0 for consistency with ESP-IDF.\n.section .text.call_start_cpu0\n1:\n    .long _stack_top\n.global call_start_cpu0\ncall_start_cpu0:\n    // We need to set the stack pointer to a different value. This is somewhat\n    // complicated in the Xtensa architecture. The code below is a modified\n    // version of the following code:\n    // https://github.com/espressif/esp-idf/blob/c77c4ccf/components/xtensa/include/xt_instr_macros.h#L47\n\n    // Disable WOE.\n    rsr.ps a2\n    movi a3, ~(PS_WOE_MASK)\n    and a2, a2, a3\n    wsr.ps a2\n    rsync\n\n    // Set WINDOWSTART to 1 << WINDOWBASE.\n    rsr.windowbase  a2\n    ssl  a2\n    movi a2, 1\n    sll  a2, a2\n    wsr.windowstart a2\n    rsync\n\n    // Load new stack pointer.\n    l32r sp, 1b\n\n    // Re-enable WOE.\n    rsr.ps a2\n    movi a3, PS_WOE\n    or a2, a2, a3\n    wsr.ps a2\n    rsync\n\n    // Enable the FPU (coprocessor 0 so the lowest bit).\n    movi a2, 1\n    wsr.cpenable a2\n    rsync\n\n    // Jump to the runtime start function written in Go.\n    call4 main\n\n.section .text.tinygo_scanCurrentStack\n.global tinygo_scanCurrentStack\ntinygo_scanCurrentStack:\n    // TODO: save callee saved registers on the stack\n    j tinygo_scanstack\n"
  },
  {
    "path": "src/device/esp/esp32c3.S",
    "content": "// This is a very minimal bootloader for the ESP32-C3. It only initializes the\n// flash and then continues with the generic RISC-V initialization code, which\n// in turn will call runtime.main.\n// It is written in assembly (and not in a higher level language) to make sure\n// it is entirely loaded into IRAM and doesn't accidentally call functions\n// stored in IROM.\n//\n// For reference, here is a nice introduction into RISC-V assembly:\n// https://www.imperialviolet.org/2016/12/31/riscv.html\n\n.section .init\n.global call_start_cpu0\n.type call_start_cpu0,@function\ncall_start_cpu0:\n    // At this point:\n    // - The ROM bootloader is finished and has jumped to here.\n    // - We're running from IRAM: both IRAM and DRAM segments have been loaded\n    //   by the ROM bootloader.\n    // - We have a usable stack (but not the one we would like to use).\n    // - No flash mappings (MMU) are set up yet.\n\n    // Reset MMU, see bootloader_reset_mmu in the ESP-IDF.\n    call Cache_Suspend_ICache\n    mv s0, a0 // autoload value\n    call Cache_Invalidate_ICache_All\n    call Cache_MMU_Init\n\n    // Set up DROM from flash.\n    // Somehow, this also sets up IROM from flash. Not sure why, but it avoids\n    // the need for another such call.\n    // C equivalent:\n    //   Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, 0x3C00_0000, 0, 64, 128, 0)\n    li a0, 0              // ext_ram: MMU_ACCESS_FLASH\n    li a1, 0x3C000000     // vaddr: address in the data bus\n    li a2, 0              // paddr: physical address in the flash chip\n    li a3, 64             // psize: always 64 (kilobytes)\n    li a4, 128            // num: pages to be set (8192K / 64K = 128)\n    li a5, 0              // fixed\n    call Cache_Dbus_MMU_Set\n\n    // Enable the flash cache.\n    mv a0, s0 // restore autoload value from Cache_Suspend_ICache call\n    call Cache_Resume_ICache\n\n    // Jump to generic RISC-V initialization, which initializes the stack\n    // pointer and globals register. It should not return.\n    // (It appears that the linker relaxes this jump and instead inserts the\n    // _start function right after here).\n    j _start\n\n.section .text.exception_vectors\n.global _vector_table\n.type _vector_table,@function\n\n_vector_table:\n\n    .option push\n    .option norvc\n\n    .rept 32\n    j handleInterruptASM            /* interrupt handler */\n    .endr\n\n    .option pop\n\n.size _vector_table, .-_vector_table\n\n"
  },
  {
    "path": "src/device/esp/esp8266.S",
    "content": "\n.section .text.tinygo_scanCurrentStack\n.global tinygo_scanCurrentStack\ntinygo_scanCurrentStack:\n    // TODO: save callee saved registers on the stack\n    j tinygo_scanstack\n"
  },
  {
    "path": "src/device/gba/gba.go",
    "content": "// Hand written file mostly derived from https://problemkaputt.de/gbatek.htm\n\n//go:build gameboyadvance\n\npackage gba\n\nimport (\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\n// Interrupt numbers.\nconst (\n\tIRQ_VBLANK  = 0\n\tIRQ_HBLANK  = 1\n\tIRQ_VCOUNT  = 2\n\tIRQ_TIMER0  = 3\n\tIRQ_TIMER1  = 4\n\tIRQ_TIMER2  = 5\n\tIRQ_TIMER3  = 6\n\tIRQ_COM     = 7\n\tIRQ_DMA0    = 8\n\tIRQ_DMA1    = 9\n\tIRQ_DMA2    = 10\n\tIRQ_DMA3    = 11\n\tIRQ_KEYPAD  = 12\n\tIRQ_GAMEPAK = 13\n)\n\n// Peripherals\nvar (\n\t// Display registers\n\tDISP = (*DISP_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x0000)))\n\n\t// Background control registers\n\tBGCNT0 = (*BGCNT_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x0008)))\n\tBGCNT1 = (*BGCNT_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x000A)))\n\tBGCNT2 = (*BGCNT_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x000C)))\n\tBGCNT3 = (*BGCNT_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x000E)))\n\n\tBG0 = (*BG_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x0010)))\n\tBG1 = (*BG_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x0014)))\n\tBG2 = (*BG_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x0018)))\n\tBG3 = (*BG_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x001C)))\n\n\tBGA2 = (*BG_AFFINE_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x0020)))\n\tBGA3 = (*BG_AFFINE_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x0030)))\n\n\tWIN = (*WIN_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x0040)))\n\n\tGRAPHICS = (*GRAPHICS_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x004C)))\n\n\t// GBA Sound Channel 1 - Tone & Sweep\n\tSOUND1 = (*SOUND1_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x0060)))\n\n\t// GBA Sound Channel 2 - Tone\n\tSOUND2 = (*SOUND2_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x0068)))\n\n\t// GBA Sound Channel 3 - Wave Output\n\tSOUND3 = (*SOUND3_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x0070)))\n\n\t// GBA Sound Channel 4 - Noise\n\tSOUND4 = (*SOUND4_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x0078)))\n\n\t// GBA Sound Control\n\tSOUND = (*SOUND_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x0080)))\n\n\tDMA0 = (*DMA_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x00B0)))\n\tDMA1 = (*DMA_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x00BC)))\n\tDMA2 = (*DMA_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x00C8)))\n\tDMA3 = (*DMA_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x00D4)))\n\n\tTM0 = (*TIMER_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x0100)))\n\tTM1 = (*TIMER_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x0104)))\n\tTM2 = (*TIMER_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x0108)))\n\tTM3 = (*TIMER_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x010C)))\n\n\t// Communication 1\n\tSIODATA32 = (*SIODATA32_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x0120)))\n\tSIOMULTI  = (*SIOMULTI_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x0120)))\n\n\tKEY = (*KEY_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x0130)))\n\n\t// Communication 2\n\tSIO = (*SIO_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x0134)))\n\n\tINTERRUPT = (*INTERRUPT_Type)(unsafe.Add(unsafe.Pointer(REG_BASE), uintptr(0x0200)))\n)\n\n// Main memory sections\nconst (\n\t// External work RAM\n\tMEM_EWRAM uintptr = 0x02000000\n\n\t// Internal work RAM\n\tMEM_IWRAM uintptr = 0x03000000\n\n\t// I/O registers\n\tMEM_IO uintptr = 0x04000000\n\n\t// Palette. Note: no 8bit write !!\n\tMEM_PAL uintptr = 0x05000000\n\n\t// Video RAM. Note: no 8bit write !!\n\tMEM_VRAM uintptr = 0x06000000\n\n\t// Object Attribute Memory (OAM) Note: no 8bit write !!\n\tMEM_OAM uintptr = 0x07000000\n\n\t// ROM. No write at all (duh)\n\tMEM_ROM uintptr = 0x08000000\n\n\t// Static RAM. 8bit write only\n\tMEM_SRAM uintptr = 0x0E000000\n)\n\n// Main section sizes\nconst (\n\tEWRAM_SIZE uintptr = 0x40000\n\tIWRAM_SIZE uintptr = 0x08000\n\tPAL_SIZE   uintptr = 0x00400\n\tVRAM_SIZE  uintptr = 0x18000\n\tOAM_SIZE   uintptr = 0x00400\n\tSRAM_SIZE  uintptr = 0x10000\n)\n\n// Sub section sizes\nconst (\n\t// BG palette size\n\tPAL_BG_SIZE = 0x00200\n\n\t// Object palette size\n\tPAL_OBJ_SIZE = 0x00200\n\n\t// Charblock size\n\tCBB_SIZE = 0x04000\n\n\t// Screenblock size\n\tSBB_SIZE = 0x00800\n\n\t// BG VRAM_MODE_0_2 size\n\tVRAM_BG_SIZE_MODE_0_2 = 0x10000\n\n\t// BG VRAM size\n\tVRAM_BG_SIZE_MODE_3_5 = 0x14000\n\n\t// Object VRAM size\n\tVRAM_OBJ_SIZE = 0x08000\n\n\t// Mode 3 buffer size\n\tM3_SIZE = 0x12C00\n\n\t// Mode 4 buffer size\n\tM4_SIZE = 0x09600\n\n\t// Mode 5 buffer size\n\tM5_SIZE = 0x0A000\n\n\t// Bitmap page size\n\tVRAM_PAGE_SIZE = 0x0A000\n)\n\n// Sub sections\nvar (\n\tREG_BASE uintptr = MEM_IO\n\n\t// Background palette address\n\tMEM_PAL_BG = MEM_PAL\n\n\t// Object palette address\n\tMEM_PAL_OBJ = MEM_PAL + PAL_BG_SIZE\n\n\t// Front page address\n\tMEM_VRAM_FRONT = MEM_VRAM\n\n\t// Back page address\n\tMEM_VRAM_BACK = MEM_VRAM + VRAM_PAGE_SIZE\n\n\t// Object VRAM address - BG Mode 0-2\n\tMEM_VRAM_OBJ_MODE0_2 = MEM_VRAM + VRAM_BG_SIZE_MODE_0_2\n\n\t// Object VRAM address - BG Mode 3-5\n\tMEM_VRAM_OBJ_MODE_3_5 = MEM_VRAM + VRAM_BG_SIZE_MODE_3_5\n)\n\n// Display registers\ntype DISP_Type struct {\n\tDISPCNT  volatile.Register16\n\t_        [2]byte\n\tDISPSTAT volatile.Register16\n\tVCOUNT   volatile.Register16\n}\n\n// Background control registers\ntype BGCNT_Type struct {\n\tCNT volatile.Register16\n}\n\n// Regular background scroll registers. (write only!)\ntype BG_Type struct {\n\tHOFS volatile.Register16\n\tVOFS volatile.Register16\n}\n\n// Affine background parameters. (write only!)\ntype BG_AFFINE_Type struct {\n\tPA volatile.Register16\n\tPB volatile.Register16\n\tPC volatile.Register16\n\tPD volatile.Register16\n\tX  volatile.Register32\n\tY  volatile.Register32\n}\n\ntype WIN_Type struct {\n\t// win0 right, left (0xLLRR)\n\tWIN0H volatile.Register16\n\n\t// win1 right, left (0xLLRR)\n\tWIN1H volatile.Register16\n\n\t// win0 bottom, top (0xTTBB)\n\tWIN0V volatile.Register16\n\n\t// win1 bottom, top (0xTTBB)\n\tWIN1V volatile.Register16\n\n\t// win0, win1 control\n\tIN volatile.Register16\n\n\t// winOut, winObj control\n\tOUT volatile.Register16\n}\n\ntype GRAPHICS_Type struct {\n\t// Mosaic control\n\tMOSAIC volatile.Register32\n\n\t// Alpha control\n\tBLDCNT volatile.Register16\n\n\t// Fade level\n\tBLDALPHA volatile.Register16\n\n\t// Blend levels\n\tBLDY volatile.Register16\n}\n\ntype SOUND1_Type struct {\n\t// Sweep register\n\tCNT_L volatile.Register16\n\n\t// Duty/Len/Envelope\n\tCNT_H volatile.Register16\n\n\t// Frequency/Control\n\tCNT_X volatile.Register16\n}\n\ntype SOUND2_Type struct {\n\t// Duty/Len/Envelope\n\tCNT_L volatile.Register16\n\n\t// not used\n\t_ volatile.Register16\n\n\t// Frequency/Control\n\tCNT_H volatile.Register16\n}\n\ntype SOUND3_Type struct {\n\t// Stop/Wave RAM select\n\tCNT_L volatile.Register16\n\n\t// Length/Volume\n\tCNT_H volatile.Register16\n\n\t// Frequency/Control\n\tCNT_X volatile.Register16\n}\n\ntype SOUND4_Type struct {\n\t// Length/Envelope\n\tCNT_L volatile.Register16\n\n\t// not used\n\t_ volatile.Register16\n\n\t// Frequency/Control\n\tCNT_H volatile.Register16\n}\n\ntype SOUND_Type struct {\n\t// Control Stereo/Volume/Enable\n\tCNT_L volatile.Register16\n\n\t// Control Mixing/DMA Control\n\tCNT_H volatile.Register16\n\n\t// Control Sound on/off\n\tCNT_X volatile.Register16\n}\n\n// DMA\ntype DMA_Type struct {\n\tSAD_L volatile.Register16\n\tSAD_H volatile.Register16\n\tDAD_L volatile.Register16\n\tDAD_H volatile.Register16\n\tCNT_L volatile.Register16\n\tCNT_H volatile.Register16\n}\n\n// TIMER\ntype TIMER_Type struct {\n\tDATA volatile.Register16\n\tCNT  volatile.Register16\n}\n\n// serial\ntype SIODATA32_Type struct {\n\tDATA32_L volatile.Register16\n\tDATA32_H volatile.Register16\n\t_        volatile.Register16\n\t_        volatile.Register16\n\tCNT      volatile.Register16\n\tDATA8    volatile.Register16\n}\n\ntype SIOMULTI_Type struct {\n\tMULTI0   volatile.Register16\n\tMULTI1   volatile.Register16\n\tMULTI2   volatile.Register16\n\tMULTI3   volatile.Register16\n\tCNT      volatile.Register16\n\tMLT_SEND volatile.Register16\n}\n\ntype SIO_Type struct {\n\tRCNT volatile.Register16\n}\n\n// Keypad registers\ntype KEY_Type struct {\n\tINPUT volatile.Register16\n\tCNT   volatile.Register16\n}\n\n// TODO: Joybus communication\n\n// Interrupt / System registers\ntype INTERRUPT_Type struct {\n\tIE      volatile.Register16\n\tIF      volatile.Register16\n\tWAITCNT volatile.Register16\n\tIME     volatile.Register16\n\tPAUSE   volatile.Register16\n}\n\n// LCD OBJ Attributes\ntype OAMOBJ_Type struct {\n\tATT0 volatile.Register16\n\tATT1 volatile.Register16\n\tATT2 volatile.Register16\n\t_    volatile.Register16\n}\n\n// OAM Rotation/Scaling Parameters\ntype OAMROT_Type struct {\n\t_  volatile.Register16\n\t_  volatile.Register16\n\t_  volatile.Register16\n\tPA volatile.Register16\n\t_  volatile.Register16\n\t_  volatile.Register16\n\t_  volatile.Register16\n\tPB volatile.Register16\n\t_  volatile.Register16\n\t_  volatile.Register16\n\t_  volatile.Register16\n\tPC volatile.Register16\n\t_  volatile.Register16\n\t_  volatile.Register16\n\t_  volatile.Register16\n\tPD volatile.Register16\n}\n\n// Constants for DISP: display\nconst (\n\t// BGMODE: background mode.\n\t// Position of BGMODE field.\n\tDISPCNT_BGMODE_Pos = 0x0\n\t// Bit mask of BGMODE field.\n\tDISPCNT_BGMODE_Msk = 0x4\n\t// BG Mode 0.\n\tDISPCNT_BGMODE_0 = 0x0\n\t// BG Mode 1.\n\tDISPCNT_BGMODE_1 = 0x1\n\t// BG Mode 2.\n\tDISPCNT_BGMODE_2 = 0x2\n\t// BG Mode 3.\n\tDISPCNT_BGMODE_3 = 0x3\n\t// BG Mode 4.\n\tDISPCNT_BGMODE_4 = 0x4\n\n\t// FRAMESELECT: frame select (mode 4 and 5 only).\n\tDISPCNT_FRAMESELECT_Pos    = 0x4\n\tDISPCNT_FRAMESELECT_FRAME0 = 0x0\n\tDISPCNT_FRAMESELECT_FRAME1 = 0x1\n\n\t// HBLANKINTERVAL: 1=Allow access to OAM during H-Blank\n\tDISPCNT_HBLANKINTERVAL_Pos     = 0x5\n\tDISPCNT_HBLANKINTERVAL_NOALLOW = 0x0\n\tDISPCNT_HBLANKINTERVAL_ALLOW   = 0x1\n\n\t// OBJCHARVRAM: (0=Two dimensional, 1=One dimensional)\n\tDISPCNT_OBJCHARVRAM_Pos = 0x6\n\tDISPCNT_OBJCHARVRAM_2D  = 0x0\n\tDISPCNT_OBJCHARVRAM_1D  = 0x1\n\n\t// FORCEDBLANK: (1=Allow FAST access to VRAM,Palette,OAM)\n\tDISPCNT_FORCEDBLANK_Pos     = 0x7\n\tDISPCNT_FORCEDBLANK_NOALLOW = 0x0\n\tDISPCNT_FORCEDBLANK_ALLOW   = 0x1\n\n\t// Screen Display BG0\n\tDISPCNT_SCREENDISPLAY_BG0_Pos     = 0x8\n\tDISPCNT_SCREENDISPLAY_BG0_ENABLE  = 0x1\n\tDISPCNT_SCREENDISPLAY_BG0_DISABLE = 0x0\n\n\t// Screen Display BG1\n\tDISPCNT_SCREENDISPLAY_BG1_Pos     = 0x9\n\tDISPCNT_SCREENDISPLAY_BG1_ENABLE  = 0x1\n\tDISPCNT_SCREENDISPLAY_BG1_DISABLE = 0x0\n\n\t// Screen Display BG2\n\tDISPCNT_SCREENDISPLAY_BG2_Pos     = 0xA\n\tDISPCNT_SCREENDISPLAY_BG2_ENABLE  = 0x1\n\tDISPCNT_SCREENDISPLAY_BG2_DISABLE = 0x0\n\n\t// Screen Display BG3\n\tDISPCNT_SCREENDISPLAY_BG3_Pos     = 0xB\n\tDISPCNT_SCREENDISPLAY_BG3_ENABLE  = 0x1\n\tDISPCNT_SCREENDISPLAY_BG3_DISABLE = 0x0\n\n\t// Screen Display OBJ\n\tDISPCNT_SCREENDISPLAY_OBJ_Pos     = 0xC\n\tDISPCNT_SCREENDISPLAY_OBJ_ENABLE  = 0x1\n\tDISPCNT_SCREENDISPLAY_OBJ_DISABLE = 0x0\n\n\t// Window 0 Display Flag (0=Off, 1=On)\n\tDISPCNT_WINDOW0_DISPLAY_Pos     = 0xD\n\tDISPCNT_WINDOW0_DISPLAY_ENABLE  = 0x1\n\tDISPCNT_WINDOW0_DISPLAY_DISABLE = 0x0\n\n\t// Window 1 Display Flag (0=Off, 1=On)\n\tDISPCNT_WINDOW1_DISPLAY_Pos     = 0xE\n\tDISPCNT_WINDOW1_DISPLAY_ENABLE  = 0x1\n\tDISPCNT_WINDOW1_DISPLAY_DISABLE = 0x0\n\n\t// OBJ Window Display Flag\n\tDISPCNT_WINDOWOBJ_DISPLAY_Pos     = 0xF\n\tDISPCNT_WINDOWOBJ_DISPLAY_ENABLE  = 0x1\n\tDISPCNT_WINDOWOBJ_DISPLAY_DISABLE = 0x0\n\n\t// DISPSTAT: display status.\n\t// V-blank\n\tDISPSTAT_VBLANK_Pos     = 0x0\n\tDISPSTAT_VBLANK_ENABLE  = 0x1\n\tDISPSTAT_VBLANK_DISABLE = 0x0\n\n\t// H-blank\n\tDISPSTAT_HBLANK_Pos     = 0x1\n\tDISPSTAT_HBLANK_ENABLE  = 0x1\n\tDISPSTAT_HBLANK_DISABLE = 0x0\n\n\t// V-counter match\n\tDISPSTAT_VCOUNTER_Pos     = 0x2\n\tDISPSTAT_VCOUNTER_MATCH   = 0x1\n\tDISPSTAT_VCOUNTER_NOMATCH = 0x0\n\n\t// V-blank IRQ\n\tDISPSTAT_VBLANK_IRQ_Pos     = 0x3\n\tDISPSTAT_VBLANK_IRQ_ENABLE  = 0x1\n\tDISPSTAT_VBLANK_IRQ_DISABLE = 0x0\n\n\t// H-blank IRQ\n\tDISPSTAT_HBLANK_IRQ_Pos     = 0x4\n\tDISPSTAT_HBLANK_IRQ_ENABLE  = 0x1\n\tDISPSTAT_HBLANK_IRQ_DISABLE = 0x0\n\n\t// V-counter IRQ\n\tDISPSTAT_VCOUNTER_IRQ_Pos     = 0x5\n\tDISPSTAT_VCOUNTER_IRQ_ENABLE  = 0x1\n\tDISPSTAT_VCOUNTER_IRQ_DISABLE = 0x0\n\n\t// V-count setting\n\tDISPSTAT_VCOUNT_SETTING_Pos = 0x8\n)\n\nconst (\n\tBGCNT_PRIORITY_Pos = 0x0\n\tBGCNT_PRIORITY_Msk = 0x3\n\n\tBGCNT_CHAR_BASE_Pos = 0x2\n\tBGCNT_CHAR_BASE_Msk = 0x3\n\n\tBGCNT_MOSAIC_Pos     = 0x6\n\tBGCNT_MOSAIC_DISABLE = 0x0\n\tBGCNT_MOSAIC_ENABLE  = 0x1\n\n\tBGCNT_COLORS_Pos = 0x7\n\tBGCNT_COLORS_16  = 0x0\n\tBGCNT_COLORS_256 = 0x1\n\n\tBGCNT_BASE_Pos = 0x8\n\tBGCNT_BASE_Msk = 0x1F\n\n\tBGCNT_OVERFLOW_Pos   = 0xD\n\tBGCNT_OVERFLOW_TRANS = 0x0\n\tBGCNT_OVERFLOW_WRAP  = 0x1\n\n\tBGCNT_SIZE_Pos = 0xE\n\tBGCNT_SIZE_Msk = 0x3\n)\n\nconst (\n\tBG_HOFS_Pos = 0x0\n\tBG_HOFS_Msk = 0x1FF\n\n\tBG_VOFS_Pos = 0x0\n\tBG_VOFS_Msk = 0x1FF\n)\n\n// Constants for TIMER\nconst (\n\t// PRESCALER: Prescaler Selection (0=F/1, 1=F/64, 2=F/256, 3=F/1024)\n\t// Position of PRESCALER field.\n\tTIMERCNT_PRESCALER_Pos = 0x0\n\t// Bit mask of PRESCALER field.\n\tTIMERCNT_PRESCALER_Msk = 0x2\n\t// 0=F/1\n\tTIMERCNT_PRESCALER_1 = 0x0\n\t// 1=F/64\n\tTIMERCNT_PRESCALER_64 = 0x1\n\t// 2=F/256\n\tTIMERCNT_PRESCALER_256 = 0x2\n\t// F/1024\n\tTIMERCNT_PRESCALER_1024 = 0x3\n\n\t// COUNTUP: Count-up Timing   (0=Normal, 1=See below)  ;Not used in TM0CNT_H\n\t// Position of COUNTUP_TIMING field.\n\tTIMERCNT_COUNTUP_TIMING_Pos     = 0x2\n\tTIMERCNT_COUNTUP_TIMING_NORMAL  = 0x0\n\tTIMERCNT_COUNTUP_TIMING_ENABLED = 0x1\n\n\tTIMERCNT_TIMER_IRQ_ENABLED_Pos = 0x06\n\tTIMERCNT_TIMER_IRQ_ENABLED     = 0x01\n\tTIMERCNT_TIMER_IRQ_DISABLED    = 0x00\n\n\tTIMERCNT_TIMER_STARTSTOP_Pos = 0x07\n\tTIMERCNT_TIMER_START         = 0x1\n\tTIMERCNT_TIMER_STOP          = 0x0\n)\n\nconst (\n\t// normal mode\n\tSIOCNT_NORMAL_SC_Pos      = 0x0\n\tSIOCNT_NORMAL_SC_INTERNAL = 0x1\n\tSIOCNT_NORMAL_SC_EXTERNAL = 0x0\n\n\tSIOCNT_NORMAL_SCSPEED_Pos  = 0x1\n\tSIOCNT_NORMAL_SCSPEED_256K = 0x0\n\tSIOCNT_NORMAL_SCSPEED_2M   = 0x1\n\n\tSIOCNT_NORMAL_SCSTATE_Pos  = 0x2\n\tSIOCNT_NORMAL_SCSTATE_LOW  = 0x0\n\tSIOCNT_NORMAL_SCSTATE_HIGH = 0x1\n\n\tSIOCNT_NORMAL_SO_INACTIVE_Pos  = 0x3\n\tSIOCNT_NORMAL_SO_INACTIVE_LOW  = 0x0\n\tSIOCNT_NORMAL_SO_INACTIVE_HIGH = 0x1\n\n\tSIOCNT_NORMAL_START_Pos    = 0x7\n\tSIOCNT_NORMAL_START_READY  = 0x0\n\tSIOCNT_NORMAL_START_ACTIVE = 0x1\n\n\tSIOCNT_NORMAL_LEN_Pos = 0xC\n\tSIOCNT_NORMAL_LEN8    = 0x0\n\tSIOCNT_NORMAL_LEN32   = 0x1\n\n\tSIOCNT_NORMAL_MODE_Pos = 0xD\n\tSIOCNT_NORMAL_MODE     = 0x0\n\n\t// multiplayer mode\n\tSIOCNT_MULTI_BR_Pos    = 0x0\n\tSIOCNT_MULTI_BR_Msk    = 0x3\n\tSIOCNT_MULTI_BR_9600   = 0x0\n\tSIOCNT_MULTI_BR_38400  = 0x1\n\tSIOCNT_MULTI_BR_57600  = 0x2\n\tSIOCNT_MULTI_BR_115200 = 0x3\n\n\tSIOCNT_MULTI_SI_Pos    = 0x2\n\tSIOCNT_MULTI_SI_PARENT = 0x0\n\tSIOCNT_MULTI_SI_CHILD  = 0x1\n\n\tSIOCNT_MULTI_SD_Pos   = 0x3\n\tSIOCNT_MULTI_SD_BAD   = 0x0\n\tSIOCNT_MULTI_SD_READY = 0x1\n\n\tSIOCNT_MULTI_ID_Pos    = 0x4\n\tSIOCNT_MULTI_ID_Msk    = 0x3\n\tSIOCNT_MULTI_ID_PARENT = 0x0\n\tSIOCNT_MULTI_ID_CHILD1 = 0x1\n\tSIOCNT_MULTI_ID_CHILD2 = 0x2\n\tSIOCNT_MULTI_ID_CHILD3 = 0x3\n\n\tSIOCNT_MULTI_ERR_Pos    = 0x6\n\tSIOCNT_MULTI_ERR_NORMAL = 0x0\n\tSIOCNT_MULTI_ERR_ERROR  = 0x1\n\n\tSIOCNT_MULTI_STARTBUSY_Pos       = 0x7\n\tSIOCNT_MULTI_STARTBUSY_INACTIVE  = 0x0\n\tSIOCNT_MULTI_STARTBUSY_STARTBUSY = 0x1\n\n\tSIOCNT_MULTI_MODE_Pos = 0xC\n\tSIOCNT_MULTI_MODE_Msk = 0x3\n\tSIOCNT_MULTI_MODE     = 0x01\n\n\t// uart mode\n\tSIOCNT_UART_BR_Pos    = 0x0\n\tSIOCNT_UART_BR_Msk    = 0x3\n\tSIOCNT_UART_BR_9600   = 0x0\n\tSIOCNT_UART_BR_38400  = 0x1\n\tSIOCNT_UART_BR_57600  = 0x2\n\tSIOCNT_UART_BR_115200 = 0x3\n\n\tSIOCNT_UART_CTS_Pos     = 0x2\n\tSIOCNT_UART_CTS_ALWAYS  = 0x0\n\tSIOCNT_UART_CTS_SENDLOW = 0x1\n\n\tSIOCNT_UART_PARITY_Pos  = 0x3\n\tSIOCNT_UART_PARITY_EVEN = 0x0\n\tSIOCNT_UART_PARITY_ODD  = 0x1\n\n\tSIOCNT_UART_SEND_Pos     = 0x4\n\tSIOCNT_UART_SEND_NOTFULL = 0x0\n\tSIOCNT_UART_SEND_FULL    = 0x1\n\n\tSIOCNT_UART_REC_Pos      = 0x5\n\tSIOCNT_UART_REC_NOTEMPTY = 0x0\n\tSIOCNT_UART_REC_EMPTY    = 0x1\n\n\tSIOCNT_UART_ERR_Pos     = 0x6\n\tSIOCNT_UART_ERR_NOERROR = 0x0\n\tSIOCNT_UART_ERR_ERROR   = 0x1\n\n\tSIOCNT_UART_DATALEN_Pos = 0x7\n\tSIOCNT_UART_DATALEN_7   = 0x0\n\tSIOCNT_UART_DATALEN_8   = 0x1\n\n\tSIOCNT_UART_FIFO_Pos     = 0x8\n\tSIOCNT_UART_FIFO_DISABLE = 0x0\n\tSIOCNT_UART_FIFO_ENABLE  = 0x1\n\n\tSIOCNT_UART_PARITY_ENABLE_Pos = 0x9\n\tSIOCNT_UART_PARITY_DISABLE    = 0x0\n\tSIOCNT_UART_PARITY_ENABLE     = 0x1\n\n\tSIOCNT_UART_SEND_ENABLE_Pos = 0xA\n\tSIOCNT_UART_SEND_DISABLE    = 0x0\n\tSIOCNT_UART_SEND_ENABLE     = 0x1\n\n\tSIOCNT_UART_REC_ENABLE_Pos = 0xB\n\tSIOCNT_UART_REC_DISABLE    = 0x0\n\tSIOCNT_UART_REC_ENABLE     = 0x1\n\n\tSIOCNT_UART_MODE_Pos = 0xC\n\tSIOCNT_UART_MODE_Msk = 0x3\n\tSIOCNT_UART_MODE     = 0x11\n\n\t// IRQs used by all\n\tSIOCNT_IRQ_Pos     = 0xE\n\tSIOCNT_IRQ_DISABLE = 0x0\n\tSIOCNT_IRQ_ENABLE  = 0x1\n)\n\nconst (\n\tSIO_RCNT_MODE_Pos    = 0xF\n\tSIO_RCNT_MODE_NORMAL = 0x0\n\tSIO_RCNT_MODE_MULTI  = 0x0\n\tSIO_RCNT_MODE_UART   = 0x0\n)\n\n// Constants for KEY\nconst (\n\t// KEYINPUT\n\tKEYINPUT_PRESSED           = 0x0\n\tKEYINPUT_RELEASED          = 0x1\n\tKEYINPUT_BUTTON_A_Pos      = 0x0\n\tKEYINPUT_BUTTON_B_Pos      = 0x1\n\tKEYINPUT_BUTTON_SELECT_Pos = 0x2\n\tKEYINPUT_BUTTON_START_Pos  = 0x3\n\tKEYINPUT_BUTTON_RIGHT_Pos  = 0x4\n\tKEYINPUT_BUTTON_LEFT_Pos   = 0x5\n\tKEYINPUT_BUTTON_UP_Pos     = 0x6\n\tKEYINPUT_BUTTON_DOWN_Pos   = 0x7\n\tKEYINPUT_BUTTON_R_Pos      = 0x8\n\tKEYINPUT_BUTTON_L_Pos      = 0x9\n\n\t// KEYCNT\n\tKEYCNT_IGNORE                = 0x0\n\tKEYCNT_SELECT                = 0x1\n\tKEYCNT_BUTTON_A_Pos          = 0x0\n\tKEYCNT_BUTTON_B_Pos          = 0x1\n\tKEYCNT_BUTTON_SELECT_Pos     = 0x2\n\tKEYCNT_BUTTON_START_Pos      = 0x3\n\tKEYCNT_BUTTON_RIGHT_Pos      = 0x4\n\tKEYCNT_BUTTON_LEFT_Pos       = 0x5\n\tKEYCNT_BUTTON_UP_Pos         = 0x6\n\tKEYCNT_BUTTON_DOWN_Pos       = 0x7\n\tKEYCNT_BUTTON_R_Pos          = 0x8\n\tKEYCNT_BUTTON_L_Pos          = 0x9\n\tKEYCNT_BUTTON_IRQ_DISABLE    = 0x0\n\tKEYCNT_BUTTON_IRQ_ENABLE     = 0x1\n\tKEYCNT_BUTTON_IRQ_ENABLE_Pos = 0xE\n\tKEYCNT_BUTTON_IRQ_COND_OR    = 0x0\n\tKEYCNT_BUTTON_IRQ_COND_AND   = 0x1\n\tKEYCNT_BUTTON_IRQ_COND_Pos   = 0xF\n)\n\n// Constants for INTERRUPT\nconst (\n\t// IE\n\tINTERRUPT_IE_ENABLED             = 0x1\n\tINTERRUPT_IE_DISABLED            = 0x0\n\tINTERRUPT_IE_VBLANK_Pos          = 0x0\n\tINTERRUPT_IE_HBLANK_Pos          = 0x1\n\tINTERRUPT_IE_VCOUNTER_MATCH_Pos  = 0x2\n\tINTERRUPT_IE_TIMER0_OVERFLOW_Pos = 0x3\n\tINTERRUPT_IE_TIMER1_OVERFLOW_Pos = 0x4\n\tINTERRUPT_IE_TIMER2_OVERFLOW_Pos = 0x5\n\tINTERRUPT_IE_TIMER3_OVERFLOW_Pos = 0x6\n\tINTERRUPT_IE_SERIAL_Pos          = 0x7\n\tINTERRUPT_IE_DMA0_Pos            = 0x8\n\tINTERRUPT_IE_DMA1_Pos            = 0x9\n\tINTERRUPT_IE_DMA2_Pos            = 0xA\n\tINTERRUPT_IE_DMA3_Pos            = 0xB\n\tINTERRUPT_IE_KEYPAD_Pos          = 0xC\n\tINTERRUPT_IE_GAMPAK_Pos          = 0xD\n\n\t// IF\n\tINTERRUPT_IF_ENABLED             = 0x1\n\tINTERRUPT_IF_DISABLED            = 0x0\n\tINTERRUPT_IF_VBLANK_Pos          = 0x0\n\tINTERRUPT_IF_HBLANK_Pos          = 0x1\n\tINTERRUPT_IF_VCOUNTER_MATCH_Pos  = 0x2\n\tINTERRUPT_IF_TIMER0_OVERFLOW_Pos = 0x3\n\tINTERRUPT_IF_TIMER1_OVERFLOW_Pos = 0x4\n\tINTERRUPT_IF_TIMER2_OVERFLOW_Pos = 0x5\n\tINTERRUPT_IF_TIMER3_OVERFLOW_Pos = 0x6\n\tINTERRUPT_IF_SERIAL_Pos          = 0x7\n\tINTERRUPT_IF_DMA0_Pos            = 0x8\n\tINTERRUPT_IF_DMA1_Pos            = 0x9\n\tINTERRUPT_IF_DMA2_Pos            = 0xA\n\tINTERRUPT_IF_DMA3_Pos            = 0xB\n\tINTERRUPT_IF_KEYPAD_Pos          = 0xC\n\tINTERRUPT_IF_GAMPAK_Pos          = 0xD\n)\n\nconst (\n\tOAMOBJ_ATT0_Y_Pos = 0x0\n\tOAMOBJ_ATT0_Y_Msk = 0xFF\n\n\tOAMOBJ_ATT0_OM_Pos  = 0x8\n\tOAMOBJ_ATT0_OM_Msk  = 0x3\n\tOAMOBJ_ATT0_OM_REG  = 0x0\n\tOAMOBJ_ATT0_OM_AFF  = 0x1\n\tOAMOBJ_ATT0_OM_HIDE = 0x2\n\tOAMOBJ_ATT0_OM_DBL  = 0x3\n\n\tOAMOBJ_ATT0_GM_Pos   = 0xA\n\tOAMOBJ_ATT0_GM_Msk   = 0x3\n\tOAMOBJ_ATT0_GM_REG   = 0x0\n\tOAMOBJ_ATT0_GM_BLEND = 0x1\n\tOAMOBJ_ATT0_GM_WIN   = 0x2\n\n\tOAMOBJ_ATT0_MOSAIC_Pos     = 0xC\n\tOAMOBJ_ATT0_MOSAIC_DISABLE = 0x0\n\tOAMOBJ_ATT0_MOSAIC_ENABLE  = 0x1\n\n\tOAMOBJ_ATT0_COLOR_Pos  = 0xD\n\tOAMOBJ_ATT0_COLOR_4BPP = 0x0\n\tOAMOBJ_ATT0_COLOR_8BPP = 0x1\n\n\tOAMOBJ_ATT0_SH_Pos    = 0xE\n\tOAMOBJ_ATT0_SH_Msk    = 0x3\n\tOAMOBJ_ATT0_SH_SQUARE = 0x0\n\tOAMOBJ_ATT0_SH_WIDE   = 0x1\n\tOAMOBJ_ATT0_SH_TALL   = 0x2\n\n\tOAMOBJ_ATT1_X_Pos = 0x0\n\tOAMOBJ_ATT1_X_Msk = 0xFF\n\n\tOAMOBJ_ATT1_AID_Pos = 0x9\n\tOAMOBJ_ATT1_AID_Msk = 0x1F\n\n\tOAMOBJ_ATT1_HF_Pos    = 0xC\n\tOAMOBJ_ATT1_HF_NOFLIP = 0x0\n\tOAMOBJ_ATT1_HF_FLIP   = 0x1\n\n\tOAMOBJ_ATT1_VF_Pos    = 0xD\n\tOAMOBJ_ATT1_VF_NOFLIP = 0x0\n\tOAMOBJ_ATT1_VF_FLIP   = 0x1\n\n\tOAMOBJ_ATT1_SZ_Pos = 0xE\n\tOAMOBJ_ATT1_SZ_Msk = 0x3\n\n\tOAMOBJ_ATT2_TID_Pos = 0x0\n\tOAMOBJ_ATT2_TID_Msk = 0xFF\n\n\tOAMOBJ_ATT2_PR_Pos = 0xA\n\tOAMOBJ_ATT2_PR_Msk = 0x3\n\n\tOAMOBJ_ATT2_PB_Pos = 0xC\n\tOAMOBJ_ATT2_PB_Msk = 0xF\n)\n"
  },
  {
    "path": "src/device/nrf/README.markdown",
    "content": "# Generated Go files for Nordic Semiconductors devices\n\nIn this directory, Go register description files are stored that are generated\nby `gen-device.py` from .svd files provided by Nordic. See the SVD files [over\nhere](https://github.com/NordicSemiconductor/nrfx/tree/master/mdk).\n\nThe original files are provided under the 3-clause BSD license, see [this\npost](https://devzone.nordicsemi.com/b/blog/posts/introducing-nordics-new-software-licensing-schemes)\nfor details. As the generated files transform most of the original file, I think\nthey should be licensed under the same license as the original files. Generated\nfiles will contain the license statement that is included in the original SVD\nfiles.\n"
  },
  {
    "path": "src/device/riscv/csr.go",
    "content": "package riscv\n\n// This file lists constants for CSR operations and defines methods on CSRs that\n// are implemented as compiler intrinsics.\n\n// CSR constants are used for use in CSR (Control and Status Register) compiler\n// intrinsics.\ntype CSR int16\n\n// Get returns the value of the given CSR.\nfunc (csr CSR) Get() uintptr\n\n// Set stores a new value in the given CSR.\nfunc (csr CSR) Set(uintptr)\n\n// SetBits atomically sets the given bits in this ISR and returns the old value.\nfunc (csr CSR) SetBits(uintptr) uintptr\n\n// ClearBits atomically clears the given bits in this ISR and returns the old\n// value.\nfunc (csr CSR) ClearBits(uintptr) uintptr\n\n// CSR values defined in the RISC-V privileged specification. Not all values may\n// be available on any given chip.\n//\n// Source: https://github.com/riscv/riscv-isa-manual/blob/riscv-priv-1.10/src/priv-csrs.tex\nconst (\n\t// User Trap Setup\n\tUSTATUS CSR = 0x000 // User status register.\n\tUIE     CSR = 0x004 // User interrupt-enable register.\n\tUTVEC   CSR = 0x005 // User trap handler base address.\n\n\t// User Trap Handling\n\tUSCRATCH CSR = 0x040 // Scratch register for user trap handlers.\n\tUEPC     CSR = 0x041 // User exception program counter.\n\tUCAUSE   CSR = 0x042 // User trap cause.\n\tUTVAL    CSR = 0x043 // User bad address or instruction.\n\tUIP      CSR = 0x044 // User interrupt pending.\n\n\t// User Floating-Point CSRs\n\tFFLAGS CSR = 0x001 // Floating-Point Accrued Exceptions.\n\tFRM    CSR = 0x002 // Floating-Point Dynamic Rounding Mode.\n\tFCSR   CSR = 0x003 // Floating-Point Control and Status\n\n\t// User Counter/Timers\n\tCYCLE         CSR = 0xC00 // Cycle counter for RDCYCLE instruction.\n\tTIME          CSR = 0xC01 // Timer for RDTIME instruction.\n\tINSTRET       CSR = 0xC02 // Instructions-retired counter for RDINSTRET instruction.\n\tHPMCOUNTER3   CSR = 0xC03 // Performance-monitoring counter 3.\n\tHPMCOUNTER4   CSR = 0xC04 // Performance-monitoring counter 4.\n\tHPMCOUNTER5   CSR = 0xC05 // Performance-monitoring counter 5.\n\tHPMCOUNTER6   CSR = 0xC06 // Performance-monitoring counter 6.\n\tHPMCOUNTER7   CSR = 0xC07 // Performance-monitoring counter 7.\n\tHPMCOUNTER8   CSR = 0xC08 // Performance-monitoring counter 8.\n\tHPMCOUNTER9   CSR = 0xC09 // Performance-monitoring counter 9.\n\tHPMCOUNTER10  CSR = 0xC0A // Performance-monitoring counter 10.\n\tHPMCOUNTER11  CSR = 0xC0B // Performance-monitoring counter 11.\n\tHPMCOUNTER12  CSR = 0xC0C // Performance-monitoring counter 12.\n\tHPMCOUNTER13  CSR = 0xC0D // Performance-monitoring counter 13.\n\tHPMCOUNTER14  CSR = 0xC0E // Performance-monitoring counter 14.\n\tHPMCOUNTER15  CSR = 0xC0F // Performance-monitoring counter 15.\n\tHPMCOUNTER16  CSR = 0xC10 // Performance-monitoring counter 16.\n\tHPMCOUNTER17  CSR = 0xC11 // Performance-monitoring counter 17.\n\tHPMCOUNTER18  CSR = 0xC12 // Performance-monitoring counter 18.\n\tHPMCOUNTER19  CSR = 0xC13 // Performance-monitoring counter 19.\n\tHPMCOUNTER20  CSR = 0xC14 // Performance-monitoring counter 20.\n\tHPMCOUNTER21  CSR = 0xC15 // Performance-monitoring counter 21.\n\tHPMCOUNTER22  CSR = 0xC16 // Performance-monitoring counter 22.\n\tHPMCOUNTER23  CSR = 0xC17 // Performance-monitoring counter 23.\n\tHPMCOUNTER24  CSR = 0xC18 // Performance-monitoring counter 24.\n\tHPMCOUNTER25  CSR = 0xC19 // Performance-monitoring counter 25.\n\tHPMCOUNTER26  CSR = 0xC1A // Performance-monitoring counter 26.\n\tHPMCOUNTER27  CSR = 0xC1B // Performance-monitoring counter 27.\n\tHPMCOUNTER28  CSR = 0xC1C // Performance-monitoring counter 28.\n\tHPMCOUNTER29  CSR = 0xC1D // Performance-monitoring counter 29.\n\tHPMCOUNTER30  CSR = 0xC1E // Performance-monitoring counter 30.\n\tHPMCOUNTER31  CSR = 0xC1F // Performance-monitoring counter 31.\n\tCYCLEH        CSR = 0xC80 // Upper 32 bits of CYCLE, RV32I only.\n\tTIMEH         CSR = 0xC81 // Upper 32 bits of TIME, RV32I only.\n\tINSTRETH      CSR = 0xC82 // Upper 32 bits of INSTRET, RV32I only.\n\tHPMCOUNTER3H  CSR = 0xC83 // Upper 32 bits of HPMCOUNTER3, RV32I only.\n\tHPMCOUNTER4H  CSR = 0xC84 // Upper 32 bits of HPMCOUNTER4, RV32I only.\n\tHPMCOUNTER5H  CSR = 0xC85 // Upper 32 bits of HPMCOUNTER5, RV32I only.\n\tHPMCOUNTER6H  CSR = 0xC86 // Upper 32 bits of HPMCOUNTER6, RV32I only.\n\tHPMCOUNTER7H  CSR = 0xC87 // Upper 32 bits of HPMCOUNTER7, RV32I only.\n\tHPMCOUNTER8H  CSR = 0xC88 // Upper 32 bits of HPMCOUNTER8, RV32I only.\n\tHPMCOUNTER9H  CSR = 0xC89 // Upper 32 bits of HPMCOUNTER9, RV32I only.\n\tHPMCOUNTER10H CSR = 0xC8A // Upper 32 bits of HPMCOUNTER10, RV32I only.\n\tHPMCOUNTER11H CSR = 0xC8B // Upper 32 bits of HPMCOUNTER11, RV32I only.\n\tHPMCOUNTER12H CSR = 0xC8C // Upper 32 bits of HPMCOUNTER12, RV32I only.\n\tHPMCOUNTER13H CSR = 0xC8D // Upper 32 bits of HPMCOUNTER13, RV32I only.\n\tHPMCOUNTER14H CSR = 0xC8E // Upper 32 bits of HPMCOUNTER14, RV32I only.\n\tHPMCOUNTER15H CSR = 0xC8F // Upper 32 bits of HPMCOUNTER15, RV32I only.\n\tHPMCOUNTER16H CSR = 0xC90 // Upper 32 bits of HPMCOUNTER16, RV32I only.\n\tHPMCOUNTER17H CSR = 0xC91 // Upper 32 bits of HPMCOUNTER17, RV32I only.\n\tHPMCOUNTER18H CSR = 0xC92 // Upper 32 bits of HPMCOUNTER18, RV32I only.\n\tHPMCOUNTER19H CSR = 0xC93 // Upper 32 bits of HPMCOUNTER19, RV32I only.\n\tHPMCOUNTER20H CSR = 0xC94 // Upper 32 bits of HPMCOUNTER20, RV32I only.\n\tHPMCOUNTER21H CSR = 0xC95 // Upper 32 bits of HPMCOUNTER21, RV32I only.\n\tHPMCOUNTER22H CSR = 0xC96 // Upper 32 bits of HPMCOUNTER22, RV32I only.\n\tHPMCOUNTER23H CSR = 0xC97 // Upper 32 bits of HPMCOUNTER23, RV32I only.\n\tHPMCOUNTER24H CSR = 0xC98 // Upper 32 bits of HPMCOUNTER24, RV32I only.\n\tHPMCOUNTER25H CSR = 0xC99 // Upper 32 bits of HPMCOUNTER25, RV32I only.\n\tHPMCOUNTER26H CSR = 0xC9A // Upper 32 bits of HPMCOUNTER26, RV32I only.\n\tHPMCOUNTER27H CSR = 0xC9B // Upper 32 bits of HPMCOUNTER27, RV32I only.\n\tHPMCOUNTER28H CSR = 0xC9C // Upper 32 bits of HPMCOUNTER28, RV32I only.\n\tHPMCOUNTER29H CSR = 0xC9D // Upper 32 bits of HPMCOUNTER29, RV32I only.\n\tHPMCOUNTER30H CSR = 0xC9E // Upper 32 bits of HPMCOUNTER30, RV32I only.\n\tHPMCOUNTER31H CSR = 0xC9F // Upper 32 bits of HPMCOUNTER31, RV32I only.\n\n\t// Supervisor Trap Setup\n\tSSTATUS    CSR = 0x100 // Supervisor status register.\n\tSEDELEG    CSR = 0x102 // Supervisor exception delegation register.\n\tSIDELEG    CSR = 0x103 // Supervisor interrupt delegation register.\n\tSIE        CSR = 0x104 // Supervisor interrupt-enable register.\n\tSTVEC      CSR = 0x105 // Supervisor trap handler base address.\n\tSCOUNTEREN CSR = 0x106 // Supervisor counter enable.\n\n\t// Supervisor Trap Handling\n\tSSCRATCH CSR = 0x140 // Scratch register for supervisor trap handlers.\n\tSEPC     CSR = 0x141 // Supervisor exception program counter.\n\tSCAUSE   CSR = 0x142 // Supervisor trap cause.\n\tSTVAL    CSR = 0x143 // Supervisor bad address or instruction.\n\tSIP      CSR = 0x144 // Supervisor interrupt pending.\n\n\t// Supervisor Protection and Translation\n\tSATP CSR = 0x180 // Supervisor address translation and protection.\n\n\t// Machine Information Registers\n\tMVENDORID CSR = 0xF11 // Vendor ID.\n\tMARCHID   CSR = 0xF12 // Architecture ID.\n\tMIMPID    CSR = 0xF13 // Implementation ID.\n\tMHARTID   CSR = 0xF14 // Hardware thread ID.\n\n\t// Machine Trap Setup\n\tMSTATUS    CSR = 0x300 // Machine status register.\n\tMISA       CSR = 0x301 // ISA and extensions\n\tMEDELEG    CSR = 0x302 // Machine exception delegation register.\n\tMIDELEG    CSR = 0x303 // Machine interrupt delegation register.\n\tMIE        CSR = 0x304 // Machine interrupt-enable register.\n\tMTVEC      CSR = 0x305 // Machine trap-handler base address.\n\tMCOUNTEREN CSR = 0x306 // Machine counter enable.\n\n\t// Machine Trap Handling\n\tMSCRATCH CSR = 0x340 // Scratch register for machine trap handlers.\n\tMEPC     CSR = 0x341 // Machine exception program counter.\n\tMCAUSE   CSR = 0x342 // Machine trap cause.\n\tMTVAL    CSR = 0x343 // Machine bad address or instruction.\n\tMIP      CSR = 0x344 // Machine interrupt pending.\n\n\t// Machine Protection and Translation\n\tPMPCFG0   CSR = 0x3A0 // Physical memory protection configuration.\n\tPMPCFG1   CSR = 0x3A1 // Physical memory protection configuration, RV32 only.\n\tPMPCFG2   CSR = 0x3A2 // Physical memory protection configuration.\n\tPMPCFG3   CSR = 0x3A3 // Physical memory protection configuration, RV32 only.\n\tPMPADDR0  CSR = 0x3B0 // Physical memory protection address register 0.\n\tPMPADDR1  CSR = 0x3B1 // Physical memory protection address register 1.\n\tPMPADDR2  CSR = 0x3B2 // Physical memory protection address register 2.\n\tPMPADDR3  CSR = 0x3B3 // Physical memory protection address register 3.\n\tPMPADDR4  CSR = 0x3B4 // Physical memory protection address register 4.\n\tPMPADDR5  CSR = 0x3B5 // Physical memory protection address register 5.\n\tPMPADDR6  CSR = 0x3B6 // Physical memory protection address register 6.\n\tPMPADDR7  CSR = 0x3B7 // Physical memory protection address register 7.\n\tPMPADDR8  CSR = 0x3B8 // Physical memory protection address register 8.\n\tPMPADDR9  CSR = 0x3B9 // Physical memory protection address register 9.\n\tPMPADDR10 CSR = 0x3BA // Physical memory protection address register 10.\n\tPMPADDR11 CSR = 0x3BB // Physical memory protection address register 11.\n\tPMPADDR12 CSR = 0x3BC // Physical memory protection address register 12.\n\tPMPADDR13 CSR = 0x3BD // Physical memory protection address register 13.\n\tPMPADDR14 CSR = 0x3BE // Physical memory protection address register 14.\n\tPMPADDR15 CSR = 0x3BF // Physical memory protection address register 15.\n\n\t// Machine Counter/Timers\n\tmcycle         CSR = 0xB00 // Machine cycle counter.\n\tminstret       CSR = 0xB02 // Machine instructions-retired counter.\n\tMHPMCOUNTER3   CSR = 0xB03 // Machine performance-monitoring counter 3.\n\tMHPMCOUNTER4   CSR = 0xB04 // Machine performance-monitoring counter 4.\n\tMHPMCOUNTER5   CSR = 0xB05 // Machine performance-monitoring counter 5.\n\tMHPMCOUNTER6   CSR = 0xB06 // Machine performance-monitoring counter 6.\n\tMHPMCOUNTER7   CSR = 0xB07 // Machine performance-monitoring counter 7.\n\tMHPMCOUNTER8   CSR = 0xB08 // Machine performance-monitoring counter 8.\n\tMHPMCOUNTER9   CSR = 0xB09 // Machine performance-monitoring counter 9.\n\tMHPMCOUNTER10  CSR = 0xB0A // Machine performance-monitoring counter 10.\n\tMHPMCOUNTER11  CSR = 0xB0B // Machine performance-monitoring counter 11.\n\tMHPMCOUNTER12  CSR = 0xB0C // Machine performance-monitoring counter 12.\n\tMHPMCOUNTER13  CSR = 0xB0D // Machine performance-monitoring counter 13.\n\tMHPMCOUNTER14  CSR = 0xB0E // Machine performance-monitoring counter 14.\n\tMHPMCOUNTER15  CSR = 0xB0F // Machine performance-monitoring counter 15.\n\tMHPMCOUNTER16  CSR = 0xB10 // Machine performance-monitoring counter 16.\n\tMHPMCOUNTER17  CSR = 0xB11 // Machine performance-monitoring counter 17.\n\tMHPMCOUNTER18  CSR = 0xB12 // Machine performance-monitoring counter 18.\n\tMHPMCOUNTER19  CSR = 0xB13 // Machine performance-monitoring counter 19.\n\tMHPMCOUNTER20  CSR = 0xB14 // Machine performance-monitoring counter 20.\n\tMHPMCOUNTER21  CSR = 0xB15 // Machine performance-monitoring counter 21.\n\tMHPMCOUNTER22  CSR = 0xB16 // Machine performance-monitoring counter 22.\n\tMHPMCOUNTER23  CSR = 0xB17 // Machine performance-monitoring counter 23.\n\tMHPMCOUNTER24  CSR = 0xB18 // Machine performance-monitoring counter 24.\n\tMHPMCOUNTER25  CSR = 0xB19 // Machine performance-monitoring counter 25.\n\tMHPMCOUNTER26  CSR = 0xB1A // Machine performance-monitoring counter 26.\n\tMHPMCOUNTER27  CSR = 0xB1B // Machine performance-monitoring counter 27.\n\tMHPMCOUNTER28  CSR = 0xB1C // Machine performance-monitoring counter 28.\n\tMHPMCOUNTER29  CSR = 0xB1D // Machine performance-monitoring counter 29.\n\tMHPMCOUNTER30  CSR = 0xB1E // Machine performance-monitoring counter 30.\n\tMHPMCOUNTER31  CSR = 0xB1F // Machine performance-monitoring counter 31.\n\tMCYCLEH        CSR = 0xB80 // Upper 32 bits of MCYCLE, RV32I only.\n\tMINSTRETH      CSR = 0xB82 // Upper 32 bits of MINSTRET, RV32I only.\n\tMHPMCOUNTER3H  CSR = 0xB83 // Upper 32 bits of MHPMCOUNTER3, RV32I only.\n\tMHPMCOUNTER4H  CSR = 0xB84 // Upper 32 bits of MHPMCOUNTER4, RV32I only.\n\tMHPMCOUNTER5H  CSR = 0xB85 // Upper 32 bits of MHPMCOUNTER5, RV32I only.\n\tMHPMCOUNTER6H  CSR = 0xB86 // Upper 32 bits of MHPMCOUNTER6, RV32I only.\n\tMHPMCOUNTER7H  CSR = 0xB87 // Upper 32 bits of MHPMCOUNTER7, RV32I only.\n\tMHPMCOUNTER8H  CSR = 0xB88 // Upper 32 bits of MHPMCOUNTER8, RV32I only.\n\tMHPMCOUNTER9H  CSR = 0xB89 // Upper 32 bits of MHPMCOUNTER9, RV32I only.\n\tMHPMCOUNTER10H CSR = 0xB8A // Upper 32 bits of MHPMCOUNTER10, RV32I only.\n\tMHPMCOUNTER11H CSR = 0xB8B // Upper 32 bits of MHPMCOUNTER11, RV32I only.\n\tMHPMCOUNTER12H CSR = 0xB8C // Upper 32 bits of MHPMCOUNTER12, RV32I only.\n\tMHPMCOUNTER13H CSR = 0xB8D // Upper 32 bits of MHPMCOUNTER13, RV32I only.\n\tMHPMCOUNTER14H CSR = 0xB8E // Upper 32 bits of MHPMCOUNTER14, RV32I only.\n\tMHPMCOUNTER15H CSR = 0xB8F // Upper 32 bits of MHPMCOUNTER15, RV32I only.\n\tMHPMCOUNTER16H CSR = 0xB90 // Upper 32 bits of MHPMCOUNTER16, RV32I only.\n\tMHPMCOUNTER17H CSR = 0xB91 // Upper 32 bits of MHPMCOUNTER17, RV32I only.\n\tMHPMCOUNTER18H CSR = 0xB92 // Upper 32 bits of MHPMCOUNTER18, RV32I only.\n\tMHPMCOUNTER19H CSR = 0xB93 // Upper 32 bits of MHPMCOUNTER19, RV32I only.\n\tMHPMCOUNTER20H CSR = 0xB94 // Upper 32 bits of MHPMCOUNTER20, RV32I only.\n\tMHPMCOUNTER21H CSR = 0xB95 // Upper 32 bits of MHPMCOUNTER21, RV32I only.\n\tMHPMCOUNTER22H CSR = 0xB96 // Upper 32 bits of MHPMCOUNTER22, RV32I only.\n\tMHPMCOUNTER23H CSR = 0xB97 // Upper 32 bits of MHPMCOUNTER23, RV32I only.\n\tMHPMCOUNTER24H CSR = 0xB98 // Upper 32 bits of MHPMCOUNTER24, RV32I only.\n\tMHPMCOUNTER25H CSR = 0xB99 // Upper 32 bits of MHPMCOUNTER25, RV32I only.\n\tMHPMCOUNTER26H CSR = 0xB9A // Upper 32 bits of MHPMCOUNTER26, RV32I only.\n\tMHPMCOUNTER27H CSR = 0xB9B // Upper 32 bits of MHPMCOUNTER27, RV32I only.\n\tMHPMCOUNTER28H CSR = 0xB9C // Upper 32 bits of MHPMCOUNTER28, RV32I only.\n\tMHPMCOUNTER29H CSR = 0xB9D // Upper 32 bits of MHPMCOUNTER29, RV32I only.\n\tMHPMCOUNTER30H CSR = 0xB9E // Upper 32 bits of MHPMCOUNTER30, RV32I only.\n\tMHPMCOUNTER31H CSR = 0xB9F // Upper 32 bits of MHPMCOUNTER31, RV32I only.\n\n\t// Machine Counter Setup\n\tMHPMEVENT4  CSR = 0x324 // Machine performance-monitoring event selector 4.\n\tMHPMEVENT5  CSR = 0x325 // Machine performance-monitoring event selector 5.\n\tMHPMEVENT6  CSR = 0x326 // Machine performance-monitoring event selector 6.\n\tMHPMEVENT7  CSR = 0x327 // Machine performance-monitoring event selector 7.\n\tMHPMEVENT8  CSR = 0x328 // Machine performance-monitoring event selector 8.\n\tMHPMEVENT9  CSR = 0x329 // Machine performance-monitoring event selector 9.\n\tMHPMEVENT10 CSR = 0x32A // Machine performance-monitoring event selector 10.\n\tMHPMEVENT11 CSR = 0x32B // Machine performance-monitoring event selector 11.\n\tMHPMEVENT12 CSR = 0x32C // Machine performance-monitoring event selector 12.\n\tMHPMEVENT13 CSR = 0x32D // Machine performance-monitoring event selector 13.\n\tMHPMEVENT14 CSR = 0x32E // Machine performance-monitoring event selector 14.\n\tMHPMEVENT15 CSR = 0x32F // Machine performance-monitoring event selector 15.\n\tMHPMEVENT16 CSR = 0x330 // Machine performance-monitoring event selector 16.\n\tMHPMEVENT17 CSR = 0x331 // Machine performance-monitoring event selector 17.\n\tMHPMEVENT18 CSR = 0x332 // Machine performance-monitoring event selector 18.\n\tMHPMEVENT19 CSR = 0x333 // Machine performance-monitoring event selector 19.\n\tMHPMEVENT20 CSR = 0x334 // Machine performance-monitoring event selector 20.\n\tMHPMEVENT21 CSR = 0x335 // Machine performance-monitoring event selector 21.\n\tMHPMEVENT22 CSR = 0x336 // Machine performance-monitoring event selector 22.\n\tMHPMEVENT23 CSR = 0x337 // Machine performance-monitoring event selector 23.\n\tMHPMEVENT24 CSR = 0x338 // Machine performance-monitoring event selector 24.\n\tMHPMEVENT25 CSR = 0x339 // Machine performance-monitoring event selector 25.\n\tMHPMEVENT26 CSR = 0x33A // Machine performance-monitoring event selector 26.\n\tMHPMEVENT27 CSR = 0x33B // Machine performance-monitoring event selector 27.\n\tMHPMEVENT28 CSR = 0x33C // Machine performance-monitoring event selector 28.\n\tMHPMEVENT29 CSR = 0x33D // Machine performance-monitoring event selector 29.\n\tMHPMEVENT30 CSR = 0x33E // Machine performance-monitoring event selector 30.\n\tMHPMEVENT31 CSR = 0x33F // Machine performance-monitoring event selector 31.\n\n\t// Debug/Trace Registers (shared with Debug Mode)\n\tTSELECT CSR = 0x7A0 // Debug/Trace trigger register select.\n\tTDATA1  CSR = 0x7A1 // First Debug/Trace trigger data register.\n\tTDATA2  CSR = 0x7A2 // Second Debug/Trace trigger data register.\n\tTDATA3  CSR = 0x7A3 // Third Debug/Trace trigger data register.\n\n\t// Debug Mode Registers\n\tDCSR     CSR = 0x7B0 // Debug control and status register.\n\tDPC      CSR = 0x7B1 // Debug PC.\n\tDSCRATCH CSR = 0x7B2 // Debug scratch register.\n)\n\n// Bitfields for the CSR registers above.\nconst (\n\t// MSTATUS (common bits between RV32 and RV64)\n\tMSTATUS_SIE  = 1 << 1\n\tMSTATUS_MIE  = 1 << 3\n\tMSTATUS_SPIE = 1 << 5\n\tMSTATUS_UBE  = 1 << 6\n\tMSTATUS_MPIE = 1 << 7\n\tMSTATUS_SPP  = 1 << 8\n\tMSTATUS_MPRV = 1 << 17\n\tMSTATUS_SUM  = 1 << 18\n\tMSTATUS_MXR  = 1 << 19\n\tMSTATUS_TVM  = 1 << 20\n\tMSTATUS_TW   = 1 << 21\n\tMSTATUS_TSR  = 1 << 22\n\n\tMIE_SSIE = 1 << 1\n\tMIE_MSIE = 1 << 3\n\tMIE_STIE = 1 << 5\n\tMIE_MTIE = 1 << 7\n\tMIE_SEIE = 1 << 9\n\tMIE_MEIE = 1 << 11\n\n\tMIP_SSIP = 1 << 1\n\tMIP_MSIP = 1 << 3\n\tMIP_STIP = 1 << 5\n\tMIP_MTIP = 1 << 7\n\tMIP_SEIP = 1 << 9\n\tMIP_MEIP = 1 << 11\n)\n\n// Interrupt constants\nconst (\n\t// MCAUSE values with the topmost bit (interrupt bit) set.\n\tSupervisorSoftwareInterrupt = 1\n\tMachineSoftwareInterrupt    = 3\n\tSupervisorTimerInterrupt    = 5\n\tMachineTimerInterrupt       = 7\n\tSupervisorExternalInterrupt = 9\n\tMachineExternalInterrupt    = 11\n\n\t// MCAUSE values with the topmost bit (interrupt bit) clear.\n\tInstructionAddressMisaligned = 0\n\tInstructionAccessFault       = 1\n\tIllegalInstruction           = 2\n\tBreakpoint                   = 3\n\tLoadAddressMisaligned        = 4\n\tLoadAccessFault              = 5\n\tStoreOrAMOAddressMisaligned  = 6\n\tStoreOrAMOAccessFault        = 7\n\tEnvironmentCallFromUMode     = 8\n\tEnvironmentCallFromSMode     = 9\n\tEnvironmentCallFromMMode     = 11\n\tInstructionPageFault         = 12\n\tLoadPageFault                = 13\n\tStoreOrAMOPageFault          = 15\n)\n"
  },
  {
    "path": "src/device/riscv/handleinterrupt.S",
    "content": "#ifdef __riscv_flen\n#define NREG 48\n#define LFREG flw\n#define SFREG fsw\n#else\n#define NREG 16\n#endif\n\n#if __riscv_xlen==64\n#define REGSIZE 8\n#define SREG sd\n#define LREG ld\n#else\n#define REGSIZE 4\n#define SREG sw\n#define LREG lw\n#endif\n\n.section .text.handleInterruptASM\n.global handleInterruptASM\n.type handleInterruptASM,@function\nhandleInterruptASM:\n    // Save and restore all registers, because the hardware only saves/restores\n    // the pc.\n    // Note: we have to do this in assembly because the \"interrupt\"=\"machine\"\n    // attribute is broken in LLVM: https://bugs.llvm.org/show_bug.cgi?id=42984\n    addi    sp, sp, -NREG*REGSIZE\n    SREG    ra, 0*REGSIZE(sp)\n    SREG    t0, 1*REGSIZE(sp)\n    SREG    t1, 2*REGSIZE(sp)\n    SREG    t2, 3*REGSIZE(sp)\n    SREG    a0, 4*REGSIZE(sp)\n    SREG    a1, 5*REGSIZE(sp)\n    SREG    a2, 6*REGSIZE(sp)\n    SREG    a3, 7*REGSIZE(sp)\n    SREG    a4, 8*REGSIZE(sp)\n    SREG    a5, 9*REGSIZE(sp)\n    SREG    a6, 10*REGSIZE(sp)\n    SREG    a7, 11*REGSIZE(sp)\n    SREG    t3, 12*REGSIZE(sp)\n    SREG    t4, 13*REGSIZE(sp)\n    SREG    t5, 14*REGSIZE(sp)\n    SREG    t6, 15*REGSIZE(sp)\n#ifdef __riscv_flen\n    SFREG   f0, (0  + 16)*REGSIZE(sp)\n    SFREG   f1, (1  + 16)*REGSIZE(sp)\n    SFREG   f2, (2  + 16)*REGSIZE(sp)\n    SFREG   f3, (3  + 16)*REGSIZE(sp)\n    SFREG   f4, (4  + 16)*REGSIZE(sp)\n    SFREG   f5, (5  + 16)*REGSIZE(sp)\n    SFREG   f6, (6  + 16)*REGSIZE(sp)\n    SFREG   f7, (7  + 16)*REGSIZE(sp)\n    SFREG   f8, (8  + 16)*REGSIZE(sp)\n    SFREG   f9, (9  + 16)*REGSIZE(sp)\n    SFREG   f10,(10 + 16)*REGSIZE(sp)\n    SFREG   f11,(11 + 16)*REGSIZE(sp)\n    SFREG   f12,(12 + 16)*REGSIZE(sp)\n    SFREG   f13,(13 + 16)*REGSIZE(sp)\n    SFREG   f14,(14 + 16)*REGSIZE(sp)\n    SFREG   f15,(15 + 16)*REGSIZE(sp)\n    SFREG   f16,(16 + 16)*REGSIZE(sp)\n    SFREG   f17,(17 + 16)*REGSIZE(sp)\n    SFREG   f18,(18 + 16)*REGSIZE(sp)\n    SFREG   f19,(19 + 16)*REGSIZE(sp)\n    SFREG   f20,(20 + 16)*REGSIZE(sp)\n    SFREG   f21,(21 + 16)*REGSIZE(sp)\n    SFREG   f22,(22 + 16)*REGSIZE(sp)\n    SFREG   f23,(23 + 16)*REGSIZE(sp)\n    SFREG   f24,(24 + 16)*REGSIZE(sp)\n    SFREG   f25,(25 + 16)*REGSIZE(sp)\n    SFREG   f26,(26 + 16)*REGSIZE(sp)\n    SFREG   f27,(27 + 16)*REGSIZE(sp)\n    SFREG   f28,(28 + 16)*REGSIZE(sp)\n    SFREG   f29,(29 + 16)*REGSIZE(sp)\n    SFREG   f30,(30 + 16)*REGSIZE(sp)\n    SFREG   f31,(31 + 16)*REGSIZE(sp)\n#endif\n    call    handleInterrupt\n#ifdef __riscv_flen\n    LFREG   f0, (31 + 16)*REGSIZE(sp)\n    LFREG   f1, (30 + 16)*REGSIZE(sp)\n    LFREG   f2, (29 + 16)*REGSIZE(sp)\n    LFREG   f3, (28 + 16)*REGSIZE(sp)\n    LFREG   f4, (27 + 16)*REGSIZE(sp)\n    LFREG   f5, (26 + 16)*REGSIZE(sp)\n    LFREG   f6, (25 + 16)*REGSIZE(sp)\n    LFREG   f7, (24 + 16)*REGSIZE(sp)\n    LFREG   f8, (23 + 16)*REGSIZE(sp)\n    LFREG   f9, (22 + 16)*REGSIZE(sp)\n    LFREG   f10,(21 + 16)*REGSIZE(sp)\n    LFREG   f11,(20 + 16)*REGSIZE(sp)\n    LFREG   f12,(19 + 16)*REGSIZE(sp)\n    LFREG   f13,(18 + 16)*REGSIZE(sp)\n    LFREG   f14,(17 + 16)*REGSIZE(sp)\n    LFREG   f15,(16 + 16)*REGSIZE(sp)\n    LFREG   f16,(15 + 16)*REGSIZE(sp)\n    LFREG   f17,(14 + 16)*REGSIZE(sp)\n    LFREG   f18,(13 + 16)*REGSIZE(sp)\n    LFREG   f19,(12 + 16)*REGSIZE(sp)\n    LFREG   f20,(11 + 16)*REGSIZE(sp)\n    LFREG   f21,(10 + 16)*REGSIZE(sp)\n    LFREG   f22,(9 + 16)*REGSIZE(sp)\n    LFREG   f23,(8 + 16)*REGSIZE(sp)\n    LFREG   f24,(7 + 16)*REGSIZE(sp)\n    LFREG   f25,(6 + 16)*REGSIZE(sp)\n    LFREG   f26,(5 + 16)*REGSIZE(sp)\n    LFREG   f27,(4 + 16)*REGSIZE(sp)\n    LFREG   f28,(3 + 16)*REGSIZE(sp)\n    LFREG   f29,(2 + 16)*REGSIZE(sp)\n    LFREG   f30,(1 + 16)*REGSIZE(sp)\n    LFREG   f31,(0 + 16)*REGSIZE(sp)\n#endif\n    LREG    t6, 15*REGSIZE(sp)\n    LREG    t5, 14*REGSIZE(sp)\n    LREG    t4, 13*REGSIZE(sp)\n    LREG    t3, 12*REGSIZE(sp)\n    LREG    a7, 11*REGSIZE(sp)\n    LREG    a6, 10*REGSIZE(sp)\n    LREG    a5, 9*REGSIZE(sp)\n    LREG    a4, 8*REGSIZE(sp)\n    LREG    a3, 7*REGSIZE(sp)\n    LREG    a2, 6*REGSIZE(sp)\n    LREG    a1, 5*REGSIZE(sp)\n    LREG    a0, 4*REGSIZE(sp)\n    LREG    t2, 3*REGSIZE(sp)\n    LREG    t1, 2*REGSIZE(sp)\n    LREG    t0, 1*REGSIZE(sp)\n    LREG    ra, 0*REGSIZE(sp)\n    addi    sp, sp, NREG*REGSIZE\n    mret\n"
  },
  {
    "path": "src/device/riscv/riscv.go",
    "content": "package riscv\n\n// Run the given assembly code. The code will be marked as having side effects,\n// as it doesn't produce output and thus would normally be eliminated by the\n// optimizer.\nfunc Asm(asm string)\n\n// Run the given inline assembly. The code will be marked as having side\n// effects, as it would otherwise be optimized away. The inline assembly string\n// recognizes template values in the form {name}, like so:\n//\n//\tarm.AsmFull(\n//\t    \"st {value}, [{result}]\",\n//\t    map[string]interface{}{\n//\t        \"value\":  1,\n//\t        \"result\": uintptr(unsafe.Pointer(&dest)),\n//\t    })\n//\n// You can use {} in the asm string (which expands to a register) to set the\n// return value.\nfunc AsmFull(asm string, regs map[string]interface{}) uintptr\n\n// DisableInterrupts disables all interrupts, and returns the old interrupt\n// state.\nfunc DisableInterrupts() uintptr {\n\t// Note: this can be optimized with a CSRRW instruction, which atomically\n\t// swaps the value and returns the old value.\n\tmask := MSTATUS.Get()\n\tMSTATUS.ClearBits(1 << 3) // clear the MIE bit\n\treturn mask\n}\n\n// EnableInterrupts enables all interrupts again. The value passed in must be\n// the mask returned by DisableInterrupts.\nfunc EnableInterrupts(mask uintptr) {\n\tmask &= 1 << 3        // clear all bits except for the MIE bit\n\tMSTATUS.SetBits(mask) // set the MIE bit, if it was previously cleared\n}\n"
  },
  {
    "path": "src/device/riscv/start.S",
    "content": ".section .init\n.global _start\n.type _start,@function\n\n_start:\n    // If we're on a multicore system, we need to wait for hart 0 to wake us up.\n#if TINYGO_CORES > 1\n    csrr a0, mhartid\n\n    // Hart 0 stack\n    bnez a0, 1f\n    la sp,      _stack_top\n\n1:\n    // Hart 1 stack\n    li a1, 1\n    bne a0, a1, 2f\n    la sp,      _stack1_top\n\n2:\n    // Hart 2 stack\n    #if TINYGO_CORES >= 3\n    li a1, 2\n    bne a0, a1, 3f\n    la sp,      _stack2_top\n    #endif\n\n3:\n    // Hart 3 stack\n    #if TINYGO_CORES >= 4\n    li a1, 3\n    bne a0, a1, 4f\n    la sp,      _stack3_top\n    #endif\n\n4:\n    // done\n\n#if TINYGO_CORES > 4\n#error only up to 4 cores are supported at the moment!\n#endif\n\n#else\n    // Load the stack pointer.\n    la sp,      _stack_top\n#endif\n\n    // Load the globals pointer. The program will load pointers relative to this\n    // register, so it must be set to the right value on startup.\n    // See: https://gnu-mcu-eclipse.github.io/arch/riscv/programmer/#the-gp-global-pointer-register\n    // Linker relaxations must be disabled to avoid the initialization beign\n    // relaxed with an uninitialized global pointer: mv gp, gp\n    .option push\n    .option norelax\n    la gp,      __global_pointer$\n    .option pop\n\n    // Jump to runtime.main\n    call main\n"
  },
  {
    "path": "src/device/tkey/tkey.go",
    "content": "//go:build tkey\n\n// Hand written file based on https://github.com/tillitis/tkey-libs/blob/main/include/tkey/tk1_mem.h\n\npackage tkey\n\nimport (\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\n// Peripherals\nvar (\n\tTRNG = (*TRNG_Type)(unsafe.Pointer(TK1_MMIO_TRNG_BASE))\n\n\tTIMER = (*TIMER_Type)(unsafe.Pointer(TK1_MMIO_TIMER_BASE))\n\n\tUDS = (*UDS_Type)(unsafe.Pointer(TK1_MMIO_UDS_BASE))\n\n\tUART = (*UART_Type)(unsafe.Pointer(TK1_MMIO_UART_BASE))\n\n\tTOUCH = (*TOUCH_Type)(unsafe.Pointer(TK1_MMIO_TOUCH_BASE))\n\n\tTK1 = (*TK1_Type)(unsafe.Pointer(TK1_MMIO_TK1_BASE))\n)\n\n// Memory sections\nconst (\n\tTK1_ROM_BASE uintptr = 0x00000000\n\n\tTK1_RAM_BASE uintptr = 0x40000000\n\n\tTK1_MMIO_BASE uintptr = 0xc0000000\n\n\tTK1_MMIO_TRNG_BASE uintptr = 0xc0000000\n\n\tTK1_MMIO_TIMER_BASE uintptr = 0xc1000000\n\n\tTK1_MMIO_UDS_BASE uintptr = 0xc2000000\n\n\tTK1_MMIO_UART_BASE uintptr = 0xc3000000\n\n\tTK1_MMIO_TOUCH_BASE uintptr = 0xc4000000\n\n\tTK1_MMIO_FW_RAM_BASE uintptr = 0xd0000000\n\n\tTK1_MMIO_TK1_BASE uintptr = 0xff000000\n)\n\n// Memory section sizes\nconst (\n\tTK1_RAM_SIZE uintptr = 0x20000\n\n\tTK1_MMIO_SIZE uintptr = 0x3fffffff\n)\n\ntype TRNG_Type struct {\n\t_       [36]byte\n\tSTATUS  volatile.Register32\n\t_       [88]byte\n\tENTROPY volatile.Register32\n}\n\ntype TIMER_Type struct {\n\t_         [32]byte\n\tCTRL      volatile.Register32\n\tSTATUS    volatile.Register32\n\tPRESCALER volatile.Register32\n\tTIMER     volatile.Register32\n}\n\ntype UDS_Type struct {\n\t_    [64]byte\n\tDATA [8]volatile.Register32\n}\n\ntype UART_Type struct {\n\t_         [128]byte\n\tRX_STATUS volatile.Register32\n\tRX_DATA   volatile.Register32\n\tRX_BYTES  volatile.Register32\n\t_         [116]byte\n\tTX_STATUS volatile.Register32\n\tTX_DATA   volatile.Register32\n}\n\ntype TOUCH_Type struct {\n\t_      [36]byte\n\tSTATUS volatile.Register32\n}\n\ntype TK1_Type struct {\n\tNAME0         volatile.Register32\n\tNAME1         volatile.Register32\n\tVERSION       volatile.Register32\n\t_             [16]byte\n\tSWITCH_APP    volatile.Register32\n\t_             [4]byte\n\tLED           volatile.Register32\n\tGPIO          volatile.Register16\n\tAPP_ADDR      volatile.Register32\n\tAPP_SIZE      volatile.Register32\n\tBLAKE2S       volatile.Register32\n\t_             [72]byte\n\tCDI_FIRST     [8]volatile.Register32\n\t_             [32]byte\n\tUDI_FIRST     [2]volatile.Register32\n\t_             [62]byte\n\tRAM_ADDR_RAND volatile.Register16\n\t_             [2]byte\n\tRAM_DATA_RAND volatile.Register16\n\t_             [126]byte\n\tCPU_MON_CTRL  volatile.Register16\n\t_             [2]byte\n\tCPU_MON_FIRST volatile.Register32\n\tCPU_MON_LAST  volatile.Register32\n\t_             [60]byte\n\tSYSTEM_RESET  volatile.Register16\n\t_             [66]byte\n\tSPI_EN        volatile.Register32\n\tSPI_XFER      volatile.Register32\n\tSPI_DATA      volatile.Register32\n}\n\nconst (\n\tTK1_MMIO_TIMER_CTRL_START_BIT = 0\n\tTK1_MMIO_TIMER_CTRL_STOP_BIT  = 1\n\tTK1_MMIO_TIMER_CTRL_START     = 1 << TK1_MMIO_TIMER_CTRL_START_BIT\n\tTK1_MMIO_TIMER_CTRL_STOP      = 1 << TK1_MMIO_TIMER_CTRL_STOP_BIT\n\n\tTK1_MMIO_TK1_LED_R_BIT = 2\n\tTK1_MMIO_TK1_LED_G_BIT = 1\n\tTK1_MMIO_TK1_LED_B_BIT = 0\n\n\tTK1_MMIO_TK1_GPIO1_BIT = 0\n\tTK1_MMIO_TK1_GPIO2_BIT = 1\n\tTK1_MMIO_TK1_GPIO3_BIT = 2\n\tTK1_MMIO_TK1_GPIO4_BIT = 3\n)\n"
  },
  {
    "path": "src/examples/adc/adc.go",
    "content": "package main\n\nimport (\n\t\"machine\"\n\t\"time\"\n)\n\n// This example assumes that an analog sensor such as a rotary dial is connected to pin ADC0.\n// When the dial is turned past the midway point, the built-in LED will light up.\n\nfunc main() {\n\tmachine.InitADC()\n\n\tled := machine.LED\n\tled.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\n\tsensor := machine.ADC{machine.ADC2}\n\tsensor.Configure(machine.ADCConfig{})\n\n\tfor {\n\t\tval := sensor.Get()\n\t\tif val < 0x8000 {\n\t\t\tled.Low()\n\t\t} else {\n\t\t\tled.High()\n\t\t}\n\t\ttime.Sleep(time.Millisecond * 100)\n\t}\n}\n"
  },
  {
    "path": "src/examples/bench-goro/bench.go",
    "content": "package main\n\nimport (\n\t\"machine\"\n\t\"runtime\"\n\t\"sync\"\n\t\"time\"\n)\n\nconst N = 500000\nconst Ngoro = 4\n\nfunc main() {\n\tstart := time.Now()\n\tvar wg sync.WaitGroup\n\twg.Add(Ngoro)\n\tfor i := 0; i < Ngoro; i++ {\n\t\tgo adder(&wg, N)\n\t}\n\twg.Wait()\n\telapsed := time.Since(start)\n\tgoroutineCtxSwitchOverhead := (elapsed / (Ngoro * N)).String()\n\n\telapsedstr := elapsed.String()\n\tmachine.LED.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\tfor {\n\t\tprintln(\"bench:\", elapsedstr, \"goroutine ctx switch:\", goroutineCtxSwitchOverhead)\n\t\tmachine.LED.High()\n\t\ttime.Sleep(elapsed)\n\t\tmachine.LED.Low()\n\t\ttime.Sleep(elapsed)\n\t}\n}\n\nfunc adder(wg *sync.WaitGroup, num int) {\n\tfor i := 0; i < num; i++ {\n\t\truntime.Gosched()\n\t}\n\twg.Done()\n}\n"
  },
  {
    "path": "src/examples/blinkm/blinkm.go",
    "content": "// Connects to an BlinkM I2C RGB LED.\n// http://thingm.com/fileadmin/thingm/downloads/BlinkM_datasheet.pdf\npackage main\n\nimport (\n\t\"machine\"\n\t\"time\"\n)\n\nfunc main() {\n\tmachine.I2C0.Configure(machine.I2CConfig{})\n\n\t// Init BlinkM\n\tmachine.I2C0.WriteRegister(0x09, 'o', nil)\n\n\tversion := []byte{0, 0}\n\tmachine.I2C0.ReadRegister(0x09, 'Z', version)\n\tprintln(\"Firmware version:\", string(version[0]), string(version[1]))\n\n\tcount := 0\n\tfor {\n\t\tswitch count {\n\t\tcase 0:\n\t\t\t// Crimson\n\t\t\tmachine.I2C0.WriteRegister(0x09, 'n', []byte{0xdc, 0x14, 0x3c})\n\t\t\tcount = 1\n\t\tcase 1:\n\t\t\t// MediumPurple\n\t\t\tmachine.I2C0.WriteRegister(0x09, 'n', []byte{0x93, 0x70, 0xdb})\n\t\t\tcount = 2\n\t\tcase 2:\n\t\t\t// MediumSeaGreen\n\t\t\tmachine.I2C0.WriteRegister(0x09, 'n', []byte{0x3c, 0xb3, 0x71})\n\t\t\tcount = 0\n\t\t}\n\n\t\ttime.Sleep(100 * time.Millisecond)\n\t}\n}\n"
  },
  {
    "path": "src/examples/blinky1/blinky1.go",
    "content": "package main\n\n// This is the most minimal blinky example and should run almost everywhere.\n\nimport (\n\t\"machine\"\n\t\"time\"\n)\n\nfunc main() {\n\tled := machine.LED\n\tled.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\tfor {\n\t\tled.Low()\n\t\ttime.Sleep(time.Millisecond * 500)\n\n\t\tled.High()\n\t\ttime.Sleep(time.Millisecond * 500)\n\t}\n}\n"
  },
  {
    "path": "src/examples/blinky2/blinky2.go",
    "content": "package main\n\n// This blinky is a bit more advanced than blink1, with two goroutines running\n// at the same time and blinking a different LED. The delay of led2 is slightly\n// less than half of led1, which would be hard to do without some sort of\n// concurrency.\n\nimport (\n\t\"machine\"\n\t\"time\"\n)\n\nfunc main() {\n\tgo led1()\n\tled2()\n}\n\nfunc led1() {\n\tled := machine.LED1\n\tled.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\tfor {\n\t\tprintln(\"+\")\n\t\tled.Low()\n\t\ttime.Sleep(time.Millisecond * 1000)\n\n\t\tprintln(\"-\")\n\t\tled.High()\n\t\ttime.Sleep(time.Millisecond * 1000)\n\t}\n}\n\nfunc led2() {\n\tled := machine.LED2\n\tled.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\tfor {\n\t\tprintln(\"  +\")\n\t\tled.Low()\n\t\ttime.Sleep(time.Millisecond * 420)\n\n\t\tprintln(\"  -\")\n\t\tled.High()\n\t\ttime.Sleep(time.Millisecond * 420)\n\t}\n}\n"
  },
  {
    "path": "src/examples/button/button.go",
    "content": "package main\n\nimport (\n\t\"machine\"\n\t\"time\"\n)\n\nconst (\n\tled    = machine.LED\n\tbutton = machine.BUTTON\n)\n\nfunc main() {\n\tled.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\tbutton.Configure(machine.PinConfig{Mode: machine.PinInputPullup})\n\n\tfor {\n\t\tif button.Get() {\n\t\t\tled.Low()\n\t\t} else {\n\t\t\tled.High()\n\t\t}\n\n\t\ttime.Sleep(time.Millisecond * 10)\n\t}\n}\n"
  },
  {
    "path": "src/examples/button2/button2.go",
    "content": "package main\n\nimport (\n\t\"machine\"\n\t\"time\"\n)\n\n// This example assumes that you are using the pca10040 board\n\nfunc main() {\n\tled1 := machine.LED1\n\tled1.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\n\tled2 := machine.LED2\n\tled2.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\n\tled3 := machine.LED3\n\tled3.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\n\tled4 := machine.LED4\n\tled4.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\n\tbutton1 := machine.BUTTON1\n\tbutton1.Configure(machine.PinConfig{Mode: machine.PinInputPullup})\n\n\tbutton2 := machine.BUTTON2\n\tbutton2.Configure(machine.PinConfig{Mode: machine.PinInputPullup})\n\n\tbutton3 := machine.BUTTON3\n\tbutton3.Configure(machine.PinConfig{Mode: machine.PinInputPullup})\n\n\tbutton4 := machine.BUTTON4\n\tbutton4.Configure(machine.PinConfig{Mode: machine.PinInputPullup})\n\n\tfor {\n\t\tled1.Set(button1.Get())\n\t\tled2.Set(button2.Get())\n\t\tled3.Set(button3.Get())\n\t\tled4.Set(button4.Get())\n\n\t\ttime.Sleep(time.Millisecond * 10)\n\t}\n}\n"
  },
  {
    "path": "src/examples/can/feather-m4-can.go",
    "content": "//go:build feather_m4_can\n\npackage main\n\nimport (\n\t\"machine\"\n)\n\nfunc init() {\n\t// power on the CAN Transceiver\n\t// https://learn.adafruit.com/adafruit-feather-m4-can-express/pinouts#can-bus-3078990-8\n\tboost_en := machine.BOOST_EN\n\tboost_en.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\tboost_en.High()\n}\n"
  },
  {
    "path": "src/examples/can/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"machine\"\n\t\"time\"\n)\n\nfunc main() {\n\tcan1 := machine.CAN1\n\tcan1.Configure(machine.CANConfig{\n\t\tTransferRate:   machine.CANTransferRate500kbps,\n\t\tTransferRateFD: machine.CANTransferRate1000kbps,\n\t\tRx:             machine.CAN1_RX,\n\t\tTx:             machine.CAN1_TX,\n\t\tStandby:        machine.CAN1_STANDBY,\n\t})\n\n\tcan0 := machine.CAN0\n\tcan0.Configure(machine.CANConfig{\n\t\tTransferRate:   machine.CANTransferRate500kbps,\n\t\tTransferRateFD: machine.CANTransferRate1000kbps,\n\t\tRx:             machine.CAN0_RX,\n\t\tTx:             machine.CAN0_TX,\n\t\tStandby:        machine.NoPin,\n\t})\n\n\trxMsg := machine.CANRxBufferElement{}\n\n\tfor {\n\t\tcan1.Tx(0x123, []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, false, false)\n\t\tcan1.Tx(0x789, []byte{0x02, 0x24, 0x46, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, true, false)\n\t\ttime.Sleep(time.Millisecond * 1000)\n\n\t\tsz0 := can0.RxFifoSize()\n\t\tif sz0 > 0 {\n\t\t\tfmt.Printf(\"CAN0 %d\\r\\n\", sz0)\n\t\t\tfor i := 0; i < sz0; i++ {\n\t\t\t\tcan0.RxRaw(&rxMsg)\n\t\t\t\tfmt.Printf(\"-> %08X %X\", rxMsg.ID, rxMsg.DLC)\n\t\t\t\tfor j := byte(0); j < rxMsg.Length(); j++ {\n\t\t\t\t\tfmt.Printf(\" %02X\", rxMsg.DB[j])\n\t\t\t\t}\n\t\t\t\tfmt.Printf(\"\\r\\n\")\n\t\t\t}\n\t\t}\n\n\t\tsz1 := can1.RxFifoSize()\n\t\tif sz1 > 0 {\n\t\t\tfmt.Printf(\"CAN1 %d\\r\\n\", sz1)\n\t\t\tfor i := 0; i < sz1; i++ {\n\t\t\t\tcan1.RxRaw(&rxMsg)\n\t\t\t\tfmt.Printf(\"-> %08X %X\", rxMsg.ID, rxMsg.DLC)\n\t\t\t\tfor j := byte(0); j < rxMsg.Length(); j++ {\n\t\t\t\t\tfmt.Printf(\" %02X\", rxMsg.DB[j])\n\t\t\t\t}\n\t\t\t\tfmt.Printf(\"\\r\\n\")\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/examples/caninterrupt/feather-m4-can.go",
    "content": "//go:build feather_m4_can\n\npackage main\n\nimport (\n\t\"machine\"\n)\n\nfunc init() {\n\t// power on the CAN Transceiver\n\t// https://learn.adafruit.com/adafruit-feather-m4-can-express/pinouts#can-bus-3078990-8\n\tboost_en := machine.BOOST_EN\n\tboost_en.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\tboost_en.High()\n}\n"
  },
  {
    "path": "src/examples/caninterrupt/main.go",
    "content": "package main\n\nimport (\n\t\"device/sam\"\n\t\"fmt\"\n\t\"machine\"\n\t\"time\"\n)\n\nvar (\n\tcan0 = machine.CAN0\n\tcan1 = machine.CAN1\n\tch   = make(chan canMsg, 10)\n)\n\ntype canMsg struct {\n\tbus byte\n\tcan machine.CANRxBufferElement\n}\n\nfunc main() {\n\tgo print(ch)\n\n\tcan1.Configure(machine.CANConfig{\n\t\tTransferRate:   machine.CANTransferRate500kbps,\n\t\tTransferRateFD: machine.CANTransferRate1000kbps,\n\t\tRx:             machine.CAN1_RX,\n\t\tTx:             machine.CAN1_TX,\n\t\tStandby:        machine.CAN1_STANDBY,\n\t})\n\t// RF0NE : Rx FIFO 0 New Message Interrupt Enable\n\tcan1.SetInterrupt(sam.CAN_IE_RF0NE, func(can *machine.CAN) {\n\t\trxMsg := machine.CANRxBufferElement{}\n\t\tcan.RxRaw(&rxMsg)\n\t\tmsg := canMsg{\n\t\t\tbus: 1,\n\t\t\tcan: rxMsg,\n\t\t}\n\t\tselect {\n\t\tcase ch <- msg:\n\t\t}\n\t})\n\n\tcan0.Configure(machine.CANConfig{\n\t\tTransferRate:   machine.CANTransferRate500kbps,\n\t\tTransferRateFD: machine.CANTransferRate1000kbps,\n\t\tRx:             machine.CAN0_RX,\n\t\tTx:             machine.CAN0_TX,\n\t\tStandby:        machine.NoPin,\n\t})\n\t// RF0NE : Rx FIFO 0 New Message Interrupt Enable\n\tcan0.SetInterrupt(sam.CAN_IE_RF0NE, func(can *machine.CAN) {\n\t\trxMsg := machine.CANRxBufferElement{}\n\t\tcan.RxRaw(&rxMsg)\n\t\tmsg := canMsg{\n\t\t\tbus: 1,\n\t\t\tcan: rxMsg,\n\t\t}\n\t\tselect {\n\t\tcase ch <- msg:\n\t\t}\n\t})\n\n\tfor {\n\t\tcan0.Tx(0x123, []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, false, false)\n\t\ttime.Sleep(time.Millisecond * 500)\n\t\tcan1.Tx(0x456, []byte{0xAA, 0xBB, 0xCC}, false, false)\n\t\ttime.Sleep(time.Millisecond * 1000)\n\t}\n}\n\nfunc print(ch <-chan canMsg) {\n\tfor {\n\t\tselect {\n\t\tcase m := <-ch:\n\t\t\tfmt.Printf(\"%d %03X %X \", m.bus, m.can.ID, m.can.DLC)\n\t\t\tfor _, d := range m.can.DB[:m.can.Length()] {\n\t\t\t\tfmt.Printf(\"%02X \", d)\n\t\t\t}\n\t\t\tfmt.Printf(\"\\r\\n\")\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/examples/dac/circuitplay_express.go",
    "content": "//go:build circuitplay_express\n\npackage main\n\nimport (\n\t\"machine\"\n)\n\nfunc init() {\n\tenable := machine.PA30\n\tenable.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\tenable.Set(true)\n}\n"
  },
  {
    "path": "src/examples/dac/dac.go",
    "content": "// Simplistic example using the DAC on the Circuit Playground Express.\n//\n// To actually use the DAC for producing complex waveforms or samples requires a DMA\n// timer-based playback mechanism which is beyond the scope of this example.\npackage main\n\nimport (\n\t\"machine\"\n\t\"time\"\n)\n\nfunc main() {\n\tspeaker := machine.A0\n\tspeaker.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\n\tmachine.DAC0.Configure(machine.DACConfig{})\n\n\tdata := []uint16{0xFFFF, 0x8000, 0x4000, 0x2000, 0x1000, 0x0000}\n\n\tfor {\n\t\tfor _, val := range data {\n\t\t\tplay(val)\n\t\t\ttime.Sleep(500 * time.Millisecond)\n\t\t}\n\t}\n}\n\nfunc play(val uint16) {\n\tfor i := 0; i < 100; i++ {\n\t\tmachine.DAC0.Set(val)\n\t\ttime.Sleep(2 * time.Millisecond)\n\n\t\tmachine.DAC0.Set(0)\n\t\ttime.Sleep(2 * time.Millisecond)\n\t}\n}\n"
  },
  {
    "path": "src/examples/dac/pyportal.go",
    "content": "//go:build pyportal\n\npackage main\n\nimport (\n\t\"machine\"\n)\n\nfunc init() {\n\tenable := machine.SPK_SD\n\tenable.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\tenable.Set(true)\n}\n"
  },
  {
    "path": "src/examples/device-id/main.go",
    "content": "package main\n\nimport (\n\t\"encoding/hex\"\n\t\"machine\"\n\t\"time\"\n)\n\nfunc main() {\n\ttime.Sleep(2 * time.Second)\n\n\t// For efficiency, it's best to get the device ID once and cache it\n\t// (e.g. on RP2040 XIP flash and interrupts disabled for period of\n\t// retrieving the hardware ID from ROM chip)\n\tid := machine.DeviceID()\n\n\tfor {\n\t\tprintln(\"Device ID:\", hex.EncodeToString(id))\n\t\ttime.Sleep(1 * time.Second)\n\t}\n}\n"
  },
  {
    "path": "src/examples/echo/echo.go",
    "content": "// This is a echo console running on the device UART.\n// Connect using default baudrate for this hardware, 8-N-1 with your terminal program.\npackage main\n\nimport (\n\t\"machine\"\n\t\"time\"\n)\n\nvar (\n\tuart = machine.Serial\n)\n\nfunc main() {\n\t// use default settings for UART\n\tuart.Configure(machine.UARTConfig{})\n\tuart.Write([]byte(\"Echo console enabled. Type something then press enter:\\r\\n\"))\n\n\tinput := make([]byte, 64)\n\ti := 0\n\tfor {\n\t\tif uart.Buffered() > 0 {\n\t\t\tdata, _ := uart.ReadByte()\n\n\t\t\tswitch data {\n\t\t\tcase 13:\n\t\t\t\t// return key\n\t\t\t\tuart.Write([]byte(\"\\r\\n\"))\n\t\t\t\tuart.Write([]byte(\"You typed: \"))\n\t\t\t\tuart.Write(input[:i])\n\t\t\t\tuart.Write([]byte(\"\\r\\n\"))\n\t\t\t\ti = 0\n\t\t\tdefault:\n\t\t\t\t// just echo the character\n\t\t\t\tuart.WriteByte(data)\n\t\t\t\tinput[i] = data\n\t\t\t\ti++\n\t\t\t}\n\t\t}\n\t\ttime.Sleep(10 * time.Millisecond)\n\t}\n}\n"
  },
  {
    "path": "src/examples/echo2/echo2.go",
    "content": "// This is a echo console running on the os.Stdin and os.Stdout.\n// Stdin and os.Stdout are connected to machine.Serial in the baremetal target.\n//\n// Serial can be switched with the -serial option as follows\n// 1. tinygo flash -target wioterminal -serial usb examples/echo2\n// 2. tinygo flash -target wioterminal -serial uart examples/echo2\n//\n// This example will also work with standard Go.\npackage main\n\nimport (\n\t\"bufio\"\n\t\"fmt\"\n\t\"os\"\n)\n\nfunc main() {\n\tfmt.Printf(\"Echo console enabled. Type something then press enter:\\r\\n\")\n\n\tscanner := bufio.NewScanner(os.Stdin)\n\n\tfor {\n\t\tmsg := \"\"\n\t\tfmt.Scanf(\"%s\\n\", &msg)\n\t\tfmt.Printf(\"You typed (scanf) : %s\\r\\n\", msg)\n\n\t\tif scanner.Scan() {\n\t\t\tfmt.Printf(\"You typed (scanner) : %s\\r\\n\", scanner.Text())\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/examples/empty/main.go",
    "content": "package main\n\nimport \"time\"\n\n// This is used for smoke tests for chips without an associated board.\n\nfunc main() {\n\tfor {\n\t\ttime.Sleep(time.Second)\n\t}\n}\n"
  },
  {
    "path": "src/examples/flash/main.go",
    "content": "package main\n\nimport (\n\t\"machine\"\n\t\"time\"\n)\n\nvar (\n\terr     error\n\tmessage = \"1234567887654321123456788765432112345678876543211234567887654321\" +\n\t\t\"1234567887654321123456788765432112345678876543211234567887654321\" +\n\t\t\"1234567887654321123456788765432112345678876543211234567887654321\" +\n\t\t\"1234567887654321123456788765432112345678876543211234567887654321\"\n)\n\nfunc main() {\n\ttime.Sleep(3 * time.Second)\n\n\t// Print out general information\n\tprintln(\"Flash data start:      \", machine.FlashDataStart())\n\tprintln(\"Flash data end:        \", machine.FlashDataEnd())\n\tprintln(\"Flash data size, bytes:\", machine.Flash.Size())\n\tprintln(\"Flash write block size:\", machine.Flash.WriteBlockSize())\n\tprintln(\"Flash erase block size:\", machine.Flash.EraseBlockSize())\n\tprintln()\n\n\toriginal := make([]byte, len(message))\n\tsaved := make([]byte, len(message))\n\n\t// Read flash contents on start (data shall survive power off)\n\tprintln(\"Reading original data from flash:\")\n\t_, err = machine.Flash.ReadAt(original, 0)\n\tcheckError(err)\n\tprintln(string(original))\n\n\t// erase flash\n\tprintln(\"Erasing flash...\")\n\tneeded := int64(len(message)) / machine.Flash.EraseBlockSize()\n\tif needed == 0 {\n\t\t// have to erase at least 1 block\n\t\tneeded = 1\n\t}\n\n\terr := machine.Flash.EraseBlocks(0, needed)\n\tcheckError(err)\n\n\t// Write the message to flash\n\tprintln(\"Writing new data to flash:\")\n\t_, err = machine.Flash.WriteAt([]byte(message), 0)\n\tcheckError(err)\n\tprintln(string(message))\n\n\t// Read back flash contents after write (verify data is the same as written)\n\tprintln(\"Reading data back from flash: \")\n\t_, err = machine.Flash.ReadAt(saved, 0)\n\tcheckError(err)\n\tif !equal(saved, []byte(message)) {\n\t\tprintln(\"data verify error\")\n\t}\n\n\tprintln(string(saved))\n\tprintln(\"Done.\")\n}\n\nfunc equal(a, b []byte) bool {\n\tif len(a) != len(b) {\n\t\treturn false\n\t}\n\tfor i, v := range a {\n\t\tif v != b[i] {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\nfunc checkError(err error) {\n\tif err != nil {\n\t\tfor {\n\t\t\tprintln(err.Error())\n\t\t\ttime.Sleep(time.Second)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/examples/gba-display/gba-display.go",
    "content": "package main\n\n// Draw a red square on the GameBoy Advance screen.\n\nimport (\n\t\"image/color\"\n\t\"machine\"\n)\n\nvar display = machine.Display\n\nfunc main() {\n\tdisplay.Configure()\n\n\tfor x := int16(30); x < 50; x++ {\n\t\tfor y := int16(80); y < 100; y++ {\n\t\t\tdisplay.SetPixel(x, y, color.RGBA{255, 0, 0, 255})\n\t\t}\n\t}\n\tdisplay.Display()\n}\n"
  },
  {
    "path": "src/examples/hello-wasm-unknown/main.go",
    "content": "// this is intended to be used as wasm32-unknown-unknown module.\n// to compile it, run:\n// tinygo build -size short -o hello-unknown.wasm -target wasm-unknown -gc=leaking -no-debug ./src/examples/hello-wasm-unknown/\npackage main\n\n// Smoke test: make sure the fmt package can be imported (even if it isn't\n// really useful for wasm-unknown).\nimport _ \"os\"\n\nvar x int32\n\n//go:wasmimport hosted echo_i32\nfunc echo(x int32)\n\n//go:export update\nfunc update() {\n\tx++\n\techo(x)\n}\n\nfunc main() {\n}\n"
  },
  {
    "path": "src/examples/hid-joystick/main.go",
    "content": "package main\n\nimport (\n\t\"log\"\n\t\"machine/usb/hid/joystick\"\n\t\"math\"\n\t\"time\"\n)\n\nvar js = joystick.Port()\n\nfunc main() {\n\tlog.SetFlags(log.Lmicroseconds)\n\tticker := time.NewTicker(10 * time.Millisecond)\n\tcnt := 0\n\tconst f = 3.0\n\tfor range ticker.C {\n\t\tt := float64(cnt) * 0.01\n\t\tx := 32767 * math.Sin(2*math.Pi*f*t)\n\t\tbutton := cnt%100 > 50\n\t\tjs.SetButton(2, button)\n\t\tjs.SetButton(3, !button)\n\t\tjs.SetAxis(0, int(x))\n\t\tjs.SendState()\n\t\tcnt++\n\t}\n}\n"
  },
  {
    "path": "src/examples/hid-keyboard/main.go",
    "content": "// to override the USB Manufacturer or Product names:\n//\n// tinygo flash -target circuitplay-express -ldflags=\"-X main.usbManufacturer='TinyGopher Labs' -X main.usbProduct='GopherKeyboard' -X main.usbSerial='XXXXX'\" examples/hid-keyboard\n//\n// you can also override the VID/PID. however, only set this if you know what you are doing,\n// since changing it can make it difficult to reflash some devices.\npackage main\n\nimport (\n\t\"machine\"\n\t\"machine/usb\"\n\t\"machine/usb/hid/keyboard\"\n\t\"strconv\"\n\t\"time\"\n)\n\nvar usbVID, usbPID string\nvar usbManufacturer, usbProduct, usbSerial string\n\nfunc main() {\n\tbutton := machine.BUTTON\n\tbutton.Configure(machine.PinConfig{Mode: machine.PinInputPullup})\n\n\tkb := keyboard.Port()\n\n\tfor {\n\t\tif !button.Get() {\n\t\t\tkb.Write([]byte(\"tinygo\"))\n\t\t\ttime.Sleep(200 * time.Millisecond)\n\t\t}\n\t}\n}\n\nfunc init() {\n\tif usbVID != \"\" {\n\t\tvid, _ := strconv.ParseUint(usbVID, 0, 16)\n\t\tusb.VendorID = uint16(vid)\n\t}\n\n\tif usbPID != \"\" {\n\t\tpid, _ := strconv.ParseUint(usbPID, 0, 16)\n\t\tusb.ProductID = uint16(pid)\n\t}\n\n\tif usbManufacturer != \"\" {\n\t\tusb.Manufacturer = usbManufacturer\n\t}\n\n\tif usbProduct != \"\" {\n\t\tusb.Product = usbProduct\n\t}\n\n\tif usbSerial != \"\" {\n\t\tusb.Serial = usbSerial\n\t}\n}\n"
  },
  {
    "path": "src/examples/hid-mouse/main.go",
    "content": "package main\n\nimport (\n\t\"machine\"\n\t\"machine/usb/hid/mouse\"\n\t\"time\"\n)\n\nfunc main() {\n\tbutton := machine.BUTTON\n\tbutton.Configure(machine.PinConfig{Mode: machine.PinInputPullup})\n\n\tmouse := mouse.Port()\n\n\tfor {\n\t\tif !button.Get() {\n\t\t\tfor j := 0; j < 5; j++ {\n\t\t\t\tfor i := 0; i < 100; i++ {\n\t\t\t\t\tmouse.Move(1, 0)\n\t\t\t\t\ttime.Sleep(1 * time.Millisecond)\n\t\t\t\t}\n\n\t\t\t\tfor i := 0; i < 100; i++ {\n\t\t\t\t\tmouse.Move(0, 1)\n\t\t\t\t\ttime.Sleep(1 * time.Millisecond)\n\t\t\t\t}\n\n\t\t\t\tfor i := 0; i < 100; i++ {\n\t\t\t\t\tmouse.Move(-1, -1)\n\t\t\t\t\ttime.Sleep(1 * time.Millisecond)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttime.Sleep(100 * time.Millisecond)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/examples/i2c-target/main.go",
    "content": "// Example demonstrating I2C controller / target comms.\n//\n// To use this example, physically connect I2C0 and I2C1.\n// I2C0 will be used as the controller and I2C1 used as\n// the target.\n//\n// In this example, the target implements a simple memory\n// map, with the controller able to read and write the\n// memory.\n\npackage main\n\nimport (\n\t\"machine\"\n\t\"time\"\n)\n\nconst (\n\ttargetAddress = 0x11\n\tmaxTxSize     = 16\n)\n\nfunc main() {\n\t// Delay to enable USB monitor time to attach\n\ttime.Sleep(3 * time.Second)\n\n\t// Controller uses default I2C pins and controller\n\t// mode is default\n\terr := controller.Configure(machine.I2CConfig{})\n\tif err != nil {\n\t\tpanic(\"failed to config I2C0 as controller\")\n\t}\n\n\t// Target uses alternate pins and target mode is\n\t// explicit\n\terr = target.Configure(machine.I2CConfig{\n\t\tMode: machine.I2CModeTarget,\n\t\tSCL:  TARGET_SCL,\n\t\tSDA:  TARGET_SDA,\n\t})\n\tif err != nil {\n\t\tpanic(\"failed to config I2C1 as target\")\n\t}\n\n\t// Put welcome message directly into target memory\n\tcopy(mem[0:], []byte(\"Hello World!\"))\n\terr = target.Listen(targetAddress)\n\tif err != nil {\n\t\tpanic(\"failed to listen as I2C target\")\n\t}\n\n\t// Start the target\n\tgo targetMain()\n\n\t// Read welcome message from target over I2C\n\tbuf := make([]byte, 12)\n\terr = controller.Tx(targetAddress, []byte{0}, buf)\n\tif err != nil {\n\t\tprintln(\"failed to read welcome message over I2C\")\n\t\tpanic(err)\n\t}\n\tprintln(\"message from target:\", string(buf))\n\n\t// Write (1,2,3) to the target starting at memory address 3\n\tprintln(\"writing (1,2,3) @ 0x3\")\n\terr = controller.Tx(targetAddress, []byte{3, 1, 2, 3}, nil)\n\tif err != nil {\n\t\tprintln(\"failed to write to I2C target\")\n\t\tpanic(err)\n\t}\n\n\ttime.Sleep(100 * time.Millisecond) // Wait for target to process write\n\tprintln(\"mem:\", mem[0], mem[1], mem[2], mem[3], mem[4], mem[5])\n\n\t// Read memory address 4 from target, which should be the value 2\n\tbuf = make([]byte, 1)\n\terr = controller.Tx(targetAddress, []byte{4}, buf[:1])\n\tif err != nil {\n\t\tprintln(\"failed to read from I2C target\")\n\t\tpanic(err)\n\t}\n\n\tif buf[0] != 2 {\n\t\tpanic(\"read incorrect value from I2C target\")\n\t}\n\n\tprintln(\"all done!\")\n\tfor {\n\t\ttime.Sleep(1 * time.Second)\n\t}\n}\n\n// -- target ---\n\nvar (\n\tmem [256]byte\n)\n\n// targetMain implements the 'main loop' for an I2C target\nfunc targetMain() {\n\tbuf := make([]byte, maxTxSize)\n\tvar ptr uint8\n\n\tfor {\n\t\tevt, n, err := target.WaitForEvent(buf)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\n\t\tswitch evt {\n\t\tcase machine.I2CReceive:\n\t\t\tif n > 0 {\n\t\t\t\tptr = buf[0]\n\t\t\t}\n\n\t\t\tfor o := 1; o < n; o++ {\n\t\t\t\tmem[ptr] = buf[o]\n\t\t\t\tptr++\n\t\t\t}\n\n\t\tcase machine.I2CRequest:\n\t\t\ttarget.Reply(mem[ptr:256])\n\n\t\tcase machine.I2CFinish:\n\t\t\t// nothing to do\n\n\t\tdefault:\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/examples/i2c-target/main_feather_nrf52840.go",
    "content": "//go:build feather_nrf52840\n\npackage main\n\nimport \"machine\"\n\nconst (\n\tTARGET_SCL = machine.A5\n\tTARGET_SDA = machine.A4\n)\n\nvar (\n\tcontroller = machine.I2C0\n\ttarget     = machine.I2C1\n)\n"
  },
  {
    "path": "src/examples/i2c-target/main_feather_rp2040.go",
    "content": "//go:build rp2040\n\npackage main\n\nimport \"machine\"\n\nconst (\n\tTARGET_SCL = machine.GPIO25\n\tTARGET_SDA = machine.GPIO24\n)\n\nvar (\n\tcontroller = machine.I2C1\n\ttarget     = machine.I2C0\n)\n"
  },
  {
    "path": "src/examples/i2s/i2s.go",
    "content": "// Example using the i2s hardware interface on the Adafruit Circuit Playground Express\n// to read data from the onboard MEMS microphone.\npackage main\n\nimport (\n\t\"machine\"\n)\n\nfunc main() {\n\tmachine.I2S0.Configure(machine.I2SConfig{\n\t\tMode:        machine.I2SModePDM,\n\t\tClockSource: machine.I2SClockSourceExternal,\n\t\tStereo:      true,\n\t})\n\n\tdata := make([]uint16, 64)\n\n\tfor {\n\t\t// get the next group of samples\n\t\tmachine.I2S0.ReadMono(data)\n\n\t\tprintln(\"data\", data[0], data[1], data[2], data[4], \"...\")\n\t}\n}\n"
  },
  {
    "path": "src/examples/machinetest/machinetest.go",
    "content": "package main\n\n// This is the same as examples/serial, but it also imports the machine package.\n// It is used as a smoke test for the machine package (for boards that don't\n// have an on-board LED and therefore can't use examples/blinky1).\n\nimport (\n\t_ \"machine\" // smoke test for the machine package\n\t\"time\"\n)\n\nfunc main() {\n\tfor {\n\t\tprintln(\"hello world!\")\n\t\ttime.Sleep(time.Second)\n\t}\n}\n"
  },
  {
    "path": "src/examples/mcp3008/mcp3008.go",
    "content": "// Connects to an MCP3008 ADC via SPI.\n// Datasheet: https://www.microchip.com/wwwproducts/en/en010530\npackage main\n\nimport (\n\t\"errors\"\n\t\"machine\"\n\t\"time\"\n)\n\n// cs is the pin used for Chip Select (CS). Change to whatever is in use on your board.\nconst cs = machine.Pin(3)\n\nvar (\n\ttx          []byte\n\trx          []byte\n\tval, result uint16\n)\n\nfunc main() {\n\tcs.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\n\tmachine.SPI0.Configure(machine.SPIConfig{\n\t\tFrequency: 4000000,\n\t\tMode:      3})\n\n\ttx = make([]byte, 3)\n\trx = make([]byte, 3)\n\n\tfor {\n\t\tval, _ = Read(0)\n\t\tprintln(val)\n\t\ttime.Sleep(50 * time.Millisecond)\n\t}\n}\n\n// Read analog data from channel\nfunc Read(channel int) (uint16, error) {\n\tif channel < 0 || channel > 7 {\n\t\treturn 0, errors.New(\"Invalid channel for read\")\n\t}\n\n\ttx[0] = 0x01\n\ttx[1] = byte(8+channel) << 4\n\ttx[2] = 0x00\n\n\tcs.Low()\n\tmachine.SPI0.Tx(tx, rx)\n\tresult = uint16((rx[1]&0x3))<<8 + uint16(rx[2])\n\tcs.High()\n\n\treturn result, nil\n}\n"
  },
  {
    "path": "src/examples/memstats/memstats.go",
    "content": "package main\n\nimport (\n\t\"math/rand\"\n\t\"runtime\"\n\t\"time\"\n)\n\nfunc main() {\n\n\tms := runtime.MemStats{}\n\n\tfor {\n\t\tescapesToHeap()\n\t\truntime.ReadMemStats(&ms)\n\t\tprintln(\"Heap before GC. Used: \", ms.HeapInuse, \" Free: \", ms.HeapIdle, \" Meta: \", ms.GCSys)\n\t\truntime.GC()\n\t\truntime.ReadMemStats(&ms)\n\t\tprintln(\"Heap after  GC. Used: \", ms.HeapInuse, \" Free: \", ms.HeapIdle, \" Meta: \", ms.GCSys)\n\t\ttime.Sleep(5 * time.Second)\n\t}\n\n}\n\nfunc escapesToHeap() {\n\tn := rand.Intn(100)\n\tprintln(\"Doing \", n, \" iterations\")\n\tfor i := 0; i < n; i++ {\n\t\ts := make([]byte, i)\n\t\t_ = append(s, 42)\n\t}\n}\n"
  },
  {
    "path": "src/examples/microbit-blink/microbit-blink.go",
    "content": "// blink program for the BBC micro:bit\npackage main\n\nimport (\n\t\"machine\"\n\t\"time\"\n)\n\n// The LED matrix in the micro:bit is a multiplexed display: https://en.wikipedia.org/wiki/Multiplexed_display\n// Driver for easier control: https://github.com/tinygo-org/drivers/tree/master/microbitmatrix\nfunc main() {\n\tledrow := machine.LED_ROW_1\n\tledrow.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\tledcol := machine.LED_COL_1\n\tledcol.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\tledcol.Low()\n\tfor {\n\t\tledrow.Low()\n\t\ttime.Sleep(time.Millisecond * 500)\n\n\t\tledrow.High()\n\t\ttime.Sleep(time.Millisecond * 500)\n\t}\n}\n"
  },
  {
    "path": "src/examples/pdm/pdm.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"machine\"\n)\n\nvar (\n\taudio = make([]int16, 16)\n\tpdm   = machine.PDM{}\n)\n\nfunc main() {\n\tmachine.BUTTONA.Configure(machine.PinConfig{Mode: machine.PinInputPulldown})\n\terr := pdm.Configure(machine.PDMConfig{CLK: machine.PDM_CLK_PIN, DIN: machine.PDM_DIN_PIN})\n\tif err != nil {\n\t\tpanic(fmt.Sprintf(\"Failed to configure PDM:%v\", err))\n\t}\n\n\tfor {\n\t\tif machine.BUTTONA.Get() {\n\t\t\tprintln(\"Recording new audio clip into memory\")\n\t\t\tpdm.Read(audio)\n\t\t\tprintln(fmt.Sprintf(\"Recorded new audio clip into memory: %v\", audio))\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/examples/pininterrupt/arduino.go",
    "content": "//go:build arduino\n\npackage main\n\nimport \"machine\"\n\nconst (\n\tbutton          = machine.D2\n\tbuttonMode      = machine.PinInputPullup\n\tbuttonPinChange = machine.PinRising\n)\n"
  },
  {
    "path": "src/examples/pininterrupt/circuitplay-express.go",
    "content": "//go:build circuitplay_express\n\npackage main\n\nimport \"machine\"\n\nconst (\n\tbutton          = machine.BUTTON\n\tbuttonMode      = machine.PinInputPulldown\n\tbuttonPinChange = machine.PinFalling\n)\n"
  },
  {
    "path": "src/examples/pininterrupt/pca10040.go",
    "content": "//go:build pca10040\n\npackage main\n\nimport \"machine\"\n\nconst (\n\tbutton          = machine.BUTTON\n\tbuttonMode      = machine.PinInputPullup\n\tbuttonPinChange = machine.PinRising\n)\n"
  },
  {
    "path": "src/examples/pininterrupt/pininterrupt.go",
    "content": "package main\n\n// This example demonstrates how to use pin change interrupts.\n//\n// This is only an example and should not be copied directly in any serious\n// circuit, because it only naively implements an important feature: debouncing.\n// See: https://en.wikipedia.org/wiki/Switch#Contact_bounce\n\nimport (\n\t\"machine\"\n\t\"time\"\n)\n\nconst (\n\tled = machine.LED\n)\n\nvar lastPress time.Time\n\nfunc main() {\n\n\t// Configure the LED, defaulting to on (usually setting the pin to low will\n\t// turn the LED on).\n\tled.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\tled.Low()\n\n\t// Make sure the pin is configured as a pullup to avoid floating inputs.\n\t// Pullup works for most buttons, as most buttons short to ground when\n\t// pressed.\n\tbutton.Configure(machine.PinConfig{Mode: buttonMode})\n\n\t// Set an interrupt on this pin.\n\terr := button.SetInterrupt(buttonPinChange, func(machine.Pin) {\n\n\t\t// Ignore events that are too close to the last registered press (debouncing)\n\t\tif time.Since(lastPress) < 100*time.Millisecond {\n\t\t\treturn\n\t\t}\n\t\tlastPress = time.Now()\n\n\t\tled.Set(!led.Get())\n\t})\n\tif err != nil {\n\t\tprintln(\"could not configure pin interrupt:\", err.Error())\n\t}\n\n\t// Make sure the program won't exit.\n\tfor {\n\t\ttime.Sleep(time.Hour)\n\t}\n}\n"
  },
  {
    "path": "src/examples/pininterrupt/stm32.go",
    "content": "//go:build stm32\n\npackage main\n\nimport \"machine\"\n\nconst (\n\tbutton          = machine.BUTTON\n\tbuttonMode      = machine.PinInputPulldown\n\tbuttonPinChange = machine.PinRising | machine.PinFalling\n)\n"
  },
  {
    "path": "src/examples/pininterrupt/wioterminal.go",
    "content": "//go:build wioterminal\n\npackage main\n\nimport \"machine\"\n\nconst (\n\tbutton          = machine.BUTTON\n\tbuttonMode      = machine.PinInput\n\tbuttonPinChange = machine.PinFalling\n)\n"
  },
  {
    "path": "src/examples/pwm/arduino-mega1280.go",
    "content": "//go:build arduino_mega1280\n\npackage main\n\nimport \"machine\"\n\nvar (\n\t// Configuration on an Arduino Uno.\n\tpwm  = machine.Timer3\n\tpinA = machine.PH3 // pin 6 on the Mega\n\tpinB = machine.PH4 // pin 7 on the Mega\n)\n"
  },
  {
    "path": "src/examples/pwm/arduino.go",
    "content": "//go:build arduino\n\npackage main\n\nimport \"machine\"\n\nvar (\n\t// Configuration on an Arduino Uno.\n\tpwm  = machine.Timer2\n\tpinA = machine.PB3 // pin 11 on the Uno\n\tpinB = machine.PD3 // pin 3 on the Uno\n)\n"
  },
  {
    "path": "src/examples/pwm/bluepill.go",
    "content": "//go:build bluepill\n\npackage main\n\nimport \"machine\"\n\nvar (\n\tpwm  = &machine.TIM2\n\tpinA = machine.PA0\n\tpinB = machine.PA1\n)\n"
  },
  {
    "path": "src/examples/pwm/feather-m4.go",
    "content": "//go:build feather_m4\n\npackage main\n\nimport \"machine\"\n\nvar (\n\tpwm  = machine.TCC0\n\tpinA = machine.D12\n\tpinB = machine.D13\n)\n"
  },
  {
    "path": "src/examples/pwm/itsybitsy-m0.go",
    "content": "//go:build itsybitsy_m0\n\npackage main\n\nimport \"machine\"\n\nvar (\n\tpwm  = machine.TCC0\n\tpinA = machine.D3\n\tpinB = machine.D4\n)\n"
  },
  {
    "path": "src/examples/pwm/itsybitsy-m4.go",
    "content": "//go:build itsybitsy_m4\n\npackage main\n\nimport \"machine\"\n\nvar (\n\tpwm  = machine.TCC0\n\tpinA = machine.D12\n\tpinB = machine.D13\n)\n"
  },
  {
    "path": "src/examples/pwm/nucleo-f722ze.go",
    "content": "//go:build stm32f7\n\npackage main\n\nimport \"machine\"\n\nvar (\n\tpwm  = &machine.TIM1\n\tpinA = machine.PA8\n\tpinB = machine.PA9\n)\n"
  },
  {
    "path": "src/examples/pwm/nucleo-l031k6.go",
    "content": "//go:build stm32l0\n\npackage main\n\nimport \"machine\"\n\nvar (\n\tpwm  = &machine.TIM2\n\tpinA = machine.PA0\n\tpinB = machine.PB3\n)\n"
  },
  {
    "path": "src/examples/pwm/nucleo-l432kc.go",
    "content": "//go:build stm32l4\n\npackage main\n\nimport \"machine\"\n\nvar (\n\tpwm  = &machine.TIM2\n\tpinA = machine.PA0\n\tpinB = machine.PB3\n)\n"
  },
  {
    "path": "src/examples/pwm/nucleo-l552ze.go",
    "content": "//go:build stm32l5\n\npackage main\n\nimport \"machine\"\n\nvar (\n\tpwm  = &machine.TIM1\n\tpinA = machine.PA8\n\tpinB = machine.PA9\n)\n"
  },
  {
    "path": "src/examples/pwm/pico.go",
    "content": "//go:build pico\n\npackage main\n\nimport \"machine\"\n\nvar (\n\tpwm  = machine.PWM4 // Pin 25 (LED on pico) corresponds to PWM4.\n\tpinA = machine.LED\n\tpinB = machine.GPIO24\n)\n"
  },
  {
    "path": "src/examples/pwm/pwm.go",
    "content": "package main\n\n// This example demonstrates some features of the PWM support.\n\nimport (\n\t\"machine\"\n\t\"time\"\n)\n\nconst delayBetweenPeriods = time.Second * 5\n\nfunc main() {\n\t// Delay a bit on startup to easily catch the first messages.\n\ttime.Sleep(time.Second * 2)\n\n\t// Configure the PWM with the given period.\n\terr := pwm.Configure(machine.PWMConfig{\n\t\tPeriod: 16384e3, // 16.384ms\n\t})\n\tif err != nil {\n\t\tprintln(\"failed to configure PWM\")\n\t\treturn\n\t}\n\n\t// The top value is the highest value that can be passed to PWMChannel.Set.\n\t// It is usually an even number.\n\tprintln(\"top:\", pwm.Top())\n\n\t// Configure the two channels we'll use as outputs.\n\tchannelA, err := pwm.Channel(pinA)\n\tif err != nil {\n\t\tprintln(\"failed to configure channel A\")\n\t\treturn\n\t}\n\tchannelB, err := pwm.Channel(pinB)\n\tif err != nil {\n\t\tprintln(\"failed to configure channel B\")\n\t\treturn\n\t}\n\n\t// Invert one of the channels to demonstrate output polarity.\n\tpwm.SetInverting(channelB, true)\n\n\t// Test out various frequencies below, including some edge cases.\n\n\tprintln(\"running at 0% duty cycle\")\n\tpwm.Set(channelA, 0)\n\tpwm.Set(channelB, 0)\n\ttime.Sleep(delayBetweenPeriods)\n\n\tprintln(\"running at 1\")\n\tpwm.Set(channelA, 1)\n\tpwm.Set(channelB, 1)\n\ttime.Sleep(delayBetweenPeriods)\n\n\tprintln(\"running at 25% duty cycle\")\n\tpwm.Set(channelA, pwm.Top()/4)\n\tpwm.Set(channelB, pwm.Top()/4)\n\ttime.Sleep(delayBetweenPeriods)\n\n\tprintln(\"running at top-1\")\n\tpwm.Set(channelA, pwm.Top()-1)\n\tpwm.Set(channelB, pwm.Top()-1)\n\ttime.Sleep(delayBetweenPeriods)\n\n\tprintln(\"running at 100% duty cycle\")\n\tpwm.Set(channelA, pwm.Top())\n\tpwm.Set(channelB, pwm.Top())\n\ttime.Sleep(delayBetweenPeriods)\n\n\tfor {\n\t\ttime.Sleep(time.Second)\n\t}\n}\n"
  },
  {
    "path": "src/examples/pwm/stm32f4disco.go",
    "content": "//go:build stm32f4disco\n\npackage main\n\nimport \"machine\"\n\nvar (\n\t// These pins correspond to LEDs on the discovery\n\t// board\n\tpwm  = &machine.TIM4\n\tpinA = machine.PD12\n\tpinB = machine.PD13\n)\n"
  },
  {
    "path": "src/examples/ram-func/main.go",
    "content": "package main\n\n// This example demonstrates how to use go:section to place code into RAM for\n// execution.  The code is present in flash in the `.data` region and copied\n// into the correct place in RAM early in startup sequence (at the same time\n// as non-zero global variables are initialized).\n//\n// This example should work on any ARM Cortex MCU.\n//\n// For Go code use the pragma \"//go:section\", for cgo use the \"section\" and\n// \"noinline\" attributes.  The `.ramfuncs` section is explicitly placed into\n// the `.data` region by the linker script.\n//\n// Running the example should print out the program counter from the functions\n// below.  The program counters should be in different memory regions.\n//\n// On RP2040, for example, the output is something like this:\n//\n//  Go in RAM:    0x20000DB4\n//  Go in flash:  0x10007610\n//  cgo in RAM:   0x20000DB8\n//  cgo in flash: 0x10002C26\n//\n// This can be confirmed using `objdump -t xxx.elf | grep main | sort`:\n//\n//  00000000 l    df *ABS*  00000000 main\n//  1000760d l     F .text  00000004 main.in_flash\n//  10007611 l     F .text  0000000c __Thumbv6MABSLongThunk_main.in_ram\n//  1000761d l     F .text  0000000c __Thumbv6MABSLongThunk__Cgo_static_eea7585d7291176ad3bb_main_c_in_ram\n//  1000bdb5 l     O .text  00000013 main$string\n//  1000bdc8 l     O .text  00000013 main$string.1\n//  1000bddb l     O .text  00000013 main$string.2\n//  1000bdee l     O .text  00000013 main$string.3\n//  20000db1 l     F .data  00000004 main.in_ram\n//  20000db5 l     F .data  00000004 _Cgo_static_eea7585d7291176ad3bb_main_c_in_ram\n//\n\nimport (\n\t\"device\"\n\t\"fmt\"\n\t\"time\"\n\t_ \"unsafe\" // unsafe is required for \"//go:section\"\n)\n\n/*\n\t#define ram_func __attribute__((section(\".ramfuncs\"),noinline))\n\n\tstatic ram_func void* main_c_in_ram() {\n\t\tvoid* p = 0;\n\n\t\tasm(\n\t\t\t\"MOV %0, PC\"\n\t\t\t: \"=r\"(p)\n\t\t);\n\n\t\treturn p;\n\t}\n\n\tstatic void* main_c_in_flash() {\n\t\tvoid* p = 0;\n\n\t\tasm(\n\t\t\t\"MOV %0, PC\"\n\t\t\t: \"=r\"(p)\n\t\t);\n\n\t\treturn p;\n\t}\n*/\nimport \"C\"\n\nfunc main() {\n\ttime.Sleep(2 * time.Second)\n\n\tfmt.Printf(\"Go in RAM:    0x%X\\n\", in_ram())\n\tfmt.Printf(\"Go in flash:  0x%X\\n\", in_flash())\n\tfmt.Printf(\"cgo in RAM:   0x%X\\n\", C.main_c_in_ram())\n\tfmt.Printf(\"cgo in flash: 0x%X\\n\", C.main_c_in_flash())\n}\n\n//go:section .ramfuncs\nfunc in_ram() uintptr {\n\treturn device.AsmFull(\"MOV {}, PC\", nil)\n}\n\n// 'go:noinline' used here to prevent function being 'inlined' into main()\n// so it appears in objdump output.  In normal use, go:inline is not\n// required for functions running from flash (flash is the default).\n//\n//go:noinline\nfunc in_flash() uintptr {\n\treturn device.AsmFull(\"MOV {}, PC\", nil)\n}\n"
  },
  {
    "path": "src/examples/rand/main.go",
    "content": "package main\n\nimport (\n\t\"crypto/rand\"\n\t\"encoding/hex\"\n\t\"time\"\n)\n\nfunc main() {\n\tvar result [32]byte\n\tfor {\n\t\trand.Read(result[:])\n\t\tencodedString := hex.EncodeToString(result[:])\n\t\tprintln(encodedString)\n\t\ttime.Sleep(time.Second)\n\t}\n}\n"
  },
  {
    "path": "src/examples/rtcinterrupt/rtcinterrupt.go",
    "content": "//go:build rp2040\n\npackage main\n\n// This example demonstrates scheduling a delayed interrupt by real time clock.\n//\n// An interrupt may execute user callback function or used for its side effects\n// like waking up from sleep or dormant states.\n//\n// The interrupt can be configured to repeat.\n//\n// There is no separate method to disable interrupt, use 0 delay for that.\n//\n// Unfortunately, it is not possible to use time.Duration to work with RTC directly,\n// that would introduce a circular dependency between \"machine\" and \"time\" packages.\n\nimport (\n\t\"fmt\"\n\t\"machine\"\n\t\"time\"\n)\n\nfunc main() {\n\n\t// Schedule and enable recurring interrupt.\n\t// The callback function is executed in the context of an interrupt handler,\n\t// so regular restrictions for this sort of code apply: no blocking, no memory allocation, etc.\n\t// Please check the online documentation for the details about interrupts:\n\t// https://tinygo.org/docs/concepts/compiler-internals/interrupts/\n\tdelay := time.Minute + 12*time.Second\n\tmachine.RTC.SetInterrupt(uint32(delay.Seconds()), true, func() { println(\"Peekaboo!\") })\n\n\tfor {\n\t\tfmt.Printf(\"%v\\r\\n\", time.Now().Format(time.RFC3339))\n\t\ttime.Sleep(1 * time.Second)\n\t}\n}\n"
  },
  {
    "path": "src/examples/serial/serial.go",
    "content": "package main\n\nimport \"time\"\n\nfunc main() {\n\tfor {\n\t\tprintln(\"hello world!\")\n\t\ttime.Sleep(time.Second)\n\t}\n}\n"
  },
  {
    "path": "src/examples/systick/README.md",
    "content": "# TinyGo ARM SysTick example\n\nThis example uses the ARM System Timer to blink an LED.  The timer fires\nan interrupt 10 times per second.  The interrupt handler toggles the LED on\nand off.\n\nMany ARM-based chips have this timer feature.  If you run the example and the\nLED blinks, then you have one.\n\nThe System Timer runs from a cycle counter.  The more cycles, the slower the\nLED will blink.  This counter is 24 bits wide, which places an upper bound on\nthe number of cycles, and the slowness of the blinking.\n"
  },
  {
    "path": "src/examples/systick/systick.go",
    "content": "package main\n\nimport (\n\t\"device/arm\"\n\t\"machine\"\n)\n\nvar timerCh = make(chan struct{}, 1)\n\nfunc main() {\n\tmachine.LED.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\n\t// timer fires 10 times per second\n\tarm.SetupSystemTimer(machine.CPUFrequency() / 10)\n\n\tfor {\n\t\tmachine.LED.Low()\n\t\t<-timerCh\n\t\tmachine.LED.High()\n\t\t<-timerCh\n\t}\n}\n\n//export SysTick_Handler\nfunc timer_isr() {\n\tselect {\n\tcase timerCh <- struct{}{}:\n\tdefault:\n\t\t// The consumer is running behind.\n\t}\n}\n"
  },
  {
    "path": "src/examples/temp/temp.go",
    "content": "// Read the internal temperature sensor of the chip.\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"machine\"\n\t\"time\"\n)\n\ntype celsius float32\n\nfunc (c celsius) String() string {\n\treturn fmt.Sprintf(\"%4.1f℃\", c)\n}\n\nfunc main() {\n\tfor {\n\t\ttemp := celsius(float32(machine.ReadTemperature()) / 1000)\n\t\tprintln(\"temperature:\", temp.String())\n\t\ttime.Sleep(time.Second)\n\t}\n}\n"
  },
  {
    "path": "src/examples/time-offset/time-offset.go",
    "content": "package main\n\n// This example demonstrates how to set the system time.\n//\n// Usually, boards don't keep time on power cycles and restarts, it resets to Unix epoch.\n// The system time can be set by calling runtime.AdjustTimeOffset().\n//\n// Possible time sources: an external RTC clock or network (WiFi access point or NTP server)\n\nimport (\n\t\"fmt\"\n\t\"runtime\"\n\t\"time\"\n)\n\nconst myTime = \"2006-01-02T15:04:05Z\" // this is an example time you source somewhere\n\nfunc main() {\n\n\t// measure how many nanoseconds the internal clock is behind\n\ttimeOfMeasurement := time.Now()\n\tactualTime, _ := time.Parse(time.RFC3339, myTime)\n\toffset := actualTime.Sub(timeOfMeasurement)\n\n\t// adjust internal clock by adding the offset to the internal clock\n\truntime.AdjustTimeOffset(int64(offset))\n\n\tfor {\n\t\tfmt.Printf(\"%v\\r\\n\", time.Now().Format(time.RFC3339))\n\t\ttime.Sleep(5 * time.Second)\n\t}\n}\n"
  },
  {
    "path": "src/examples/uart/uart.go",
    "content": "// This reads from UART1 and outputs to default serial, usually UART0 or USB.\n// Example of how to work with UARTs other than the default.\npackage main\n\nimport (\n\t\"machine\"\n\t\"time\"\n)\n\nvar (\n\tuart = machine.UART1\n\ttx   = machine.UART1_TX_PIN\n\trx   = machine.UART1_RX_PIN\n)\n\nfunc main() {\n\tuart.Configure(machine.UARTConfig{TX: tx, RX: rx})\n\tfor {\n\t\tif uart.Buffered() > 0 {\n\t\t\tdata, _ := uart.ReadByte()\n\t\t\tprint(string(data))\n\t\t}\n\t\ttime.Sleep(10 * time.Millisecond)\n\t}\n}\n"
  },
  {
    "path": "src/examples/usb-midi/main.go",
    "content": "package main\n\nimport (\n\t\"machine\"\n\t\"machine/usb/adc/midi\"\n\n\t\"time\"\n)\n\n// Try it easily by opening the following site in Chrome.\n// https://www.onlinemusictools.com/kb/\n\nconst (\n\tcable    = 0\n\tchannel  = 1\n\tvelocity = 0x40\n)\n\nfunc main() {\n\tled := machine.LED\n\tled.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\n\tbutton := machine.BUTTON\n\tbutton.Configure(machine.PinConfig{Mode: machine.PinInputPullup})\n\n\tm := midi.Port()\n\tm.SetRxHandler(func(b []byte) {\n\t\t// blink when we receive a MIDI message\n\t\tled.Set(!led.Get())\n\t})\n\n\tm.SetTxHandler(func() {\n\t\t// blink when we send a MIDI message\n\t\tled.Set(!led.Get())\n\t})\n\n\tprev := true\n\tchords := []struct {\n\t\tname  string\n\t\tnotes []midi.Note\n\t}{\n\t\t{name: \"C \", notes: []midi.Note{midi.C4, midi.E4, midi.G4}},\n\t\t{name: \"G \", notes: []midi.Note{midi.G3, midi.B3, midi.D4}},\n\t\t{name: \"Am\", notes: []midi.Note{midi.A3, midi.C4, midi.E4}},\n\t\t{name: \"F \", notes: []midi.Note{midi.F3, midi.A3, midi.C4}},\n\t}\n\tindex := 0\n\n\tfor {\n\t\tcurrent := button.Get()\n\t\tif prev != current {\n\t\t\tif current {\n\t\t\t\tfor _, note := range chords[index].notes {\n\t\t\t\t\tm.NoteOff(cable, channel, note, velocity)\n\t\t\t\t}\n\t\t\t\tindex = (index + 1) % len(chords)\n\t\t\t} else {\n\t\t\t\tfor _, note := range chords[index].notes {\n\t\t\t\t\tm.NoteOn(cable, channel, note, velocity)\n\t\t\t\t}\n\t\t\t}\n\t\t\tprev = current\n\t\t}\n\t\ttime.Sleep(100 * time.Millisecond)\n\t}\n}\n"
  },
  {
    "path": "src/examples/usb-storage/main.go",
    "content": "package main\n\nimport (\n\t\"machine\"\n\t\"machine/usb/msc\"\n\t\"time\"\n)\n\nfunc main() {\n\tmsc.Port(machine.Flash)\n\n\tfor {\n\t\ttime.Sleep(2 * time.Second)\n\t}\n}\n"
  },
  {
    "path": "src/examples/wasm/.gitignore",
    "content": "html/*\n"
  },
  {
    "path": "src/examples/wasm/GNUmakefile",
    "content": "invoke: clean wasm_exec\n\ttinygo build -o ./html/wasm.wasm -target wasm -no-debug ./invoke/wasm.go\n\tcp ./invoke/wasm.js ./html/\n\tcp ./invoke/index.html ./html/\n\nexport: clean wasm_exec\n\ttinygo build -o ./html/wasm.wasm -target wasm -no-debug ./export/wasm.go\n\tcp ./export/wasm.js ./html/\n\tcp ./export/index.html ./html/\n\ncallback: clean wasm_exec\n\ttinygo build -o ./html/wasm.wasm -target wasm ./callback/wasm.go\n\tcp ./callback/wasm.js ./html/\n\tcp ./callback/index.html ./html/\n\nslices: clean wasm_exec\n\ttinygo build -o ./html/wasm.wasm -target wasm -no-debug ./slices/wasm.go\n\tcp ./slices/wasm.js ./html/\n\tcp ./slices/index.html ./html/\n\n\nmain: clean wasm_exec\n\ttinygo build -o ./html/wasm.wasm -target wasm -no-debug ./main/main.go\n\tcp ./main/index.html ./html/\n\nwasm_exec:\n\tcp `tinygo env TINYGOROOT`/targets/wasm_exec.js ./html/\n\nclean:\n\trm -rf ./html\n\tmkdir ./html\n"
  },
  {
    "path": "src/examples/wasm/README.md",
    "content": "# TinyGo WebAssembly examples\n\nThe examples here show two different ways of using WebAssembly with TinyGo:\n\n1. Defining and exporting functions via the `//export <name>` directive. See\n[the export folder](./export) for an example of this.  Additionally, the Wasm\nmodule (which has a default value of `env`) can be specified using\n`//go:wasm-module <module>`.\n1. Defining and executing a `func main()`. This is similar to how the Go\nstandard library implementation works. See [the main folder](./main) for an\nexample of this.\n\n## Building\n\nBuild using the `tinygo` compiler:\n\n```bash\n$ tinygo build -o ./wasm.wasm -target wasm ./main/main.go\n```\n\nThis creates a `wasm.wasm` file, which we can load in JavaScript and execute in\na browser.\n\nNext, choose which example you want to use:\n* [callback](callback): Defines and configures callbacks in Wasm.\n* [export](export): Defines callbacks in Wasm, but configures them in JavaScript.\n* [invoke](invoke): Invokes a function defined in JavaScript from Wasm.\n* [main](main): Prints a message to the JavaScript console from Wasm.\n* [slices](slices): Splits an Array defined in JavaScript from Wasm.\n\nLet's say you chose [main](main), you'd build it like so:\n```bash\n$ make main\n```\n\n## Running\n\nStart the local web server:\n\n```bash\n$ go run server.go\nServing ./html on http://localhost:8080\n```\n\nUse your web browser to visit http://localhost:8080.\n\n* Tip: Open the browser development tools (e.g. Right-click, Inspect in\n  FireFox) to see console output.\n\n## How it works\n\nExecution of the contents require a few JavaScript helper functions which are\ncalled from WebAssembly.\n\nWe have defined these in [wasm_exec.js](../../../targets/wasm_exec.js).  It is\nbased on `$GOROOT/misc/wasm/wasm_exec.js` from the standard library, but is\nslightly different. Ensure you are using the same version of `wasm_exec.js` as\nthe version of `tinygo` you are using to compile.\n\nThe general steps required to run the WebAssembly file in the browser includes\nloading it into JavaScript with `WebAssembly.instantiateStreaming`, or\n`WebAssembly.instantiate` in some browsers:\n\n```js\nconst go = new Go(); // Defined in wasm_exec.js\nconst WASM_URL = 'wasm.wasm';\n\nvar wasm;\n\nif ('instantiateStreaming' in WebAssembly) {\n\tWebAssembly.instantiateStreaming(fetch(WASM_URL), go.importObject).then(function (obj) {\n\t\twasm = obj.instance;\n\t\tgo.run(wasm);\n\t})\n} else {\n\tfetch(WASM_URL).then(resp =>\n\t\tresp.arrayBuffer()\n\t).then(bytes =>\n\t\tWebAssembly.instantiate(bytes, go.importObject).then(function (obj) {\n\t\t\twasm = obj.instance;\n\t\t\tgo.run(wasm);\n\t\t})\n\t)\n}\n```\n\nIf you have used explicit exports, you can call them by invoking them under the\n`wasm.exports` namespace. See the [`export`](./export/wasm.js) directory for an\nexample of this.\n\nIn addition to the JavaScript, it is important the wasm file is served with the\n[`Content-Type`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type)\nheader set to `application/wasm`.  Without it, most browsers won't run it.\n\n```go\npackage main\n\nimport (\n\t\"log\"\n\t\"net/http\"\n\t\"strings\"\n)\n\nconst dir = \"./html\"\n\nfunc main() {\n\tfs := http.FileServer(http.Dir(dir))\n\tlog.Print(\"Serving \" + dir + \" on http://localhost:8080\")\n\thttp.ListenAndServe(\":8080\", http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {\n\t\tresp.Header().Add(\"Cache-Control\", \"no-cache\")\n\t\tif strings.HasSuffix(req.URL.Path, \".wasm\") {\n\t\t\tresp.Header().Set(\"content-type\", \"application/wasm\")\n\t\t}\n\t\tfs.ServeHTTP(resp, req)\n\t}))}\n```\n\nThis simple server serves anything inside the `./html` directory on port\n`8080`, setting any `*.wasm` files `Content-Type` header appropriately.\n\nFor development purposes (**only!**), it also sets the `Cache-Control` header\nso your browser doesn't cache the files.  This is useful while developing, to\nensure your browser displays the newest wasm when you recompile.\n\nIn a production environment you **probably wouldn't** want to set the\n`Cache-Control` header like this.  Caching is generally beneficial for end\nusers.\n\nFurther information on the `Cache-Control` header can be found here:\n\n* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control\n"
  },
  {
    "path": "src/examples/wasm/callback/index.html",
    "content": "<!DOCTYPE html>\n\n<html>\n\n<head>\n\t<meta charset=\"utf-8\" />\n\t<title>Go WebAssembly</title>\n\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n\t<script src=\"wasm_exec.js\" defer></script>\n\t<script src=\"wasm.js\" defer></script>\n</head>\n\n<body>\n\t<h1>WebAssembly</h1>\n\t<p>Add two numbers, using WebAssembly:</p>\n\t<input type=\"number\" id=\"a\" value=\"0\" /> + <input type=\"number\" id=\"b\" value=\"0\" /> = <input type=\"number\" id=\"result\" readonly />\n</body>\n\n</html>\n"
  },
  {
    "path": "src/examples/wasm/callback/wasm.go",
    "content": "package main\n\nimport (\n\t\"strconv\"\n\t\"syscall/js\"\n)\n\nvar a, b int\n\nfunc main() {\n\twait := make(chan struct{}, 0)\n\tdocument := js.Global().Get(\"document\")\n\tdocument.Call(\"getElementById\", \"a\").Set(\"oninput\", updater(&a))\n\tdocument.Call(\"getElementById\", \"b\").Set(\"oninput\", updater(&b))\n\tupdate()\n\t<-wait\n}\n\nfunc updater(n *int) js.Func {\n\treturn js.FuncOf(func(this js.Value, args []js.Value) interface{} {\n\t\t*n, _ = strconv.Atoi(this.Get(\"value\").String())\n\t\tupdate()\n\t\treturn nil\n\t})\n}\n\nfunc update() {\n\tjs.Global().Get(\"document\").Call(\"getElementById\", \"result\").Set(\"value\", a+b)\n}\n"
  },
  {
    "path": "src/examples/wasm/callback/wasm.js",
    "content": "'use strict';\n\nconst WASM_URL = 'wasm.wasm';\n\nvar wasm;\n\nfunction init() {\n  const go = new Go();\n  if ('instantiateStreaming' in WebAssembly) {\n    WebAssembly.instantiateStreaming(fetch(WASM_URL), go.importObject).then(function (obj) {\n      wasm = obj.instance;\n      go.run(wasm);\n    })\n  } else {\n    fetch(WASM_URL).then(resp =>\n      resp.arrayBuffer()\n    ).then(bytes =>\n      WebAssembly.instantiate(bytes, go.importObject).then(function (obj) {\n        wasm = obj.instance;\n        go.run(wasm);\n      })\n    )\n  }\n}\n\ninit();\n"
  },
  {
    "path": "src/examples/wasm/export/index.html",
    "content": "<!DOCTYPE html>\n\n<html>\n\n<head>\n\t<meta charset=\"utf-8\" />\n\t<title>Go WebAssembly</title>\n\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n\t<script src=\"wasm_exec.js\" defer></script>\n\t<script src=\"wasm.js\" defer></script>\n</head>\n\n<body>\n\t<h1>WebAssembly</h1>\n\t<p>Add two numbers, using WebAssembly:</p>\n\t<input type=\"number\" id=\"a\" value=\"2\" /> + <input type=\"number\" id=\"b\" value=\"2\" /> = <input type=\"number\"\n\t\tid=\"result\" readonly />\n</body>\n\n</html>\n"
  },
  {
    "path": "src/examples/wasm/export/wasm.go",
    "content": "package main\n\nimport (\n\t\"strconv\"\n\t\"syscall/js\"\n)\n\nfunc main() {\n}\n\n//export add\nfunc add(a, b int) int {\n\treturn a + b\n}\n\n//export update\nfunc update() {\n\tdocument := js.Global().Get(\"document\")\n\taStr := document.Call(\"getElementById\", \"a\").Get(\"value\").String()\n\tbStr := document.Call(\"getElementById\", \"b\").Get(\"value\").String()\n\ta, _ := strconv.Atoi(aStr)\n\tb, _ := strconv.Atoi(bStr)\n\tresult := add(a, b)\n\tdocument.Call(\"getElementById\", \"result\").Set(\"value\", result)\n}\n"
  },
  {
    "path": "src/examples/wasm/export/wasm.js",
    "content": "'use strict';\n\nconst WASM_URL = 'wasm.wasm';\n\nvar wasm;\n\nfunction updateResult() {\n  wasm.exports.update();\n}\n\nfunction init() {\n  document.querySelector('#a').oninput = updateResult;\n  document.querySelector('#b').oninput = updateResult;\n\n  const go = new Go();\n  if ('instantiateStreaming' in WebAssembly) {\n    WebAssembly.instantiateStreaming(fetch(WASM_URL), go.importObject).then(function (obj) {\n      wasm = obj.instance;\n      go.run(wasm);\n      updateResult();\n    })\n  } else {\n    fetch(WASM_URL).then(resp =>\n      resp.arrayBuffer()\n    ).then(bytes =>\n      WebAssembly.instantiate(bytes, go.importObject).then(function (obj) {\n        wasm = obj.instance;\n        go.run(wasm);\n        updateResult();\n      })\n    )\n  }\n}\n\ninit();\n"
  },
  {
    "path": "src/examples/wasm/invoke/index.html",
    "content": "<!DOCTYPE html>\n\n<html>\n\n<head>\n    <meta charset=\"utf-8\"/>\n    <title>Go WebAssembly</title>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/>\n    <script src=\"wasm_exec.js\" defer></script>\n    <script src=\"wasm.js\" defer></script>\n</head>\n\n<body>\n    <h1>WebAssembly</h1>\n    <p>Edit on either side to mimic values, using WebAssembly:</p>\n    <input type=\"text\" id=\"a\" value=\"\"/>==<input type=\"text\" id=\"b\" value=\"\"/>\n</body>\n\n</html>\n"
  },
  {
    "path": "src/examples/wasm/invoke/wasm.go",
    "content": "package main\n\nimport (\n\t\"syscall/js\"\n)\n\nfunc runner(this js.Value, args []js.Value) interface{} {\n\treturn args[0].Invoke(args[1]).String()\n}\n\nfunc main() {\n\twait := make(chan struct{}, 0)\n\tjs.Global().Set(\"runner\", js.FuncOf(runner))\n\t<-wait\n}\n"
  },
  {
    "path": "src/examples/wasm/invoke/wasm.js",
    "content": "'use strict';\n\nconst WASM_URL = 'wasm.wasm';\n\nvar wasm;\n\nfunction updateRight() {\n    const value = document.getElementById(\"a\").value;\n    window.runner(function (value) {\n        document.getElementById(\"b\").value = value;\n    }, value);\n}\n\nfunction updateLeft() {\n    const value = document.getElementById(\"b\").value;\n    window.runner(function (value) {\n        document.getElementById(\"a\").value = value;\n    }, value);\n}\n\nfunction init() {\n    document.querySelector('#a').oninput = updateRight;\n    document.querySelector('#b').oninput = updateLeft;\n\n    const go = new Go();\n    if ('instantiateStreaming' in WebAssembly) {\n        WebAssembly.instantiateStreaming(fetch(WASM_URL), go.importObject).then(function (obj) {\n            wasm = obj.instance;\n            go.run(wasm);\n        })\n    } else {\n        fetch(WASM_URL).then(resp =>\n            resp.arrayBuffer()\n        ).then(bytes =>\n            WebAssembly.instantiate(bytes, go.importObject).then(function (obj) {\n                wasm = obj.instance;\n                go.run(wasm);\n            })\n        )\n    }\n}\n\ninit();\n"
  },
  {
    "path": "src/examples/wasm/main/README.md",
    "content": "# WebAssembly main execution example\n\nA simple hello world that prints to the browser console.\n\n## License\n\nNote that `index.html` is copied almost verbatim from the Go 1.12 source at\n`$GOROOT/misc/wasm/wasm_exec.html`. Its license applies to this file.\n"
  },
  {
    "path": "src/examples/wasm/main/index.html",
    "content": "<!doctype html>\n<!--\nCopyright 2018 The Go Authors. All rights reserved.\nUse of this source code is governed by a BSD-style\nlicense that can be found in the LICENSE file.\n-->\n<html>\n\n<head>\n\t<meta charset=\"utf-8\">\n\t<title>Go wasm</title>\n</head>\n\n<body>\n\t<!--\n\tAdd the following polyfill for Microsoft Edge 17/18 support:\n\t<script src=\"https://cdn.jsdelivr.net/npm/text-encoding@0.7.0/lib/encoding.min.js\"></script>\n\t(see https://caniuse.com/#feat=textencoder)\n\t-->\n\t<script src=\"wasm_exec.js\"></script>\n\t<script>\n\t\tif (!WebAssembly.instantiateStreaming) { // polyfill\n\t\t\tWebAssembly.instantiateStreaming = async (resp, importObject) => {\n\t\t\t\tconst source = await (await resp).arrayBuffer();\n\t\t\t\treturn await WebAssembly.instantiate(source, importObject);\n\t\t\t};\n\t\t}\n\n\t\tconst go = new Go();\n\t\tlet mod, inst;\n\t\tWebAssembly.instantiateStreaming(fetch(\"wasm.wasm\"), go.importObject).then((result) => {\n\t\t\tmod = result.module;\n\t\t\tinst = result.instance;\n\t\t\tdocument.getElementById(\"runButton\").disabled = false;\n\t\t}).catch((err) => {\n\t\t\tconsole.error(err);\n\t\t});\n\n\t\tasync function run() {\n\t\t\tconsole.clear();\n\t\t\tawait go.run(inst);\n\t\t\tinst = await WebAssembly.instantiate(mod, go.importObject); // reset instance\n\t\t}\n\t</script>\n\n\t<button onClick=\"run();\" id=\"runButton\" disabled>Run</button>\n</body>\n\n</html>\n"
  },
  {
    "path": "src/examples/wasm/main/main.go",
    "content": "package main\n\nfunc main() {\n\tprintln(\"Hello world!\")\n}\n"
  },
  {
    "path": "src/examples/wasm/server.go",
    "content": "package main\n\nimport (\n\t\"log\"\n\t\"net/http\"\n\t\"strings\"\n)\n\nconst dir = \"./html\"\n\nfunc main() {\n\tfs := http.FileServer(http.Dir(dir))\n\tlog.Print(\"Serving \" + dir + \" on http://localhost:8080\")\n\thttp.ListenAndServe(\":8080\", http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {\n\t\tresp.Header().Add(\"Cache-Control\", \"no-cache\")\n\t\tif strings.HasSuffix(req.URL.Path, \".wasm\") {\n\t\t\tresp.Header().Set(\"content-type\", \"application/wasm\")\n\t\t}\n\t\tfs.ServeHTTP(resp, req)\n\t}))\n}\n"
  },
  {
    "path": "src/examples/wasm/slices/index.html",
    "content": "<!DOCTYPE html>\n\n<html>\n\n<head>\n    <meta charset=\"utf-8\"/>\n    <title>Go WebAssembly</title>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/>\n    <script src=\"wasm_exec.js\" defer></script>\n    <script src=\"wasm.js\" defer></script>\n</head>\n\n<body>\n    <h1>WebAssembly</h1>\n    <p>type values separated by comma, using WebAssembly:</p>\n    <input type=\"text\" id=\"a\" value=\"\"/>==<div id=\"b\"></div>\n</body>\n\n</html>\n"
  },
  {
    "path": "src/examples/wasm/slices/wasm.go",
    "content": "package main\n\nimport (\n\t\"strings\"\n\t\"syscall/js\"\n)\n\nfunc splitter(this js.Value, args []js.Value) interface{} {\n\tvalues := strings.Split(args[0].String(), \",\")\n\n\tresult := make([]interface{}, 0)\n\tfor _, each := range values {\n\t\tresult = append(result, each)\n\t}\n\n\treturn js.ValueOf(result)\n}\n\nfunc main() {\n\twait := make(chan struct{}, 0)\n\tjs.Global().Set(\"splitter\", js.FuncOf(splitter))\n\t<-wait\n}\n"
  },
  {
    "path": "src/examples/wasm/slices/wasm.js",
    "content": "'use strict';\n\nconst WASM_URL = 'wasm.wasm';\n\nvar wasm;\n\nfunction update() {\n    const value = document.getElementById(\"a\").value;\n    document.getElementById(\"b\").innerHTML = JSON.stringify(window.splitter(value));\n}\n\nfunction init() {\n    document.querySelector('#a').oninput = update;\n\n    const go = new Go();\n    if ('instantiateStreaming' in WebAssembly) {\n        WebAssembly.instantiateStreaming(fetch(WASM_URL), go.importObject).then(function (obj) {\n            wasm = obj.instance;\n            go.run(wasm);\n        })\n    } else {\n        fetch(WASM_URL).then(resp =>\n            resp.arrayBuffer()\n        ).then(bytes =>\n            WebAssembly.instantiate(bytes, go.importObject).then(function (obj) {\n                wasm = obj.instance;\n                go.run(wasm);\n            })\n        )\n    }\n}\n\ninit();\n"
  },
  {
    "path": "src/examples/watchdog/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"machine\"\n\t\"time\"\n)\n\nfunc main() {\n\t//sleep for 2 secs for console\n\ttime.Sleep(2 * time.Second)\n\n\tconfig := machine.WatchdogConfig{\n\t\tTimeoutMillis: 1000,\n\t}\n\n\tprintln(\"configuring watchdog for max 1 second updates\")\n\tmachine.Watchdog.Configure(config)\n\n\t// From this point the watchdog is running and Update must be\n\t// called periodically, per the config\n\tmachine.Watchdog.Start()\n\n\t// This loop should complete because watchdog update is called\n\t// every 100ms.\n\tstart := time.Now()\n\tprintln(\"updating watchdog for 3 seconds\")\n\tfor i := 0; i < 30; i++ {\n\t\ttime.Sleep(100 * time.Millisecond)\n\t\tmachine.Watchdog.Update()\n\t\tfmt.Printf(\"alive @ %v\\n\", time.Now().Sub(start))\n\t}\n\n\t// This loop should cause a watchdog reset after 1s since\n\t// there is no update call.\n\tstart = time.Now()\n\tprintln(\"entering tight loop\")\n\tfor {\n\t\ttime.Sleep(100 * time.Millisecond)\n\t\tfmt.Printf(\"alive @ %v\\n\", time.Now().Sub(start))\n\t}\n}\n"
  },
  {
    "path": "src/internal/abi/abi.go",
    "content": "// Package abi exposes low-level details of the Go compiler/runtime\npackage abi\n"
  },
  {
    "path": "src/internal/abi/escape.go",
    "content": "package abi\n\nimport \"unsafe\"\n\n// Tell the compiler the given pointer doesn't escape.\n// The compiler knows about this function and will give the nocapture parameter\n// attribute.\nfunc NoEscape(p unsafe.Pointer) unsafe.Pointer {\n\treturn p\n}\n\nfunc Escape[T any](x T) T {\n\t// This function is either implemented in the compiler, or left undefined\n\t// for some variation of T. The body of this function should not be compiled\n\t// as-is.\n\tpanic(\"internal/abi.Escape: unreachable (implemented in the compiler)\")\n}\n"
  },
  {
    "path": "src/internal/abi/funcpc.go",
    "content": "package abi\n\n// These two signatures are present to satisfy the expectation of some programs\n// (in particular internal/syscall/unix on MacOS). They do not currently have an\n// implementation, in part because TinyGo doesn't use ABI0 or ABIInternal (it\n// uses a C-like calling convention).\n// Calls to FuncPCABI0 however are treated specially by the compiler when\n// compiling for MacOS.\n\nfunc FuncPCABI0(f interface{}) uintptr\n\nfunc FuncPCABIInternal(f interface{}) uintptr\n"
  },
  {
    "path": "src/internal/abi/type.go",
    "content": "package abi\n\ntype Type struct {\n\t// Intentionally left empty. TinyGo uses a different way to represent types,\n\t// so this is unimplementable. The type definition here is purely for\n\t// compatibility.\n}\n"
  },
  {
    "path": "src/internal/binary/binary.go",
    "content": "// Package binary is a lightweight replacement package for encoding/binary.\npackage binary\n\n// This file contains small helper functions for working with binary data.\n\nvar LittleEndian = littleEndian{}\n\ntype littleEndian struct{}\n\n// Encode data like encoding/binary.LittleEndian.Uint16.\nfunc (littleEndian) Uint16(b []byte) uint16 {\n\treturn uint16(b[0]) | uint16(b[1])<<8\n}\n\n// Store data like binary.LittleEndian.PutUint16.\nfunc (littleEndian) PutUint16(b []byte, v uint16) {\n\tb[0] = byte(v)\n\tb[1] = byte(v >> 8)\n}\n\n// Append data like binary.LittleEndian.AppendUint16.\nfunc (littleEndian) AppendUint16(b []byte, v uint16) []byte {\n\treturn append(b,\n\t\tbyte(v),\n\t\tbyte(v>>8),\n\t)\n}\n\n// Encode data like encoding/binary.LittleEndian.Uint32.\nfunc (littleEndian) Uint32(b []byte) uint32 {\n\treturn uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24\n}\n\nfunc (littleEndian) Uint64(b []byte) uint64 {\n\treturn uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |\n\t\tuint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56\n}\n"
  },
  {
    "path": "src/internal/bytealg/bytealg.go",
    "content": "package bytealg\n\n// Some code in this file has been copied from the Go source code, and has\n// copyright of their original authors:\n//\n// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n//\n// This is indicated specifically in the file.\n\nconst (\n\t// Index can search any valid length of string.\n\n\tMaxLen        = int(-1) >> 31\n\tMaxBruteForce = MaxLen\n)\n\n// Compare two byte slices.\n// Returns -1 if the first differing byte is lower in a, or 1 if the first differing byte is greater in b.\n// If the byte slices are equal, returns 0.\n// If the lengths are different and there are no differing bytes, compares based on length.\nfunc Compare(a, b []byte) int {\n\t// Compare for differing bytes.\n\tfor i := 0; i < len(a) && i < len(b); i++ {\n\t\tswitch {\n\t\tcase a[i] < b[i]:\n\t\t\treturn -1\n\t\tcase a[i] > b[i]:\n\t\t\treturn 1\n\t\t}\n\t}\n\n\t// Compare lengths.\n\tswitch {\n\tcase len(a) > len(b):\n\t\treturn 1\n\tcase len(a) < len(b):\n\t\treturn -1\n\tdefault:\n\t\treturn 0\n\t}\n}\n\n// This function was copied from the Go 1.23 source tree (with runtime_cmpstring\n// manually inlined).\nfunc CompareString(a, b string) int {\n\tl := len(a)\n\tif len(b) < l {\n\t\tl = len(b)\n\t}\n\tfor i := 0; i < l; i++ {\n\t\tc1, c2 := a[i], b[i]\n\t\tif c1 < c2 {\n\t\t\treturn -1\n\t\t}\n\t\tif c1 > c2 {\n\t\t\treturn +1\n\t\t}\n\t}\n\tif len(a) < len(b) {\n\t\treturn -1\n\t}\n\tif len(a) > len(b) {\n\t\treturn +1\n\t}\n\treturn 0\n}\n\n// Count the number of instances of a byte in a slice.\nfunc Count(b []byte, c byte) int {\n\t// Use a simple implementation, as there is no intrinsic that does this like we want.\n\tn := 0\n\tfor _, v := range b {\n\t\tif v == c {\n\t\t\tn++\n\t\t}\n\t}\n\treturn n\n}\n\n// Count the number of instances of a byte in a string.\nfunc CountString(s string, c byte) int {\n\t// Use a simple implementation, as there is no intrinsic that does this like we want.\n\t// Currently, the compiler does not generate zero-copy byte-string conversions, so this needs to be separate from Count.\n\tn := 0\n\tfor i := 0; i < len(s); i++ {\n\t\tif s[i] == c {\n\t\t\tn++\n\t\t}\n\t}\n\treturn n\n}\n\n// Cutover is not reachable in TinyGo, but must exist as it is referenced.\nfunc Cutover(n int) int {\n\t// Setting MaxLen and MaxBruteForce should force a different path to be taken.\n\t// This should never be called.\n\tpanic(\"cutover is unreachable\")\n}\n\n// Equal checks if two byte slices are equal.\n// It is equivalent to bytes.Equal.\nfunc Equal(a, b []byte) bool {\n\tif len(a) != len(b) {\n\t\treturn false\n\t}\n\n\tfor i, v := range a {\n\t\tif v != b[i] {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\n// Index finds the base index of the first instance of the byte sequence b in a.\n// If a does not contain b, this returns -1.\nfunc Index(a, b []byte) int {\n\tfor i := 0; i <= len(a)-len(b); i++ {\n\t\tif Equal(a[i:i+len(b)], b) {\n\t\t\treturn i\n\t\t}\n\t}\n\treturn -1\n}\n\n// Index finds the index of the first instance of the specified byte in the slice.\n// If the byte is not found, this returns -1.\nfunc IndexByte(b []byte, c byte) int {\n\tfor i, v := range b {\n\t\tif v == c {\n\t\t\treturn i\n\t\t}\n\t}\n\treturn -1\n}\n\n// Index finds the index of the first instance of the specified byte in the string.\n// If the byte is not found, this returns -1.\nfunc IndexByteString(s string, c byte) int {\n\tfor i := 0; i < len(s); i++ {\n\t\tif s[i] == c {\n\t\t\treturn i\n\t\t}\n\t}\n\treturn -1\n}\n\n// Index finds the base index of the first instance of a substring in a string.\n// If the substring is not found, this returns -1.\nfunc IndexString(str, sub string) int {\n\tfor i := 0; i <= len(str)-len(sub); i++ {\n\t\tif str[i:i+len(sub)] == sub {\n\t\t\treturn i\n\t\t}\n\t}\n\treturn -1\n}\n\n// The following code has been copied from the Go 1.15 release tree.\n\n// PrimeRK is the prime base used in Rabin-Karp algorithm.\nconst PrimeRK = 16777619\n\n// HashStrBytes returns the hash and the appropriate multiplicative\n// factor for use in Rabin-Karp algorithm.\n//\n// This function was removed in Go 1.22.\nfunc HashStrBytes(sep []byte) (uint32, uint32) {\n\thash := uint32(0)\n\tfor i := 0; i < len(sep); i++ {\n\t\thash = hash*PrimeRK + uint32(sep[i])\n\t}\n\tvar pow, sq uint32 = 1, PrimeRK\n\tfor i := len(sep); i > 0; i >>= 1 {\n\t\tif i&1 != 0 {\n\t\t\tpow *= sq\n\t\t}\n\t\tsq *= sq\n\t}\n\treturn hash, pow\n}\n\n// HashStr returns the hash and the appropriate multiplicative\n// factor for use in Rabin-Karp algorithm.\n//\n// This function was removed in Go 1.22.\nfunc HashStr[T string | []byte](sep T) (uint32, uint32) {\n\thash := uint32(0)\n\tfor i := 0; i < len(sep); i++ {\n\t\thash = hash*PrimeRK + uint32(sep[i])\n\t}\n\tvar pow, sq uint32 = 1, PrimeRK\n\tfor i := len(sep); i > 0; i >>= 1 {\n\t\tif i&1 != 0 {\n\t\t\tpow *= sq\n\t\t}\n\t\tsq *= sq\n\t}\n\treturn hash, pow\n}\n\n// HashStrRevBytes returns the hash of the reverse of sep and the\n// appropriate multiplicative factor for use in Rabin-Karp algorithm.\n//\n// This function was removed in Go 1.22.\nfunc HashStrRevBytes(sep []byte) (uint32, uint32) {\n\thash := uint32(0)\n\tfor i := len(sep) - 1; i >= 0; i-- {\n\t\thash = hash*PrimeRK + uint32(sep[i])\n\t}\n\tvar pow, sq uint32 = 1, PrimeRK\n\tfor i := len(sep); i > 0; i >>= 1 {\n\t\tif i&1 != 0 {\n\t\t\tpow *= sq\n\t\t}\n\t\tsq *= sq\n\t}\n\treturn hash, pow\n}\n\n// HashStrRev returns the hash of the reverse of sep and the\n// appropriate multiplicative factor for use in Rabin-Karp algorithm.\n//\n// Copied from the Go 1.22rc1 source tree.\nfunc HashStrRev[T string | []byte](sep T) (uint32, uint32) {\n\thash := uint32(0)\n\tfor i := len(sep) - 1; i >= 0; i-- {\n\t\thash = hash*PrimeRK + uint32(sep[i])\n\t}\n\tvar pow, sq uint32 = 1, PrimeRK\n\tfor i := len(sep); i > 0; i >>= 1 {\n\t\tif i&1 != 0 {\n\t\t\tpow *= sq\n\t\t}\n\t\tsq *= sq\n\t}\n\treturn hash, pow\n}\n\n// IndexRabinKarpBytes uses the Rabin-Karp search algorithm to return the index of the\n// first occurrence of substr in s, or -1 if not present.\n//\n// This function was removed in Go 1.22.\nfunc IndexRabinKarpBytes(s, sep []byte) int {\n\t// Rabin-Karp search\n\thashsep, pow := HashStrBytes(sep)\n\tn := len(sep)\n\tvar h uint32\n\tfor i := 0; i < n; i++ {\n\t\th = h*PrimeRK + uint32(s[i])\n\t}\n\tif h == hashsep && Equal(s[:n], sep) {\n\t\treturn 0\n\t}\n\tfor i := n; i < len(s); {\n\t\th *= PrimeRK\n\t\th += uint32(s[i])\n\t\th -= pow * uint32(s[i-n])\n\t\ti++\n\t\tif h == hashsep && Equal(s[i-n:i], sep) {\n\t\t\treturn i - n\n\t\t}\n\t}\n\treturn -1\n}\n\n// IndexRabinKarp uses the Rabin-Karp search algorithm to return the index of the\n// first occurrence of sep in s, or -1 if not present.\n//\n// Copied from the Go 1.22rc1 source tree.\nfunc IndexRabinKarp[T string | []byte](s, sep T) int {\n\t// Rabin-Karp search\n\thashss, pow := HashStr(sep)\n\tn := len(sep)\n\tvar h uint32\n\tfor i := 0; i < n; i++ {\n\t\th = h*PrimeRK + uint32(s[i])\n\t}\n\tif h == hashss && string(s[:n]) == string(sep) {\n\t\treturn 0\n\t}\n\tfor i := n; i < len(s); {\n\t\th *= PrimeRK\n\t\th += uint32(s[i])\n\t\th -= pow * uint32(s[i-n])\n\t\ti++\n\t\tif h == hashss && string(s[i-n:i]) == string(sep) {\n\t\t\treturn i - n\n\t\t}\n\t}\n\treturn -1\n}\n\n// MakeNoZero makes a slice of length and capacity n without zeroing the bytes.\n// It is the caller's responsibility to ensure uninitialized bytes\n// do not leak to the end user.\nfunc MakeNoZero(n int) []byte {\n\t// Note: this does zero the buffer even though that's not necessary.\n\t// For performance reasons we might want to change this (similar to the\n\t// malloc function implemented in the runtime).\n\treturn make([]byte, n)\n}\n\n// Copied from the Go 1.22rc1 source tree.\nfunc LastIndexByte(s []byte, c byte) int {\n\tfor i := len(s) - 1; i >= 0; i-- {\n\t\tif s[i] == c {\n\t\t\treturn i\n\t\t}\n\t}\n\treturn -1\n}\n\n// Copied from the Go 1.22rc1 source tree.\nfunc LastIndexByteString(s string, c byte) int {\n\tfor i := len(s) - 1; i >= 0; i-- {\n\t\tif s[i] == c {\n\t\t\treturn i\n\t\t}\n\t}\n\treturn -1\n}\n\n// LastIndexRabinKarp uses the Rabin-Karp search algorithm to return the last index of the\n// occurrence of sep in s, or -1 if not present.\n//\n// Copied from the Go 1.22rc1 source tree.\nfunc LastIndexRabinKarp[T string | []byte](s, sep T) int {\n\t// Rabin-Karp search from the end of the string\n\thashss, pow := HashStrRev(sep)\n\tn := len(sep)\n\tlast := len(s) - n\n\tvar h uint32\n\tfor i := len(s) - 1; i >= last; i-- {\n\t\th = h*PrimeRK + uint32(s[i])\n\t}\n\tif h == hashss && string(s[last:]) == string(sep) {\n\t\treturn last\n\t}\n\tfor i := last - 1; i >= 0; i-- {\n\t\th *= PrimeRK\n\t\th += uint32(s[i])\n\t\th -= pow * uint32(s[i+n])\n\t\tif h == hashss && string(s[i:i+n]) == string(sep) {\n\t\t\treturn i\n\t\t}\n\t}\n\treturn -1\n}\n"
  },
  {
    "path": "src/internal/cm/abi.go",
    "content": "package cm\n\nimport \"unsafe\"\n\n// AnyInteger is a type constraint for any integer type.\ntype AnyInteger interface {\n\t~int | ~uint | ~uintptr | ~int8 | ~uint8 | ~int16 | ~uint16 | ~int32 | ~uint32 | ~int64 | ~uint64\n}\n\n// Reinterpret reinterprets the bits of type From into type T.\n// Will panic if the size of From is smaller than the size of To.\nfunc Reinterpret[T, From any](from From) (to T) {\n\tif unsafe.Sizeof(to) > unsafe.Sizeof(from) {\n\t\tpanic(\"reinterpret: size of to > from\")\n\t}\n\treturn *(*T)(unsafe.Pointer(&from))\n}\n\n// LowerString lowers a [string] into a pair of Core WebAssembly types.\n//\n// [string]: https://pkg.go.dev/builtin#string\nfunc LowerString[S ~string](s S) (*byte, uint32) {\n\treturn unsafe.StringData(string(s)), uint32(len(s))\n}\n\n// LiftString lifts Core WebAssembly types into a [string].\nfunc LiftString[T ~string, Data unsafe.Pointer | uintptr | *uint8, Len AnyInteger](data Data, len Len) T {\n\treturn T(unsafe.String((*uint8)(unsafe.Pointer(data)), int(len)))\n}\n\n// LowerList lowers a [List] into a pair of Core WebAssembly types.\nfunc LowerList[L AnyList[T], T any](list L) (*T, uint32) {\n\tl := (*List[T])(unsafe.Pointer(&list))\n\treturn l.data, uint32(l.len)\n}\n\n// LiftList lifts Core WebAssembly types into a [List].\nfunc LiftList[L AnyList[T], T any, Data unsafe.Pointer | uintptr | *T, Len AnyInteger](data Data, len Len) L {\n\treturn L(NewList((*T)(unsafe.Pointer(data)), len))\n}\n\n// BoolToU32 converts a value whose underlying type is [bool] into a [uint32].\n// Used to lower a [bool] into a Core WebAssembly i32 as specified in the [Canonical ABI].\n//\n// [bool]: https://pkg.go.dev/builtin#bool\n// [uint32]: https://pkg.go.dev/builtin#uint32\n// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md\nfunc BoolToU32[B ~bool](v B) uint32 { return uint32(*(*uint8)(unsafe.Pointer(&v))) }\n\n// U32ToBool converts a [uint32] into a [bool].\n// Used to lift a Core WebAssembly i32 into a [bool] as specified in the [Canonical ABI].\n//\n// [uint32]: https://pkg.go.dev/builtin#uint32\n// [bool]: https://pkg.go.dev/builtin#bool\n// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md\nfunc U32ToBool(v uint32) bool { tmp := uint8(v); return *(*bool)(unsafe.Pointer(&tmp)) }\n\n// F32ToU32 maps the bits of a [float32] into a [uint32].\n// Used to lower a [float32] into a Core WebAssembly i32 as specified in the [Canonical ABI].\n//\n// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md\n// [float32]: https://pkg.go.dev/builtin#float32\n// [uint32]: https://pkg.go.dev/builtin#uint32\nfunc F32ToU32(v float32) uint32 { return *(*uint32)(unsafe.Pointer(&v)) }\n\n// U32ToF32 maps the bits of a [uint32] into a [float32].\n// Used to lift a Core WebAssembly i32 into a [float32] as specified in the [Canonical ABI].\n//\n// [uint32]: https://pkg.go.dev/builtin#uint32\n// [float32]: https://pkg.go.dev/builtin#float32\n// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md\nfunc U32ToF32(v uint32) float32 { return *(*float32)(unsafe.Pointer(&v)) }\n\n// F64ToU64 maps the bits of a [float64] into a [uint64].\n// Used to lower a [float64] into a Core WebAssembly i64 as specified in the [Canonical ABI].\n//\n// [float64]: https://pkg.go.dev/builtin#float64\n// [uint64]: https://pkg.go.dev/builtin#uint64\n// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md\n//\n// [uint32]: https://pkg.go.dev/builtin#uint32\nfunc F64ToU64(v float64) uint64 { return *(*uint64)(unsafe.Pointer(&v)) }\n\n// U64ToF64 maps the bits of a [uint64] into a [float64].\n// Used to lift a Core WebAssembly i64 into a [float64] as specified in the [Canonical ABI].\n//\n// [uint64]: https://pkg.go.dev/builtin#uint64\n// [float64]: https://pkg.go.dev/builtin#float64\n// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md\nfunc U64ToF64(v uint64) float64 { return *(*float64)(unsafe.Pointer(&v)) }\n\n// F32ToU64 maps the bits of a [float32] into a [uint64].\n// Used to lower a [float32] into a Core WebAssembly i64 when required by the [Canonical ABI].\n//\n// [float32]: https://pkg.go.dev/builtin#float32\n// [uint64]: https://pkg.go.dev/builtin#uint64\n// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md\nfunc F32ToU64(v float32) uint64 { return uint64(*(*uint32)(unsafe.Pointer(&v))) }\n\n// U64ToF32 maps the bits of a [uint64] into a [float32].\n// Used to lift a Core WebAssembly i64 into a [float32] when required by the [Canonical ABI].\n//\n// [uint64]: https://pkg.go.dev/builtin#uint64\n// [float32]: https://pkg.go.dev/builtin#float32\n// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md\nfunc U64ToF32(v uint64) float32 {\n\ttruncated := uint32(v)\n\treturn *(*float32)(unsafe.Pointer(&truncated))\n}\n\n// PointerToU32 converts a pointer of type *T into a [uint32].\n// Used to lower a pointer into a Core WebAssembly i32 as specified in the [Canonical ABI].\n//\n// [uint32]: https://pkg.go.dev/builtin#uint32\n// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md\nfunc PointerToU32[T any](v *T) uint32 { return uint32(uintptr(unsafe.Pointer(v))) }\n\n// U32ToPointer converts a [uint32] into a pointer of type *T.\n// Used to lift a Core WebAssembly i32 into a pointer as specified in the [Canonical ABI].\n//\n// [uint32]: https://pkg.go.dev/builtin#uint32\n// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md\nfunc U32ToPointer[T any](v uint32) *T { return (*T)(unsafePointer(uintptr(v))) }\n\n// PointerToU64 converts a pointer of type *T into a [uint64].\n// Used to lower a pointer into a Core WebAssembly i64 as specified in the [Canonical ABI].\n//\n// [uint64]: https://pkg.go.dev/builtin#uint64\n// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md\nfunc PointerToU64[T any](v *T) uint64 { return uint64(uintptr(unsafe.Pointer(v))) }\n\n// U64ToPointer converts a [uint64] into a pointer of type *T.\n// Used to lift a Core WebAssembly i64 into a pointer as specified in the [Canonical ABI].\n//\n// [uint64]: https://pkg.go.dev/builtin#uint64\n// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md\nfunc U64ToPointer[T any](v uint64) *T { return (*T)(unsafePointer(uintptr(v))) }\n\n// Appease vet, see https://github.com/golang/go/issues/58625\nfunc unsafePointer(p uintptr) unsafe.Pointer {\n\treturn *(*unsafe.Pointer)(unsafe.Pointer(&p))\n}\n"
  },
  {
    "path": "src/internal/cm/case.go",
    "content": "package cm\n\n// CaseUnmarshaler returns an function that can unmarshal text into\n// [variant] or [enum] case T.\n//\n// [enum]: https://component-model.bytecodealliance.org/design/wit.html#enums\n// [variant]: https://component-model.bytecodealliance.org/design/wit.html#variants\nfunc CaseUnmarshaler[T ~uint8 | ~uint16 | ~uint32](cases []string) func(v *T, text []byte) error {\n\tif len(cases) <= linearScanThreshold {\n\t\treturn func(v *T, text []byte) error {\n\t\t\tif len(text) == 0 {\n\t\t\t\treturn &emptyTextError{}\n\t\t\t}\n\t\t\ts := string(text)\n\t\t\tfor i := 0; i < len(cases); i++ {\n\t\t\t\tif cases[i] == s {\n\t\t\t\t\t*v = T(i)\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn &noMatchingCaseError{}\n\t\t}\n\t}\n\n\tm := make(map[string]T, len(cases))\n\tfor i, v := range cases {\n\t\tm[v] = T(i)\n\t}\n\n\treturn func(v *T, text []byte) error {\n\t\tif len(text) == 0 {\n\t\t\treturn &emptyTextError{}\n\t\t}\n\t\tc, ok := m[string(text)]\n\t\tif !ok {\n\t\t\treturn &noMatchingCaseError{}\n\t\t}\n\t\t*v = c\n\t\treturn nil\n\t}\n}\n\nconst linearScanThreshold = 16\n\ntype emptyTextError struct{}\n\nfunc (*emptyTextError) Error() string { return \"empty text\" }\n\ntype noMatchingCaseError struct{}\n\nfunc (*noMatchingCaseError) Error() string { return \"no matching case\" }\n"
  },
  {
    "path": "src/internal/cm/docs.go",
    "content": "// Package cm provides types and functions for interfacing with the WebAssembly Component Model.\n//\n// The types in this package (such as [List], [Option], [Result], and [Variant]) are designed to match the memory layout\n// of [Component Model] types as specified in the [Canonical ABI].\n//\n// [Component Model]: https://component-model.bytecodealliance.org/introduction.html\n// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#alignment\npackage cm\n"
  },
  {
    "path": "src/internal/cm/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/cm/error.go",
    "content": "package cm\n\nimport \"unsafe\"\n\n// ErrorContext represents the Component Model [error-context] type,\n// an immutable, non-deterministic, host-defined value meant to aid in debugging.\n//\n// [error-context]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md#error-context-type\ntype ErrorContext struct {\n\t_ HostLayout\n\terrorContext\n}\n\ntype errorContext uint32\n\n// Error implements the [error] interface. It returns the debug message associated with err.\nfunc (err errorContext) Error() string {\n\treturn err.DebugMessage()\n}\n\n// String implements [fmt.Stringer].\nfunc (err errorContext) String() string {\n\treturn err.DebugMessage()\n}\n\n// DebugMessage represents the Canonical ABI [error-context.debug-message] function.\n//\n// [error-context.debug-message]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md#error-contextdebug-message\nfunc (err errorContext) DebugMessage() string {\n\tvar s string\n\twasmimport_errorContextDebugMessage(err, unsafe.Pointer(&s))\n\treturn s\n}\n\n// Drop represents the Canonical ABI [error-context.drop] function.\n//\n// [error-context.drop]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md#error-contextdrop\nfunc (err errorContext) Drop() {\n\twasmimport_errorContextDrop(err)\n}\n"
  },
  {
    "path": "src/internal/cm/error.wasm.go",
    "content": "package cm\n\nimport \"unsafe\"\n\n// msg uses unsafe.Pointer for compatibility with go1.23 and lower.\n//\n//go:wasmimport canon error-context.debug-message\n//go:noescape\nfunc wasmimport_errorContextDebugMessage(err errorContext, msg unsafe.Pointer)\n\n//go:wasmimport canon error-context.drop\n//go:noescape\nfunc wasmimport_errorContextDrop(err errorContext)\n"
  },
  {
    "path": "src/internal/cm/future.go",
    "content": "package cm\n\n// Future represents the Component Model [future] type.\n// A future is a special case of stream. In non-error cases,\n// a future delivers exactly one value before being automatically closed.\n//\n// [future]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md#asynchronous-value-types\ntype Future[T any] struct {\n\t_ HostLayout\n\tfuture[T]\n}\n\ntype future[T any] uint32\n\n// TODO: implement methods on type future\n"
  },
  {
    "path": "src/internal/cm/hostlayout_go122.go",
    "content": "//go:build !go1.23\n\npackage cm\n\n// HostLayout marks a struct as using host memory layout.\n// See [structs.HostLayout] in Go 1.23 or later.\ntype HostLayout struct {\n\t_ hostLayout // prevent accidental conversion with plain struct{}\n}\n\ntype hostLayout struct{}\n"
  },
  {
    "path": "src/internal/cm/hostlayout_go123.go",
    "content": "//go:build go1.23\n\npackage cm\n\nimport \"structs\"\n\n// HostLayout marks a struct as using host memory layout.\n// See [structs.HostLayout] in Go 1.23 or later.\ntype HostLayout = structs.HostLayout\n"
  },
  {
    "path": "src/internal/cm/list.go",
    "content": "package cm\n\nimport (\n\t\"unsafe\"\n)\n\n// List represents a Component Model list.\n// The binary representation of list<T> is similar to a Go slice minus the cap field.\ntype List[T any] struct {\n\t_ HostLayout\n\tlist[T]\n}\n\n// AnyList is a type constraint for generic functions that accept any [List] type.\ntype AnyList[T any] interface {\n\t~struct {\n\t\t_ HostLayout\n\t\tlist[T]\n\t}\n}\n\n// NewList returns a List[T] from data and len.\nfunc NewList[T any, Len AnyInteger](data *T, len Len) List[T] {\n\treturn List[T]{\n\t\tlist: list[T]{\n\t\t\tdata: data,\n\t\t\tlen:  uintptr(len),\n\t\t},\n\t}\n}\n\n// ToList returns a List[T] equivalent to the Go slice s.\n// The underlying slice data is not copied, and the resulting List points at the\n// same array storage as the slice.\nfunc ToList[S ~[]T, T any](s S) List[T] {\n\treturn NewList[T](unsafe.SliceData([]T(s)), uintptr(len(s)))\n}\n\n// list represents the internal representation of a Component Model list.\n// It is intended to be embedded in a [List], so embedding types maintain\n// the methods defined on this type.\ntype list[T any] struct {\n\t_    HostLayout\n\tdata *T\n\tlen  uintptr\n}\n\n// Slice returns a Go slice representing the List.\nfunc (l list[T]) Slice() []T {\n\treturn unsafe.Slice(l.data, l.len)\n}\n\n// Data returns the data pointer for the list.\nfunc (l list[T]) Data() *T {\n\treturn l.data\n}\n\n// Len returns the length of the list.\n// TODO: should this return an int instead of a uintptr?\nfunc (l list[T]) Len() uintptr {\n\treturn l.len\n}\n"
  },
  {
    "path": "src/internal/cm/option.go",
    "content": "package cm\n\n// Option represents a Component Model [option<T>] type.\n//\n// [option<T>]: https://component-model.bytecodealliance.org/design/wit.html#options\ntype Option[T any] struct {\n\t_ HostLayout\n\toption[T]\n}\n\n// None returns an [Option] representing the none case,\n// equivalent to the zero value.\nfunc None[T any]() Option[T] {\n\treturn Option[T]{}\n}\n\n// Some returns an [Option] representing the some case.\nfunc Some[T any](v T) Option[T] {\n\treturn Option[T]{\n\t\toption: option[T]{\n\t\t\tisSome: true,\n\t\t\tsome:   v,\n\t\t},\n\t}\n}\n\n// option represents the internal representation of a Component Model option type.\n// The first byte is a bool representing none or some,\n// followed by storage for the associated type T.\ntype option[T any] struct {\n\t_      HostLayout\n\tisSome bool\n\tsome   T\n}\n\n// None returns true if o represents the none case.\nfunc (o *option[T]) None() bool {\n\treturn !o.isSome\n}\n\n// Some returns a non-nil *T if o represents the some case,\n// or nil if o represents the none case.\nfunc (o *option[T]) Some() *T {\n\tif o.isSome {\n\t\treturn &o.some\n\t}\n\treturn nil\n}\n\n// Value returns T if o represents the some case,\n// or the zero value of T if o represents the none case.\n// This does not have a pointer receiver, so it can be chained.\nfunc (o option[T]) Value() T {\n\tif !o.isSome {\n\t\tvar zero T\n\t\treturn zero\n\t}\n\treturn o.some\n}\n"
  },
  {
    "path": "src/internal/cm/resource.go",
    "content": "package cm\n\n// Resource represents an opaque Component Model [resource handle].\n// It is represented in the [Canonical ABI] as an 32-bit integer.\n//\n// [resource handle]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md#handle-types\n// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md\ntype Resource uint32\n\n// Rep represents a Component Model [resource rep], the core representation type of a resource.\n// It is represented in the [Canonical ABI] as an 32-bit integer.\n//\n// [resource rep]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#canon-resourcerep\n// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md\ntype Rep uint32\n\n// ResourceNone is a sentinel value indicating a null or uninitialized resource.\n// This is a reserved value specified in the [Canonical ABI runtime state].\n//\n// [Canonical ABI runtime state]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#runtime-state\nconst ResourceNone = 0\n"
  },
  {
    "path": "src/internal/cm/result.go",
    "content": "package cm\n\nimport \"unsafe\"\n\nconst (\n\t// ResultOK represents the OK case of a result.\n\tResultOK = false\n\n\t// ResultErr represents the error case of a result.\n\tResultErr = true\n)\n\n// BoolResult represents a result with no OK or error type.\n// False represents the OK case and true represents the error case.\ntype BoolResult bool\n\n// Result represents a result sized to hold the Shape type.\n// The size of the Shape type must be greater than or equal to the size of OK and Err types.\n// For results with two zero-length types, use [BoolResult].\ntype Result[Shape, OK, Err any] struct {\n\t_ HostLayout\n\tresult[Shape, OK, Err]\n}\n\n// AnyResult is a type constraint for generic functions that accept any [Result] type.\ntype AnyResult[Shape, OK, Err any] interface {\n\t~struct {\n\t\t_ HostLayout\n\t\tresult[Shape, OK, Err]\n\t}\n}\n\n// result represents the internal representation of a Component Model result type.\ntype result[Shape, OK, Err any] struct {\n\t_     HostLayout\n\tisErr bool\n\t_     [0]OK\n\t_     [0]Err\n\tdata  Shape // [unsafe.Sizeof(*(*Shape)(unsafe.Pointer(nil)))]byte\n}\n\n// IsOK returns true if r represents the OK case.\nfunc (r *result[Shape, OK, Err]) IsOK() bool {\n\tr.validate()\n\treturn !r.isErr\n}\n\n// IsErr returns true if r represents the error case.\nfunc (r *result[Shape, OK, Err]) IsErr() bool {\n\tr.validate()\n\treturn r.isErr\n}\n\n// OK returns a non-nil *OK pointer if r represents the OK case.\n// If r represents an error, then it returns nil.\nfunc (r *result[Shape, OK, Err]) OK() *OK {\n\tr.validate()\n\tif r.isErr {\n\t\treturn nil\n\t}\n\treturn (*OK)(unsafe.Pointer(&r.data))\n}\n\n// Err returns a non-nil *Err pointer if r represents the error case.\n// If r represents the OK case, then it returns nil.\nfunc (r *result[Shape, OK, Err]) Err() *Err {\n\tr.validate()\n\tif !r.isErr {\n\t\treturn nil\n\t}\n\treturn (*Err)(unsafe.Pointer(&r.data))\n}\n\n// Result returns (OK, zero value of Err, false) if r represents the OK case,\n// or (zero value of OK, Err, true) if r represents the error case.\n// This does not have a pointer receiver, so it can be chained.\nfunc (r result[Shape, OK, Err]) Result() (ok OK, err Err, isErr bool) {\n\tif r.isErr {\n\t\treturn ok, *(*Err)(unsafe.Pointer(&r.data)), true\n\t}\n\treturn *(*OK)(unsafe.Pointer(&r.data)), err, false\n}\n\n// This function is sized so it can be inlined and optimized away.\nfunc (r *result[Shape, OK, Err]) validate() {\n\tvar shape Shape\n\tvar ok OK\n\tvar err Err\n\n\t// Check if size of Shape is greater than both OK and Err\n\tif unsafe.Sizeof(shape) > unsafe.Sizeof(ok) && unsafe.Sizeof(shape) > unsafe.Sizeof(err) {\n\t\tpanic(\"result: size of data type > OK and Err types\")\n\t}\n\n\t// Check if size of OK is greater than Shape\n\tif unsafe.Sizeof(ok) > unsafe.Sizeof(shape) {\n\t\tpanic(\"result: size of OK type > data type\")\n\t}\n\n\t// Check if size of Err is greater than Shape\n\tif unsafe.Sizeof(err) > unsafe.Sizeof(shape) {\n\t\tpanic(\"result: size of Err type > data type\")\n\t}\n\n\t// Check if Shape is zero-sized, but size of result != 1\n\tif unsafe.Sizeof(shape) == 0 && unsafe.Sizeof(*r) != 1 {\n\t\tpanic(\"result: size of data type == 0, but result size != 1\")\n\t}\n}\n\n// OK returns an OK result with shape Shape and type OK and Err.\n// Pass Result[OK, OK, Err] or Result[Err, OK, Err] as the first type argument.\nfunc OK[R AnyResult[Shape, OK, Err], Shape, OK, Err any](ok OK) R {\n\tvar r Result[Shape, OK, Err]\n\tr.validate()\n\tr.isErr = ResultOK\n\t*((*OK)(unsafe.Pointer(&r.data))) = ok\n\treturn R(r)\n}\n\n// Err returns an error result with shape Shape and type OK and Err.\n// Pass Result[OK, OK, Err] or Result[Err, OK, Err] as the first type argument.\nfunc Err[R AnyResult[Shape, OK, Err], Shape, OK, Err any](err Err) R {\n\tvar r Result[Shape, OK, Err]\n\tr.validate()\n\tr.isErr = ResultErr\n\t*((*Err)(unsafe.Pointer(&r.data))) = err\n\treturn R(r)\n}\n"
  },
  {
    "path": "src/internal/cm/stream.go",
    "content": "package cm\n\n// Stream represents the Component Model [stream] type.\n// A stream is a special case of stream. In non-error cases,\n// a stream delivers exactly one value before being automatically closed.\n//\n// [stream]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md#asynchronous-value-types\ntype Stream[T any] struct {\n\t_ HostLayout\n\tstream[T]\n}\n\ntype stream[T any] uint32\n\n// TODO: implement methods on type stream\n"
  },
  {
    "path": "src/internal/cm/tuple.go",
    "content": "package cm\n\n// Tuple represents a [Component Model tuple] with 2 fields.\n//\n// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples\ntype Tuple[T0, T1 any] struct {\n\t_  HostLayout\n\tF0 T0\n\tF1 T1\n}\n\n// Tuple3 represents a [Component Model tuple] with 3 fields.\n//\n// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples\ntype Tuple3[T0, T1, T2 any] struct {\n\t_  HostLayout\n\tF0 T0\n\tF1 T1\n\tF2 T2\n}\n\n// Tuple4 represents a [Component Model tuple] with 4 fields.\n//\n// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples\ntype Tuple4[T0, T1, T2, T3 any] struct {\n\t_  HostLayout\n\tF0 T0\n\tF1 T1\n\tF2 T2\n\tF3 T3\n}\n\n// Tuple5 represents a [Component Model tuple] with 5 fields.\n//\n// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples\ntype Tuple5[T0, T1, T2, T3, T4 any] struct {\n\t_  HostLayout\n\tF0 T0\n\tF1 T1\n\tF2 T2\n\tF3 T3\n\tF4 T4\n}\n\n// Tuple6 represents a [Component Model tuple] with 6 fields.\n//\n// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples\ntype Tuple6[T0, T1, T2, T3, T4, T5 any] struct {\n\t_  HostLayout\n\tF0 T0\n\tF1 T1\n\tF2 T2\n\tF3 T3\n\tF4 T4\n\tF5 T5\n}\n\n// Tuple7 represents a [Component Model tuple] with 7 fields.\n//\n// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples\ntype Tuple7[T0, T1, T2, T3, T4, T5, T6 any] struct {\n\t_  HostLayout\n\tF0 T0\n\tF1 T1\n\tF2 T2\n\tF3 T3\n\tF4 T4\n\tF5 T5\n\tF6 T6\n}\n\n// Tuple8 represents a [Component Model tuple] with 8 fields.\n//\n// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples\ntype Tuple8[T0, T1, T2, T3, T4, T5, T6, T7 any] struct {\n\t_  HostLayout\n\tF0 T0\n\tF1 T1\n\tF2 T2\n\tF3 T3\n\tF4 T4\n\tF5 T5\n\tF6 T6\n\tF7 T7\n}\n\n// Tuple9 represents a [Component Model tuple] with 9 fields.\n//\n// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples\ntype Tuple9[T0, T1, T2, T3, T4, T5, T6, T7, T8 any] struct {\n\t_  HostLayout\n\tF0 T0\n\tF1 T1\n\tF2 T2\n\tF3 T3\n\tF4 T4\n\tF5 T5\n\tF6 T6\n\tF7 T7\n\tF8 T8\n}\n\n// Tuple10 represents a [Component Model tuple] with 10 fields.\n//\n// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples\ntype Tuple10[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9 any] struct {\n\t_  HostLayout\n\tF0 T0\n\tF1 T1\n\tF2 T2\n\tF3 T3\n\tF4 T4\n\tF5 T5\n\tF6 T6\n\tF7 T7\n\tF8 T8\n\tF9 T9\n}\n\n// Tuple11 represents a [Component Model tuple] with 11 fields.\n//\n// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples\ntype Tuple11[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any] struct {\n\t_   HostLayout\n\tF0  T0\n\tF1  T1\n\tF2  T2\n\tF3  T3\n\tF4  T4\n\tF5  T5\n\tF6  T6\n\tF7  T7\n\tF8  T8\n\tF9  T9\n\tF10 T10\n}\n\n// Tuple12 represents a [Component Model tuple] with 12 fields.\n//\n// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples\ntype Tuple12[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any] struct {\n\t_   HostLayout\n\tF0  T0\n\tF1  T1\n\tF2  T2\n\tF3  T3\n\tF4  T4\n\tF5  T5\n\tF6  T6\n\tF7  T7\n\tF8  T8\n\tF9  T9\n\tF10 T10\n\tF11 T11\n}\n\n// Tuple13 represents a [Component Model tuple] with 13 fields.\n//\n// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples\ntype Tuple13[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any] struct {\n\t_   HostLayout\n\tF0  T0\n\tF1  T1\n\tF2  T2\n\tF3  T3\n\tF4  T4\n\tF5  T5\n\tF6  T6\n\tF7  T7\n\tF8  T8\n\tF9  T9\n\tF10 T10\n\tF11 T11\n\tF12 T12\n}\n\n// Tuple14 represents a [Component Model tuple] with 14 fields.\n//\n// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples\ntype Tuple14[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any] struct {\n\t_   HostLayout\n\tF0  T0\n\tF1  T1\n\tF2  T2\n\tF3  T3\n\tF4  T4\n\tF5  T5\n\tF6  T6\n\tF7  T7\n\tF8  T8\n\tF9  T9\n\tF10 T10\n\tF11 T11\n\tF12 T12\n\tF13 T13\n}\n\n// Tuple15 represents a [Component Model tuple] with 15 fields.\n//\n// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples\ntype Tuple15[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any] struct {\n\t_   HostLayout\n\tF0  T0\n\tF1  T1\n\tF2  T2\n\tF3  T3\n\tF4  T4\n\tF5  T5\n\tF6  T6\n\tF7  T7\n\tF8  T8\n\tF9  T9\n\tF10 T10\n\tF11 T11\n\tF12 T12\n\tF13 T13\n\tF14 T14\n}\n\n// Tuple16 represents a [Component Model tuple] with 16 fields.\n//\n// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples\ntype Tuple16[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any] struct {\n\t_   HostLayout\n\tF0  T0\n\tF1  T1\n\tF2  T2\n\tF3  T3\n\tF4  T4\n\tF5  T5\n\tF6  T6\n\tF7  T7\n\tF8  T8\n\tF9  T9\n\tF10 T10\n\tF11 T11\n\tF12 T12\n\tF13 T13\n\tF14 T14\n\tF15 T15\n}\n\n// MaxTuple specifies the maximum number of fields in a Tuple* type, currently [Tuple16].\n// See https://github.com/WebAssembly/component-model/issues/373 for more information.\nconst MaxTuple = 16\n"
  },
  {
    "path": "src/internal/cm/variant.go",
    "content": "package cm\n\nimport \"unsafe\"\n\n// Discriminant is the set of types that can represent the tag or discriminator of a variant.\n// Use uint8 where there are 256 or fewer cases, uint16 for up to 65,536 cases, or uint32 for anything greater.\ntype Discriminant interface {\n\tuint8 | uint16 | uint32\n}\n\n// Variant represents a loosely-typed Component Model variant.\n// Shape and Align must be non-zero sized types. To create a variant with no associated\n// types, use an enum.\ntype Variant[Tag Discriminant, Shape, Align any] struct {\n\t_ HostLayout\n\tvariant[Tag, Shape, Align]\n}\n\n// AnyVariant is a type constraint for generic functions that accept any [Variant] type.\ntype AnyVariant[Tag Discriminant, Shape, Align any] interface {\n\t~struct {\n\t\t_ HostLayout\n\t\tvariant[Tag, Shape, Align]\n\t}\n}\n\n// NewVariant returns a [Variant] with tag of type Disc, storage and GC shape of type Shape,\n// aligned to type Align, with a value of type T.\nfunc NewVariant[Tag Discriminant, Shape, Align any, T any](tag Tag, data T) Variant[Tag, Shape, Align] {\n\tvalidateVariant[Tag, Shape, Align, T]()\n\tvar v Variant[Tag, Shape, Align]\n\tv.tag = tag\n\t*(*T)(unsafe.Pointer(&v.data)) = data\n\treturn v\n}\n\n// New returns a [Variant] with tag of type Disc, storage and GC shape of type Shape,\n// aligned to type Align, with a value of type T.\nfunc New[V AnyVariant[Tag, Shape, Align], Tag Discriminant, Shape, Align any, T any](tag Tag, data T) V {\n\tvalidateVariant[Tag, Shape, Align, T]()\n\tvar v variant[Tag, Shape, Align]\n\tv.tag = tag\n\t*(*T)(unsafe.Pointer(&v.data)) = data\n\treturn *(*V)(unsafe.Pointer(&v))\n}\n\n// Case returns a non-nil *T if the [Variant] case is equal to tag, otherwise it returns nil.\nfunc Case[T any, V AnyVariant[Tag, Shape, Align], Tag Discriminant, Shape, Align any](v *V, tag Tag) *T {\n\tvalidateVariant[Tag, Shape, Align, T]()\n\tv2 := (*variant[Tag, Shape, Align])(unsafe.Pointer(v))\n\tif v2.tag == tag {\n\t\treturn (*T)(unsafe.Pointer(&v2.data))\n\t}\n\treturn nil\n}\n\n// variant is the internal representation of a Component Model variant.\n// Shape and Align must be non-zero sized types.\ntype variant[Tag Discriminant, Shape, Align any] struct {\n\t_    HostLayout\n\ttag  Tag\n\t_    [0]Align\n\tdata Shape // [unsafe.Sizeof(*(*Shape)(unsafe.Pointer(nil)))]byte\n}\n\n// Tag returns the tag (discriminant) of variant v.\nfunc (v *variant[Tag, Shape, Align]) Tag() Tag {\n\treturn v.tag\n}\n\n// This function is sized so it can be inlined and optimized away.\nfunc validateVariant[Disc Discriminant, Shape, Align any, T any]() {\n\tvar v variant[Disc, Shape, Align]\n\tvar t T\n\n\t// Check if size of T is greater than Shape\n\tif unsafe.Sizeof(t) > unsafe.Sizeof(v.data) {\n\t\tpanic(\"variant: size of requested type > data type\")\n\t}\n\n\t// Check if Shape is zero-sized, but size of result != 1\n\tif unsafe.Sizeof(v.data) == 0 && unsafe.Sizeof(v) != 1 {\n\t\tpanic(\"variant: size of data type == 0, but variant size != 1\")\n\t}\n}\n"
  },
  {
    "path": "src/internal/futex/futex.go",
    "content": "package futex\n\n// Cross platform futex implementation.\n// Futexes are supported on all major operating systems and on WebAssembly.\n//\n// For more information, see: https://outerproduct.net/futex-dictionary.html\n\nimport (\n\t\"sync/atomic\"\n\t\"unsafe\"\n)\n\n// A futex is a way for userspace to wait with the pointer as the key, and for\n// another thread to wake one or all waiting threads keyed on the same pointer.\n//\n// A futex does not change the underlying value, it only reads it before going\n// to sleep (atomically) to prevent lost wake-ups.\ntype Futex struct {\n\tatomic.Uint32\n}\n\n// Atomically check for cmp to still be equal to the futex value and if so, go\n// to sleep. Return true if we were definitely awoken by a call to Wake or\n// WakeAll, and false if we can't be sure of that.\nfunc (f *Futex) Wait(cmp uint32) bool {\n\ttinygo_futex_wait((*uint32)(unsafe.Pointer(&f.Uint32)), cmp)\n\n\t// We *could* detect a zero return value from the futex system call which\n\t// would indicate we got awoken by a Wake or WakeAll call. However, this is\n\t// what the manual page has to say:\n\t//\n\t// > Note that a wake-up can also be caused by common futex usage patterns\n\t// > in unrelated code that happened to have previously used the futex\n\t// > word's memory location (e.g., typical futex-based implementations of\n\t// > Pthreads mutexes can cause this under some conditions). Therefore,\n\t// > callers should always conservatively assume that a return value of 0\n\t// > can mean a spurious wake-up, and use the futex word's value (i.e., the\n\t// > user-space synchronization scheme) to decide whether to continue to\n\t// > block or not.\n\t//\n\t// I'm not sure whether we do anything like pthread does, so to be on the\n\t// safe side we say we don't know whether the wakeup was spurious or not and\n\t// return false.\n\treturn false\n}\n\n// Like Wait, but times out after the number of nanoseconds in timeout.\nfunc (f *Futex) WaitUntil(cmp uint32, timeout uint64) {\n\ttinygo_futex_wait_timeout((*uint32)(unsafe.Pointer(&f.Uint32)), cmp, timeout)\n}\n\n// Wake a single waiter.\nfunc (f *Futex) Wake() {\n\ttinygo_futex_wake((*uint32)(unsafe.Pointer(&f.Uint32)))\n}\n\n// Wake all waiters.\nfunc (f *Futex) WakeAll() {\n\ttinygo_futex_wake_all((*uint32)(unsafe.Pointer(&f.Uint32)))\n}\n\n//export tinygo_futex_wait\nfunc tinygo_futex_wait(addr *uint32, cmp uint32)\n\n//export tinygo_futex_wait_timeout\nfunc tinygo_futex_wait_timeout(addr *uint32, cmp uint32, timeout uint64)\n\n//export tinygo_futex_wake\nfunc tinygo_futex_wake(addr *uint32)\n\n//export tinygo_futex_wake_all\nfunc tinygo_futex_wake_all(addr *uint32)\n"
  },
  {
    "path": "src/internal/futex/futex_darwin.c",
    "content": "//go:build none\n\n// This file is manually included, to avoid CGo which would cause a circular\n// import.\n\n#include <stdint.h>\n\n// This API isn't documented by Apple, but it is used by LLVM libc++ (so should\n// be stable) and has been documented extensively here:\n// https://outerproduct.net/futex-dictionary.html\n\nint __ulock_wait(uint32_t operation, void *addr, uint64_t value, uint32_t timeout_us);\nint __ulock_wait2(uint32_t operation, void *addr, uint64_t value, uint64_t timeout_ns, uint64_t value2);\nint __ulock_wake(uint32_t operation, void *addr, uint64_t wake_value);\n\n// Operation code.\n#define UL_COMPARE_AND_WAIT 1\n\n// Flags to the operation value.\n#define ULF_WAKE_ALL 0x00000100\n#define ULF_NO_ERRNO 0x01000000\n\nvoid tinygo_futex_wait(uint32_t *addr, uint32_t cmp) {\n    __ulock_wait(UL_COMPARE_AND_WAIT|ULF_NO_ERRNO, addr, (uint64_t)cmp, 0);\n}\n\nvoid tinygo_futex_wait_timeout(uint32_t *addr, uint32_t cmp, uint64_t timeout) {\n    // Make sure that an accidental use of a zero timeout is not treated as an\n    // infinite timeout. Return if it's zero since it wouldn't be waiting for\n    // any significant time anyway.\n    // Probably unnecessary, but guards against potential bugs.\n    if (timeout == 0) {\n        return;\n    }\n\n    // Note: __ulock_wait2 is available since MacOS 11.\n    // I think that's fine, since the version before that (MacOS 10.15) is EOL\n    // since 2022. Though if needed, we could certainly use __ulock_wait instead\n    // and deal with the smaller timeout value.\n    __ulock_wait2(UL_COMPARE_AND_WAIT|ULF_NO_ERRNO, addr, (uint64_t)cmp, timeout, 0);\n}\n\nvoid tinygo_futex_wake(uint32_t *addr) {\n    __ulock_wake(UL_COMPARE_AND_WAIT|ULF_NO_ERRNO, addr, 0);\n}\n\nvoid tinygo_futex_wake_all(uint32_t *addr) {\n    __ulock_wake(UL_COMPARE_AND_WAIT|ULF_NO_ERRNO|ULF_WAKE_ALL, addr, 0);\n}\n"
  },
  {
    "path": "src/internal/futex/futex_linux.c",
    "content": "//go:build none\n\n// This file is manually included, to avoid CGo which would cause a circular\n// import.\n\n#include <limits.h>\n#include <stdint.h>\n#include <sys/syscall.h>\n#include <time.h>\n#include <unistd.h>\n\n#define FUTEX_WAIT         0\n#define FUTEX_WAKE         1\n#define FUTEX_PRIVATE_FLAG 128\n\nvoid tinygo_futex_wait(uint32_t *addr, uint32_t cmp) {\n    syscall(SYS_futex, addr, FUTEX_WAIT|FUTEX_PRIVATE_FLAG, cmp, NULL, NULL, 0);\n}\n\nvoid tinygo_futex_wait_timeout(uint32_t *addr, uint32_t cmp, uint64_t timeout) {\n    struct timespec ts = {0};\n    ts.tv_sec = timeout / 1000000000;\n    ts.tv_nsec = timeout % 1000000000;\n    syscall(SYS_futex, addr, FUTEX_WAIT|FUTEX_PRIVATE_FLAG, cmp, &ts, NULL, 0);\n}\n\nvoid tinygo_futex_wake(uint32_t *addr) {\n    syscall(SYS_futex, addr, FUTEX_WAKE|FUTEX_PRIVATE_FLAG, 1, NULL, NULL, 0);\n}\n\nvoid tinygo_futex_wake_all(uint32_t *addr) {\n    syscall(SYS_futex, addr, FUTEX_WAKE|FUTEX_PRIVATE_FLAG, INT_MAX, NULL, NULL, 0);\n}\n"
  },
  {
    "path": "src/internal/fuzz/fuzz.go",
    "content": "// Package fuzz is a shim to allow compilation against Go 1.18.\n// It only defines a single type to work with testing/internal/testdeps,\n// and hide all the other new dependencies from this package.\npackage fuzz\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"io\"\n\t\"reflect\"\n\t\"time\"\n)\n\n// CorpusEntry represents an individual input for fuzzing.\n//\n// We must use an equivalent type in the testing and testing/internal/testdeps\n// packages, but testing can't import this package directly, and we don't want\n// to export this type from testing. Instead, we use the same struct type and\n// use a type alias (not a defined type) for convenience.\ntype CorpusEntry = struct {\n\tParent string\n\n\t// Path is the path of the corpus file, if the entry was loaded from disk.\n\t// For other entries, including seed values provided by f.Add, Path is the\n\t// name of the test, e.g. seed#0 or its hash.\n\tPath string\n\n\t// Data is the raw input data. Data should only be populated for seed\n\t// values. For on-disk corpus files, Data will be nil, as it will be loaded\n\t// from disk using Path.\n\tData []byte\n\n\t// Values is the unmarshaled values from a corpus file.\n\tValues []any\n\n\tGeneration int\n\n\t// IsSeed indicates whether this entry is part of the seed corpus.\n\tIsSeed bool\n}\n\n// CoordinateFuzzingOpts is a set of arguments for CoordinateFuzzing.\n// The zero value is valid for each field unless specified otherwise.\ntype CoordinateFuzzingOpts struct {\n\t// Log is a writer for logging progress messages and warnings.\n\t// If nil, io.Discard will be used instead.\n\tLog io.Writer\n\n\t// Timeout is the amount of wall clock time to spend fuzzing after the corpus\n\t// has loaded. If zero, there will be no time limit.\n\tTimeout time.Duration\n\n\t// Limit is the number of random values to generate and test. If zero,\n\t// there will be no limit on the number of generated values.\n\tLimit int64\n\n\t// MinimizeTimeout is the amount of wall clock time to spend minimizing\n\t// after discovering a crasher. If zero, there will be no time limit. If\n\t// MinimizeTimeout and MinimizeLimit are both zero, then minimization will\n\t// be disabled.\n\tMinimizeTimeout time.Duration\n\n\t// MinimizeLimit is the maximum number of calls to the fuzz function to be\n\t// made while minimizing after finding a crash. If zero, there will be no\n\t// limit. Calls to the fuzz function made when minimizing also count toward\n\t// Limit. If MinimizeTimeout and MinimizeLimit are both zero, then\n\t// minimization will be disabled.\n\tMinimizeLimit int64\n\n\t// parallel is the number of worker processes to run in parallel. If zero,\n\t// CoordinateFuzzing will run GOMAXPROCS workers.\n\tParallel int\n\n\t// Seed is a list of seed values added by the fuzz target with testing.F.Add\n\t// and in testdata.\n\tSeed []CorpusEntry\n\n\t// Types is the list of types which make up a corpus entry.\n\t// Types must be set and must match values in Seed.\n\tTypes []reflect.Type\n\n\t// CorpusDir is a directory where files containing values that crash the\n\t// code being tested may be written. CorpusDir must be set.\n\tCorpusDir string\n\n\t// CacheDir is a directory containing additional \"interesting\" values.\n\t// The fuzzer may derive new values from these, and may write new values here.\n\tCacheDir string\n}\n\n// CoordinateFuzzing creates several worker processes and communicates with\n// them to test random inputs that could trigger crashes and expose bugs.\n// The worker processes run the same binary in the same directory with the\n// same environment variables as the coordinator process. Workers also run\n// with the same arguments as the coordinator, except with the -test.fuzzworker\n// flag prepended to the argument list.\n//\n// If a crash occurs, the function will return an error containing information\n// about the crash, which can be reported to the user.\nfunc CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err error) {\n\treturn errors.New(\"not implemented\")\n}\n\n// ReadCorpus reads the corpus from the provided dir. The returned corpus\n// entries are guaranteed to match the given types. Any malformed files will\n// be saved in a MalformedCorpusError and returned, along with the most recent\n// error.\nfunc ReadCorpus(dir string, types []reflect.Type) ([]CorpusEntry, error) {\n\treturn nil, errors.New(\"not implemented\")\n}\n\n// CheckCorpus verifies that the types in vals match the expected types\n// provided.\nfunc CheckCorpus(vals []any, types []reflect.Type) error {\n\treturn errors.New(\"not implemented\")\n}\n\nfunc ResetCoverage()    {}\nfunc SnapshotCoverage() {}\n\n// RunFuzzWorker is called in a worker process to communicate with the\n// coordinator process in order to fuzz random inputs. RunFuzzWorker loops\n// until the coordinator tells it to stop.\n//\n// fn is a wrapper on the fuzz function. It may return an error to indicate\n// a given input \"crashed\". The coordinator will also record a crasher if\n// the function times out or terminates the process.\n//\n// RunFuzzWorker returns an error if it could not communicate with the\n// coordinator process.\nfunc RunFuzzWorker(ctx context.Context, fn func(CorpusEntry) error) error {\n\treturn errors.New(\"not implemented\")\n}\n"
  },
  {
    "path": "src/internal/gclayout/gclayout.go",
    "content": "package gclayout\n\nimport \"unsafe\"\n\n// Internal constants for gc layout\n// See runtime/gc_precise.go\n\ntype Layout uintptr\n\nconst (\n\t// 16-bit int => bits = 4\n\t// 32-bit int => bits = 5\n\t// 64-bit int => bits = 6\n\tsizeBits = 4 + unsafe.Sizeof(uintptr(0))/4\n\n\tsizeShift = sizeBits + 1\n\n\tNoPtrs  = Layout(uintptr(0b0<<sizeShift) | uintptr(0b1<<1) | uintptr(1))\n\tPointer = Layout(uintptr(0b1<<sizeShift) | uintptr(0b1<<1) | uintptr(1))\n\tString  = Layout(uintptr(0b01<<sizeShift) | uintptr(0b10<<1) | uintptr(1))\n\tSlice   = Layout(uintptr(0b001<<sizeShift) | uintptr(0b11<<1) | uintptr(1))\n)\n\nfunc (l Layout) AsPtr() unsafe.Pointer { return unsafe.Pointer(l) }\n"
  },
  {
    "path": "src/internal/reflectlite/deepequal.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Deep equality test via reflection\n\npackage reflectlite\n\nimport \"unsafe\"\n\n// During deepValueEqual, must keep track of checks that are\n// in progress. The comparison algorithm assumes that all\n// checks in progress are true when it reencounters them.\n// Visited comparisons are stored in a map indexed by visit.\ntype visit struct {\n\ta1  unsafe.Pointer\n\ta2  unsafe.Pointer\n\ttyp *RawType\n}\n\n// Tests for deep equality using reflected types. The map argument tracks\n// comparisons that have already been seen, which allows short circuiting on\n// recursive types.\nfunc deepValueEqual(v1, v2 Value, visited map[visit]struct{}) bool {\n\tif !v1.IsValid() || !v2.IsValid() {\n\t\treturn v1.IsValid() == v2.IsValid()\n\t}\n\tif v1.typecode != v2.typecode {\n\t\treturn false\n\t}\n\n\t// We want to avoid putting more in the visited map than we need to.\n\t// For any possible reference cycle that might be encountered,\n\t// hard(v1, v2) needs to return true for at least one of the types in the cycle,\n\t// and it's safe and valid to get Value's internal pointer.\n\thard := func(v1, v2 Value) bool {\n\t\tswitch v1.Kind() {\n\t\tcase Map, Slice, Ptr, Interface:\n\t\t\t// Nil pointers cannot be cyclic. Avoid putting them in the visited map.\n\t\t\treturn !v1.IsNil() && !v2.IsNil()\n\t\t}\n\t\treturn false\n\t}\n\n\tif hard(v1, v2) {\n\t\taddr1 := v1.pointer()\n\t\taddr2 := v2.pointer()\n\t\tif uintptr(addr1) > uintptr(addr2) {\n\t\t\t// Canonicalize order to reduce number of entries in visited.\n\t\t\t// Assumes non-moving garbage collector.\n\t\t\taddr1, addr2 = addr2, addr1\n\t\t}\n\n\t\t// Short circuit if references are already seen.\n\t\tv := visit{addr1, addr2, v1.typecode}\n\t\tif _, ok := visited[v]; ok {\n\t\t\treturn true\n\t\t}\n\n\t\t// Remember for later.\n\t\tvisited[v] = struct{}{}\n\t}\n\n\tswitch v1.Kind() {\n\tcase Array:\n\t\tfor i := 0; i < v1.Len(); i++ {\n\t\t\tif !deepValueEqual(v1.Index(i), v2.Index(i), visited) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\tcase Slice:\n\t\tif v1.IsNil() != v2.IsNil() {\n\t\t\treturn false\n\t\t}\n\t\tif v1.Len() != v2.Len() {\n\t\t\treturn false\n\t\t}\n\t\tif v1.UnsafePointer() == v2.UnsafePointer() {\n\t\t\treturn true\n\t\t}\n\t\tfor i := 0; i < v1.Len(); i++ {\n\t\t\tif !deepValueEqual(v1.Index(i), v2.Index(i), visited) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\tcase Interface:\n\t\tif v1.IsNil() || v2.IsNil() {\n\t\t\treturn v1.IsNil() == v2.IsNil()\n\t\t}\n\t\treturn deepValueEqual(v1.Elem(), v2.Elem(), visited)\n\tcase Ptr:\n\t\tif v1.UnsafePointer() == v2.UnsafePointer() {\n\t\t\treturn true\n\t\t}\n\t\treturn deepValueEqual(v1.Elem(), v2.Elem(), visited)\n\tcase Struct:\n\t\tfor i, n := 0, v1.NumField(); i < n; i++ {\n\t\t\tif !deepValueEqual(v1.Field(i), v2.Field(i), visited) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\tcase Map:\n\t\tif v1.IsNil() != v2.IsNil() {\n\t\t\treturn false\n\t\t}\n\t\tif v1.Len() != v2.Len() {\n\t\t\treturn false\n\t\t}\n\t\tif v1.UnsafePointer() == v2.UnsafePointer() {\n\t\t\treturn true\n\t\t}\n\t\tfor _, k := range v1.MapKeys() {\n\t\t\tval1 := v1.MapIndex(k)\n\t\t\tval2 := v2.MapIndex(k)\n\t\t\tif !val1.IsValid() || !val2.IsValid() || !deepValueEqual(val1, val2, visited) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\tcase Func:\n\t\tif v1.IsNil() && v2.IsNil() {\n\t\t\treturn true\n\t\t}\n\t\t// Can't do better than this:\n\t\treturn false\n\tdefault:\n\t\t// Normal equality suffices\n\t\treturn valueInterfaceUnsafe(v1) == valueInterfaceUnsafe(v2)\n\t}\n}\n\n// DeepEqual reports whether x and y are “deeply equal”, defined as follows.\n// Two values of identical type are deeply equal if one of the following cases applies.\n// Values of distinct types are never deeply equal.\n//\n// Array values are deeply equal when their corresponding elements are deeply equal.\n//\n// Struct values are deeply equal if their corresponding fields,\n// both exported and unexported, are deeply equal.\n//\n// Func values are deeply equal if both are nil; otherwise they are not deeply equal.\n//\n// Interface values are deeply equal if they hold deeply equal concrete values.\n//\n// Map values are deeply equal when all of the following are true:\n// they are both nil or both non-nil, they have the same length,\n// and either they are the same map object or their corresponding keys\n// (matched using Go equality) map to deeply equal values.\n//\n// Pointer values are deeply equal if they are equal using Go's == operator\n// or if they point to deeply equal values.\n//\n// Slice values are deeply equal when all of the following are true:\n// they are both nil or both non-nil, they have the same length,\n// and either they point to the same initial entry of the same underlying array\n// (that is, &x[0] == &y[0]) or their corresponding elements (up to length) are deeply equal.\n// Note that a non-nil empty slice and a nil slice (for example, []byte{} and []byte(nil))\n// are not deeply equal.\n//\n// Other values - numbers, bools, strings, and channels - are deeply equal\n// if they are equal using Go's == operator.\n//\n// In general DeepEqual is a recursive relaxation of Go's == operator.\n// However, this idea is impossible to implement without some inconsistency.\n// Specifically, it is possible for a value to be unequal to itself,\n// either because it is of func type (uncomparable in general)\n// or because it is a floating-point NaN value (not equal to itself in floating-point comparison),\n// or because it is an array, struct, or interface containing\n// such a value.\n// On the other hand, pointer values are always equal to themselves,\n// even if they point at or contain such problematic values,\n// because they compare equal using Go's == operator, and that\n// is a sufficient condition to be deeply equal, regardless of content.\n// DeepEqual has been defined so that the same short-cut applies\n// to slices and maps: if x and y are the same slice or the same map,\n// they are deeply equal regardless of content.\n//\n// As DeepEqual traverses the data values it may find a cycle. The\n// second and subsequent times that DeepEqual compares two pointer\n// values that have been compared before, it treats the values as\n// equal rather than examining the values to which they point.\n// This ensures that DeepEqual terminates.\nfunc DeepEqual(x, y interface{}) bool {\n\tif x == nil || y == nil {\n\t\treturn x == y\n\t}\n\tv1 := ValueOf(x)\n\tv2 := ValueOf(y)\n\tif v1.typecode != v2.typecode {\n\t\treturn false\n\t}\n\treturn deepValueEqual(v1, v2, make(map[visit]struct{}))\n}\n"
  },
  {
    "path": "src/internal/reflectlite/endian_big.go",
    "content": "//go:build mips\n\npackage reflectlite\n\nimport \"unsafe\"\n\n// loadValue loads a value that may or may not be word-aligned. The number of\n// bytes given in size are loaded. The biggest possible size it can load is that\n// of an uintptr.\nfunc loadValue(ptr unsafe.Pointer, size uintptr) uintptr {\n\tloadedValue := uintptr(0)\n\tfor i := uintptr(0); i < size; i++ {\n\t\tloadedValue <<= 8\n\t\tloadedValue |= uintptr(*(*byte)(ptr))\n\t\tptr = unsafe.Add(ptr, 1)\n\t}\n\treturn loadedValue\n}\n\n// storeValue is the inverse of loadValue. It stores a value to a pointer that\n// doesn't need to be aligned.\nfunc storeValue(ptr unsafe.Pointer, size, value uintptr) {\n\t// This could perhaps be optimized using bits.ReverseBytes32 if needed.\n\tvalue <<= (unsafe.Sizeof(uintptr(0)) - size) * 8\n\tfor i := uintptr(0); i < size; i++ {\n\t\t*(*byte)(ptr) = byte(value >> ((unsafe.Sizeof(uintptr(0)) - 1) * 8))\n\t\tptr = unsafe.Add(ptr, 1)\n\t\tvalue <<= 8\n\t}\n}\n\n// maskAndShift cuts out a part of a uintptr. Note that the offset may not be 0.\nfunc maskAndShift(value, offset, size uintptr) uintptr {\n\tmask := ^uintptr(0) >> ((unsafe.Sizeof(uintptr(0)) - size) * 8)\n\treturn (uintptr(value) >> ((unsafe.Sizeof(uintptr(0)) - offset - size) * 8)) & mask\n}\n"
  },
  {
    "path": "src/internal/reflectlite/endian_little.go",
    "content": "//go:build !mips\n\npackage reflectlite\n\nimport \"unsafe\"\n\n// loadValue loads a value that may or may not be word-aligned. The number of\n// bytes given in size are loaded. The biggest possible size it can load is that\n// of an uintptr.\nfunc loadValue(ptr unsafe.Pointer, size uintptr) uintptr {\n\tloadedValue := uintptr(0)\n\tshift := uintptr(0)\n\tfor i := uintptr(0); i < size; i++ {\n\t\tloadedValue |= uintptr(*(*byte)(ptr)) << shift\n\t\tshift += 8\n\t\tptr = unsafe.Add(ptr, 1)\n\t}\n\treturn loadedValue\n}\n\n// storeValue is the inverse of loadValue. It stores a value to a pointer that\n// doesn't need to be aligned.\nfunc storeValue(ptr unsafe.Pointer, size, value uintptr) {\n\tfor i := uintptr(0); i < size; i++ {\n\t\t*(*byte)(ptr) = byte(value)\n\t\tptr = unsafe.Add(ptr, 1)\n\t\tvalue >>= 8\n\t}\n}\n\n// maskAndShift cuts out a part of a uintptr. Note that the offset may not be 0.\nfunc maskAndShift(value, offset, size uintptr) uintptr {\n\tmask := ^uintptr(0) >> ((unsafe.Sizeof(uintptr(0)) - size) * 8)\n\treturn (uintptr(value) >> (offset * 8)) & mask\n}\n"
  },
  {
    "path": "src/internal/reflectlite/strconv.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage reflectlite\n\nimport (\n\t\"unicode/utf8\"\n)\n\n// errSyntax indicates that a value does not have the right syntax for the target type.\nvar errSyntax = badSyntax{}\n\ntype badSyntax struct{}\n\nfunc (badSyntax) Error() string {\n\treturn \"invalid syntax\"\n}\n\nfunc unhex(b byte) (v rune, ok bool) {\n\tc := rune(b)\n\tswitch {\n\tcase '0' <= c && c <= '9':\n\t\treturn c - '0', true\n\tcase 'a' <= c && c <= 'f':\n\t\treturn c - 'a' + 10, true\n\tcase 'A' <= c && c <= 'F':\n\t\treturn c - 'A' + 10, true\n\t}\n\treturn\n}\n\nconst (\n\tlowerhex = \"0123456789abcef\"\n)\n\n// unquoteChar decodes the first character or byte in the escaped string\n// or character literal represented by the string s.\n// It returns four values:\n//\n//  1. value, the decoded Unicode code point or byte value;\n//  2. multibyte, a boolean indicating whether the decoded character requires a multibyte UTF-8 representation;\n//  3. tail, the remainder of the string after the character; and\n//  4. an error that will be nil if the character is syntactically valid.\n//\n// The second argument, quote, specifies the type of literal being parsed\n// and therefore which escaped quote character is permitted.\n// If set to a single quote, it permits the sequence \\' and disallows unescaped '.\n// If set to a double quote, it permits \\\" and disallows unescaped \".\n// If set to zero, it does not permit either escape and allows both quote characters to appear unescaped.\nfunc unquoteChar(s string, quote byte) (value rune, multibyte bool, tail string, err error) {\n\t// easy cases\n\tif len(s) == 0 {\n\t\terr = errSyntax\n\t\treturn\n\t}\n\tswitch c := s[0]; {\n\tcase c == quote && (quote == '\\'' || quote == '\"'):\n\t\terr = errSyntax\n\t\treturn\n\tcase c >= utf8.RuneSelf:\n\t\tr, size := utf8.DecodeRuneInString(s)\n\t\treturn r, true, s[size:], nil\n\tcase c != '\\\\':\n\t\treturn rune(s[0]), false, s[1:], nil\n\t}\n\n\t// hard case: c is backslash\n\tif len(s) <= 1 {\n\t\terr = errSyntax\n\t\treturn\n\t}\n\tc := s[1]\n\ts = s[2:]\n\n\tswitch c {\n\tcase 'a':\n\t\tvalue = '\\a'\n\tcase 'b':\n\t\tvalue = '\\b'\n\tcase 'f':\n\t\tvalue = '\\f'\n\tcase 'n':\n\t\tvalue = '\\n'\n\tcase 'r':\n\t\tvalue = '\\r'\n\tcase 't':\n\t\tvalue = '\\t'\n\tcase 'v':\n\t\tvalue = '\\v'\n\tcase 'x', 'u', 'U':\n\t\tn := 0\n\t\tswitch c {\n\t\tcase 'x':\n\t\t\tn = 2\n\t\tcase 'u':\n\t\t\tn = 4\n\t\tcase 'U':\n\t\t\tn = 8\n\t\t}\n\t\tvar v rune\n\t\tif len(s) < n {\n\t\t\terr = errSyntax\n\t\t\treturn\n\t\t}\n\t\tfor j := 0; j < n; j++ {\n\t\t\tx, ok := unhex(s[j])\n\t\t\tif !ok {\n\t\t\t\terr = errSyntax\n\t\t\t\treturn\n\t\t\t}\n\t\t\tv = v<<4 | x\n\t\t}\n\t\ts = s[n:]\n\t\tif c == 'x' {\n\t\t\t// single-byte string, possibly not UTF-8\n\t\t\tvalue = v\n\t\t\tbreak\n\t\t}\n\t\tif v > utf8.MaxRune {\n\t\t\terr = errSyntax\n\t\t\treturn\n\t\t}\n\t\tvalue = v\n\t\tmultibyte = true\n\tcase '0', '1', '2', '3', '4', '5', '6', '7':\n\t\tv := rune(c) - '0'\n\t\tif len(s) < 2 {\n\t\t\terr = errSyntax\n\t\t\treturn\n\t\t}\n\t\tfor j := 0; j < 2; j++ { // one digit already; two more\n\t\t\tx := rune(s[j]) - '0'\n\t\t\tif x < 0 || x > 7 {\n\t\t\t\terr = errSyntax\n\t\t\t\treturn\n\t\t\t}\n\t\t\tv = (v << 3) | x\n\t\t}\n\t\ts = s[2:]\n\t\tif v > 255 {\n\t\t\terr = errSyntax\n\t\t\treturn\n\t\t}\n\t\tvalue = v\n\tcase '\\\\':\n\t\tvalue = '\\\\'\n\tcase '\\'', '\"':\n\t\tif c != quote {\n\t\t\terr = errSyntax\n\t\t\treturn\n\t\t}\n\t\tvalue = rune(c)\n\tdefault:\n\t\terr = errSyntax\n\t\treturn\n\t}\n\ttail = s\n\treturn\n}\n\n// unquote interprets s as a single-quoted, double-quoted,\n// or backquoted Go string literal, returning the string value\n// that s quotes.  (If s is single-quoted, it would be a Go\n// character literal; unquote returns the corresponding\n// one-character string.)\nfunc unquote(s string) (string, error) {\n\tn := len(s)\n\tif n < 2 {\n\t\treturn \"\", errSyntax\n\t}\n\tquote := s[0]\n\tif quote != s[n-1] {\n\t\treturn \"\", errSyntax\n\t}\n\ts = s[1 : n-1]\n\n\tif quote == '`' {\n\t\tif contains(s, '`') {\n\t\t\treturn \"\", errSyntax\n\t\t}\n\t\tif contains(s, '\\r') {\n\t\t\t// -1 because we know there is at least one \\r to remove.\n\t\t\tbuf := make([]byte, 0, len(s)-1)\n\t\t\tfor i := 0; i < len(s); i++ {\n\t\t\t\tif s[i] != '\\r' {\n\t\t\t\t\tbuf = append(buf, s[i])\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn string(buf), nil\n\t\t}\n\t\treturn s, nil\n\t}\n\tif quote != '\"' && quote != '\\'' {\n\t\treturn \"\", errSyntax\n\t}\n\tif contains(s, '\\n') {\n\t\treturn \"\", errSyntax\n\t}\n\n\t// Is it trivial? Avoid allocation.\n\tif !contains(s, '\\\\') && !contains(s, quote) {\n\t\tswitch quote {\n\t\tcase '\"':\n\t\t\tif utf8.ValidString(s) {\n\t\t\t\treturn s, nil\n\t\t\t}\n\t\tcase '\\'':\n\t\t\tr, size := utf8.DecodeRuneInString(s)\n\t\t\tif size == len(s) && (r != utf8.RuneError || size != 1) {\n\t\t\t\treturn s, nil\n\t\t\t}\n\t\t}\n\t}\n\n\tvar runeTmp [utf8.UTFMax]byte\n\tbuf := make([]byte, 0, 3*len(s)/2) // Try to avoid more allocations.\n\tfor len(s) > 0 {\n\t\tc, multibyte, ss, err := unquoteChar(s, quote)\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\ts = ss\n\t\tif c < utf8.RuneSelf || !multibyte {\n\t\t\tbuf = append(buf, byte(c))\n\t\t} else {\n\t\t\tn := utf8.EncodeRune(runeTmp[:], c)\n\t\t\tbuf = append(buf, runeTmp[:n]...)\n\t\t}\n\t\tif quote == '\\'' && len(s) != 0 {\n\t\t\t// single-quoted must be single character\n\t\t\treturn \"\", errSyntax\n\t\t}\n\t}\n\treturn string(buf), nil\n}\n\nfunc quote(s string) string {\n\tbuf := make([]byte, 0, 3*len(s)/2)\n\tconst quote = '\"'\n\n\tbuf = append(buf, quote)\n\tfor width := 0; len(s) > 0; s = s[width:] {\n\t\tr := rune(s[0])\n\t\twidth = 1\n\t\tif r >= utf8.RuneSelf {\n\t\t\tr, width = utf8.DecodeRuneInString(s)\n\t\t}\n\t\tif width == 1 && r == utf8.RuneError {\n\t\t\tbuf = append(buf, `\\x`...)\n\t\t\tbuf = append(buf, lowerhex[s[0]>>4])\n\t\t\tbuf = append(buf, lowerhex[s[0]&0xF])\n\t\t\tcontinue\n\t\t}\n\t\tbuf = appendEscapedRune(buf, r)\n\t}\n\tbuf = append(buf, quote)\n\treturn string(buf)\n}\n\nfunc appendEscapedRune(buf []byte, r rune) []byte {\n\n\tconst quote = '\"'\n\n\tvar runeTmp [utf8.UTFMax]byte\n\tif r == rune(quote) || r == '\\\\' { // always backslashed\n\t\tbuf = append(buf, '\\\\')\n\t\tbuf = append(buf, byte(r))\n\t\treturn buf\n\t}\n\tif isPrint(r) {\n\t\tn := utf8.EncodeRune(runeTmp[:], r)\n\t\tbuf = append(buf, runeTmp[:n]...)\n\t\treturn buf\n\t}\n\tswitch r {\n\tcase '\\a':\n\t\tbuf = append(buf, `\\a`...)\n\tcase '\\b':\n\t\tbuf = append(buf, `\\b`...)\n\tcase '\\f':\n\t\tbuf = append(buf, `\\f`...)\n\tcase '\\n':\n\t\tbuf = append(buf, `\\n`...)\n\tcase '\\r':\n\t\tbuf = append(buf, `\\r`...)\n\tcase '\\t':\n\t\tbuf = append(buf, `\\t`...)\n\tcase '\\v':\n\t\tbuf = append(buf, `\\v`...)\n\tdefault:\n\t\tswitch {\n\t\tcase r < ' ' || r == 0x7f:\n\t\t\tbuf = append(buf, `\\x`...)\n\t\t\tbuf = append(buf, lowerhex[byte(r)>>4])\n\t\t\tbuf = append(buf, lowerhex[byte(r)&0xF])\n\t\tcase !utf8.ValidRune(r):\n\t\t\tr = 0xFFFD\n\t\t\tfallthrough\n\t\tcase r < 0x10000:\n\t\t\tbuf = append(buf, `\\u`...)\n\t\t\tfor s := 12; s >= 0; s -= 4 {\n\t\t\t\tbuf = append(buf, lowerhex[r>>uint(s)&0xF])\n\t\t\t}\n\t\tdefault:\n\t\t\tbuf = append(buf, `\\U`...)\n\t\t\tfor s := 28; s >= 0; s -= 4 {\n\t\t\t\tbuf = append(buf, lowerhex[r>>uint(s)&0xF])\n\t\t\t}\n\t\t}\n\t}\n\treturn buf\n}\n\n// This is only used for struct tags.  Assume\nfunc isPrint(r rune) bool {\n\tif r <= 0xFF {\n\t\tif 0x20 <= r && r <= 0x7E {\n\t\t\t// All the ASCII is printable from space through DEL-1.\n\t\t\treturn true\n\t\t}\n\t\tif 0xA1 <= r && r <= 0xFF {\n\t\t\t// Similarly for ¡ through ÿ...\n\t\t\treturn r != 0xAD // ...except for the bizarre soft hyphen.\n\t\t}\n\t\treturn false\n\t}\n\n\t// TinyGo: Skip all other unicode processing\n\treturn false\n}\n\n// contains reports whether the string contains the byte c.\nfunc contains(s string, c byte) bool {\n\treturn indexByteString(s, c) != -1\n}\n\n// Index finds the index of the first instance of the specified byte in the string.\n// If the byte is not found, this returns -1.\nfunc indexByteString(s string, c byte) int {\n\tfor i := 0; i < len(s); i++ {\n\t\tif s[i] == c {\n\t\t\treturn i\n\t\t}\n\t}\n\treturn -1\n}\n"
  },
  {
    "path": "src/internal/reflectlite/swapper.go",
    "content": "package reflectlite\n\nimport \"unsafe\"\n\n// Some of code here has been copied from the Go sources:\n//   https://github.com/golang/go/blob/go1.15.2/src/reflect/swapper.go\n// It has the following copyright note:\n//\n// \t\tCopyright 2016 The Go Authors. All rights reserved.\n// \t\tUse of this source code is governed by a BSD-style\n// \t\tlicense that can be found in the LICENSE file.\n\nfunc Swapper(slice interface{}) func(i, j int) {\n\tv := ValueOf(slice)\n\tif v.Kind() != Slice {\n\t\tpanic(&ValueError{Method: \"Swapper\"})\n\t}\n\n\t// Just return Nop func if nothing to swap.\n\tif v.Len() < 2 {\n\t\treturn func(i, j int) {}\n\t}\n\n\ttyp := v.typecode.Elem()\n\tsize := typ.Size()\n\n\theader := (*sliceHeader)(v.value)\n\ttmp := unsafe.Pointer(&make([]byte, size)[0])\n\n\treturn func(i, j int) {\n\t\tif uint(i) >= uint(header.len) || uint(j) >= uint(header.len) {\n\t\t\tpanic(\"reflect: slice index out of range\")\n\t\t}\n\t\tval1 := unsafe.Add(header.data, uintptr(i)*size)\n\t\tval2 := unsafe.Add(header.data, uintptr(j)*size)\n\t\tmemcpy(tmp, val1, size)\n\t\tmemcpy(val1, val2, size)\n\t\tmemcpy(val2, tmp, size)\n\t}\n}\n"
  },
  {
    "path": "src/internal/reflectlite/type.go",
    "content": "package reflectlite\n\nimport (\n\t\"internal/gclayout\"\n\t\"internal/itoa\"\n\t\"unsafe\"\n)\n\n// Flags stored in the first byte of the struct field byte array. Must be kept\n// up to date with compiler/interface.go.\nconst (\n\tstructFieldFlagAnonymous = 1 << iota\n\tstructFieldFlagHasTag\n\tstructFieldFlagIsExported\n\tstructFieldFlagIsEmbedded\n)\n\ntype Kind uint8\n\n// Copied from reflect/type.go\n// https://golang.org/src/reflect/type.go?s=8302:8316#L217\n// These constants must match basicTypes and the typeKind* constants in\n// compiler/interface.go\nconst (\n\tInvalid Kind = iota\n\tBool\n\tInt\n\tInt8\n\tInt16\n\tInt32\n\tInt64\n\tUint\n\tUint8\n\tUint16\n\tUint32\n\tUint64\n\tUintptr\n\tFloat32\n\tFloat64\n\tComplex64\n\tComplex128\n\tString\n\tUnsafePointer\n\tChan\n\tInterface\n\tPointer\n\tSlice\n\tArray\n\tFunc\n\tMap\n\tStruct\n)\n\n// Ptr is the old name for the Pointer kind.\nconst Ptr = Pointer\n\nfunc (k Kind) String() string {\n\tswitch k {\n\tcase Invalid:\n\t\treturn \"invalid\"\n\tcase Bool:\n\t\treturn \"bool\"\n\tcase Int:\n\t\treturn \"int\"\n\tcase Int8:\n\t\treturn \"int8\"\n\tcase Int16:\n\t\treturn \"int16\"\n\tcase Int32:\n\t\treturn \"int32\"\n\tcase Int64:\n\t\treturn \"int64\"\n\tcase Uint:\n\t\treturn \"uint\"\n\tcase Uint8:\n\t\treturn \"uint8\"\n\tcase Uint16:\n\t\treturn \"uint16\"\n\tcase Uint32:\n\t\treturn \"uint32\"\n\tcase Uint64:\n\t\treturn \"uint64\"\n\tcase Uintptr:\n\t\treturn \"uintptr\"\n\tcase Float32:\n\t\treturn \"float32\"\n\tcase Float64:\n\t\treturn \"float64\"\n\tcase Complex64:\n\t\treturn \"complex64\"\n\tcase Complex128:\n\t\treturn \"complex128\"\n\tcase String:\n\t\treturn \"string\"\n\tcase UnsafePointer:\n\t\treturn \"unsafe.Pointer\"\n\tcase Chan:\n\t\treturn \"chan\"\n\tcase Interface:\n\t\treturn \"interface\"\n\tcase Pointer:\n\t\treturn \"ptr\"\n\tcase Slice:\n\t\treturn \"slice\"\n\tcase Array:\n\t\treturn \"array\"\n\tcase Func:\n\t\treturn \"func\"\n\tcase Map:\n\t\treturn \"map\"\n\tcase Struct:\n\t\treturn \"struct\"\n\tdefault:\n\t\treturn \"kind\" + itoa.Itoa(int(int8(k)))\n\t}\n}\n\n// Copied from reflect/type.go\n// https://go.dev/src/reflect/type.go?#L348\n\n// ChanDir represents a channel type's direction.\ntype ChanDir int\n\nconst (\n\tRecvDir ChanDir             = 1 << iota // <-chan\n\tSendDir                                 // chan<-\n\tBothDir = RecvDir | SendDir             // chan\n)\n\n// Type represents the minimal interface for a Go type.\ntype Type interface {\n\t// These should match the reflectlite.Type implementation in Go.\n\tAssignableTo(u Type) bool\n\tComparable() bool\n\tElem() Type\n\tImplements(u Type) bool\n\tKind() Kind\n\tName() string\n\tPkgPath() string\n\tSize() uintptr\n\tString() string\n\n\t// Additional methods shared with reflect.Type.\n\tAlign() int\n\tField(i int) StructField\n\tKey() Type\n\tLen() int\n\tNumField() int\n\tNumMethod() int\n}\n\n// Constants for the 'meta' byte.\nconst (\n\tkindMask       = 31  // mask to apply to the meta byte to get the Kind value\n\tflagNamed      = 32  // flag that is set if this is a named type\n\tflagComparable = 64  // flag that is set if this type is comparable\n\tflagIsBinary   = 128 // flag that is set if this type uses the hashmap binary algorithm\n)\n\n// The base type struct. All type structs start with this.\ntype RawType struct {\n\tmeta uint8 // metadata byte, contains kind and flags (see constants above)\n}\n\n// All types that have an element type: named, chan, slice, array, map (but not\n// pointer because it doesn't have ptrTo).\ntype elemType struct {\n\tRawType\n\tnumMethod uint16\n\tptrTo     *RawType\n\telem      *RawType\n}\n\ntype ptrType struct {\n\tRawType\n\tnumMethod uint16\n\telem      *RawType\n}\n\ntype interfaceType struct {\n\tRawType\n\tptrTo *RawType\n\t// TODO: methods\n}\n\ntype arrayType struct {\n\tRawType\n\tnumMethod uint16\n\tptrTo     *RawType\n\telem      *RawType\n\tarrayLen  uintptr\n\tslicePtr  *RawType\n}\n\ntype mapType struct {\n\tRawType\n\tnumMethod uint16\n\tptrTo     *RawType\n\telem      *RawType\n\tkey       *RawType\n}\n\ntype namedType struct {\n\tRawType\n\tnumMethod uint16\n\tptrTo     *RawType\n\telem      *RawType\n\tpkg       *byte\n\tname      [1]byte\n}\n\n// Type for struct types. The numField value is intentionally put before ptrTo\n// for better struct packing on 32-bit and 64-bit architectures. On these\n// architectures, the ptrTo field still has the same offset as in all the other\n// type structs.\n// The fields array isn't necessarily 1 structField long, instead it is as long\n// as numFields. The array is given a length of 1 to satisfy the Go type\n// checker.\ntype structType struct {\n\tRawType\n\tnumMethod uint16\n\tptrTo     *RawType\n\tpkgpath   *byte\n\tsize      uint32\n\tnumField  uint16\n\tfields    [1]structField // the remaining fields are all of type structField\n}\n\ntype structField struct {\n\tfieldType *RawType\n\tdata      unsafe.Pointer // various bits of information, packed in a byte array\n}\n\n// Equivalent to (go/types.Type).Underlying(): if this is a named type return\n// the underlying type, else just return the type itself.\nfunc (t *RawType) underlying() *RawType {\n\tif t.isNamed() {\n\t\treturn (*elemType)(unsafe.Pointer(t)).elem\n\t}\n\treturn t\n}\n\nfunc (t *RawType) ptrtag() uintptr {\n\treturn uintptr(unsafe.Pointer(t)) & 0b11\n}\n\nfunc (t *RawType) isNamed() bool {\n\tif tag := t.ptrtag(); tag != 0 {\n\t\treturn false\n\t}\n\treturn t.meta&flagNamed != 0\n}\n\nfunc TypeOf(i interface{}) Type {\n\tif i == nil {\n\t\treturn nil\n\t}\n\ttypecode, _ := decomposeInterface(i)\n\treturn (*RawType)(typecode)\n}\n\nfunc PtrTo(t Type) Type { return PointerTo(t) }\n\nfunc PointerTo(t Type) Type {\n\treturn pointerTo(t.(*RawType))\n}\n\nfunc pointerTo(t *RawType) *RawType {\n\tif t.isNamed() {\n\t\treturn (*elemType)(unsafe.Pointer(t)).ptrTo\n\t}\n\n\tswitch t.Kind() {\n\tcase Pointer:\n\t\tif tag := t.ptrtag(); tag < 3 {\n\t\t\treturn (*RawType)(unsafe.Add(unsafe.Pointer(t), 1))\n\t\t}\n\n\t\t// TODO(dgryski): This is blocking https://github.com/tinygo-org/tinygo/issues/3131\n\t\t// We need to be able to create types that match existing types to prevent typecode equality.\n\t\tpanic(\"reflect: cannot make *****T type\")\n\tcase Struct:\n\t\treturn (*structType)(unsafe.Pointer(t)).ptrTo\n\tdefault:\n\t\treturn (*elemType)(unsafe.Pointer(t)).ptrTo\n\t}\n}\n\nfunc (t *RawType) String() string {\n\tif t.isNamed() {\n\t\ts := t.name()\n\t\tif s[0] == '.' {\n\t\t\treturn s[1:]\n\t\t}\n\t\treturn s\n\t}\n\tswitch t.Kind() {\n\tcase Chan:\n\t\telem := t.elem().String()\n\t\tswitch t.ChanDir() {\n\t\tcase SendDir:\n\t\t\treturn \"chan<- \" + elem\n\t\tcase RecvDir:\n\t\t\treturn \"<-chan \" + elem\n\t\tcase BothDir:\n\t\t\tif elem[0] == '<' {\n\t\t\t\t// typ is recv chan, need parentheses as \"<-\" associates with leftmost\n\t\t\t\t// chan possible, see:\n\t\t\t\t// * https://golang.org/ref/spec#Channel_types\n\t\t\t\t// * https://github.com/golang/go/issues/39897\n\t\t\t\treturn \"chan (\" + elem + \")\"\n\t\t\t}\n\t\t\treturn \"chan \" + elem\n\t\t}\n\n\tcase Pointer:\n\t\treturn \"*\" + t.elem().String()\n\tcase Slice:\n\t\treturn \"[]\" + t.elem().String()\n\tcase Array:\n\t\treturn \"[\" + itoa.Itoa(t.Len()) + \"]\" + t.elem().String()\n\tcase Map:\n\t\treturn \"map[\" + t.key().String() + \"]\" + t.elem().String()\n\tcase Struct:\n\t\tnumField := t.NumField()\n\t\tif numField == 0 {\n\t\t\treturn \"struct {}\"\n\t\t}\n\t\ts := \"struct {\"\n\t\tfor i := 0; i < numField; i++ {\n\t\t\tf := t.rawField(i)\n\t\t\ts += \" \" + f.Name + \" \" + f.Type.String()\n\t\t\tif f.Tag != \"\" {\n\t\t\t\ts += \" \" + quote(string(f.Tag))\n\t\t\t}\n\t\t\t// every field except the last needs a semicolon\n\t\t\tif i < numField-1 {\n\t\t\t\ts += \";\"\n\t\t\t}\n\t\t}\n\t\ts += \" }\"\n\t\treturn s\n\tcase Interface:\n\t\t// TODO(dgryski): Needs actual method set info\n\t\treturn \"interface {}\"\n\tdefault:\n\t\treturn t.Kind().String()\n\t}\n\n\treturn t.Kind().String()\n}\n\nfunc (t *RawType) Kind() Kind {\n\tif t == nil {\n\t\treturn Invalid\n\t}\n\n\tif tag := t.ptrtag(); tag != 0 {\n\t\treturn Pointer\n\t}\n\n\treturn Kind(t.meta & kindMask)\n}\n\nvar (\n\terrTypeElem         = &TypeError{\"Elem\"}\n\terrTypeKey          = &TypeError{\"Key\"}\n\terrTypeField        = &TypeError{\"Field\"}\n\terrTypeBits         = &TypeError{\"Bits\"}\n\terrTypeLen          = &TypeError{\"Len\"}\n\terrTypeNumField     = &TypeError{\"NumField\"}\n\terrTypeChanDir      = &TypeError{\"ChanDir\"}\n\terrTypeFieldByName  = &TypeError{\"FieldByName\"}\n\terrTypeFieldByIndex = &TypeError{\"FieldByIndex\"}\n)\n\n// Elem returns the element type for channel, slice and array types, the\n// pointed-to value for pointer types, and the key type for map types.\nfunc (t *RawType) Elem() Type {\n\treturn t.elem()\n}\n\nfunc (t *RawType) elem() *RawType {\n\tif tag := t.ptrtag(); tag != 0 {\n\t\treturn (*RawType)(unsafe.Add(unsafe.Pointer(t), -1))\n\t}\n\n\tunderlying := t.underlying()\n\tswitch underlying.Kind() {\n\tcase Pointer:\n\t\treturn (*ptrType)(unsafe.Pointer(underlying)).elem\n\tcase Chan, Slice, Array, Map:\n\t\treturn (*elemType)(unsafe.Pointer(underlying)).elem\n\tdefault:\n\t\tpanic(errTypeElem)\n\t}\n}\n\nfunc (t *RawType) key() *RawType {\n\tunderlying := t.underlying()\n\tif underlying.Kind() != Map {\n\t\tpanic(errTypeKey)\n\t}\n\treturn (*mapType)(unsafe.Pointer(underlying)).key\n}\n\n// Field returns the type of the i'th field of this struct type. It panics if t\n// is not a struct type.\nfunc (t *RawType) Field(i int) StructField {\n\tfield := t.rawField(i)\n\treturn StructField{\n\t\tName:      field.Name,\n\t\tPkgPath:   field.PkgPath,\n\t\tType:      field.Type, // note: converts RawType to Type\n\t\tTag:       field.Tag,\n\t\tAnonymous: field.Anonymous,\n\t\tOffset:    field.Offset,\n\t\tIndex:     []int{i},\n\t}\n}\n\nfunc rawStructFieldFromPointer(descriptor *structType, fieldType *RawType, data unsafe.Pointer, flagsByte uint8, name string, offset uint32) rawStructField {\n\t// Read the field tag, if there is one.\n\tvar tag string\n\tif flagsByte&structFieldFlagHasTag != 0 {\n\t\tdata = unsafe.Add(data, 1) // C: data+1\n\t\ttagLen := uintptr(*(*byte)(data))\n\t\tdata = unsafe.Add(data, 1) // C: data+1\n\t\ttag = *(*string)(unsafe.Pointer(&stringHeader{\n\t\t\tdata: data,\n\t\t\tlen:  tagLen,\n\t\t}))\n\t}\n\n\t// Set the PkgPath to some (arbitrary) value if the package path is not\n\t// exported.\n\tpkgPath := \"\"\n\tif flagsByte&structFieldFlagIsExported == 0 {\n\t\t// This field is unexported.\n\t\tpkgPath = readStringZ(unsafe.Pointer(descriptor.pkgpath))\n\t}\n\n\treturn rawStructField{\n\t\tName:      name,\n\t\tPkgPath:   pkgPath,\n\t\tType:      fieldType,\n\t\tTag:       StructTag(tag),\n\t\tAnonymous: flagsByte&structFieldFlagAnonymous != 0,\n\t\tOffset:    uintptr(offset),\n\t}\n}\n\n// rawField returns nearly the same value as Field but without converting the\n// Type member to an interface.\n//\n// For internal use only.\nfunc (t *RawType) rawField(n int) rawStructField {\n\tif t.Kind() != Struct {\n\t\tpanic(errTypeField)\n\t}\n\tdescriptor := (*structType)(unsafe.Pointer(t.underlying()))\n\tif uint(n) >= uint(descriptor.numField) {\n\t\tpanic(\"reflect: field index out of range\")\n\t}\n\n\t// Iterate over all the fields to calculate the offset.\n\t// This offset could have been stored directly in the array (to make the\n\t// lookup faster), but by calculating it on-the-fly a bit of storage can be\n\t// saved.\n\tfield := (*structField)(unsafe.Add(unsafe.Pointer(&descriptor.fields[0]), uintptr(n)*unsafe.Sizeof(structField{})))\n\tdata := field.data\n\n\t// Read some flags of this field, like whether the field is an embedded\n\t// field. See structFieldFlagAnonymous and similar flags.\n\tflagsByte := *(*byte)(data)\n\tdata = unsafe.Add(data, 1)\n\toffset, lenOffs := uvarint32(unsafe.Slice((*byte)(data), maxVarintLen32))\n\tdata = unsafe.Add(data, lenOffs)\n\n\tname := readStringZ(data)\n\tdata = unsafe.Add(data, len(name))\n\n\treturn rawStructFieldFromPointer(descriptor, field.fieldType, data, flagsByte, name, offset)\n}\n\n// rawFieldByNameFunc returns nearly the same value as FieldByNameFunc but without converting the\n// Type member to an interface.\n//\n// For internal use only.\nfunc (t *RawType) rawFieldByNameFunc(match func(string) bool) (rawStructField, []int, bool) {\n\tif t.Kind() != Struct {\n\t\tpanic(errTypeField)\n\t}\n\n\ttype fieldWalker struct {\n\t\tt     *RawType\n\t\tindex []int\n\t}\n\n\tqueue := make([]fieldWalker, 0, 4)\n\tqueue = append(queue, fieldWalker{t, nil})\n\n\tfor len(queue) > 0 {\n\t\ttype result struct {\n\t\t\tr     rawStructField\n\t\t\tindex []int\n\t\t}\n\n\t\tvar found []result\n\t\tvar nextlevel []fieldWalker\n\n\t\t// For all the structs at this level..\n\t\tfor _, ll := range queue {\n\t\t\t// Iterate over all the fields looking for the matching name\n\t\t\t// Also calculate field offset.\n\n\t\t\tdescriptor := (*structType)(unsafe.Pointer(ll.t.underlying()))\n\t\t\tfield := &descriptor.fields[0]\n\n\t\t\tfor i := uint16(0); i < descriptor.numField; i++ {\n\t\t\t\tdata := field.data\n\n\t\t\t\t// Read some flags of this field, like whether the field is an embedded\n\t\t\t\t// field. See structFieldFlagAnonymous and similar flags.\n\t\t\t\tflagsByte := *(*byte)(data)\n\t\t\t\tdata = unsafe.Add(data, 1)\n\n\t\t\t\toffset, lenOffs := uvarint32(unsafe.Slice((*byte)(data), maxVarintLen32))\n\t\t\t\tdata = unsafe.Add(data, lenOffs)\n\n\t\t\t\tname := readStringZ(data)\n\t\t\t\tdata = unsafe.Add(data, len(name))\n\t\t\t\tif match(name) {\n\t\t\t\t\tfound = append(found, result{\n\t\t\t\t\t\trawStructFieldFromPointer(descriptor, field.fieldType, data, flagsByte, name, offset),\n\t\t\t\t\t\tappend(ll.index[:len(ll.index):len(ll.index)], int(i)),\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tstructOrPtrToStruct := field.fieldType.Kind() == Struct || (field.fieldType.Kind() == Pointer && field.fieldType.elem().Kind() == Struct)\n\t\t\t\tif flagsByte&structFieldFlagIsEmbedded == structFieldFlagIsEmbedded && structOrPtrToStruct {\n\t\t\t\t\tembedded := field.fieldType\n\t\t\t\t\tif embedded.Kind() == Pointer {\n\t\t\t\t\t\tembedded = embedded.elem()\n\t\t\t\t\t}\n\n\t\t\t\t\tnextlevel = append(nextlevel, fieldWalker{\n\t\t\t\t\t\tt:     embedded,\n\t\t\t\t\t\tindex: append(ll.index[:len(ll.index):len(ll.index)], int(i)),\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\t// update offset/field pointer if there *is* a next field\n\t\t\t\tif i < descriptor.numField-1 {\n\t\t\t\t\t// Increment pointer to the next field.\n\t\t\t\t\tfield = (*structField)(unsafe.Add(unsafe.Pointer(field), unsafe.Sizeof(structField{})))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// found multiple hits at this level\n\t\tif len(found) > 1 {\n\t\t\treturn rawStructField{}, nil, false\n\t\t}\n\n\t\t// found the field we were looking for\n\t\tif len(found) == 1 {\n\t\t\tr := found[0]\n\t\t\treturn r.r, r.index, true\n\t\t}\n\n\t\t// else len(found) == 0, move on to the next level\n\t\tqueue = append(queue[:0], nextlevel...)\n\t}\n\n\t// didn't find it\n\treturn rawStructField{}, nil, false\n}\n\n// Bits returns the number of bits that this type uses. It is only valid for\n// arithmetic types (integers, floats, and complex numbers). For other types, it\n// will panic.\nfunc (t *RawType) Bits() int {\n\tkind := t.Kind()\n\tif kind >= Int && kind <= Complex128 {\n\t\treturn int(t.Size()) * 8\n\t}\n\tpanic(errTypeBits)\n}\n\n// Len returns the number of elements in this array. It panics of the type kind\n// is not Array.\nfunc (t *RawType) Len() int {\n\tif t.Kind() != Array {\n\t\tpanic(errTypeLen)\n\t}\n\n\treturn int((*arrayType)(unsafe.Pointer(t.underlying())).arrayLen)\n}\n\n// NumField returns the number of fields of a struct type. It panics for other\n// type kinds.\nfunc (t *RawType) NumField() int {\n\tif t.Kind() != Struct {\n\t\tpanic(errTypeNumField)\n\t}\n\treturn int((*structType)(unsafe.Pointer(t.underlying())).numField)\n}\n\n// Size returns the size in bytes of a given type. It is similar to\n// unsafe.Sizeof.\nfunc (t *RawType) Size() uintptr {\n\tswitch t.Kind() {\n\tcase Bool, Int8, Uint8:\n\t\treturn 1\n\tcase Int16, Uint16:\n\t\treturn 2\n\tcase Int32, Uint32:\n\t\treturn 4\n\tcase Int64, Uint64:\n\t\treturn 8\n\tcase Int, Uint:\n\t\treturn unsafe.Sizeof(int(0))\n\tcase Uintptr:\n\t\treturn unsafe.Sizeof(uintptr(0))\n\tcase Float32:\n\t\treturn 4\n\tcase Float64:\n\t\treturn 8\n\tcase Complex64:\n\t\treturn 8\n\tcase Complex128:\n\t\treturn 16\n\tcase String:\n\t\treturn unsafe.Sizeof(\"\")\n\tcase UnsafePointer, Chan, Map, Pointer:\n\t\treturn unsafe.Sizeof(uintptr(0))\n\tcase Slice:\n\t\treturn unsafe.Sizeof([]int{})\n\tcase Interface:\n\t\treturn unsafe.Sizeof(interface{}(nil))\n\tcase Func:\n\t\tvar f func()\n\t\treturn unsafe.Sizeof(f)\n\tcase Array:\n\t\treturn t.elem().Size() * uintptr(t.Len())\n\tcase Struct:\n\t\tu := t.underlying()\n\t\treturn uintptr((*structType)(unsafe.Pointer(u)).size)\n\tdefault:\n\t\tpanic(\"unimplemented: size of type\")\n\t}\n}\n\n// Align returns the alignment of this type. It is similar to calling\n// unsafe.Alignof.\nfunc (t *RawType) Align() int {\n\tswitch t.Kind() {\n\tcase Bool, Int8, Uint8:\n\t\treturn int(unsafe.Alignof(int8(0)))\n\tcase Int16, Uint16:\n\t\treturn int(unsafe.Alignof(int16(0)))\n\tcase Int32, Uint32:\n\t\treturn int(unsafe.Alignof(int32(0)))\n\tcase Int64, Uint64:\n\t\treturn int(unsafe.Alignof(int64(0)))\n\tcase Int, Uint:\n\t\treturn int(unsafe.Alignof(int(0)))\n\tcase Uintptr:\n\t\treturn int(unsafe.Alignof(uintptr(0)))\n\tcase Float32:\n\t\treturn int(unsafe.Alignof(float32(0)))\n\tcase Float64:\n\t\treturn int(unsafe.Alignof(float64(0)))\n\tcase Complex64:\n\t\treturn int(unsafe.Alignof(complex64(0)))\n\tcase Complex128:\n\t\treturn int(unsafe.Alignof(complex128(0)))\n\tcase String:\n\t\treturn int(unsafe.Alignof(\"\"))\n\tcase UnsafePointer, Chan, Map, Pointer:\n\t\treturn int(unsafe.Alignof(uintptr(0)))\n\tcase Slice:\n\t\treturn int(unsafe.Alignof([]int(nil)))\n\tcase Interface:\n\t\treturn int(unsafe.Alignof(interface{}(nil)))\n\tcase Func:\n\t\tvar f func()\n\t\treturn int(unsafe.Alignof(f))\n\tcase Struct:\n\t\tnumField := t.NumField()\n\t\talignment := 1\n\t\tfor i := 0; i < numField; i++ {\n\t\t\tfieldAlignment := t.rawField(i).Type.Align()\n\t\t\tif fieldAlignment > alignment {\n\t\t\t\talignment = fieldAlignment\n\t\t\t}\n\t\t}\n\t\treturn alignment\n\tcase Array:\n\t\treturn t.elem().Align()\n\tdefault:\n\t\tpanic(\"unimplemented: alignment of type\")\n\t}\n}\n\nfunc (r *RawType) gcLayout() unsafe.Pointer {\n\tkind := r.Kind()\n\n\tif kind < String {\n\t\treturn gclayout.NoPtrs.AsPtr()\n\t}\n\n\tswitch kind {\n\tcase Pointer, UnsafePointer, Chan, Map:\n\t\treturn gclayout.Pointer.AsPtr()\n\tcase String:\n\t\treturn gclayout.String.AsPtr()\n\tcase Slice:\n\t\treturn gclayout.Slice.AsPtr()\n\t}\n\n\t// Unknown (for now); let the conservative pointer scanning handle it\n\treturn nil\n}\n\n// FieldAlign returns the alignment if this type is used in a struct field. It\n// is currently an alias for Align() but this might change in the future.\nfunc (t *RawType) FieldAlign() int {\n\treturn t.Align()\n}\n\n// AssignableTo returns whether a value of type t can be assigned to a variable\n// of type u.\nfunc (t *RawType) AssignableTo(u Type) bool {\n\tif t == u.(*RawType) {\n\t\treturn true\n\t}\n\n\tif t.underlying() == u.(*RawType).underlying() && (!t.isNamed() || !u.(*RawType).isNamed()) {\n\t\treturn true\n\t}\n\n\tif u.Kind() == Interface && u.NumMethod() == 0 {\n\t\treturn true\n\t}\n\n\tif u.Kind() == Interface {\n\t\tpanic(\"reflect: unimplemented: AssignableTo with interface\")\n\t}\n\treturn false\n}\n\nfunc (t *RawType) Implements(u Type) bool {\n\tif u.Kind() != Interface {\n\t\tpanic(\"reflect: non-interface type passed to Type.Implements\")\n\t}\n\treturn t.AssignableTo(u)\n}\n\n// Comparable returns whether values of this type can be compared to each other.\nfunc (t *RawType) Comparable() bool {\n\treturn (t.meta & flagComparable) == flagComparable\n}\n\n// isBinary returns if the hashmapAlgorithmBinary functions can be used on this type\nfunc (t *RawType) isBinary() bool {\n\treturn (t.meta & flagIsBinary) == flagIsBinary\n}\n\nfunc (t *RawType) ChanDir() ChanDir {\n\tif t.Kind() != Chan {\n\t\tpanic(errTypeChanDir)\n\t}\n\n\tdir := int((*elemType)(unsafe.Pointer(t)).numMethod)\n\n\t// nummethod is overloaded for channel to store channel direction\n\treturn ChanDir(dir)\n}\n\nfunc (t *RawType) NumMethod() int {\n\n\tif t.isNamed() {\n\t\treturn int((*namedType)(unsafe.Pointer(t)).numMethod)\n\t}\n\n\tswitch t.Kind() {\n\tcase Pointer:\n\t\treturn int((*ptrType)(unsafe.Pointer(t)).numMethod)\n\tcase Struct:\n\t\treturn int((*structType)(unsafe.Pointer(t)).numMethod)\n\tcase Interface:\n\t\t//FIXME: Use len(methods)\n\t\treturn (*interfaceType)(unsafe.Pointer(t)).ptrTo.NumMethod()\n\t}\n\n\t// Other types have no methods attached.  Note we don't panic here.\n\treturn 0\n}\n\n// Read and return a null terminated string starting from data.\nfunc readStringZ(data unsafe.Pointer) string {\n\tstart := data\n\tvar len uintptr\n\tfor *(*byte)(data) != 0 {\n\t\tlen++\n\t\tdata = unsafe.Add(data, 1) // C: data++\n\t}\n\n\treturn *(*string)(unsafe.Pointer(&stringHeader{\n\t\tdata: start,\n\t\tlen:  len,\n\t}))\n}\n\nfunc (t *RawType) name() string {\n\tntype := (*namedType)(unsafe.Pointer(t))\n\treturn readStringZ(unsafe.Pointer(&ntype.name[0]))\n}\n\nfunc (t *RawType) Name() string {\n\tif t.isNamed() {\n\t\tname := t.name()\n\t\tfor i := 0; i < len(name); i++ {\n\t\t\tif name[i] == '.' {\n\t\t\t\treturn name[i+1:]\n\t\t\t}\n\t\t}\n\t\tpanic(\"corrupt name data\")\n\t}\n\n\tif kind := t.Kind(); kind < UnsafePointer {\n\t\treturn t.Kind().String()\n\t} else if kind == UnsafePointer {\n\t\treturn \"Pointer\"\n\t}\n\n\treturn \"\"\n}\n\nfunc (t *RawType) Key() Type {\n\treturn t.key()\n}\n\n// OverflowComplex reports whether the complex128 x cannot be represented by type t.\n// It panics if t's Kind is not Complex64 or Complex128.\nfunc (t RawType) OverflowComplex(x complex128) bool {\n\tk := t.Kind()\n\tswitch k {\n\tcase Complex64:\n\t\treturn overflowFloat32(real(x)) || overflowFloat32(imag(x))\n\tcase Complex128:\n\t\treturn false\n\t}\n\tpanic(\"reflect: OverflowComplex of non-complex type\")\n}\n\n// OverflowFloat reports whether the float64 x cannot be represented by type t.\n// It panics if t's Kind is not Float32 or Float64.\nfunc (t RawType) OverflowFloat(x float64) bool {\n\tk := t.Kind()\n\tswitch k {\n\tcase Float32:\n\t\treturn overflowFloat32(x)\n\tcase Float64:\n\t\treturn false\n\t}\n\tpanic(\"reflect: OverflowFloat of non-float type\")\n}\n\n// OverflowInt reports whether the int64 x cannot be represented by type t.\n// It panics if t's Kind is not Int, Int8, Int16, Int32, or Int64.\nfunc (t RawType) OverflowInt(x int64) bool {\n\tk := t.Kind()\n\tswitch k {\n\tcase Int, Int8, Int16, Int32, Int64:\n\t\tbitSize := t.Size() * 8\n\t\ttrunc := (x << (64 - bitSize)) >> (64 - bitSize)\n\t\treturn x != trunc\n\t}\n\tpanic(\"reflect: OverflowInt of non-int type\")\n}\n\n// OverflowUint reports whether the uint64 x cannot be represented by type t.\n// It panics if t's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64.\nfunc (t RawType) OverflowUint(x uint64) bool {\n\tk := t.Kind()\n\tswitch k {\n\tcase Uint, Uintptr, Uint8, Uint16, Uint32, Uint64:\n\t\tbitSize := t.Size() * 8\n\t\ttrunc := (x << (64 - bitSize)) >> (64 - bitSize)\n\t\treturn x != trunc\n\t}\n\tpanic(\"reflect: OverflowUint of non-uint type\")\n}\n\nfunc (t *RawType) PkgPath() string {\n\tif t.isNamed() {\n\t\tntype := (*namedType)(unsafe.Pointer(t))\n\t\treturn readStringZ(unsafe.Pointer(ntype.pkg))\n\t}\n\n\treturn \"\"\n}\n\nfunc (t *RawType) FieldByName(name string) (StructField, bool) {\n\tif t.Kind() != Struct {\n\t\tpanic(errTypeFieldByName)\n\t}\n\n\tfield, index, ok := t.rawFieldByNameFunc(func(n string) bool { return n == name })\n\tif !ok {\n\t\treturn StructField{}, false\n\t}\n\n\treturn StructField{\n\t\tName:      field.Name,\n\t\tPkgPath:   field.PkgPath,\n\t\tType:      field.Type, // note: converts RawType to Type\n\t\tTag:       field.Tag,\n\t\tAnonymous: field.Anonymous,\n\t\tOffset:    field.Offset,\n\t\tIndex:     index,\n\t}, true\n}\n\nfunc (t *RawType) FieldByNameFunc(match func(string) bool) (StructField, bool) {\n\tif t.Kind() != Struct {\n\t\tpanic(TypeError{\"FieldByNameFunc\"})\n\t}\n\n\tfield, index, ok := t.rawFieldByNameFunc(match)\n\tif !ok {\n\t\treturn StructField{}, false\n\t}\n\n\treturn StructField{\n\t\tName:      field.Name,\n\t\tPkgPath:   field.PkgPath,\n\t\tType:      field.Type, // note: converts RawType to Type\n\t\tTag:       field.Tag,\n\t\tAnonymous: field.Anonymous,\n\t\tOffset:    field.Offset,\n\t\tIndex:     index,\n\t}, true\n}\n\nfunc (t *RawType) FieldByIndex(index []int) StructField {\n\tftype := t\n\tvar field rawStructField\n\n\tfor _, n := range index {\n\t\tstructOrPtrToStruct := ftype.Kind() == Struct || (ftype.Kind() == Pointer && ftype.elem().Kind() == Struct)\n\t\tif !structOrPtrToStruct {\n\t\t\tpanic(errTypeFieldByIndex)\n\t\t}\n\n\t\tif ftype.Kind() == Pointer {\n\t\t\tftype = ftype.elem()\n\t\t}\n\n\t\tfield = ftype.rawField(n)\n\t\tftype = field.Type\n\t}\n\n\treturn StructField{\n\t\tName:      field.Name,\n\t\tPkgPath:   field.PkgPath,\n\t\tType:      field.Type, // note: converts RawType to Type\n\t\tTag:       field.Tag,\n\t\tAnonymous: field.Anonymous,\n\t\tOffset:    field.Offset,\n\t\tIndex:     index,\n\t}\n}\n\n// A StructField describes a single field in a struct.\n// This must be kept in sync with [reflect.StructField].\ntype StructField struct {\n\t// Name indicates the field name.\n\tName string\n\n\t// PkgPath is the package path where the struct containing this field is\n\t// declared for unexported fields, or the empty string for exported fields.\n\tPkgPath string\n\n\tType      Type\n\tTag       StructTag // field tag string\n\tOffset    uintptr\n\tIndex     []int // index sequence for Type.FieldByIndex\n\tAnonymous bool\n}\n\n// IsExported reports whether the field is exported.\nfunc (f StructField) IsExported() bool {\n\treturn f.PkgPath == \"\"\n}\n\n// rawStructField is the same as StructField but with the Type member replaced\n// with RawType. For internal use only. Avoiding this conversion to the Type\n// interface improves code size in many cases.\ntype rawStructField struct {\n\tName      string\n\tPkgPath   string\n\tType      *RawType\n\tTag       StructTag\n\tOffset    uintptr\n\tAnonymous bool\n}\n\n// A StructTag is the tag string in a struct field.\ntype StructTag string\n\n// TODO: it would be feasible to do the key/value splitting at compile time,\n// avoiding the code size cost of doing it at runtime\n\n// Get returns the value associated with key in the tag string.\nfunc (tag StructTag) Get(key string) string {\n\tv, _ := tag.Lookup(key)\n\treturn v\n}\n\n// Lookup returns the value associated with key in the tag string.\nfunc (tag StructTag) Lookup(key string) (value string, ok bool) {\n\tfor tag != \"\" {\n\t\t// Skip leading space.\n\t\ti := 0\n\t\tfor i < len(tag) && tag[i] == ' ' {\n\t\t\ti++\n\t\t}\n\t\ttag = tag[i:]\n\t\tif tag == \"\" {\n\t\t\tbreak\n\t\t}\n\n\t\t// Scan to colon. A space, a quote or a control character is a syntax error.\n\t\t// Strictly speaking, control chars include the range [0x7f, 0x9f], not just\n\t\t// [0x00, 0x1f], but in practice, we ignore the multi-byte control characters\n\t\t// as it is simpler to inspect the tag's bytes than the tag's runes.\n\t\ti = 0\n\t\tfor i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '\"' && tag[i] != 0x7f {\n\t\t\ti++\n\t\t}\n\t\tif i == 0 || i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '\"' {\n\t\t\tbreak\n\t\t}\n\t\tname := string(tag[:i])\n\t\ttag = tag[i+1:]\n\n\t\t// Scan quoted string to find value.\n\t\ti = 1\n\t\tfor i < len(tag) && tag[i] != '\"' {\n\t\t\tif tag[i] == '\\\\' {\n\t\t\t\ti++\n\t\t\t}\n\t\t\ti++\n\t\t}\n\t\tif i >= len(tag) {\n\t\t\tbreak\n\t\t}\n\t\tqvalue := string(tag[:i+1])\n\t\ttag = tag[i+1:]\n\n\t\tif key == name {\n\t\t\tvalue, err := unquote(qvalue)\n\t\t\tif err != nil {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\treturn value, true\n\t\t}\n\t}\n\treturn \"\", false\n}\n\n// TypeError is the error that is used in a panic when invoking a method on a\n// type that is not applicable to that type.\ntype TypeError struct {\n\tMethod string\n}\n\nfunc (e *TypeError) Error() string {\n\treturn \"reflect: call of reflect.Type.\" + e.Method + \" on invalid type\"\n}\n\nfunc align(offset uintptr, alignment uintptr) uintptr {\n\treturn (offset + alignment - 1) &^ (alignment - 1)\n}\n\nfunc SliceOf(t Type) Type {\n\tpanic(\"unimplemented: reflect.SliceOf()\")\n}\n\nfunc ArrayOf(n int, t Type) Type {\n\tpanic(\"unimplemented: reflect.ArrayOf()\")\n}\n\nfunc StructOf([]StructField) Type {\n\tpanic(\"unimplemented: reflect.StructOf()\")\n}\n\nfunc MapOf(key, value Type) Type {\n\tpanic(\"unimplemented: reflect.MapOf()\")\n}\n\nfunc FuncOf(in, out []Type, variadic bool) Type {\n\tpanic(\"unimplemented: reflect.FuncOf()\")\n}\n\nconst maxVarintLen32 = 5\n\n// encoding/binary.Uvarint, specialized for uint32\nfunc uvarint32(buf []byte) (uint32, int) {\n\tvar x uint32\n\tvar s uint\n\tfor i, b := range buf {\n\t\tif b < 0x80 {\n\t\t\treturn x | uint32(b)<<s, i + 1\n\t\t}\n\t\tx |= uint32(b&0x7f) << s\n\t\ts += 7\n\t}\n\treturn 0, 0\n}\n\n// TypeFor returns the [Type] that represents the type argument T.\nfunc TypeFor[T any]() Type {\n\t// This function was copied from the Go 1.22 source tree.\n\treturn TypeOf((*T)(nil)).Elem()\n}\n"
  },
  {
    "path": "src/internal/reflectlite/value.go",
    "content": "package reflectlite\n\nimport (\n\t\"math\"\n\t\"unsafe\"\n)\n\ntype valueFlags uint8\n\n// Flags list some useful flags that contain some extra information not\n// contained in an interface{} directly, like whether this value was exported at\n// all (it is possible to read unexported fields using reflection, but it is not\n// possible to modify them).\nconst (\n\tvalueFlagIndirect valueFlags = 1 << iota\n\tvalueFlagExported\n\tvalueFlagEmbedRO\n\tvalueFlagStickyRO\n\n\tvalueFlagRO = valueFlagEmbedRO | valueFlagStickyRO\n)\n\nfunc (v valueFlags) ro() valueFlags {\n\tif v&valueFlagRO != 0 {\n\t\treturn valueFlagStickyRO\n\t}\n\treturn 0\n}\n\ntype Value struct {\n\ttypecode *RawType\n\tvalue    unsafe.Pointer\n\tflags    valueFlags\n}\n\n// isIndirect returns whether the value pointer in this Value is always a\n// pointer to the value. If it is false, it is only a pointer to the value if\n// the value is bigger than a pointer.\nfunc (v Value) isIndirect() bool {\n\treturn v.flags&valueFlagIndirect != 0\n}\n\n// isExported returns whether the value represented by this Value could be\n// accessed without violating type system constraints. For example, it is not\n// set for unexported struct fields.\nfunc (v Value) isExported() bool {\n\treturn v.flags&valueFlagExported != 0\n}\n\nfunc (v Value) isRO() bool {\n\treturn v.flags&(valueFlagRO) != 0\n}\n\nfunc (v Value) checkRO() {\n\tif v.isRO() {\n\t\tpanic(\"reflect: value is not settable\")\n\t}\n}\n\nfunc Indirect(v Value) Value {\n\tif v.Kind() != Ptr {\n\t\treturn v\n\t}\n\treturn v.Elem()\n}\n\n//go:linkname composeInterface runtime.composeInterface\nfunc composeInterface(unsafe.Pointer, unsafe.Pointer) interface{}\n\n//go:linkname decomposeInterface runtime.decomposeInterface\nfunc decomposeInterface(i interface{}) (unsafe.Pointer, unsafe.Pointer)\n\nfunc ValueOf(i interface{}) Value {\n\ttypecode, value := decomposeInterface(i)\n\treturn Value{\n\t\ttypecode: (*RawType)(typecode),\n\t\tvalue:    value,\n\t\tflags:    valueFlagExported,\n\t}\n}\n\nfunc (v Value) Interface() interface{} {\n\tif !v.isExported() {\n\t\tpanic(\"(reflect.Value).Interface: unexported\")\n\t}\n\treturn valueInterfaceUnsafe(v)\n}\n\n// valueInterfaceUnsafe is used by the runtime to hash map keys. It should not\n// be subject to the isExported check.\nfunc valueInterfaceUnsafe(v Value) interface{} {\n\tif v.typecode.Kind() == Interface {\n\t\t// The value itself is an interface. This can happen when getting the\n\t\t// value of a struct field of interface type, like this:\n\t\t//     type T struct {\n\t\t//         X interface{}\n\t\t//     }\n\t\treturn *(*interface{})(v.value)\n\t}\n\tif v.isIndirect() && v.typecode.Size() <= unsafe.Sizeof(uintptr(0)) {\n\t\t// Value was indirect but must be put back directly in the interface\n\t\t// value.\n\t\tvar value uintptr\n\t\tfor j := v.typecode.Size(); j != 0; j-- {\n\t\t\tvalue = (value << 8) | uintptr(*(*uint8)(unsafe.Add(v.value, j-1)))\n\t\t}\n\t\tv.value = unsafe.Pointer(value)\n\t}\n\treturn composeInterface(unsafe.Pointer(v.typecode), v.value)\n}\n\nfunc (v Value) Type() Type {\n\treturn v.typecode\n}\n\n// IsZero reports whether v is the zero value for its type.\n// It panics if the argument is invalid.\nfunc (v Value) IsZero() bool {\n\tswitch v.Kind() {\n\tcase Bool:\n\t\treturn !v.Bool()\n\tcase Int, Int8, Int16, Int32, Int64:\n\t\treturn v.Int() == 0\n\tcase Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:\n\t\treturn v.Uint() == 0\n\tcase Float32, Float64:\n\t\treturn v.Float() == 0\n\tcase Complex64, Complex128:\n\t\treturn v.Complex() == 0\n\tcase Array:\n\t\tfor i := 0; i < v.Len(); i++ {\n\t\t\tif !v.Index(i).IsZero() {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\tcase Chan, Func, Interface, Map, Pointer, Slice, UnsafePointer:\n\t\treturn v.IsNil()\n\tcase String:\n\t\treturn v.Len() == 0\n\tcase Struct:\n\t\tfor i := 0; i < v.NumField(); i++ {\n\t\t\tif !v.Field(i).IsZero() && v.Type().Field(i).Name != \"_\" {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\tdefault:\n\t\t// This should never happens, but will act as a safeguard for\n\t\t// later, as a default value doesn't makes sense here.\n\t\tpanic(&ValueError{Method: \"reflect.Value.IsZero\", Kind: v.Kind()})\n\t}\n}\n\n// Internal function only, do not use.\n//\n// RawType returns the raw, underlying type code. It is used in the runtime\n// package and needs to be exported for the runtime package to access it.\nfunc (v Value) RawType() *RawType {\n\treturn v.typecode\n}\n\nfunc (v Value) Kind() Kind {\n\treturn v.typecode.Kind()\n}\n\n// IsNil returns whether the value is the nil value. It panics if the value Kind\n// is not a channel, map, pointer, function, slice, or interface.\nfunc (v Value) IsNil() bool {\n\tswitch v.Kind() {\n\tcase Chan, Map, Ptr, UnsafePointer:\n\t\treturn v.pointer() == nil\n\tcase Func:\n\t\tif v.value == nil {\n\t\t\treturn true\n\t\t}\n\t\tfn := (*funcHeader)(v.value)\n\t\treturn fn.Code == nil\n\tcase Slice:\n\t\tif v.value == nil {\n\t\t\treturn true\n\t\t}\n\t\tslice := (*sliceHeader)(v.value)\n\t\treturn slice.data == nil\n\tcase Interface:\n\t\tval := *(*interface{})(v.value)\n\t\treturn val == nil\n\tdefault:\n\t\tpanic(&ValueError{Method: \"IsNil\", Kind: v.Kind()})\n\t}\n}\n\n// Pointer returns the underlying pointer of the given value for the following\n// types: chan, map, pointer, unsafe.Pointer, slice, func.\nfunc (v Value) Pointer() uintptr {\n\treturn uintptr(v.UnsafePointer())\n}\n\n// UnsafePointer returns the underlying pointer of the given value for the\n// following types: chan, map, pointer, unsafe.Pointer, slice, func.\nfunc (v Value) UnsafePointer() unsafe.Pointer {\n\tswitch v.Kind() {\n\tcase Chan, Map, Ptr, UnsafePointer:\n\t\treturn v.pointer()\n\tcase Slice:\n\t\tslice := (*sliceHeader)(v.value)\n\t\treturn slice.data\n\tcase Func:\n\t\tfn := (*funcHeader)(v.value)\n\t\tif fn.Context != nil {\n\t\t\treturn fn.Context\n\t\t}\n\t\treturn fn.Code\n\tdefault:\n\t\tpanic(&ValueError{Method: \"UnsafePointer\", Kind: v.Kind()})\n\t}\n}\n\n// pointer returns the underlying pointer represented by v.\n// v.Kind() must be Ptr, Map, Chan, or UnsafePointer\nfunc (v Value) pointer() unsafe.Pointer {\n\tif v.isIndirect() {\n\t\treturn *(*unsafe.Pointer)(v.value)\n\t}\n\treturn v.value\n}\n\nfunc (v Value) IsValid() bool {\n\treturn v.typecode != nil\n}\n\nfunc (v Value) CanInterface() bool {\n\treturn v.isExported() && !v.isRO()\n}\n\nfunc (v Value) CanAddr() bool {\n\treturn v.flags&(valueFlagIndirect) == valueFlagIndirect\n}\n\nfunc (v Value) Comparable() bool {\n\tk := v.Kind()\n\tswitch k {\n\tcase Invalid:\n\t\treturn false\n\n\tcase Array:\n\t\tswitch v.Type().Elem().Kind() {\n\t\tcase Interface, Array, Struct:\n\t\t\tfor i := 0; i < v.Type().Len(); i++ {\n\t\t\t\tif !v.Index(i).Comparable() {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true\n\t\t}\n\t\treturn v.Type().Comparable()\n\n\tcase Interface:\n\t\treturn v.Elem().Comparable()\n\n\tcase Struct:\n\t\tfor i := 0; i < v.NumField(); i++ {\n\t\t\tif !v.Field(i).Comparable() {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\n\tdefault:\n\t\treturn v.Type().Comparable()\n\t}\n}\n\n// Equal reports true if v is equal to u.\n// For two invalid values, Equal will report true.\n// For an interface value, Equal will compare the value within the interface.\n// Otherwise, If the values have different types, Equal will report false.\n// Otherwise, for arrays and structs Equal will compare each element in order,\n// and report false if it finds non-equal elements.\n// During all comparisons, if values of the same type are compared,\n// and the type is not comparable, Equal will panic.\n//\n// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\nfunc (v Value) Equal(u Value) bool {\n\tif v.Kind() == Interface {\n\t\tv = v.Elem()\n\t}\n\tif u.Kind() == Interface {\n\t\tu = u.Elem()\n\t}\n\n\tif !v.IsValid() || !u.IsValid() {\n\t\treturn v.IsValid() == u.IsValid()\n\t}\n\n\tif v.Kind() != u.Kind() || v.Type() != u.Type() {\n\t\treturn false\n\t}\n\n\t// Handle each Kind directly rather than calling valueInterface\n\t// to avoid allocating.\n\tswitch v.Kind() {\n\tdefault:\n\t\tpanic(\"reflect.Value.Equal: invalid Kind\")\n\tcase Bool:\n\t\treturn v.Bool() == u.Bool()\n\tcase Int, Int8, Int16, Int32, Int64:\n\t\treturn v.Int() == u.Int()\n\tcase Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:\n\t\treturn v.Uint() == u.Uint()\n\tcase Float32, Float64:\n\t\treturn v.Float() == u.Float()\n\tcase Complex64, Complex128:\n\t\treturn v.Complex() == u.Complex()\n\tcase String:\n\t\treturn v.String() == u.String()\n\tcase Chan, Pointer, UnsafePointer:\n\t\treturn v.Pointer() == u.Pointer()\n\tcase Array:\n\t\t// u and v have the same type so they have the same length\n\t\tvl := v.Len()\n\t\tif vl == 0 {\n\t\t\t// panic on [0]func()\n\t\t\tif !v.Type().Elem().Comparable() {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\treturn true\n\t\t}\n\t\tfor i := 0; i < vl; i++ {\n\t\t\tif !v.Index(i).Equal(u.Index(i)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\tcase Struct:\n\t\t// u and v have the same type so they have the same fields\n\t\tnf := v.NumField()\n\t\tfor i := 0; i < nf; i++ {\n\t\t\tif !v.Field(i).Equal(u.Field(i)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\tcase Func, Map, Slice:\n\t\tbreak\n\t}\n\tpanic(\"reflect.Value.Equal: values of type \" + v.Type().String() + \" are not comparable\")\n}\n\nfunc (v Value) Addr() Value {\n\tif !v.CanAddr() {\n\t\tpanic(\"reflect.Value.Addr of unaddressable value\")\n\t}\n\t// Preserve flagRO instead of using v.flag.ro() so that\n\t// v.Addr().Elem() is equivalent to v (#32772)\n\tflags := v.flags & (valueFlagExported | valueFlagRO)\n\treturn Value{\n\t\ttypecode: pointerTo(v.typecode),\n\t\tvalue:    v.value,\n\t\tflags:    flags,\n\t}\n}\n\nfunc (v Value) UnsafeAddr() uintptr {\n\treturn uintptr(v.Addr().UnsafePointer())\n}\n\nfunc (v Value) CanSet() bool {\n\treturn v.flags&(valueFlagExported|valueFlagIndirect|valueFlagRO) == valueFlagExported|valueFlagIndirect\n}\n\nfunc (v Value) Bool() bool {\n\tswitch v.Kind() {\n\tcase Bool:\n\t\tif v.isIndirect() {\n\t\t\treturn *((*bool)(v.value))\n\t\t} else {\n\t\t\treturn uintptr(v.value) != 0\n\t\t}\n\tdefault:\n\t\tpanic(&ValueError{Method: \"Bool\", Kind: v.Kind()})\n\t}\n}\n\n// CanInt reports whether Uint can be used without panicking.\nfunc (v Value) CanInt() bool {\n\tswitch v.Kind() {\n\tcase Int, Int8, Int16, Int32, Int64:\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\nfunc (v Value) Int() int64 {\n\tswitch v.Kind() {\n\tcase Int:\n\t\tif v.isIndirect() || unsafe.Sizeof(int(0)) > unsafe.Sizeof(uintptr(0)) {\n\t\t\treturn int64(*(*int)(v.value))\n\t\t} else {\n\t\t\treturn int64(int(uintptr(v.value)))\n\t\t}\n\tcase Int8:\n\t\tif v.isIndirect() {\n\t\t\treturn int64(*(*int8)(v.value))\n\t\t} else {\n\t\t\treturn int64(int8(uintptr(v.value)))\n\t\t}\n\tcase Int16:\n\t\tif v.isIndirect() {\n\t\t\treturn int64(*(*int16)(v.value))\n\t\t} else {\n\t\t\treturn int64(int16(uintptr(v.value)))\n\t\t}\n\tcase Int32:\n\t\tif v.isIndirect() || unsafe.Sizeof(int32(0)) > unsafe.Sizeof(uintptr(0)) {\n\t\t\treturn int64(*(*int32)(v.value))\n\t\t} else {\n\t\t\treturn int64(int32(uintptr(v.value)))\n\t\t}\n\tcase Int64:\n\t\tif v.isIndirect() || unsafe.Sizeof(int64(0)) > unsafe.Sizeof(uintptr(0)) {\n\t\t\treturn int64(*(*int64)(v.value))\n\t\t} else {\n\t\t\treturn int64(int64(uintptr(v.value)))\n\t\t}\n\tdefault:\n\t\tpanic(&ValueError{Method: \"Int\", Kind: v.Kind()})\n\t}\n}\n\n// CanUint reports whether Uint can be used without panicking.\nfunc (v Value) CanUint() bool {\n\tswitch v.Kind() {\n\tcase Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\nfunc (v Value) Uint() uint64 {\n\tswitch v.Kind() {\n\tcase Uintptr:\n\t\tif v.isIndirect() {\n\t\t\treturn uint64(*(*uintptr)(v.value))\n\t\t} else {\n\t\t\treturn uint64(uintptr(v.value))\n\t\t}\n\tcase Uint8:\n\t\tif v.isIndirect() {\n\t\t\treturn uint64(*(*uint8)(v.value))\n\t\t} else {\n\t\t\treturn uint64(uintptr(v.value))\n\t\t}\n\tcase Uint16:\n\t\tif v.isIndirect() {\n\t\t\treturn uint64(*(*uint16)(v.value))\n\t\t} else {\n\t\t\treturn uint64(uintptr(v.value))\n\t\t}\n\tcase Uint:\n\t\tif v.isIndirect() || unsafe.Sizeof(uint(0)) > unsafe.Sizeof(uintptr(0)) {\n\t\t\treturn uint64(*(*uint)(v.value))\n\t\t} else {\n\t\t\treturn uint64(uintptr(v.value))\n\t\t}\n\tcase Uint32:\n\t\tif v.isIndirect() || unsafe.Sizeof(uint32(0)) > unsafe.Sizeof(uintptr(0)) {\n\t\t\treturn uint64(*(*uint32)(v.value))\n\t\t} else {\n\t\t\treturn uint64(uintptr(v.value))\n\t\t}\n\tcase Uint64:\n\t\tif v.isIndirect() || unsafe.Sizeof(uint64(0)) > unsafe.Sizeof(uintptr(0)) {\n\t\t\treturn uint64(*(*uint64)(v.value))\n\t\t} else {\n\t\t\treturn uint64(uintptr(v.value))\n\t\t}\n\tdefault:\n\t\tpanic(&ValueError{Method: \"Uint\", Kind: v.Kind()})\n\t}\n}\n\n// CanFloat reports whether Float can be used without panicking.\nfunc (v Value) CanFloat() bool {\n\tswitch v.Kind() {\n\tcase Float32, Float64:\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\nfunc (v Value) Float32() float32 {\n\tswitch v.Kind() {\n\tcase Float32:\n\t\tif v.isIndirect() || unsafe.Sizeof(float32(0)) > unsafe.Sizeof(uintptr(0)) {\n\t\t\t// The float is stored as an external value on systems with 16-bit\n\t\t\t// pointers.\n\t\t\treturn *(*float32)(v.value)\n\t\t} else {\n\t\t\t// The float is directly stored in the interface value on systems\n\t\t\t// with 32-bit and 64-bit pointers.\n\t\t\treturn *(*float32)(unsafe.Pointer(&v.value))\n\t\t}\n\n\tcase Float64:\n\t\treturn float32(v.Float())\n\n\t}\n\n\tpanic(&ValueError{Method: \"Float\", Kind: v.Kind()})\n}\n\nfunc (v Value) Float() float64 {\n\tswitch v.Kind() {\n\tcase Float32:\n\t\tif v.isIndirect() || unsafe.Sizeof(float32(0)) > unsafe.Sizeof(uintptr(0)) {\n\t\t\t// The float is stored as an external value on systems with 16-bit\n\t\t\t// pointers.\n\t\t\treturn float64(*(*float32)(v.value))\n\t\t} else {\n\t\t\t// The float is directly stored in the interface value on systems\n\t\t\t// with 32-bit and 64-bit pointers.\n\t\t\treturn float64(*(*float32)(unsafe.Pointer(&v.value)))\n\t\t}\n\tcase Float64:\n\t\tif v.isIndirect() || unsafe.Sizeof(float64(0)) > unsafe.Sizeof(uintptr(0)) {\n\t\t\t// For systems with 16-bit and 32-bit pointers.\n\t\t\treturn *(*float64)(v.value)\n\t\t} else {\n\t\t\t// The float is directly stored in the interface value on systems\n\t\t\t// with 64-bit pointers.\n\t\t\treturn *(*float64)(unsafe.Pointer(&v.value))\n\t\t}\n\tdefault:\n\t\tpanic(&ValueError{Method: \"Float\", Kind: v.Kind()})\n\t}\n}\n\n// CanComplex reports whether Complex can be used without panicking.\nfunc (v Value) CanComplex() bool {\n\tswitch v.Kind() {\n\tcase Complex64, Complex128:\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\nfunc (v Value) Complex() complex128 {\n\tswitch v.Kind() {\n\tcase Complex64:\n\t\tif v.isIndirect() || unsafe.Sizeof(complex64(0)) > unsafe.Sizeof(uintptr(0)) {\n\t\t\t// The complex number is stored as an external value on systems with\n\t\t\t// 16-bit and 32-bit pointers.\n\t\t\treturn complex128(*(*complex64)(v.value))\n\t\t} else {\n\t\t\t// The complex number is directly stored in the interface value on\n\t\t\t// systems with 64-bit pointers.\n\t\t\treturn complex128(*(*complex64)(unsafe.Pointer(&v.value)))\n\t\t}\n\tcase Complex128:\n\t\t// This is a 128-bit value, which is always stored as an external value.\n\t\t// It may be stored in the pointer directly on very uncommon\n\t\t// architectures with 128-bit pointers, however.\n\t\treturn *(*complex128)(v.value)\n\tdefault:\n\t\tpanic(&ValueError{Method: \"Complex\", Kind: v.Kind()})\n\t}\n}\n\nfunc (v Value) String() string {\n\tswitch v.Kind() {\n\tcase String:\n\t\t// A string value is always bigger than a pointer as it is made of a\n\t\t// pointer and a length.\n\t\treturn *(*string)(v.value)\n\tdefault:\n\t\t// Special case because of the special treatment of .String() in Go.\n\t\treturn \"<\" + v.typecode.String() + \" Value>\"\n\t}\n}\n\nfunc (v Value) Bytes() []byte {\n\tswitch v.Kind() {\n\tcase Slice:\n\t\tif v.typecode.elem().Kind() != Uint8 {\n\t\t\tpanic(&ValueError{Method: \"Bytes\", Kind: v.Kind()})\n\t\t}\n\t\treturn *(*[]byte)(v.value)\n\n\tcase Array:\n\t\tv.checkAddressable()\n\n\t\tif v.typecode.elem().Kind() != Uint8 {\n\t\t\tpanic(&ValueError{Method: \"Bytes\", Kind: v.Kind()})\n\t\t}\n\n\t\t// Small inline arrays are not addressable, so we only have to\n\t\t// handle addressable arrays which will be stored as pointers\n\t\t// in v.value\n\t\treturn unsafe.Slice((*byte)(v.value), v.Len())\n\t}\n\n\tpanic(&ValueError{Method: \"Bytes\", Kind: v.Kind()})\n}\n\nfunc (v Value) Slice(i, j int) Value {\n\tswitch v.Kind() {\n\tcase Slice:\n\t\thdr := *(*sliceHeader)(v.value)\n\t\ti, j := uintptr(i), uintptr(j)\n\n\t\tif j < i || hdr.cap < j {\n\t\t\tslicePanic()\n\t\t}\n\n\t\telemSize := v.typecode.underlying().elem().Size()\n\n\t\thdr.len = j - i\n\t\thdr.cap = hdr.cap - i\n\t\thdr.data = unsafe.Add(hdr.data, i*elemSize)\n\n\t\treturn Value{\n\t\t\ttypecode: v.typecode,\n\t\t\tvalue:    unsafe.Pointer(&hdr),\n\t\t\tflags:    v.flags,\n\t\t}\n\n\tcase Array:\n\t\tv.checkAddressable()\n\t\tbuf, length := buflen(v)\n\t\ti, j := uintptr(i), uintptr(j)\n\t\tif j < i || length < j {\n\t\t\tslicePanic()\n\t\t}\n\n\t\telemSize := v.typecode.underlying().elem().Size()\n\n\t\tvar hdr sliceHeader\n\t\thdr.len = j - i\n\t\thdr.cap = length - i\n\t\thdr.data = unsafe.Add(buf, i*elemSize)\n\n\t\tsliceType := (*arrayType)(unsafe.Pointer(v.typecode.underlying())).slicePtr\n\t\treturn Value{\n\t\t\ttypecode: sliceType,\n\t\t\tvalue:    unsafe.Pointer(&hdr),\n\t\t\tflags:    v.flags,\n\t\t}\n\n\tcase String:\n\t\ti, j := uintptr(i), uintptr(j)\n\t\tstr := *(*stringHeader)(v.value)\n\n\t\tif j < i || str.len < j {\n\t\t\tslicePanic()\n\t\t}\n\n\t\thdr := stringHeader{\n\t\t\tdata: unsafe.Add(str.data, i),\n\t\t\tlen:  j - i,\n\t\t}\n\n\t\treturn Value{\n\t\t\ttypecode: v.typecode,\n\t\t\tvalue:    unsafe.Pointer(&hdr),\n\t\t\tflags:    v.flags,\n\t\t}\n\t}\n\n\tpanic(&ValueError{Method: \"Slice\", Kind: v.Kind()})\n}\n\nfunc (v Value) Slice3(i, j, k int) Value {\n\tswitch v.Kind() {\n\tcase Slice:\n\t\thdr := *(*sliceHeader)(v.value)\n\t\ti, j, k := uintptr(i), uintptr(j), uintptr(k)\n\n\t\tif j < i || k < j || hdr.len < k {\n\t\t\tslicePanic()\n\t\t}\n\n\t\telemSize := v.typecode.underlying().elem().Size()\n\n\t\thdr.len = j - i\n\t\thdr.cap = k - i\n\t\thdr.data = unsafe.Add(hdr.data, i*elemSize)\n\n\t\treturn Value{\n\t\t\ttypecode: v.typecode,\n\t\t\tvalue:    unsafe.Pointer(&hdr),\n\t\t\tflags:    v.flags,\n\t\t}\n\n\tcase Array:\n\t\tv.checkAddressable()\n\t\tbuf, length := buflen(v)\n\t\ti, j, k := uintptr(i), uintptr(j), uintptr(k)\n\t\tif j < i || k < j || length < k {\n\t\t\tslicePanic()\n\t\t}\n\n\t\telemSize := v.typecode.underlying().elem().Size()\n\n\t\tvar hdr sliceHeader\n\t\thdr.len = j - i\n\t\thdr.cap = k - i\n\t\thdr.data = unsafe.Add(buf, i*elemSize)\n\n\t\tsliceType := (*arrayType)(unsafe.Pointer(v.typecode.underlying())).slicePtr\n\t\treturn Value{\n\t\t\ttypecode: sliceType,\n\t\t\tvalue:    unsafe.Pointer(&hdr),\n\t\t\tflags:    v.flags,\n\t\t}\n\t}\n\n\tpanic(\"unimplemented: (reflect.Value).Slice3()\")\n}\n\n//go:linkname maplen runtime.hashmapLen\nfunc maplen(p unsafe.Pointer) int\n\n//go:linkname chanlen runtime.chanLen\nfunc chanlen(p unsafe.Pointer) int\n\n// Len returns the length of this value for slices, strings, arrays, channels,\n// and maps. For other types, it panics.\nfunc (v Value) Len() int {\n\tswitch v.typecode.Kind() {\n\tcase Array:\n\t\treturn v.typecode.Len()\n\tcase Chan:\n\t\treturn chanlen(v.pointer())\n\tcase Map:\n\t\treturn maplen(v.pointer())\n\tcase Slice:\n\t\treturn int((*sliceHeader)(v.value).len)\n\tcase String:\n\t\treturn int((*stringHeader)(v.value).len)\n\tdefault:\n\t\tpanic(&ValueError{Method: \"Len\", Kind: v.Kind()})\n\t}\n}\n\n//go:linkname chancap runtime.chanCap\nfunc chancap(p unsafe.Pointer) int\n\n// Cap returns the capacity of this value for arrays, channels and slices.\n// For other types, it panics.\nfunc (v Value) Cap() int {\n\tswitch v.typecode.Kind() {\n\tcase Array:\n\t\treturn v.typecode.Len()\n\tcase Chan:\n\t\treturn chancap(v.pointer())\n\tcase Slice:\n\t\treturn int((*sliceHeader)(v.value).cap)\n\tdefault:\n\t\tpanic(&ValueError{Method: \"Cap\", Kind: v.Kind()})\n\t}\n}\n\n//go:linkname mapclear runtime.hashmapClear\nfunc mapclear(p unsafe.Pointer)\n\n// Clear clears the contents of a map or zeros the contents of a slice\n//\n// It panics if v's Kind is not Map or Slice.\nfunc (v Value) Clear() {\n\tswitch v.typecode.Kind() {\n\tcase Map:\n\t\tmapclear(v.pointer())\n\tcase Slice:\n\t\thdr := (*sliceHeader)(v.value)\n\t\telemSize := v.typecode.underlying().elem().Size()\n\t\tmemzero(hdr.data, elemSize*hdr.len)\n\tdefault:\n\t\tpanic(&ValueError{Method: \"Clear\", Kind: v.Kind()})\n\t}\n}\n\n// NumField returns the number of fields of this struct. It panics for other\n// value types.\nfunc (v Value) NumField() int {\n\treturn v.typecode.NumField()\n}\n\nfunc (v Value) Elem() Value {\n\tswitch v.Kind() {\n\tcase Ptr:\n\t\tptr := v.pointer()\n\t\tif ptr == nil {\n\t\t\treturn Value{}\n\t\t}\n\t\t// Don't copy RO flags\n\t\tflags := (v.flags & (valueFlagIndirect | valueFlagExported)) | valueFlagIndirect\n\t\treturn Value{\n\t\t\ttypecode: v.typecode.elem(),\n\t\t\tvalue:    ptr,\n\t\t\tflags:    flags,\n\t\t}\n\tcase Interface:\n\t\ttypecode, value := decomposeInterface(*(*interface{})(v.value))\n\t\treturn Value{\n\t\t\ttypecode: (*RawType)(typecode),\n\t\t\tvalue:    value,\n\t\t\tflags:    v.flags &^ valueFlagIndirect,\n\t\t}\n\tdefault:\n\t\tpanic(&ValueError{Method: \"Elem\", Kind: v.Kind()})\n\t}\n}\n\n// Field returns the value of the i'th field of this struct.\nfunc (v Value) Field(i int) Value {\n\tif v.Kind() != Struct {\n\t\tpanic(&ValueError{Method: \"Field\", Kind: v.Kind()})\n\t}\n\tstructField := v.typecode.rawField(i)\n\n\t// Copy flags but clear EmbedRO; we're not an embedded field anymore\n\tflags := v.flags & ^valueFlagEmbedRO\n\tif structField.PkgPath != \"\" {\n\t\t// No PkgPath => not exported.\n\t\t// Clear exported flag even if the parent was exported.\n\t\tflags &^= valueFlagExported\n\n\t\t// Update the RO flag\n\t\tif structField.Anonymous {\n\t\t\t// Embedded field\n\t\t\tflags |= valueFlagEmbedRO\n\t\t} else {\n\t\t\tflags |= valueFlagStickyRO\n\t\t}\n\t} else {\n\t\t// Parent field may not have been exported but we are\n\t\tflags |= valueFlagExported\n\t}\n\n\tsize := v.typecode.Size()\n\tfieldType := structField.Type\n\tfieldSize := fieldType.Size()\n\tif v.isIndirect() || fieldSize > unsafe.Sizeof(uintptr(0)) {\n\t\t// v.value was already a pointer to the value and it should stay that\n\t\t// way.\n\t\treturn Value{\n\t\t\tflags:    flags,\n\t\t\ttypecode: fieldType,\n\t\t\tvalue:    unsafe.Add(v.value, structField.Offset),\n\t\t}\n\t}\n\n\t// The fieldSize is smaller than uintptr, which means that the value will\n\t// have to be stored directly in the interface value.\n\n\tif fieldSize == 0 {\n\t\t// The struct field is zero sized.\n\t\t// This is a rare situation, but because it's undefined behavior\n\t\t// to shift the size of the value (zeroing the value), handle this\n\t\t// situation explicitly.\n\t\treturn Value{\n\t\t\tflags:    flags,\n\t\t\ttypecode: fieldType,\n\t\t\tvalue:    unsafe.Pointer(nil),\n\t\t}\n\t}\n\n\tif size > unsafe.Sizeof(uintptr(0)) {\n\t\t// The value was not stored in the interface before but will be\n\t\t// afterwards, so load the value (from the correct offset) and return\n\t\t// it.\n\t\tptr := unsafe.Add(v.value, structField.Offset)\n\t\tvalue := unsafe.Pointer(loadValue(ptr, fieldSize))\n\t\treturn Value{\n\t\t\tflags:    flags &^ valueFlagIndirect,\n\t\t\ttypecode: fieldType,\n\t\t\tvalue:    value,\n\t\t}\n\t}\n\n\t// The value was already stored directly in the interface and it still\n\t// is. Cut out the part of the value that we need.\n\tvalue := maskAndShift(uintptr(v.value), structField.Offset, fieldSize)\n\treturn Value{\n\t\tflags:    flags,\n\t\ttypecode: fieldType,\n\t\tvalue:    unsafe.Pointer(value),\n\t}\n}\n\nvar uint8Type = TypeOf(uint8(0)).(*RawType)\n\nfunc (v Value) Index(i int) Value {\n\tswitch v.Kind() {\n\tcase Slice:\n\t\t// Extract an element from the slice.\n\t\tslice := *(*sliceHeader)(v.value)\n\t\tif uint(i) >= uint(slice.len) {\n\t\t\tpanic(\"reflect: slice index out of range\")\n\t\t}\n\t\tflags := (v.flags & (valueFlagExported | valueFlagIndirect)) | valueFlagIndirect | v.flags.ro()\n\t\telem := Value{\n\t\t\ttypecode: v.typecode.elem(),\n\t\t\tflags:    flags,\n\t\t}\n\t\telem.value = unsafe.Add(slice.data, elem.typecode.Size()*uintptr(i)) // pointer to new value\n\t\treturn elem\n\tcase String:\n\t\t// Extract a character from a string.\n\t\t// A string is never stored directly in the interface, but always as a\n\t\t// pointer to the string value.\n\t\t// Keeping valueFlagExported if set, but don't set valueFlagIndirect\n\t\t// otherwise CanSet will return true for string elements (which is bad,\n\t\t// strings are read-only).\n\t\ts := *(*stringHeader)(v.value)\n\t\tif uint(i) >= uint(s.len) {\n\t\t\tpanic(\"reflect: string index out of range\")\n\t\t}\n\t\treturn Value{\n\t\t\ttypecode: uint8Type,\n\t\t\tvalue:    unsafe.Pointer(uintptr(*(*uint8)(unsafe.Add(s.data, i)))),\n\t\t\tflags:    v.flags & valueFlagExported,\n\t\t}\n\tcase Array:\n\t\t// Extract an element from the array.\n\t\telemType := v.typecode.elem()\n\t\telemSize := elemType.Size()\n\t\tsize := v.typecode.Size()\n\t\tif size == 0 {\n\t\t\t// The element size is 0 and/or the length of the array is 0.\n\t\t\treturn Value{\n\t\t\t\ttypecode: v.typecode.elem(),\n\t\t\t\tflags:    v.flags,\n\t\t\t}\n\t\t}\n\t\tif elemSize > unsafe.Sizeof(uintptr(0)) {\n\t\t\t// The resulting value doesn't fit in a pointer so must be\n\t\t\t// indirect. Also, because size != 0 this implies that the array\n\t\t\t// length must be != 0, and thus that the total size is at least\n\t\t\t// elemSize.\n\t\t\taddr := unsafe.Add(v.value, elemSize*uintptr(i)) // pointer to new value\n\t\t\treturn Value{\n\t\t\t\ttypecode: v.typecode.elem(),\n\t\t\t\tflags:    v.flags,\n\t\t\t\tvalue:    addr,\n\t\t\t}\n\t\t}\n\n\t\tif size > unsafe.Sizeof(uintptr(0)) || v.isIndirect() {\n\t\t\t// The element fits in a pointer, but the array is not stored in the pointer directly.\n\t\t\t// Load the value from the pointer.\n\t\t\taddr := unsafe.Add(v.value, elemSize*uintptr(i)) // pointer to new value\n\t\t\tvalue := addr\n\t\t\tif !v.isIndirect() {\n\t\t\t\t// Use a pointer to the value (don't load the value) if the\n\t\t\t\t// 'indirect' flag is set.\n\t\t\t\tvalue = unsafe.Pointer(loadValue(addr, elemSize))\n\t\t\t}\n\t\t\treturn Value{\n\t\t\t\ttypecode: v.typecode.elem(),\n\t\t\t\tflags:    v.flags,\n\t\t\t\tvalue:    value,\n\t\t\t}\n\t\t}\n\n\t\t// The value fits in a pointer, so extract it with some shifting and\n\t\t// masking.\n\t\toffset := elemSize * uintptr(i)\n\t\tvalue := maskAndShift(uintptr(v.value), offset, elemSize)\n\t\treturn Value{\n\t\t\ttypecode: v.typecode.elem(),\n\t\t\tflags:    v.flags,\n\t\t\tvalue:    unsafe.Pointer(value),\n\t\t}\n\tdefault:\n\t\tpanic(&ValueError{Method: \"Index\", Kind: v.Kind()})\n\t}\n}\n\nfunc (v Value) NumMethod() int {\n\tif v.typecode == nil {\n\t\tpanic(&ValueError{Method: \"reflect.Value.NumMethod\", Kind: Invalid})\n\t}\n\treturn v.typecode.NumMethod()\n}\n\n// OverflowFloat reports whether the float64 x cannot be represented by v's type.\n// It panics if v's Kind is not Float32 or Float64.\nfunc (v Value) OverflowFloat(x float64) bool {\n\tk := v.Kind()\n\tswitch k {\n\tcase Float32:\n\t\treturn overflowFloat32(x)\n\tcase Float64:\n\t\treturn false\n\t}\n\tpanic(&ValueError{Method: \"reflect.Value.OverflowFloat\", Kind: v.Kind()})\n}\n\nfunc overflowFloat32(x float64) bool {\n\tif x < 0 {\n\t\tx = -x\n\t}\n\treturn math.MaxFloat32 < x && x <= math.MaxFloat64\n}\n\nfunc (v Value) MapKeys() []Value {\n\tif v.Kind() != Map {\n\t\tpanic(&ValueError{Method: \"MapKeys\", Kind: v.Kind()})\n\t}\n\n\t// empty map\n\tif v.Len() == 0 {\n\t\treturn nil\n\t}\n\n\tkeys := make([]Value, 0, v.Len())\n\n\tit := hashmapNewIterator()\n\tk := New(v.typecode.Key())\n\te := New(v.typecode.Elem())\n\n\tkeyType := v.typecode.key()\n\tkeyTypeIsEmptyInterface := keyType.Kind() == Interface && keyType.NumMethod() == 0\n\tshouldUnpackInterface := !keyTypeIsEmptyInterface && keyType.Kind() != String && !keyType.isBinary()\n\n\tfor hashmapNext(v.pointer(), it, k.value, e.value) {\n\t\tif shouldUnpackInterface {\n\t\t\tintf := *(*interface{})(k.value)\n\t\t\tv := ValueOf(intf)\n\t\t\tkeys = append(keys, v)\n\t\t} else {\n\t\t\tkeys = append(keys, k.Elem())\n\t\t}\n\t\tk = New(v.typecode.Key())\n\t}\n\n\treturn keys\n}\n\n//go:linkname hashmapStringGet runtime.hashmapStringGet\nfunc hashmapStringGet(m unsafe.Pointer, key string, value unsafe.Pointer, valueSize uintptr) bool\n\n//go:linkname hashmapBinaryGet runtime.hashmapBinaryGet\nfunc hashmapBinaryGet(m unsafe.Pointer, key, value unsafe.Pointer, valueSize uintptr) bool\n\n//go:linkname hashmapInterfaceGet runtime.hashmapInterfaceGet\nfunc hashmapInterfaceGet(m unsafe.Pointer, key interface{}, value unsafe.Pointer, valueSize uintptr) bool\n\nfunc (v Value) MapIndex(key Value) Value {\n\tif v.Kind() != Map {\n\t\tpanic(&ValueError{Method: \"MapIndex\", Kind: v.Kind()})\n\t}\n\n\tvkey := v.typecode.key()\n\n\t// compare key type with actual key type of map\n\tif !key.typecode.AssignableTo(vkey) {\n\t\t// type error?\n\t\tpanic(\"reflect.Value.MapIndex: incompatible types for key\")\n\t}\n\n\telemType := v.typecode.Elem()\n\telem := New(elemType)\n\n\tif vkey.Kind() == String {\n\t\tif ok := hashmapStringGet(v.pointer(), *(*string)(key.value), elem.value, elemType.Size()); !ok {\n\t\t\treturn Value{}\n\t\t}\n\t\treturn elem.Elem()\n\t} else if vkey.isBinary() {\n\t\tvar keyptr unsafe.Pointer\n\t\tif key.isIndirect() || key.typecode.Size() > unsafe.Sizeof(uintptr(0)) {\n\t\t\tkeyptr = key.value\n\t\t} else {\n\t\t\tkeyptr = unsafe.Pointer(&key.value)\n\t\t}\n\t\t//TODO(dgryski): zero out padding bytes in key, if any\n\t\tif ok := hashmapBinaryGet(v.pointer(), keyptr, elem.value, elemType.Size()); !ok {\n\t\t\treturn Value{}\n\t\t}\n\t\treturn elem.Elem()\n\t} else {\n\t\tif ok := hashmapInterfaceGet(v.pointer(), key.Interface(), elem.value, elemType.Size()); !ok {\n\t\t\treturn Value{}\n\t\t}\n\t\treturn elem.Elem()\n\t}\n}\n\n//go:linkname hashmapNewIterator runtime.hashmapNewIterator\nfunc hashmapNewIterator() unsafe.Pointer\n\n//go:linkname hashmapNext runtime.hashmapNext\nfunc hashmapNext(m unsafe.Pointer, it unsafe.Pointer, key, value unsafe.Pointer) bool\n\nfunc (v Value) MapRange() *MapIter {\n\titer := &MapIter{}\n\titer.Reset(v)\n\treturn iter\n}\n\ntype MapIter struct {\n\tm   Value\n\tit  unsafe.Pointer\n\tkey Value\n\tval Value\n\n\tvalid              bool\n\tunpackKeyInterface bool\n}\n\nfunc (it *MapIter) Key() Value {\n\tif !it.valid {\n\t\tpanic(\"reflect.MapIter.Key called on invalid iterator\")\n\t}\n\n\tif it.unpackKeyInterface {\n\t\tintf := *(*interface{})(it.key.value)\n\t\tv := ValueOf(intf)\n\t\treturn v\n\t}\n\n\treturn it.key.Elem()\n}\n\nfunc (v Value) SetIterKey(iter *MapIter) {\n\tv.Set(iter.Key())\n}\n\nfunc (it *MapIter) Value() Value {\n\tif !it.valid {\n\t\tpanic(\"reflect.MapIter.Value called on invalid iterator\")\n\t}\n\n\treturn it.val.Elem()\n}\n\nfunc (v Value) SetIterValue(iter *MapIter) {\n\tv.Set(iter.Value())\n}\n\nfunc (it *MapIter) Next() bool {\n\tit.key = New(it.m.typecode.Key())\n\tit.val = New(it.m.typecode.Elem())\n\n\tit.valid = hashmapNext(it.m.pointer(), it.it, it.key.value, it.val.value)\n\treturn it.valid\n}\n\nfunc (iter *MapIter) Reset(v Value) {\n\tif v.Kind() != Map {\n\t\tpanic(&ValueError{Method: \"MapRange\", Kind: v.Kind()})\n\t}\n\n\tkeyType := v.typecode.key()\n\n\tkeyTypeIsEmptyInterface := keyType.Kind() == Interface && keyType.NumMethod() == 0\n\tshouldUnpackInterface := !keyTypeIsEmptyInterface && keyType.Kind() != String && !keyType.isBinary()\n\n\t*iter = MapIter{\n\t\tm:                  v,\n\t\tit:                 hashmapNewIterator(),\n\t\tunpackKeyInterface: shouldUnpackInterface,\n\t}\n}\n\nfunc (v Value) Set(x Value) {\n\tv.checkAddressable()\n\tv.checkRO()\n\tif !x.typecode.AssignableTo(v.typecode) {\n\t\tpanic(\"reflect.Value.Set: value of type \" + x.typecode.String() + \" cannot be assigned to type \" + v.typecode.String())\n\t}\n\n\tif v.typecode.Kind() == Interface && x.typecode.Kind() != Interface {\n\t\t// move the value of x back into the interface, if possible\n\t\tif x.isIndirect() && x.typecode.Size() <= unsafe.Sizeof(uintptr(0)) {\n\t\t\tx.value = unsafe.Pointer(loadValue(x.value, x.typecode.Size()))\n\t\t}\n\n\t\tintf := composeInterface(unsafe.Pointer(x.typecode), x.value)\n\t\tx = Value{\n\t\t\ttypecode: v.typecode,\n\t\t\tvalue:    unsafe.Pointer(&intf),\n\t\t}\n\t}\n\n\tsize := v.typecode.Size()\n\tif size <= unsafe.Sizeof(uintptr(0)) && !x.isIndirect() {\n\t\tstoreValue(v.value, size, uintptr(x.value))\n\t} else {\n\t\tmemcpy(v.value, x.value, size)\n\t}\n}\n\nfunc (v Value) SetZero() {\n\tv.checkAddressable()\n\tv.checkRO()\n\tsize := v.typecode.Size()\n\tmemzero(v.value, size)\n}\n\nfunc (v Value) SetBool(x bool) {\n\tv.checkAddressable()\n\tv.checkRO()\n\tswitch v.Kind() {\n\tcase Bool:\n\t\t*(*bool)(v.value) = x\n\tdefault:\n\t\tpanic(&ValueError{Method: \"SetBool\", Kind: v.Kind()})\n\t}\n}\n\nfunc (v Value) SetInt(x int64) {\n\tv.checkAddressable()\n\tv.checkRO()\n\tswitch v.Kind() {\n\tcase Int:\n\t\t*(*int)(v.value) = int(x)\n\tcase Int8:\n\t\t*(*int8)(v.value) = int8(x)\n\tcase Int16:\n\t\t*(*int16)(v.value) = int16(x)\n\tcase Int32:\n\t\t*(*int32)(v.value) = int32(x)\n\tcase Int64:\n\t\t*(*int64)(v.value) = x\n\tdefault:\n\t\tpanic(&ValueError{Method: \"SetInt\", Kind: v.Kind()})\n\t}\n}\n\nfunc (v Value) SetUint(x uint64) {\n\tv.checkAddressable()\n\tv.checkRO()\n\tswitch v.Kind() {\n\tcase Uint:\n\t\t*(*uint)(v.value) = uint(x)\n\tcase Uint8:\n\t\t*(*uint8)(v.value) = uint8(x)\n\tcase Uint16:\n\t\t*(*uint16)(v.value) = uint16(x)\n\tcase Uint32:\n\t\t*(*uint32)(v.value) = uint32(x)\n\tcase Uint64:\n\t\t*(*uint64)(v.value) = x\n\tcase Uintptr:\n\t\t*(*uintptr)(v.value) = uintptr(x)\n\tdefault:\n\t\tpanic(&ValueError{Method: \"SetUint\", Kind: v.Kind()})\n\t}\n}\n\nfunc (v Value) SetFloat(x float64) {\n\tv.checkAddressable()\n\tv.checkRO()\n\tswitch v.Kind() {\n\tcase Float32:\n\t\t*(*float32)(v.value) = float32(x)\n\tcase Float64:\n\t\t*(*float64)(v.value) = x\n\tdefault:\n\t\tpanic(&ValueError{Method: \"SetFloat\", Kind: v.Kind()})\n\t}\n}\n\nfunc (v Value) SetComplex(x complex128) {\n\tv.checkAddressable()\n\tv.checkRO()\n\tswitch v.Kind() {\n\tcase Complex64:\n\t\t*(*complex64)(v.value) = complex64(x)\n\tcase Complex128:\n\t\t*(*complex128)(v.value) = x\n\tdefault:\n\t\tpanic(&ValueError{Method: \"SetComplex\", Kind: v.Kind()})\n\t}\n}\n\nfunc (v Value) SetString(x string) {\n\tv.checkAddressable()\n\tv.checkRO()\n\tswitch v.Kind() {\n\tcase String:\n\t\t*(*string)(v.value) = x\n\tdefault:\n\t\tpanic(&ValueError{Method: \"SetString\", Kind: v.Kind()})\n\t}\n}\n\nfunc (v Value) SetBytes(x []byte) {\n\tv.checkAddressable()\n\tv.checkRO()\n\tif v.typecode.Kind() != Slice || v.typecode.elem().Kind() != Uint8 {\n\t\tpanic(\"reflect.Value.SetBytes called on not []byte\")\n\t}\n\n\t// copy the header contents over\n\t*(*[]byte)(v.value) = x\n}\n\nfunc (v Value) SetCap(n int) {\n\tpanic(\"unimplemented: (reflect.Value).SetCap()\")\n}\n\nfunc (v Value) SetLen(n int) {\n\tif v.typecode.Kind() != Slice {\n\t\tpanic(&ValueError{Method: \"reflect.Value.SetLen\", Kind: v.Kind()})\n\t}\n\tv.checkAddressable()\n\thdr := (*sliceHeader)(v.value)\n\tif int(uintptr(n)) != n || uintptr(n) > hdr.cap {\n\t\tpanic(\"reflect.Value.SetLen: slice length out of range\")\n\t}\n\thdr.len = uintptr(n)\n}\n\nfunc (v Value) checkAddressable() {\n\tif !v.isIndirect() {\n\t\tpanic(\"reflect: value is not addressable\")\n\t}\n}\n\n// OverflowInt reports whether the int64 x cannot be represented by v's type.\n// It panics if v's Kind is not Int, Int8, Int16, Int32, or Int64.\nfunc (v Value) OverflowInt(x int64) bool {\n\tswitch v.Kind() {\n\tcase Int, Int8, Int16, Int32, Int64:\n\t\tbitSize := v.typecode.Size() * 8\n\t\ttrunc := (x << (64 - bitSize)) >> (64 - bitSize)\n\t\treturn x != trunc\n\t}\n\tpanic(&ValueError{Method: \"reflect.Value.OverflowInt\", Kind: v.Kind()})\n}\n\n// OverflowUint reports whether the uint64 x cannot be represented by v's type.\n// It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64.\nfunc (v Value) OverflowUint(x uint64) bool {\n\tk := v.Kind()\n\tswitch k {\n\tcase Uint, Uintptr, Uint8, Uint16, Uint32, Uint64:\n\t\tbitSize := v.typecode.Size() * 8\n\t\ttrunc := (x << (64 - bitSize)) >> (64 - bitSize)\n\t\treturn x != trunc\n\t}\n\tpanic(&ValueError{Method: \"reflect.Value.OverflowUint\", Kind: v.Kind()})\n}\n\nfunc (v Value) CanConvert(t Type) bool {\n\t// TODO: Optimize this to not actually perform a conversion\n\t_, ok := convertOp(v, t)\n\treturn ok\n}\n\nfunc (v Value) Convert(t Type) Value {\n\tif v, ok := convertOp(v, t); ok {\n\t\treturn v\n\t}\n\n\tpanic(\"reflect.Value.Convert: value of type \" + v.typecode.String() + \" cannot be converted to type \" + t.String())\n}\n\nfunc convertOp(src Value, typ Type) (Value, bool) {\n\n\t// Easy check first.  Do we even need to do anything?\n\tif src.typecode.underlying() == typ.(*RawType).underlying() {\n\t\treturn Value{\n\t\t\ttypecode: typ.(*RawType),\n\t\t\tvalue:    src.value,\n\t\t\tflags:    src.flags,\n\t\t}, true\n\t}\n\n\tif rtype := typ.(*RawType); rtype.Kind() == Interface && rtype.NumMethod() == 0 {\n\t\tiface := composeInterface(unsafe.Pointer(src.typecode), src.value)\n\t\treturn Value{\n\t\t\ttypecode: rtype,\n\t\t\tvalue:    unsafe.Pointer(&iface),\n\t\t\tflags:    valueFlagExported,\n\t\t}, true\n\t}\n\n\tswitch src.Kind() {\n\tcase Int, Int8, Int16, Int32, Int64:\n\t\tswitch rtype := typ.(*RawType); rtype.Kind() {\n\t\tcase Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:\n\t\t\treturn cvtInt(src, rtype), true\n\t\tcase Float32, Float64:\n\t\t\treturn cvtIntFloat(src, rtype), true\n\t\tcase String:\n\t\t\treturn cvtIntString(src, rtype), true\n\t\t}\n\n\tcase Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:\n\t\tswitch rtype := typ.(*RawType); rtype.Kind() {\n\t\tcase Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:\n\t\t\treturn cvtUint(src, rtype), true\n\t\tcase Float32, Float64:\n\t\t\treturn cvtUintFloat(src, rtype), true\n\t\tcase String:\n\t\t\treturn cvtUintString(src, rtype), true\n\t\t}\n\n\tcase Float32, Float64:\n\t\tswitch rtype := typ.(*RawType); rtype.Kind() {\n\t\tcase Int, Int8, Int16, Int32, Int64:\n\t\t\treturn cvtFloatInt(src, rtype), true\n\t\tcase Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:\n\t\t\treturn cvtFloatUint(src, rtype), true\n\t\tcase Float32, Float64:\n\t\t\treturn cvtFloat(src, rtype), true\n\t\t}\n\n\t\t/*\n\t\t\tcase Complex64, Complex128:\n\t\t\t\tswitch src.Kind() {\n\t\t\t\tcase Complex64, Complex128:\n\t\t\t\t\treturn cvtComplex\n\t\t\t\t}\n\t\t*/\n\n\tcase Slice:\n\t\tswitch rtype := typ.(*RawType); rtype.Kind() {\n\t\tcase Array:\n\t\t\tif src.typecode.elem() == rtype.elem() && rtype.Len() <= src.Len() {\n\t\t\t\treturn Value{\n\t\t\t\t\ttypecode: rtype,\n\t\t\t\t\tvalue:    (*sliceHeader)(src.value).data,\n\t\t\t\t\tflags:    src.flags | valueFlagIndirect,\n\t\t\t\t}, true\n\t\t\t}\n\t\tcase Pointer:\n\t\t\tif rtype.Elem().Kind() == Array {\n\t\t\t\tif src.typecode.elem() == rtype.elem().elem() && rtype.elem().Len() <= src.Len() {\n\t\t\t\t\treturn Value{\n\t\t\t\t\t\ttypecode: rtype,\n\t\t\t\t\t\tvalue:    (*sliceHeader)(src.value).data,\n\t\t\t\t\t\tflags:    src.flags & (valueFlagExported | valueFlagRO),\n\t\t\t\t\t}, true\n\t\t\t\t}\n\t\t\t}\n\t\tcase String:\n\t\t\tif !src.typecode.elem().isNamed() {\n\t\t\t\tswitch src.Type().Elem().Kind() {\n\t\t\t\tcase Uint8:\n\t\t\t\t\treturn cvtBytesString(src, rtype), true\n\t\t\t\tcase Int32:\n\t\t\t\t\treturn cvtRunesString(src, rtype), true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\tcase String:\n\t\trtype := typ.(*RawType)\n\t\tif typ.Kind() == Slice && !rtype.elem().isNamed() {\n\t\t\tswitch typ.Elem().Kind() {\n\t\t\tcase Uint8:\n\t\t\t\treturn cvtStringBytes(src, rtype), true\n\t\t\tcase Int32:\n\t\t\t\treturn cvtStringRunes(src, rtype), true\n\t\t\t}\n\t\t}\n\t}\n\n\t// TODO(dgryski): Unimplemented:\n\t// Chan\n\t// Non-defined pointers types with same underlying base type\n\t// Interface <-> Type conversions\n\n\treturn Value{}, false\n}\n\nfunc cvtInt(v Value, t *RawType) Value {\n\treturn makeInt(v.flags, uint64(v.Int()), t)\n}\n\nfunc cvtUint(v Value, t *RawType) Value {\n\treturn makeInt(v.flags, v.Uint(), t)\n}\n\nfunc cvtIntFloat(v Value, t *RawType) Value {\n\treturn makeFloat(v.flags, float64(v.Int()), t)\n}\n\nfunc cvtUintFloat(v Value, t *RawType) Value {\n\treturn makeFloat(v.flags, float64(v.Uint()), t)\n}\n\nfunc cvtFloatInt(v Value, t *RawType) Value {\n\treturn makeInt(v.flags, uint64(int64(v.Float())), t)\n}\n\nfunc cvtFloatUint(v Value, t *RawType) Value {\n\treturn makeInt(v.flags, uint64(v.Float()), t)\n}\n\nfunc cvtFloat(v Value, t *RawType) Value {\n\tif v.Type().Kind() == Float32 && t.Kind() == Float32 {\n\t\t// Don't do any conversion if both types have underlying type float32.\n\t\t// This avoids converting to float64 and back, which will\n\t\t// convert a signaling NaN to a quiet NaN. See issue 36400.\n\t\treturn makeFloat32(v.flags, v.Float32(), t)\n\t}\n\treturn makeFloat(v.flags, v.Float(), t)\n}\n\n//go:linkname stringToBytes runtime.stringToBytes\nfunc stringToBytes(x string) []byte\n\nfunc cvtStringBytes(v Value, t *RawType) Value {\n\tb := stringToBytes(*(*string)(v.value))\n\treturn Value{\n\t\ttypecode: t,\n\t\tvalue:    unsafe.Pointer(&b),\n\t\tflags:    v.flags,\n\t}\n}\n\n//go:linkname stringFromBytes runtime.stringFromBytes\nfunc stringFromBytes(x []byte) string\n\nfunc cvtBytesString(v Value, t *RawType) Value {\n\ts := stringFromBytes(*(*[]byte)(v.value))\n\treturn Value{\n\t\ttypecode: t,\n\t\tvalue:    unsafe.Pointer(&s),\n\t\tflags:    v.flags,\n\t}\n}\n\nfunc makeInt(flags valueFlags, bits uint64, t *RawType) Value {\n\tsize := t.Size()\n\n\tv := Value{\n\t\ttypecode: t,\n\t\tflags:    flags,\n\t}\n\n\tptr := unsafe.Pointer(&v.value)\n\tif size > unsafe.Sizeof(uintptr(0)) {\n\t\tptr = alloc(size, nil)\n\t\tv.value = ptr\n\t}\n\n\tswitch size {\n\tcase 1:\n\t\t*(*uint8)(ptr) = uint8(bits)\n\tcase 2:\n\t\t*(*uint16)(ptr) = uint16(bits)\n\tcase 4:\n\t\t*(*uint32)(ptr) = uint32(bits)\n\tcase 8:\n\t\t*(*uint64)(ptr) = bits\n\t}\n\treturn v\n}\n\nfunc makeFloat(flags valueFlags, f float64, t *RawType) Value {\n\tsize := t.Size()\n\n\tv := Value{\n\t\ttypecode: t,\n\t\tflags:    flags,\n\t}\n\n\tptr := unsafe.Pointer(&v.value)\n\tif size > unsafe.Sizeof(uintptr(0)) {\n\t\tptr = alloc(size, nil)\n\t\tv.value = ptr\n\t}\n\n\tswitch size {\n\tcase 4:\n\t\t*(*float32)(ptr) = float32(f)\n\tcase 8:\n\t\t*(*float64)(ptr) = f\n\t}\n\treturn v\n}\n\nfunc makeFloat32(flags valueFlags, f float32, t *RawType) Value {\n\tv := Value{\n\t\ttypecode: t,\n\t\tflags:    flags,\n\t}\n\t*(*float32)(unsafe.Pointer(&v.value)) = float32(f)\n\treturn v\n}\n\nfunc cvtIntString(src Value, t *RawType) Value {\n\tpanic(\"cvtUintString: unimplemented\")\n}\n\nfunc cvtUintString(src Value, t *RawType) Value {\n\tpanic(\"cvtUintString: unimplemented\")\n}\n\nfunc cvtStringRunes(src Value, t *RawType) Value {\n\tpanic(\"cvsStringRunes: unimplemented\")\n}\n\nfunc cvtRunesString(src Value, t *RawType) Value {\n\tpanic(\"cvsRunesString: unimplemented\")\n}\n\n//go:linkname slicePanic runtime.slicePanic\nfunc slicePanic()\n\nfunc MakeSlice(typ Type, len, cap int) Value {\n\tif typ.Kind() != Slice {\n\t\tpanic(\"reflect.MakeSlice of non-slice type\")\n\t}\n\n\trtype := typ.(*RawType)\n\n\tulen := uint(len)\n\tucap := uint(cap)\n\tmaxSize := (^uintptr(0)) / 2\n\telem := rtype.elem()\n\telementSize := elem.Size()\n\tif elementSize > 1 {\n\t\tmaxSize /= uintptr(elementSize)\n\t}\n\tif ulen > ucap || ucap > uint(maxSize) {\n\t\tslicePanic()\n\t}\n\n\t// This can't overflow because of the above checks.\n\tsize := uintptr(ucap) * elementSize\n\n\tvar slice sliceHeader\n\tslice.cap = uintptr(ucap)\n\tslice.len = uintptr(ulen)\n\tlayout := elem.gcLayout()\n\n\tslice.data = alloc(size, layout)\n\n\treturn Value{\n\t\ttypecode: rtype,\n\t\tvalue:    unsafe.Pointer(&slice),\n\t\tflags:    valueFlagExported,\n\t}\n}\n\nvar zerobuffer unsafe.Pointer\n\nconst zerobufferLen = 32\n\nfunc init() {\n\t// 32 characters of zero bytes\n\tzerobufferStr := \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n\ts := (*stringHeader)(unsafe.Pointer(&zerobufferStr))\n\tzerobuffer = s.data\n}\n\nfunc Zero(typ Type) Value {\n\tsize := typ.Size()\n\tif size <= unsafe.Sizeof(uintptr(0)) {\n\t\treturn Value{\n\t\t\ttypecode: typ.(*RawType),\n\t\t\tvalue:    nil,\n\t\t\tflags:    valueFlagExported | valueFlagRO,\n\t\t}\n\t}\n\n\tif size <= zerobufferLen {\n\t\treturn Value{\n\t\t\ttypecode: typ.(*RawType),\n\t\t\tvalue:    unsafe.Pointer(zerobuffer),\n\t\t\tflags:    valueFlagExported | valueFlagRO,\n\t\t}\n\t}\n\n\treturn Value{\n\t\ttypecode: typ.(*RawType),\n\t\tvalue:    alloc(size, nil),\n\t\tflags:    valueFlagExported | valueFlagRO,\n\t}\n}\n\n// New is the reflect equivalent of the new(T) keyword, returning a pointer to a\n// new value of the given type.\nfunc New(typ Type) Value {\n\treturn Value{\n\t\ttypecode: pointerTo(typ.(*RawType)),\n\t\tvalue:    alloc(typ.Size(), nil),\n\t\tflags:    valueFlagExported,\n\t}\n}\n\ntype funcHeader struct {\n\tContext unsafe.Pointer\n\tCode    unsafe.Pointer\n}\n\n// Slice header that matches the underlying structure. Used for when we switch\n// to a precise GC, which needs to know exactly where pointers live.\ntype sliceHeader struct {\n\tdata unsafe.Pointer\n\tlen  uintptr\n\tcap  uintptr\n}\n\n// Like sliceHeader, this type is used internally to make sure pointer and\n// non-pointer fields match those of actual strings.\ntype stringHeader struct {\n\tdata unsafe.Pointer\n\tlen  uintptr\n}\n\n// Verify SliceHeader and StringHeader sizes.\n// See https://github.com/tinygo-org/tinygo/pull/4156\n// and https://github.com/tinygo-org/tinygo/issues/1284.\nvar (\n\t_ [unsafe.Sizeof([]byte{})]byte = [unsafe.Sizeof(sliceHeader{})]byte{}\n\t_ [unsafe.Sizeof(\"\")]byte       = [unsafe.Sizeof(stringHeader{})]byte{}\n)\n\ntype ValueError struct {\n\tMethod string\n\tKind   Kind\n}\n\nfunc (e *ValueError) Error() string {\n\tif e.Kind == 0 {\n\t\treturn \"reflect: call of \" + e.Method + \" on zero Value\"\n\t}\n\treturn \"reflect: call of \" + e.Method + \" on \" + e.Kind.String() + \" Value\"\n}\n\n//go:linkname memcpy runtime.memcpy\nfunc memcpy(dst, src unsafe.Pointer, size uintptr)\n\n//go:linkname memzero runtime.memzero\nfunc memzero(ptr unsafe.Pointer, size uintptr)\n\n//go:linkname alloc runtime.alloc\nfunc alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer\n\n//go:linkname sliceAppend runtime.sliceAppend\nfunc sliceAppend(srcBuf, elemsBuf unsafe.Pointer, srcLen, srcCap, elemsLen uintptr, elemSize uintptr) (unsafe.Pointer, uintptr, uintptr)\n\n//go:linkname sliceCopy runtime.sliceCopy\nfunc sliceCopy(dst, src unsafe.Pointer, dstLen, srcLen uintptr, elemSize uintptr) int\n\n// Copy copies the contents of src into dst until either\n// dst has been filled or src has been exhausted.\nfunc Copy(dst, src Value) int {\n\tcompatibleTypes := false ||\n\t\t// dst and src are both slices or arrays with equal types\n\t\t((dst.typecode.Kind() == Slice || dst.typecode.Kind() == Array) &&\n\t\t\t(src.typecode.Kind() == Slice || src.typecode.Kind() == Array) &&\n\t\t\t(dst.typecode.elem() == src.typecode.elem())) ||\n\t\t// dst is array or slice of uint8 and src is string\n\t\t((dst.typecode.Kind() == Slice || dst.typecode.Kind() == Array) &&\n\t\t\tdst.typecode.elem().Kind() == Uint8 &&\n\t\t\tsrc.typecode.Kind() == String)\n\n\tif !compatibleTypes {\n\t\tpanic(\"Copy: type mismatch: \" + dst.typecode.String() + \"/\" + src.typecode.String())\n\t}\n\n\t// Can read from an unaddressable array but not write to one.\n\tif dst.typecode.Kind() == Array && !dst.isIndirect() {\n\t\tpanic(\"reflect.Copy: unaddressable array value\")\n\t}\n\n\tdstbuf, dstlen := buflen(dst)\n\tsrcbuf, srclen := buflen(src)\n\n\tif srclen > 0 {\n\t\tdst.checkRO()\n\t}\n\n\treturn sliceCopy(dstbuf, srcbuf, dstlen, srclen, dst.typecode.elem().Size())\n}\n\nfunc buflen(v Value) (unsafe.Pointer, uintptr) {\n\tvar buf unsafe.Pointer\n\tvar len uintptr\n\tswitch v.typecode.Kind() {\n\tcase Slice:\n\t\thdr := (*sliceHeader)(v.value)\n\t\tbuf = hdr.data\n\t\tlen = hdr.len\n\tcase Array:\n\t\tif v.isIndirect() || v.typecode.Size() > unsafe.Sizeof(uintptr(0)) {\n\t\t\tbuf = v.value\n\t\t} else {\n\t\t\tbuf = unsafe.Pointer(&v.value)\n\t\t}\n\t\tlen = uintptr(v.Len())\n\tcase String:\n\t\thdr := (*stringHeader)(v.value)\n\t\tbuf = hdr.data\n\t\tlen = hdr.len\n\tdefault:\n\t\t// This shouldn't happen\n\t\tpanic(\"reflect.Copy: not slice or array or string\")\n\t}\n\n\treturn buf, len\n}\n\n//go:linkname sliceGrow runtime.sliceGrow\nfunc sliceGrow(buf unsafe.Pointer, oldLen, oldCap, newCap, elemSize uintptr) (unsafe.Pointer, uintptr, uintptr)\n\n// extend slice to hold n new elements\nfunc extendSlice(v Value, n int) sliceHeader {\n\tif v.Kind() != Slice {\n\t\tpanic(&ValueError{Method: \"extendSlice\", Kind: v.Kind()})\n\t}\n\n\tvar old sliceHeader\n\tif v.value != nil {\n\t\told = *(*sliceHeader)(v.value)\n\t}\n\n\tnbuf, nlen, ncap := sliceGrow(old.data, old.len, old.cap, old.len+uintptr(n), v.typecode.elem().Size())\n\n\treturn sliceHeader{\n\t\tdata: nbuf,\n\t\tlen:  nlen + uintptr(n),\n\t\tcap:  ncap,\n\t}\n}\n\n// Append appends the values x to a slice s and returns the resulting slice.\n// As in Go, each x's value must be assignable to the slice's element type.\nfunc Append(v Value, x ...Value) Value {\n\tif v.Kind() != Slice {\n\t\tpanic(&ValueError{Method: \"Append\", Kind: v.Kind()})\n\t}\n\toldLen := v.Len()\n\tnewslice := extendSlice(v, len(x))\n\tv.flags = valueFlagExported\n\tv.value = (unsafe.Pointer)(&newslice)\n\tfor i, xx := range x {\n\t\tv.Index(oldLen + i).Set(xx)\n\t}\n\treturn v\n}\n\n// AppendSlice appends a slice t to a slice s and returns the resulting slice.\n// The slices s and t must have the same element type.\nfunc AppendSlice(s, t Value) Value {\n\tif s.typecode.Kind() != Slice || t.typecode.Kind() != Slice || s.typecode != t.typecode {\n\t\t// Not a very helpful error message, but shortened to just one error to\n\t\t// keep code size down.\n\t\tpanic(\"reflect.AppendSlice: invalid types\")\n\t}\n\tif !s.isExported() || !t.isExported() {\n\t\t// One of the sides was not exported, so can't access the data.\n\t\tpanic(\"reflect.AppendSlice: unexported\")\n\t}\n\tsSlice := (*sliceHeader)(s.value)\n\ttSlice := (*sliceHeader)(t.value)\n\telemSize := s.typecode.elem().Size()\n\tptr, len, cap := sliceAppend(sSlice.data, tSlice.data, sSlice.len, sSlice.cap, tSlice.len, elemSize)\n\tresult := &sliceHeader{\n\t\tdata: ptr,\n\t\tlen:  len,\n\t\tcap:  cap,\n\t}\n\treturn Value{\n\t\ttypecode: s.typecode,\n\t\tvalue:    unsafe.Pointer(result),\n\t\tflags:    valueFlagExported,\n\t}\n}\n\n// Grow increases the slice's capacity, if necessary, to guarantee space for\n// another n elements. After Grow(n), at least n elements can be appended\n// to the slice without another allocation.\n//\n// It panics if v's Kind is not a Slice or if n is negative or too large to\n// allocate the memory.\nfunc (v Value) Grow(n int) {\n\tv.checkAddressable()\n\tif n < 0 {\n\t\tpanic(\"reflect.Grow: negative length\")\n\t}\n\tif v.Kind() != Slice {\n\t\tpanic(&ValueError{Method: \"Grow\", Kind: v.Kind()})\n\t}\n\tslice := (*sliceHeader)(v.value)\n\tnewslice := extendSlice(v, n)\n\t// Only copy the new data and cap: the len remains unchanged.\n\tslice.data = newslice.data\n\tslice.cap = newslice.cap\n}\n\n//go:linkname hashmapStringSet runtime.hashmapStringSet\nfunc hashmapStringSet(m unsafe.Pointer, key string, value unsafe.Pointer)\n\n//go:linkname hashmapBinarySet runtime.hashmapBinarySet\nfunc hashmapBinarySet(m unsafe.Pointer, key, value unsafe.Pointer)\n\n//go:linkname hashmapInterfaceSet runtime.hashmapInterfaceSet\nfunc hashmapInterfaceSet(m unsafe.Pointer, key interface{}, value unsafe.Pointer)\n\n//go:linkname hashmapStringDelete runtime.hashmapStringDelete\nfunc hashmapStringDelete(m unsafe.Pointer, key string)\n\n//go:linkname hashmapBinaryDelete runtime.hashmapBinaryDelete\nfunc hashmapBinaryDelete(m unsafe.Pointer, key unsafe.Pointer)\n\n//go:linkname hashmapInterfaceDelete runtime.hashmapInterfaceDelete\nfunc hashmapInterfaceDelete(m unsafe.Pointer, key interface{})\n\nfunc (v Value) SetMapIndex(key, elem Value) {\n\tv.checkRO()\n\tif v.Kind() != Map {\n\t\tpanic(&ValueError{Method: \"SetMapIndex\", Kind: v.Kind()})\n\t}\n\n\tvkey := v.typecode.key()\n\n\t// compare key type with actual key type of map\n\tif !key.typecode.AssignableTo(vkey) {\n\t\tpanic(\"reflect.Value.SetMapIndex: incompatible types for key\")\n\t}\n\n\t// if elem is the zero Value, it means delete\n\tdel := elem == Value{}\n\n\tif !del && !elem.typecode.AssignableTo(v.typecode.elem()) {\n\t\tpanic(\"reflect.Value.SetMapIndex: incompatible types for value\")\n\t}\n\n\t// make elem an interface if it needs to be converted\n\tif v.typecode.elem().Kind() == Interface && elem.typecode.Kind() != Interface {\n\t\tintf := composeInterface(unsafe.Pointer(elem.typecode), elem.value)\n\t\telem = Value{\n\t\t\ttypecode: v.typecode.elem(),\n\t\t\tvalue:    unsafe.Pointer(&intf),\n\t\t}\n\t}\n\n\tif key.Kind() == String {\n\t\tif del {\n\t\t\thashmapStringDelete(v.pointer(), *(*string)(key.value))\n\t\t} else {\n\t\t\tvar elemptr unsafe.Pointer\n\t\t\tif elem.isIndirect() || elem.typecode.Size() > unsafe.Sizeof(uintptr(0)) {\n\t\t\t\telemptr = elem.value\n\t\t\t} else {\n\t\t\t\telemptr = unsafe.Pointer(&elem.value)\n\t\t\t}\n\t\t\thashmapStringSet(v.pointer(), *(*string)(key.value), elemptr)\n\t\t}\n\n\t} else if key.typecode.isBinary() {\n\t\tvar keyptr unsafe.Pointer\n\t\tif key.isIndirect() || key.typecode.Size() > unsafe.Sizeof(uintptr(0)) {\n\t\t\tkeyptr = key.value\n\t\t} else {\n\t\t\tkeyptr = unsafe.Pointer(&key.value)\n\t\t}\n\n\t\tif del {\n\t\t\thashmapBinaryDelete(v.pointer(), keyptr)\n\t\t} else {\n\t\t\tvar elemptr unsafe.Pointer\n\t\t\tif elem.isIndirect() || elem.typecode.Size() > unsafe.Sizeof(uintptr(0)) {\n\t\t\t\telemptr = elem.value\n\t\t\t} else {\n\t\t\t\telemptr = unsafe.Pointer(&elem.value)\n\t\t\t}\n\t\t\thashmapBinarySet(v.pointer(), keyptr, elemptr)\n\t\t}\n\t} else {\n\t\tif del {\n\t\t\thashmapInterfaceDelete(v.pointer(), key.Interface())\n\t\t} else {\n\t\t\tvar elemptr unsafe.Pointer\n\t\t\tif elem.isIndirect() || elem.typecode.Size() > unsafe.Sizeof(uintptr(0)) {\n\t\t\t\telemptr = elem.value\n\t\t\t} else {\n\t\t\t\telemptr = unsafe.Pointer(&elem.value)\n\t\t\t}\n\n\t\t\thashmapInterfaceSet(v.pointer(), key.Interface(), elemptr)\n\t\t}\n\t}\n}\n\n// FieldByIndex returns the nested field corresponding to index.\nfunc (v Value) FieldByIndex(index []int) Value {\n\tif len(index) == 1 {\n\t\treturn v.Field(index[0])\n\t}\n\tif v.Kind() != Struct {\n\t\tpanic(&ValueError{\"FieldByIndex\", v.Kind()})\n\t}\n\tfor i, x := range index {\n\t\tif i > 0 {\n\t\t\tif v.Kind() == Pointer && v.typecode.elem().Kind() == Struct {\n\t\t\t\tif v.IsNil() {\n\t\t\t\t\tpanic(\"reflect: indirection through nil pointer to embedded struct\")\n\t\t\t\t}\n\t\t\t\tv = v.Elem()\n\t\t\t}\n\t\t}\n\t\tv = v.Field(x)\n\t}\n\treturn v\n}\n\n// FieldByIndexErr returns the nested field corresponding to index.\nfunc (v Value) FieldByIndexErr(index []int) (Value, error) {\n\treturn Value{}, &ValueError{Method: \"FieldByIndexErr\"}\n}\n\nfunc (v Value) FieldByName(name string) Value {\n\tif v.Kind() != Struct {\n\t\tpanic(&ValueError{\"FieldByName\", v.Kind()})\n\t}\n\n\tif field, ok := v.typecode.FieldByName(name); ok {\n\t\treturn v.FieldByIndex(field.Index)\n\t}\n\treturn Value{}\n}\n\nfunc (v Value) FieldByNameFunc(match func(string) bool) Value {\n\tif v.Kind() != Struct {\n\t\tpanic(&ValueError{\"FieldByName\", v.Kind()})\n\t}\n\n\tif field, ok := v.typecode.FieldByNameFunc(match); ok {\n\t\treturn v.FieldByIndex(field.Index)\n\t}\n\treturn Value{}\n}\n\n//go:linkname hashmapMake runtime.hashmapMake\nfunc hashmapMake(keySize, valueSize uintptr, sizeHint uintptr, alg uint8) unsafe.Pointer\n\n// MakeMapWithSize creates a new map with the specified type and initial space\n// for approximately n elements.\nfunc MakeMapWithSize(typ Type, n int) Value {\n\n\t// TODO(dgryski): deduplicate these?  runtime and reflect both need them.\n\tconst (\n\t\thashmapAlgorithmBinary uint8 = iota\n\t\thashmapAlgorithmString\n\t\thashmapAlgorithmInterface\n\t)\n\n\tif typ.Kind() != Map {\n\t\tpanic(&ValueError{Method: \"MakeMap\", Kind: typ.Kind()})\n\t}\n\n\tif n < 0 {\n\t\tpanic(\"reflect.MakeMapWithSize: negative size hint\")\n\t}\n\n\tkey := typ.Key().(*RawType)\n\tval := typ.Elem().(*RawType)\n\n\tvar alg uint8\n\n\tif key.Kind() == String {\n\t\talg = hashmapAlgorithmString\n\t} else if key.isBinary() {\n\t\talg = hashmapAlgorithmBinary\n\t} else {\n\t\talg = hashmapAlgorithmInterface\n\t}\n\n\tm := hashmapMake(key.Size(), val.Size(), uintptr(n), alg)\n\n\treturn Value{\n\t\ttypecode: typ.(*RawType),\n\t\tvalue:    m,\n\t\tflags:    valueFlagExported,\n\t}\n}\n\n// MakeMap creates a new map with the specified type.\nfunc MakeMap(typ Type) Value {\n\treturn MakeMapWithSize(typ, 8)\n}\n\nfunc (v Value) Call(in []Value) []Value {\n\tpanic(\"unimplemented: (reflect.Value).Call()\")\n}\n\nfunc (v Value) CallSlice(in []Value) []Value {\n\tpanic(\"unimplemented: (reflect.Value).CallSlice()\")\n}\n\nfunc (v Value) Method(i int) Value {\n\tpanic(\"unimplemented: (reflect.Value).Method()\")\n}\n\nfunc (v Value) MethodByName(name string) Value {\n\tpanic(\"unimplemented: (reflect.Value).MethodByName()\")\n}\n\nfunc (v Value) Recv() (x Value, ok bool) {\n\tpanic(\"unimplemented: (reflect.Value).Recv()\")\n}\n\nfunc NewAt(typ Type, p unsafe.Pointer) Value {\n\tpanic(\"unimplemented: reflect.New()\")\n}\n"
  },
  {
    "path": "src/internal/reflectlite/visiblefields.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage reflectlite\n\n// VisibleFields returns all the visible fields in t, which must be a\n// struct type. A field is defined as visible if it's accessible\n// directly with a FieldByName call. The returned fields include fields\n// inside anonymous struct members and unexported fields. They follow\n// the same order found in the struct, with anonymous fields followed\n// immediately by their promoted fields.\n//\n// For each element e of the returned slice, the corresponding field\n// can be retrieved from a value v of type t by calling v.FieldByIndex(e.Index).\nfunc VisibleFields(t Type) []StructField {\n\tif t == nil {\n\t\tpanic(\"reflect: VisibleFields(nil)\")\n\t}\n\tif t.Kind() != Struct {\n\t\tpanic(\"reflect.VisibleFields of non-struct type\")\n\t}\n\tw := &visibleFieldsWalker{\n\t\tbyName:   make(map[string]int),\n\t\tvisiting: make(map[Type]bool),\n\t\tfields:   make([]StructField, 0, t.NumField()),\n\t\tindex:    make([]int, 0, 2),\n\t}\n\tw.walk(t)\n\t// Remove all the fields that have been hidden.\n\t// Use an in-place removal that avoids copying in\n\t// the common case that there are no hidden fields.\n\tj := 0\n\tfor i := range w.fields {\n\t\tf := &w.fields[i]\n\t\tif f.Name == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tif i != j {\n\t\t\t// A field has been removed. We need to shuffle\n\t\t\t// all the subsequent elements up.\n\t\t\tw.fields[j] = *f\n\t\t}\n\t\tj++\n\t}\n\treturn w.fields[:j]\n}\n\ntype visibleFieldsWalker struct {\n\tbyName   map[string]int\n\tvisiting map[Type]bool\n\tfields   []StructField\n\tindex    []int\n}\n\n// walk walks all the fields in the struct type t, visiting\n// fields in index preorder and appending them to w.fields\n// (this maintains the required ordering).\n// Fields that have been overridden have their\n// Name field cleared.\nfunc (w *visibleFieldsWalker) walk(t Type) {\n\tif w.visiting[t] {\n\t\treturn\n\t}\n\tw.visiting[t] = true\n\tfor i := 0; i < t.NumField(); i++ {\n\t\tf := t.Field(i)\n\t\tw.index = append(w.index, i)\n\t\tadd := true\n\t\tif oldIndex, ok := w.byName[f.Name]; ok {\n\t\t\told := &w.fields[oldIndex]\n\t\t\tif len(w.index) == len(old.Index) {\n\t\t\t\t// Fields with the same name at the same depth\n\t\t\t\t// cancel one another out. Set the field name\n\t\t\t\t// to empty to signify that has happened, and\n\t\t\t\t// there's no need to add this field.\n\t\t\t\told.Name = \"\"\n\t\t\t\tadd = false\n\t\t\t} else if len(w.index) < len(old.Index) {\n\t\t\t\t// The old field loses because it's deeper than the new one.\n\t\t\t\told.Name = \"\"\n\t\t\t} else {\n\t\t\t\t// The old field wins because it's shallower than the new one.\n\t\t\t\tadd = false\n\t\t\t}\n\t\t}\n\t\tif add {\n\t\t\t// Copy the index so that it's not overwritten\n\t\t\t// by the other appends.\n\t\t\tf.Index = append([]int(nil), w.index...)\n\t\t\tw.byName[f.Name] = len(w.fields)\n\t\t\tw.fields = append(w.fields, f)\n\t\t}\n\t\tif f.Anonymous {\n\t\t\tif f.Type.Kind() == Pointer {\n\t\t\t\tf.Type = f.Type.Elem()\n\t\t\t}\n\t\t\tif f.Type.Kind() == Struct {\n\t\t\t\tw.walk(f.Type)\n\t\t\t}\n\t\t}\n\t\tw.index = w.index[:len(w.index)-1]\n\t}\n\tdelete(w.visiting, t)\n}\n"
  },
  {
    "path": "src/internal/syscall/unix/constants.go",
    "content": "package unix\n\nconst (\n\tR_OK = 0x4\n\tW_OK = 0x2\n\tX_OK = 0x1\n)\n"
  },
  {
    "path": "src/internal/syscall/unix/eaccess.go",
    "content": "package unix\n\nimport \"syscall\"\n\nfunc Eaccess(path string, mode uint32) error {\n\t// We don't support this syscall on baremetal or wasm.\n\t// Callers are generally able to deal with this since unix.Eaccess also\n\t// isn't available on Android.\n\treturn syscall.ENOSYS\n}\n"
  },
  {
    "path": "src/internal/syscall/unix/getrandom.go",
    "content": "package unix\n\ntype GetRandomFlag uintptr\n\nconst (\n\tGRND_NONBLOCK GetRandomFlag = 0x0001\n\tGRND_RANDOM   GetRandomFlag = 0x0002\n)\n\nfunc GetRandom(p []byte, flags GetRandomFlag) (n int, err error) {\n\tpanic(\"todo: unix.GetRandom\")\n}\n"
  },
  {
    "path": "src/internal/task/atomic-cooperative.go",
    "content": "//go:build tinygo.unicore\n\npackage task\n\n// Atomics implementation for cooperative systems. The atomic types here aren't\n// actually atomic, they assume that accesses cannot be interrupted by a\n// different goroutine or interrupt happening at the same time.\n\ntype atomicIntegerType interface {\n\tuintptr | uint32 | uint64\n}\n\ntype pseudoAtomic[T atomicIntegerType] struct {\n\tv T\n}\n\nfunc (x *pseudoAtomic[T]) Add(delta T) T { x.v += delta; return x.v }\nfunc (x *pseudoAtomic[T]) Load() T       { return x.v }\nfunc (x *pseudoAtomic[T]) Store(val T)   { x.v = val }\nfunc (x *pseudoAtomic[T]) CompareAndSwap(old, new T) (swapped bool) {\n\tif x.v != old {\n\t\treturn false\n\t}\n\tx.v = new\n\treturn true\n}\nfunc (x *pseudoAtomic[T]) Swap(new T) (old T) {\n\told = x.v\n\tx.v = new\n\treturn\n}\n\n// Uintptr is an atomic uintptr when multithreading is enabled, and a plain old\n// uintptr otherwise.\ntype Uintptr = pseudoAtomic[uintptr]\n\n// Uint32 is an atomic uint32 when multithreading is enabled, and a plain old\n// uint32 otherwise.\ntype Uint32 = pseudoAtomic[uint32]\n\n// Uint64 is an atomic uint64 when multithreading is enabled, and a plain old\n// uint64 otherwise.\ntype Uint64 = pseudoAtomic[uint64]\n"
  },
  {
    "path": "src/internal/task/atomic-preemptive.go",
    "content": "//go:build !tinygo.unicore\n\npackage task\n\n// Atomics implementation for non-cooperative systems (multithreaded, etc).\n// These atomic types use real atomic instructions.\n\nimport \"sync/atomic\"\n\ntype (\n\tUintptr = atomic.Uintptr\n\tUint32  = atomic.Uint32\n\tUint64  = atomic.Uint64\n)\n"
  },
  {
    "path": "src/internal/task/darwin.go",
    "content": "//go:build darwin\n\npackage task\n\nimport \"unsafe\"\n\n// MacOS uses a pointer so unsafe.Pointer should be fine:\n//\n//\ttypedef struct _opaque_pthread_t *__darwin_pthread_t;\n//\ttypedef __darwin_pthread_t pthread_t;\ntype threadID unsafe.Pointer\n"
  },
  {
    "path": "src/internal/task/futex-cooperative.go",
    "content": "//go:build tinygo.unicore\n\npackage task\n\n// A futex is a way for userspace to wait with the pointer as the key, and for\n// another thread to wake one or all waiting threads keyed on the same pointer.\n//\n// A futex does not change the underlying value, it only reads it before to prevent\n// lost wake-ups.\ntype Futex struct {\n\tUint32\n\twaiters Stack\n}\n\n// Atomically check for cmp to still be equal to the futex value and if so, go\n// to sleep. Return true if we were definitely awoken by a call to Wake or\n// WakeAll, and false if we can't be sure of that.\nfunc (f *Futex) Wait(cmp uint32) (awoken bool) {\n\tif f.Uint32.v != cmp {\n\t\treturn false\n\t}\n\n\t// Push the current goroutine onto the waiter stack.\n\tf.waiters.Push(Current())\n\n\t// Pause until the waiters are awoken by Wake/WakeAll.\n\tPause()\n\n\t// We were awoken by a call to Wake or WakeAll. There is no chance for\n\t// spurious wakeups.\n\treturn true\n}\n\n// Wake a single waiter.\nfunc (f *Futex) Wake() {\n\tif t := f.waiters.Pop(); t != nil {\n\t\tscheduleTask(t)\n\t}\n}\n\n// Wake all waiters.\nfunc (f *Futex) WakeAll() {\n\tfor t := f.waiters.Pop(); t != nil; t = f.waiters.Pop() {\n\t\tscheduleTask(t)\n\t}\n}\n"
  },
  {
    "path": "src/internal/task/futex-cores.go",
    "content": "//go:build scheduler.cores\n\npackage task\n\nimport \"runtime/interrupt\"\n\n// A futex is a way for userspace to wait with the pointer as the key, and for\n// another thread to wake one or all waiting threads keyed on the same pointer.\n//\n// A futex does not change the underlying value, it only reads it before to prevent\n// lost wake-ups.\ntype Futex struct {\n\tUint32\n\n\twaiters Stack\n}\n\n// Atomically check for cmp to still be equal to the futex value and if so, go\n// to sleep. Return true if we were definitely awoken by a call to Wake or\n// WakeAll, and false if we can't be sure of that.\nfunc (f *Futex) Wait(cmp uint32) (awoken bool) {\n\tmask := lockFutex()\n\n\tif f.Uint32.Load() != cmp {\n\t\tunlockFutex(mask)\n\t\treturn false\n\t}\n\n\t// Push the current goroutine onto the waiter stack.\n\tf.waiters.Push(Current())\n\n\tunlockFutex(mask)\n\n\t// Pause until this task is awoken by Wake/WakeAll.\n\tPause()\n\n\t// We were awoken by a call to Wake or WakeAll. There is no chance for\n\t// spurious wakeups.\n\treturn true\n}\n\n// Wake a single waiter.\nfunc (f *Futex) Wake() {\n\tmask := lockFutex()\n\tif t := f.waiters.Pop(); t != nil {\n\t\tscheduleTask(t)\n\t}\n\tunlockFutex(mask)\n}\n\n// Wake all waiters.\nfunc (f *Futex) WakeAll() {\n\tmask := lockFutex()\n\tfor t := f.waiters.Pop(); t != nil; t = f.waiters.Pop() {\n\t\tscheduleTask(t)\n\t}\n\tunlockFutex(mask)\n}\n\n//go:linkname lockFutex runtime.lockFutex\nfunc lockFutex() interrupt.State\n\n//go:linkname unlockFutex runtime.unlockFutex\nfunc unlockFutex(interrupt.State)\n"
  },
  {
    "path": "src/internal/task/futex-threads.go",
    "content": "//go:build scheduler.threads\n\npackage task\n\nimport \"internal/futex\"\n\ntype Futex = futex.Futex\n"
  },
  {
    "path": "src/internal/task/gc_stack_chain.go",
    "content": "//go:build (gc.conservative || gc.custom || gc.precise) && tinygo.wasm\n\npackage task\n\nimport \"unsafe\"\n\n//go:linkname swapStackChain runtime.swapStackChain\nfunc swapStackChain(dst *unsafe.Pointer)\n\ntype gcData struct {\n\tstackChain unsafe.Pointer\n}\n\nfunc (gcd *gcData) swap() {\n\tswapStackChain(&gcd.stackChain)\n}\n"
  },
  {
    "path": "src/internal/task/gc_stack_noop.go",
    "content": "//go:build !(gc.conservative || gc.custom || gc.precise) || !tinygo.wasm\n\npackage task\n\ntype gcData struct{}\n\nfunc (gcd *gcData) swap() {\n}\n"
  },
  {
    "path": "src/internal/task/linux.go",
    "content": "//go:build linux && !baremetal\n\npackage task\n\nimport \"unsafe\"\n\n// Musl uses a pointer (or unsigned long for C++) so unsafe.Pointer should be\n// fine.\ntype threadID unsafe.Pointer\n"
  },
  {
    "path": "src/internal/task/mutex-cooperative.go",
    "content": "//go:build tinygo.unicore\n\npackage task\n\ntype Mutex struct {\n\tlocked  bool\n\tblocked Stack\n}\n\nfunc (m *Mutex) Lock() {\n\tif m.locked {\n\t\t// Push self onto stack of blocked tasks, and wait to be resumed.\n\t\tm.blocked.Push(Current())\n\t\tPause()\n\t\treturn\n\t}\n\n\tm.locked = true\n}\n\nfunc (m *Mutex) Unlock() {\n\tif !m.locked {\n\t\tpanic(\"sync: unlock of unlocked Mutex\")\n\t}\n\n\t// Wake up a blocked task, if applicable.\n\tif t := m.blocked.Pop(); t != nil {\n\t\tscheduleTask(t)\n\t} else {\n\t\tm.locked = false\n\t}\n}\n\n// TryLock tries to lock m and reports whether it succeeded.\n//\n// Note that while correct uses of TryLock do exist, they are rare,\n// and use of TryLock is often a sign of a deeper problem\n// in a particular use of mutexes.\nfunc (m *Mutex) TryLock() bool {\n\tif m.locked {\n\t\treturn false\n\t}\n\tm.Lock()\n\treturn true\n}\n"
  },
  {
    "path": "src/internal/task/mutex-preemptive.go",
    "content": "//go:build !tinygo.unicore\n\npackage task\n\n// Futex-based mutex.\n// This is largely based on the paper \"Futexes are Tricky\" by Ulrich Drepper.\n// It describes a few ways to implement mutexes using a futex, and how some\n// seemingly-obvious implementations don't exactly work as intended.\n// Unfortunately, Go atomic operations work slightly differently so we can't\n// copy the algorithm verbatim.\n//\n// The implementation works like this. The futex can have 3 different values,\n// depending on the state:\n//\n//   - 0: the futex is currently unlocked.\n//   - 1: the futex is locked, but is uncontended. There is one special case: if\n//     a contended futex is unlocked, it is set to 0. It is possible for another\n//     thread to lock the futex before the next waiter is woken. But because a\n//     waiter will be woken (if there is one), it will always change to 2\n//     regardless. So this is not a problem.\n//   - 2: the futex is locked, and is contended. At least one thread is trying\n//     to obtain the lock (and is in the contended loop, see below).\n//\n// For the paper, see:\n// https://dept-info.labri.fr/~denis/Enseignement/2008-IR/Articles/01-futex.pdf)\n\ntype Mutex struct {\n\tfutex Futex\n}\n\nfunc (m *Mutex) Lock() {\n\t// Fast path: try to take an uncontended lock.\n\tif m.futex.CompareAndSwap(0, 1) {\n\t\t// We obtained the mutex.\n\t\treturn\n\t}\n\n\t// The futex is contended, so we enter the contended loop.\n\t// If we manage to change the futex from 0 to 2, we managed to take the\n\t// lock. Else, we have to wait until a call to Unlock unlocks this mutex.\n\t// (Unlock will wake one waiter when it finds the futex is set to 2 when\n\t// unlocking).\n\tfor m.futex.Swap(2) != 0 {\n\t\t// Wait until we get resumed in Unlock.\n\t\tm.futex.Wait(2)\n\t}\n}\n\nfunc (m *Mutex) Unlock() {\n\tif old := m.futex.Swap(0); old == 0 {\n\t\t// Mutex wasn't locked before.\n\t\tpanic(\"sync: unlock of unlocked Mutex\")\n\t} else if old == 2 {\n\t\t// Mutex was a contended lock, so we need to wake the next waiter.\n\t\tm.futex.Wake()\n\t}\n}\n\n// TryLock tries to lock m and reports whether it succeeded.\n//\n// Note that while correct uses of TryLock do exist, they are rare,\n// and use of TryLock is often a sign of a deeper problem\n// in a particular use of mutexes.\nfunc (m *Mutex) TryLock() bool {\n\t// Fast path: try to take an uncontended lock.\n\tif m.futex.CompareAndSwap(0, 1) {\n\t\t// We obtained the mutex.\n\t\treturn true\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "src/internal/task/pmutex-cooperative.go",
    "content": "//go:build tinygo.unicore\n\npackage task\n\n// PMutex is a real mutex on systems that can be either preemptive or threaded,\n// and a dummy lock on other (purely cooperative) systems.\n//\n// It is mainly useful for short operations that need a lock when threading may\n// be involved, but which do not need a lock with a purely cooperative\n// scheduler.\ntype PMutex struct {\n}\n\nfunc (m *PMutex) Lock() {\n}\n\nfunc (m *PMutex) Unlock() {\n}\n"
  },
  {
    "path": "src/internal/task/pmutex-preemptive.go",
    "content": "//go:build !tinygo.unicore\n\npackage task\n\n// PMutex is a real mutex on systems that can be either preemptive or threaded,\n// and a dummy lock on other (purely cooperative) systems.\n//\n// It is mainly useful for short operations that need a lock when threading may\n// be involved, but which do not need a lock with a purely cooperative\n// scheduler.\ntype PMutex = Mutex\n"
  },
  {
    "path": "src/internal/task/queue.go",
    "content": "package task\n\nimport \"runtime/interrupt\"\n\nconst asserts = false\n\n// Queue is a FIFO container of tasks.\n// The zero value is an empty queue.\ntype Queue struct {\n\thead, tail *Task\n}\n\n// Push a task onto the queue.\nfunc (q *Queue) Push(t *Task) {\n\tmask := lockAtomics()\n\tif asserts && t.Next != nil {\n\t\tunlockAtomics(mask)\n\t\tpanic(\"runtime: pushing a task to a queue with a non-nil Next pointer\")\n\t}\n\tif q.tail != nil {\n\t\tq.tail.Next = t\n\t}\n\tq.tail = t\n\tt.Next = nil\n\tif q.head == nil {\n\t\tq.head = t\n\t}\n\tunlockAtomics(mask)\n}\n\n// Pop a task off of the queue.\nfunc (q *Queue) Pop() *Task {\n\tmask := lockAtomics()\n\tt := q.head\n\tif t == nil {\n\t\tunlockAtomics(mask)\n\t\treturn nil\n\t}\n\tq.head = t.Next\n\tif q.tail == t {\n\t\tq.tail = nil\n\t}\n\tt.Next = nil\n\tunlockAtomics(mask)\n\treturn t\n}\n\n// Append pops the contents of another queue and pushes them onto the end of this queue.\nfunc (q *Queue) Append(other *Queue) {\n\tmask := lockAtomics()\n\tif q.head == nil {\n\t\tq.head = other.head\n\t} else {\n\t\tq.tail.Next = other.head\n\t}\n\tq.tail = other.tail\n\tother.head, other.tail = nil, nil\n\tunlockAtomics(mask)\n}\n\n// Empty checks if the queue is empty.\nfunc (q *Queue) Empty() bool {\n\tmask := lockAtomics()\n\tempty := q.head == nil\n\tunlockAtomics(mask)\n\treturn empty\n}\n\n// Stack is a LIFO container of tasks.\n// The zero value is an empty stack.\n// This is slightly cheaper than a queue, so it can be preferable when strict ordering is not necessary.\ntype Stack struct {\n\ttop *Task\n}\n\n// Push a task onto the stack.\nfunc (s *Stack) Push(t *Task) {\n\tmask := lockAtomics()\n\tif asserts && t.Next != nil {\n\t\tunlockAtomics(mask)\n\t\tpanic(\"runtime: pushing a task to a stack with a non-nil Next pointer\")\n\t}\n\ts.top, t.Next = t, s.top\n\tunlockAtomics(mask)\n}\n\n// Pop a task off of the stack.\nfunc (s *Stack) Pop() *Task {\n\tmask := lockAtomics()\n\tt := s.top\n\tif t != nil {\n\t\ts.top = t.Next\n\t\tt.Next = nil\n\t}\n\tunlockAtomics(mask)\n\treturn t\n}\n\n// tail follows the chain of tasks.\n// If t is nil, returns nil.\n// Otherwise, returns the task in the chain where the Next field is nil.\nfunc (t *Task) tail() *Task {\n\tif t == nil {\n\t\treturn nil\n\t}\n\tfor t.Next != nil {\n\t\tt = t.Next\n\t}\n\treturn t\n}\n\n// Queue moves the contents of the stack into a queue.\n// Elements can be popped from the queue in the same order that they would be popped from the stack.\nfunc (s *Stack) Queue() Queue {\n\tmask := lockAtomics()\n\thead := s.top\n\ts.top = nil\n\tq := Queue{\n\t\thead: head,\n\t\ttail: head.tail(),\n\t}\n\tunlockAtomics(mask)\n\treturn q\n}\n\n// Use runtime.lockAtomics and runtime.unlockAtomics so that Queue and Stack\n// work correctly even on multicore systems. These functions are normally used\n// to implement atomic operations, but the same spinlock can also be used for\n// Queue/Stack operations which are very fast.\n// These functions are just plain old interrupt disable/restore on non-multicore\n// systems.\n\n//go:linkname lockAtomics runtime.lockAtomics\nfunc lockAtomics() interrupt.State\n\n//go:linkname unlockAtomics runtime.unlockAtomics\nfunc unlockAtomics(mask interrupt.State)\n"
  },
  {
    "path": "src/internal/task/semaphore.go",
    "content": "package task\n\n// Barebones semaphore implementation.\n// The main limitation is that if there are multiple waiters, a single Post()\n// call won't do anything. Only when Post() has been called to awaken all\n// waiters will the waiters proceed.\n// This limitation is not a problem when there will only be a single waiter.\ntype Semaphore struct {\n\tfutex Futex\n}\n\n// Post (unlock) the semaphore, incrementing the value in the semaphore.\nfunc (s *Semaphore) Post() {\n\tnewValue := s.futex.Add(1)\n\tif newValue == 0 {\n\t\ts.futex.WakeAll()\n\t}\n}\n\n// Wait (lock) the semaphore, decrementing the value in the semaphore.\nfunc (s *Semaphore) Wait() {\n\tdelta := int32(-1)\n\tvalue := s.futex.Add(uint32(delta))\n\tfor {\n\t\tif int32(value) >= 0 {\n\t\t\t// Semaphore unlocked!\n\t\t\treturn\n\t\t}\n\t\ts.futex.Wait(value)\n\t\tvalue = s.futex.Load()\n\t}\n}\n"
  },
  {
    "path": "src/internal/task/task.go",
    "content": "package task\n\nimport (\n\t\"unsafe\"\n)\n\n// Task is a state of goroutine for scheduling purposes.\ntype Task struct {\n\t// Next is a field which can be used to make a linked list of tasks.\n\tNext *Task\n\n\t// Ptr is a field which can be used for storing a pointer.\n\tPtr unsafe.Pointer\n\n\t// Data is a field which can be used for storing state information.\n\tData uint64\n\n\t// gcData holds data for the GC.\n\tgcData gcData\n\n\t// state is the underlying running state of the task.\n\tstate state\n\n\t// This is needed for some crypto packages.\n\tFipsIndicator uint8\n\n\t// State of the goroutine: running, paused, or must-resume-next-pause.\n\t// This extra field doesn't increase memory usage on 32-bit CPUs and above,\n\t// since it falls into the padding of the FipsIndicator bit above.\n\tRunState uint8\n\n\t// DeferFrame stores a pointer to the (stack allocated) defer frame of the\n\t// goroutine that is used for the recover builtin.\n\tDeferFrame unsafe.Pointer\n}\n\nconst (\n\t// Initial state: the goroutine state is saved on the stack.\n\tRunStatePaused = iota\n\n\t// The goroutine is running right now.\n\tRunStateRunning\n\n\t// The goroutine is running, but already marked as \"can resume\".\n\t// The next call to Pause() won't actually pause the goroutine.\n\tRunStateResuming\n)\n\n// DataUint32 returns the Data field as a uint32. The value is only valid after\n// setting it through SetDataUint32 or by storing to it using DataAtomicUint32.\nfunc (t *Task) DataUint32() uint32 {\n\treturn *(*uint32)(unsafe.Pointer(&t.Data))\n}\n\n// SetDataUint32 updates the uint32 portion of the Data field (which could be\n// the first 4 or last 4 bytes depending on the architecture endianness).\nfunc (t *Task) SetDataUint32(val uint32) {\n\t*(*uint32)(unsafe.Pointer(&t.Data)) = val\n}\n\n// DataAtomicUint32 returns the Data field as an atomic-if-needed Uint32 value.\nfunc (t *Task) DataAtomicUint32() *Uint32 {\n\treturn (*Uint32)(unsafe.Pointer(&t.Data))\n}\n\n// getGoroutineStackSize is a compiler intrinsic that returns the stack size for\n// the given function and falls back to the default stack size. It is replaced\n// with a load from a special section just before codegen.\nfunc getGoroutineStackSize(fn uintptr) uintptr\n\n//go:linkname runtime_alloc runtime.alloc\nfunc runtime_alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer\n\n//go:linkname scheduleTask runtime.scheduleTask\nfunc scheduleTask(*Task)\n"
  },
  {
    "path": "src/internal/task/task_asyncify.go",
    "content": "//go:build scheduler.asyncify\n\npackage task\n\nimport (\n\t\"unsafe\"\n)\n\n// Stack canary, to detect a stack overflow. The number is a random number\n// generated by random.org. The bit fiddling dance is necessary because\n// otherwise Go wouldn't allow the cast to a smaller integer size.\nconst stackCanary = uintptr(uint64(0x670c1333b83bf575) & uint64(^uintptr(0)))\n\n//go:linkname runtimePanic runtime.runtimePanic\nfunc runtimePanic(str string)\n\n// state is a structure which holds a reference to the state of the task.\n// When the task is suspended, the stack pointers are saved here.\ntype state struct {\n\t// entry is the entry function of the task.\n\t// This is needed every time the function is invoked so that asyncify knows what to rewind.\n\tentry uintptr\n\n\t// args are a pointer to a struct holding the arguments of the function.\n\targs unsafe.Pointer\n\n\t// stackState is the state of the stack while unwound.\n\tstackState\n\n\tlaunched bool\n}\n\n// stackState is the saved state of a stack while unwound.\n// The stack is arranged with asyncify at the bottom, C stack at the top, and a gap of available stack space between the two.\ntype stackState struct {\n\t// asyncify is the stack pointer of the asyncify stack.\n\t// This starts from the bottom and grows upwards.\n\tasyncifysp unsafe.Pointer\n\n\t// asyncify is stack pointer of the C stack.\n\t// This starts from the top and grows downwards.\n\tcsp unsafe.Pointer\n\n\t// Pointer to the first (lowest address) of the stack. It must never be\n\t// overwritten. It can be checked from time to time to see whether a stack\n\t// overflow happened in the past.\n\tcanaryPtr *uintptr\n}\n\n// start creates and starts a new goroutine with the given function and arguments.\n// The new goroutine is immediately started.\nfunc start(fn uintptr, args unsafe.Pointer, stackSize uintptr) {\n\tt := &Task{}\n\tt.state.initialize(fn, args, stackSize)\n\tscheduleTask(t)\n}\n\n//export tinygo_launch\nfunc (*state) launch()\n\n//go:linkname align runtime.align\nfunc align(p uintptr) uintptr\n\n// initialize the state and prepare to call the specified function with the specified argument bundle.\nfunc (s *state) initialize(fn uintptr, args unsafe.Pointer, stackSize uintptr) {\n\t// Save the entry call.\n\ts.entry = fn\n\ts.args = args\n\n\t// Create a stack.\n\tstack := runtime_alloc(stackSize, nil)\n\n\t// Set up the stack canary, a random number that should be checked when\n\t// switching from the task back to the scheduler. The stack canary pointer\n\t// points to the first word of the stack. If it has changed between now and\n\t// the next stack switch, there was a stack overflow.\n\ts.canaryPtr = (*uintptr)(stack)\n\t*s.canaryPtr = stackCanary\n\n\t// Calculate stack base addresses.\n\ts.asyncifysp = unsafe.Add(stack, unsafe.Sizeof(uintptr(0)))\n\ts.csp = unsafe.Add(stack, stackSize)\n}\n\n// currentTask is the current running task, or nil if currently in the scheduler.\nvar currentTask *Task\n\n// Current returns the current active task.\nfunc Current() *Task {\n\treturn currentTask\n}\n\n// Pause suspends the current task and returns to the scheduler.\n// This function may only be called when running on a goroutine stack, not when running on the system stack.\nfunc Pause() {\n\tif *currentTask.state.canaryPtr != stackCanary {\n\t\truntimePanic(\"stack overflow\")\n\t}\n\n\tcurrentTask.state.unwind()\n}\n\n//export tinygo_unwind\nfunc (*stackState) unwind()\n\n// Resume the task until it pauses or completes.\n// This may only be called from the scheduler.\nfunc (t *Task) Resume() {\n\t// The current task must be saved and restored because this can nest on WASM with JS.\n\tprevTask := currentTask\n\tif prevTask == nil {\n\t\t// Save the system stack pointer.\n\t\tsaveStackPointer()\n\t}\n\tt.gcData.swap()\n\tcurrentTask = t\n\tif !t.state.launched {\n\t\tt.state.launch()\n\t\tt.state.launched = true\n\t} else {\n\t\tt.state.rewind()\n\t}\n\tcurrentTask = prevTask\n\tt.gcData.swap()\n\tif uintptr(t.state.asyncifysp) > uintptr(t.state.csp) {\n\t\truntimePanic(\"stack overflow\")\n\t}\n}\n\n//go:linkname saveStackPointer runtime.saveStackPointer\nfunc saveStackPointer()\n\n//export tinygo_rewind\nfunc (*state) rewind()\n\n// OnSystemStack returns whether the caller is running on the system stack.\nfunc OnSystemStack() bool {\n\t// If there is not an active goroutine, then this must be running on the system stack.\n\treturn Current() == nil\n}\n"
  },
  {
    "path": "src/internal/task/task_asyncify_wasm.S",
    "content": ".globaltype __stack_pointer, i32\n\n.functype start_unwind (i32) -> ()\n.import_module start_unwind, asyncify\n.import_name start_unwind, start_unwind\n.functype stop_unwind () -> ()\n.import_module stop_unwind, asyncify\n.import_name stop_unwind, stop_unwind\n.functype start_rewind (i32) -> ()\n.import_module start_rewind, asyncify\n.import_name start_rewind, start_rewind\n.functype stop_rewind () -> ()\n.import_module stop_rewind, asyncify\n.import_name stop_rewind, stop_rewind\n\n.global  tinygo_unwind\n.hidden  tinygo_unwind\n.type    tinygo_unwind,@function\ntinygo_unwind: // func (state *stackState) unwind()\n    .functype tinygo_unwind (i32) -> ()\n    // Check if we are rewinding.\n    i32.const 0\n    i32.load8_u tinygo_rewinding\n    if // if tinygo_rewinding {\n    // Stop rewinding.\n    call stop_rewind\n    i32.const 0\n    i32.const 0\n    i32.store8 tinygo_rewinding // tinygo_rewinding = false;\n    else\n    // Save the C stack pointer (destination structure pointer is in local 0).\n    local.get 0\n    global.get __stack_pointer\n    i32.store 4 // state.csp = getCurrentStackPointer()\n    // Ask asyncify to unwind.\n    // When resuming, asyncify will return this function with tinygo_rewinding set to true.\n    local.get 0\n    call start_unwind // asyncify.start_unwind(state)\n    end_if\n    return\n    end_function\n\n.global tinygo_launch\n.hidden tinygo_launch\n.type tinygo_launch,@function\ntinygo_launch: // func (state *state) launch()\n    .functype tinygo_launch (i32) -> ()\n    // Switch to the goroutine's C stack.\n    global.get __stack_pointer // prev := getCurrentStackPointer()\n    local.get 0\n    i32.load 12\n    global.set __stack_pointer // setStackPointer(state.csp)\n    // Get the argument pack and entry pointer.\n    local.get 0\n    i32.load 4 // args := state.args\n    local.get 0\n    i32.load 0 // fn := state.entry\n    // Launch the entry function.\n    call_indirect (i32) -> () // fn(args)\n    // Stop unwinding.\n    call stop_unwind\n    // Restore the C stack.\n    global.set __stack_pointer // setStackPointer(prev)\n    return\n    end_function\n\n.global  tinygo_rewind\n.hidden  tinygo_rewind\n.type    tinygo_rewind,@function\ntinygo_rewind: // func (state *state) rewind()\n    .functype tinygo_rewind (i32) -> ()\n    // Switch to the goroutine's C stack.\n    global.get __stack_pointer // prev := getCurrentStackPointer()\n    local.get 0\n    i32.load 12\n    global.set __stack_pointer // setStackPointer(state.csp)\n    // Get the argument pack and entry pointer.\n    local.get 0\n    i32.load 4 // args := state.args\n    local.get 0\n    i32.load 0 // fn := state.entry\n    // Prepare to rewind.\n    i32.const 0\n    i32.const 1\n    i32.store8 tinygo_rewinding // tinygo_rewinding = true;\n    local.get 0\n    i32.const 8\n    i32.add\n    call start_rewind // asyncify.start_rewind(&state.stackState)\n    // Launch the entry function.\n    // This will actually rewind the call stack.\n    call_indirect (i32) -> () // fn(args)\n    // Stop unwinding.\n    call stop_unwind\n    // Restore the C stack.\n    global.set __stack_pointer // setStackPointer(prev)\n    return\n    end_function\n\n        .hidden tinygo_rewinding                # @tinygo_rewinding\n        .type   tinygo_rewinding,@object\n        .section        .bss.tinygo_rewinding,\"\",@\n        .globl  tinygo_rewinding\ntinygo_rewinding:\n        .int8   0                               # 0x0\n        .size   tinygo_rewinding, 1\n"
  },
  {
    "path": "src/internal/task/task_none.go",
    "content": "//go:build scheduler.none\n\npackage task\n\nimport \"unsafe\"\n\n// There is only one goroutine so the task struct can be a global.\nvar mainTask Task\n\n//go:linkname runtimePanic runtime.runtimePanic\nfunc runtimePanic(str string)\n\nfunc Pause() {\n\truntimePanic(\"scheduler is disabled\")\n}\n\nfunc Current() *Task {\n\t// Return a task struct, which is used for the recover builtin for example.\n\treturn &mainTask\n}\n\n//go:noinline\nfunc start(fn uintptr, args unsafe.Pointer, stackSize uintptr) {\n\t// The compiler will error if this is reachable.\n\truntimePanic(\"scheduler is disabled\")\n}\n\ntype state struct{}\n\nfunc (t *Task) Resume() {\n\truntimePanic(\"scheduler is disabled\")\n}\n\n// OnSystemStack returns whether the caller is running on the system stack.\nfunc OnSystemStack() bool {\n\t// This scheduler does not do any stack switching.\n\treturn true\n}\n\nfunc SystemStack() uintptr {\n\t// System stack is the current stack, so this shouldn't be called.\n\truntimePanic(\"scheduler is disabled\")\n\treturn 0 // unreachable\n}\n"
  },
  {
    "path": "src/internal/task/task_stack.go",
    "content": "//go:build scheduler.tasks || scheduler.cores\n\npackage task\n\nimport (\n\t\"unsafe\"\n)\n\n//go:linkname runtimePanic runtime.runtimePanic\nfunc runtimePanic(str string)\n\n// Stack canary, to detect a stack overflow. The number is a random number\n// generated by random.org. The bit fiddling dance is necessary because\n// otherwise Go wouldn't allow the cast to a smaller integer size.\nconst stackCanary = uintptr(uint64(0x670c1333b83bf575) & uint64(^uintptr(0)))\n\n// state is a structure which holds a reference to the state of the task.\n// When the task is suspended, the registers are stored onto the stack and the stack pointer is stored into sp.\ntype state struct {\n\t// sp is the stack pointer of the saved state.\n\t// When the task is inactive, the saved registers are stored at the top of the stack.\n\t// Note: this should ideally be a unsafe.Pointer for the precise GC. The GC\n\t// will find the stack through canaryPtr though so it's not currently a\n\t// problem to store this value as uintptr.\n\tsp uintptr\n\n\t// canaryPtr points to the top word of the stack (the lowest address).\n\t// This is used to detect stack overflows.\n\t// When initializing the goroutine, the stackCanary constant is stored there.\n\t// If the stack overflowed, the word will likely no longer equal stackCanary.\n\tcanaryPtr *uintptr\n}\n\n//export tinygo_task_exit\nfunc taskExit() {\n\t// TODO: explicitly free the stack after switching back to the scheduler.\n\tPause()\n}\n\n// initialize the state and prepare to call the specified function with the specified argument bundle.\nfunc (s *state) initialize(fn uintptr, args unsafe.Pointer, stackSize uintptr) {\n\t// Create a stack.\n\tstack := runtime_alloc(stackSize, nil)\n\n\t// Set up the stack canary, a random number that should be checked when\n\t// switching from the task back to the scheduler. The stack canary pointer\n\t// points to the first word of the stack. If it has changed between now and\n\t// the next stack switch, there was a stack overflow.\n\ts.canaryPtr = (*uintptr)(stack)\n\t*s.canaryPtr = stackCanary\n\n\t// Get a pointer to the top of the stack, where the initial register values\n\t// are stored. They will be popped off the stack on the first stack switch\n\t// to the goroutine, and will start running tinygo_startTask (this setup\n\t// happens in archInit).\n\tr := (*calleeSavedRegs)(unsafe.Add(stack, stackSize-unsafe.Sizeof(calleeSavedRegs{})))\n\n\t// Invoke architecture-specific initialization.\n\ts.archInit(r, fn, args)\n}\n\n//export tinygo_swapTask\nfunc swapTask(oldStack uintptr, newStack *uintptr)\n\n// startTask is a small wrapper function that sets up the first (and only)\n// argument to the new goroutine and makes sure it is exited when the goroutine\n// finishes.\n//\n//go:extern tinygo_startTask\nvar startTask [0]uint8\n\n// start creates and starts a new goroutine with the given function and arguments.\n// The new goroutine is scheduled to run later.\nfunc start(fn uintptr, args unsafe.Pointer, stackSize uintptr) {\n\tt := &Task{}\n\tt.state.initialize(fn, args, stackSize)\n\tscheduleTask(t)\n}\n\n// OnSystemStack returns whether the caller is running on the system stack.\nfunc OnSystemStack() bool {\n\t// If there is not an active goroutine, then this must be running on the system stack.\n\treturn Current() == nil\n}\n"
  },
  {
    "path": "src/internal/task/task_stack_386.S",
    "content": "#ifdef _WIN32\n.global  _tinygo_startTask\n_tinygo_startTask:\n#else // Linux etc\n.section .text.tinygo_startTask\n.global  tinygo_startTask\n.type    tinygo_startTask, %function\ntinygo_startTask:\n#endif\n    .cfi_startproc\n    // Small assembly stub for starting a goroutine. This is already run on the\n    // new stack, with the callee-saved registers already loaded.\n    // Most importantly, EBX contain the pc of the to-be-started function and\n    // ESI contain the only argument it is given. Multiple arguments are packed\n    // into one by storing them in a new allocation.\n\n    // Indicate to the unwinder that there is nothing to unwind, this is the\n    // root frame. It avoids bogus extra frames in GDB.\n    .cfi_undefined eip\n\n    // Set the first argument of the goroutine start wrapper, which contains all\n    // the arguments.\n    pushl %esi\n\n    // Branch to the \"goroutine start\" function.\n    calll *%ebx\n\n    // Rebalance the stack (to undo the above push).\n    addl $4, %esp\n\n    // After return, exit this goroutine. This is a tail call.\n    #ifdef _WIN32\n    jmp _tinygo_task_exit\n    #else\n    jmp tinygo_task_exit\n    #endif\n    .cfi_endproc\n\n#ifdef _WIN32\n.global _tinygo_swapTask\n_tinygo_swapTask:\n#else\n.global tinygo_swapTask\n.type tinygo_swapTask, %function\ntinygo_swapTask:\n#endif\n    // This function gets the following parameters:\n    movl 4(%esp), %eax // newStack uintptr\n    movl 8(%esp), %ecx // oldStack *uintptr\n    // More information on the calling convention:\n    // https://wiki.osdev.org/System_V_ABI#i386\n\n    // Save all callee-saved registers:\n    pushl %ebp\n    pushl %edi\n    pushl %esi\n    pushl %ebx\n\n    // Save the current stack pointer in oldStack.\n    movl %esp, (%ecx)\n\n    // Switch to the new stack pointer.\n    movl %eax, %esp\n\n    // Load saved register from the new stack.\n    popl %ebx\n    popl %esi\n    popl %edi\n    popl %ebp\n\n    // Return into the new task, as if tinygo_swapTask was a regular call.\n    ret\n"
  },
  {
    "path": "src/internal/task/task_stack_386.go",
    "content": "//go:build scheduler.tasks && 386\n\npackage task\n\nimport \"unsafe\"\n\nvar systemStack uintptr\n\n// calleeSavedRegs is the list of registers that must be saved and restored when\n// switching between tasks. Also see task_stack_386.S that relies on the exact\n// layout of this struct.\ntype calleeSavedRegs struct {\n\tebx uintptr\n\tesi uintptr\n\tedi uintptr\n\tebp uintptr\n\n\tpc uintptr\n\n\t// Pad this struct so that tasks start on a 16-byte aligned stack.\n\t_ [3]uintptr\n}\n\n// archInit runs architecture-specific setup for the goroutine startup.\nfunc (s *state) archInit(r *calleeSavedRegs, fn uintptr, args unsafe.Pointer) {\n\t// Store the initial sp for the startTask function (implemented in assembly).\n\ts.sp = uintptr(unsafe.Pointer(r))\n\n\t// Initialize the registers.\n\t// These will be popped off of the stack on the first resume of the goroutine.\n\n\t// Start the function at tinygo_startTask (defined in\n\t// src/internal/task/task_stack_386.S). This assembly code calls a function\n\t// (passed in EBX) with a single argument (passed in ESI). After the\n\t// function returns, it calls Pause().\n\tr.pc = uintptr(unsafe.Pointer(&startTask))\n\n\t// Pass the function to call in EBX.\n\t// This function is a compiler-generated wrapper which loads arguments out\n\t// of a struct pointer. See createGoroutineStartWrapper (defined in\n\t// compiler/goroutine.go) for more information.\n\tr.ebx = fn\n\n\t// Pass the pointer to the arguments struct in ESI.\n\tr.esi = uintptr(args)\n}\n\nfunc (s *state) resume() {\n\tswapTask(s.sp, &systemStack)\n}\n\nfunc (s *state) pause() {\n\tnewStack := systemStack\n\tsystemStack = 0\n\tswapTask(newStack, &s.sp)\n}\n\n// SystemStack returns the system stack pointer when called from a task stack.\n// When called from the system stack, it returns 0.\nfunc SystemStack() uintptr {\n\treturn systemStack\n}\n"
  },
  {
    "path": "src/internal/task/task_stack_amd64.S",
    "content": "#ifdef __MACH__ // Darwin\n.global  _tinygo_startTask\n_tinygo_startTask:\n#else // Linux etc\n.section .text.tinygo_startTask\n.global  tinygo_startTask\ntinygo_startTask:\n#endif\n    .cfi_startproc\n    // Small assembly stub for starting a goroutine. This is already run on the\n    // new stack, with the callee-saved registers already loaded.\n    // Most importantly, r12 contain the pc of the to-be-started function and\n    // r13 contain the only argument it is given. Multiple arguments are packed\n    // into one by storing them in a new allocation.\n\n    // Indicate to the unwinder that there is nothing to unwind, this is the\n    // root frame. It avoids bogus extra frames in GDB like here:\n    //     #10 0x00000000004277b6 in <goroutine wrapper> () at [...]\n    //     #11 0x00000000004278f3 in tinygo_startTask () at [...]\n    //     #12 0x0000000000002030 in ?? ()\n    //     #13 0x0000000000000071 in ?? ()\n    .cfi_undefined rip\n\n    // Set the first argument of the goroutine start wrapper, which contains all\n    // the arguments.\n    movq %r13, %rdi\n\n    // Branch to the \"goroutine start\" function.\n    callq *%r12\n\n    // After return, exit this goroutine. This is a tail call.\n    #ifdef __MACH__\n    jmp _tinygo_task_exit\n    #else\n    jmp tinygo_task_exit\n    #endif\n    .cfi_endproc\n\n#ifdef __MACH__ // Darwin\n.global _tinygo_swapTask\n_tinygo_swapTask:\n#else // Linux etc\n.global tinygo_swapTask\n.section .text.tinygo_swapTask\ntinygo_swapTask:\n#endif\n    // This function gets the following parameters:\n    // %rdi = newStack uintptr\n    // %rsi = oldStack *uintptr\n\n    // Save all callee-saved registers:\n    pushq %r15\n    pushq %r14\n    pushq %r13\n    pushq %r12\n    pushq %rbp\n    pushq %rbx\n\n    // Save the current stack pointer in oldStack.\n    movq %rsp, (%rsi)\n\n    // Switch to the new stack pointer.\n    movq %rdi, %rsp\n\n    // Load saved register from the new stack.\n    popq %rbx\n    popq %rbp\n    popq %r12\n    popq %r13\n    popq %r14\n    popq %r15\n\n    // Return into the new task, as if tinygo_swapTask was a regular call.\n    ret\n\n#ifdef __MACH__ // Darwin\n// allow these symbols to stripped as dead code\n.subsections_via_symbols\n#endif\n"
  },
  {
    "path": "src/internal/task/task_stack_amd64.go",
    "content": "//go:build scheduler.tasks && amd64 && !windows\n\npackage task\n\nimport \"unsafe\"\n\nvar systemStack uintptr\n\n// calleeSavedRegs is the list of registers that must be saved and restored when\n// switching between tasks. Also see task_stack_amd64.S that relies on the exact\n// layout of this struct.\ntype calleeSavedRegs struct {\n\trbx uintptr\n\trbp uintptr\n\tr12 uintptr\n\tr13 uintptr\n\tr14 uintptr\n\tr15 uintptr\n\n\tpc uintptr\n}\n\n// archInit runs architecture-specific setup for the goroutine startup.\nfunc (s *state) archInit(r *calleeSavedRegs, fn uintptr, args unsafe.Pointer) {\n\t// Store the initial sp for the startTask function (implemented in assembly).\n\ts.sp = uintptr(unsafe.Pointer(r))\n\n\t// Initialize the registers.\n\t// These will be popped off of the stack on the first resume of the goroutine.\n\n\t// Start the function at tinygo_startTask (defined in\n\t// src/internal/task/task_stack_amd64.S). This assembly code calls a\n\t// function (passed in r12) with a single argument (passed in r13). After\n\t// the function returns, it calls Pause().\n\tr.pc = uintptr(unsafe.Pointer(&startTask))\n\n\t// Pass the function to call in r12.\n\t// This function is a compiler-generated wrapper which loads arguments out\n\t// of a struct pointer. See createGoroutineStartWrapper (defined in\n\t// compiler/goroutine.go) for more information.\n\tr.r12 = fn\n\n\t// Pass the pointer to the arguments struct in r13.\n\tr.r13 = uintptr(args)\n}\n\nfunc (s *state) resume() {\n\tswapTask(s.sp, &systemStack)\n}\n\nfunc (s *state) pause() {\n\tnewStack := systemStack\n\tsystemStack = 0\n\tswapTask(newStack, &s.sp)\n}\n\n// SystemStack returns the system stack pointer when called from a task stack.\n// When called from the system stack, it returns 0.\nfunc SystemStack() uintptr {\n\treturn systemStack\n}\n"
  },
  {
    "path": "src/internal/task/task_stack_amd64_windows.S",
    "content": "// Windows on amd64 has a slightly different ABI than other (*nix) systems.\n// Therefore, assembly functions need to be tweaked slightly.\n//\n// The calling convention is described here:\n// https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170\n\n.section .text.tinygo_startTask,\"ax\"\n.global  tinygo_startTask\ntinygo_startTask:\n    // Small assembly stub for starting a goroutine. This is already run on the\n    // new stack, with the callee-saved registers already loaded.\n    // Most importantly, r12 contain the pc of the to-be-started function and\n    // r13 contain the only argument it is given. Multiple arguments are packed\n    // into one by storing them in a new allocation.\n\n    // Set the first argument of the goroutine start wrapper, which contains all\n    // the arguments.\n    movq %r13, %rcx\n\n    // Branch to the \"goroutine start\" function.\n    callq *%r12\n\n    // After return, exit this goroutine.\n    // This has to be a call, not a jump, to keep the stack correctly aligned.\n    callq tinygo_task_exit\n\n.global tinygo_swapTask\n.section .text.tinygo_swapTask,\"ax\"\ntinygo_swapTask:\n    // This function gets the following parameters:\n    // %rcx = newStack uintptr\n    // %rdx = oldStack *uintptr\n\n    // Save all callee-saved registers:\n    pushq %r15\n    pushq %r14\n    pushq %r13\n    pushq %r12\n    pushq %rsi\n    pushq %rdi\n    pushq %rbp\n    sub   $160, %rsp\n    movaps  %xmm6, 144(%rsp)\n    movaps  %xmm7, 128(%rsp)\n    movaps  %xmm8, 112(%rsp)\n    movaps  %xmm9,  96(%rsp)\n    movaps  %xmm10, 80(%rsp)\n    movaps  %xmm11, 64(%rsp)\n    movaps  %xmm12, 48(%rsp)\n    movaps  %xmm13, 32(%rsp)\n    movaps  %xmm14, 16(%rsp)\n    movaps  %xmm15,  0(%rsp)\n    pushq %rbx\n\n    // Save the current stack pointer in oldStack.\n    movq %rsp, (%rdx)\n\n    // Switch to the new stack pointer.\n    movq %rcx, %rsp\n\n    // Load saved register from the new stack.\n    popq %rbx\n    movaps 0(%rsp),   %xmm15\n    movaps 16(%rsp),  %xmm14\n    movaps 32(%rsp),  %xmm13\n    movaps 48(%rsp),  %xmm12\n    movaps 64(%rsp),  %xmm11\n    movaps 80(%rsp),  %xmm10\n    movaps 96(%rsp),  %xmm9\n    movaps 112(%rsp), %xmm8\n    movaps 128(%rsp), %xmm7\n    movaps 144(%rsp), %xmm6\n    add   $160, %rsp\n    popq %rbp\n    popq %rdi\n    popq %rsi\n    popq %r12\n    popq %r13\n    popq %r14\n    popq %r15\n\n    // Return into the new task, as if tinygo_swapTask was a regular call.\n    ret\n"
  },
  {
    "path": "src/internal/task/task_stack_amd64_windows.go",
    "content": "//go:build scheduler.tasks && amd64 && windows\n\npackage task\n\n// This is almost the same as task_stack_amd64.go, but with the extra rdi and\n// rsi registers saved: Windows has a slightly different calling convention.\n\nimport \"unsafe\"\n\nvar systemStack uintptr\n\n// calleeSavedRegs is the list of registers that must be saved and restored when\n// switching between tasks. Also see task_stack_amd64_windows.S that relies on\n// the exact layout of this struct.\n// The calling convention is described here:\n// https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170\n// Most importantly, these are the registers we need to save/restore:\n//\n// > The x64 ABI considers registers RBX, RBP, RDI, RSI, RSP, R12, R13, R14,\n// > R15, and XMM6-XMM15 nonvolatile. They must be saved and restored by a\n// > function that uses them.\ntype calleeSavedRegs struct {\n\t// Note: rbx is placed here so that the stack is correctly aligned when\n\t// loading/storing the xmm registers.\n\trbx   uintptr\n\txmm15 [2]uint64\n\txmm14 [2]uint64\n\txmm13 [2]uint64\n\txmm12 [2]uint64\n\txmm11 [2]uint64\n\txmm10 [2]uint64\n\txmm9  [2]uint64\n\txmm8  [2]uint64\n\txmm7  [2]uint64\n\txmm6  [2]uint64\n\trbp   uintptr\n\trdi   uintptr\n\trsi   uintptr\n\tr12   uintptr\n\tr13   uintptr\n\tr14   uintptr\n\tr15   uintptr\n\n\tpc uintptr\n}\n\n// archInit runs architecture-specific setup for the goroutine startup.\nfunc (s *state) archInit(r *calleeSavedRegs, fn uintptr, args unsafe.Pointer) {\n\t// Store the initial sp for the startTask function (implemented in assembly).\n\ts.sp = uintptr(unsafe.Pointer(r))\n\n\t// Initialize the registers.\n\t// These will be popped off of the stack on the first resume of the goroutine.\n\n\t// Start the function at tinygo_startTask (defined in\n\t// src/internal/task/task_stack_amd64_windows.S). This assembly code calls a\n\t// function (passed in r12) with a single argument (passed in r13). After\n\t// the function returns, it calls Pause().\n\tr.pc = uintptr(unsafe.Pointer(&startTask))\n\n\t// Pass the function to call in r12.\n\t// This function is a compiler-generated wrapper which loads arguments out\n\t// of a struct pointer. See createGoroutineStartWrapper (defined in\n\t// compiler/goroutine.go) for more information.\n\tr.r12 = fn\n\n\t// Pass the pointer to the arguments struct in r13.\n\tr.r13 = uintptr(args)\n}\n\nfunc (s *state) resume() {\n\tswapTask(s.sp, &systemStack)\n}\n\nfunc (s *state) pause() {\n\tnewStack := systemStack\n\tsystemStack = 0\n\tswapTask(newStack, &s.sp)\n}\n\n// SystemStack returns the system stack pointer when called from a task stack.\n// When called from the system stack, it returns 0.\nfunc SystemStack() uintptr {\n\treturn systemStack\n}\n"
  },
  {
    "path": "src/internal/task/task_stack_arm.S",
    "content": "//go:build tinygo\n\n// Only generate .debug_frame, don't generate .eh_frame.\n.cfi_sections .debug_frame\n\n.section .text.tinygo_startTask\n.global  tinygo_startTask\n.type    tinygo_startTask, %function\ntinygo_startTask:\n    .cfi_startproc\n    // Small assembly stub for starting a goroutine. This is already run on the\n    // new stack, with the callee-saved registers already loaded.\n    // Most importantly, r4 contains the pc of the to-be-started function and r5\n    // contains the only argument it is given. Multiple arguments are packed\n    // into one by storing them in a new allocation.\n\n    // Indicate to the unwinder that there is nothing to unwind, this is the\n    // root frame. It avoids the following (bogus) error message in GDB:\n    //     Backtrace stopped: previous frame identical to this frame (corrupt stack?)\n    .cfi_undefined lr\n\n    // Set the first argument of the goroutine start wrapper, which contains all\n    // the arguments.\n    mov   r0, r5\n\n    // Branch to the \"goroutine start\" function. By using blx instead of bx,\n    // we'll return here instead of tail calling.\n    blx   r4\n\n    // After return, exit this goroutine. This is a tail call.\n    bl    tinygo_task_exit\n    .cfi_endproc\n.size tinygo_startTask, .-tinygo_startTask\n\n.global tinygo_swapTask\n.type tinygo_swapTask, %function\ntinygo_swapTask:\n    // This function gets the following parameters:\n    // r0 = newStack uintptr\n    // r1 = oldStack *uintptr\n\n    // Save all callee-saved registers:\n    push {r4-r11, lr}\n\n    // Save the current stack pointer in oldStack.\n    str sp, [r1]\n\n    // Switch to the new stack pointer.\n    mov sp, r0\n\n    // Load state from new task and branch to the previous position in the\n    // program.\n    pop {r4-r11, pc}\n"
  },
  {
    "path": "src/internal/task/task_stack_arm.go",
    "content": "//go:build scheduler.tasks && arm && !cortexm && !avr && !xtensa && !tinygo.riscv\n\npackage task\n\nimport \"unsafe\"\n\nvar systemStack uintptr\n\n// calleeSavedRegs is the list of registers that must be saved and restored when\n// switching between tasks. Also see task_stack_arm.S that relies on the exact\n// layout of this struct.\ntype calleeSavedRegs struct {\n\tr4  uintptr\n\tr5  uintptr\n\tr6  uintptr\n\tr7  uintptr\n\tr8  uintptr\n\tr9  uintptr\n\tr10 uintptr\n\tr11 uintptr\n\n\tpc uintptr\n}\n\n// archInit runs architecture-specific setup for the goroutine startup.\nfunc (s *state) archInit(r *calleeSavedRegs, fn uintptr, args unsafe.Pointer) {\n\t// Store the initial sp for the startTask function (implemented in assembly).\n\ts.sp = uintptr(unsafe.Pointer(r))\n\n\t// Initialize the registers.\n\t// These will be popped off of the stack on the first resume of the goroutine.\n\n\t// Start the function at tinygo_startTask (defined in src/internal/task/task_stack_arm.S).\n\t// This assembly code calls a function (passed in r4) with a single argument\n\t// (passed in r5). After the function returns, it calls Pause().\n\tr.pc = uintptr(unsafe.Pointer(&startTask))\n\n\t// Pass the function to call in r4.\n\t// This function is a compiler-generated wrapper which loads arguments out of a struct pointer.\n\t// See createGoroutineStartWrapper (defined in compiler/goroutine.go) for more information.\n\tr.r4 = fn\n\n\t// Pass the pointer to the arguments struct in r5.\n\tr.r5 = uintptr(args)\n}\n\nfunc (s *state) resume() {\n\tswapTask(s.sp, &systemStack)\n}\n\nfunc (s *state) pause() {\n\tnewStack := systemStack\n\tsystemStack = 0\n\tswapTask(newStack, &s.sp)\n}\n\n// SystemStack returns the system stack pointer when called from a task stack.\n// When called from the system stack, it returns 0.\nfunc SystemStack() uintptr {\n\treturn systemStack\n}\n"
  },
  {
    "path": "src/internal/task/task_stack_arm64.S",
    "content": "#ifdef __MACH__\n.global  _tinygo_startTask\n_tinygo_startTask:\n#else\n.global  tinygo_startTask\ntinygo_startTask:\n#endif\n    .cfi_startproc\n    // Small assembly stub for starting a goroutine. This is already run on the\n    // new stack, with the callee-saved registers already loaded.\n    // Most importantly, x19 contains the pc of the to-be-started function and\n    // x20 contains the only argument it is given. Multiple arguments are packed\n    // into one by storing them in a new allocation.\n\n    // Indicate to the unwinder that there is nothing to unwind, this is the\n    // root frame. It avoids the following (bogus) error message in GDB:\n    //     Backtrace stopped: previous frame identical to this frame (corrupt stack?)\n    .cfi_undefined lr\n\n    // Set the first argument of the goroutine start wrapper, which contains all\n    // the arguments.\n    mov   x0, x20\n\n    // Branch to the \"goroutine start\" function. By using blx instead of bx,\n    // we'll return here instead of tail calling.\n    blr   x19\n\n    // After return, exit this goroutine. This is a tail call.\n#ifdef __MACH__\n    b     _tinygo_task_exit\n#else\n    b     tinygo_task_exit\n#endif\n    .cfi_endproc\n#ifndef __MACH__\n#endif\n\n\n#ifdef __MACH__\n.global _tinygo_swapTask\n_tinygo_swapTask:\n#else\n.global tinygo_swapTask\ntinygo_swapTask:\n#endif\n    // This function gets the following parameters:\n    // x0 = newStack uintptr\n    // x1 = oldStack *uintptr\n\n    // Save all callee-saved registers:\n    stp     x19, x20, [sp, #-160]!\n    stp     x21, x22, [sp, #16]\n    stp     x23, x24, [sp, #32]\n    stp     x25, x26, [sp, #48]\n    stp     x27, x28, [sp, #64]\n    stp     x29, x30, [sp, #80]\n    stp     d8,  d9,  [sp, #96]\n    stp     d10, d11, [sp, #112]\n    stp     d12, d13, [sp, #128]\n    stp     d14, d15, [sp, #144]\n\n    // Save the current stack pointer in oldStack.\n    mov x8, sp\n    str x8, [x1]\n\n    // Switch to the new stack pointer.\n    mov sp, x0\n\n    // Restore stack state and return.\n    ldp     d14, d15, [sp, #144]\n    ldp     d12, d13, [sp, #128]\n    ldp     d10, d11, [sp, #112]\n    ldp     d8, d9, [sp, #96]\n    ldp     x29, x30, [sp, #80]\n    ldp     x27, x28, [sp, #64]\n    ldp     x25, x26, [sp, #48]\n    ldp     x23, x24, [sp, #32]\n    ldp     x21, x22, [sp, #16]\n    ldp     x19, x20, [sp], #160\n    ret\n"
  },
  {
    "path": "src/internal/task/task_stack_arm64.go",
    "content": "//go:build scheduler.tasks && arm64\n\npackage task\n\nimport \"unsafe\"\n\nvar systemStack uintptr\n\n// calleeSavedRegs is the list of registers that must be saved and restored when\n// switching between tasks. Also see task_stack_arm64.S that relies on the exact\n// layout of this struct.\ntype calleeSavedRegs struct {\n\tx19 uintptr\n\tx20 uintptr\n\tx21 uintptr\n\tx22 uintptr\n\tx23 uintptr\n\tx24 uintptr\n\tx25 uintptr\n\tx26 uintptr\n\tx27 uintptr\n\tx28 uintptr\n\tx29 uintptr\n\tpc  uintptr // aka x30 aka LR\n\n\td8  uintptr\n\td9  uintptr\n\td10 uintptr\n\td11 uintptr\n\td12 uintptr\n\td13 uintptr\n\td14 uintptr\n\td15 uintptr\n}\n\n// archInit runs architecture-specific setup for the goroutine startup.\nfunc (s *state) archInit(r *calleeSavedRegs, fn uintptr, args unsafe.Pointer) {\n\t// Store the initial sp for the startTask function (implemented in assembly).\n\ts.sp = uintptr(unsafe.Pointer(r))\n\n\t// Initialize the registers.\n\t// These will be popped off of the stack on the first resume of the goroutine.\n\n\t// Start the function at tinygo_startTask (defined in src/internal/task/task_stack_arm64.S).\n\t// This assembly code calls a function (passed in x19) with a single argument\n\t// (passed in x20). After the function returns, it calls Pause().\n\tr.pc = uintptr(unsafe.Pointer(&startTask))\n\n\t// Pass the function to call in x19.\n\t// This function is a compiler-generated wrapper which loads arguments out of a struct pointer.\n\t// See createGoroutineStartWrapper (defined in compiler/goroutine.go) for more information.\n\tr.x19 = fn\n\n\t// Pass the pointer to the arguments struct in x20.\n\tr.x20 = uintptr(args)\n}\n\nfunc (s *state) resume() {\n\tswapTask(s.sp, &systemStack)\n}\n\nfunc (s *state) pause() {\n\tnewStack := systemStack\n\tsystemStack = 0\n\tswapTask(newStack, &s.sp)\n}\n\n// SystemStack returns the system stack pointer when called from a task stack.\n// When called from the system stack, it returns 0.\nfunc SystemStack() uintptr {\n\treturn systemStack\n}\n"
  },
  {
    "path": "src/internal/task/task_stack_avr.S",
    "content": "//go:build tinygo\n\n.section .bss.tinygo_systemStack\n.global tinygo_systemStack\n.type   tinygo_systemStack, %object\ntinygo_systemStack:\n    .short 0\n\n.section .text.tinygo_startTask\n.global  tinygo_startTask\n.type    tinygo_startTask, %function\ntinygo_startTask:\n    // Small assembly stub for starting a goroutine. This is already run on the\n    // new stack, with the callee-saved registers already loaded.\n    // Most importantly, r2r3 contain the pc of the to-be-started function and\n    // r4r5 contain the only argument it is given. Multiple arguments are packed\n    // into one by storing them in a new allocation.\n\n    // Set the first argument of the goroutine start wrapper, which contains all\n    // the arguments.\n    movw  r24, r4\n\n    // Branch to the \"goroutine start\" function. Note that the Z register is\n    // call-clobbered, so does not need to be restored after use.\n    movw  Z, r2\n    icall\n\n    // After return, exit this goroutine. This is a tail call.\n#if __AVR_ARCH__ == 2 || __AVR_ARCH__ == 25\n    // Small memory devices (≤8kB flash) that do not have the long call\n    // instruction available will need to use rcall instead.\n    // Note that they will probably not be able to run more than the main\n    // goroutine anyway, but this file is compiled for all AVRs so it needs to\n    // compile at least.\n    rcall  tinygo_task_exit\n#else\n    // Other devices can (and must) use the regular call instruction.\n    call tinygo_task_exit\n#endif\n\n.global tinygo_swapTask\n.type tinygo_swapTask, %function\ntinygo_swapTask:\n    // This function gets the following parameters:\n    // r24:r25 = newStack uintptr\n    // r22:r23 = oldStack *uintptr\n\n    // Save all call-saved registers:\n    // https://gcc.gnu.org/wiki/avr-gcc#Call-Saved_Registers\n    push r29 // Y\n    push r28 // Y\n    push r17\n    push r16\n    push r15\n    push r14\n    push r13\n    push r12\n    push r11\n    push r10\n    push r9\n    push r8\n    push r7\n    push r6\n    push r5\n    push r4\n    push r3\n    push r2\n\n    // Save the current stack pointer in oldStack.\n    in  r2, 0x3d; SPL\n    in  r3, 0x3e; SPH\n    movw Y, r22\n    std Y+0, r2\n    std Y+1, r3\n\n    // Switch to the new stack pointer.\n    in   r0, 0x3f ; SREG\n    cli\n    out  0x3d, r24; SPL\n    out  0x3f, r0 ; SREG, restore interrupts (after the next instruction)\n    out  0x3e, r25; SPH\n\n    // Load saved register from the new stack.\n    pop r2\n    pop r3\n    pop r4\n    pop r5\n    pop r6\n    pop r7\n    pop r8\n    pop r9\n    pop r10\n    pop r11\n    pop r12\n    pop r13\n    pop r14\n    pop r15\n    pop r16\n    pop r17\n    pop r28 // Y\n    pop r29 // Y\n\n    // Return into the new task, as if tinygo_swapTask was a regular call.\n    ret\n"
  },
  {
    "path": "src/internal/task/task_stack_avr.go",
    "content": "//go:build scheduler.tasks && avr\n\npackage task\n\nimport \"unsafe\"\n\n//go:extern tinygo_systemStack\nvar systemStack uintptr\n\n// calleeSavedRegs is the list of registers that must be saved and restored when\n// switching between tasks. Also see task_stack_avr.S that relies on the exact\n// layout of this struct.\n//\n// https://gcc.gnu.org/wiki/avr-gcc#Call-Saved_Registers\ntype calleeSavedRegs struct {\n\tr2r3   uintptr\n\tr4r5   uintptr\n\tr6r7   uintptr\n\tr8r9   uintptr\n\tr10r11 uintptr\n\tr12r13 uintptr\n\tr14r15 uintptr\n\tr16r17 uintptr\n\tr28r29 uintptr // Y register\n\n\tpc uintptr\n}\n\n// archInit runs architecture-specific setup for the goroutine startup.\n// Note: adding //go:noinline to work around an AVR backend bug.\n//\n//go:noinline\nfunc (s *state) archInit(r *calleeSavedRegs, fn uintptr, args unsafe.Pointer) {\n\t// Store the initial sp for the startTask function (implemented in assembly).\n\ts.sp = uintptr(unsafe.Pointer(r)) - 1\n\n\t// Initialize the registers.\n\t// These will be popped off of the stack on the first resume of the goroutine.\n\n\t// Start the function at tinygo_startTask.\n\tstartTask := uintptr(unsafe.Pointer(&startTask))\n\tr.pc = startTask/2>>8 | startTask/2<<8\n\n\t// Pass the function to call in r2:r3.\n\t// This function is a compiler-generated wrapper which loads arguments out\n\t// of a struct pointer. See createGoroutineStartWrapper (defined in\n\t// compiler/goroutine.go) for more information.\n\tr.r2r3 = fn\n\n\t// Pass the pointer to the arguments struct in r4:45.\n\tr.r4r5 = uintptr(args)\n}\n\nfunc (s *state) resume() {\n\tswapTask(s.sp, &systemStack)\n}\n\nfunc (s *state) pause() {\n\tnewStack := systemStack\n\tsystemStack = 0\n\tswapTask(newStack, &s.sp)\n}\n\n// SystemStack returns the system stack pointer when called from a task stack.\n// When called from the system stack, it returns 0.\nfunc SystemStack() uintptr {\n\treturn systemStack\n}\n"
  },
  {
    "path": "src/internal/task/task_stack_cortexm.S",
    "content": "//go:build tinygo\n\n// Only generate .debug_frame, don't generate .eh_frame.\n.cfi_sections .debug_frame\n\n.section .text.tinygo_startTask\n.global  tinygo_startTask\n.type    tinygo_startTask, %function\ntinygo_startTask:\n    .cfi_startproc\n    // Small assembly stub for starting a goroutine. This is already run on the\n    // new stack, with the callee-saved registers already loaded.\n    // Most importantly, r4 contains the pc of the to-be-started function and r5\n    // contains the only argument it is given. Multiple arguments are packed\n    // into one by storing them in a new allocation.\n\n    // Indicate to the unwinder that there is nothing to unwind, this is the\n    // root frame. It avoids the following (bogus) error message in GDB:\n    //     Backtrace stopped: previous frame identical to this frame (corrupt stack?)\n    .cfi_undefined lr\n\n    // Set the first argument of the goroutine start wrapper, which contains all\n    // the arguments.\n    mov   r0, r5\n\n    // Branch to the \"goroutine start\" function. By using blx instead of bx,\n    // we'll return here instead of tail calling.\n    blx   r4\n\n    // After return, exit this goroutine. This is a tail call.\n    bl    \ttinygo_task_exit\n    .cfi_endproc\n.size tinygo_startTask, .-tinygo_startTask\n\n.section .text.tinygo_switchToScheduler\n.global  tinygo_switchToScheduler\n.type    tinygo_switchToScheduler, %function\ntinygo_switchToScheduler:\n    .cfi_startproc\n    // r0 = sp *uintptr\n\n    // Currently on the task stack (SP=PSP). We need to store the position on\n    // the stack where the in-use registers will be stored.\n    mov r1, sp\n    subs r1, #36\n    str r1, [r0]\n\n    b tinygo_swapTask\n    .cfi_endproc\n.size tinygo_switchToScheduler, .-tinygo_switchToScheduler\n\n.section .text.tinygo_switchToTask\n.global  tinygo_switchToTask\n.type    tinygo_switchToTask, %function\ntinygo_switchToTask:\n    .cfi_startproc\n    // r0 = sp uintptr\n\n    // Currently on the scheduler stack (SP=MSP). We'll have to update the PSP,\n    // and then we can invoke swapTask.\n    msr PSP, r0\n\n    b.n tinygo_swapTask\n    .cfi_endproc\n.size tinygo_switchToTask, .-tinygo_switchToTask\n\n.section .text.tinygo_swapTask\n.global  tinygo_swapTask\n.type    tinygo_swapTask, %function\ntinygo_swapTask:\n    .cfi_startproc\n    // This function stores the current register state to the stack, switches to\n    // the other stack (MSP/PSP), and loads the register state from the other\n    // stack. Apart from saving and restoring all relevant callee-saved\n    // registers, it also ends with branching to the last program counter (saved\n    // as the lr register, to follow the ARM calling convention).\n\n    // On pre-Thumb2 CPUs (Cortex-M0 in particular), registers r8-r15 cannot be\n    // used directly. Only very few operations work on them, such as mov. That's\n    // why the higher register values are first stored in the temporary register\n    // r3 when loading/storing them.\n    // It is possible to reduce the swapTask by two instructions (~2 cycles) on\n    // Cortex-M0 by reordering the layout of the pushed registers from {r4-r11,\n    // lr} to {r8-r11, r4-r8, lr}. However, that also requires a change on the\n    // Go side (depending on thumb1/thumb2!) and so is not really worth the\n    // complexity.\n\n    // Store state to old task. It saves the lr instead of the pc, because that\n    // will be the pc after returning back to the old task (in a different\n    // invocation of swapTask).\n    #if defined(__thumb2__)\n    push {r4-r11, lr}\n    .cfi_def_cfa_offset 9*4\n    #else\n    mov r0, r8\n    mov r1, r9\n    mov r2, r10\n    mov r3, r11\n    push {r0-r3, lr}\n    .cfi_def_cfa_offset 5*4\n    push {r4-r7}\n    .cfi_def_cfa_offset 9*4\n    #endif\n\n    // Switch the stack. This could either switch from PSP to MSP, or from MSP\n    // to PSP. By using an XOR (eor), it will just switch to the other stack.\n    mrs  r0, CONTROL // load CONTROL register\n    movs r3, #2\n    eors r0, r0, r3  // flip the SPSEL (active stack pointer) bit\n    msr  CONTROL, r0 // store CONTROL register\n    isb              // required to flush the pipeline\n\n    // Load state from new task and branch to the previous position in the\n    // program.\n    #if defined(__thumb2__)\n    pop {r4-r11, pc}\n    #else\n    pop {r4-r7}\n    .cfi_def_cfa_offset 5*4\n    pop {r0-r3}\n    .cfi_def_cfa_offset 1*4\n    mov r8, r0\n    mov r9, r1\n    mov r10, r2\n    mov r11, r3\n    pop {pc}\n    #endif\n    .cfi_endproc\n.size tinygo_swapTask, .-tinygo_swapTask\n"
  },
  {
    "path": "src/internal/task/task_stack_cortexm.c",
    "content": "//go:build (scheduler.tasks || scheduler.cores) && cortexm\n#include <stdint.h>\n\nuintptr_t SystemStack() {\n    uintptr_t sp;\n    asm volatile(\n        \"mrs %0, MSP\"\n        : \"=r\"(sp)\n        :\n        : \"memory\"\n    );\n    return sp;\n}\n"
  },
  {
    "path": "src/internal/task/task_stack_cortexm.go",
    "content": "//go:build (scheduler.tasks || scheduler.cores) && cortexm\n\npackage task\n\n// Note that this is almost the same as task_stack_arm.go, but it uses the MSP\n// register to store the system stack pointer instead of a global variable. The\n// big advantage of this is that interrupts always execute with MSP (and not\n// PSP, which is used for goroutines) so that goroutines do not need extra stack\n// space for interrupts.\n\nimport \"C\"\nimport (\n\t\"unsafe\"\n)\n\n// calleeSavedRegs is the list of registers that must be saved and restored when\n// switching between tasks. Also see task_stack_cortexm.S that relies on the\n// exact layout of this struct.\ntype calleeSavedRegs struct {\n\tr4  uintptr\n\tr5  uintptr\n\tr6  uintptr\n\tr7  uintptr\n\tr8  uintptr\n\tr9  uintptr\n\tr10 uintptr\n\tr11 uintptr\n\n\tpc uintptr\n}\n\n// archInit runs architecture-specific setup for the goroutine startup.\nfunc (s *state) archInit(r *calleeSavedRegs, fn uintptr, args unsafe.Pointer) {\n\t// Store the initial sp for the startTask function (implemented in assembly).\n\ts.sp = uintptr(unsafe.Pointer(r))\n\n\t// Initialize the registers.\n\t// These will be popped off of the stack on the first resume of the goroutine.\n\n\t// Start the function at tinygo_startTask (defined in src/internal/task/task_stack_cortexm.S).\n\t// This assembly code calls a function (passed in r4) with a single argument (passed in r5).\n\t// After the function returns, it calls Pause().\n\tr.pc = uintptr(unsafe.Pointer(&startTask))\n\n\t// Pass the function to call in r4.\n\t// This function is a compiler-generated wrapper which loads arguments out of a struct pointer.\n\t// See createGoroutineStartWrapper (defined in compiler/goroutine.go) for more information.\n\tr.r4 = fn\n\n\t// Pass the pointer to the arguments struct in r5.\n\tr.r5 = uintptr(args)\n}\n\nfunc (s *state) resume() {\n\ttinygo_switchToTask(s.sp)\n}\n\n//export tinygo_switchToTask\nfunc tinygo_switchToTask(uintptr)\n\n//export tinygo_switchToScheduler\nfunc tinygo_switchToScheduler(*uintptr)\n\nfunc (s *state) pause() {\n\ttinygo_switchToScheduler(&s.sp)\n}\n\n// SystemStack returns the system stack pointer. On Cortex-M, it is always\n// available.\n//\n//export SystemStack\nfunc SystemStack() uintptr\n"
  },
  {
    "path": "src/internal/task/task_stack_esp32.S",
    "content": "//go:build tinygo\n\n.section .text.tinygo_startTask,\"ax\",@progbits\n.global  tinygo_startTask\n.type    tinygo_startTask, %function\ntinygo_startTask:\n    // Small assembly stub for starting a goroutine. This already runs on the\n    // new stack, control reaches this function after returning from the initial\n    // tinygo_swapTask below (the retw.n instruction).\n    //\n    // The stack was set up in such a way that it looks as if this function was\n    // paused using tinygo_swapTask by setting up the parent register window and\n    // return pointer as a call4 instruction - except such a call never took\n    // place. Instead, the stack pointer is switched to the new stack after all\n    // live-but-invisible registers have been flushed to the stack. This means\n    // that all registers as present in tinygo_swapTask are moved four up (a2 in\n    // tinygo_swapTask is a6 in this function). We don't use any of those\n    // registers however. Instead, the retw.n instruction will load them through\n    // an underflow exception from the stack which means we get a0-a3 as defined\n    // in task_stack_esp32.go.\n\n    // Branch to the \"goroutine start\" function. The first (and only) parameter\n    // is stored in a2, but has to be moved to a6 to make it appear as a2 in the\n    // goroutine start function (due to changing the register window by four\n    // with callx4).\n    mov.n a6, a2\n    callx4 a3\n\n    // After return, exit this goroutine. This call never returns.\n    call4  tinygo_task_exit\n\n.section .text.tinygo_swapTask,\"ax\",@progbits\n.global tinygo_swapTask\n.type tinygo_swapTask, %function\ntinygo_swapTask:\n    // This function gets the following parameters:\n    // a2 = newStack uintptr\n    // a3 = oldStack *uintptr\n\n    // Reserve 32 bytes on the stack. It really needs to be 32 bytes, with 16\n    // extra at the bottom to adhere to the ABI.\n    entry sp, 32\n\n    // Disable interrupts while flushing registers. This is necessary because\n    // interrupts might want to use the stack pointer (at a2) which will be some\n    // arbitrary register while registers are flushed.\n    rsil a4, 3 // XCHAL_EXCM_LEVEL\n\n    // Flush all unsaved registers to the stack.\n    // This trick has been borrowed from the Zephyr project:\n    // https://github.com/zephyrproject-rtos/zephyr/blob/d79b003758/arch/xtensa/include/xtensa-asm2-s.h#L17\n    and a12, a12, a12\n    rotw 3\n    and a12, a12, a12\n    rotw 3\n    and a12, a12, a12\n    rotw 3\n    and a12, a12, a12\n    rotw 3\n    and a12, a12, a12\n    rotw 4\n\n    // Restore interrupts.\n    wsr.ps a4\n\n    // At this point, the following is true:\n    //     WindowStart == 1 << WindowBase\n    // Therefore, we don't need to do this manually.\n    // It also means that the stack pointer can now be safely modified.\n\n    // Save a0, which stores the return address and the parent register window\n    // in the upper two bits.\n    s32i.n a0, sp, 0\n\n    // Save the current stack pointer in oldStack.\n    s32i.n  sp, a3, 0\n\n    // Switch to the new stack pointer (newStack).\n    mov.n   sp, a2\n\n    // Load a0, which is the previous return address from before the previous\n    // switch or the constructed return address to tinygo_startTask. This\n    // register also stores the parent register window.\n    l32i.n a0, sp, 0\n\n    // Return into the new stack. This instruction will trigger a window\n    // underflow, reloading the saved registers from the stack.\n    retw.n\n"
  },
  {
    "path": "src/internal/task/task_stack_esp32.go",
    "content": "//go:build scheduler.tasks && (esp32 || esp32s3)\n\npackage task\n\n// The windowed ABI (used on the ESP32) is as follows:\n//   a0:    return address (link register)\n//   a1:    stack pointer (must be 16-byte aligned)\n//   a2-a7: incoming arguments\n//   a7:    stack frame pointer (optional, normally unused in TinyGo)\n// Sources:\n//   http://cholla.mmto.org/esp8266/xtensa.html\n//   https://0x04.net/~mwk/doc/xtensa.pdf\n\nimport (\n\t\"unsafe\"\n)\n\nvar systemStack uintptr\n\n// calleeSavedRegs is the list of registers that must be saved and restored when\n// switching between tasks. Also see task_stack_esp8266.S that relies on the\n// exact layout of this struct.\ntype calleeSavedRegs struct {\n\t// Registers in the register window of tinygo_startTask.\n\ta0 uintptr\n\ta1 uintptr\n\ta2 uintptr\n\ta3 uintptr\n\n\t// Locals that can be used by tinygo_swapTask.\n\t// The first field is the a0 loaded in tinygo_swapTask, the rest is unused.\n\tlocals [4]uintptr\n}\n\n// archInit runs architecture-specific setup for the goroutine startup.\nfunc (s *state) archInit(r *calleeSavedRegs, fn uintptr, args unsafe.Pointer) {\n\t// Store the stack pointer for the tinygo_swapTask function (implemented in\n\t// assembly). It needs to point to the locals field instead of a0 so that\n\t// the retw.n at the end of tinygo_swapTask will return into\n\t// tinygo_startTask with a0-a3 loaded (using the register window mechanism).\n\ts.sp = uintptr(unsafe.Pointer(&r.locals[0]))\n\n\t// Start the goroutine at tinygo_startTask (defined in\n\t// src/internal/task/task_stack_esp32.S). The topmost two bits are not part\n\t// of the address but instead store the register window of the caller.\n\t// In this case there is no caller, instead we set up the return address as\n\t// if tinygo_startTask called tinygo_swapTask with a call4 instruction.\n\tr.locals[0] = uintptr(unsafe.Pointer(&startTask))&^(3<<30) | (1 << 30)\n\n\t// Set up the stack pointer inside tinygo_startTask.\n\t// Unlike most calling conventions, the windowed ABI actually saves the\n\t// stack pointer on the stack to make register windowing work.\n\tr.a1 = uintptr(unsafe.Pointer(r)) + 32\n\n\t// Store the function pointer and the (only) parameter on the stack in a\n\t// location that will be reloaded into registers when doing the\n\t// pseudo-return to tinygo_startTask using the register window mechanism.\n\tr.a3 = fn\n\tr.a2 = uintptr(args)\n}\n\nfunc (s *state) resume() {\n\tswapTask(s.sp, &systemStack)\n}\n\nfunc (s *state) pause() {\n\tnewStack := systemStack\n\tsystemStack = 0\n\tswapTask(newStack, &s.sp)\n}\n\n// SystemStack returns the system stack pointer when called from a task stack.\n// When called from the system stack, it returns 0.\nfunc SystemStack() uintptr {\n\treturn systemStack\n}\n"
  },
  {
    "path": "src/internal/task/task_stack_esp8266.S",
    "content": "//go:build tinygo\n\n.section .text.tinygo_startTask,\"ax\",@progbits\n.global  tinygo_startTask\n.type    tinygo_startTask, %function\ntinygo_startTask:\n    // Small assembly stub for starting a goroutine. This is already run on the\n    // new stack, with the callee-saved registers already loaded.\n    // Most importantly, r4 contains the pc of the to-be-started function and r5\n    // contains the only argument it is given. Multiple arguments are packed\n    // into one by storing them in a new allocation.\n\n    // Set the first argument of the goroutine start wrapper, which contains all\n    // the arguments.\n    mov.n  a2, a13\n\n    // Branch to the \"goroutine start\" function.\n    callx0 a12\n\n    // After return, exit this goroutine. This is a tail call.\n    call0  tinygo_task_exit\n.size tinygo_startTask, .-tinygo_startTask\n\n.global tinygo_swapTask\n.type tinygo_swapTask, %function\ntinygo_swapTask:\n    // This function gets the following parameters:\n    //   a2 = newStack uintptr\n    //   a3 = oldStack *uintptr\n    // Note:\n    //   a0 is the return address\n    //   a1 is the stack pointer (sp)\n\n    // Save all callee-saved registers:\n    addi    sp,  sp, -20\n    s32i.n  a12, sp, 0\n    s32i.n  a13, sp, 4\n    s32i.n  a14, sp, 8\n    s32i.n  a15, sp, 12\n    s32i.n  a0,  sp, 16\n\n    // Save the current stack pointer in oldStack.\n    s32i.n  sp, a3, 0\n\n    // Switch to the new stack pointer.\n    mov.n   sp, a2\n\n    // Load state from new task and branch to the previous position in the\n    // program.\n    l32i.n  a12, sp, 0\n    l32i.n  a13, sp, 4\n    l32i.n  a14, sp, 8\n    l32i.n  a15, sp, 12\n    l32i.n  a0,  sp, 16\n    addi    sp,  sp, 20\n    ret.n\n"
  },
  {
    "path": "src/internal/task/task_stack_esp8266.go",
    "content": "//go:build scheduler.tasks && esp8266\n\npackage task\n\n// Stack switch implementation for the ESP8266, which does not use the windowed\n// ABI of Xtensa. Registers are assigned as follows:\n//   a0:      return address (link register)\n//   a1:      stack pointer (must be 16-byte aligned)\n//   a2-a7:   incoming arguments\n//   a8:      static chain (unused)\n//   a12-a15: callee-saved\n//   a15:     stack frame pointer (optional, unused)\n// Sources:\n// http://cholla.mmto.org/esp8266/xtensa.html\n// https://0x04.net/~mwk/doc/xtensa.pdf\n\nimport \"unsafe\"\n\nvar systemStack uintptr\n\n// calleeSavedRegs is the list of registers that must be saved and restored when\n// switching between tasks. Also see task_stack_esp8266.S that relies on the\n// exact layout of this struct.\ntype calleeSavedRegs struct {\n\ta12 uintptr\n\ta13 uintptr\n\ta14 uintptr\n\ta15 uintptr\n\n\tpc uintptr // also link register or r0\n}\n\n// archInit runs architecture-specific setup for the goroutine startup.\nfunc (s *state) archInit(r *calleeSavedRegs, fn uintptr, args unsafe.Pointer) {\n\t// Store the initial sp for the startTask function (implemented in assembly).\n\ts.sp = uintptr(unsafe.Pointer(r))\n\n\t// Initialize the registers.\n\t// These will be popped off of the stack on the first resume of the goroutine.\n\n\t// Start the function at tinygo_startTask (defined in\n\t// src/internal/task/task_stack_esp8266.S).\n\t// This assembly code calls a function (passed in a12) with a single argument\n\t// (passed in a13). After the function returns, it calls Pause().\n\tr.pc = uintptr(unsafe.Pointer(&startTask))\n\n\t// Pass the function to call in a12.\n\t// This function is a compiler-generated wrapper which loads arguments out of a struct pointer.\n\t// See createGoroutineStartWrapper (defined in compiler/goroutine.go) for more information.\n\tr.a12 = fn\n\n\t// Pass the pointer to the arguments struct in a13.\n\tr.a13 = uintptr(args)\n}\n\nfunc (s *state) resume() {\n\tswapTask(s.sp, &systemStack)\n}\n\nfunc (s *state) pause() {\n\tnewStack := systemStack\n\tsystemStack = 0\n\tswapTask(newStack, &s.sp)\n}\n\n// SystemStack returns the system stack pointer when called from a task stack.\n// When called from the system stack, it returns 0.\nfunc SystemStack() uintptr {\n\treturn systemStack\n}\n"
  },
  {
    "path": "src/internal/task/task_stack_mipsx.S",
    "content": "// Do not reorder instructions to insert a branch delay slot.\n// We know what we're doing, and will manually fill the branch delay slot.\n.set noreorder\n\n.section .text.tinygo_startTask\n.global  tinygo_startTask\n.type    tinygo_startTask, %function\ntinygo_startTask:\n    // Small assembly stub for starting a goroutine. This is already run on the\n    // new stack, with the callee-saved registers already loaded.\n    // Most importantly, s0 contains the pc of the to-be-started function and s1\n    // contains the only argument it is given. Multiple arguments are packed\n    // into one by storing them in a new allocation.\n\n    // Set the first argument of the goroutine start wrapper, which contains all\n    // the arguments.\n    move  $a0, $s1\n\n    // Branch to the \"goroutine start\" function. Use jalr to write the return\n    // address to ra so we'll return here after the goroutine exits.\n    jalr  $s0\n    nop\n\n    // After return, exit this goroutine. This is a tail call.\n    j     tinygo_task_exit\n    nop\n\n.section .text.tinygo_swapTask\n.global  tinygo_swapTask\n.type    tinygo_swapTask, %function\ntinygo_swapTask:\n    // This function gets the following parameters:\n    //   a0 = newStack uintptr\n    //   a1 = oldStack *uintptr\n\n    // Push all callee-saved registers.\n    addiu $sp, $sp, -40\n    sw $ra, 36($sp)\n    sw $s8, 32($sp)\n    sw $s7, 28($sp)\n    sw $s6, 24($sp)\n    sw $s5, 20($sp)\n    sw $s4, 16($sp)\n    sw $s3, 12($sp)\n    sw $s2,  8($sp)\n    sw $s1,  4($sp)\n    sw $s0,   ($sp)\n\n    // Save the current stack pointer in oldStack.\n    sw $sp, 0($a1)\n\n    // Switch to the new stack pointer.\n    move $sp, $a0\n\n    // Pop all saved registers from this new stack.\n    lw $ra,  36($sp)\n    lw $s8,  32($sp)\n    lw $s7,  28($sp)\n    lw $s6,  24($sp)\n    lw $s5,  20($sp)\n    lw $s4,  16($sp)\n    lw $s3,  12($sp)\n    lw $s2,   8($sp)\n    lw $s1,   4($sp)\n    lw $s0,    ($sp)\n    addiu $sp, $sp, 40\n\n    // Return into the task.\n    jalr $ra\n    nop\n"
  },
  {
    "path": "src/internal/task/task_stack_mipsx.go",
    "content": "//go:build scheduler.tasks && (mips || mipsle)\n\npackage task\n\nimport \"unsafe\"\n\nvar systemStack uintptr\n\n// calleeSavedRegs is the list of registers that must be saved and restored when\n// switching between tasks. Also see task_stack_mips.S that relies on the exact\n// layout of this struct.\ntype calleeSavedRegs struct {\n\ts0 uintptr\n\ts1 uintptr\n\ts2 uintptr\n\ts3 uintptr\n\ts4 uintptr\n\ts5 uintptr\n\ts6 uintptr\n\ts7 uintptr\n\ts8 uintptr\n\tra uintptr\n}\n\n// archInit runs architecture-specific setup for the goroutine startup.\nfunc (s *state) archInit(r *calleeSavedRegs, fn uintptr, args unsafe.Pointer) {\n\t// Store the initial sp for the startTask function (implemented in assembly).\n\ts.sp = uintptr(unsafe.Pointer(r))\n\n\t// Initialize the registers.\n\t// These will be popped off of the stack on the first resume of the goroutine.\n\n\t// Start the function at tinygo_startTask (defined in src/internal/task/task_stack_mipsle.S).\n\t// This assembly code calls a function (passed in s0) with a single argument\n\t// (passed in s1). After the function returns, it calls Pause().\n\tr.ra = uintptr(unsafe.Pointer(&startTask))\n\n\t// Pass the function to call in s0.\n\t// This function is a compiler-generated wrapper which loads arguments out of a struct pointer.\n\t// See createGoroutineStartWrapper (defined in compiler/goroutine.go) for more information.\n\tr.s0 = fn\n\n\t// Pass the pointer to the arguments struct in s1.\n\tr.s1 = uintptr(args)\n}\n\nfunc (s *state) resume() {\n\tswapTask(s.sp, &systemStack)\n}\n\nfunc (s *state) pause() {\n\tnewStack := systemStack\n\tsystemStack = 0\n\tswapTask(newStack, &s.sp)\n}\n\n// SystemStack returns the system stack pointer when called from a task stack.\n// When called from the system stack, it returns 0.\nfunc SystemStack() uintptr {\n\treturn systemStack\n}\n"
  },
  {
    "path": "src/internal/task/task_stack_multicore.go",
    "content": "//go:build scheduler.cores\n\npackage task\n\nimport \"runtime/interrupt\"\n\n// Current returns the current active task.\n//\n//go:linkname Current runtime.currentTask\nfunc Current() *Task\n\n// Pause suspends the current task and returns to the scheduler.\n// This function may only be called when running on a goroutine stack, not when running on the system stack or in an interrupt.\nfunc Pause() {\n\tlockScheduler()\n\tPauseLocked()\n}\n\n// PauseLocked is the same as Pause, but must be called with the scheduler lock\n// already taken.\nfunc PauseLocked() {\n\t// Check whether the canary (the lowest address of the stack) is still\n\t// valid. If it is not, a stack overflow has occurred.\n\tcurrent := Current()\n\tif *current.state.canaryPtr != stackCanary {\n\t\truntimePanic(\"goroutine stack overflow\")\n\t}\n\tif interrupt.In() {\n\t\truntimePanic(\"blocked inside interrupt\")\n\t}\n\tif current.RunState == RunStateResuming {\n\t\t// Another core already marked this goroutine as ready to resume.\n\t\tcurrent.RunState = RunStateRunning\n\t\tunlockScheduler()\n\t\treturn\n\t}\n\tcurrent.RunState = RunStatePaused\n\tcurrent.state.pause()\n}\n\n// Resume the task until it pauses or completes.\n// This may only be called from the scheduler.\nfunc (t *Task) Resume() {\n\tt.gcData.swap()\n\tt.state.resume()\n\tt.gcData.swap()\n}\n\n//go:linkname lockScheduler runtime.lockScheduler\nfunc lockScheduler()\n\n//go:linkname unlockScheduler runtime.unlockScheduler\nfunc unlockScheduler()\n"
  },
  {
    "path": "src/internal/task/task_stack_tinygoriscv.S",
    "content": "//go:build tinygo\n\n.section .text.tinygo_startTask\n.global  tinygo_startTask\n.type    tinygo_startTask, %function\ntinygo_startTask:\n    // Small assembly stub for starting a goroutine. This is already run on the\n    // new stack, with the callee-saved registers already loaded.\n    // Most importantly, s0 contains the pc of the to-be-started function and s1\n    // contains the only argument it is given. Multiple arguments are packed\n    // into one by storing them in a new allocation.\n\n    // Set the first argument of the goroutine start wrapper, which contains all\n    // the arguments.\n    mv    a0, s1\n\n    // Branch to the \"goroutine start\" function. Use jalr to write the return\n    // address to ra so we'll return here after the goroutine exits.\n    jalr  s0\n\n    // After return, exit this goroutine. This is a tail call.\n    tail  tinygo_task_exit\n\n.section .text.tinygo_swapTask\n.global  tinygo_swapTask\n.type    tinygo_swapTask, %function\ntinygo_swapTask:\n    // This function gets the following parameters:\n    //   a0 = newStack uintptr\n    //   a1 = oldStack *uintptr\n\n    // Push all callee-saved registers.\n    addi sp, sp, -52\n    sw ra,  48(sp)\n    sw s11, 44(sp)\n    sw s10, 40(sp)\n    sw s9,  36(sp)\n    sw s8,  32(sp)\n    sw s7,  28(sp)\n    sw s6,  24(sp)\n    sw s5,  20(sp)\n    sw s4,  16(sp)\n    sw s3,  12(sp)\n    sw s2,   8(sp)\n    sw s1,   4(sp)\n    sw s0,    (sp)\n\n    // Save the current stack pointer in oldStack.\n    sw sp,  0(a1)\n\n    // Switch to the new stack pointer.\n    mv sp,  a0\n\n    // Pop all saved registers from this new stack.\n    lw ra,  48(sp)\n    lw s11, 44(sp)\n    lw s10, 40(sp)\n    lw s9,  36(sp)\n    lw s8,  32(sp)\n    lw s7,  28(sp)\n    lw s6,  24(sp)\n    lw s5,  20(sp)\n    lw s4,  16(sp)\n    lw s3,  12(sp)\n    lw s2,   8(sp)\n    lw s1,   4(sp)\n    lw s0,    (sp)\n    addi sp, sp, 52\n\n    // Return into the task.\n    ret\n"
  },
  {
    "path": "src/internal/task/task_stack_tinygoriscv.go",
    "content": "//go:build (scheduler.tasks || scheduler.cores) && tinygo.riscv\n\npackage task\n\nimport \"unsafe\"\n\n// Returns a pointer where the system stack can be stored.\n// This is a layering violation! We should probably refactor this so that we\n// don't need such gymnastics to store the system stack pointer. (It should\n// probably be moved to the runtime).\n//\n//go:linkname runtime_systemStackPtr runtime.systemStackPtr\nfunc runtime_systemStackPtr() *uintptr\n\n// calleeSavedRegs is the list of registers that must be saved and restored when\n// switching between tasks. Also see scheduler_riscv.S that relies on the\n// exact layout of this struct.\ntype calleeSavedRegs struct {\n\ts0  uintptr // x8 (fp)\n\ts1  uintptr // x9\n\ts2  uintptr // x18\n\ts3  uintptr // x19\n\ts4  uintptr // x20\n\ts5  uintptr // x21\n\ts6  uintptr // x22\n\ts7  uintptr // x23\n\ts8  uintptr // x24\n\ts9  uintptr // x25\n\ts10 uintptr // x26\n\ts11 uintptr // x27\n\n\tpc uintptr\n}\n\n// archInit runs architecture-specific setup for the goroutine startup.\nfunc (s *state) archInit(r *calleeSavedRegs, fn uintptr, args unsafe.Pointer) {\n\t// Store the initial sp for the startTask function (implemented in assembly).\n\ts.sp = uintptr(unsafe.Pointer(r))\n\n\t// Initialize the registers.\n\t// These will be popped off of the stack on the first resume of the goroutine.\n\n\t// Start the function at tinygo_startTask (defined in src/internal/task/task_stack_riscv.S).\n\t// This assembly code calls a function (passed in s0) with a single argument\n\t// (passed in s1). After the function returns, it calls Pause().\n\tr.pc = uintptr(unsafe.Pointer(&startTask))\n\n\t// Pass the function to call in s0.\n\t// This function is a compiler-generated wrapper which loads arguments out\n\t// of a struct pointer. See createGoroutineStartWrapper (defined in\n\t// compiler/goroutine.go) for more information.\n\tr.s0 = fn\n\n\t// Pass the pointer to the arguments struct in s1.\n\tr.s1 = uintptr(args)\n}\n\nfunc (s *state) resume() {\n\tswapTask(s.sp, runtime_systemStackPtr())\n}\n\nfunc (s *state) pause() {\n\tsystemStackPtr := runtime_systemStackPtr()\n\tnewStack := *systemStackPtr\n\t*systemStackPtr = 0\n\tswapTask(newStack, &s.sp)\n}\n\n// SystemStack returns the system stack pointer when called from a task stack.\n// When called from the system stack, it returns 0.\nfunc SystemStack() uintptr {\n\treturn *runtime_systemStackPtr()\n}\n"
  },
  {
    "path": "src/internal/task/task_stack_unicore.go",
    "content": "//go:build scheduler.tasks\n\npackage task\n\nimport \"runtime/interrupt\"\n\n// currentTask is the current running task, or nil if currently in the scheduler.\nvar currentTask *Task\n\n// Current returns the current active task.\nfunc Current() *Task {\n\treturn currentTask\n}\n\n// Pause suspends the current task and returns to the scheduler.\n// This function may only be called when running on a goroutine stack, not when running on the system stack or in an interrupt.\nfunc Pause() {\n\t// Check whether the canary (the lowest address of the stack) is still\n\t// valid. If it is not, a stack overflow has occurred.\n\tif *currentTask.state.canaryPtr != stackCanary {\n\t\truntimePanic(\"goroutine stack overflow\")\n\t}\n\tif interrupt.In() {\n\t\truntimePanic(\"blocked inside interrupt\")\n\t}\n\tcurrentTask.state.pause()\n}\n\n// Resume the task until it pauses or completes.\n// This may only be called from the scheduler.\nfunc (t *Task) Resume() {\n\tcurrentTask = t\n\tt.gcData.swap()\n\tt.state.resume()\n\tt.gcData.swap()\n\tcurrentTask = nil\n}\n"
  },
  {
    "path": "src/internal/task/task_threads.c",
    "content": "//go:build none\n\n#define _GNU_SOURCE\n#include <pthread.h>\n#include <signal.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <unistd.h>\n\n#ifdef __linux__\n#include <semaphore.h>\n\n// BDWGC also uses SIGRTMIN+6 on Linux, which seems like a reasonable choice.\n#define taskPauseSignal (SIGRTMIN + 6)\n\n#elif __APPLE__\n#include <dispatch/dispatch.h>\n// SIGIO is for interrupt-driven I/O.\n// I don't think anybody should be using this nowadays, so I think we can\n// repurpose it as a signal for GC.\n// BDWGC uses a special way to pause/resume other threads on MacOS, which may be\n// better but needs more work. Using signal keeps the code similar between Linux\n// and MacOS.\n#define taskPauseSignal SIGIO\n\n#endif // __linux__, __APPLE__\n\n// Pointer to the current task.Task structure.\n// Ideally the entire task.Task structure would be a thread-local variable but\n// this also works.\nstatic __thread void *current_task;\n\nstruct state_pass {\n    void      *(*start)(void*);\n    void      *args;\n    void      *task;\n    uintptr_t *stackTop;\n    #if __APPLE__\n    dispatch_semaphore_t startlock;\n    #else\n    sem_t     startlock;\n    #endif\n};\n\n// Handle the GC pause in Go.\nvoid tinygo_task_gc_pause(int sig);\n\n// Initialize the main thread.\nvoid tinygo_task_init(void *mainTask, pthread_t *thread, int *numCPU, void *context) {\n    // Make sure the current task pointer is set correctly for the main\n    // goroutine as well.\n    current_task = mainTask;\n\n    // Store the thread ID of the main thread.\n    *thread = pthread_self();\n\n    // Register the \"GC pause\" signal for the entire process.\n    // Using pthread_kill, we can still send the signal to a specific thread.\n    struct sigaction act = { 0 };\n    act.sa_handler = tinygo_task_gc_pause;\n    act.sa_flags = SA_RESTART;\n    sigaction(taskPauseSignal, &act, NULL);\n\n    // Obtain the number of CPUs available on program start (for NumCPU).\n    int num = sysconf(_SC_NPROCESSORS_ONLN);\n    if (num <= 0) {\n        // Fallback in case there is an error.\n        num = 1;\n    }\n    *numCPU = num;\n}\n\nvoid tinygo_task_exited(void*);\n\n// Helper to start a goroutine while also storing the 'task' structure.\nstatic void* start_wrapper(void *arg) {\n    struct state_pass *state = arg;\n    void *(*start)(void*) = state->start;\n    void *args = state->args;\n    current_task = state->task;\n\n    // Save the current stack pointer in the goroutine state, for the GC.\n    int stackAddr;\n    *(state->stackTop) = (uintptr_t)(&stackAddr);\n\n    // Notify the caller that the thread has successfully started and\n    // initialized.\n    #if __APPLE__\n    dispatch_semaphore_signal(state->startlock);\n    #else\n    sem_post(&state->startlock);\n    #endif\n\n    // Run the goroutine function.\n    start(args);\n\n    // Notify the Go side this thread will exit.\n    tinygo_task_exited(current_task);\n\n    return NULL;\n};\n\n// Start a new goroutine in an OS thread.\nint tinygo_task_start(uintptr_t fn, void *args, void *task, pthread_t *thread, uintptr_t *stackTop, uintptr_t stackSize, void *context) {\n    // Sanity check. Should get optimized away.\n    if (sizeof(pthread_t) != sizeof(void*)) {\n        __builtin_trap();\n    }\n\n    struct state_pass state = {\n        .start     = (void*)fn,\n        .args      = args,\n        .task      = task,\n        .stackTop  = stackTop,\n    };\n    #if __APPLE__\n    state.startlock = dispatch_semaphore_create(0);\n    #else\n    sem_init(&state.startlock, 0, 0);\n    #endif\n    pthread_attr_t attrs;\n    pthread_attr_init(&attrs);\n\tpthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);\n    pthread_attr_setstacksize(&attrs, stackSize);\n    int result = pthread_create(thread, &attrs, &start_wrapper, &state);\n    pthread_attr_destroy(&attrs);\n\tif (result != 0) {\n\t\treturn result;\n\t}\n\n    // Wait until the thread has been created and read all state_pass variables.\n    #if __APPLE__\n    dispatch_semaphore_wait(state.startlock, DISPATCH_TIME_FOREVER);\n    dispatch_release(state.startlock);\n    #else\n    sem_wait(&state.startlock);\n    sem_destroy(&state.startlock);\n    #endif\n\n    return result;\n}\n\n// Return the current task (for task.Current()).\nvoid* tinygo_task_current(void) {\n    return current_task;\n}\n\n// Send a signal to cause the task to pause for the GC mark phase.\nvoid tinygo_task_send_gc_signal(pthread_t thread) {\n    pthread_kill(thread, taskPauseSignal);\n}\n"
  },
  {
    "path": "src/internal/task/task_threads.go",
    "content": "//go:build scheduler.threads\n\npackage task\n\nimport (\n\t\"sync/atomic\"\n\t\"unsafe\"\n)\n\n// If true, print verbose debug logs.\nconst verbose = false\n\n// Scheduler-specific state.\ntype state struct {\n\t// Goroutine ID. The number here is not really significant and after a while\n\t// it could wrap around. But it is useful for debugging.\n\tid uintptr\n\n\t// Thread ID, pthread_t or similar (typically implemented as a pointer).\n\tthread threadID\n\n\t// Highest address of the stack. It is stored when the goroutine starts, and\n\t// is needed to be able to scan the stack.\n\tstackTop uintptr\n\n\t// Lowest address of the stack.\n\t// This is populated when the thread is stopped by the GC.\n\tstackBottom uintptr\n\n\t// Next task in the activeTasks queue.\n\tQueueNext *Task\n\n\t// Semaphore to pause/resume the thread atomically.\n\tpauseSem Semaphore\n}\n\n// Goroutine counter, starting at 0 for the main goroutine.\nvar goroutineID uintptr\n\nvar numCPU int32\n\nvar mainTask Task\n\n// Queue of tasks (see QueueNext) that currently exist in the program.\nvar activeTasks = &mainTask\nvar activeTaskLock PMutex\n\nfunc OnSystemStack() bool {\n\truntimePanic(\"todo: task.OnSystemStack\")\n\treturn false\n}\n\n// Initialize the main goroutine state. Must be called by the runtime on\n// startup, before starting any other goroutines.\nfunc Init(sp uintptr) {\n\tmainTask.state.stackTop = sp\n\ttinygo_task_init(&mainTask, &mainTask.state.thread, &numCPU)\n}\n\n// Return the task struct for the current thread.\nfunc Current() *Task {\n\tt := (*Task)(tinygo_task_current())\n\tif t == nil {\n\t\truntimePanic(\"unknown current task\")\n\t}\n\treturn t\n}\n\n// Pause pauses the current task, until it is resumed by another task.\n// It is possible that another task has called Resume() on the task before it\n// hits Pause(), in which case the task won't be paused but continues\n// immediately.\nfunc Pause() {\n\t// Wait until resumed\n\tt := Current()\n\tif verbose {\n\t\tprintln(\"*** pause:  \", t.state.id)\n\t}\n\tt.state.pauseSem.Wait()\n}\n\n// Resume the given task.\n// It is legal to resume a task before it gets paused, it means that the next\n// call to Pause() won't pause but will continue immediately. This happens in\n// practice sometimes in channel operations, where the Resume() might get called\n// between the channel unlock and the call to Pause().\nfunc (t *Task) Resume() {\n\tif verbose {\n\t\tprintln(\"*** resume: \", t.state.id)\n\t}\n\t// Increment the semaphore counter.\n\t// If the task is currently paused in Wait(), it will resume.\n\t// If the task is not yet paused, the next call to Wait() will continue\n\t// immediately.\n\tt.state.pauseSem.Post()\n}\n\n// otherGoroutines is the total number of live goroutines minus one.\nvar otherGoroutines uint32\n\n// Start a new OS thread.\nfunc start(fn uintptr, args unsafe.Pointer, stackSize uintptr) {\n\tt := &Task{}\n\tt.state.id = atomic.AddUintptr(&goroutineID, 1)\n\tif verbose {\n\t\tprintln(\"*** start:  \", t.state.id, \"from\", Current().state.id)\n\t}\n\n\t// Start the new thread, and add it to the list of threads.\n\t// Do this with a lock so that only started threads are part of the queue\n\t// and the stop-the-world GC won't see threads that haven't started yet or\n\t// are not fully started yet.\n\tactiveTaskLock.Lock()\n\terrCode := tinygo_task_start(fn, args, t, &t.state.thread, &t.state.stackTop, stackSize)\n\tif errCode != 0 {\n\t\truntimePanic(\"could not start thread\")\n\t}\n\tt.state.QueueNext = activeTasks\n\tactiveTasks = t\n\totherGoroutines++\n\tactiveTaskLock.Unlock()\n}\n\n//export tinygo_task_exited\nfunc taskExited(t *Task) {\n\tif verbose {\n\t\tprintln(\"*** exit:\", t.state.id)\n\t}\n\n\t// Remove from the queue.\n\t// TODO: this can be made more efficient by using a doubly linked list.\n\tactiveTaskLock.Lock()\n\tfound := false\n\tfor q := &activeTasks; *q != nil; q = &(*q).state.QueueNext {\n\t\tif *q == t {\n\t\t\t*q = t.state.QueueNext\n\t\t\tfound = true\n\t\t\tbreak\n\t\t}\n\t}\n\totherGoroutines--\n\tactiveTaskLock.Unlock()\n\n\t// Sanity check.\n\tif !found {\n\t\truntimePanic(\"taskExited failed\")\n\t}\n}\n\n// scanWaitGroup is used to wait on until all threads have finished the current state transition.\nvar scanWaitGroup waitGroup\n\ntype waitGroup struct {\n\tf Futex\n}\n\nfunc initWaitGroup(n uint32) waitGroup {\n\tvar wg waitGroup\n\twg.f.Store(n)\n\treturn wg\n}\n\nfunc (wg *waitGroup) done() {\n\tif wg.f.Add(^uint32(0)) == 0 {\n\t\twg.f.WakeAll()\n\t}\n}\n\nfunc (wg *waitGroup) wait() {\n\tfor {\n\t\tval := wg.f.Load()\n\t\tif val == 0 {\n\t\t\treturn\n\t\t}\n\t\twg.f.Wait(val)\n\t}\n}\n\n// gcState is used to track and notify threads when the GC is stopping/resuming.\nvar gcState Futex\n\nconst (\n\tgcStateResumed = iota\n\tgcStateStopped\n)\n\n// GC scan phase. Because we need to stop the world while scanning, this kinda\n// needs to be done in the tasks package.\n//\n// After calling this function, GCResumeWorld needs to be called once to resume\n// all threads again.\nfunc GCStopWorldAndScan() {\n\tcurrent := Current()\n\n\t// NOTE: This does not need to be atomic.\n\tif gcState.Load() == gcStateResumed {\n\t\t// Don't allow new goroutines to be started while pausing/resuming threads\n\t\t// in the stop-the-world phase.\n\t\tactiveTaskLock.Lock()\n\n\t\t// Wait for threads to finish resuming.\n\t\tscanWaitGroup.wait()\n\n\t\t// Change the gc state to stopped.\n\t\t// NOTE: This does not need to be atomic.\n\t\tgcState.Store(gcStateStopped)\n\n\t\t// Set the number of threads to wait for.\n\t\tscanWaitGroup = initWaitGroup(otherGoroutines)\n\n\t\t// Pause all other threads.\n\t\tfor t := activeTasks; t != nil; t = t.state.QueueNext {\n\t\t\tif t != current {\n\t\t\t\ttinygo_task_send_gc_signal(t.state.thread)\n\t\t\t}\n\t\t}\n\n\t\t// Wait for the threads to finish stopping.\n\t\tscanWaitGroup.wait()\n\t}\n\n\t// Scan other thread stacks.\n\tfor t := activeTasks; t != nil; t = t.state.QueueNext {\n\t\tif t != current {\n\t\t\tmarkRoots(t.state.stackBottom, t.state.stackTop)\n\t\t}\n\t}\n\n\t// Scan the current stack, and all current registers.\n\tscanCurrentStack()\n\n\t// Scan all globals (implemented in the runtime).\n\tgcScanGlobals()\n}\n\n// After the GC is done scanning, resume all other threads.\nfunc GCResumeWorld() {\n\t// NOTE: This does not need to be atomic.\n\tif gcState.Load() == gcStateResumed {\n\t\t// This is already resumed.\n\t\treturn\n\t}\n\n\t// Set the wait group to track resume progress.\n\tscanWaitGroup = initWaitGroup(otherGoroutines)\n\n\t// Set the state to resumed.\n\tgcState.Store(gcStateResumed)\n\n\t// Wake all of the stopped threads.\n\tgcState.WakeAll()\n\n\t// Allow goroutines to start and exit again.\n\tactiveTaskLock.Unlock()\n}\n\n//go:linkname markRoots runtime.markRoots\nfunc markRoots(start, end uintptr)\n\n// Scan globals, implemented in the runtime package.\nfunc gcScanGlobals()\n\nvar stackScanLock PMutex\n\n//export tinygo_task_gc_pause\nfunc tingyo_task_gc_pause(sig int32) {\n\t// Write the entrty stack pointer to the state.\n\tCurrent().state.stackBottom = uintptr(stacksave())\n\n\t// Notify the GC that we are stopped.\n\tscanWaitGroup.done()\n\n\t// Wait for the GC to resume.\n\tfor gcState.Load() == gcStateStopped {\n\t\tgcState.Wait(gcStateStopped)\n\t}\n\n\t// Notify the GC that we have resumed.\n\tscanWaitGroup.done()\n}\n\n//go:export tinygo_scanCurrentStack\nfunc scanCurrentStack()\n\n//go:linkname stacksave runtime.stacksave\nfunc stacksave() unsafe.Pointer\n\n// Return the highest address of the current stack.\nfunc StackTop() uintptr {\n\treturn Current().state.stackTop\n}\n\n//go:linkname runtimePanic runtime.runtimePanic\nfunc runtimePanic(msg string)\n\n// Using //go:linkname instead of //export so that we don't tell the compiler\n// that the 't' parameter won't escape (because it will).\n//\n//go:linkname tinygo_task_init tinygo_task_init\nfunc tinygo_task_init(t *Task, thread *threadID, numCPU *int32)\n\n// Here same as for tinygo_task_init.\n//\n//go:linkname tinygo_task_start tinygo_task_start\nfunc tinygo_task_start(fn uintptr, args unsafe.Pointer, t *Task, thread *threadID, stackTop *uintptr, stackSize uintptr) int32\n\n// Pause the thread by sending it a signal.\n//\n//export tinygo_task_send_gc_signal\nfunc tinygo_task_send_gc_signal(threadID)\n\n//export tinygo_task_current\nfunc tinygo_task_current() unsafe.Pointer\n\nfunc NumCPU() int {\n\treturn int(numCPU)\n}\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/command/command.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package command represents the world \"wasi:cli/command@0.2.0\".\npackage command\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/environment/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/environment/environment.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage environment\n\nimport (\n\t\"internal/cm\"\n)\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:cli@0.2.0\".\n\n//go:wasmimport wasi:cli/environment@0.2.0 get-environment\n//go:noescape\nfunc wasmimport_GetEnvironment(result *cm.List[[2]string])\n\n//go:wasmimport wasi:cli/environment@0.2.0 get-arguments\n//go:noescape\nfunc wasmimport_GetArguments(result *cm.List[string])\n\n//go:wasmimport wasi:cli/environment@0.2.0 initial-cwd\n//go:noescape\nfunc wasmimport_InitialCWD(result *cm.Option[string])\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/environment/environment.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package environment represents the imported interface \"wasi:cli/environment@0.2.0\".\npackage environment\n\nimport (\n\t\"internal/cm\"\n)\n\n// GetEnvironment represents the imported function \"get-environment\".\n//\n// Get the POSIX-style environment variables.\n//\n// Each environment variable is provided as a pair of string variable names\n// and string value.\n//\n// Morally, these are a value import, but until value imports are available\n// in the component model, this import function should return the same\n// values each time it is called.\n//\n//\tget-environment: func() -> list<tuple<string, string>>\n//\n//go:nosplit\nfunc GetEnvironment() (result cm.List[[2]string]) {\n\twasmimport_GetEnvironment(&result)\n\treturn\n}\n\n// GetArguments represents the imported function \"get-arguments\".\n//\n// Get the POSIX-style arguments to the program.\n//\n//\tget-arguments: func() -> list<string>\n//\n//go:nosplit\nfunc GetArguments() (result cm.List[string]) {\n\twasmimport_GetArguments(&result)\n\treturn\n}\n\n// InitialCWD represents the imported function \"initial-cwd\".\n//\n// Return a path that programs should use as their initial current working\n// directory, interpreting `.` as shorthand for this.\n//\n//\tinitial-cwd: func() -> option<string>\n//\n//go:nosplit\nfunc InitialCWD() (result cm.Option[string]) {\n\twasmimport_InitialCWD(&result)\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/exit/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/exit/exit.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage exit\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:cli@0.2.0\".\n\n//go:wasmimport wasi:cli/exit@0.2.0 exit\n//go:noescape\nfunc wasmimport_Exit(status0 uint32)\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/exit/exit.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package exit represents the imported interface \"wasi:cli/exit@0.2.0\".\npackage exit\n\nimport (\n\t\"internal/cm\"\n)\n\n// Exit represents the imported function \"exit\".\n//\n// Exit the current instance and any linked instances.\n//\n//\texit: func(status: result)\n//\n//go:nosplit\nfunc Exit(status cm.BoolResult) {\n\tstatus0 := (uint32)(cm.BoolToU32(status))\n\twasmimport_Exit((uint32)(status0))\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/run/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/run/run.exports.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage run\n\nimport (\n\t\"internal/cm\"\n)\n\n// Exports represents the caller-defined exports from \"wasi:cli/run@0.2.0\".\nvar Exports struct {\n\t// Run represents the caller-defined, exported function \"run\".\n\t//\n\t// Run the program.\n\t//\n\t//\trun: func() -> result\n\tRun func() (result cm.BoolResult)\n}\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/run/run.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage run\n\nimport (\n\t\"internal/cm\"\n)\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:cli@0.2.0\".\n\n//go:wasmexport wasi:cli/run@0.2.0#run\n//export wasi:cli/run@0.2.0#run\nfunc wasmexport_Run() (result0 uint32) {\n\tresult := Exports.Run()\n\tresult0 = (uint32)(cm.BoolToU32(result))\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/run/run.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package run represents the exported interface \"wasi:cli/run@0.2.0\".\npackage run\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/stderr/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/stderr/stderr.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage stderr\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:cli@0.2.0\".\n\n//go:wasmimport wasi:cli/stderr@0.2.0 get-stderr\n//go:noescape\nfunc wasmimport_GetStderr() (result0 uint32)\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/stderr/stderr.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package stderr represents the imported interface \"wasi:cli/stderr@0.2.0\".\npackage stderr\n\nimport (\n\t\"internal/cm\"\n\t\"internal/wasi/io/v0.2.0/streams\"\n)\n\n// OutputStream represents the imported type alias \"wasi:cli/stderr@0.2.0#output-stream\".\n//\n// See [streams.OutputStream] for more information.\ntype OutputStream = streams.OutputStream\n\n// GetStderr represents the imported function \"get-stderr\".\n//\n//\tget-stderr: func() -> output-stream\n//\n//go:nosplit\nfunc GetStderr() (result OutputStream) {\n\tresult0 := wasmimport_GetStderr()\n\tresult = cm.Reinterpret[OutputStream]((uint32)(result0))\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/stdin/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/stdin/stdin.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage stdin\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:cli@0.2.0\".\n\n//go:wasmimport wasi:cli/stdin@0.2.0 get-stdin\n//go:noescape\nfunc wasmimport_GetStdin() (result0 uint32)\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/stdin/stdin.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package stdin represents the imported interface \"wasi:cli/stdin@0.2.0\".\npackage stdin\n\nimport (\n\t\"internal/cm\"\n\t\"internal/wasi/io/v0.2.0/streams\"\n)\n\n// InputStream represents the imported type alias \"wasi:cli/stdin@0.2.0#input-stream\".\n//\n// See [streams.InputStream] for more information.\ntype InputStream = streams.InputStream\n\n// GetStdin represents the imported function \"get-stdin\".\n//\n//\tget-stdin: func() -> input-stream\n//\n//go:nosplit\nfunc GetStdin() (result InputStream) {\n\tresult0 := wasmimport_GetStdin()\n\tresult = cm.Reinterpret[InputStream]((uint32)(result0))\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/stdout/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/stdout/stdout.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage stdout\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:cli@0.2.0\".\n\n//go:wasmimport wasi:cli/stdout@0.2.0 get-stdout\n//go:noescape\nfunc wasmimport_GetStdout() (result0 uint32)\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/stdout/stdout.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package stdout represents the imported interface \"wasi:cli/stdout@0.2.0\".\npackage stdout\n\nimport (\n\t\"internal/cm\"\n\t\"internal/wasi/io/v0.2.0/streams\"\n)\n\n// OutputStream represents the imported type alias \"wasi:cli/stdout@0.2.0#output-stream\".\n//\n// See [streams.OutputStream] for more information.\ntype OutputStream = streams.OutputStream\n\n// GetStdout represents the imported function \"get-stdout\".\n//\n//\tget-stdout: func() -> output-stream\n//\n//go:nosplit\nfunc GetStdout() (result OutputStream) {\n\tresult0 := wasmimport_GetStdout()\n\tresult = cm.Reinterpret[OutputStream]((uint32)(result0))\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/terminal-input/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/terminal-input/terminal-input.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage terminalinput\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:cli@0.2.0\".\n\n//go:wasmimport wasi:cli/terminal-input@0.2.0 [resource-drop]terminal-input\n//go:noescape\nfunc wasmimport_TerminalInputResourceDrop(self0 uint32)\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/terminal-input/terminal-input.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package terminalinput represents the imported interface \"wasi:cli/terminal-input@0.2.0\".\n//\n// Terminal input.\n//\n// In the future, this may include functions for disabling echoing,\n// disabling input buffering so that keyboard events are sent through\n// immediately, querying supported features, and so on.\npackage terminalinput\n\nimport (\n\t\"internal/cm\"\n)\n\n// TerminalInput represents the imported resource \"wasi:cli/terminal-input@0.2.0#terminal-input\".\n//\n// The input side of a terminal.\n//\n//\tresource terminal-input\ntype TerminalInput cm.Resource\n\n// ResourceDrop represents the imported resource-drop for resource \"terminal-input\".\n//\n// Drops a resource handle.\n//\n//go:nosplit\nfunc (self TerminalInput) ResourceDrop() {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_TerminalInputResourceDrop((uint32)(self0))\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/terminal-output/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/terminal-output/terminal-output.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage terminaloutput\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:cli@0.2.0\".\n\n//go:wasmimport wasi:cli/terminal-output@0.2.0 [resource-drop]terminal-output\n//go:noescape\nfunc wasmimport_TerminalOutputResourceDrop(self0 uint32)\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/terminal-output/terminal-output.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package terminaloutput represents the imported interface \"wasi:cli/terminal-output@0.2.0\".\n//\n// Terminal output.\n//\n// In the future, this may include functions for querying the terminal\n// size, being notified of terminal size changes, querying supported\n// features, and so on.\npackage terminaloutput\n\nimport (\n\t\"internal/cm\"\n)\n\n// TerminalOutput represents the imported resource \"wasi:cli/terminal-output@0.2.0#terminal-output\".\n//\n// The output side of a terminal.\n//\n//\tresource terminal-output\ntype TerminalOutput cm.Resource\n\n// ResourceDrop represents the imported resource-drop for resource \"terminal-output\".\n//\n// Drops a resource handle.\n//\n//go:nosplit\nfunc (self TerminalOutput) ResourceDrop() {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_TerminalOutputResourceDrop((uint32)(self0))\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/terminal-stderr/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/terminal-stderr/terminal-stderr.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage terminalstderr\n\nimport (\n\t\"internal/cm\"\n)\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:cli@0.2.0\".\n\n//go:wasmimport wasi:cli/terminal-stderr@0.2.0 get-terminal-stderr\n//go:noescape\nfunc wasmimport_GetTerminalStderr(result *cm.Option[TerminalOutput])\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/terminal-stderr/terminal-stderr.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package terminalstderr represents the imported interface \"wasi:cli/terminal-stderr@0.2.0\".\n//\n// An interface providing an optional `terminal-output` for stderr as a\n// link-time authority.\npackage terminalstderr\n\nimport (\n\t\"internal/cm\"\n\tterminaloutput \"internal/wasi/cli/v0.2.0/terminal-output\"\n)\n\n// TerminalOutput represents the imported type alias \"wasi:cli/terminal-stderr@0.2.0#terminal-output\".\n//\n// See [terminaloutput.TerminalOutput] for more information.\ntype TerminalOutput = terminaloutput.TerminalOutput\n\n// GetTerminalStderr represents the imported function \"get-terminal-stderr\".\n//\n// If stderr is connected to a terminal, return a `terminal-output` handle\n// allowing further interaction with it.\n//\n//\tget-terminal-stderr: func() -> option<terminal-output>\n//\n//go:nosplit\nfunc GetTerminalStderr() (result cm.Option[TerminalOutput]) {\n\twasmimport_GetTerminalStderr(&result)\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/terminal-stdin/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/terminal-stdin/terminal-stdin.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage terminalstdin\n\nimport (\n\t\"internal/cm\"\n)\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:cli@0.2.0\".\n\n//go:wasmimport wasi:cli/terminal-stdin@0.2.0 get-terminal-stdin\n//go:noescape\nfunc wasmimport_GetTerminalStdin(result *cm.Option[TerminalInput])\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/terminal-stdin/terminal-stdin.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package terminalstdin represents the imported interface \"wasi:cli/terminal-stdin@0.2.0\".\n//\n// An interface providing an optional `terminal-input` for stdin as a\n// link-time authority.\npackage terminalstdin\n\nimport (\n\t\"internal/cm\"\n\tterminalinput \"internal/wasi/cli/v0.2.0/terminal-input\"\n)\n\n// TerminalInput represents the imported type alias \"wasi:cli/terminal-stdin@0.2.0#terminal-input\".\n//\n// See [terminalinput.TerminalInput] for more information.\ntype TerminalInput = terminalinput.TerminalInput\n\n// GetTerminalStdin represents the imported function \"get-terminal-stdin\".\n//\n// If stdin is connected to a terminal, return a `terminal-input` handle\n// allowing further interaction with it.\n//\n//\tget-terminal-stdin: func() -> option<terminal-input>\n//\n//go:nosplit\nfunc GetTerminalStdin() (result cm.Option[TerminalInput]) {\n\twasmimport_GetTerminalStdin(&result)\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/terminal-stdout/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/terminal-stdout/terminal-stdout.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage terminalstdout\n\nimport (\n\t\"internal/cm\"\n)\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:cli@0.2.0\".\n\n//go:wasmimport wasi:cli/terminal-stdout@0.2.0 get-terminal-stdout\n//go:noescape\nfunc wasmimport_GetTerminalStdout(result *cm.Option[TerminalOutput])\n"
  },
  {
    "path": "src/internal/wasi/cli/v0.2.0/terminal-stdout/terminal-stdout.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package terminalstdout represents the imported interface \"wasi:cli/terminal-stdout@0.2.0\".\n//\n// An interface providing an optional `terminal-output` for stdout as a\n// link-time authority.\npackage terminalstdout\n\nimport (\n\t\"internal/cm\"\n\tterminaloutput \"internal/wasi/cli/v0.2.0/terminal-output\"\n)\n\n// TerminalOutput represents the imported type alias \"wasi:cli/terminal-stdout@0.2.0#terminal-output\".\n//\n// See [terminaloutput.TerminalOutput] for more information.\ntype TerminalOutput = terminaloutput.TerminalOutput\n\n// GetTerminalStdout represents the imported function \"get-terminal-stdout\".\n//\n// If stdout is connected to a terminal, return a `terminal-output` handle\n// allowing further interaction with it.\n//\n//\tget-terminal-stdout: func() -> option<terminal-output>\n//\n//go:nosplit\nfunc GetTerminalStdout() (result cm.Option[TerminalOutput]) {\n\twasmimport_GetTerminalStdout(&result)\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/clocks/v0.2.0/monotonic-clock/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/clocks/v0.2.0/monotonic-clock/monotonic-clock.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage monotonicclock\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:clocks@0.2.0\".\n\n//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 now\n//go:noescape\nfunc wasmimport_Now() (result0 uint64)\n\n//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 resolution\n//go:noescape\nfunc wasmimport_Resolution() (result0 uint64)\n\n//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 subscribe-instant\n//go:noescape\nfunc wasmimport_SubscribeInstant(when0 uint64) (result0 uint32)\n\n//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 subscribe-duration\n//go:noescape\nfunc wasmimport_SubscribeDuration(when0 uint64) (result0 uint32)\n"
  },
  {
    "path": "src/internal/wasi/clocks/v0.2.0/monotonic-clock/monotonic-clock.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package monotonicclock represents the imported interface \"wasi:clocks/monotonic-clock@0.2.0\".\n//\n// WASI Monotonic Clock is a clock API intended to let users measure elapsed\n// time.\n//\n// It is intended to be portable at least between Unix-family platforms and\n// Windows.\n//\n// A monotonic clock is a clock which has an unspecified initial value, and\n// successive reads of the clock will produce non-decreasing values.\n//\n// It is intended for measuring elapsed time.\npackage monotonicclock\n\nimport (\n\t\"internal/cm\"\n\t\"internal/wasi/io/v0.2.0/poll\"\n)\n\n// Pollable represents the imported type alias \"wasi:clocks/monotonic-clock@0.2.0#pollable\".\n//\n// See [poll.Pollable] for more information.\ntype Pollable = poll.Pollable\n\n// Instant represents the u64 \"wasi:clocks/monotonic-clock@0.2.0#instant\".\n//\n// An instant in time, in nanoseconds. An instant is relative to an\n// unspecified initial value, and can only be compared to instances from\n// the same monotonic-clock.\n//\n//\ttype instant = u64\ntype Instant uint64\n\n// Duration represents the u64 \"wasi:clocks/monotonic-clock@0.2.0#duration\".\n//\n// A duration of time, in nanoseconds.\n//\n//\ttype duration = u64\ntype Duration uint64\n\n// Now represents the imported function \"now\".\n//\n// Read the current value of the clock.\n//\n// The clock is monotonic, therefore calling this function repeatedly will\n// produce a sequence of non-decreasing values.\n//\n//\tnow: func() -> instant\n//\n//go:nosplit\nfunc Now() (result Instant) {\n\tresult0 := wasmimport_Now()\n\tresult = (Instant)((uint64)(result0))\n\treturn\n}\n\n// Resolution represents the imported function \"resolution\".\n//\n// Query the resolution of the clock. Returns the duration of time\n// corresponding to a clock tick.\n//\n//\tresolution: func() -> duration\n//\n//go:nosplit\nfunc Resolution() (result Duration) {\n\tresult0 := wasmimport_Resolution()\n\tresult = (Duration)((uint64)(result0))\n\treturn\n}\n\n// SubscribeInstant represents the imported function \"subscribe-instant\".\n//\n// Create a `pollable` which will resolve once the specified instant\n// occured.\n//\n//\tsubscribe-instant: func(when: instant) -> pollable\n//\n//go:nosplit\nfunc SubscribeInstant(when Instant) (result Pollable) {\n\twhen0 := (uint64)(when)\n\tresult0 := wasmimport_SubscribeInstant((uint64)(when0))\n\tresult = cm.Reinterpret[Pollable]((uint32)(result0))\n\treturn\n}\n\n// SubscribeDuration represents the imported function \"subscribe-duration\".\n//\n// Create a `pollable` which will resolve once the given duration has\n// elapsed, starting at the time at which this function was called.\n// occured.\n//\n//\tsubscribe-duration: func(when: duration) -> pollable\n//\n//go:nosplit\nfunc SubscribeDuration(when Duration) (result Pollable) {\n\twhen0 := (uint64)(when)\n\tresult0 := wasmimport_SubscribeDuration((uint64)(when0))\n\tresult = cm.Reinterpret[Pollable]((uint32)(result0))\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/clocks/v0.2.0/wall-clock/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/clocks/v0.2.0/wall-clock/wall-clock.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage wallclock\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:clocks@0.2.0\".\n\n//go:wasmimport wasi:clocks/wall-clock@0.2.0 now\n//go:noescape\nfunc wasmimport_Now(result *DateTime)\n\n//go:wasmimport wasi:clocks/wall-clock@0.2.0 resolution\n//go:noescape\nfunc wasmimport_Resolution(result *DateTime)\n"
  },
  {
    "path": "src/internal/wasi/clocks/v0.2.0/wall-clock/wall-clock.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package wallclock represents the imported interface \"wasi:clocks/wall-clock@0.2.0\".\n//\n// WASI Wall Clock is a clock API intended to let users query the current\n// time. The name \"wall\" makes an analogy to a \"clock on the wall\", which\n// is not necessarily monotonic as it may be reset.\n//\n// It is intended to be portable at least between Unix-family platforms and\n// Windows.\n//\n// A wall clock is a clock which measures the date and time according to\n// some external reference.\n//\n// External references may be reset, so this clock is not necessarily\n// monotonic, making it unsuitable for measuring elapsed time.\n//\n// It is intended for reporting the current date and time for humans.\npackage wallclock\n\nimport (\n\t\"internal/cm\"\n)\n\n// DateTime represents the record \"wasi:clocks/wall-clock@0.2.0#datetime\".\n//\n// A time and date in seconds plus nanoseconds.\n//\n//\trecord datetime {\n//\t\tseconds: u64,\n//\t\tnanoseconds: u32,\n//\t}\ntype DateTime struct {\n\t_           cm.HostLayout `json:\"-\"`\n\tSeconds     uint64        `json:\"seconds\"`\n\tNanoseconds uint32        `json:\"nanoseconds\"`\n}\n\n// Now represents the imported function \"now\".\n//\n// Read the current value of the clock.\n//\n// This clock is not monotonic, therefore calling this function repeatedly\n// will not necessarily produce a sequence of non-decreasing values.\n//\n// The returned timestamps represent the number of seconds since\n// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch],\n// also known as [Unix Time].\n//\n// The nanoseconds field of the output is always less than 1000000000.\n//\n//\tnow: func() -> datetime\n//\n// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16\n// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time\n//\n//go:nosplit\nfunc Now() (result DateTime) {\n\twasmimport_Now(&result)\n\treturn\n}\n\n// Resolution represents the imported function \"resolution\".\n//\n// Query the resolution of the clock.\n//\n// The nanoseconds field of the output is always less than 1000000000.\n//\n//\tresolution: func() -> datetime\n//\n//go:nosplit\nfunc Resolution() (result DateTime) {\n\twasmimport_Resolution(&result)\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/filesystem/v0.2.0/preopens/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/filesystem/v0.2.0/preopens/preopens.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage preopens\n\nimport (\n\t\"internal/cm\"\n)\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:filesystem@0.2.0\".\n\n//go:wasmimport wasi:filesystem/preopens@0.2.0 get-directories\n//go:noescape\nfunc wasmimport_GetDirectories(result *cm.List[cm.Tuple[Descriptor, string]])\n"
  },
  {
    "path": "src/internal/wasi/filesystem/v0.2.0/preopens/preopens.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package preopens represents the imported interface \"wasi:filesystem/preopens@0.2.0\".\npackage preopens\n\nimport (\n\t\"internal/cm\"\n\t\"internal/wasi/filesystem/v0.2.0/types\"\n)\n\n// Descriptor represents the imported type alias \"wasi:filesystem/preopens@0.2.0#descriptor\".\n//\n// See [types.Descriptor] for more information.\ntype Descriptor = types.Descriptor\n\n// GetDirectories represents the imported function \"get-directories\".\n//\n// Return the set of preopened directories, and their path.\n//\n//\tget-directories: func() -> list<tuple<descriptor, string>>\n//\n//go:nosplit\nfunc GetDirectories() (result cm.List[cm.Tuple[Descriptor, string]]) {\n\twasmimport_GetDirectories(&result)\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/filesystem/v0.2.0/types/abi.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage types\n\nimport (\n\t\"internal/cm\"\n\twallclock \"internal/wasi/clocks/v0.2.0/wall-clock\"\n\t\"unsafe\"\n)\n\n// MetadataHashValueShape is used for storage in variant or result types.\ntype MetadataHashValueShape struct {\n\t_     cm.HostLayout\n\tshape [unsafe.Sizeof(MetadataHashValue{})]byte\n}\n\n// TupleListU8BoolShape is used for storage in variant or result types.\ntype TupleListU8BoolShape struct {\n\t_     cm.HostLayout\n\tshape [unsafe.Sizeof(cm.Tuple[cm.List[uint8], bool]{})]byte\n}\n\nfunc lower_DateTime(v wallclock.DateTime) (f0 uint64, f1 uint32) {\n\tf0 = (uint64)(v.Seconds)\n\tf1 = (uint32)(v.Nanoseconds)\n\treturn\n}\n\nfunc lower_NewTimestamp(v NewTimestamp) (f0 uint32, f1 uint64, f2 uint32) {\n\tf0 = (uint32)(v.Tag())\n\tswitch f0 {\n\tcase 2: // timestamp\n\t\tv1, v2 := lower_DateTime(*cm.Case[DateTime](&v, 2))\n\t\tf1 = (uint64)(v1)\n\t\tf2 = (uint32)(v2)\n\t}\n\treturn\n}\n\n// DescriptorStatShape is used for storage in variant or result types.\ntype DescriptorStatShape struct {\n\t_     cm.HostLayout\n\tshape [unsafe.Sizeof(DescriptorStat{})]byte\n}\n\n// OptionDirectoryEntryShape is used for storage in variant or result types.\ntype OptionDirectoryEntryShape struct {\n\t_     cm.HostLayout\n\tshape [unsafe.Sizeof(cm.Option[DirectoryEntry]{})]byte\n}\n"
  },
  {
    "path": "src/internal/wasi/filesystem/v0.2.0/types/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/filesystem/v0.2.0/types/types.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage types\n\nimport (\n\t\"internal/cm\"\n)\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:filesystem@0.2.0\".\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [resource-drop]descriptor\n//go:noescape\nfunc wasmimport_DescriptorResourceDrop(self0 uint32)\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.advise\n//go:noescape\nfunc wasmimport_DescriptorAdvise(self0 uint32, offset0 uint64, length0 uint64, advice0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.append-via-stream\n//go:noescape\nfunc wasmimport_DescriptorAppendViaStream(self0 uint32, result *cm.Result[OutputStream, OutputStream, ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.create-directory-at\n//go:noescape\nfunc wasmimport_DescriptorCreateDirectoryAt(self0 uint32, path0 *uint8, path1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.get-flags\n//go:noescape\nfunc wasmimport_DescriptorGetFlags(self0 uint32, result *cm.Result[DescriptorFlags, DescriptorFlags, ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.get-type\n//go:noescape\nfunc wasmimport_DescriptorGetType(self0 uint32, result *cm.Result[DescriptorType, DescriptorType, ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.is-same-object\n//go:noescape\nfunc wasmimport_DescriptorIsSameObject(self0 uint32, other0 uint32) (result0 uint32)\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.link-at\n//go:noescape\nfunc wasmimport_DescriptorLinkAt(self0 uint32, oldPathFlags0 uint32, oldPath0 *uint8, oldPath1 uint32, newDescriptor0 uint32, newPath0 *uint8, newPath1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.metadata-hash\n//go:noescape\nfunc wasmimport_DescriptorMetadataHash(self0 uint32, result *cm.Result[MetadataHashValueShape, MetadataHashValue, ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.metadata-hash-at\n//go:noescape\nfunc wasmimport_DescriptorMetadataHashAt(self0 uint32, pathFlags0 uint32, path0 *uint8, path1 uint32, result *cm.Result[MetadataHashValueShape, MetadataHashValue, ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.open-at\n//go:noescape\nfunc wasmimport_DescriptorOpenAt(self0 uint32, pathFlags0 uint32, path0 *uint8, path1 uint32, openFlags0 uint32, flags0 uint32, result *cm.Result[Descriptor, Descriptor, ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.read\n//go:noescape\nfunc wasmimport_DescriptorRead(self0 uint32, length0 uint64, offset0 uint64, result *cm.Result[TupleListU8BoolShape, cm.Tuple[cm.List[uint8], bool], ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.read-directory\n//go:noescape\nfunc wasmimport_DescriptorReadDirectory(self0 uint32, result *cm.Result[DirectoryEntryStream, DirectoryEntryStream, ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.read-via-stream\n//go:noescape\nfunc wasmimport_DescriptorReadViaStream(self0 uint32, offset0 uint64, result *cm.Result[InputStream, InputStream, ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.readlink-at\n//go:noescape\nfunc wasmimport_DescriptorReadLinkAt(self0 uint32, path0 *uint8, path1 uint32, result *cm.Result[string, string, ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.remove-directory-at\n//go:noescape\nfunc wasmimport_DescriptorRemoveDirectoryAt(self0 uint32, path0 *uint8, path1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.rename-at\n//go:noescape\nfunc wasmimport_DescriptorRenameAt(self0 uint32, oldPath0 *uint8, oldPath1 uint32, newDescriptor0 uint32, newPath0 *uint8, newPath1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.set-size\n//go:noescape\nfunc wasmimport_DescriptorSetSize(self0 uint32, size0 uint64, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.set-times\n//go:noescape\nfunc wasmimport_DescriptorSetTimes(self0 uint32, dataAccessTimestamp0 uint32, dataAccessTimestamp1 uint64, dataAccessTimestamp2 uint32, dataModificationTimestamp0 uint32, dataModificationTimestamp1 uint64, dataModificationTimestamp2 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.set-times-at\n//go:noescape\nfunc wasmimport_DescriptorSetTimesAt(self0 uint32, pathFlags0 uint32, path0 *uint8, path1 uint32, dataAccessTimestamp0 uint32, dataAccessTimestamp1 uint64, dataAccessTimestamp2 uint32, dataModificationTimestamp0 uint32, dataModificationTimestamp1 uint64, dataModificationTimestamp2 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.stat\n//go:noescape\nfunc wasmimport_DescriptorStat(self0 uint32, result *cm.Result[DescriptorStatShape, DescriptorStat, ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.stat-at\n//go:noescape\nfunc wasmimport_DescriptorStatAt(self0 uint32, pathFlags0 uint32, path0 *uint8, path1 uint32, result *cm.Result[DescriptorStatShape, DescriptorStat, ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.symlink-at\n//go:noescape\nfunc wasmimport_DescriptorSymlinkAt(self0 uint32, oldPath0 *uint8, oldPath1 uint32, newPath0 *uint8, newPath1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.sync\n//go:noescape\nfunc wasmimport_DescriptorSync(self0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.sync-data\n//go:noescape\nfunc wasmimport_DescriptorSyncData(self0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.unlink-file-at\n//go:noescape\nfunc wasmimport_DescriptorUnlinkFileAt(self0 uint32, path0 *uint8, path1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.write\n//go:noescape\nfunc wasmimport_DescriptorWrite(self0 uint32, buffer0 *uint8, buffer1 uint32, offset0 uint64, result *cm.Result[uint64, FileSize, ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.write-via-stream\n//go:noescape\nfunc wasmimport_DescriptorWriteViaStream(self0 uint32, offset0 uint64, result *cm.Result[OutputStream, OutputStream, ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [resource-drop]directory-entry-stream\n//go:noescape\nfunc wasmimport_DirectoryEntryStreamResourceDrop(self0 uint32)\n\n//go:wasmimport wasi:filesystem/types@0.2.0 [method]directory-entry-stream.read-directory-entry\n//go:noescape\nfunc wasmimport_DirectoryEntryStreamReadDirectoryEntry(self0 uint32, result *cm.Result[OptionDirectoryEntryShape, cm.Option[DirectoryEntry], ErrorCode])\n\n//go:wasmimport wasi:filesystem/types@0.2.0 filesystem-error-code\n//go:noescape\nfunc wasmimport_FilesystemErrorCode(err0 uint32, result *cm.Option[ErrorCode])\n"
  },
  {
    "path": "src/internal/wasi/filesystem/v0.2.0/types/types.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package types represents the imported interface \"wasi:filesystem/types@0.2.0\".\n//\n// WASI filesystem is a filesystem API primarily intended to let users run WASI\n// programs that access their files on their existing filesystems, without\n// significant overhead.\n//\n// It is intended to be roughly portable between Unix-family platforms and\n// Windows, though it does not hide many of the major differences.\n//\n// Paths are passed as interface-type `string`s, meaning they must consist of\n// a sequence of Unicode Scalar Values (USVs). Some filesystems may contain\n// paths which are not accessible by this API.\n//\n// The directory separator in WASI is always the forward-slash (`/`).\n//\n// All paths in WASI are relative paths, and are interpreted relative to a\n// `descriptor` referring to a base directory. If a `path` argument to any WASI\n// function starts with `/`, or if any step of resolving a `path`, including\n// `..` and symbolic link steps, reaches a directory outside of the base\n// directory, or reaches a symlink to an absolute or rooted path in the\n// underlying filesystem, the function fails with `error-code::not-permitted`.\n//\n// For more information about WASI path resolution and sandboxing, see\n// [WASI filesystem path resolution].\n//\n// [WASI filesystem path resolution]: https://github.com/WebAssembly/wasi-filesystem/blob/main/path-resolution.md\npackage types\n\nimport (\n\t\"internal/cm\"\n\twallclock \"internal/wasi/clocks/v0.2.0/wall-clock\"\n\t\"internal/wasi/io/v0.2.0/streams\"\n)\n\n// InputStream represents the imported type alias \"wasi:filesystem/types@0.2.0#input-stream\".\n//\n// See [streams.InputStream] for more information.\ntype InputStream = streams.InputStream\n\n// OutputStream represents the imported type alias \"wasi:filesystem/types@0.2.0#output-stream\".\n//\n// See [streams.OutputStream] for more information.\ntype OutputStream = streams.OutputStream\n\n// Error represents the imported type alias \"wasi:filesystem/types@0.2.0#error\".\n//\n// See [streams.Error] for more information.\ntype Error = streams.Error\n\n// DateTime represents the type alias \"wasi:filesystem/types@0.2.0#datetime\".\n//\n// See [wallclock.DateTime] for more information.\ntype DateTime = wallclock.DateTime\n\n// FileSize represents the u64 \"wasi:filesystem/types@0.2.0#filesize\".\n//\n// File size or length of a region within a file.\n//\n//\ttype filesize = u64\ntype FileSize uint64\n\n// DescriptorType represents the enum \"wasi:filesystem/types@0.2.0#descriptor-type\".\n//\n// The type of a filesystem object referenced by a descriptor.\n//\n// Note: This was called `filetype` in earlier versions of WASI.\n//\n//\tenum descriptor-type {\n//\t\tunknown,\n//\t\tblock-device,\n//\t\tcharacter-device,\n//\t\tdirectory,\n//\t\tfifo,\n//\t\tsymbolic-link,\n//\t\tregular-file,\n//\t\tsocket\n//\t}\ntype DescriptorType uint8\n\nconst (\n\t// The type of the descriptor or file is unknown or is different from\n\t// any of the other types specified.\n\tDescriptorTypeUnknown DescriptorType = iota\n\n\t// The descriptor refers to a block device inode.\n\tDescriptorTypeBlockDevice\n\n\t// The descriptor refers to a character device inode.\n\tDescriptorTypeCharacterDevice\n\n\t// The descriptor refers to a directory inode.\n\tDescriptorTypeDirectory\n\n\t// The descriptor refers to a named pipe.\n\tDescriptorTypeFIFO\n\n\t// The file refers to a symbolic link inode.\n\tDescriptorTypeSymbolicLink\n\n\t// The descriptor refers to a regular file inode.\n\tDescriptorTypeRegularFile\n\n\t// The descriptor refers to a socket.\n\tDescriptorTypeSocket\n)\n\nvar _DescriptorTypeStrings = [8]string{\n\t\"unknown\",\n\t\"block-device\",\n\t\"character-device\",\n\t\"directory\",\n\t\"fifo\",\n\t\"symbolic-link\",\n\t\"regular-file\",\n\t\"socket\",\n}\n\n// String implements [fmt.Stringer], returning the enum case name of e.\nfunc (e DescriptorType) String() string {\n\treturn _DescriptorTypeStrings[e]\n}\n\n// MarshalText implements [encoding.TextMarshaler].\nfunc (e DescriptorType) MarshalText() ([]byte, error) {\n\treturn []byte(e.String()), nil\n}\n\n// UnmarshalText implements [encoding.TextUnmarshaler], unmarshaling into an enum\n// case. Returns an error if the supplied text is not one of the enum cases.\nfunc (e *DescriptorType) UnmarshalText(text []byte) error {\n\treturn _DescriptorTypeUnmarshalCase(e, text)\n}\n\nvar _DescriptorTypeUnmarshalCase = cm.CaseUnmarshaler[DescriptorType](_DescriptorTypeStrings[:])\n\n// DescriptorFlags represents the flags \"wasi:filesystem/types@0.2.0#descriptor-flags\".\n//\n// Descriptor flags.\n//\n// Note: This was called `fdflags` in earlier versions of WASI.\n//\n//\tflags descriptor-flags {\n//\t\tread,\n//\t\twrite,\n//\t\tfile-integrity-sync,\n//\t\tdata-integrity-sync,\n//\t\trequested-write-sync,\n//\t\tmutate-directory,\n//\t}\ntype DescriptorFlags uint8\n\nconst (\n\t// Read mode: Data can be read.\n\tDescriptorFlagsRead DescriptorFlags = 1 << iota\n\n\t// Write mode: Data can be written to.\n\tDescriptorFlagsWrite\n\n\t// Request that writes be performed according to synchronized I/O file\n\t// integrity completion. The data stored in the file and the file's\n\t// metadata are synchronized. This is similar to `O_SYNC` in POSIX.\n\t//\n\t// The precise semantics of this operation have not yet been defined for\n\t// WASI. At this time, it should be interpreted as a request, and not a\n\t// requirement.\n\tDescriptorFlagsFileIntegritySync\n\n\t// Request that writes be performed according to synchronized I/O data\n\t// integrity completion. Only the data stored in the file is\n\t// synchronized. This is similar to `O_DSYNC` in POSIX.\n\t//\n\t// The precise semantics of this operation have not yet been defined for\n\t// WASI. At this time, it should be interpreted as a request, and not a\n\t// requirement.\n\tDescriptorFlagsDataIntegritySync\n\n\t// Requests that reads be performed at the same level of integrety\n\t// requested for writes. This is similar to `O_RSYNC` in POSIX.\n\t//\n\t// The precise semantics of this operation have not yet been defined for\n\t// WASI. At this time, it should be interpreted as a request, and not a\n\t// requirement.\n\tDescriptorFlagsRequestedWriteSync\n\n\t// Mutating directories mode: Directory contents may be mutated.\n\t//\n\t// When this flag is unset on a descriptor, operations using the\n\t// descriptor which would create, rename, delete, modify the data or\n\t// metadata of filesystem objects, or obtain another handle which\n\t// would permit any of those, shall fail with `error-code::read-only` if\n\t// they would otherwise succeed.\n\t//\n\t// This may only be set on directories.\n\tDescriptorFlagsMutateDirectory\n)\n\n// PathFlags represents the flags \"wasi:filesystem/types@0.2.0#path-flags\".\n//\n// Flags determining the method of how paths are resolved.\n//\n//\tflags path-flags {\n//\t\tsymlink-follow,\n//\t}\ntype PathFlags uint8\n\nconst (\n\t// As long as the resolved path corresponds to a symbolic link, it is\n\t// expanded.\n\tPathFlagsSymlinkFollow PathFlags = 1 << iota\n)\n\n// OpenFlags represents the flags \"wasi:filesystem/types@0.2.0#open-flags\".\n//\n// Open flags used by `open-at`.\n//\n//\tflags open-flags {\n//\t\tcreate,\n//\t\tdirectory,\n//\t\texclusive,\n//\t\ttruncate,\n//\t}\ntype OpenFlags uint8\n\nconst (\n\t// Create file if it does not exist, similar to `O_CREAT` in POSIX.\n\tOpenFlagsCreate OpenFlags = 1 << iota\n\n\t// Fail if not a directory, similar to `O_DIRECTORY` in POSIX.\n\tOpenFlagsDirectory\n\n\t// Fail if file already exists, similar to `O_EXCL` in POSIX.\n\tOpenFlagsExclusive\n\n\t// Truncate file to size 0, similar to `O_TRUNC` in POSIX.\n\tOpenFlagsTruncate\n)\n\n// LinkCount represents the u64 \"wasi:filesystem/types@0.2.0#link-count\".\n//\n// Number of hard links to an inode.\n//\n//\ttype link-count = u64\ntype LinkCount uint64\n\n// DescriptorStat represents the record \"wasi:filesystem/types@0.2.0#descriptor-stat\".\n//\n// File attributes.\n//\n// Note: This was called `filestat` in earlier versions of WASI.\n//\n//\trecord descriptor-stat {\n//\t\t%type: descriptor-type,\n//\t\tlink-count: link-count,\n//\t\tsize: filesize,\n//\t\tdata-access-timestamp: option<datetime>,\n//\t\tdata-modification-timestamp: option<datetime>,\n//\t\tstatus-change-timestamp: option<datetime>,\n//\t}\ntype DescriptorStat struct {\n\t_ cm.HostLayout `json:\"-\"`\n\t// File type.\n\tType DescriptorType `json:\"type\"`\n\n\t// Number of hard links to the file.\n\tLinkCount LinkCount `json:\"link-count\"`\n\n\t// For regular files, the file size in bytes. For symbolic links, the\n\t// length in bytes of the pathname contained in the symbolic link.\n\tSize FileSize `json:\"size\"`\n\n\t// Last data access timestamp.\n\t//\n\t// If the `option` is none, the platform doesn't maintain an access\n\t// timestamp for this file.\n\tDataAccessTimestamp cm.Option[DateTime] `json:\"data-access-timestamp\"`\n\n\t// Last data modification timestamp.\n\t//\n\t// If the `option` is none, the platform doesn't maintain a\n\t// modification timestamp for this file.\n\tDataModificationTimestamp cm.Option[DateTime] `json:\"data-modification-timestamp\"`\n\n\t// Last file status-change timestamp.\n\t//\n\t// If the `option` is none, the platform doesn't maintain a\n\t// status-change timestamp for this file.\n\tStatusChangeTimestamp cm.Option[DateTime] `json:\"status-change-timestamp\"`\n}\n\n// NewTimestamp represents the variant \"wasi:filesystem/types@0.2.0#new-timestamp\".\n//\n// When setting a timestamp, this gives the value to set it to.\n//\n//\tvariant new-timestamp {\n//\t\tno-change,\n//\t\tnow,\n//\t\ttimestamp(datetime),\n//\t}\ntype NewTimestamp cm.Variant[uint8, DateTime, DateTime]\n\n// NewTimestampNoChange returns a [NewTimestamp] of case \"no-change\".\n//\n// Leave the timestamp set to its previous value.\nfunc NewTimestampNoChange() NewTimestamp {\n\tvar data struct{}\n\treturn cm.New[NewTimestamp](0, data)\n}\n\n// NoChange returns true if [NewTimestamp] represents the variant case \"no-change\".\nfunc (self *NewTimestamp) NoChange() bool {\n\treturn self.Tag() == 0\n}\n\n// NewTimestampNow returns a [NewTimestamp] of case \"now\".\n//\n// Set the timestamp to the current time of the system clock associated\n// with the filesystem.\nfunc NewTimestampNow() NewTimestamp {\n\tvar data struct{}\n\treturn cm.New[NewTimestamp](1, data)\n}\n\n// Now returns true if [NewTimestamp] represents the variant case \"now\".\nfunc (self *NewTimestamp) Now() bool {\n\treturn self.Tag() == 1\n}\n\n// NewTimestampTimestamp returns a [NewTimestamp] of case \"timestamp\".\n//\n// Set the timestamp to the given value.\nfunc NewTimestampTimestamp(data DateTime) NewTimestamp {\n\treturn cm.New[NewTimestamp](2, data)\n}\n\n// Timestamp returns a non-nil *[DateTime] if [NewTimestamp] represents the variant case \"timestamp\".\nfunc (self *NewTimestamp) Timestamp() *DateTime {\n\treturn cm.Case[DateTime](self, 2)\n}\n\nvar _NewTimestampStrings = [3]string{\n\t\"no-change\",\n\t\"now\",\n\t\"timestamp\",\n}\n\n// String implements [fmt.Stringer], returning the variant case name of v.\nfunc (v NewTimestamp) String() string {\n\treturn _NewTimestampStrings[v.Tag()]\n}\n\n// DirectoryEntry represents the record \"wasi:filesystem/types@0.2.0#directory-entry\".\n//\n// A directory entry.\n//\n//\trecord directory-entry {\n//\t\t%type: descriptor-type,\n//\t\tname: string,\n//\t}\ntype DirectoryEntry struct {\n\t_ cm.HostLayout `json:\"-\"`\n\t// The type of the file referred to by this directory entry.\n\tType DescriptorType `json:\"type\"`\n\n\t// The name of the object.\n\tName string `json:\"name\"`\n}\n\n// ErrorCode represents the enum \"wasi:filesystem/types@0.2.0#error-code\".\n//\n// Error codes returned by functions, similar to `errno` in POSIX.\n// Not all of these error codes are returned by the functions provided by this\n// API; some are used in higher-level library layers, and others are provided\n// merely for alignment with POSIX.\n//\n//\tenum error-code {\n//\t\taccess,\n//\t\twould-block,\n//\t\talready,\n//\t\tbad-descriptor,\n//\t\tbusy,\n//\t\tdeadlock,\n//\t\tquota,\n//\t\texist,\n//\t\tfile-too-large,\n//\t\tillegal-byte-sequence,\n//\t\tin-progress,\n//\t\tinterrupted,\n//\t\tinvalid,\n//\t\tio,\n//\t\tis-directory,\n//\t\tloop,\n//\t\ttoo-many-links,\n//\t\tmessage-size,\n//\t\tname-too-long,\n//\t\tno-device,\n//\t\tno-entry,\n//\t\tno-lock,\n//\t\tinsufficient-memory,\n//\t\tinsufficient-space,\n//\t\tnot-directory,\n//\t\tnot-empty,\n//\t\tnot-recoverable,\n//\t\tunsupported,\n//\t\tno-tty,\n//\t\tno-such-device,\n//\t\toverflow,\n//\t\tnot-permitted,\n//\t\tpipe,\n//\t\tread-only,\n//\t\tinvalid-seek,\n//\t\ttext-file-busy,\n//\t\tcross-device\n//\t}\ntype ErrorCode uint8\n\nconst (\n\t// Permission denied, similar to `EACCES` in POSIX.\n\tErrorCodeAccess ErrorCode = iota\n\n\t// Resource unavailable, or operation would block, similar to `EAGAIN` and `EWOULDBLOCK`\n\t// in POSIX.\n\tErrorCodeWouldBlock\n\n\t// Connection already in progress, similar to `EALREADY` in POSIX.\n\tErrorCodeAlready\n\n\t// Bad descriptor, similar to `EBADF` in POSIX.\n\tErrorCodeBadDescriptor\n\n\t// Device or resource busy, similar to `EBUSY` in POSIX.\n\tErrorCodeBusy\n\n\t// Resource deadlock would occur, similar to `EDEADLK` in POSIX.\n\tErrorCodeDeadlock\n\n\t// Storage quota exceeded, similar to `EDQUOT` in POSIX.\n\tErrorCodeQuota\n\n\t// File exists, similar to `EEXIST` in POSIX.\n\tErrorCodeExist\n\n\t// File too large, similar to `EFBIG` in POSIX.\n\tErrorCodeFileTooLarge\n\n\t// Illegal byte sequence, similar to `EILSEQ` in POSIX.\n\tErrorCodeIllegalByteSequence\n\n\t// Operation in progress, similar to `EINPROGRESS` in POSIX.\n\tErrorCodeInProgress\n\n\t// Interrupted function, similar to `EINTR` in POSIX.\n\tErrorCodeInterrupted\n\n\t// Invalid argument, similar to `EINVAL` in POSIX.\n\tErrorCodeInvalid\n\n\t// I/O error, similar to `EIO` in POSIX.\n\tErrorCodeIO\n\n\t// Is a directory, similar to `EISDIR` in POSIX.\n\tErrorCodeIsDirectory\n\n\t// Too many levels of symbolic links, similar to `ELOOP` in POSIX.\n\tErrorCodeLoop\n\n\t// Too many links, similar to `EMLINK` in POSIX.\n\tErrorCodeTooManyLinks\n\n\t// Message too large, similar to `EMSGSIZE` in POSIX.\n\tErrorCodeMessageSize\n\n\t// Filename too long, similar to `ENAMETOOLONG` in POSIX.\n\tErrorCodeNameTooLong\n\n\t// No such device, similar to `ENODEV` in POSIX.\n\tErrorCodeNoDevice\n\n\t// No such file or directory, similar to `ENOENT` in POSIX.\n\tErrorCodeNoEntry\n\n\t// No locks available, similar to `ENOLCK` in POSIX.\n\tErrorCodeNoLock\n\n\t// Not enough space, similar to `ENOMEM` in POSIX.\n\tErrorCodeInsufficientMemory\n\n\t// No space left on device, similar to `ENOSPC` in POSIX.\n\tErrorCodeInsufficientSpace\n\n\t// Not a directory or a symbolic link to a directory, similar to `ENOTDIR` in POSIX.\n\tErrorCodeNotDirectory\n\n\t// Directory not empty, similar to `ENOTEMPTY` in POSIX.\n\tErrorCodeNotEmpty\n\n\t// State not recoverable, similar to `ENOTRECOVERABLE` in POSIX.\n\tErrorCodeNotRecoverable\n\n\t// Not supported, similar to `ENOTSUP` and `ENOSYS` in POSIX.\n\tErrorCodeUnsupported\n\n\t// Inappropriate I/O control operation, similar to `ENOTTY` in POSIX.\n\tErrorCodeNoTTY\n\n\t// No such device or address, similar to `ENXIO` in POSIX.\n\tErrorCodeNoSuchDevice\n\n\t// Value too large to be stored in data type, similar to `EOVERFLOW` in POSIX.\n\tErrorCodeOverflow\n\n\t// Operation not permitted, similar to `EPERM` in POSIX.\n\tErrorCodeNotPermitted\n\n\t// Broken pipe, similar to `EPIPE` in POSIX.\n\tErrorCodePipe\n\n\t// Read-only file system, similar to `EROFS` in POSIX.\n\tErrorCodeReadOnly\n\n\t// Invalid seek, similar to `ESPIPE` in POSIX.\n\tErrorCodeInvalidSeek\n\n\t// Text file busy, similar to `ETXTBSY` in POSIX.\n\tErrorCodeTextFileBusy\n\n\t// Cross-device link, similar to `EXDEV` in POSIX.\n\tErrorCodeCrossDevice\n)\n\nvar _ErrorCodeStrings = [37]string{\n\t\"access\",\n\t\"would-block\",\n\t\"already\",\n\t\"bad-descriptor\",\n\t\"busy\",\n\t\"deadlock\",\n\t\"quota\",\n\t\"exist\",\n\t\"file-too-large\",\n\t\"illegal-byte-sequence\",\n\t\"in-progress\",\n\t\"interrupted\",\n\t\"invalid\",\n\t\"io\",\n\t\"is-directory\",\n\t\"loop\",\n\t\"too-many-links\",\n\t\"message-size\",\n\t\"name-too-long\",\n\t\"no-device\",\n\t\"no-entry\",\n\t\"no-lock\",\n\t\"insufficient-memory\",\n\t\"insufficient-space\",\n\t\"not-directory\",\n\t\"not-empty\",\n\t\"not-recoverable\",\n\t\"unsupported\",\n\t\"no-tty\",\n\t\"no-such-device\",\n\t\"overflow\",\n\t\"not-permitted\",\n\t\"pipe\",\n\t\"read-only\",\n\t\"invalid-seek\",\n\t\"text-file-busy\",\n\t\"cross-device\",\n}\n\n// String implements [fmt.Stringer], returning the enum case name of e.\nfunc (e ErrorCode) String() string {\n\treturn _ErrorCodeStrings[e]\n}\n\n// MarshalText implements [encoding.TextMarshaler].\nfunc (e ErrorCode) MarshalText() ([]byte, error) {\n\treturn []byte(e.String()), nil\n}\n\n// UnmarshalText implements [encoding.TextUnmarshaler], unmarshaling into an enum\n// case. Returns an error if the supplied text is not one of the enum cases.\nfunc (e *ErrorCode) UnmarshalText(text []byte) error {\n\treturn _ErrorCodeUnmarshalCase(e, text)\n}\n\nvar _ErrorCodeUnmarshalCase = cm.CaseUnmarshaler[ErrorCode](_ErrorCodeStrings[:])\n\n// Advice represents the enum \"wasi:filesystem/types@0.2.0#advice\".\n//\n// File or memory access pattern advisory information.\n//\n//\tenum advice {\n//\t\tnormal,\n//\t\tsequential,\n//\t\trandom,\n//\t\twill-need,\n//\t\tdont-need,\n//\t\tno-reuse\n//\t}\ntype Advice uint8\n\nconst (\n\t// The application has no advice to give on its behavior with respect\n\t// to the specified data.\n\tAdviceNormal Advice = iota\n\n\t// The application expects to access the specified data sequentially\n\t// from lower offsets to higher offsets.\n\tAdviceSequential\n\n\t// The application expects to access the specified data in a random\n\t// order.\n\tAdviceRandom\n\n\t// The application expects to access the specified data in the near\n\t// future.\n\tAdviceWillNeed\n\n\t// The application expects that it will not access the specified data\n\t// in the near future.\n\tAdviceDontNeed\n\n\t// The application expects to access the specified data once and then\n\t// not reuse it thereafter.\n\tAdviceNoReuse\n)\n\nvar _AdviceStrings = [6]string{\n\t\"normal\",\n\t\"sequential\",\n\t\"random\",\n\t\"will-need\",\n\t\"dont-need\",\n\t\"no-reuse\",\n}\n\n// String implements [fmt.Stringer], returning the enum case name of e.\nfunc (e Advice) String() string {\n\treturn _AdviceStrings[e]\n}\n\n// MarshalText implements [encoding.TextMarshaler].\nfunc (e Advice) MarshalText() ([]byte, error) {\n\treturn []byte(e.String()), nil\n}\n\n// UnmarshalText implements [encoding.TextUnmarshaler], unmarshaling into an enum\n// case. Returns an error if the supplied text is not one of the enum cases.\nfunc (e *Advice) UnmarshalText(text []byte) error {\n\treturn _AdviceUnmarshalCase(e, text)\n}\n\nvar _AdviceUnmarshalCase = cm.CaseUnmarshaler[Advice](_AdviceStrings[:])\n\n// MetadataHashValue represents the record \"wasi:filesystem/types@0.2.0#metadata-hash-value\".\n//\n// A 128-bit hash value, split into parts because wasm doesn't have a\n// 128-bit integer type.\n//\n//\trecord metadata-hash-value {\n//\t\tlower: u64,\n//\t\tupper: u64,\n//\t}\ntype MetadataHashValue struct {\n\t_ cm.HostLayout `json:\"-\"`\n\t// 64 bits of a 128-bit hash value.\n\tLower uint64 `json:\"lower\"`\n\n\t// Another 64 bits of a 128-bit hash value.\n\tUpper uint64 `json:\"upper\"`\n}\n\n// Descriptor represents the imported resource \"wasi:filesystem/types@0.2.0#descriptor\".\n//\n// A descriptor is a reference to a filesystem object, which may be a file,\n// directory, named pipe, special file, or other object on which filesystem\n// calls may be made.\n//\n//\tresource descriptor\ntype Descriptor cm.Resource\n\n// ResourceDrop represents the imported resource-drop for resource \"descriptor\".\n//\n// Drops a resource handle.\n//\n//go:nosplit\nfunc (self Descriptor) ResourceDrop() {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_DescriptorResourceDrop((uint32)(self0))\n\treturn\n}\n\n// Advise represents the imported method \"advise\".\n//\n// Provide file advisory information on a descriptor.\n//\n// This is similar to `posix_fadvise` in POSIX.\n//\n//\tadvise: func(offset: filesize, length: filesize, advice: advice) -> result<_, error-code>\n//\n//go:nosplit\nfunc (self Descriptor) Advise(offset FileSize, length FileSize, advice Advice) (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\toffset0 := (uint64)(offset)\n\tlength0 := (uint64)(length)\n\tadvice0 := (uint32)(advice)\n\twasmimport_DescriptorAdvise((uint32)(self0), (uint64)(offset0), (uint64)(length0), (uint32)(advice0), &result)\n\treturn\n}\n\n// AppendViaStream represents the imported method \"append-via-stream\".\n//\n// Return a stream for appending to a file, if available.\n//\n// May fail with an error-code describing why the file cannot be appended.\n//\n// Note: This allows using `write-stream`, which is similar to `write` with\n// `O_APPEND` in in POSIX.\n//\n//\tappend-via-stream: func() -> result<output-stream, error-code>\n//\n//go:nosplit\nfunc (self Descriptor) AppendViaStream() (result cm.Result[OutputStream, OutputStream, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_DescriptorAppendViaStream((uint32)(self0), &result)\n\treturn\n}\n\n// CreateDirectoryAt represents the imported method \"create-directory-at\".\n//\n// Create a directory.\n//\n// Note: This is similar to `mkdirat` in POSIX.\n//\n//\tcreate-directory-at: func(path: string) -> result<_, error-code>\n//\n//go:nosplit\nfunc (self Descriptor) CreateDirectoryAt(path string) (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tpath0, path1 := cm.LowerString(path)\n\twasmimport_DescriptorCreateDirectoryAt((uint32)(self0), (*uint8)(path0), (uint32)(path1), &result)\n\treturn\n}\n\n// GetFlags represents the imported method \"get-flags\".\n//\n// Get flags associated with a descriptor.\n//\n// Note: This returns similar flags to `fcntl(fd, F_GETFL)` in POSIX.\n//\n// Note: This returns the value that was the `fs_flags` value returned\n// from `fdstat_get` in earlier versions of WASI.\n//\n//\tget-flags: func() -> result<descriptor-flags, error-code>\n//\n//go:nosplit\nfunc (self Descriptor) GetFlags() (result cm.Result[DescriptorFlags, DescriptorFlags, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_DescriptorGetFlags((uint32)(self0), &result)\n\treturn\n}\n\n// GetType represents the imported method \"get-type\".\n//\n// Get the dynamic type of a descriptor.\n//\n// Note: This returns the same value as the `type` field of the `fd-stat`\n// returned by `stat`, `stat-at` and similar.\n//\n// Note: This returns similar flags to the `st_mode & S_IFMT` value provided\n// by `fstat` in POSIX.\n//\n// Note: This returns the value that was the `fs_filetype` value returned\n// from `fdstat_get` in earlier versions of WASI.\n//\n//\tget-type: func() -> result<descriptor-type, error-code>\n//\n//go:nosplit\nfunc (self Descriptor) GetType() (result cm.Result[DescriptorType, DescriptorType, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_DescriptorGetType((uint32)(self0), &result)\n\treturn\n}\n\n// IsSameObject represents the imported method \"is-same-object\".\n//\n// Test whether two descriptors refer to the same filesystem object.\n//\n// In POSIX, this corresponds to testing whether the two descriptors have the\n// same device (`st_dev`) and inode (`st_ino` or `d_ino`) numbers.\n// wasi-filesystem does not expose device and inode numbers, so this function\n// may be used instead.\n//\n//\tis-same-object: func(other: borrow<descriptor>) -> bool\n//\n//go:nosplit\nfunc (self Descriptor) IsSameObject(other Descriptor) (result bool) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tother0 := cm.Reinterpret[uint32](other)\n\tresult0 := wasmimport_DescriptorIsSameObject((uint32)(self0), (uint32)(other0))\n\tresult = (bool)(cm.U32ToBool((uint32)(result0)))\n\treturn\n}\n\n// LinkAt represents the imported method \"link-at\".\n//\n// Create a hard link.\n//\n// Note: This is similar to `linkat` in POSIX.\n//\n//\tlink-at: func(old-path-flags: path-flags, old-path: string, new-descriptor: borrow<descriptor>,\n//\tnew-path: string) -> result<_, error-code>\n//\n//go:nosplit\nfunc (self Descriptor) LinkAt(oldPathFlags PathFlags, oldPath string, newDescriptor Descriptor, newPath string) (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\toldPathFlags0 := (uint32)(oldPathFlags)\n\toldPath0, oldPath1 := cm.LowerString(oldPath)\n\tnewDescriptor0 := cm.Reinterpret[uint32](newDescriptor)\n\tnewPath0, newPath1 := cm.LowerString(newPath)\n\twasmimport_DescriptorLinkAt((uint32)(self0), (uint32)(oldPathFlags0), (*uint8)(oldPath0), (uint32)(oldPath1), (uint32)(newDescriptor0), (*uint8)(newPath0), (uint32)(newPath1), &result)\n\treturn\n}\n\n// MetadataHash represents the imported method \"metadata-hash\".\n//\n// Return a hash of the metadata associated with a filesystem object referred\n// to by a descriptor.\n//\n// This returns a hash of the last-modification timestamp and file size, and\n// may also include the inode number, device number, birth timestamp, and\n// other metadata fields that may change when the file is modified or\n// replaced. It may also include a secret value chosen by the\n// implementation and not otherwise exposed.\n//\n// Implementations are encourated to provide the following properties:\n//\n// - If the file is not modified or replaced, the computed hash value should\n// usually not change.\n// - If the object is modified or replaced, the computed hash value should\n// usually change.\n// - The inputs to the hash should not be easily computable from the\n// computed hash.\n//\n// However, none of these is required.\n//\n//\tmetadata-hash: func() -> result<metadata-hash-value, error-code>\n//\n//go:nosplit\nfunc (self Descriptor) MetadataHash() (result cm.Result[MetadataHashValueShape, MetadataHashValue, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_DescriptorMetadataHash((uint32)(self0), &result)\n\treturn\n}\n\n// MetadataHashAt represents the imported method \"metadata-hash-at\".\n//\n// Return a hash of the metadata associated with a filesystem object referred\n// to by a directory descriptor and a relative path.\n//\n// This performs the same hash computation as `metadata-hash`.\n//\n//\tmetadata-hash-at: func(path-flags: path-flags, path: string) -> result<metadata-hash-value,\n//\terror-code>\n//\n//go:nosplit\nfunc (self Descriptor) MetadataHashAt(pathFlags PathFlags, path string) (result cm.Result[MetadataHashValueShape, MetadataHashValue, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tpathFlags0 := (uint32)(pathFlags)\n\tpath0, path1 := cm.LowerString(path)\n\twasmimport_DescriptorMetadataHashAt((uint32)(self0), (uint32)(pathFlags0), (*uint8)(path0), (uint32)(path1), &result)\n\treturn\n}\n\n// OpenAt represents the imported method \"open-at\".\n//\n// Open a file or directory.\n//\n// The returned descriptor is not guaranteed to be the lowest-numbered\n// descriptor not currently open/ it is randomized to prevent applications\n// from depending on making assumptions about indexes, since this is\n// error-prone in multi-threaded contexts. The returned descriptor is\n// guaranteed to be less than 2**31.\n//\n// If `flags` contains `descriptor-flags::mutate-directory`, and the base\n// descriptor doesn't have `descriptor-flags::mutate-directory` set,\n// `open-at` fails with `error-code::read-only`.\n//\n// If `flags` contains `write` or `mutate-directory`, or `open-flags`\n// contains `truncate` or `create`, and the base descriptor doesn't have\n// `descriptor-flags::mutate-directory` set, `open-at` fails with\n// `error-code::read-only`.\n//\n// Note: This is similar to `openat` in POSIX.\n//\n//\topen-at: func(path-flags: path-flags, path: string, open-flags: open-flags, %flags:\n//\tdescriptor-flags) -> result<descriptor, error-code>\n//\n//go:nosplit\nfunc (self Descriptor) OpenAt(pathFlags PathFlags, path string, openFlags OpenFlags, flags DescriptorFlags) (result cm.Result[Descriptor, Descriptor, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tpathFlags0 := (uint32)(pathFlags)\n\tpath0, path1 := cm.LowerString(path)\n\topenFlags0 := (uint32)(openFlags)\n\tflags0 := (uint32)(flags)\n\twasmimport_DescriptorOpenAt((uint32)(self0), (uint32)(pathFlags0), (*uint8)(path0), (uint32)(path1), (uint32)(openFlags0), (uint32)(flags0), &result)\n\treturn\n}\n\n// Read represents the imported method \"read\".\n//\n// Read from a descriptor, without using and updating the descriptor's offset.\n//\n// This function returns a list of bytes containing the data that was\n// read, along with a bool which, when true, indicates that the end of the\n// file was reached. The returned list will contain up to `length` bytes; it\n// may return fewer than requested, if the end of the file is reached or\n// if the I/O operation is interrupted.\n//\n// In the future, this may change to return a `stream<u8, error-code>`.\n//\n// Note: This is similar to `pread` in POSIX.\n//\n//\tread: func(length: filesize, offset: filesize) -> result<tuple<list<u8>, bool>,\n//\terror-code>\n//\n//go:nosplit\nfunc (self Descriptor) Read(length FileSize, offset FileSize) (result cm.Result[TupleListU8BoolShape, cm.Tuple[cm.List[uint8], bool], ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tlength0 := (uint64)(length)\n\toffset0 := (uint64)(offset)\n\twasmimport_DescriptorRead((uint32)(self0), (uint64)(length0), (uint64)(offset0), &result)\n\treturn\n}\n\n// ReadDirectory represents the imported method \"read-directory\".\n//\n// Read directory entries from a directory.\n//\n// On filesystems where directories contain entries referring to themselves\n// and their parents, often named `.` and `..` respectively, these entries\n// are omitted.\n//\n// This always returns a new stream which starts at the beginning of the\n// directory. Multiple streams may be active on the same directory, and they\n// do not interfere with each other.\n//\n//\tread-directory: func() -> result<directory-entry-stream, error-code>\n//\n//go:nosplit\nfunc (self Descriptor) ReadDirectory() (result cm.Result[DirectoryEntryStream, DirectoryEntryStream, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_DescriptorReadDirectory((uint32)(self0), &result)\n\treturn\n}\n\n// ReadViaStream represents the imported method \"read-via-stream\".\n//\n// Return a stream for reading from a file, if available.\n//\n// May fail with an error-code describing why the file cannot be read.\n//\n// Multiple read, write, and append streams may be active on the same open\n// file and they do not interfere with each other.\n//\n// Note: This allows using `read-stream`, which is similar to `read` in POSIX.\n//\n//\tread-via-stream: func(offset: filesize) -> result<input-stream, error-code>\n//\n//go:nosplit\nfunc (self Descriptor) ReadViaStream(offset FileSize) (result cm.Result[InputStream, InputStream, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\toffset0 := (uint64)(offset)\n\twasmimport_DescriptorReadViaStream((uint32)(self0), (uint64)(offset0), &result)\n\treturn\n}\n\n// ReadLinkAt represents the imported method \"readlink-at\".\n//\n// Read the contents of a symbolic link.\n//\n// If the contents contain an absolute or rooted path in the underlying\n// filesystem, this function fails with `error-code::not-permitted`.\n//\n// Note: This is similar to `readlinkat` in POSIX.\n//\n//\treadlink-at: func(path: string) -> result<string, error-code>\n//\n//go:nosplit\nfunc (self Descriptor) ReadLinkAt(path string) (result cm.Result[string, string, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tpath0, path1 := cm.LowerString(path)\n\twasmimport_DescriptorReadLinkAt((uint32)(self0), (*uint8)(path0), (uint32)(path1), &result)\n\treturn\n}\n\n// RemoveDirectoryAt represents the imported method \"remove-directory-at\".\n//\n// Remove a directory.\n//\n// Return `error-code::not-empty` if the directory is not empty.\n//\n// Note: This is similar to `unlinkat(fd, path, AT_REMOVEDIR)` in POSIX.\n//\n//\tremove-directory-at: func(path: string) -> result<_, error-code>\n//\n//go:nosplit\nfunc (self Descriptor) RemoveDirectoryAt(path string) (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tpath0, path1 := cm.LowerString(path)\n\twasmimport_DescriptorRemoveDirectoryAt((uint32)(self0), (*uint8)(path0), (uint32)(path1), &result)\n\treturn\n}\n\n// RenameAt represents the imported method \"rename-at\".\n//\n// Rename a filesystem object.\n//\n// Note: This is similar to `renameat` in POSIX.\n//\n//\trename-at: func(old-path: string, new-descriptor: borrow<descriptor>, new-path:\n//\tstring) -> result<_, error-code>\n//\n//go:nosplit\nfunc (self Descriptor) RenameAt(oldPath string, newDescriptor Descriptor, newPath string) (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\toldPath0, oldPath1 := cm.LowerString(oldPath)\n\tnewDescriptor0 := cm.Reinterpret[uint32](newDescriptor)\n\tnewPath0, newPath1 := cm.LowerString(newPath)\n\twasmimport_DescriptorRenameAt((uint32)(self0), (*uint8)(oldPath0), (uint32)(oldPath1), (uint32)(newDescriptor0), (*uint8)(newPath0), (uint32)(newPath1), &result)\n\treturn\n}\n\n// SetSize represents the imported method \"set-size\".\n//\n// Adjust the size of an open file. If this increases the file's size, the\n// extra bytes are filled with zeros.\n//\n// Note: This was called `fd_filestat_set_size` in earlier versions of WASI.\n//\n//\tset-size: func(size: filesize) -> result<_, error-code>\n//\n//go:nosplit\nfunc (self Descriptor) SetSize(size FileSize) (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tsize0 := (uint64)(size)\n\twasmimport_DescriptorSetSize((uint32)(self0), (uint64)(size0), &result)\n\treturn\n}\n\n// SetTimes represents the imported method \"set-times\".\n//\n// Adjust the timestamps of an open file or directory.\n//\n// Note: This is similar to `futimens` in POSIX.\n//\n// Note: This was called `fd_filestat_set_times` in earlier versions of WASI.\n//\n//\tset-times: func(data-access-timestamp: new-timestamp, data-modification-timestamp:\n//\tnew-timestamp) -> result<_, error-code>\n//\n//go:nosplit\nfunc (self Descriptor) SetTimes(dataAccessTimestamp NewTimestamp, dataModificationTimestamp NewTimestamp) (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tdataAccessTimestamp0, dataAccessTimestamp1, dataAccessTimestamp2 := lower_NewTimestamp(dataAccessTimestamp)\n\tdataModificationTimestamp0, dataModificationTimestamp1, dataModificationTimestamp2 := lower_NewTimestamp(dataModificationTimestamp)\n\twasmimport_DescriptorSetTimes((uint32)(self0), (uint32)(dataAccessTimestamp0), (uint64)(dataAccessTimestamp1), (uint32)(dataAccessTimestamp2), (uint32)(dataModificationTimestamp0), (uint64)(dataModificationTimestamp1), (uint32)(dataModificationTimestamp2), &result)\n\treturn\n}\n\n// SetTimesAt represents the imported method \"set-times-at\".\n//\n// Adjust the timestamps of a file or directory.\n//\n// Note: This is similar to `utimensat` in POSIX.\n//\n// Note: This was called `path_filestat_set_times` in earlier versions of\n// WASI.\n//\n//\tset-times-at: func(path-flags: path-flags, path: string, data-access-timestamp:\n//\tnew-timestamp, data-modification-timestamp: new-timestamp) -> result<_, error-code>\n//\n//go:nosplit\nfunc (self Descriptor) SetTimesAt(pathFlags PathFlags, path string, dataAccessTimestamp NewTimestamp, dataModificationTimestamp NewTimestamp) (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tpathFlags0 := (uint32)(pathFlags)\n\tpath0, path1 := cm.LowerString(path)\n\tdataAccessTimestamp0, dataAccessTimestamp1, dataAccessTimestamp2 := lower_NewTimestamp(dataAccessTimestamp)\n\tdataModificationTimestamp0, dataModificationTimestamp1, dataModificationTimestamp2 := lower_NewTimestamp(dataModificationTimestamp)\n\twasmimport_DescriptorSetTimesAt((uint32)(self0), (uint32)(pathFlags0), (*uint8)(path0), (uint32)(path1), (uint32)(dataAccessTimestamp0), (uint64)(dataAccessTimestamp1), (uint32)(dataAccessTimestamp2), (uint32)(dataModificationTimestamp0), (uint64)(dataModificationTimestamp1), (uint32)(dataModificationTimestamp2), &result)\n\treturn\n}\n\n// Stat represents the imported method \"stat\".\n//\n// Return the attributes of an open file or directory.\n//\n// Note: This is similar to `fstat` in POSIX, except that it does not return\n// device and inode information. For testing whether two descriptors refer to\n// the same underlying filesystem object, use `is-same-object`. To obtain\n// additional data that can be used do determine whether a file has been\n// modified, use `metadata-hash`.\n//\n// Note: This was called `fd_filestat_get` in earlier versions of WASI.\n//\n//\tstat: func() -> result<descriptor-stat, error-code>\n//\n//go:nosplit\nfunc (self Descriptor) Stat() (result cm.Result[DescriptorStatShape, DescriptorStat, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_DescriptorStat((uint32)(self0), &result)\n\treturn\n}\n\n// StatAt represents the imported method \"stat-at\".\n//\n// Return the attributes of a file or directory.\n//\n// Note: This is similar to `fstatat` in POSIX, except that it does not\n// return device and inode information. See the `stat` description for a\n// discussion of alternatives.\n//\n// Note: This was called `path_filestat_get` in earlier versions of WASI.\n//\n//\tstat-at: func(path-flags: path-flags, path: string) -> result<descriptor-stat,\n//\terror-code>\n//\n//go:nosplit\nfunc (self Descriptor) StatAt(pathFlags PathFlags, path string) (result cm.Result[DescriptorStatShape, DescriptorStat, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tpathFlags0 := (uint32)(pathFlags)\n\tpath0, path1 := cm.LowerString(path)\n\twasmimport_DescriptorStatAt((uint32)(self0), (uint32)(pathFlags0), (*uint8)(path0), (uint32)(path1), &result)\n\treturn\n}\n\n// SymlinkAt represents the imported method \"symlink-at\".\n//\n// Create a symbolic link (also known as a \"symlink\").\n//\n// If `old-path` starts with `/`, the function fails with\n// `error-code::not-permitted`.\n//\n// Note: This is similar to `symlinkat` in POSIX.\n//\n//\tsymlink-at: func(old-path: string, new-path: string) -> result<_, error-code>\n//\n//go:nosplit\nfunc (self Descriptor) SymlinkAt(oldPath string, newPath string) (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\toldPath0, oldPath1 := cm.LowerString(oldPath)\n\tnewPath0, newPath1 := cm.LowerString(newPath)\n\twasmimport_DescriptorSymlinkAt((uint32)(self0), (*uint8)(oldPath0), (uint32)(oldPath1), (*uint8)(newPath0), (uint32)(newPath1), &result)\n\treturn\n}\n\n// Sync represents the imported method \"sync\".\n//\n// Synchronize the data and metadata of a file to disk.\n//\n// This function succeeds with no effect if the file descriptor is not\n// opened for writing.\n//\n// Note: This is similar to `fsync` in POSIX.\n//\n//\tsync: func() -> result<_, error-code>\n//\n//go:nosplit\nfunc (self Descriptor) Sync() (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_DescriptorSync((uint32)(self0), &result)\n\treturn\n}\n\n// SyncData represents the imported method \"sync-data\".\n//\n// Synchronize the data of a file to disk.\n//\n// This function succeeds with no effect if the file descriptor is not\n// opened for writing.\n//\n// Note: This is similar to `fdatasync` in POSIX.\n//\n//\tsync-data: func() -> result<_, error-code>\n//\n//go:nosplit\nfunc (self Descriptor) SyncData() (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_DescriptorSyncData((uint32)(self0), &result)\n\treturn\n}\n\n// UnlinkFileAt represents the imported method \"unlink-file-at\".\n//\n// Unlink a filesystem object that is not a directory.\n//\n// Return `error-code::is-directory` if the path refers to a directory.\n// Note: This is similar to `unlinkat(fd, path, 0)` in POSIX.\n//\n//\tunlink-file-at: func(path: string) -> result<_, error-code>\n//\n//go:nosplit\nfunc (self Descriptor) UnlinkFileAt(path string) (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tpath0, path1 := cm.LowerString(path)\n\twasmimport_DescriptorUnlinkFileAt((uint32)(self0), (*uint8)(path0), (uint32)(path1), &result)\n\treturn\n}\n\n// Write represents the imported method \"write\".\n//\n// Write to a descriptor, without using and updating the descriptor's offset.\n//\n// It is valid to write past the end of a file; the file is extended to the\n// extent of the write, with bytes between the previous end and the start of\n// the write set to zero.\n//\n// In the future, this may change to take a `stream<u8, error-code>`.\n//\n// Note: This is similar to `pwrite` in POSIX.\n//\n//\twrite: func(buffer: list<u8>, offset: filesize) -> result<filesize, error-code>\n//\n//go:nosplit\nfunc (self Descriptor) Write(buffer cm.List[uint8], offset FileSize) (result cm.Result[uint64, FileSize, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tbuffer0, buffer1 := cm.LowerList(buffer)\n\toffset0 := (uint64)(offset)\n\twasmimport_DescriptorWrite((uint32)(self0), (*uint8)(buffer0), (uint32)(buffer1), (uint64)(offset0), &result)\n\treturn\n}\n\n// WriteViaStream represents the imported method \"write-via-stream\".\n//\n// Return a stream for writing to a file, if available.\n//\n// May fail with an error-code describing why the file cannot be written.\n//\n// Note: This allows using `write-stream`, which is similar to `write` in\n// POSIX.\n//\n//\twrite-via-stream: func(offset: filesize) -> result<output-stream, error-code>\n//\n//go:nosplit\nfunc (self Descriptor) WriteViaStream(offset FileSize) (result cm.Result[OutputStream, OutputStream, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\toffset0 := (uint64)(offset)\n\twasmimport_DescriptorWriteViaStream((uint32)(self0), (uint64)(offset0), &result)\n\treturn\n}\n\n// DirectoryEntryStream represents the imported resource \"wasi:filesystem/types@0.2.0#directory-entry-stream\".\n//\n// A stream of directory entries.\n//\n//\tresource directory-entry-stream\ntype DirectoryEntryStream cm.Resource\n\n// ResourceDrop represents the imported resource-drop for resource \"directory-entry-stream\".\n//\n// Drops a resource handle.\n//\n//go:nosplit\nfunc (self DirectoryEntryStream) ResourceDrop() {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_DirectoryEntryStreamResourceDrop((uint32)(self0))\n\treturn\n}\n\n// ReadDirectoryEntry represents the imported method \"read-directory-entry\".\n//\n// Read a single directory entry from a `directory-entry-stream`.\n//\n//\tread-directory-entry: func() -> result<option<directory-entry>, error-code>\n//\n//go:nosplit\nfunc (self DirectoryEntryStream) ReadDirectoryEntry() (result cm.Result[OptionDirectoryEntryShape, cm.Option[DirectoryEntry], ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_DirectoryEntryStreamReadDirectoryEntry((uint32)(self0), &result)\n\treturn\n}\n\n// FilesystemErrorCode represents the imported function \"filesystem-error-code\".\n//\n// Attempts to extract a filesystem-related `error-code` from the stream\n// `error` provided.\n//\n// Stream operations which return `stream-error::last-operation-failed`\n// have a payload with more information about the operation that failed.\n// This payload can be passed through to this function to see if there's\n// filesystem-related information about the error to return.\n//\n// Note that this function is fallible because not all stream-related\n// errors are filesystem-related errors.\n//\n//\tfilesystem-error-code: func(err: borrow<error>) -> option<error-code>\n//\n//go:nosplit\nfunc FilesystemErrorCode(err Error) (result cm.Option[ErrorCode]) {\n\terr0 := cm.Reinterpret[uint32](err)\n\twasmimport_FilesystemErrorCode((uint32)(err0), &result)\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/io/v0.2.0/error/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/io/v0.2.0/error/error.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage ioerror\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:io@0.2.0\".\n\n//go:wasmimport wasi:io/error@0.2.0 [resource-drop]error\n//go:noescape\nfunc wasmimport_ErrorResourceDrop(self0 uint32)\n\n//go:wasmimport wasi:io/error@0.2.0 [method]error.to-debug-string\n//go:noescape\nfunc wasmimport_ErrorToDebugString(self0 uint32, result *string)\n"
  },
  {
    "path": "src/internal/wasi/io/v0.2.0/error/error.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package ioerror represents the imported interface \"wasi:io/error@0.2.0\".\npackage ioerror\n\nimport (\n\t\"internal/cm\"\n)\n\n// Error represents the imported resource \"wasi:io/error@0.2.0#error\".\n//\n// A resource which represents some error information.\n//\n// The only method provided by this resource is `to-debug-string`,\n// which provides some human-readable information about the error.\n//\n// In the `wasi:io` package, this resource is returned through the\n// `wasi:io/streams/stream-error` type.\n//\n// To provide more specific error information, other interfaces may\n// provide functions to further \"downcast\" this error into more specific\n// error information. For example, `error`s returned in streams derived\n// from filesystem types to be described using the filesystem's own\n// error-code type, using the function\n// `wasi:filesystem/types/filesystem-error-code`, which takes a parameter\n// `borrow<error>` and returns\n// `option<wasi:filesystem/types/error-code>`.\n//\n// The set of functions which can \"downcast\" an `error` into a more\n// concrete type is open.\n//\n//\tresource error\ntype Error cm.Resource\n\n// ResourceDrop represents the imported resource-drop for resource \"error\".\n//\n// Drops a resource handle.\n//\n//go:nosplit\nfunc (self Error) ResourceDrop() {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_ErrorResourceDrop((uint32)(self0))\n\treturn\n}\n\n// ToDebugString represents the imported method \"to-debug-string\".\n//\n// Returns a string that is suitable to assist humans in debugging\n// this error.\n//\n// WARNING: The returned string should not be consumed mechanically!\n// It may change across platforms, hosts, or other implementation\n// details. Parsing this string is a major platform-compatibility\n// hazard.\n//\n//\tto-debug-string: func() -> string\n//\n//go:nosplit\nfunc (self Error) ToDebugString() (result string) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_ErrorToDebugString((uint32)(self0), &result)\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/io/v0.2.0/poll/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/io/v0.2.0/poll/poll.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage poll\n\nimport (\n\t\"internal/cm\"\n)\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:io@0.2.0\".\n\n//go:wasmimport wasi:io/poll@0.2.0 [resource-drop]pollable\n//go:noescape\nfunc wasmimport_PollableResourceDrop(self0 uint32)\n\n//go:wasmimport wasi:io/poll@0.2.0 [method]pollable.block\n//go:noescape\nfunc wasmimport_PollableBlock(self0 uint32)\n\n//go:wasmimport wasi:io/poll@0.2.0 [method]pollable.ready\n//go:noescape\nfunc wasmimport_PollableReady(self0 uint32) (result0 uint32)\n\n//go:wasmimport wasi:io/poll@0.2.0 poll\n//go:noescape\nfunc wasmimport_Poll(in0 *Pollable, in1 uint32, result *cm.List[uint32])\n"
  },
  {
    "path": "src/internal/wasi/io/v0.2.0/poll/poll.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package poll represents the imported interface \"wasi:io/poll@0.2.0\".\n//\n// A poll API intended to let users wait for I/O events on multiple handles\n// at once.\npackage poll\n\nimport (\n\t\"internal/cm\"\n)\n\n// Pollable represents the imported resource \"wasi:io/poll@0.2.0#pollable\".\n//\n// `pollable` represents a single I/O event which may be ready, or not.\n//\n//\tresource pollable\ntype Pollable cm.Resource\n\n// ResourceDrop represents the imported resource-drop for resource \"pollable\".\n//\n// Drops a resource handle.\n//\n//go:nosplit\nfunc (self Pollable) ResourceDrop() {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_PollableResourceDrop((uint32)(self0))\n\treturn\n}\n\n// Block represents the imported method \"block\".\n//\n// `block` returns immediately if the pollable is ready, and otherwise\n// blocks until ready.\n//\n// This function is equivalent to calling `poll.poll` on a list\n// containing only this pollable.\n//\n//\tblock: func()\n//\n//go:nosplit\nfunc (self Pollable) Block() {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_PollableBlock((uint32)(self0))\n\treturn\n}\n\n// Ready represents the imported method \"ready\".\n//\n// Return the readiness of a pollable. This function never blocks.\n//\n// Returns `true` when the pollable is ready, and `false` otherwise.\n//\n//\tready: func() -> bool\n//\n//go:nosplit\nfunc (self Pollable) Ready() (result bool) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tresult0 := wasmimport_PollableReady((uint32)(self0))\n\tresult = (bool)(cm.U32ToBool((uint32)(result0)))\n\treturn\n}\n\n// Poll represents the imported function \"poll\".\n//\n// Poll for completion on a set of pollables.\n//\n// This function takes a list of pollables, which identify I/O sources of\n// interest, and waits until one or more of the events is ready for I/O.\n//\n// The result `list<u32>` contains one or more indices of handles in the\n// argument list that is ready for I/O.\n//\n// If the list contains more elements than can be indexed with a `u32`\n// value, this function traps.\n//\n// A timeout can be implemented by adding a pollable from the\n// wasi-clocks API to the list.\n//\n// This function does not return a `result`; polling in itself does not\n// do any I/O so it doesn't fail. If any of the I/O sources identified by\n// the pollables has an error, it is indicated by marking the source as\n// being reaedy for I/O.\n//\n//\tpoll: func(in: list<borrow<pollable>>) -> list<u32>\n//\n//go:nosplit\nfunc Poll(in cm.List[Pollable]) (result cm.List[uint32]) {\n\tin0, in1 := cm.LowerList(in)\n\twasmimport_Poll((*Pollable)(in0), (uint32)(in1), &result)\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/io/v0.2.0/streams/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/io/v0.2.0/streams/streams.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage streams\n\nimport (\n\t\"internal/cm\"\n)\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:io@0.2.0\".\n\n//go:wasmimport wasi:io/streams@0.2.0 [resource-drop]input-stream\n//go:noescape\nfunc wasmimport_InputStreamResourceDrop(self0 uint32)\n\n//go:wasmimport wasi:io/streams@0.2.0 [method]input-stream.blocking-read\n//go:noescape\nfunc wasmimport_InputStreamBlockingRead(self0 uint32, len0 uint64, result *cm.Result[cm.List[uint8], cm.List[uint8], StreamError])\n\n//go:wasmimport wasi:io/streams@0.2.0 [method]input-stream.blocking-skip\n//go:noescape\nfunc wasmimport_InputStreamBlockingSkip(self0 uint32, len0 uint64, result *cm.Result[uint64, uint64, StreamError])\n\n//go:wasmimport wasi:io/streams@0.2.0 [method]input-stream.read\n//go:noescape\nfunc wasmimport_InputStreamRead(self0 uint32, len0 uint64, result *cm.Result[cm.List[uint8], cm.List[uint8], StreamError])\n\n//go:wasmimport wasi:io/streams@0.2.0 [method]input-stream.skip\n//go:noescape\nfunc wasmimport_InputStreamSkip(self0 uint32, len0 uint64, result *cm.Result[uint64, uint64, StreamError])\n\n//go:wasmimport wasi:io/streams@0.2.0 [method]input-stream.subscribe\n//go:noescape\nfunc wasmimport_InputStreamSubscribe(self0 uint32) (result0 uint32)\n\n//go:wasmimport wasi:io/streams@0.2.0 [resource-drop]output-stream\n//go:noescape\nfunc wasmimport_OutputStreamResourceDrop(self0 uint32)\n\n//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.blocking-flush\n//go:noescape\nfunc wasmimport_OutputStreamBlockingFlush(self0 uint32, result *cm.Result[StreamError, struct{}, StreamError])\n\n//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.blocking-splice\n//go:noescape\nfunc wasmimport_OutputStreamBlockingSplice(self0 uint32, src0 uint32, len0 uint64, result *cm.Result[uint64, uint64, StreamError])\n\n//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.blocking-write-and-flush\n//go:noescape\nfunc wasmimport_OutputStreamBlockingWriteAndFlush(self0 uint32, contents0 *uint8, contents1 uint32, result *cm.Result[StreamError, struct{}, StreamError])\n\n//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.blocking-write-zeroes-and-flush\n//go:noescape\nfunc wasmimport_OutputStreamBlockingWriteZeroesAndFlush(self0 uint32, len0 uint64, result *cm.Result[StreamError, struct{}, StreamError])\n\n//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.check-write\n//go:noescape\nfunc wasmimport_OutputStreamCheckWrite(self0 uint32, result *cm.Result[uint64, uint64, StreamError])\n\n//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.flush\n//go:noescape\nfunc wasmimport_OutputStreamFlush(self0 uint32, result *cm.Result[StreamError, struct{}, StreamError])\n\n//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.splice\n//go:noescape\nfunc wasmimport_OutputStreamSplice(self0 uint32, src0 uint32, len0 uint64, result *cm.Result[uint64, uint64, StreamError])\n\n//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.subscribe\n//go:noescape\nfunc wasmimport_OutputStreamSubscribe(self0 uint32) (result0 uint32)\n\n//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.write\n//go:noescape\nfunc wasmimport_OutputStreamWrite(self0 uint32, contents0 *uint8, contents1 uint32, result *cm.Result[StreamError, struct{}, StreamError])\n\n//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.write-zeroes\n//go:noescape\nfunc wasmimport_OutputStreamWriteZeroes(self0 uint32, len0 uint64, result *cm.Result[StreamError, struct{}, StreamError])\n"
  },
  {
    "path": "src/internal/wasi/io/v0.2.0/streams/streams.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package streams represents the imported interface \"wasi:io/streams@0.2.0\".\n//\n// WASI I/O is an I/O abstraction API which is currently focused on providing\n// stream types.\n//\n// In the future, the component model is expected to add built-in stream types;\n// when it does, they are expected to subsume this API.\npackage streams\n\nimport (\n\t\"internal/cm\"\n\tioerror \"internal/wasi/io/v0.2.0/error\"\n\t\"internal/wasi/io/v0.2.0/poll\"\n)\n\n// Error represents the imported type alias \"wasi:io/streams@0.2.0#error\".\n//\n// See [ioerror.Error] for more information.\ntype Error = ioerror.Error\n\n// Pollable represents the imported type alias \"wasi:io/streams@0.2.0#pollable\".\n//\n// See [poll.Pollable] for more information.\ntype Pollable = poll.Pollable\n\n// StreamError represents the imported variant \"wasi:io/streams@0.2.0#stream-error\".\n//\n// An error for input-stream and output-stream operations.\n//\n//\tvariant stream-error {\n//\t\tlast-operation-failed(error),\n//\t\tclosed,\n//\t}\ntype StreamError cm.Variant[uint8, Error, Error]\n\n// StreamErrorLastOperationFailed returns a [StreamError] of case \"last-operation-failed\".\n//\n// The last operation (a write or flush) failed before completion.\n//\n// More information is available in the `error` payload.\nfunc StreamErrorLastOperationFailed(data Error) StreamError {\n\treturn cm.New[StreamError](0, data)\n}\n\n// LastOperationFailed returns a non-nil *[Error] if [StreamError] represents the variant case \"last-operation-failed\".\nfunc (self *StreamError) LastOperationFailed() *Error {\n\treturn cm.Case[Error](self, 0)\n}\n\n// StreamErrorClosed returns a [StreamError] of case \"closed\".\n//\n// The stream is closed: no more input will be accepted by the\n// stream. A closed output-stream will return this error on all\n// future operations.\nfunc StreamErrorClosed() StreamError {\n\tvar data struct{}\n\treturn cm.New[StreamError](1, data)\n}\n\n// Closed returns true if [StreamError] represents the variant case \"closed\".\nfunc (self *StreamError) Closed() bool {\n\treturn self.Tag() == 1\n}\n\nvar _StreamErrorStrings = [2]string{\n\t\"last-operation-failed\",\n\t\"closed\",\n}\n\n// String implements [fmt.Stringer], returning the variant case name of v.\nfunc (v StreamError) String() string {\n\treturn _StreamErrorStrings[v.Tag()]\n}\n\n// InputStream represents the imported resource \"wasi:io/streams@0.2.0#input-stream\".\n//\n// An input bytestream.\n//\n// `input-stream`s are *non-blocking* to the extent practical on underlying\n// platforms. I/O operations always return promptly; if fewer bytes are\n// promptly available than requested, they return the number of bytes promptly\n// available, which could even be zero. To wait for data to be available,\n// use the `subscribe` function to obtain a `pollable` which can be polled\n// for using `wasi:io/poll`.\n//\n//\tresource input-stream\ntype InputStream cm.Resource\n\n// ResourceDrop represents the imported resource-drop for resource \"input-stream\".\n//\n// Drops a resource handle.\n//\n//go:nosplit\nfunc (self InputStream) ResourceDrop() {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_InputStreamResourceDrop((uint32)(self0))\n\treturn\n}\n\n// BlockingRead represents the imported method \"blocking-read\".\n//\n// Read bytes from a stream, after blocking until at least one byte can\n// be read. Except for blocking, behavior is identical to `read`.\n//\n//\tblocking-read: func(len: u64) -> result<list<u8>, stream-error>\n//\n//go:nosplit\nfunc (self InputStream) BlockingRead(len_ uint64) (result cm.Result[cm.List[uint8], cm.List[uint8], StreamError]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tlen0 := (uint64)(len_)\n\twasmimport_InputStreamBlockingRead((uint32)(self0), (uint64)(len0), &result)\n\treturn\n}\n\n// BlockingSkip represents the imported method \"blocking-skip\".\n//\n// Skip bytes from a stream, after blocking until at least one byte\n// can be skipped. Except for blocking behavior, identical to `skip`.\n//\n//\tblocking-skip: func(len: u64) -> result<u64, stream-error>\n//\n//go:nosplit\nfunc (self InputStream) BlockingSkip(len_ uint64) (result cm.Result[uint64, uint64, StreamError]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tlen0 := (uint64)(len_)\n\twasmimport_InputStreamBlockingSkip((uint32)(self0), (uint64)(len0), &result)\n\treturn\n}\n\n// Read represents the imported method \"read\".\n//\n// Perform a non-blocking read from the stream.\n//\n// When the source of a `read` is binary data, the bytes from the source\n// are returned verbatim. When the source of a `read` is known to the\n// implementation to be text, bytes containing the UTF-8 encoding of the\n// text are returned.\n//\n// This function returns a list of bytes containing the read data,\n// when successful. The returned list will contain up to `len` bytes;\n// it may return fewer than requested, but not more. The list is\n// empty when no bytes are available for reading at this time. The\n// pollable given by `subscribe` will be ready when more bytes are\n// available.\n//\n// This function fails with a `stream-error` when the operation\n// encounters an error, giving `last-operation-failed`, or when the\n// stream is closed, giving `closed`.\n//\n// When the caller gives a `len` of 0, it represents a request to\n// read 0 bytes. If the stream is still open, this call should\n// succeed and return an empty list, or otherwise fail with `closed`.\n//\n// The `len` parameter is a `u64`, which could represent a list of u8 which\n// is not possible to allocate in wasm32, or not desirable to allocate as\n// as a return value by the callee. The callee may return a list of bytes\n// less than `len` in size while more bytes are available for reading.\n//\n//\tread: func(len: u64) -> result<list<u8>, stream-error>\n//\n//go:nosplit\nfunc (self InputStream) Read(len_ uint64) (result cm.Result[cm.List[uint8], cm.List[uint8], StreamError]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tlen0 := (uint64)(len_)\n\twasmimport_InputStreamRead((uint32)(self0), (uint64)(len0), &result)\n\treturn\n}\n\n// Skip represents the imported method \"skip\".\n//\n// Skip bytes from a stream. Returns number of bytes skipped.\n//\n// Behaves identical to `read`, except instead of returning a list\n// of bytes, returns the number of bytes consumed from the stream.\n//\n//\tskip: func(len: u64) -> result<u64, stream-error>\n//\n//go:nosplit\nfunc (self InputStream) Skip(len_ uint64) (result cm.Result[uint64, uint64, StreamError]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tlen0 := (uint64)(len_)\n\twasmimport_InputStreamSkip((uint32)(self0), (uint64)(len0), &result)\n\treturn\n}\n\n// Subscribe represents the imported method \"subscribe\".\n//\n// Create a `pollable` which will resolve once either the specified stream\n// has bytes available to read or the other end of the stream has been\n// closed.\n// The created `pollable` is a child resource of the `input-stream`.\n// Implementations may trap if the `input-stream` is dropped before\n// all derived `pollable`s created with this function are dropped.\n//\n//\tsubscribe: func() -> pollable\n//\n//go:nosplit\nfunc (self InputStream) Subscribe() (result Pollable) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tresult0 := wasmimport_InputStreamSubscribe((uint32)(self0))\n\tresult = cm.Reinterpret[Pollable]((uint32)(result0))\n\treturn\n}\n\n// OutputStream represents the imported resource \"wasi:io/streams@0.2.0#output-stream\".\n//\n// An output bytestream.\n//\n// `output-stream`s are *non-blocking* to the extent practical on\n// underlying platforms. Except where specified otherwise, I/O operations also\n// always return promptly, after the number of bytes that can be written\n// promptly, which could even be zero. To wait for the stream to be ready to\n// accept data, the `subscribe` function to obtain a `pollable` which can be\n// polled for using `wasi:io/poll`.\n//\n//\tresource output-stream\ntype OutputStream cm.Resource\n\n// ResourceDrop represents the imported resource-drop for resource \"output-stream\".\n//\n// Drops a resource handle.\n//\n//go:nosplit\nfunc (self OutputStream) ResourceDrop() {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_OutputStreamResourceDrop((uint32)(self0))\n\treturn\n}\n\n// BlockingFlush represents the imported method \"blocking-flush\".\n//\n// Request to flush buffered output, and block until flush completes\n// and stream is ready for writing again.\n//\n//\tblocking-flush: func() -> result<_, stream-error>\n//\n//go:nosplit\nfunc (self OutputStream) BlockingFlush() (result cm.Result[StreamError, struct{}, StreamError]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_OutputStreamBlockingFlush((uint32)(self0), &result)\n\treturn\n}\n\n// BlockingSplice represents the imported method \"blocking-splice\".\n//\n// Read from one stream and write to another, with blocking.\n//\n// This is similar to `splice`, except that it blocks until the\n// `output-stream` is ready for writing, and the `input-stream`\n// is ready for reading, before performing the `splice`.\n//\n//\tblocking-splice: func(src: borrow<input-stream>, len: u64) -> result<u64, stream-error>\n//\n//go:nosplit\nfunc (self OutputStream) BlockingSplice(src InputStream, len_ uint64) (result cm.Result[uint64, uint64, StreamError]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tsrc0 := cm.Reinterpret[uint32](src)\n\tlen0 := (uint64)(len_)\n\twasmimport_OutputStreamBlockingSplice((uint32)(self0), (uint32)(src0), (uint64)(len0), &result)\n\treturn\n}\n\n// BlockingWriteAndFlush represents the imported method \"blocking-write-and-flush\".\n//\n// Perform a write of up to 4096 bytes, and then flush the stream. Block\n// until all of these operations are complete, or an error occurs.\n//\n// This is a convenience wrapper around the use of `check-write`,\n// `subscribe`, `write`, and `flush`, and is implemented with the\n// following pseudo-code:\n//\n//\tlet pollable = this.subscribe();\n//\twhile !contents.is_empty() {\n//\t    // Wait for the stream to become writable\n//\t    pollable.block();\n//\t    let Ok(n) = this.check-write(); // eliding error handling\n//\t    let len = min(n, contents.len());\n//\t    let (chunk, rest) = contents.split_at(len);\n//\t    this.write(chunk  );            // eliding error handling\n//\t    contents = rest;\n//\t}\n//\tthis.flush();\n//\t// Wait for completion of `flush`\n//\tpollable.block();\n//\t// Check for any errors that arose during `flush`\n//\tlet _ = this.check-write();         // eliding error handling\n//\n//\tblocking-write-and-flush: func(contents: list<u8>) -> result<_, stream-error>\n//\n//go:nosplit\nfunc (self OutputStream) BlockingWriteAndFlush(contents cm.List[uint8]) (result cm.Result[StreamError, struct{}, StreamError]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tcontents0, contents1 := cm.LowerList(contents)\n\twasmimport_OutputStreamBlockingWriteAndFlush((uint32)(self0), (*uint8)(contents0), (uint32)(contents1), &result)\n\treturn\n}\n\n// BlockingWriteZeroesAndFlush represents the imported method \"blocking-write-zeroes-and-flush\".\n//\n// Perform a write of up to 4096 zeroes, and then flush the stream.\n// Block until all of these operations are complete, or an error\n// occurs.\n//\n// This is a convenience wrapper around the use of `check-write`,\n// `subscribe`, `write-zeroes`, and `flush`, and is implemented with\n// the following pseudo-code:\n//\n//\tlet pollable = this.subscribe();\n//\twhile num_zeroes != 0 {\n//\t    // Wait for the stream to become writable\n//\t    pollable.block();\n//\t    let Ok(n) = this.check-write(); // eliding error handling\n//\t    let len = min(n, num_zeroes);\n//\t    this.write-zeroes(len);         // eliding error handling\n//\t    num_zeroes -= len;\n//\t}\n//\tthis.flush();\n//\t// Wait for completion of `flush`\n//\tpollable.block();\n//\t// Check for any errors that arose during `flush`\n//\tlet _ = this.check-write();         // eliding error handling\n//\n//\tblocking-write-zeroes-and-flush: func(len: u64) -> result<_, stream-error>\n//\n//go:nosplit\nfunc (self OutputStream) BlockingWriteZeroesAndFlush(len_ uint64) (result cm.Result[StreamError, struct{}, StreamError]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tlen0 := (uint64)(len_)\n\twasmimport_OutputStreamBlockingWriteZeroesAndFlush((uint32)(self0), (uint64)(len0), &result)\n\treturn\n}\n\n// CheckWrite represents the imported method \"check-write\".\n//\n// Check readiness for writing. This function never blocks.\n//\n// Returns the number of bytes permitted for the next call to `write`,\n// or an error. Calling `write` with more bytes than this function has\n// permitted will trap.\n//\n// When this function returns 0 bytes, the `subscribe` pollable will\n// become ready when this function will report at least 1 byte, or an\n// error.\n//\n//\tcheck-write: func() -> result<u64, stream-error>\n//\n//go:nosplit\nfunc (self OutputStream) CheckWrite() (result cm.Result[uint64, uint64, StreamError]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_OutputStreamCheckWrite((uint32)(self0), &result)\n\treturn\n}\n\n// Flush represents the imported method \"flush\".\n//\n// Request to flush buffered output. This function never blocks.\n//\n// This tells the output-stream that the caller intends any buffered\n// output to be flushed. the output which is expected to be flushed\n// is all that has been passed to `write` prior to this call.\n//\n// Upon calling this function, the `output-stream` will not accept any\n// writes (`check-write` will return `ok(0)`) until the flush has\n// completed. The `subscribe` pollable will become ready when the\n// flush has completed and the stream can accept more writes.\n//\n//\tflush: func() -> result<_, stream-error>\n//\n//go:nosplit\nfunc (self OutputStream) Flush() (result cm.Result[StreamError, struct{}, StreamError]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_OutputStreamFlush((uint32)(self0), &result)\n\treturn\n}\n\n// Splice represents the imported method \"splice\".\n//\n// Read from one stream and write to another.\n//\n// The behavior of splice is equivelant to:\n// 1. calling `check-write` on the `output-stream`\n// 2. calling `read` on the `input-stream` with the smaller of the\n// `check-write` permitted length and the `len` provided to `splice`\n// 3. calling `write` on the `output-stream` with that read data.\n//\n// Any error reported by the call to `check-write`, `read`, or\n// `write` ends the splice and reports that error.\n//\n// This function returns the number of bytes transferred; it may be less\n// than `len`.\n//\n//\tsplice: func(src: borrow<input-stream>, len: u64) -> result<u64, stream-error>\n//\n//go:nosplit\nfunc (self OutputStream) Splice(src InputStream, len_ uint64) (result cm.Result[uint64, uint64, StreamError]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tsrc0 := cm.Reinterpret[uint32](src)\n\tlen0 := (uint64)(len_)\n\twasmimport_OutputStreamSplice((uint32)(self0), (uint32)(src0), (uint64)(len0), &result)\n\treturn\n}\n\n// Subscribe represents the imported method \"subscribe\".\n//\n// Create a `pollable` which will resolve once the output-stream\n// is ready for more writing, or an error has occured. When this\n// pollable is ready, `check-write` will return `ok(n)` with n>0, or an\n// error.\n//\n// If the stream is closed, this pollable is always ready immediately.\n//\n// The created `pollable` is a child resource of the `output-stream`.\n// Implementations may trap if the `output-stream` is dropped before\n// all derived `pollable`s created with this function are dropped.\n//\n//\tsubscribe: func() -> pollable\n//\n//go:nosplit\nfunc (self OutputStream) Subscribe() (result Pollable) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tresult0 := wasmimport_OutputStreamSubscribe((uint32)(self0))\n\tresult = cm.Reinterpret[Pollable]((uint32)(result0))\n\treturn\n}\n\n// Write represents the imported method \"write\".\n//\n// Perform a write. This function never blocks.\n//\n// When the destination of a `write` is binary data, the bytes from\n// `contents` are written verbatim. When the destination of a `write` is\n// known to the implementation to be text, the bytes of `contents` are\n// transcoded from UTF-8 into the encoding of the destination and then\n// written.\n//\n// Precondition: check-write gave permit of Ok(n) and contents has a\n// length of less than or equal to n. Otherwise, this function will trap.\n//\n// returns Err(closed) without writing if the stream has closed since\n// the last call to check-write provided a permit.\n//\n//\twrite: func(contents: list<u8>) -> result<_, stream-error>\n//\n//go:nosplit\nfunc (self OutputStream) Write(contents cm.List[uint8]) (result cm.Result[StreamError, struct{}, StreamError]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tcontents0, contents1 := cm.LowerList(contents)\n\twasmimport_OutputStreamWrite((uint32)(self0), (*uint8)(contents0), (uint32)(contents1), &result)\n\treturn\n}\n\n// WriteZeroes represents the imported method \"write-zeroes\".\n//\n// Write zeroes to a stream.\n//\n// This should be used precisely like `write` with the exact same\n// preconditions (must use check-write first), but instead of\n// passing a list of bytes, you simply pass the number of zero-bytes\n// that should be written.\n//\n//\twrite-zeroes: func(len: u64) -> result<_, stream-error>\n//\n//go:nosplit\nfunc (self OutputStream) WriteZeroes(len_ uint64) (result cm.Result[StreamError, struct{}, StreamError]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tlen0 := (uint64)(len_)\n\twasmimport_OutputStreamWriteZeroes((uint32)(self0), (uint64)(len0), &result)\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/random/v0.2.0/insecure/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/random/v0.2.0/insecure/insecure.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage insecure\n\nimport (\n\t\"internal/cm\"\n)\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:random@0.2.0\".\n\n//go:wasmimport wasi:random/insecure@0.2.0 get-insecure-random-bytes\n//go:noescape\nfunc wasmimport_GetInsecureRandomBytes(len0 uint64, result *cm.List[uint8])\n\n//go:wasmimport wasi:random/insecure@0.2.0 get-insecure-random-u64\n//go:noescape\nfunc wasmimport_GetInsecureRandomU64() (result0 uint64)\n"
  },
  {
    "path": "src/internal/wasi/random/v0.2.0/insecure/insecure.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package insecure represents the imported interface \"wasi:random/insecure@0.2.0\".\n//\n// The insecure interface for insecure pseudo-random numbers.\n//\n// It is intended to be portable at least between Unix-family platforms and\n// Windows.\npackage insecure\n\nimport (\n\t\"internal/cm\"\n)\n\n// GetInsecureRandomBytes represents the imported function \"get-insecure-random-bytes\".\n//\n// Return `len` insecure pseudo-random bytes.\n//\n// This function is not cryptographically secure. Do not use it for\n// anything related to security.\n//\n// There are no requirements on the values of the returned bytes, however\n// implementations are encouraged to return evenly distributed values with\n// a long period.\n//\n//\tget-insecure-random-bytes: func(len: u64) -> list<u8>\n//\n//go:nosplit\nfunc GetInsecureRandomBytes(len_ uint64) (result cm.List[uint8]) {\n\tlen0 := (uint64)(len_)\n\twasmimport_GetInsecureRandomBytes((uint64)(len0), &result)\n\treturn\n}\n\n// GetInsecureRandomU64 represents the imported function \"get-insecure-random-u64\".\n//\n// Return an insecure pseudo-random `u64` value.\n//\n// This function returns the same type of pseudo-random data as\n// `get-insecure-random-bytes`, represented as a `u64`.\n//\n//\tget-insecure-random-u64: func() -> u64\n//\n//go:nosplit\nfunc GetInsecureRandomU64() (result uint64) {\n\tresult0 := wasmimport_GetInsecureRandomU64()\n\tresult = (uint64)((uint64)(result0))\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/random/v0.2.0/insecure-seed/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/random/v0.2.0/insecure-seed/insecure-seed.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage insecureseed\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:random@0.2.0\".\n\n//go:wasmimport wasi:random/insecure-seed@0.2.0 insecure-seed\n//go:noescape\nfunc wasmimport_InsecureSeed(result *[2]uint64)\n"
  },
  {
    "path": "src/internal/wasi/random/v0.2.0/insecure-seed/insecure-seed.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package insecureseed represents the imported interface \"wasi:random/insecure-seed@0.2.0\".\n//\n// The insecure-seed interface for seeding hash-map DoS resistance.\n//\n// It is intended to be portable at least between Unix-family platforms and\n// Windows.\npackage insecureseed\n\n// InsecureSeed represents the imported function \"insecure-seed\".\n//\n// Return a 128-bit value that may contain a pseudo-random value.\n//\n// The returned value is not required to be computed from a CSPRNG, and may\n// even be entirely deterministic. Host implementations are encouraged to\n// provide pseudo-random values to any program exposed to\n// attacker-controlled content, to enable DoS protection built into many\n// languages' hash-map implementations.\n//\n// This function is intended to only be called once, by a source language\n// to initialize Denial Of Service (DoS) protection in its hash-map\n// implementation.\n//\n// # Expected future evolution\n//\n// This will likely be changed to a value import, to prevent it from being\n// called multiple times and potentially used for purposes other than DoS\n// protection.\n//\n//\tinsecure-seed: func() -> tuple<u64, u64>\n//\n//go:nosplit\nfunc InsecureSeed() (result [2]uint64) {\n\twasmimport_InsecureSeed(&result)\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/random/v0.2.0/random/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/random/v0.2.0/random/random.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage random\n\nimport (\n\t\"internal/cm\"\n)\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:random@0.2.0\".\n\n//go:wasmimport wasi:random/random@0.2.0 get-random-bytes\n//go:noescape\nfunc wasmimport_GetRandomBytes(len0 uint64, result *cm.List[uint8])\n\n//go:wasmimport wasi:random/random@0.2.0 get-random-u64\n//go:noescape\nfunc wasmimport_GetRandomU64() (result0 uint64)\n"
  },
  {
    "path": "src/internal/wasi/random/v0.2.0/random/random.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package random represents the imported interface \"wasi:random/random@0.2.0\".\n//\n// WASI Random is a random data API.\n//\n// It is intended to be portable at least between Unix-family platforms and\n// Windows.\npackage random\n\nimport (\n\t\"internal/cm\"\n)\n\n// GetRandomBytes represents the imported function \"get-random-bytes\".\n//\n// Return `len` cryptographically-secure random or pseudo-random bytes.\n//\n// This function must produce data at least as cryptographically secure and\n// fast as an adequately seeded cryptographically-secure pseudo-random\n// number generator (CSPRNG). It must not block, from the perspective of\n// the calling program, under any circumstances, including on the first\n// request and on requests for numbers of bytes. The returned data must\n// always be unpredictable.\n//\n// This function must always return fresh data. Deterministic environments\n// must omit this function, rather than implementing it with deterministic\n// data.\n//\n//\tget-random-bytes: func(len: u64) -> list<u8>\n//\n//go:nosplit\nfunc GetRandomBytes(len_ uint64) (result cm.List[uint8]) {\n\tlen0 := (uint64)(len_)\n\twasmimport_GetRandomBytes((uint64)(len0), &result)\n\treturn\n}\n\n// GetRandomU64 represents the imported function \"get-random-u64\".\n//\n// Return a cryptographically-secure random or pseudo-random `u64` value.\n//\n// This function returns the same type of data as `get-random-bytes`,\n// represented as a `u64`.\n//\n//\tget-random-u64: func() -> u64\n//\n//go:nosplit\nfunc GetRandomU64() (result uint64) {\n\tresult0 := wasmimport_GetRandomU64()\n\tresult = (uint64)((uint64)(result0))\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/sockets/v0.2.0/instance-network/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/sockets/v0.2.0/instance-network/instance-network.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage instancenetwork\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:sockets@0.2.0\".\n\n//go:wasmimport wasi:sockets/instance-network@0.2.0 instance-network\n//go:noescape\nfunc wasmimport_InstanceNetwork() (result0 uint32)\n"
  },
  {
    "path": "src/internal/wasi/sockets/v0.2.0/instance-network/instance-network.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package instancenetwork represents the imported interface \"wasi:sockets/instance-network@0.2.0\".\n//\n// This interface provides a value-export of the default network handle..\npackage instancenetwork\n\nimport (\n\t\"internal/cm\"\n\t\"internal/wasi/sockets/v0.2.0/network\"\n)\n\n// Network represents the imported type alias \"wasi:sockets/instance-network@0.2.0#network\".\n//\n// See [network.Network] for more information.\ntype Network = network.Network\n\n// InstanceNetwork represents the imported function \"instance-network\".\n//\n// Get a handle to the default network.\n//\n//\tinstance-network: func() -> network\n//\n//go:nosplit\nfunc InstanceNetwork() (result Network) {\n\tresult0 := wasmimport_InstanceNetwork()\n\tresult = cm.Reinterpret[Network]((uint32)(result0))\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/sockets/v0.2.0/ip-name-lookup/abi.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage ipnamelookup\n\nimport (\n\t\"internal/cm\"\n\t\"unsafe\"\n)\n\n// OptionIPAddressShape is used for storage in variant or result types.\ntype OptionIPAddressShape struct {\n\t_     cm.HostLayout\n\tshape [unsafe.Sizeof(cm.Option[IPAddress]{})]byte\n}\n"
  },
  {
    "path": "src/internal/wasi/sockets/v0.2.0/ip-name-lookup/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/sockets/v0.2.0/ip-name-lookup/ip-name-lookup.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage ipnamelookup\n\nimport (\n\t\"internal/cm\"\n)\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:sockets@0.2.0\".\n\n//go:wasmimport wasi:sockets/ip-name-lookup@0.2.0 [resource-drop]resolve-address-stream\n//go:noescape\nfunc wasmimport_ResolveAddressStreamResourceDrop(self0 uint32)\n\n//go:wasmimport wasi:sockets/ip-name-lookup@0.2.0 [method]resolve-address-stream.resolve-next-address\n//go:noescape\nfunc wasmimport_ResolveAddressStreamResolveNextAddress(self0 uint32, result *cm.Result[OptionIPAddressShape, cm.Option[IPAddress], ErrorCode])\n\n//go:wasmimport wasi:sockets/ip-name-lookup@0.2.0 [method]resolve-address-stream.subscribe\n//go:noescape\nfunc wasmimport_ResolveAddressStreamSubscribe(self0 uint32) (result0 uint32)\n\n//go:wasmimport wasi:sockets/ip-name-lookup@0.2.0 resolve-addresses\n//go:noescape\nfunc wasmimport_ResolveAddresses(network0 uint32, name0 *uint8, name1 uint32, result *cm.Result[ResolveAddressStream, ResolveAddressStream, ErrorCode])\n"
  },
  {
    "path": "src/internal/wasi/sockets/v0.2.0/ip-name-lookup/ip-name-lookup.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package ipnamelookup represents the imported interface \"wasi:sockets/ip-name-lookup@0.2.0\".\npackage ipnamelookup\n\nimport (\n\t\"internal/cm\"\n\t\"internal/wasi/io/v0.2.0/poll\"\n\t\"internal/wasi/sockets/v0.2.0/network\"\n)\n\n// Pollable represents the imported type alias \"wasi:sockets/ip-name-lookup@0.2.0#pollable\".\n//\n// See [poll.Pollable] for more information.\ntype Pollable = poll.Pollable\n\n// Network represents the imported type alias \"wasi:sockets/ip-name-lookup@0.2.0#network\".\n//\n// See [network.Network] for more information.\ntype Network = network.Network\n\n// ErrorCode represents the type alias \"wasi:sockets/ip-name-lookup@0.2.0#error-code\".\n//\n// See [network.ErrorCode] for more information.\ntype ErrorCode = network.ErrorCode\n\n// IPAddress represents the type alias \"wasi:sockets/ip-name-lookup@0.2.0#ip-address\".\n//\n// See [network.IPAddress] for more information.\ntype IPAddress = network.IPAddress\n\n// ResolveAddressStream represents the imported resource \"wasi:sockets/ip-name-lookup@0.2.0#resolve-address-stream\".\n//\n//\tresource resolve-address-stream\ntype ResolveAddressStream cm.Resource\n\n// ResourceDrop represents the imported resource-drop for resource \"resolve-address-stream\".\n//\n// Drops a resource handle.\n//\n//go:nosplit\nfunc (self ResolveAddressStream) ResourceDrop() {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_ResolveAddressStreamResourceDrop((uint32)(self0))\n\treturn\n}\n\n// ResolveNextAddress represents the imported method \"resolve-next-address\".\n//\n// Returns the next address from the resolver.\n//\n// This function should be called multiple times. On each call, it will\n// return the next address in connection order preference. If all\n// addresses have been exhausted, this function returns `none`.\n//\n// This function never returns IPv4-mapped IPv6 addresses.\n//\n// # Typical errors\n// - `name-unresolvable`:          Name does not exist or has no suitable associated\n// IP addresses. (EAI_NONAME, EAI_NODATA, EAI_ADDRFAMILY)\n// - `temporary-resolver-failure`: A temporary failure in name resolution occurred.\n// (EAI_AGAIN)\n// - `permanent-resolver-failure`: A permanent failure in name resolution occurred.\n// (EAI_FAIL)\n// - `would-block`:                A result is not available yet. (EWOULDBLOCK, EAGAIN)\n//\n//\tresolve-next-address: func() -> result<option<ip-address>, error-code>\n//\n//go:nosplit\nfunc (self ResolveAddressStream) ResolveNextAddress() (result cm.Result[OptionIPAddressShape, cm.Option[IPAddress], ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_ResolveAddressStreamResolveNextAddress((uint32)(self0), &result)\n\treturn\n}\n\n// Subscribe represents the imported method \"subscribe\".\n//\n// Create a `pollable` which will resolve once the stream is ready for I/O.\n//\n// Note: this function is here for WASI Preview2 only.\n// It's planned to be removed when `future` is natively supported in Preview3.\n//\n//\tsubscribe: func() -> pollable\n//\n//go:nosplit\nfunc (self ResolveAddressStream) Subscribe() (result Pollable) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tresult0 := wasmimport_ResolveAddressStreamSubscribe((uint32)(self0))\n\tresult = cm.Reinterpret[Pollable]((uint32)(result0))\n\treturn\n}\n\n// ResolveAddresses represents the imported function \"resolve-addresses\".\n//\n// Resolve an internet host name to a list of IP addresses.\n//\n// Unicode domain names are automatically converted to ASCII using IDNA encoding.\n// If the input is an IP address string, the address is parsed and returned\n// as-is without making any external requests.\n//\n// See the wasi-socket proposal README.md for a comparison with getaddrinfo.\n//\n// This function never blocks. It either immediately fails or immediately\n// returns successfully with a `resolve-address-stream` that can be used\n// to (asynchronously) fetch the results.\n//\n// # Typical errors\n// - `invalid-argument`: `name` is a syntactically invalid domain name or IP address.\n//\n// # References:\n// - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/getaddrinfo.html>\n// - <https://man7.org/linux/man-pages/man3/getaddrinfo.3.html>\n// - <https://learn.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-getaddrinfo>\n// - <https://man.freebsd.org/cgi/man.cgi?query=getaddrinfo&sektion=3>\n//\n//\tresolve-addresses: func(network: borrow<network>, name: string) -> result<resolve-address-stream,\n//\terror-code>\n//\n//go:nosplit\nfunc ResolveAddresses(network_ Network, name string) (result cm.Result[ResolveAddressStream, ResolveAddressStream, ErrorCode]) {\n\tnetwork0 := cm.Reinterpret[uint32](network_)\n\tname0, name1 := cm.LowerString(name)\n\twasmimport_ResolveAddresses((uint32)(network0), (*uint8)(name0), (uint32)(name1), &result)\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/sockets/v0.2.0/network/abi.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage network\n\nimport (\n\t\"internal/cm\"\n\t\"unsafe\"\n)\n\n// IPv6SocketAddressShape is used for storage in variant or result types.\ntype IPv6SocketAddressShape struct {\n\t_     cm.HostLayout\n\tshape [unsafe.Sizeof(IPv6SocketAddress{})]byte\n}\n"
  },
  {
    "path": "src/internal/wasi/sockets/v0.2.0/network/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/sockets/v0.2.0/network/network.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage network\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:sockets@0.2.0\".\n\n//go:wasmimport wasi:sockets/network@0.2.0 [resource-drop]network\n//go:noescape\nfunc wasmimport_NetworkResourceDrop(self0 uint32)\n"
  },
  {
    "path": "src/internal/wasi/sockets/v0.2.0/network/network.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package network represents the imported interface \"wasi:sockets/network@0.2.0\".\npackage network\n\nimport (\n\t\"internal/cm\"\n)\n\n// Network represents the imported resource \"wasi:sockets/network@0.2.0#network\".\n//\n// An opaque resource that represents access to (a subset of) the network.\n// This enables context-based security for networking.\n// There is no need for this to map 1:1 to a physical network interface.\n//\n//\tresource network\ntype Network cm.Resource\n\n// ResourceDrop represents the imported resource-drop for resource \"network\".\n//\n// Drops a resource handle.\n//\n//go:nosplit\nfunc (self Network) ResourceDrop() {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_NetworkResourceDrop((uint32)(self0))\n\treturn\n}\n\n// ErrorCode represents the enum \"wasi:sockets/network@0.2.0#error-code\".\n//\n// Error codes.\n//\n// In theory, every API can return any error code.\n// In practice, API's typically only return the errors documented per API\n// combined with a couple of errors that are always possible:\n// - `unknown`\n// - `access-denied`\n// - `not-supported`\n// - `out-of-memory`\n// - `concurrency-conflict`\n//\n// See each individual API for what the POSIX equivalents are. They sometimes differ\n// per API.\n//\n//\tenum error-code {\n//\t\tunknown,\n//\t\taccess-denied,\n//\t\tnot-supported,\n//\t\tinvalid-argument,\n//\t\tout-of-memory,\n//\t\ttimeout,\n//\t\tconcurrency-conflict,\n//\t\tnot-in-progress,\n//\t\twould-block,\n//\t\tinvalid-state,\n//\t\tnew-socket-limit,\n//\t\taddress-not-bindable,\n//\t\taddress-in-use,\n//\t\tremote-unreachable,\n//\t\tconnection-refused,\n//\t\tconnection-reset,\n//\t\tconnection-aborted,\n//\t\tdatagram-too-large,\n//\t\tname-unresolvable,\n//\t\ttemporary-resolver-failure,\n//\t\tpermanent-resolver-failure\n//\t}\ntype ErrorCode uint8\n\nconst (\n\t// Unknown error\n\tErrorCodeUnknown ErrorCode = iota\n\n\t// Access denied.\n\t//\n\t// POSIX equivalent: EACCES, EPERM\n\tErrorCodeAccessDenied\n\n\t// The operation is not supported.\n\t//\n\t// POSIX equivalent: EOPNOTSUPP\n\tErrorCodeNotSupported\n\n\t// One of the arguments is invalid.\n\t//\n\t// POSIX equivalent: EINVAL\n\tErrorCodeInvalidArgument\n\n\t// Not enough memory to complete the operation.\n\t//\n\t// POSIX equivalent: ENOMEM, ENOBUFS, EAI_MEMORY\n\tErrorCodeOutOfMemory\n\n\t// The operation timed out before it could finish completely.\n\tErrorCodeTimeout\n\n\t// This operation is incompatible with another asynchronous operation that is already\n\t// in progress.\n\t//\n\t// POSIX equivalent: EALREADY\n\tErrorCodeConcurrencyConflict\n\n\t// Trying to finish an asynchronous operation that:\n\t// - has not been started yet, or:\n\t// - was already finished by a previous `finish-*` call.\n\t//\n\t// Note: this is scheduled to be removed when `future`s are natively supported.\n\tErrorCodeNotInProgress\n\n\t// The operation has been aborted because it could not be completed immediately.\n\t//\n\t// Note: this is scheduled to be removed when `future`s are natively supported.\n\tErrorCodeWouldBlock\n\n\t// The operation is not valid in the socket's current state.\n\tErrorCodeInvalidState\n\n\t// A new socket resource could not be created because of a system limit.\n\tErrorCodeNewSocketLimit\n\n\t// A bind operation failed because the provided address is not an address that the\n\t// `network` can bind to.\n\tErrorCodeAddressNotBindable\n\n\t// A bind operation failed because the provided address is already in use or because\n\t// there are no ephemeral ports available.\n\tErrorCodeAddressInUse\n\n\t// The remote address is not reachable\n\tErrorCodeRemoteUnreachable\n\n\t// The TCP connection was forcefully rejected\n\tErrorCodeConnectionRefused\n\n\t// The TCP connection was reset.\n\tErrorCodeConnectionReset\n\n\t// A TCP connection was aborted.\n\tErrorCodeConnectionAborted\n\n\t// The size of a datagram sent to a UDP socket exceeded the maximum\n\t// supported size.\n\tErrorCodeDatagramTooLarge\n\n\t// Name does not exist or has no suitable associated IP addresses.\n\tErrorCodeNameUnresolvable\n\n\t// A temporary failure in name resolution occurred.\n\tErrorCodeTemporaryResolverFailure\n\n\t// A permanent failure in name resolution occurred.\n\tErrorCodePermanentResolverFailure\n)\n\nvar _ErrorCodeStrings = [21]string{\n\t\"unknown\",\n\t\"access-denied\",\n\t\"not-supported\",\n\t\"invalid-argument\",\n\t\"out-of-memory\",\n\t\"timeout\",\n\t\"concurrency-conflict\",\n\t\"not-in-progress\",\n\t\"would-block\",\n\t\"invalid-state\",\n\t\"new-socket-limit\",\n\t\"address-not-bindable\",\n\t\"address-in-use\",\n\t\"remote-unreachable\",\n\t\"connection-refused\",\n\t\"connection-reset\",\n\t\"connection-aborted\",\n\t\"datagram-too-large\",\n\t\"name-unresolvable\",\n\t\"temporary-resolver-failure\",\n\t\"permanent-resolver-failure\",\n}\n\n// String implements [fmt.Stringer], returning the enum case name of e.\nfunc (e ErrorCode) String() string {\n\treturn _ErrorCodeStrings[e]\n}\n\n// MarshalText implements [encoding.TextMarshaler].\nfunc (e ErrorCode) MarshalText() ([]byte, error) {\n\treturn []byte(e.String()), nil\n}\n\n// UnmarshalText implements [encoding.TextUnmarshaler], unmarshaling into an enum\n// case. Returns an error if the supplied text is not one of the enum cases.\nfunc (e *ErrorCode) UnmarshalText(text []byte) error {\n\treturn _ErrorCodeUnmarshalCase(e, text)\n}\n\nvar _ErrorCodeUnmarshalCase = cm.CaseUnmarshaler[ErrorCode](_ErrorCodeStrings[:])\n\n// IPAddressFamily represents the enum \"wasi:sockets/network@0.2.0#ip-address-family\".\n//\n//\tenum ip-address-family {\n//\t\tipv4,\n//\t\tipv6\n//\t}\ntype IPAddressFamily uint8\n\nconst (\n\t// Similar to `AF_INET` in POSIX.\n\tIPAddressFamilyIPv4 IPAddressFamily = iota\n\n\t// Similar to `AF_INET6` in POSIX.\n\tIPAddressFamilyIPv6\n)\n\nvar _IPAddressFamilyStrings = [2]string{\n\t\"ipv4\",\n\t\"ipv6\",\n}\n\n// String implements [fmt.Stringer], returning the enum case name of e.\nfunc (e IPAddressFamily) String() string {\n\treturn _IPAddressFamilyStrings[e]\n}\n\n// MarshalText implements [encoding.TextMarshaler].\nfunc (e IPAddressFamily) MarshalText() ([]byte, error) {\n\treturn []byte(e.String()), nil\n}\n\n// UnmarshalText implements [encoding.TextUnmarshaler], unmarshaling into an enum\n// case. Returns an error if the supplied text is not one of the enum cases.\nfunc (e *IPAddressFamily) UnmarshalText(text []byte) error {\n\treturn _IPAddressFamilyUnmarshalCase(e, text)\n}\n\nvar _IPAddressFamilyUnmarshalCase = cm.CaseUnmarshaler[IPAddressFamily](_IPAddressFamilyStrings[:])\n\n// IPv4Address represents the tuple \"wasi:sockets/network@0.2.0#ipv4-address\".\n//\n//\ttype ipv4-address = tuple<u8, u8, u8, u8>\ntype IPv4Address [4]uint8\n\n// IPv6Address represents the tuple \"wasi:sockets/network@0.2.0#ipv6-address\".\n//\n//\ttype ipv6-address = tuple<u16, u16, u16, u16, u16, u16, u16, u16>\ntype IPv6Address [8]uint16\n\n// IPAddress represents the variant \"wasi:sockets/network@0.2.0#ip-address\".\n//\n//\tvariant ip-address {\n//\t\tipv4(ipv4-address),\n//\t\tipv6(ipv6-address),\n//\t}\ntype IPAddress cm.Variant[uint8, IPv6Address, IPv6Address]\n\n// IPAddressIPv4 returns a [IPAddress] of case \"ipv4\".\nfunc IPAddressIPv4(data IPv4Address) IPAddress {\n\treturn cm.New[IPAddress](0, data)\n}\n\n// IPv4 returns a non-nil *[IPv4Address] if [IPAddress] represents the variant case \"ipv4\".\nfunc (self *IPAddress) IPv4() *IPv4Address {\n\treturn cm.Case[IPv4Address](self, 0)\n}\n\n// IPAddressIPv6 returns a [IPAddress] of case \"ipv6\".\nfunc IPAddressIPv6(data IPv6Address) IPAddress {\n\treturn cm.New[IPAddress](1, data)\n}\n\n// IPv6 returns a non-nil *[IPv6Address] if [IPAddress] represents the variant case \"ipv6\".\nfunc (self *IPAddress) IPv6() *IPv6Address {\n\treturn cm.Case[IPv6Address](self, 1)\n}\n\nvar _IPAddressStrings = [2]string{\n\t\"ipv4\",\n\t\"ipv6\",\n}\n\n// String implements [fmt.Stringer], returning the variant case name of v.\nfunc (v IPAddress) String() string {\n\treturn _IPAddressStrings[v.Tag()]\n}\n\n// IPv4SocketAddress represents the record \"wasi:sockets/network@0.2.0#ipv4-socket-address\".\n//\n//\trecord ipv4-socket-address {\n//\t\tport: u16,\n//\t\taddress: ipv4-address,\n//\t}\ntype IPv4SocketAddress struct {\n\t_ cm.HostLayout `json:\"-\"`\n\t// sin_port\n\tPort uint16 `json:\"port\"`\n\n\t// sin_addr\n\tAddress IPv4Address `json:\"address\"`\n}\n\n// IPv6SocketAddress represents the record \"wasi:sockets/network@0.2.0#ipv6-socket-address\".\n//\n//\trecord ipv6-socket-address {\n//\t\tport: u16,\n//\t\tflow-info: u32,\n//\t\taddress: ipv6-address,\n//\t\tscope-id: u32,\n//\t}\ntype IPv6SocketAddress struct {\n\t_ cm.HostLayout `json:\"-\"`\n\t// sin6_port\n\tPort uint16 `json:\"port\"`\n\n\t// sin6_flowinfo\n\tFlowInfo uint32 `json:\"flow-info\"`\n\n\t// sin6_addr\n\tAddress IPv6Address `json:\"address\"`\n\n\t// sin6_scope_id\n\tScopeID uint32 `json:\"scope-id\"`\n}\n\n// IPSocketAddress represents the variant \"wasi:sockets/network@0.2.0#ip-socket-address\".\n//\n//\tvariant ip-socket-address {\n//\t\tipv4(ipv4-socket-address),\n//\t\tipv6(ipv6-socket-address),\n//\t}\ntype IPSocketAddress cm.Variant[uint8, IPv6SocketAddressShape, IPv6SocketAddress]\n\n// IPSocketAddressIPv4 returns a [IPSocketAddress] of case \"ipv4\".\nfunc IPSocketAddressIPv4(data IPv4SocketAddress) IPSocketAddress {\n\treturn cm.New[IPSocketAddress](0, data)\n}\n\n// IPv4 returns a non-nil *[IPv4SocketAddress] if [IPSocketAddress] represents the variant case \"ipv4\".\nfunc (self *IPSocketAddress) IPv4() *IPv4SocketAddress {\n\treturn cm.Case[IPv4SocketAddress](self, 0)\n}\n\n// IPSocketAddressIPv6 returns a [IPSocketAddress] of case \"ipv6\".\nfunc IPSocketAddressIPv6(data IPv6SocketAddress) IPSocketAddress {\n\treturn cm.New[IPSocketAddress](1, data)\n}\n\n// IPv6 returns a non-nil *[IPv6SocketAddress] if [IPSocketAddress] represents the variant case \"ipv6\".\nfunc (self *IPSocketAddress) IPv6() *IPv6SocketAddress {\n\treturn cm.Case[IPv6SocketAddress](self, 1)\n}\n\nvar _IPSocketAddressStrings = [2]string{\n\t\"ipv4\",\n\t\"ipv6\",\n}\n\n// String implements [fmt.Stringer], returning the variant case name of v.\nfunc (v IPSocketAddress) String() string {\n\treturn _IPSocketAddressStrings[v.Tag()]\n}\n"
  },
  {
    "path": "src/internal/wasi/sockets/v0.2.0/tcp/abi.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage tcp\n\nimport (\n\t\"internal/cm\"\n\t\"internal/wasi/sockets/v0.2.0/network\"\n\t\"unsafe\"\n)\n\n// TupleTCPSocketInputStreamOutputStreamShape is used for storage in variant or result types.\ntype TupleTCPSocketInputStreamOutputStreamShape struct {\n\t_     cm.HostLayout\n\tshape [unsafe.Sizeof(cm.Tuple3[TCPSocket, InputStream, OutputStream]{})]byte\n}\n\n// TupleInputStreamOutputStreamShape is used for storage in variant or result types.\ntype TupleInputStreamOutputStreamShape struct {\n\t_     cm.HostLayout\n\tshape [unsafe.Sizeof(cm.Tuple[InputStream, OutputStream]{})]byte\n}\n\n// IPSocketAddressShape is used for storage in variant or result types.\ntype IPSocketAddressShape struct {\n\t_     cm.HostLayout\n\tshape [unsafe.Sizeof(IPSocketAddress{})]byte\n}\n\nfunc lower_IPv4Address(v network.IPv4Address) (f0 uint32, f1 uint32, f2 uint32, f3 uint32) {\n\tf0 = (uint32)(v[0])\n\tf1 = (uint32)(v[1])\n\tf2 = (uint32)(v[2])\n\tf3 = (uint32)(v[3])\n\treturn\n}\n\nfunc lower_IPv4SocketAddress(v network.IPv4SocketAddress) (f0 uint32, f1 uint32, f2 uint32, f3 uint32, f4 uint32) {\n\tf0 = (uint32)(v.Port)\n\tf1, f2, f3, f4 = lower_IPv4Address(v.Address)\n\treturn\n}\n\nfunc lower_IPv6Address(v network.IPv6Address) (f0 uint32, f1 uint32, f2 uint32, f3 uint32, f4 uint32, f5 uint32, f6 uint32, f7 uint32) {\n\tf0 = (uint32)(v[0])\n\tf1 = (uint32)(v[1])\n\tf2 = (uint32)(v[2])\n\tf3 = (uint32)(v[3])\n\tf4 = (uint32)(v[4])\n\tf5 = (uint32)(v[5])\n\tf6 = (uint32)(v[6])\n\tf7 = (uint32)(v[7])\n\treturn\n}\n\nfunc lower_IPv6SocketAddress(v network.IPv6SocketAddress) (f0 uint32, f1 uint32, f2 uint32, f3 uint32, f4 uint32, f5 uint32, f6 uint32, f7 uint32, f8 uint32, f9 uint32, f10 uint32) {\n\tf0 = (uint32)(v.Port)\n\tf1 = (uint32)(v.FlowInfo)\n\tf2, f3, f4, f5, f6, f7, f8, f9 = lower_IPv6Address(v.Address)\n\tf10 = (uint32)(v.ScopeID)\n\treturn\n}\n\nfunc lower_IPSocketAddress(v network.IPSocketAddress) (f0 uint32, f1 uint32, f2 uint32, f3 uint32, f4 uint32, f5 uint32, f6 uint32, f7 uint32, f8 uint32, f9 uint32, f10 uint32, f11 uint32) {\n\tf0 = (uint32)(v.Tag())\n\tswitch f0 {\n\tcase 0: // ipv4\n\t\tv1, v2, v3, v4, v5 := lower_IPv4SocketAddress(*cm.Case[network.IPv4SocketAddress](&v, 0))\n\t\tf1 = (uint32)(v1)\n\t\tf2 = (uint32)(v2)\n\t\tf3 = (uint32)(v3)\n\t\tf4 = (uint32)(v4)\n\t\tf5 = (uint32)(v5)\n\tcase 1: // ipv6\n\t\tv1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11 := lower_IPv6SocketAddress(*cm.Case[network.IPv6SocketAddress](&v, 1))\n\t\tf1 = (uint32)(v1)\n\t\tf2 = (uint32)(v2)\n\t\tf3 = (uint32)(v3)\n\t\tf4 = (uint32)(v4)\n\t\tf5 = (uint32)(v5)\n\t\tf6 = (uint32)(v6)\n\t\tf7 = (uint32)(v7)\n\t\tf8 = (uint32)(v8)\n\t\tf9 = (uint32)(v9)\n\t\tf10 = (uint32)(v10)\n\t\tf11 = (uint32)(v11)\n\t}\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/sockets/v0.2.0/tcp/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/sockets/v0.2.0/tcp/tcp.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage tcp\n\nimport (\n\t\"internal/cm\"\n)\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:sockets@0.2.0\".\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [resource-drop]tcp-socket\n//go:noescape\nfunc wasmimport_TCPSocketResourceDrop(self0 uint32)\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.accept\n//go:noescape\nfunc wasmimport_TCPSocketAccept(self0 uint32, result *cm.Result[TupleTCPSocketInputStreamOutputStreamShape, cm.Tuple3[TCPSocket, InputStream, OutputStream], ErrorCode])\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.address-family\n//go:noescape\nfunc wasmimport_TCPSocketAddressFamily(self0 uint32) (result0 uint32)\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.finish-bind\n//go:noescape\nfunc wasmimport_TCPSocketFinishBind(self0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.finish-connect\n//go:noescape\nfunc wasmimport_TCPSocketFinishConnect(self0 uint32, result *cm.Result[TupleInputStreamOutputStreamShape, cm.Tuple[InputStream, OutputStream], ErrorCode])\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.finish-listen\n//go:noescape\nfunc wasmimport_TCPSocketFinishListen(self0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.hop-limit\n//go:noescape\nfunc wasmimport_TCPSocketHopLimit(self0 uint32, result *cm.Result[uint8, uint8, ErrorCode])\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.is-listening\n//go:noescape\nfunc wasmimport_TCPSocketIsListening(self0 uint32) (result0 uint32)\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.keep-alive-count\n//go:noescape\nfunc wasmimport_TCPSocketKeepAliveCount(self0 uint32, result *cm.Result[uint32, uint32, ErrorCode])\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.keep-alive-enabled\n//go:noescape\nfunc wasmimport_TCPSocketKeepAliveEnabled(self0 uint32, result *cm.Result[ErrorCode, bool, ErrorCode])\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.keep-alive-idle-time\n//go:noescape\nfunc wasmimport_TCPSocketKeepAliveIdleTime(self0 uint32, result *cm.Result[uint64, Duration, ErrorCode])\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.keep-alive-interval\n//go:noescape\nfunc wasmimport_TCPSocketKeepAliveInterval(self0 uint32, result *cm.Result[uint64, Duration, ErrorCode])\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.local-address\n//go:noescape\nfunc wasmimport_TCPSocketLocalAddress(self0 uint32, result *cm.Result[IPSocketAddressShape, IPSocketAddress, ErrorCode])\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.receive-buffer-size\n//go:noescape\nfunc wasmimport_TCPSocketReceiveBufferSize(self0 uint32, result *cm.Result[uint64, uint64, ErrorCode])\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.remote-address\n//go:noescape\nfunc wasmimport_TCPSocketRemoteAddress(self0 uint32, result *cm.Result[IPSocketAddressShape, IPSocketAddress, ErrorCode])\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.send-buffer-size\n//go:noescape\nfunc wasmimport_TCPSocketSendBufferSize(self0 uint32, result *cm.Result[uint64, uint64, ErrorCode])\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.set-hop-limit\n//go:noescape\nfunc wasmimport_TCPSocketSetHopLimit(self0 uint32, value0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.set-keep-alive-count\n//go:noescape\nfunc wasmimport_TCPSocketSetKeepAliveCount(self0 uint32, value0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.set-keep-alive-enabled\n//go:noescape\nfunc wasmimport_TCPSocketSetKeepAliveEnabled(self0 uint32, value0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.set-keep-alive-idle-time\n//go:noescape\nfunc wasmimport_TCPSocketSetKeepAliveIdleTime(self0 uint32, value0 uint64, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.set-keep-alive-interval\n//go:noescape\nfunc wasmimport_TCPSocketSetKeepAliveInterval(self0 uint32, value0 uint64, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.set-listen-backlog-size\n//go:noescape\nfunc wasmimport_TCPSocketSetListenBacklogSize(self0 uint32, value0 uint64, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.set-receive-buffer-size\n//go:noescape\nfunc wasmimport_TCPSocketSetReceiveBufferSize(self0 uint32, value0 uint64, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.set-send-buffer-size\n//go:noescape\nfunc wasmimport_TCPSocketSetSendBufferSize(self0 uint32, value0 uint64, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.shutdown\n//go:noescape\nfunc wasmimport_TCPSocketShutdown(self0 uint32, shutdownType0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.start-bind\n//go:noescape\nfunc wasmimport_TCPSocketStartBind(self0 uint32, network0 uint32, localAddress0 uint32, localAddress1 uint32, localAddress2 uint32, localAddress3 uint32, localAddress4 uint32, localAddress5 uint32, localAddress6 uint32, localAddress7 uint32, localAddress8 uint32, localAddress9 uint32, localAddress10 uint32, localAddress11 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.start-connect\n//go:noescape\nfunc wasmimport_TCPSocketStartConnect(self0 uint32, network0 uint32, remoteAddress0 uint32, remoteAddress1 uint32, remoteAddress2 uint32, remoteAddress3 uint32, remoteAddress4 uint32, remoteAddress5 uint32, remoteAddress6 uint32, remoteAddress7 uint32, remoteAddress8 uint32, remoteAddress9 uint32, remoteAddress10 uint32, remoteAddress11 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.start-listen\n//go:noescape\nfunc wasmimport_TCPSocketStartListen(self0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.subscribe\n//go:noescape\nfunc wasmimport_TCPSocketSubscribe(self0 uint32) (result0 uint32)\n"
  },
  {
    "path": "src/internal/wasi/sockets/v0.2.0/tcp/tcp.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package tcp represents the imported interface \"wasi:sockets/tcp@0.2.0\".\npackage tcp\n\nimport (\n\t\"internal/cm\"\n\tmonotonicclock \"internal/wasi/clocks/v0.2.0/monotonic-clock\"\n\t\"internal/wasi/io/v0.2.0/poll\"\n\t\"internal/wasi/io/v0.2.0/streams\"\n\t\"internal/wasi/sockets/v0.2.0/network\"\n)\n\n// InputStream represents the imported type alias \"wasi:sockets/tcp@0.2.0#input-stream\".\n//\n// See [streams.InputStream] for more information.\ntype InputStream = streams.InputStream\n\n// OutputStream represents the imported type alias \"wasi:sockets/tcp@0.2.0#output-stream\".\n//\n// See [streams.OutputStream] for more information.\ntype OutputStream = streams.OutputStream\n\n// Pollable represents the imported type alias \"wasi:sockets/tcp@0.2.0#pollable\".\n//\n// See [poll.Pollable] for more information.\ntype Pollable = poll.Pollable\n\n// Duration represents the type alias \"wasi:sockets/tcp@0.2.0#duration\".\n//\n// See [monotonicclock.Duration] for more information.\ntype Duration = monotonicclock.Duration\n\n// Network represents the imported type alias \"wasi:sockets/tcp@0.2.0#network\".\n//\n// See [network.Network] for more information.\ntype Network = network.Network\n\n// ErrorCode represents the type alias \"wasi:sockets/tcp@0.2.0#error-code\".\n//\n// See [network.ErrorCode] for more information.\ntype ErrorCode = network.ErrorCode\n\n// IPSocketAddress represents the type alias \"wasi:sockets/tcp@0.2.0#ip-socket-address\".\n//\n// See [network.IPSocketAddress] for more information.\ntype IPSocketAddress = network.IPSocketAddress\n\n// IPAddressFamily represents the type alias \"wasi:sockets/tcp@0.2.0#ip-address-family\".\n//\n// See [network.IPAddressFamily] for more information.\ntype IPAddressFamily = network.IPAddressFamily\n\n// ShutdownType represents the enum \"wasi:sockets/tcp@0.2.0#shutdown-type\".\n//\n//\tenum shutdown-type {\n//\t\treceive,\n//\t\tsend,\n//\t\tboth\n//\t}\ntype ShutdownType uint8\n\nconst (\n\t// Similar to `SHUT_RD` in POSIX.\n\tShutdownTypeReceive ShutdownType = iota\n\n\t// Similar to `SHUT_WR` in POSIX.\n\tShutdownTypeSend\n\n\t// Similar to `SHUT_RDWR` in POSIX.\n\tShutdownTypeBoth\n)\n\nvar _ShutdownTypeStrings = [3]string{\n\t\"receive\",\n\t\"send\",\n\t\"both\",\n}\n\n// String implements [fmt.Stringer], returning the enum case name of e.\nfunc (e ShutdownType) String() string {\n\treturn _ShutdownTypeStrings[e]\n}\n\n// MarshalText implements [encoding.TextMarshaler].\nfunc (e ShutdownType) MarshalText() ([]byte, error) {\n\treturn []byte(e.String()), nil\n}\n\n// UnmarshalText implements [encoding.TextUnmarshaler], unmarshaling into an enum\n// case. Returns an error if the supplied text is not one of the enum cases.\nfunc (e *ShutdownType) UnmarshalText(text []byte) error {\n\treturn _ShutdownTypeUnmarshalCase(e, text)\n}\n\nvar _ShutdownTypeUnmarshalCase = cm.CaseUnmarshaler[ShutdownType](_ShutdownTypeStrings[:])\n\n// TCPSocket represents the imported resource \"wasi:sockets/tcp@0.2.0#tcp-socket\".\n//\n// A TCP socket resource.\n//\n// The socket can be in one of the following states:\n// - `unbound`\n// - `bind-in-progress`\n// - `bound` (See note below)\n// - `listen-in-progress`\n// - `listening`\n// - `connect-in-progress`\n// - `connected`\n// - `closed`\n// See <https://github.com/WebAssembly/wasi-sockets/TcpSocketOperationalSemantics.md>\n// for a more information.\n//\n// Note: Except where explicitly mentioned, whenever this documentation uses\n// the term \"bound\" without backticks it actually means: in the `bound` state *or\n// higher*.\n// (i.e. `bound`, `listen-in-progress`, `listening`, `connect-in-progress` or `connected`)\n//\n// In addition to the general error codes documented on the\n// `network::error-code` type, TCP socket methods may always return\n// `error(invalid-state)` when in the `closed` state.\n//\n//\tresource tcp-socket\ntype TCPSocket cm.Resource\n\n// ResourceDrop represents the imported resource-drop for resource \"tcp-socket\".\n//\n// Drops a resource handle.\n//\n//go:nosplit\nfunc (self TCPSocket) ResourceDrop() {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_TCPSocketResourceDrop((uint32)(self0))\n\treturn\n}\n\n// Accept represents the imported method \"accept\".\n//\n// Accept a new client socket.\n//\n// The returned socket is bound and in the `connected` state. The following properties\n// are inherited from the listener socket:\n// - `address-family`\n// - `keep-alive-enabled`\n// - `keep-alive-idle-time`\n// - `keep-alive-interval`\n// - `keep-alive-count`\n// - `hop-limit`\n// - `receive-buffer-size`\n// - `send-buffer-size`\n//\n// On success, this function returns the newly accepted client socket along with\n// a pair of streams that can be used to read & write to the connection.\n//\n// # Typical errors\n// - `invalid-state`:      Socket is not in the `listening` state. (EINVAL)\n// - `would-block`:        No pending connections at the moment. (EWOULDBLOCK, EAGAIN)\n// - `connection-aborted`: An incoming connection was pending, but was terminated\n// by the client before this listener could accept it. (ECONNABORTED)\n// - `new-socket-limit`:   The new socket resource could not be created because of\n// a system limit. (EMFILE, ENFILE)\n//\n// # References\n// - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html>\n// - <https://man7.org/linux/man-pages/man2/accept.2.html>\n// - <https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-accept>\n// - <https://man.freebsd.org/cgi/man.cgi?query=accept&sektion=2>\n//\n//\taccept: func() -> result<tuple<tcp-socket, input-stream, output-stream>, error-code>\n//\n//go:nosplit\nfunc (self TCPSocket) Accept() (result cm.Result[TupleTCPSocketInputStreamOutputStreamShape, cm.Tuple3[TCPSocket, InputStream, OutputStream], ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_TCPSocketAccept((uint32)(self0), &result)\n\treturn\n}\n\n// AddressFamily represents the imported method \"address-family\".\n//\n// Whether this is a IPv4 or IPv6 socket.\n//\n// Equivalent to the SO_DOMAIN socket option.\n//\n//\taddress-family: func() -> ip-address-family\n//\n//go:nosplit\nfunc (self TCPSocket) AddressFamily() (result IPAddressFamily) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tresult0 := wasmimport_TCPSocketAddressFamily((uint32)(self0))\n\tresult = (network.IPAddressFamily)((uint32)(result0))\n\treturn\n}\n\n// FinishBind represents the imported method \"finish-bind\".\n//\n//\tfinish-bind: func() -> result<_, error-code>\n//\n//go:nosplit\nfunc (self TCPSocket) FinishBind() (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_TCPSocketFinishBind((uint32)(self0), &result)\n\treturn\n}\n\n// FinishConnect represents the imported method \"finish-connect\".\n//\n//\tfinish-connect: func() -> result<tuple<input-stream, output-stream>, error-code>\n//\n//go:nosplit\nfunc (self TCPSocket) FinishConnect() (result cm.Result[TupleInputStreamOutputStreamShape, cm.Tuple[InputStream, OutputStream], ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_TCPSocketFinishConnect((uint32)(self0), &result)\n\treturn\n}\n\n// FinishListen represents the imported method \"finish-listen\".\n//\n//\tfinish-listen: func() -> result<_, error-code>\n//\n//go:nosplit\nfunc (self TCPSocket) FinishListen() (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_TCPSocketFinishListen((uint32)(self0), &result)\n\treturn\n}\n\n// HopLimit represents the imported method \"hop-limit\".\n//\n// Equivalent to the IP_TTL & IPV6_UNICAST_HOPS socket options.\n//\n// If the provided value is 0, an `invalid-argument` error is returned.\n//\n// # Typical errors\n// - `invalid-argument`:     (set) The TTL value must be 1 or higher.\n//\n//\thop-limit: func() -> result<u8, error-code>\n//\n//go:nosplit\nfunc (self TCPSocket) HopLimit() (result cm.Result[uint8, uint8, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_TCPSocketHopLimit((uint32)(self0), &result)\n\treturn\n}\n\n// IsListening represents the imported method \"is-listening\".\n//\n// Whether the socket is in the `listening` state.\n//\n// Equivalent to the SO_ACCEPTCONN socket option.\n//\n//\tis-listening: func() -> bool\n//\n//go:nosplit\nfunc (self TCPSocket) IsListening() (result bool) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tresult0 := wasmimport_TCPSocketIsListening((uint32)(self0))\n\tresult = (bool)(cm.U32ToBool((uint32)(result0)))\n\treturn\n}\n\n// KeepAliveCount represents the imported method \"keep-alive-count\".\n//\n// The maximum amount of keepalive packets TCP should send before aborting the connection.\n//\n// If the provided value is 0, an `invalid-argument` error is returned.\n// Any other value will never cause an error, but it might be silently clamped and/or\n// rounded.\n// I.e. after setting a value, reading the same setting back may return a different\n// value.\n//\n// Equivalent to the TCP_KEEPCNT socket option.\n//\n// # Typical errors\n// - `invalid-argument`:     (set) The provided value was 0.\n//\n//\tkeep-alive-count: func() -> result<u32, error-code>\n//\n//go:nosplit\nfunc (self TCPSocket) KeepAliveCount() (result cm.Result[uint32, uint32, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_TCPSocketKeepAliveCount((uint32)(self0), &result)\n\treturn\n}\n\n// KeepAliveEnabled represents the imported method \"keep-alive-enabled\".\n//\n// Enables or disables keepalive.\n//\n// The keepalive behavior can be adjusted using:\n// - `keep-alive-idle-time`\n// - `keep-alive-interval`\n// - `keep-alive-count`\n// These properties can be configured while `keep-alive-enabled` is false, but only\n// come into effect when `keep-alive-enabled` is true.\n//\n// Equivalent to the SO_KEEPALIVE socket option.\n//\n//\tkeep-alive-enabled: func() -> result<bool, error-code>\n//\n//go:nosplit\nfunc (self TCPSocket) KeepAliveEnabled() (result cm.Result[ErrorCode, bool, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_TCPSocketKeepAliveEnabled((uint32)(self0), &result)\n\treturn\n}\n\n// KeepAliveIdleTime represents the imported method \"keep-alive-idle-time\".\n//\n// Amount of time the connection has to be idle before TCP starts sending keepalive\n// packets.\n//\n// If the provided value is 0, an `invalid-argument` error is returned.\n// Any other value will never cause an error, but it might be silently clamped and/or\n// rounded.\n// I.e. after setting a value, reading the same setting back may return a different\n// value.\n//\n// Equivalent to the TCP_KEEPIDLE socket option. (TCP_KEEPALIVE on MacOS)\n//\n// # Typical errors\n// - `invalid-argument`:     (set) The provided value was 0.\n//\n//\tkeep-alive-idle-time: func() -> result<duration, error-code>\n//\n//go:nosplit\nfunc (self TCPSocket) KeepAliveIdleTime() (result cm.Result[uint64, Duration, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_TCPSocketKeepAliveIdleTime((uint32)(self0), &result)\n\treturn\n}\n\n// KeepAliveInterval represents the imported method \"keep-alive-interval\".\n//\n// The time between keepalive packets.\n//\n// If the provided value is 0, an `invalid-argument` error is returned.\n// Any other value will never cause an error, but it might be silently clamped and/or\n// rounded.\n// I.e. after setting a value, reading the same setting back may return a different\n// value.\n//\n// Equivalent to the TCP_KEEPINTVL socket option.\n//\n// # Typical errors\n// - `invalid-argument`:     (set) The provided value was 0.\n//\n//\tkeep-alive-interval: func() -> result<duration, error-code>\n//\n//go:nosplit\nfunc (self TCPSocket) KeepAliveInterval() (result cm.Result[uint64, Duration, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_TCPSocketKeepAliveInterval((uint32)(self0), &result)\n\treturn\n}\n\n// LocalAddress represents the imported method \"local-address\".\n//\n// Get the bound local address.\n//\n// POSIX mentions:\n// > If the socket has not been bound to a local name, the value\n// > stored in the object pointed to by `address` is unspecified.\n//\n// WASI is stricter and requires `local-address` to return `invalid-state` when the\n// socket hasn't been bound yet.\n//\n// # Typical errors\n// - `invalid-state`: The socket is not bound to any local address.\n//\n// # References\n// - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html>\n// - <https://man7.org/linux/man-pages/man2/getsockname.2.html>\n// - <https://learn.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-getsockname>\n// - <https://man.freebsd.org/cgi/man.cgi?getsockname>\n//\n//\tlocal-address: func() -> result<ip-socket-address, error-code>\n//\n//go:nosplit\nfunc (self TCPSocket) LocalAddress() (result cm.Result[IPSocketAddressShape, IPSocketAddress, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_TCPSocketLocalAddress((uint32)(self0), &result)\n\treturn\n}\n\n// ReceiveBufferSize represents the imported method \"receive-buffer-size\".\n//\n// The kernel buffer space reserved for sends/receives on this socket.\n//\n// If the provided value is 0, an `invalid-argument` error is returned.\n// Any other value will never cause an error, but it might be silently clamped and/or\n// rounded.\n// I.e. after setting a value, reading the same setting back may return a different\n// value.\n//\n// Equivalent to the SO_RCVBUF and SO_SNDBUF socket options.\n//\n// # Typical errors\n// - `invalid-argument`:     (set) The provided value was 0.\n//\n//\treceive-buffer-size: func() -> result<u64, error-code>\n//\n//go:nosplit\nfunc (self TCPSocket) ReceiveBufferSize() (result cm.Result[uint64, uint64, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_TCPSocketReceiveBufferSize((uint32)(self0), &result)\n\treturn\n}\n\n// RemoteAddress represents the imported method \"remote-address\".\n//\n// Get the remote address.\n//\n// # Typical errors\n// - `invalid-state`: The socket is not connected to a remote address. (ENOTCONN)\n//\n// # References\n// - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html>\n// - <https://man7.org/linux/man-pages/man2/getpeername.2.html>\n// - <https://learn.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-getpeername>\n// - <https://man.freebsd.org/cgi/man.cgi?query=getpeername&sektion=2&n=1>\n//\n//\tremote-address: func() -> result<ip-socket-address, error-code>\n//\n//go:nosplit\nfunc (self TCPSocket) RemoteAddress() (result cm.Result[IPSocketAddressShape, IPSocketAddress, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_TCPSocketRemoteAddress((uint32)(self0), &result)\n\treturn\n}\n\n// SendBufferSize represents the imported method \"send-buffer-size\".\n//\n//\tsend-buffer-size: func() -> result<u64, error-code>\n//\n//go:nosplit\nfunc (self TCPSocket) SendBufferSize() (result cm.Result[uint64, uint64, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_TCPSocketSendBufferSize((uint32)(self0), &result)\n\treturn\n}\n\n// SetHopLimit represents the imported method \"set-hop-limit\".\n//\n//\tset-hop-limit: func(value: u8) -> result<_, error-code>\n//\n//go:nosplit\nfunc (self TCPSocket) SetHopLimit(value uint8) (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tvalue0 := (uint32)(value)\n\twasmimport_TCPSocketSetHopLimit((uint32)(self0), (uint32)(value0), &result)\n\treturn\n}\n\n// SetKeepAliveCount represents the imported method \"set-keep-alive-count\".\n//\n//\tset-keep-alive-count: func(value: u32) -> result<_, error-code>\n//\n//go:nosplit\nfunc (self TCPSocket) SetKeepAliveCount(value uint32) (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tvalue0 := (uint32)(value)\n\twasmimport_TCPSocketSetKeepAliveCount((uint32)(self0), (uint32)(value0), &result)\n\treturn\n}\n\n// SetKeepAliveEnabled represents the imported method \"set-keep-alive-enabled\".\n//\n//\tset-keep-alive-enabled: func(value: bool) -> result<_, error-code>\n//\n//go:nosplit\nfunc (self TCPSocket) SetKeepAliveEnabled(value bool) (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tvalue0 := (uint32)(cm.BoolToU32(value))\n\twasmimport_TCPSocketSetKeepAliveEnabled((uint32)(self0), (uint32)(value0), &result)\n\treturn\n}\n\n// SetKeepAliveIdleTime represents the imported method \"set-keep-alive-idle-time\".\n//\n//\tset-keep-alive-idle-time: func(value: duration) -> result<_, error-code>\n//\n//go:nosplit\nfunc (self TCPSocket) SetKeepAliveIdleTime(value Duration) (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tvalue0 := (uint64)(value)\n\twasmimport_TCPSocketSetKeepAliveIdleTime((uint32)(self0), (uint64)(value0), &result)\n\treturn\n}\n\n// SetKeepAliveInterval represents the imported method \"set-keep-alive-interval\".\n//\n//\tset-keep-alive-interval: func(value: duration) -> result<_, error-code>\n//\n//go:nosplit\nfunc (self TCPSocket) SetKeepAliveInterval(value Duration) (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tvalue0 := (uint64)(value)\n\twasmimport_TCPSocketSetKeepAliveInterval((uint32)(self0), (uint64)(value0), &result)\n\treturn\n}\n\n// SetListenBacklogSize represents the imported method \"set-listen-backlog-size\".\n//\n// Hints the desired listen queue size. Implementations are free to ignore this.\n//\n// If the provided value is 0, an `invalid-argument` error is returned.\n// Any other value will never cause an error, but it might be silently clamped and/or\n// rounded.\n//\n// # Typical errors\n// - `not-supported`:        (set) The platform does not support changing the backlog\n// size after the initial listen.\n// - `invalid-argument`:     (set) The provided value was 0.\n// - `invalid-state`:        (set) The socket is in the `connect-in-progress` or `connected`\n// state.\n//\n//\tset-listen-backlog-size: func(value: u64) -> result<_, error-code>\n//\n//go:nosplit\nfunc (self TCPSocket) SetListenBacklogSize(value uint64) (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tvalue0 := (uint64)(value)\n\twasmimport_TCPSocketSetListenBacklogSize((uint32)(self0), (uint64)(value0), &result)\n\treturn\n}\n\n// SetReceiveBufferSize represents the imported method \"set-receive-buffer-size\".\n//\n//\tset-receive-buffer-size: func(value: u64) -> result<_, error-code>\n//\n//go:nosplit\nfunc (self TCPSocket) SetReceiveBufferSize(value uint64) (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tvalue0 := (uint64)(value)\n\twasmimport_TCPSocketSetReceiveBufferSize((uint32)(self0), (uint64)(value0), &result)\n\treturn\n}\n\n// SetSendBufferSize represents the imported method \"set-send-buffer-size\".\n//\n//\tset-send-buffer-size: func(value: u64) -> result<_, error-code>\n//\n//go:nosplit\nfunc (self TCPSocket) SetSendBufferSize(value uint64) (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tvalue0 := (uint64)(value)\n\twasmimport_TCPSocketSetSendBufferSize((uint32)(self0), (uint64)(value0), &result)\n\treturn\n}\n\n// Shutdown represents the imported method \"shutdown\".\n//\n// Initiate a graceful shutdown.\n//\n// - `receive`: The socket is not expecting to receive any data from\n// the peer. The `input-stream` associated with this socket will be\n// closed. Any data still in the receive queue at time of calling\n// this method will be discarded.\n// - `send`: The socket has no more data to send to the peer. The `output-stream`\n// associated with this socket will be closed and a FIN packet will be sent.\n// - `both`: Same effect as `receive` & `send` combined.\n//\n// This function is idempotent. Shutting a down a direction more than once\n// has no effect and returns `ok`.\n//\n// The shutdown function does not close (drop) the socket.\n//\n// # Typical errors\n// - `invalid-state`: The socket is not in the `connected` state. (ENOTCONN)\n//\n// # References\n// - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/shutdown.html>\n// - <https://man7.org/linux/man-pages/man2/shutdown.2.html>\n// - <https://learn.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-shutdown>\n// - <https://man.freebsd.org/cgi/man.cgi?query=shutdown&sektion=2>\n//\n//\tshutdown: func(shutdown-type: shutdown-type) -> result<_, error-code>\n//\n//go:nosplit\nfunc (self TCPSocket) Shutdown(shutdownType ShutdownType) (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tshutdownType0 := (uint32)(shutdownType)\n\twasmimport_TCPSocketShutdown((uint32)(self0), (uint32)(shutdownType0), &result)\n\treturn\n}\n\n// StartBind represents the imported method \"start-bind\".\n//\n// Bind the socket to a specific network on the provided IP address and port.\n//\n// If the IP address is zero (`0.0.0.0` in IPv4, `::` in IPv6), it is left to the\n// implementation to decide which\n// network interface(s) to bind to.\n// If the TCP/UDP port is zero, the socket will be bound to a random free port.\n//\n// Bind can be attempted multiple times on the same socket, even with\n// different arguments on each iteration. But never concurrently and\n// only as long as the previous bind failed. Once a bind succeeds, the\n// binding can't be changed anymore.\n//\n// # Typical errors\n// - `invalid-argument`:          The `local-address` has the wrong address family.\n// (EAFNOSUPPORT, EFAULT on Windows)\n// - `invalid-argument`:          `local-address` is not a unicast address. (EINVAL)\n// - `invalid-argument`:          `local-address` is an IPv4-mapped IPv6 address.\n// (EINVAL)\n// - `invalid-state`:             The socket is already bound. (EINVAL)\n// - `address-in-use`:            No ephemeral ports available. (EADDRINUSE, ENOBUFS\n// on Windows)\n// - `address-in-use`:            Address is already in use. (EADDRINUSE)\n// - `address-not-bindable`:      `local-address` is not an address that the `network`\n// can bind to. (EADDRNOTAVAIL)\n// - `not-in-progress`:           A `bind` operation is not in progress.\n// - `would-block`:               Can't finish the operation, it is still in progress.\n// (EWOULDBLOCK, EAGAIN)\n//\n// # Implementors note\n// When binding to a non-zero port, this bind operation shouldn't be affected by the\n// TIME_WAIT\n// state of a recently closed socket on the same local address. In practice this means\n// that the SO_REUSEADDR\n// socket option should be set implicitly on all platforms, except on Windows where\n// this is the default behavior\n// and SO_REUSEADDR performs something different entirely.\n//\n// Unlike in POSIX, in WASI the bind operation is async. This enables\n// interactive WASI hosts to inject permission prompts. Runtimes that\n// don't want to make use of this ability can simply call the native\n// `bind` as part of either `start-bind` or `finish-bind`.\n//\n// # References\n// - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html>\n// - <https://man7.org/linux/man-pages/man2/bind.2.html>\n// - <https://learn.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-bind>\n// - <https://man.freebsd.org/cgi/man.cgi?query=bind&sektion=2&format=html>\n//\n//\tstart-bind: func(network: borrow<network>, local-address: ip-socket-address) ->\n//\tresult<_, error-code>\n//\n//go:nosplit\nfunc (self TCPSocket) StartBind(network_ Network, localAddress IPSocketAddress) (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tnetwork0 := cm.Reinterpret[uint32](network_)\n\tlocalAddress0, localAddress1, localAddress2, localAddress3, localAddress4, localAddress5, localAddress6, localAddress7, localAddress8, localAddress9, localAddress10, localAddress11 := lower_IPSocketAddress(localAddress)\n\twasmimport_TCPSocketStartBind((uint32)(self0), (uint32)(network0), (uint32)(localAddress0), (uint32)(localAddress1), (uint32)(localAddress2), (uint32)(localAddress3), (uint32)(localAddress4), (uint32)(localAddress5), (uint32)(localAddress6), (uint32)(localAddress7), (uint32)(localAddress8), (uint32)(localAddress9), (uint32)(localAddress10), (uint32)(localAddress11), &result)\n\treturn\n}\n\n// StartConnect represents the imported method \"start-connect\".\n//\n// Connect to a remote endpoint.\n//\n// On success:\n// - the socket is transitioned into the `connection` state.\n// - a pair of streams is returned that can be used to read & write to the connection\n//\n// After a failed connection attempt, the socket will be in the `closed`\n// state and the only valid action left is to `drop` the socket. A single\n// socket can not be used to connect more than once.\n//\n// # Typical errors\n// - `invalid-argument`:          The `remote-address` has the wrong address family.\n// (EAFNOSUPPORT)\n// - `invalid-argument`:          `remote-address` is not a unicast address. (EINVAL,\n// ENETUNREACH on Linux, EAFNOSUPPORT on MacOS)\n// - `invalid-argument`:          `remote-address` is an IPv4-mapped IPv6 address.\n// (EINVAL, EADDRNOTAVAIL on Illumos)\n// - `invalid-argument`:          The IP address in `remote-address` is set to INADDR_ANY\n// (`0.0.0.0` / `::`). (EADDRNOTAVAIL on Windows)\n// - `invalid-argument`:          The port in `remote-address` is set to 0. (EADDRNOTAVAIL\n// on Windows)\n// - `invalid-argument`:          The socket is already attached to a different network.\n// The `network` passed to `connect` must be identical to the one passed to `bind`.\n// - `invalid-state`:             The socket is already in the `connected` state.\n// (EISCONN)\n// - `invalid-state`:             The socket is already in the `listening` state.\n// (EOPNOTSUPP, EINVAL on Windows)\n// - `timeout`:                   Connection timed out. (ETIMEDOUT)\n// - `connection-refused`:        The connection was forcefully rejected. (ECONNREFUSED)\n// - `connection-reset`:          The connection was reset. (ECONNRESET)\n// - `connection-aborted`:        The connection was aborted. (ECONNABORTED)\n// - `remote-unreachable`:        The remote address is not reachable. (EHOSTUNREACH,\n// EHOSTDOWN, ENETUNREACH, ENETDOWN, ENONET)\n// - `address-in-use`:            Tried to perform an implicit bind, but there were\n// no ephemeral ports available. (EADDRINUSE, EADDRNOTAVAIL on Linux, EAGAIN on BSD)\n// - `not-in-progress`:           A connect operation is not in progress.\n// - `would-block`:               Can't finish the operation, it is still in progress.\n// (EWOULDBLOCK, EAGAIN)\n//\n// # Implementors note\n// The POSIX equivalent of `start-connect` is the regular `connect` syscall.\n// Because all WASI sockets are non-blocking this is expected to return\n// EINPROGRESS, which should be translated to `ok()` in WASI.\n//\n// The POSIX equivalent of `finish-connect` is a `poll` for event `POLLOUT`\n// with a timeout of 0 on the socket descriptor. Followed by a check for\n// the `SO_ERROR` socket option, in case the poll signaled readiness.\n//\n// # References\n// - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html>\n// - <https://man7.org/linux/man-pages/man2/connect.2.html>\n// - <https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect>\n// - <https://man.freebsd.org/cgi/man.cgi?connect>\n//\n//\tstart-connect: func(network: borrow<network>, remote-address: ip-socket-address)\n//\t-> result<_, error-code>\n//\n//go:nosplit\nfunc (self TCPSocket) StartConnect(network_ Network, remoteAddress IPSocketAddress) (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tnetwork0 := cm.Reinterpret[uint32](network_)\n\tremoteAddress0, remoteAddress1, remoteAddress2, remoteAddress3, remoteAddress4, remoteAddress5, remoteAddress6, remoteAddress7, remoteAddress8, remoteAddress9, remoteAddress10, remoteAddress11 := lower_IPSocketAddress(remoteAddress)\n\twasmimport_TCPSocketStartConnect((uint32)(self0), (uint32)(network0), (uint32)(remoteAddress0), (uint32)(remoteAddress1), (uint32)(remoteAddress2), (uint32)(remoteAddress3), (uint32)(remoteAddress4), (uint32)(remoteAddress5), (uint32)(remoteAddress6), (uint32)(remoteAddress7), (uint32)(remoteAddress8), (uint32)(remoteAddress9), (uint32)(remoteAddress10), (uint32)(remoteAddress11), &result)\n\treturn\n}\n\n// StartListen represents the imported method \"start-listen\".\n//\n// Start listening for new connections.\n//\n// Transitions the socket into the `listening` state.\n//\n// Unlike POSIX, the socket must already be explicitly bound.\n//\n// # Typical errors\n// - `invalid-state`:             The socket is not bound to any local address. (EDESTADDRREQ)\n// - `invalid-state`:             The socket is already in the `connected` state.\n// (EISCONN, EINVAL on BSD)\n// - `invalid-state`:             The socket is already in the `listening` state.\n// - `address-in-use`:            Tried to perform an implicit bind, but there were\n// no ephemeral ports available. (EADDRINUSE)\n// - `not-in-progress`:           A listen operation is not in progress.\n// - `would-block`:               Can't finish the operation, it is still in progress.\n// (EWOULDBLOCK, EAGAIN)\n//\n// # Implementors note\n// Unlike in POSIX, in WASI the listen operation is async. This enables\n// interactive WASI hosts to inject permission prompts. Runtimes that\n// don't want to make use of this ability can simply call the native\n// `listen` as part of either `start-listen` or `finish-listen`.\n//\n// # References\n// - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html>\n// - <https://man7.org/linux/man-pages/man2/listen.2.html>\n// - <https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-listen>\n// - <https://man.freebsd.org/cgi/man.cgi?query=listen&sektion=2>\n//\n//\tstart-listen: func() -> result<_, error-code>\n//\n//go:nosplit\nfunc (self TCPSocket) StartListen() (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_TCPSocketStartListen((uint32)(self0), &result)\n\treturn\n}\n\n// Subscribe represents the imported method \"subscribe\".\n//\n// Create a `pollable` which can be used to poll for, or block on,\n// completion of any of the asynchronous operations of this socket.\n//\n// When `finish-bind`, `finish-listen`, `finish-connect` or `accept`\n// return `error(would-block)`, this pollable can be used to wait for\n// their success or failure, after which the method can be retried.\n//\n// The pollable is not limited to the async operation that happens to be\n// in progress at the time of calling `subscribe` (if any). Theoretically,\n// `subscribe` only has to be called once per socket and can then be\n// (re)used for the remainder of the socket's lifetime.\n//\n// See <https://github.com/WebAssembly/wasi-sockets/TcpSocketOperationalSemantics.md#Pollable-readiness>\n// for a more information.\n//\n// Note: this function is here for WASI Preview2 only.\n// It's planned to be removed when `future` is natively supported in Preview3.\n//\n//\tsubscribe: func() -> pollable\n//\n//go:nosplit\nfunc (self TCPSocket) Subscribe() (result Pollable) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tresult0 := wasmimport_TCPSocketSubscribe((uint32)(self0))\n\tresult = cm.Reinterpret[Pollable]((uint32)(result0))\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/sockets/v0.2.0/tcp-create-socket/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/sockets/v0.2.0/tcp-create-socket/tcp-create-socket.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage tcpcreatesocket\n\nimport (\n\t\"internal/cm\"\n)\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:sockets@0.2.0\".\n\n//go:wasmimport wasi:sockets/tcp-create-socket@0.2.0 create-tcp-socket\n//go:noescape\nfunc wasmimport_CreateTCPSocket(addressFamily0 uint32, result *cm.Result[TCPSocket, TCPSocket, ErrorCode])\n"
  },
  {
    "path": "src/internal/wasi/sockets/v0.2.0/tcp-create-socket/tcp-create-socket.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package tcpcreatesocket represents the imported interface \"wasi:sockets/tcp-create-socket@0.2.0\".\npackage tcpcreatesocket\n\nimport (\n\t\"internal/cm\"\n\t\"internal/wasi/sockets/v0.2.0/network\"\n\t\"internal/wasi/sockets/v0.2.0/tcp\"\n)\n\n// Network represents the imported type alias \"wasi:sockets/tcp-create-socket@0.2.0#network\".\n//\n// See [network.Network] for more information.\ntype Network = network.Network\n\n// ErrorCode represents the type alias \"wasi:sockets/tcp-create-socket@0.2.0#error-code\".\n//\n// See [network.ErrorCode] for more information.\ntype ErrorCode = network.ErrorCode\n\n// IPAddressFamily represents the type alias \"wasi:sockets/tcp-create-socket@0.2.0#ip-address-family\".\n//\n// See [network.IPAddressFamily] for more information.\ntype IPAddressFamily = network.IPAddressFamily\n\n// TCPSocket represents the imported type alias \"wasi:sockets/tcp-create-socket@0.2.0#tcp-socket\".\n//\n// See [tcp.TCPSocket] for more information.\ntype TCPSocket = tcp.TCPSocket\n\n// CreateTCPSocket represents the imported function \"create-tcp-socket\".\n//\n// Create a new TCP socket.\n//\n// Similar to `socket(AF_INET or AF_INET6, SOCK_STREAM, IPPROTO_TCP)` in POSIX.\n// On IPv6 sockets, IPV6_V6ONLY is enabled by default and can't be configured otherwise.\n//\n// This function does not require a network capability handle. This is considered\n// to be safe because\n// at time of creation, the socket is not bound to any `network` yet. Up to the moment\n// `bind`/`connect`\n// is called, the socket is effectively an in-memory configuration object, unable\n// to communicate with the outside world.\n//\n// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous\n// operations.\n//\n// # Typical errors\n// - `not-supported`:     The specified `address-family` is not supported. (EAFNOSUPPORT)\n// - `new-socket-limit`:  The new socket resource could not be created because of\n// a system limit. (EMFILE, ENFILE)\n//\n// # References\n// - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html>\n// - <https://man7.org/linux/man-pages/man2/socket.2.html>\n// - <https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsasocketw>\n// - <https://man.freebsd.org/cgi/man.cgi?query=socket&sektion=2>\n//\n//\tcreate-tcp-socket: func(address-family: ip-address-family) -> result<tcp-socket,\n//\terror-code>\n//\n//go:nosplit\nfunc CreateTCPSocket(addressFamily IPAddressFamily) (result cm.Result[TCPSocket, TCPSocket, ErrorCode]) {\n\taddressFamily0 := (uint32)(addressFamily)\n\twasmimport_CreateTCPSocket((uint32)(addressFamily0), &result)\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/sockets/v0.2.0/udp/abi.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage udp\n\nimport (\n\t\"internal/cm\"\n\t\"internal/wasi/sockets/v0.2.0/network\"\n\t\"unsafe\"\n)\n\n// IPSocketAddressShape is used for storage in variant or result types.\ntype IPSocketAddressShape struct {\n\t_     cm.HostLayout\n\tshape [unsafe.Sizeof(IPSocketAddress{})]byte\n}\n\nfunc lower_IPv4Address(v network.IPv4Address) (f0 uint32, f1 uint32, f2 uint32, f3 uint32) {\n\tf0 = (uint32)(v[0])\n\tf1 = (uint32)(v[1])\n\tf2 = (uint32)(v[2])\n\tf3 = (uint32)(v[3])\n\treturn\n}\n\nfunc lower_IPv4SocketAddress(v network.IPv4SocketAddress) (f0 uint32, f1 uint32, f2 uint32, f3 uint32, f4 uint32) {\n\tf0 = (uint32)(v.Port)\n\tf1, f2, f3, f4 = lower_IPv4Address(v.Address)\n\treturn\n}\n\nfunc lower_IPv6Address(v network.IPv6Address) (f0 uint32, f1 uint32, f2 uint32, f3 uint32, f4 uint32, f5 uint32, f6 uint32, f7 uint32) {\n\tf0 = (uint32)(v[0])\n\tf1 = (uint32)(v[1])\n\tf2 = (uint32)(v[2])\n\tf3 = (uint32)(v[3])\n\tf4 = (uint32)(v[4])\n\tf5 = (uint32)(v[5])\n\tf6 = (uint32)(v[6])\n\tf7 = (uint32)(v[7])\n\treturn\n}\n\nfunc lower_IPv6SocketAddress(v network.IPv6SocketAddress) (f0 uint32, f1 uint32, f2 uint32, f3 uint32, f4 uint32, f5 uint32, f6 uint32, f7 uint32, f8 uint32, f9 uint32, f10 uint32) {\n\tf0 = (uint32)(v.Port)\n\tf1 = (uint32)(v.FlowInfo)\n\tf2, f3, f4, f5, f6, f7, f8, f9 = lower_IPv6Address(v.Address)\n\tf10 = (uint32)(v.ScopeID)\n\treturn\n}\n\nfunc lower_IPSocketAddress(v network.IPSocketAddress) (f0 uint32, f1 uint32, f2 uint32, f3 uint32, f4 uint32, f5 uint32, f6 uint32, f7 uint32, f8 uint32, f9 uint32, f10 uint32, f11 uint32) {\n\tf0 = (uint32)(v.Tag())\n\tswitch f0 {\n\tcase 0: // ipv4\n\t\tv1, v2, v3, v4, v5 := lower_IPv4SocketAddress(*cm.Case[network.IPv4SocketAddress](&v, 0))\n\t\tf1 = (uint32)(v1)\n\t\tf2 = (uint32)(v2)\n\t\tf3 = (uint32)(v3)\n\t\tf4 = (uint32)(v4)\n\t\tf5 = (uint32)(v5)\n\tcase 1: // ipv6\n\t\tv1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11 := lower_IPv6SocketAddress(*cm.Case[network.IPv6SocketAddress](&v, 1))\n\t\tf1 = (uint32)(v1)\n\t\tf2 = (uint32)(v2)\n\t\tf3 = (uint32)(v3)\n\t\tf4 = (uint32)(v4)\n\t\tf5 = (uint32)(v5)\n\t\tf6 = (uint32)(v6)\n\t\tf7 = (uint32)(v7)\n\t\tf8 = (uint32)(v8)\n\t\tf9 = (uint32)(v9)\n\t\tf10 = (uint32)(v10)\n\t\tf11 = (uint32)(v11)\n\t}\n\treturn\n}\n\n// TupleIncomingDatagramStreamOutgoingDatagramStreamShape is used for storage in variant or result types.\ntype TupleIncomingDatagramStreamOutgoingDatagramStreamShape struct {\n\t_     cm.HostLayout\n\tshape [unsafe.Sizeof(cm.Tuple[IncomingDatagramStream, OutgoingDatagramStream]{})]byte\n}\n\nfunc lower_OptionIPSocketAddress(v cm.Option[IPSocketAddress]) (f0 uint32, f1 uint32, f2 uint32, f3 uint32, f4 uint32, f5 uint32, f6 uint32, f7 uint32, f8 uint32, f9 uint32, f10 uint32, f11 uint32, f12 uint32) {\n\tsome := v.Some()\n\tif some != nil {\n\t\tf0 = 1\n\t\tv1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12 := lower_IPSocketAddress(*some)\n\t\tf1 = (uint32)(v1)\n\t\tf2 = (uint32)(v2)\n\t\tf3 = (uint32)(v3)\n\t\tf4 = (uint32)(v4)\n\t\tf5 = (uint32)(v5)\n\t\tf6 = (uint32)(v6)\n\t\tf7 = (uint32)(v7)\n\t\tf8 = (uint32)(v8)\n\t\tf9 = (uint32)(v9)\n\t\tf10 = (uint32)(v10)\n\t\tf11 = (uint32)(v11)\n\t\tf12 = (uint32)(v12)\n\t}\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/sockets/v0.2.0/udp/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/sockets/v0.2.0/udp/udp.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage udp\n\nimport (\n\t\"internal/cm\"\n)\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:sockets@0.2.0\".\n\n//go:wasmimport wasi:sockets/udp@0.2.0 [resource-drop]udp-socket\n//go:noescape\nfunc wasmimport_UDPSocketResourceDrop(self0 uint32)\n\n//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.address-family\n//go:noescape\nfunc wasmimport_UDPSocketAddressFamily(self0 uint32) (result0 uint32)\n\n//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.finish-bind\n//go:noescape\nfunc wasmimport_UDPSocketFinishBind(self0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.local-address\n//go:noescape\nfunc wasmimport_UDPSocketLocalAddress(self0 uint32, result *cm.Result[IPSocketAddressShape, IPSocketAddress, ErrorCode])\n\n//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.receive-buffer-size\n//go:noescape\nfunc wasmimport_UDPSocketReceiveBufferSize(self0 uint32, result *cm.Result[uint64, uint64, ErrorCode])\n\n//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.remote-address\n//go:noescape\nfunc wasmimport_UDPSocketRemoteAddress(self0 uint32, result *cm.Result[IPSocketAddressShape, IPSocketAddress, ErrorCode])\n\n//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.send-buffer-size\n//go:noescape\nfunc wasmimport_UDPSocketSendBufferSize(self0 uint32, result *cm.Result[uint64, uint64, ErrorCode])\n\n//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.set-receive-buffer-size\n//go:noescape\nfunc wasmimport_UDPSocketSetReceiveBufferSize(self0 uint32, value0 uint64, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.set-send-buffer-size\n//go:noescape\nfunc wasmimport_UDPSocketSetSendBufferSize(self0 uint32, value0 uint64, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.set-unicast-hop-limit\n//go:noescape\nfunc wasmimport_UDPSocketSetUnicastHopLimit(self0 uint32, value0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.start-bind\n//go:noescape\nfunc wasmimport_UDPSocketStartBind(self0 uint32, network0 uint32, localAddress0 uint32, localAddress1 uint32, localAddress2 uint32, localAddress3 uint32, localAddress4 uint32, localAddress5 uint32, localAddress6 uint32, localAddress7 uint32, localAddress8 uint32, localAddress9 uint32, localAddress10 uint32, localAddress11 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])\n\n//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.stream\n//go:noescape\nfunc wasmimport_UDPSocketStream(self0 uint32, remoteAddress0 uint32, remoteAddress1 uint32, remoteAddress2 uint32, remoteAddress3 uint32, remoteAddress4 uint32, remoteAddress5 uint32, remoteAddress6 uint32, remoteAddress7 uint32, remoteAddress8 uint32, remoteAddress9 uint32, remoteAddress10 uint32, remoteAddress11 uint32, remoteAddress12 uint32, result *cm.Result[TupleIncomingDatagramStreamOutgoingDatagramStreamShape, cm.Tuple[IncomingDatagramStream, OutgoingDatagramStream], ErrorCode])\n\n//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.subscribe\n//go:noescape\nfunc wasmimport_UDPSocketSubscribe(self0 uint32) (result0 uint32)\n\n//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.unicast-hop-limit\n//go:noescape\nfunc wasmimport_UDPSocketUnicastHopLimit(self0 uint32, result *cm.Result[uint8, uint8, ErrorCode])\n\n//go:wasmimport wasi:sockets/udp@0.2.0 [resource-drop]incoming-datagram-stream\n//go:noescape\nfunc wasmimport_IncomingDatagramStreamResourceDrop(self0 uint32)\n\n//go:wasmimport wasi:sockets/udp@0.2.0 [method]incoming-datagram-stream.receive\n//go:noescape\nfunc wasmimport_IncomingDatagramStreamReceive(self0 uint32, maxResults0 uint64, result *cm.Result[cm.List[IncomingDatagram], cm.List[IncomingDatagram], ErrorCode])\n\n//go:wasmimport wasi:sockets/udp@0.2.0 [method]incoming-datagram-stream.subscribe\n//go:noescape\nfunc wasmimport_IncomingDatagramStreamSubscribe(self0 uint32) (result0 uint32)\n\n//go:wasmimport wasi:sockets/udp@0.2.0 [resource-drop]outgoing-datagram-stream\n//go:noescape\nfunc wasmimport_OutgoingDatagramStreamResourceDrop(self0 uint32)\n\n//go:wasmimport wasi:sockets/udp@0.2.0 [method]outgoing-datagram-stream.check-send\n//go:noescape\nfunc wasmimport_OutgoingDatagramStreamCheckSend(self0 uint32, result *cm.Result[uint64, uint64, ErrorCode])\n\n//go:wasmimport wasi:sockets/udp@0.2.0 [method]outgoing-datagram-stream.send\n//go:noescape\nfunc wasmimport_OutgoingDatagramStreamSend(self0 uint32, datagrams0 *OutgoingDatagram, datagrams1 uint32, result *cm.Result[uint64, uint64, ErrorCode])\n\n//go:wasmimport wasi:sockets/udp@0.2.0 [method]outgoing-datagram-stream.subscribe\n//go:noescape\nfunc wasmimport_OutgoingDatagramStreamSubscribe(self0 uint32) (result0 uint32)\n"
  },
  {
    "path": "src/internal/wasi/sockets/v0.2.0/udp/udp.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package udp represents the imported interface \"wasi:sockets/udp@0.2.0\".\npackage udp\n\nimport (\n\t\"internal/cm\"\n\t\"internal/wasi/io/v0.2.0/poll\"\n\t\"internal/wasi/sockets/v0.2.0/network\"\n)\n\n// Pollable represents the imported type alias \"wasi:sockets/udp@0.2.0#pollable\".\n//\n// See [poll.Pollable] for more information.\ntype Pollable = poll.Pollable\n\n// Network represents the imported type alias \"wasi:sockets/udp@0.2.0#network\".\n//\n// See [network.Network] for more information.\ntype Network = network.Network\n\n// ErrorCode represents the type alias \"wasi:sockets/udp@0.2.0#error-code\".\n//\n// See [network.ErrorCode] for more information.\ntype ErrorCode = network.ErrorCode\n\n// IPSocketAddress represents the type alias \"wasi:sockets/udp@0.2.0#ip-socket-address\".\n//\n// See [network.IPSocketAddress] for more information.\ntype IPSocketAddress = network.IPSocketAddress\n\n// IPAddressFamily represents the type alias \"wasi:sockets/udp@0.2.0#ip-address-family\".\n//\n// See [network.IPAddressFamily] for more information.\ntype IPAddressFamily = network.IPAddressFamily\n\n// IncomingDatagram represents the record \"wasi:sockets/udp@0.2.0#incoming-datagram\".\n//\n// A received datagram.\n//\n//\trecord incoming-datagram {\n//\t\tdata: list<u8>,\n//\t\tremote-address: ip-socket-address,\n//\t}\ntype IncomingDatagram struct {\n\t_ cm.HostLayout `json:\"-\"`\n\t// The payload.\n\t//\n\t// Theoretical max size: ~64 KiB. In practice, typically less than 1500 bytes.\n\tData cm.List[uint8] `json:\"data\"`\n\n\t// The source address.\n\t//\n\t// This field is guaranteed to match the remote address the stream was initialized\n\t// with, if any.\n\t//\n\t// Equivalent to the `src_addr` out parameter of `recvfrom`.\n\tRemoteAddress IPSocketAddress `json:\"remote-address\"`\n}\n\n// OutgoingDatagram represents the record \"wasi:sockets/udp@0.2.0#outgoing-datagram\".\n//\n// A datagram to be sent out.\n//\n//\trecord outgoing-datagram {\n//\t\tdata: list<u8>,\n//\t\tremote-address: option<ip-socket-address>,\n//\t}\ntype OutgoingDatagram struct {\n\t_ cm.HostLayout `json:\"-\"`\n\t// The payload.\n\tData cm.List[uint8] `json:\"data\"`\n\n\t// The destination address.\n\t//\n\t// The requirements on this field depend on how the stream was initialized:\n\t// - with a remote address: this field must be None or match the stream's remote address\n\t// exactly.\n\t// - without a remote address: this field is required.\n\t//\n\t// If this value is None, the send operation is equivalent to `send` in POSIX. Otherwise\n\t// it is equivalent to `sendto`.\n\tRemoteAddress cm.Option[IPSocketAddress] `json:\"remote-address\"`\n}\n\n// UDPSocket represents the imported resource \"wasi:sockets/udp@0.2.0#udp-socket\".\n//\n// A UDP socket handle.\n//\n//\tresource udp-socket\ntype UDPSocket cm.Resource\n\n// ResourceDrop represents the imported resource-drop for resource \"udp-socket\".\n//\n// Drops a resource handle.\n//\n//go:nosplit\nfunc (self UDPSocket) ResourceDrop() {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_UDPSocketResourceDrop((uint32)(self0))\n\treturn\n}\n\n// AddressFamily represents the imported method \"address-family\".\n//\n// Whether this is a IPv4 or IPv6 socket.\n//\n// Equivalent to the SO_DOMAIN socket option.\n//\n//\taddress-family: func() -> ip-address-family\n//\n//go:nosplit\nfunc (self UDPSocket) AddressFamily() (result IPAddressFamily) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tresult0 := wasmimport_UDPSocketAddressFamily((uint32)(self0))\n\tresult = (network.IPAddressFamily)((uint32)(result0))\n\treturn\n}\n\n// FinishBind represents the imported method \"finish-bind\".\n//\n//\tfinish-bind: func() -> result<_, error-code>\n//\n//go:nosplit\nfunc (self UDPSocket) FinishBind() (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_UDPSocketFinishBind((uint32)(self0), &result)\n\treturn\n}\n\n// LocalAddress represents the imported method \"local-address\".\n//\n// Get the current bound address.\n//\n// POSIX mentions:\n// > If the socket has not been bound to a local name, the value\n// > stored in the object pointed to by `address` is unspecified.\n//\n// WASI is stricter and requires `local-address` to return `invalid-state` when the\n// socket hasn't been bound yet.\n//\n// # Typical errors\n// - `invalid-state`: The socket is not bound to any local address.\n//\n// # References\n// - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html>\n// - <https://man7.org/linux/man-pages/man2/getsockname.2.html>\n// - <https://learn.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-getsockname>\n// - <https://man.freebsd.org/cgi/man.cgi?getsockname>\n//\n//\tlocal-address: func() -> result<ip-socket-address, error-code>\n//\n//go:nosplit\nfunc (self UDPSocket) LocalAddress() (result cm.Result[IPSocketAddressShape, IPSocketAddress, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_UDPSocketLocalAddress((uint32)(self0), &result)\n\treturn\n}\n\n// ReceiveBufferSize represents the imported method \"receive-buffer-size\".\n//\n// The kernel buffer space reserved for sends/receives on this socket.\n//\n// If the provided value is 0, an `invalid-argument` error is returned.\n// Any other value will never cause an error, but it might be silently clamped and/or\n// rounded.\n// I.e. after setting a value, reading the same setting back may return a different\n// value.\n//\n// Equivalent to the SO_RCVBUF and SO_SNDBUF socket options.\n//\n// # Typical errors\n// - `invalid-argument`:     (set) The provided value was 0.\n//\n//\treceive-buffer-size: func() -> result<u64, error-code>\n//\n//go:nosplit\nfunc (self UDPSocket) ReceiveBufferSize() (result cm.Result[uint64, uint64, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_UDPSocketReceiveBufferSize((uint32)(self0), &result)\n\treturn\n}\n\n// RemoteAddress represents the imported method \"remote-address\".\n//\n// Get the address the socket is currently streaming to.\n//\n// # Typical errors\n// - `invalid-state`: The socket is not streaming to a specific remote address. (ENOTCONN)\n//\n// # References\n// - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html>\n// - <https://man7.org/linux/man-pages/man2/getpeername.2.html>\n// - <https://learn.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-getpeername>\n// - <https://man.freebsd.org/cgi/man.cgi?query=getpeername&sektion=2&n=1>\n//\n//\tremote-address: func() -> result<ip-socket-address, error-code>\n//\n//go:nosplit\nfunc (self UDPSocket) RemoteAddress() (result cm.Result[IPSocketAddressShape, IPSocketAddress, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_UDPSocketRemoteAddress((uint32)(self0), &result)\n\treturn\n}\n\n// SendBufferSize represents the imported method \"send-buffer-size\".\n//\n//\tsend-buffer-size: func() -> result<u64, error-code>\n//\n//go:nosplit\nfunc (self UDPSocket) SendBufferSize() (result cm.Result[uint64, uint64, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_UDPSocketSendBufferSize((uint32)(self0), &result)\n\treturn\n}\n\n// SetReceiveBufferSize represents the imported method \"set-receive-buffer-size\".\n//\n//\tset-receive-buffer-size: func(value: u64) -> result<_, error-code>\n//\n//go:nosplit\nfunc (self UDPSocket) SetReceiveBufferSize(value uint64) (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tvalue0 := (uint64)(value)\n\twasmimport_UDPSocketSetReceiveBufferSize((uint32)(self0), (uint64)(value0), &result)\n\treturn\n}\n\n// SetSendBufferSize represents the imported method \"set-send-buffer-size\".\n//\n//\tset-send-buffer-size: func(value: u64) -> result<_, error-code>\n//\n//go:nosplit\nfunc (self UDPSocket) SetSendBufferSize(value uint64) (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tvalue0 := (uint64)(value)\n\twasmimport_UDPSocketSetSendBufferSize((uint32)(self0), (uint64)(value0), &result)\n\treturn\n}\n\n// SetUnicastHopLimit represents the imported method \"set-unicast-hop-limit\".\n//\n//\tset-unicast-hop-limit: func(value: u8) -> result<_, error-code>\n//\n//go:nosplit\nfunc (self UDPSocket) SetUnicastHopLimit(value uint8) (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tvalue0 := (uint32)(value)\n\twasmimport_UDPSocketSetUnicastHopLimit((uint32)(self0), (uint32)(value0), &result)\n\treturn\n}\n\n// StartBind represents the imported method \"start-bind\".\n//\n// Bind the socket to a specific network on the provided IP address and port.\n//\n// If the IP address is zero (`0.0.0.0` in IPv4, `::` in IPv6), it is left to the\n// implementation to decide which\n// network interface(s) to bind to.\n// If the port is zero, the socket will be bound to a random free port.\n//\n// # Typical errors\n// - `invalid-argument`:          The `local-address` has the wrong address family.\n// (EAFNOSUPPORT, EFAULT on Windows)\n// - `invalid-state`:             The socket is already bound. (EINVAL)\n// - `address-in-use`:            No ephemeral ports available. (EADDRINUSE, ENOBUFS\n// on Windows)\n// - `address-in-use`:            Address is already in use. (EADDRINUSE)\n// - `address-not-bindable`:      `local-address` is not an address that the `network`\n// can bind to. (EADDRNOTAVAIL)\n// - `not-in-progress`:           A `bind` operation is not in progress.\n// - `would-block`:               Can't finish the operation, it is still in progress.\n// (EWOULDBLOCK, EAGAIN)\n//\n// # Implementors note\n// Unlike in POSIX, in WASI the bind operation is async. This enables\n// interactive WASI hosts to inject permission prompts. Runtimes that\n// don't want to make use of this ability can simply call the native\n// `bind` as part of either `start-bind` or `finish-bind`.\n//\n// # References\n// - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html>\n// - <https://man7.org/linux/man-pages/man2/bind.2.html>\n// - <https://learn.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-bind>\n// - <https://man.freebsd.org/cgi/man.cgi?query=bind&sektion=2&format=html>\n//\n//\tstart-bind: func(network: borrow<network>, local-address: ip-socket-address) ->\n//\tresult<_, error-code>\n//\n//go:nosplit\nfunc (self UDPSocket) StartBind(network_ Network, localAddress IPSocketAddress) (result cm.Result[ErrorCode, struct{}, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tnetwork0 := cm.Reinterpret[uint32](network_)\n\tlocalAddress0, localAddress1, localAddress2, localAddress3, localAddress4, localAddress5, localAddress6, localAddress7, localAddress8, localAddress9, localAddress10, localAddress11 := lower_IPSocketAddress(localAddress)\n\twasmimport_UDPSocketStartBind((uint32)(self0), (uint32)(network0), (uint32)(localAddress0), (uint32)(localAddress1), (uint32)(localAddress2), (uint32)(localAddress3), (uint32)(localAddress4), (uint32)(localAddress5), (uint32)(localAddress6), (uint32)(localAddress7), (uint32)(localAddress8), (uint32)(localAddress9), (uint32)(localAddress10), (uint32)(localAddress11), &result)\n\treturn\n}\n\n// Stream represents the imported method \"stream\".\n//\n// Set up inbound & outbound communication channels, optionally to a specific peer.\n//\n// This function only changes the local socket configuration and does not generate\n// any network traffic.\n// On success, the `remote-address` of the socket is updated. The `local-address`\n// may be updated as well,\n// based on the best network path to `remote-address`.\n//\n// When a `remote-address` is provided, the returned streams are limited to communicating\n// with that specific peer:\n// - `send` can only be used to send to this destination.\n// - `receive` will only return datagrams sent from the provided `remote-address`.\n//\n// This method may be called multiple times on the same socket to change its association,\n// but\n// only the most recently returned pair of streams will be operational. Implementations\n// may trap if\n// the streams returned by a previous invocation haven't been dropped yet before calling\n// `stream` again.\n//\n// The POSIX equivalent in pseudo-code is:\n//\n//\tif (was previously connected) {\n//\t\tconnect(s, AF_UNSPEC)\n//\t}\n//\tif (remote_address is Some) {\n//\t\tconnect(s, remote_address)\n//\t}\n//\n// Unlike in POSIX, the socket must already be explicitly bound.\n//\n// # Typical errors\n// - `invalid-argument`:          The `remote-address` has the wrong address family.\n// (EAFNOSUPPORT)\n// - `invalid-argument`:          The IP address in `remote-address` is set to INADDR_ANY\n// (`0.0.0.0` / `::`). (EDESTADDRREQ, EADDRNOTAVAIL)\n// - `invalid-argument`:          The port in `remote-address` is set to 0. (EDESTADDRREQ,\n// EADDRNOTAVAIL)\n// - `invalid-state`:             The socket is not bound.\n// - `address-in-use`:            Tried to perform an implicit bind, but there were\n// no ephemeral ports available. (EADDRINUSE, EADDRNOTAVAIL on Linux, EAGAIN on BSD)\n// - `remote-unreachable`:        The remote address is not reachable. (ECONNRESET,\n// ENETRESET, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN, ENONET)\n// - `connection-refused`:        The connection was refused. (ECONNREFUSED)\n//\n// # References\n// - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html>\n// - <https://man7.org/linux/man-pages/man2/connect.2.html>\n// - <https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect>\n// - <https://man.freebsd.org/cgi/man.cgi?connect>\n//\n//\t%stream: func(remote-address: option<ip-socket-address>) -> result<tuple<incoming-datagram-stream,\n//\toutgoing-datagram-stream>, error-code>\n//\n//go:nosplit\nfunc (self UDPSocket) Stream(remoteAddress cm.Option[IPSocketAddress]) (result cm.Result[TupleIncomingDatagramStreamOutgoingDatagramStreamShape, cm.Tuple[IncomingDatagramStream, OutgoingDatagramStream], ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tremoteAddress0, remoteAddress1, remoteAddress2, remoteAddress3, remoteAddress4, remoteAddress5, remoteAddress6, remoteAddress7, remoteAddress8, remoteAddress9, remoteAddress10, remoteAddress11, remoteAddress12 := lower_OptionIPSocketAddress(remoteAddress)\n\twasmimport_UDPSocketStream((uint32)(self0), (uint32)(remoteAddress0), (uint32)(remoteAddress1), (uint32)(remoteAddress2), (uint32)(remoteAddress3), (uint32)(remoteAddress4), (uint32)(remoteAddress5), (uint32)(remoteAddress6), (uint32)(remoteAddress7), (uint32)(remoteAddress8), (uint32)(remoteAddress9), (uint32)(remoteAddress10), (uint32)(remoteAddress11), (uint32)(remoteAddress12), &result)\n\treturn\n}\n\n// Subscribe represents the imported method \"subscribe\".\n//\n// Create a `pollable` which will resolve once the socket is ready for I/O.\n//\n// Note: this function is here for WASI Preview2 only.\n// It's planned to be removed when `future` is natively supported in Preview3.\n//\n//\tsubscribe: func() -> pollable\n//\n//go:nosplit\nfunc (self UDPSocket) Subscribe() (result Pollable) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tresult0 := wasmimport_UDPSocketSubscribe((uint32)(self0))\n\tresult = cm.Reinterpret[Pollable]((uint32)(result0))\n\treturn\n}\n\n// UnicastHopLimit represents the imported method \"unicast-hop-limit\".\n//\n// Equivalent to the IP_TTL & IPV6_UNICAST_HOPS socket options.\n//\n// If the provided value is 0, an `invalid-argument` error is returned.\n//\n// # Typical errors\n// - `invalid-argument`:     (set) The TTL value must be 1 or higher.\n//\n//\tunicast-hop-limit: func() -> result<u8, error-code>\n//\n//go:nosplit\nfunc (self UDPSocket) UnicastHopLimit() (result cm.Result[uint8, uint8, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_UDPSocketUnicastHopLimit((uint32)(self0), &result)\n\treturn\n}\n\n// IncomingDatagramStream represents the imported resource \"wasi:sockets/udp@0.2.0#incoming-datagram-stream\".\n//\n//\tresource incoming-datagram-stream\ntype IncomingDatagramStream cm.Resource\n\n// ResourceDrop represents the imported resource-drop for resource \"incoming-datagram-stream\".\n//\n// Drops a resource handle.\n//\n//go:nosplit\nfunc (self IncomingDatagramStream) ResourceDrop() {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_IncomingDatagramStreamResourceDrop((uint32)(self0))\n\treturn\n}\n\n// Receive represents the imported method \"receive\".\n//\n// Receive messages on the socket.\n//\n// This function attempts to receive up to `max-results` datagrams on the socket without\n// blocking.\n// The returned list may contain fewer elements than requested, but never more.\n//\n// This function returns successfully with an empty list when either:\n// - `max-results` is 0, or:\n// - `max-results` is greater than 0, but no results are immediately available.\n// This function never returns `error(would-block)`.\n//\n// # Typical errors\n// - `remote-unreachable`: The remote address is not reachable. (ECONNRESET, ENETRESET\n// on Windows, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN, ENONET)\n// - `connection-refused`: The connection was refused. (ECONNREFUSED)\n//\n// # References\n// - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html>\n// - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html>\n// - <https://man7.org/linux/man-pages/man2/recv.2.html>\n// - <https://man7.org/linux/man-pages/man2/recvmmsg.2.html>\n// - <https://learn.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-recv>\n// - <https://learn.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-recvfrom>\n// - <https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms741687(v=vs.85)>\n// - <https://man.freebsd.org/cgi/man.cgi?query=recv&sektion=2>\n//\n//\treceive: func(max-results: u64) -> result<list<incoming-datagram>, error-code>\n//\n//go:nosplit\nfunc (self IncomingDatagramStream) Receive(maxResults uint64) (result cm.Result[cm.List[IncomingDatagram], cm.List[IncomingDatagram], ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tmaxResults0 := (uint64)(maxResults)\n\twasmimport_IncomingDatagramStreamReceive((uint32)(self0), (uint64)(maxResults0), &result)\n\treturn\n}\n\n// Subscribe represents the imported method \"subscribe\".\n//\n// Create a `pollable` which will resolve once the stream is ready to receive again.\n//\n// Note: this function is here for WASI Preview2 only.\n// It's planned to be removed when `future` is natively supported in Preview3.\n//\n//\tsubscribe: func() -> pollable\n//\n//go:nosplit\nfunc (self IncomingDatagramStream) Subscribe() (result Pollable) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tresult0 := wasmimport_IncomingDatagramStreamSubscribe((uint32)(self0))\n\tresult = cm.Reinterpret[Pollable]((uint32)(result0))\n\treturn\n}\n\n// OutgoingDatagramStream represents the imported resource \"wasi:sockets/udp@0.2.0#outgoing-datagram-stream\".\n//\n//\tresource outgoing-datagram-stream\ntype OutgoingDatagramStream cm.Resource\n\n// ResourceDrop represents the imported resource-drop for resource \"outgoing-datagram-stream\".\n//\n// Drops a resource handle.\n//\n//go:nosplit\nfunc (self OutgoingDatagramStream) ResourceDrop() {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_OutgoingDatagramStreamResourceDrop((uint32)(self0))\n\treturn\n}\n\n// CheckSend represents the imported method \"check-send\".\n//\n// Check readiness for sending. This function never blocks.\n//\n// Returns the number of datagrams permitted for the next call to `send`,\n// or an error. Calling `send` with more datagrams than this function has\n// permitted will trap.\n//\n// When this function returns ok(0), the `subscribe` pollable will\n// become ready when this function will report at least ok(1), or an\n// error.\n//\n// Never returns `would-block`.\n//\n//\tcheck-send: func() -> result<u64, error-code>\n//\n//go:nosplit\nfunc (self OutgoingDatagramStream) CheckSend() (result cm.Result[uint64, uint64, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\twasmimport_OutgoingDatagramStreamCheckSend((uint32)(self0), &result)\n\treturn\n}\n\n// Send represents the imported method \"send\".\n//\n// Send messages on the socket.\n//\n// This function attempts to send all provided `datagrams` on the socket without blocking\n// and\n// returns how many messages were actually sent (or queued for sending). This function\n// never\n// returns `error(would-block)`. If none of the datagrams were able to be sent, `ok(0)`\n// is returned.\n//\n// This function semantically behaves the same as iterating the `datagrams` list and\n// sequentially\n// sending each individual datagram until either the end of the list has been reached\n// or the first error occurred.\n// If at least one datagram has been sent successfully, this function never returns\n// an error.\n//\n// If the input list is empty, the function returns `ok(0)`.\n//\n// Each call to `send` must be permitted by a preceding `check-send`. Implementations\n// must trap if\n// either `check-send` was not called or `datagrams` contains more items than `check-send`\n// permitted.\n//\n// # Typical errors\n// - `invalid-argument`:        The `remote-address` has the wrong address family.\n// (EAFNOSUPPORT)\n// - `invalid-argument`:        The IP address in `remote-address` is set to INADDR_ANY\n// (`0.0.0.0` / `::`). (EDESTADDRREQ, EADDRNOTAVAIL)\n// - `invalid-argument`:        The port in `remote-address` is set to 0. (EDESTADDRREQ,\n// EADDRNOTAVAIL)\n// - `invalid-argument`:        The socket is in \"connected\" mode and `remote-address`\n// is `some` value that does not match the address passed to `stream`. (EISCONN)\n// - `invalid-argument`:        The socket is not \"connected\" and no value for `remote-address`\n// was provided. (EDESTADDRREQ)\n// - `remote-unreachable`:      The remote address is not reachable. (ECONNRESET,\n// ENETRESET on Windows, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN, ENONET)\n// - `connection-refused`:      The connection was refused. (ECONNREFUSED)\n// - `datagram-too-large`:      The datagram is too large. (EMSGSIZE)\n//\n// # References\n// - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html>\n// - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html>\n// - <https://man7.org/linux/man-pages/man2/send.2.html>\n// - <https://man7.org/linux/man-pages/man2/sendmmsg.2.html>\n// - <https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-send>\n// - <https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto>\n// - <https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsasendmsg>\n// - <https://man.freebsd.org/cgi/man.cgi?query=send&sektion=2>\n//\n//\tsend: func(datagrams: list<outgoing-datagram>) -> result<u64, error-code>\n//\n//go:nosplit\nfunc (self OutgoingDatagramStream) Send(datagrams cm.List[OutgoingDatagram]) (result cm.Result[uint64, uint64, ErrorCode]) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tdatagrams0, datagrams1 := cm.LowerList(datagrams)\n\twasmimport_OutgoingDatagramStreamSend((uint32)(self0), (*OutgoingDatagram)(datagrams0), (uint32)(datagrams1), &result)\n\treturn\n}\n\n// Subscribe represents the imported method \"subscribe\".\n//\n// Create a `pollable` which will resolve once the stream is ready to send again.\n//\n// Note: this function is here for WASI Preview2 only.\n// It's planned to be removed when `future` is natively supported in Preview3.\n//\n//\tsubscribe: func() -> pollable\n//\n//go:nosplit\nfunc (self OutgoingDatagramStream) Subscribe() (result Pollable) {\n\tself0 := cm.Reinterpret[uint32](self)\n\tresult0 := wasmimport_OutgoingDatagramStreamSubscribe((uint32)(self0))\n\tresult = cm.Reinterpret[Pollable]((uint32)(result0))\n\treturn\n}\n"
  },
  {
    "path": "src/internal/wasi/sockets/v0.2.0/udp-create-socket/empty.s",
    "content": "// This file exists for testing this package without WebAssembly,\n// allowing empty function bodies with a //go:wasmimport directive.\n// See https://pkg.go.dev/cmd/compile for more information.\n"
  },
  {
    "path": "src/internal/wasi/sockets/v0.2.0/udp-create-socket/udp-create-socket.wasm.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\npackage udpcreatesocket\n\nimport (\n\t\"internal/cm\"\n)\n\n// This file contains wasmimport and wasmexport declarations for \"wasi:sockets@0.2.0\".\n\n//go:wasmimport wasi:sockets/udp-create-socket@0.2.0 create-udp-socket\n//go:noescape\nfunc wasmimport_CreateUDPSocket(addressFamily0 uint32, result *cm.Result[UDPSocket, UDPSocket, ErrorCode])\n"
  },
  {
    "path": "src/internal/wasi/sockets/v0.2.0/udp-create-socket/udp-create-socket.wit.go",
    "content": "// Code generated by wit-bindgen-go. DO NOT EDIT.\n\n// Package udpcreatesocket represents the imported interface \"wasi:sockets/udp-create-socket@0.2.0\".\npackage udpcreatesocket\n\nimport (\n\t\"internal/cm\"\n\t\"internal/wasi/sockets/v0.2.0/network\"\n\t\"internal/wasi/sockets/v0.2.0/udp\"\n)\n\n// Network represents the imported type alias \"wasi:sockets/udp-create-socket@0.2.0#network\".\n//\n// See [network.Network] for more information.\ntype Network = network.Network\n\n// ErrorCode represents the type alias \"wasi:sockets/udp-create-socket@0.2.0#error-code\".\n//\n// See [network.ErrorCode] for more information.\ntype ErrorCode = network.ErrorCode\n\n// IPAddressFamily represents the type alias \"wasi:sockets/udp-create-socket@0.2.0#ip-address-family\".\n//\n// See [network.IPAddressFamily] for more information.\ntype IPAddressFamily = network.IPAddressFamily\n\n// UDPSocket represents the imported type alias \"wasi:sockets/udp-create-socket@0.2.0#udp-socket\".\n//\n// See [udp.UDPSocket] for more information.\ntype UDPSocket = udp.UDPSocket\n\n// CreateUDPSocket represents the imported function \"create-udp-socket\".\n//\n// Create a new UDP socket.\n//\n// Similar to `socket(AF_INET or AF_INET6, SOCK_DGRAM, IPPROTO_UDP)` in POSIX.\n// On IPv6 sockets, IPV6_V6ONLY is enabled by default and can't be configured otherwise.\n//\n// This function does not require a network capability handle. This is considered\n// to be safe because\n// at time of creation, the socket is not bound to any `network` yet. Up to the moment\n// `bind` is called,\n// the socket is effectively an in-memory configuration object, unable to communicate\n// with the outside world.\n//\n// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous\n// operations.\n//\n// # Typical errors\n// - `not-supported`:     The specified `address-family` is not supported. (EAFNOSUPPORT)\n// - `new-socket-limit`:  The new socket resource could not be created because of\n// a system limit. (EMFILE, ENFILE)\n//\n// # References:\n// - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html>\n// - <https://man7.org/linux/man-pages/man2/socket.2.html>\n// - <https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsasocketw>\n// - <https://man.freebsd.org/cgi/man.cgi?query=socket&sektion=2>\n//\n//\tcreate-udp-socket: func(address-family: ip-address-family) -> result<udp-socket,\n//\terror-code>\n//\n//go:nosplit\nfunc CreateUDPSocket(addressFamily IPAddressFamily) (result cm.Result[UDPSocket, UDPSocket, ErrorCode]) {\n\taddressFamily0 := (uint32)(addressFamily)\n\twasmimport_CreateUDPSocket((uint32)(addressFamily0), &result)\n\treturn\n}\n"
  },
  {
    "path": "src/machine/adc.go",
    "content": "package machine\n\n// Hardware abstraction layer for the analog-to-digital conversion (ADC)\n// peripheral.\n\n// ADCConfig holds ADC configuration parameters. If left unspecified, the zero\n// value of each parameter will use the peripheral's default settings.\ntype ADCConfig struct {\n\tReference  uint32 // analog reference voltage (AREF) in millivolts\n\tResolution uint32 // number of bits for a single conversion (e.g., 8, 10, 12)\n\tSamples    uint32 // number of samples for a single conversion (e.g., 4, 8, 16, 32)\n\tSampleTime uint32 // sample time, in microseconds (µs)\n}\n"
  },
  {
    "path": "src/machine/board_adafruit-esp32-feather-v2.go",
    "content": "//go:build adafruit_esp32_feather_v2\n\npackage machine\n\nconst GPIO20 Pin = 20\n\nconst (\n\tIO0  = GPIO0\n\tIO2  = GPIO2\n\tIO4  = GPIO4\n\tIO5  = GPIO5\n\tIO7  = GPIO7\n\tIO8  = GPIO8\n\tIO12 = GPIO12\n\tIO13 = GPIO13\n\tIO14 = GPIO14\n\tIO15 = GPIO15\n\tIO19 = GPIO19\n\tIO20 = GPIO20\n\tIO21 = GPIO21\n\tIO22 = GPIO22\n\tIO25 = GPIO25\n\tIO26 = GPIO26\n\tIO27 = GPIO27\n\tIO32 = GPIO32\n\tIO33 = GPIO33\n\tIO34 = GPIO34\n\tIO35 = GPIO35\n\tIO36 = GPIO36\n\tIO37 = GPIO37\n\tIO38 = GPIO38\n\tIO39 = GPIO39\n)\n\n// Digital pins\nconst (\n\tD12 = IO12\n\tD13 = IO13\n\tD14 = IO14\n\tD15 = IO15\n\tD27 = IO27\n\tD32 = IO32\n\tD33 = IO33\n\tD37 = IO37\n)\n\n// Analog pins\nconst (\n\tA0 = IO26\n\tA1 = IO25\n\tA2 = IO34\n\tA3 = IO39\n\tA4 = IO36\n\tA5 = IO4\n)\n\n// Built-in LEDs and Button\nconst (\n\tWS2812             = IO0\n\tNEOPIXEL           = WS2812\n\tNEOPIXEL_I2C_POWER = IO2\n\tLED                = IO13\n\tBUTTON             = IO38\n)\n\n// SPI pins\nconst (\n\tSPI_SCK_PIN  = IO5\n\tSPI_MOSI_PIN = IO19\n\tSPI_MISO_PIN = IO21\n\n\tSPI_SDO_PIN = SPI_MOSI_PIN\n\tSPI_SDI_PIN = SPI_MISO_PIN\n\n\t// Silk labels\n\tSCK = SPI_SCK_PIN\n\tMO  = SPI_MOSI_PIN\n\tMI  = SPI_MISO_PIN\n)\n\n// I2C pins\nconst (\n\tI2C_SCL_PIN = IO20\n\tI2C_SDA_PIN = IO22\n\n\t// Silk labels\n\tSCL = I2C_SCL_PIN\n\tSDA = I2C_SDA_PIN\n)\n\n// ADC pins\nconst (\n\tADC1_0 = IO36\n\tADC1_1 = IO37\n\tADC1_2 = IO38\n\tADC1_3 = IO39\n\tADC1_4 = IO32\n\tADC1_5 = IO33\n\tADC1_6 = IO34\n\tADC1_7 = IO35\n\n\tADC2_0 = IO4\n\tADC2_1 = IO0\n\tADC2_2 = IO2\n\tADC2_3 = IO15\n\tADC2_4 = IO13\n\tADC2_5 = IO12\n\tADC2_6 = IO14\n\tADC2_7 = IO27\n\tADC2_8 = IO25\n\tADC2_9 = IO26\n)\n\n// UART pins\nconst (\n\tUART_TX_PIN = IO19\n\tUART_RX_PIN = IO22\n\n\tUART2_TX_PIN = IO8\n\tUART2_RX_PIN = IO7\n\n\t// Silk labels\n\tRX = UART2_RX_PIN\n\tTX = UART2_TX_PIN\n)\n"
  },
  {
    "path": "src/machine/board_ae_rp2040.go",
    "content": "//go:build ae_rp2040\n\npackage machine\n\n// GPIO pins\nconst (\n\tGP0  Pin = GPIO0\n\tGP1  Pin = GPIO1\n\tGP2  Pin = GPIO2\n\tGP3  Pin = GPIO3\n\tGP4  Pin = GPIO4\n\tGP5  Pin = GPIO5\n\tGP6  Pin = GPIO6\n\tGP7  Pin = GPIO7\n\tGP8  Pin = GPIO8\n\tGP9  Pin = GPIO9\n\tGP10 Pin = GPIO10\n\tGP11 Pin = GPIO11\n\tGP12 Pin = GPIO12\n\tGP13 Pin = GPIO13\n\tGP14 Pin = GPIO14\n\tGP15 Pin = GPIO15\n\tGP16 Pin = GPIO16\n\tGP17 Pin = GPIO17\n\tGP18 Pin = GPIO18\n\tGP19 Pin = GPIO19\n\tGP20 Pin = GPIO20\n\tGP21 Pin = GPIO21\n\tGP22 Pin = GPIO22\n\tGP26 Pin = GPIO26\n\tGP27 Pin = GPIO27\n\tGP28 Pin = GPIO28\n\tGP29 Pin = GPIO29\n\n\t// Onboard crystal oscillator frequency, in MHz.\n\txoscFreq = 12 // MHz\n)\n\n// I2C Default pins on Raspberry Pico.\nconst (\n\tI2C0_SDA_PIN = GP4\n\tI2C0_SCL_PIN = GP5\n\n\tI2C1_SDA_PIN = GP2\n\tI2C1_SCL_PIN = GP3\n)\n\n// SPI default pins\nconst (\n\t// Default Serial Clock Bus 0 for SPI communications\n\tSPI0_SCK_PIN = GPIO18\n\t// Default Serial Out Bus 0 for SPI communications\n\tSPI0_SDO_PIN = GPIO19 // Tx\n\t// Default Serial In Bus 0 for SPI communications\n\tSPI0_SDI_PIN = GPIO16 // Rx\n\n\t// Default Serial Clock Bus 1 for SPI communications\n\tSPI1_SCK_PIN = GPIO10\n\t// Default Serial Out Bus 1 for SPI communications\n\tSPI1_SDO_PIN = GPIO11 // Tx\n\t// Default Serial In Bus 1 for SPI communications\n\tSPI1_SDI_PIN = GPIO12 // Rx\n)\n\n// UART pins\nconst (\n\tUART0_TX_PIN = GPIO0\n\tUART0_RX_PIN = GPIO1\n\tUART1_TX_PIN = GPIO8\n\tUART1_RX_PIN = GPIO9\n\tUART_TX_PIN  = UART0_TX_PIN\n\tUART_RX_PIN  = UART0_RX_PIN\n)\n\nvar DefaultUART = UART0\n\n// USB identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"AE-RP2040\"\n\tusb_STRING_MANUFACTURER = \"AKIZUKI DENSHI\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2E8A\n\tusb_PID uint16 = 0x000A\n)\n"
  },
  {
    "path": "src/machine/board_arduino.go",
    "content": "//go:build arduino\n\npackage machine\n\n// Digital pins, marked as plain numbers on the board.\nconst (\n\tD0  = PD0 // RX\n\tD1  = PD1 // TX\n\tD2  = PD2\n\tD3  = PD3\n\tD4  = PD4\n\tD5  = PD5\n\tD6  = PD6\n\tD7  = PD7\n\tD8  = PB0\n\tD9  = PB1\n\tD10 = PB2\n\tD11 = PB3\n\tD12 = PB4\n\tD13 = PB5\n)\n\n// LED on the Arduino\nconst LED Pin = D13\n\n// ADC on the Arduino\nconst (\n\tADC0 Pin = PC0\n\tADC1 Pin = PC1\n\tADC2 Pin = PC2\n\tADC3 Pin = PC3\n\tADC4 Pin = PC4 // Used by TWI for SDA\n\tADC5 Pin = PC5 // Used by TWI for SCL\n)\n\n// UART pins\nconst (\n\tUART_TX_PIN Pin = PD1\n\tUART_RX_PIN Pin = PD0\n)\n"
  },
  {
    "path": "src/machine/board_arduino_leonardo.go",
    "content": "//go:build arduino_leonardo\n\npackage machine\n\n// Return the current CPU frequency in hertz.\nfunc CPUFrequency() uint32 {\n\treturn 16000000\n}\n\n// Digital pins, marked as plain numbers on the board.\nconst (\n\tD0  = PD2 // RX\n\tD1  = PD3 // TX\n\tD2  = PD1\n\tD3  = PD0\n\tD4  = PD4\n\tD5  = PC6\n\tD6  = PD7\n\tD7  = PE6\n\tD8  = PB4\n\tD9  = PB5\n\tD10 = PB6\n\tD11 = PB7\n\tD12 = PD6\n\tD13 = PC7\n)\n\n// LED on the Arduino\nconst LED Pin = D13\n\n// ADC on the Arduino\nconst (\n\tADC0 Pin = PF7\n\tADC1 Pin = PF6\n\tADC2 Pin = PF5\n\tADC3 Pin = PF4\n\tADC4 Pin = PF1\n\tADC5 Pin = PF0\n)\n"
  },
  {
    "path": "src/machine/board_arduino_mega1280.go",
    "content": "//go:build arduino_mega1280\n\npackage machine\n\n// Return the current CPU frequency in hertz.\nfunc CPUFrequency() uint32 {\n\treturn 16000000\n}\n\nconst (\n\tA0  Pin = PF0\n\tA1  Pin = PF1\n\tA2  Pin = PF2\n\tA3  Pin = PF3\n\tA4  Pin = PF4\n\tA5  Pin = PF5\n\tA6  Pin = PF6\n\tA7  Pin = PF7\n\tA8  Pin = PK0\n\tA9  Pin = PK1\n\tA10 Pin = PK2\n\tA11 Pin = PK3\n\tA12 Pin = PK4\n\tA13 Pin = PK5\n\tA14 Pin = PK6\n\tA15 Pin = PK7\n\n\t// Analog Input\n\tADC0  Pin = PF0\n\tADC1  Pin = PF1\n\tADC2  Pin = PF2\n\tADC3  Pin = PF3\n\tADC4  Pin = PF4\n\tADC5  Pin = PF5\n\tADC6  Pin = PF6\n\tADC7  Pin = PF7\n\tADC8  Pin = PK0\n\tADC9  Pin = PK1\n\tADC10 Pin = PK2\n\tADC11 Pin = PK3\n\tADC12 Pin = PK4\n\tADC13 Pin = PK5\n\tADC14 Pin = PK6\n\tADC15 Pin = PK7\n\n\t// Digital pins\n\tD0  Pin = PE0\n\tD1  Pin = PE1\n\tD2  Pin = PE4\n\tD3  Pin = PE5\n\tD4  Pin = PG5\n\tD5  Pin = PE3\n\tD6  Pin = PH3\n\tD7  Pin = PH4\n\tD8  Pin = PH5\n\tD9  Pin = PH6\n\tD10 Pin = PB4\n\tD11 Pin = PB5\n\tD12 Pin = PB6\n\tD13 Pin = PB7\n\tD14 Pin = PJ1\n\tD15 Pin = PJ0\n\tD16 Pin = PH1\n\tD17 Pin = PH0\n\tD18 Pin = PD3\n\tD19 Pin = PD2\n\tD20 Pin = PD1\n\tD21 Pin = PD0\n\tD22 Pin = PA0\n\tD23 Pin = PA1\n\tD24 Pin = PA2\n\tD25 Pin = PA3\n\tD26 Pin = PA4\n\tD27 Pin = PA5\n\tD28 Pin = PA6\n\tD29 Pin = PA7\n\tD30 Pin = PC7\n\tD31 Pin = PC6\n\tD32 Pin = PC5\n\tD33 Pin = PC4\n\tD34 Pin = PC3\n\tD35 Pin = PC2\n\tD36 Pin = PC1\n\tD37 Pin = PC0\n\tD38 Pin = PD7\n\tD39 Pin = PG2\n\tD40 Pin = PG1\n\tD41 Pin = PG0\n\tD42 Pin = PL7\n\tD43 Pin = PL6\n\tD44 Pin = PL5\n\tD45 Pin = PL4\n\tD46 Pin = PL3\n\tD47 Pin = PL2\n\tD48 Pin = PL1\n\tD49 Pin = PL0\n\tD50 Pin = PB3\n\tD51 Pin = PB2\n\tD52 Pin = PB1\n\tD53 Pin = PB0\n\n\tAREF Pin = NoPin\n\tLED  Pin = PB7\n)\n"
  },
  {
    "path": "src/machine/board_arduino_mega2560.go",
    "content": "//go:build arduino_mega2560\n\npackage machine\n\nimport (\n\t\"device/avr\"\n\t\"runtime/interrupt\"\n)\n\n// Return the current CPU frequency in hertz.\nfunc CPUFrequency() uint32 {\n\treturn 16000000\n}\n\nconst (\n\tA0  Pin = PF0\n\tA1  Pin = PF1\n\tA2  Pin = PF2\n\tA3  Pin = PF3\n\tA4  Pin = PF4\n\tA5  Pin = PF5\n\tA6  Pin = PF6\n\tA7  Pin = PF7\n\tA8  Pin = PK0\n\tA9  Pin = PK1\n\tA10 Pin = PK2\n\tA11 Pin = PK3\n\tA12 Pin = PK4\n\tA13 Pin = PK5\n\tA14 Pin = PK6\n\tA15 Pin = PK7\n\n\t// Analog Input\n\tADC0  Pin = PF0\n\tADC1  Pin = PF1\n\tADC2  Pin = PF2\n\tADC3  Pin = PF3\n\tADC4  Pin = PF4\n\tADC5  Pin = PF5\n\tADC6  Pin = PF6\n\tADC7  Pin = PF7\n\tADC8  Pin = PK0\n\tADC9  Pin = PK1\n\tADC10 Pin = PK2\n\tADC11 Pin = PK3\n\tADC12 Pin = PK4\n\tADC13 Pin = PK5\n\tADC14 Pin = PK6\n\tADC15 Pin = PK7\n\n\t// Digital pins\n\tD0  Pin = PE0\n\tD1  Pin = PE1\n\tD2  Pin = PE4\n\tD3  Pin = PE5\n\tD4  Pin = PG5\n\tD5  Pin = PE3\n\tD6  Pin = PH3\n\tD7  Pin = PH4\n\tD8  Pin = PH5\n\tD9  Pin = PH6\n\tD10 Pin = PB4\n\tD11 Pin = PB5\n\tD12 Pin = PB6\n\tD13 Pin = PB7\n\tD14 Pin = PJ1 // TX3\n\tD15 Pin = PJ0 // RX3\n\tD16 Pin = PH1 // TX2\n\tD17 Pin = PH0 // RX2\n\tD18 Pin = PD3 // TX1\n\tD19 Pin = PD2 // RX1\n\tD20 Pin = PD1\n\tD21 Pin = PD0\n\tD22 Pin = PA0\n\tD23 Pin = PA1\n\tD24 Pin = PA2\n\tD25 Pin = PA3\n\tD26 Pin = PA4\n\tD27 Pin = PA5\n\tD28 Pin = PA6\n\tD29 Pin = PA7\n\tD30 Pin = PC7\n\tD31 Pin = PC6\n\tD32 Pin = PC5\n\tD33 Pin = PC4\n\tD34 Pin = PC3\n\tD35 Pin = PC2\n\tD36 Pin = PC1\n\tD37 Pin = PC0\n\tD38 Pin = PD7\n\tD39 Pin = PG2\n\tD40 Pin = PG1\n\tD41 Pin = PG0\n\tD42 Pin = PL7\n\tD43 Pin = PL6\n\tD44 Pin = PL5\n\tD45 Pin = PL4\n\tD46 Pin = PL3\n\tD47 Pin = PL2\n\tD48 Pin = PL1\n\tD49 Pin = PL0\n\tD50 Pin = PB3\n\tD51 Pin = PB2\n\tD52 Pin = PB1\n\tD53 Pin = PB0\n\n\tAREF Pin = NoPin\n\tLED  Pin = PB7\n)\n\n// UART pins\nconst (\n\tUART_TX_PIN  Pin = UART0_TX_PIN\n\tUART_RX_PIN  Pin = UART0_RX_PIN\n\tUART0_TX_PIN Pin = D1\n\tUART0_RX_PIN Pin = D0\n\tUART1_TX_PIN Pin = D18\n\tUART1_RX_PIN Pin = D19\n\tUART2_TX_PIN Pin = D16\n\tUART2_RX_PIN Pin = D17\n\tUART3_TX_PIN Pin = D14\n\tUART3_RX_PIN Pin = D15\n)\n\nvar (\n\tUART1  = &_UART1\n\t_UART1 = UART{\n\t\tBuffer: NewRingBuffer(),\n\n\t\tdataReg:    avr.UDR1,\n\t\tbaudRegH:   avr.UBRR1H,\n\t\tbaudRegL:   avr.UBRR1L,\n\t\tstatusRegA: avr.UCSR1A,\n\t\tstatusRegB: avr.UCSR1B,\n\t\tstatusRegC: avr.UCSR1C,\n\t}\n\tUART2  = &_UART2\n\t_UART2 = UART{\n\t\tBuffer: NewRingBuffer(),\n\n\t\tdataReg:    avr.UDR2,\n\t\tbaudRegH:   avr.UBRR2H,\n\t\tbaudRegL:   avr.UBRR2L,\n\t\tstatusRegA: avr.UCSR2A,\n\t\tstatusRegB: avr.UCSR2B,\n\t\tstatusRegC: avr.UCSR2C,\n\t}\n\tUART3  = &_UART3\n\t_UART3 = UART{\n\t\tBuffer: NewRingBuffer(),\n\n\t\tdataReg:    avr.UDR3,\n\t\tbaudRegH:   avr.UBRR3H,\n\t\tbaudRegL:   avr.UBRR3L,\n\t\tstatusRegA: avr.UCSR3A,\n\t\tstatusRegB: avr.UCSR3B,\n\t\tstatusRegC: avr.UCSR3C,\n\t}\n)\n\nfunc init() {\n\tinterrupt.New(irq_USART1_RX, _UART1.handleInterrupt)\n\tinterrupt.New(irq_USART2_RX, _UART2.handleInterrupt)\n\tinterrupt.New(irq_USART3_RX, _UART3.handleInterrupt)\n}\n"
  },
  {
    "path": "src/machine/board_arduino_mkr1000.go",
    "content": "//go:build arduino_mkr1000\n\n// This contains the pin mappings for the Arduino MKR1000 board.\n//\n// For more information, see: https://store.arduino.cc/usa/arduino-mkr1000-with-headers-mounted\npackage machine\n\n// used to reset into bootloader\nconst resetMagicValue = 0x07738135\n\n// GPIO Pins\nconst (\n\tD0 Pin = PA22 // PWM available\n\tD1 Pin = PA23 // PWM available\n\tD2 Pin = PA10 // PWM available\n\tD3 Pin = PA11 // PWM available\n\tD4 Pin = PB10 // PWM available\n\tD5 Pin = PB11 // PWM available\n\n\tD6  Pin = PA20 // PWM available\n\tD7  Pin = PA21 // PWM available\n\tD8  Pin = PA16 // PWM available\n\tD9  Pin = PA17\n\tD10 Pin = PA19 // PWM available\n\tD11 Pin = PA08 // SDA\n\tD12 Pin = PA09 // PWM available, SCL\n\tD13 Pin = PB23 // RX\n\tD14 Pin = PB22 // TX\n\n\tRX0 Pin = PB23 // UART2 RX\n\tTX1 Pin = PB22 // UART2 TX\n)\n\n// Analog pins\nconst (\n\tA0 Pin = PA02 // ADC0/AIN[0]\n\tA1 Pin = PB02 // AIN[10]\n\tA2 Pin = PB03 // AIN[11]\n\tA3 Pin = PA04 // AIN[04]\n\tA4 Pin = PA05 // AIN[05]\n\tA5 Pin = PA06 // AIN[06]\n\tA6 Pin = PA07 // AIN[07]\n)\n\nconst (\n\tLED = D6\n)\n\n// USBCDC pins\nconst (\n\tUSBCDC_DM_PIN Pin = PA24\n\tUSBCDC_DP_PIN Pin = PA25\n)\n\n// UART1 pins\nconst (\n\tUART_TX_PIN Pin = PB22\n\tUART_RX_PIN Pin = PB23\n)\n\n// I2C pins\nconst (\n\tSDA_PIN Pin = D11 // SDA\n\tSCL_PIN Pin = D12 // SCL\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN Pin = D9  // SCK: S1\n\tSPI0_SDO_PIN Pin = D8  // SDO: S1\n\tSPI0_SDI_PIN Pin = D10 // SDI: S1\n)\n\n// I2S pins\nconst (\n\tI2S_SCK_PIN Pin = PA10\n\tI2S_SDO_PIN Pin = PA07\n\tI2S_SDI_PIN     = NoPin\n\tI2S_WS_PIN      = NoPin // TODO: figure out what this is on Arduino MKR1000\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Arduino MKR1000\"\n\tusb_STRING_MANUFACTURER = \"Arduino\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2341\n\tusb_PID uint16 = 0x804e\n)\n"
  },
  {
    "path": "src/machine/board_arduino_mkrwifi1010.go",
    "content": "//go:build arduino_mkrwifi1010\n\n// This contains the pin mappings for the Arduino MKR WiFi 1010 board.\n//\n// For more information, see: https://store.arduino.cc/usa/mkr-wifi-1010\npackage machine\n\n// used to reset into bootloader\nconst resetMagicValue = 0x07738135\n\n// GPIO Pins\nconst (\n\tD0 Pin = PA22 // PWM available\n\tD1 Pin = PA23 // PWM available\n\tD2 Pin = PA10 // PWM available\n\tD3 Pin = PA11 // PWM available\n\tD4 Pin = PB10 // PWM available\n\tD5 Pin = PB11 // PWM available\n\n\tD6  Pin = PA20 // PWM available\n\tD7  Pin = PA21 // PWM available\n\tD8  Pin = PA16 // PWM available\n\tD9  Pin = PA17\n\tD10 Pin = PA19 // PWM available\n\tD11 Pin = PA08 // SDA\n\tD12 Pin = PA09 // PWM available, SCL\n\tD13 Pin = PB23 // RX\n\tD14 Pin = PB22 // TX\n\n\tRX0 Pin = PB23 // UART1 RX\n\tTX1 Pin = PB22 // UART1 TX\n)\n\n// Analog pins\nconst (\n\tA0 Pin = PA02 // ADC0/AIN[0]\n\tA1 Pin = PB02 // AIN[10]\n\tA2 Pin = PB03 // AIN[11]\n\tA3 Pin = PA04 // AIN[04]\n\tA4 Pin = PA05 // AIN[05]\n\tA5 Pin = PA06 // AIN[06]\n\tA6 Pin = PA07 // AIN[07]\n)\n\nconst (\n\tLED = D6\n)\n\n// USBCDC pins\nconst (\n\tUSBCDC_DM_PIN Pin = PA24\n\tUSBCDC_DP_PIN Pin = PA25\n)\n\n// UART1 pins\nconst (\n\tUART_TX_PIN Pin = PB22\n\tUART_RX_PIN Pin = PB23\n)\n\n// I2C pins\nconst (\n\tSDA_PIN Pin = D11 // SDA\n\tSCL_PIN Pin = D12 // SCL\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN Pin = D9  // SCK: S1\n\tSPI0_SDO_PIN Pin = D8  // SDO: S1\n\tSPI0_SDI_PIN Pin = D10 // SDI: S1\n)\n\n// I2S pins\nconst (\n\tI2S_SCK_PIN Pin = PA10\n\tI2S_SDO_PIN Pin = PA07\n\tI2S_SDI_PIN     = NoPin\n\tI2S_WS_PIN      = NoPin // TODO: figure out what this is on Arduino MKR WiFi 1010.\n)\n\n// NINA-W102 Pins\nconst (\n\tNINA_SDO    Pin = PA12\n\tNINA_SDI    Pin = PA13\n\tNINA_CS     Pin = PA14\n\tNINA_SCK    Pin = PA15\n\tNINA_GPIO0  Pin = PA27\n\tNINA_RESETN Pin = PB08\n\tNINA_ACK    Pin = PA28\n\tNINA_TX     Pin = PA22\n\tNINA_RX     Pin = PA23\n)\n\n// UART on the Arduino MKR WiFi 1010.\nvar UART1 = &sercomUSART5\n\n// I2C on the Arduino MKR WiFi 1010.\nvar (\n\tI2C0 = sercomI2CM2\n)\n\n// SPI on the Arduino MKR WiFi 1010.\nvar (\n\tSPI0 = sercomSPIM1\n\n\tSPI1     = sercomSPIM4\n\tNINA_SPI = SPI1\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Arduino MKR WiFi 1010\"\n\tusb_STRING_MANUFACTURER = \"Arduino\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2341\n\tusb_PID uint16 = 0x8054\n)\n\nvar (\n\tDefaultUART = UART1\n)\n"
  },
  {
    "path": "src/machine/board_arduino_nano.go",
    "content": "//go:build arduino_nano\n\npackage machine\n\n// Digital pins.\nconst (\n\tD0  = PD0 // RX0\n\tD1  = PD1 // TX1\n\tD2  = PD2\n\tD3  = PD3\n\tD4  = PD4\n\tD5  = PD5\n\tD6  = PD6\n\tD7  = PD7\n\tD8  = PB0\n\tD9  = PB1\n\tD10 = PB2\n\tD11 = PB3\n\tD12 = PB4\n\tD13 = PB5\n)\n\n// LED on the Arduino\nconst LED Pin = D13\n\n// ADC on the Arduino\nconst (\n\tADC0 Pin = PC0\n\tADC1 Pin = PC1\n\tADC2 Pin = PC2\n\tADC3 Pin = PC3\n\tADC4 Pin = PC4 // Used by TWI for SDA\n\tADC5 Pin = PC5 // Used by TWI for SCL\n)\n\n// UART pins\nconst (\n\tUART_TX_PIN Pin = PD1\n\tUART_RX_PIN Pin = PD0\n)\n"
  },
  {
    "path": "src/machine/board_arduino_nano33.go",
    "content": "//go:build arduino_nano33\n\n// This contains the pin mappings for the Arduino Nano33 IoT board.\n//\n// For more information, see: https://store.arduino.cc/nano-33-iot\npackage machine\n\n// used to reset into bootloader\nconst resetMagicValue = 0x07738135\n\n// GPIO Pins\nconst (\n\tRX0 Pin = PB23 // UART2 RX\n\tTX1 Pin = PB22 // UART2 TX\n\n\tD2 Pin = PB10 // PWM available\n\tD3 Pin = PB11 // PWM available\n\tD4 Pin = PA07\n\tD5 Pin = PA05 // PWM available\n\tD6 Pin = PA04 // PWM available\n\tD7 Pin = PA06\n\n\tD8  Pin = PA18\n\tD9  Pin = PA20 // PWM available\n\tD10 Pin = PA21 // PWM available\n\tD11 Pin = PA16 // PWM available\n\tD12 Pin = PA19 // PWM available\n\n\tD13 Pin = PA17\n)\n\n// Analog pins\nconst (\n\tA0 Pin = PA02 // ADC/AIN[0]\n\tA1 Pin = PB02 // ADC/AIN[10]\n\tA2 Pin = PA11 // ADC/AIN[19]\n\tA3 Pin = PA10 // ADC/AIN[18],\n\tA4 Pin = PB08 // ADC/AIN[2], SCL:  SERCOM2/PAD[1]\n\tA5 Pin = PB09 // ADC/AIN[3], SDA:  SERCOM2/PAD[1]\n\tA6 Pin = PA09 // ADC/AIN[17]\n\tA7 Pin = PB03 // ADC/AIN[11]\n)\n\nconst (\n\tLED = D13\n)\n\n// USBCDC pins\nconst (\n\tUSBCDC_DM_PIN Pin = PA24\n\tUSBCDC_DP_PIN Pin = PA25\n)\n\n// UART1 pins\nconst (\n\tUART_TX_PIN Pin = PA22\n\tUART_RX_PIN Pin = PA23\n)\n\n// UART1 on the Arduino Nano 33 connects to the onboard NINA-W102 WiFi chip.\nvar UART1 = &sercomUSART3\n\n// UART2 on the Arduino Nano 33 connects to the normal TX/RX pins.\nvar UART2 = &sercomUSART5\n\n// UART_NINA on the Arduino Nano 33 connects to the NINA HCI.\nvar UART_NINA = &sercomUSART2\n\n// I2C pins\nconst (\n\tSDA_PIN Pin = A4 // SDA: SERCOM4/PAD[1]\n\tSCL_PIN Pin = A5 // SCL: SERCOM4/PAD[1]\n)\n\n// I2C on the Arduino Nano 33.\nvar (\n\tI2C0 = sercomI2CM4\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN Pin = D13 // SCK: SERCOM1/PAD[1]\n\tSPI0_SDO_PIN Pin = D11 // SDO: SERCOM1/PAD[0]\n\tSPI0_SDI_PIN Pin = D12 // SDI: SERCOM1/PAD[3]\n)\n\n// SPI on the Arduino Nano 33.\nvar SPI0 = sercomSPIM1\n\n// SPI1 is connected to the NINA-W102 chip on the Arduino Nano 33.\nvar (\n\tSPI1     = sercomSPIM2\n\tNINA_SPI = SPI1\n)\n\n// NINA-W102 Pins\nconst (\n\tNINA_SDO    Pin = PA12\n\tNINA_SDI    Pin = PA13\n\tNINA_CS     Pin = PA14\n\tNINA_SCK    Pin = PA15\n\tNINA_GPIO0  Pin = PA27\n\tNINA_RESETN Pin = PA08\n\tNINA_ACK    Pin = PA28\n\tNINA_TX     Pin = PA12\n\tNINA_RX     Pin = PA13\n\tNINA_RTS    Pin = PA14\n\tNINA_CTS    Pin = PA15\n)\n\n// NINA-W102 settings\nconst (\n\tNINA_BAUDRATE         = 912600\n\tNINA_RESET_INVERTED   = true\n\tNINA_SOFT_FLOWCONTROL = false\n)\n\n// I2S pins\nconst (\n\tI2S_SCK_PIN Pin = PA10\n\tI2S_SDO_PIN Pin = PA08\n\tI2S_SDI_PIN     = NoPin\n\tI2S_WS_PIN      = NoPin // TODO: figure out what this is on Arduino Nano 33.\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Arduino NANO 33 IoT\"\n\tusb_STRING_MANUFACTURER = \"Arduino\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2341\n\tusb_PID uint16 = 0x8057\n)\n"
  },
  {
    "path": "src/machine/board_arduino_zero.go",
    "content": "//go:build sam && atsamd21 && arduino_zero\n\npackage machine\n\n// used to reset into bootloader\nconst resetMagicValue = 0x07738135\n\n// GPIO Pins - Digital Low\nconst (\n\tD0 = PA11 // RX\n\tD1 = PA10 // TX\n\tD2 = PA14\n\tD3 = PA09 // PWM available\n\tD4 = PA08 // PWM available\n\tD5 = PA15 // PWM available\n\tD6 = PA20 // PWM available\n\tD7 = PA21\n)\n\n// GPIO Pins - Digital High\nconst (\n\tD8  = PA06 // PWM available\n\tD9  = PA07 // PWM available\n\tD10 = PA18 // PWM available\n\tD11 = PA16 // PWM available\n\tD12 = PA19 // PWM available\n\tD13 = PA17 // PWM available\n)\n\n// ADC pins\nconst (\n\tAREF Pin = PA03\n\tADC0 Pin = PA02\n\tADC1 Pin = PB08\n\tADC2 Pin = PB09\n\tADC3 Pin = PA04\n\tADC4 Pin = PA05\n\tADC5 Pin = PB02\n)\n\n// LEDs on the Arduino Zero\nconst (\n\tLED      = LED1\n\tLED1 Pin = D13\n\tLED2 Pin = PA27 // TX LED\n\tLED3 Pin = PB03 // RX LED\n)\n\n// SPI pins - EDBG connected\nconst (\n\tSPI0_SDO_PIN Pin = PA16 // MOSI: SERCOM1/PAD[0]\n\tSPI0_SDI_PIN Pin = PA19 // MISO: SERCOM1/PAD[2]\n\tSPI0_SCK_PIN Pin = PA17 // SCK:  SERCOM1/PAD[3]\n)\n\n// SPI pins (Legacy ICSP)\nconst (\n\tSPI1_SDO_PIN Pin = PB10 // MOSI: SERCOM4/PAD[2] - Pin 4\n\tSPI1_SDI_PIN Pin = PA12 // MISO: SERCOM4/PAD[0] - Pin 1\n\tSPI1_SCK_PIN Pin = PB11 // SCK:  SERCOM4/PAD[3] - Pin 3\n)\n\n// I2C pins - EDBG connected\nconst (\n\tSDA_PIN Pin = PA22 // SDA: SERCOM3/PAD[0] - Pin 20\n\tSCL_PIN Pin = PA23 // SCL: SERCOM3/PAD[1] - Pin 21\n)\n\n// I2S pins - might not be exposed\nconst (\n\tI2S_SCK_PIN Pin = PA10\n\tI2S_SDO_PIN Pin = PA07\n\tI2S_SDI_PIN     = NoPin\n\tI2S_WS_PIN  Pin = PA11\n)\n\n// UART0 pins - EDBG connected\nconst (\n\tUART_RX_PIN Pin = D0\n\tUART_TX_PIN Pin = D1\n)\n\n// 'native' USB port pins\nconst (\n\tUSBCDC_DM_PIN Pin = PA24\n\tUSBCDC_DP_PIN Pin = PA25\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Arduino Zero\"\n\tusb_STRING_MANUFACTURER = \"Arduino LLC\"\n\n\tusb_VID uint16 = 0x2341\n\tusb_PID uint16 = 0x804d\n)\n\n// 32.768 KHz Crystal\nconst (\n\tXIN32  Pin = PA00\n\tXOUT32 Pin = PA01\n)\n"
  },
  {
    "path": "src/machine/board_atmega328p.go",
    "content": "//go:build (avr && atmega328p) || arduino || arduino_nano\n\npackage machine\n\n// Return the current CPU frequency in hertz.\nfunc CPUFrequency() uint32 {\n\treturn 16000000\n}\n\nconst (\n\t// Note: start at port B because there is no port A.\n\tportB Pin = iota * 8\n\tportC\n\tportD\n)\n\nconst (\n\tPB0 = portB + 0\n\tPB1 = portB + 1 // peripherals: Timer1 channel A\n\tPB2 = portB + 2 // peripherals: Timer1 channel B\n\tPB3 = portB + 3 // peripherals: Timer2 channel A\n\tPB4 = portB + 4\n\tPB5 = portB + 5\n\tPB6 = portB + 6\n\tPB7 = portB + 7\n\tPC0 = portC + 0\n\tPC1 = portC + 1\n\tPC2 = portC + 2\n\tPC3 = portC + 3\n\tPC4 = portC + 4 // peripherals: I2C0 SDA\n\tPC5 = portC + 5 // peripherals: I2C0 SCL\n\tPC6 = portC + 6\n\tPC7 = portC + 7\n\tPD0 = portD + 0\n\tPD1 = portD + 1\n\tPD2 = portD + 2\n\tPD3 = portD + 3 // peripherals: Timer2 channel B\n\tPD4 = portD + 4\n\tPD5 = portD + 5 // peripherals: Timer0 channel B\n\tPD6 = portD + 6 // peripherals: Timer0 channel A\n\tPD7 = portD + 7\n)\n"
  },
  {
    "path": "src/machine/board_atmega328pb.go",
    "content": "//go:build avr && atmega328pb\n\npackage machine\n\n// Return the current CPU frequency in hertz.\nfunc CPUFrequency() uint32 {\n\treturn 16000000\n}\n\nconst (\n\t// Note: start at port B because there is no port A.\n\tportB Pin = iota * 8\n\tportC\n\tportD\n\tportE\n)\n\nconst (\n\tPB0 = portB + 0\n\tPB1 = portB + 1 // peripherals: Timer1 channel A\n\tPB2 = portB + 2 // peripherals: Timer1 channel B\n\tPB3 = portB + 3 // peripherals: Timer2 channel A\n\tPB4 = portB + 4\n\tPB5 = portB + 5\n\tPB6 = portB + 6\n\tPB7 = portB + 7\n\tPC0 = portC + 0\n\tPC1 = portC + 1\n\tPC2 = portC + 2\n\tPC3 = portC + 3\n\tPC4 = portC + 4 // peripherals: I2C0 SDA\n\tPC5 = portC + 5 // peripherals: I2C0 SCL\n\tPC6 = portC + 6\n\tPC7 = portC + 7\n\tPD0 = portD + 0\n\tPD1 = portD + 1\n\tPD2 = portD + 2\n\tPD3 = portD + 3 // peripherals: Timer2 channel B\n\tPD4 = portD + 4\n\tPD5 = portD + 5 // peripherals: Timer0 channel B\n\tPD6 = portD + 6 // peripherals: Timer0 channel A\n\tPD7 = portD + 7\n\tPE0 = portE + 0 // peripherals: I2C1 SDA\n\tPE1 = portE + 1 // peripherals: I2C1 SCL\n\tPE2 = portE + 2\n\tPE3 = portE + 3\n\tPE4 = portE + 4\n\tPE5 = portE + 5\n\tPE6 = portE + 6\n\tPE7 = portE + 7\n)\n"
  },
  {
    "path": "src/machine/board_atsamd21.go",
    "content": "//go:build (sam && atsamd21) || arduino_nano33 || circuitplay_express\n\npackage machine\n\n// Return the current CPU frequency in hertz.\nfunc CPUFrequency() uint32 {\n\treturn 48000000\n}\n\n// Note that the below pins have a few I2C pins listed that according to the\n// datasheet don't support I2C yet they are used in practice on boards from\n// Adafruit and Arduino. See machine_atsamd21_simulator.go for details.\n\n// Hardware pins\nconst (\n\tPA00 Pin = 0 // peripherals: TCC2 channel 0, sercomI2CM1 SDA\n\tPA01 Pin = 1 // peripherals: TCC2 channel 1, sercomI2CM1 SCL\n\tPA02 Pin = 2\n\tPA03 Pin = 3\n\tPA04 Pin = 4  // peripherals: TCC0 channel 0\n\tPA05 Pin = 5  // peripherals: TCC0 channel 1\n\tPA06 Pin = 6  // peripherals: TCC1 channel 0\n\tPA07 Pin = 7  // peripherals: TCC1 channel 1\n\tPA08 Pin = 8  // peripherals: TCC0 channel 0, TCC1 channel 2, sercomI2CM0 SDA, sercomI2CM2 SDA\n\tPA09 Pin = 9  // peripherals: TCC0 channel 1, TCC1 channel 3, sercomI2CM0 SCL, sercomI2CM2 SCL\n\tPA10 Pin = 10 // peripherals: TCC1 channel 0, TCC0 channel 2\n\tPA11 Pin = 11 // peripherals: TCC1 channel 1, TCC0 channel 3\n\tPA12 Pin = 12 // peripherals: TCC2 channel 0, TCC0 channel 2, sercomI2CM2 SDA, sercomI2CM4 SDA\n\tPA13 Pin = 13 // peripherals: TCC2 channel 1, TCC0 channel 3, sercomI2CM2 SCL, sercomI2CM4 SCL\n\tPA14 Pin = 14 // peripherals: TCC0 channel 0\n\tPA15 Pin = 15 // peripherals: TCC0 channel 1\n\tPA16 Pin = 16 // peripherals: TCC2 channel 0, TCC0 channel 2, sercomI2CM1 SDA, sercomI2CM3 SDA\n\tPA17 Pin = 17 // peripherals: TCC2 channel 1, TCC0 channel 3, sercomI2CM1 SCL, sercomI2CM3 SCL\n\tPA18 Pin = 18 // peripherals: TCC0 channel 2\n\tPA19 Pin = 19 // peripherals: TCC0 channel 3\n\tPA20 Pin = 20 // peripherals: TCC0 channel 2\n\tPA21 Pin = 21 // peripherals: TCC0 channel 3\n\tPA22 Pin = 22 // peripherals: TCC0 channel 0, sercomI2CM3 SDA, sercomI2CM5 SDA\n\tPA23 Pin = 23 // peripherals: TCC0 channel 1, sercomI2CM3 SCL, sercomI2CM5 SCL\n\tPA24 Pin = 24 // peripherals: TCC1 channel 2\n\tPA25 Pin = 25 // peripherals: TCC1 channel 3\n\tPA26 Pin = 26\n\tPA27 Pin = 27\n\tPA28 Pin = 28\n\tPA29 Pin = 29\n\tPA30 Pin = 30 // peripherals: TCC1 channel 0\n\tPA31 Pin = 31 // peripherals: TCC1 channel 1\n\tPB00 Pin = 32\n\tPB01 Pin = 33\n\tPB02 Pin = 34 // peripherals: sercomI2CM5 SDA\n\tPB03 Pin = 35 // peripherals: sercomI2CM5 SCL\n\tPB04 Pin = 36\n\tPB05 Pin = 37\n\tPB06 Pin = 38\n\tPB07 Pin = 39\n\tPB08 Pin = 40 // peripherals: sercomI2CM4 SDA\n\tPB09 Pin = 41 // peripherals: sercomI2CM4 SCL\n\tPB10 Pin = 42 // peripherals: TCC0 channel 0\n\tPB11 Pin = 43 // peripherals: TCC0 channel 1\n\tPB12 Pin = 44 // peripherals: TCC0 channel 2, sercomI2CM4 SDA\n\tPB13 Pin = 45 // peripherals: TCC0 channel 3, sercomI2CM4 SCL\n\tPB14 Pin = 46\n\tPB15 Pin = 47\n\tPB16 Pin = 48 // peripherals: TCC0 channel 0, sercomI2CM5 SDA\n\tPB17 Pin = 49 // peripherals: TCC0 channel 1, sercomI2CM5 SCL\n\tPB18 Pin = 50\n\tPB19 Pin = 51\n\tPB20 Pin = 52\n\tPB21 Pin = 53\n\tPB22 Pin = 54\n\tPB23 Pin = 55\n\tPB24 Pin = 56\n\tPB25 Pin = 57\n\tPB26 Pin = 58\n\tPB27 Pin = 59\n\tPB28 Pin = 60\n\tPB29 Pin = 61\n\tPB30 Pin = 62 // peripherals: TCC0 channel 0, TCC1 channel 2, sercomI2CM5 SDA\n\tPB31 Pin = 63 // peripherals: TCC0 channel 1, TCC1 channel 3, sercomI2CM5 SCL\n)\n"
  },
  {
    "path": "src/machine/board_atsame54-xpro.go",
    "content": "//go:build atsame54_xpro\n\npackage machine\n\nimport (\n\t\"device/sam\"\n)\n\n// Definition for compatibility, but not used\nconst resetMagicValue = 0x00000000\n\nconst (\n\tLED    = PC18\n\tBUTTON = PB31\n)\n\nconst (\n\t// https://ww1.microchip.com/downloads/en/DeviceDoc/70005321A.pdf\n\n\t// Extension Header EXT1\n\tEXT1_PIN3_ADC_P     = PB04\n\tEXT1_PIN4_ADC_N     = PB05\n\tEXT1_PIN5_GPIO1     = PA06\n\tEXT1_PIN6_GPIO2     = PA07\n\tEXT1_PIN7_PWM_P     = PB08\n\tEXT1_PIN8_PWM_N     = PB09\n\tEXT1_PIN9_IRQ       = PB07\n\tEXT1_PIN9_GPIO      = PB07\n\tEXT1_PIN10_SPI_SS_B = PA27\n\tEXT1_PIN10_GPIO     = PA27\n\tEXT1_PIN11_TWI_SDA  = PA22\n\tEXT1_PIN12_TWI_SCL  = PA23\n\tEXT1_PIN13_UART_RX  = PA05\n\tEXT1_PIN14_UART_TX  = PA04\n\tEXT1_PIN15_SPI_SS_A = PB28\n\tEXT1_PIN16_SPI_SDO  = PB27\n\tEXT1_PIN17_SPI_SDI  = PB29\n\tEXT1_PIN18_SPI_SCK  = PB26\n\n\t// Extension Header EXT2\n\tEXT2_PIN3_ADC_P     = PB00\n\tEXT2_PIN4_ADC_N     = PA03\n\tEXT2_PIN5_GPIO1     = PB01\n\tEXT2_PIN6_GPIO2     = PB06\n\tEXT2_PIN7_PWM_P     = PB14\n\tEXT2_PIN8_PWM_N     = PB15\n\tEXT2_PIN9_IRQ       = PD00\n\tEXT2_PIN9_GPIO      = PD00\n\tEXT2_PIN10_SPI_SS_B = PB02\n\tEXT2_PIN10_GPIO     = PB02\n\tEXT2_PIN11_TWI_SDA  = PD08\n\tEXT2_PIN12_TWI_SCL  = PD09\n\tEXT2_PIN13_UART_RX  = PB17\n\tEXT2_PIN14_UART_TX  = PB16\n\tEXT2_PIN15_SPI_SS_A = PC06\n\tEXT2_PIN16_SPI_SDO  = PC04\n\tEXT2_PIN17_SPI_SDI  = PC07\n\tEXT2_PIN18_SPI_SCK  = PC05\n\n\t// Extension Header EXT3\n\tEXT3_PIN3_ADC_P     = PC02\n\tEXT3_PIN4_ADC_N     = PC03\n\tEXT3_PIN5_GPIO1     = PC01\n\tEXT3_PIN6_GPIO2     = PC10\n\tEXT3_PIN7_PWM_P     = PD10\n\tEXT3_PIN8_PWM_N     = PD11\n\tEXT3_PIN9_IRQ       = PC30\n\tEXT3_PIN9_GPIO      = PC30\n\tEXT3_PIN10_SPI_SS_B = PC31\n\tEXT3_PIN10_GPIO     = PC31\n\tEXT3_PIN11_TWI_SDA  = PD08\n\tEXT3_PIN12_TWI_SCL  = PD09\n\tEXT3_PIN13_UART_RX  = PC23\n\tEXT3_PIN14_UART_TX  = PC22\n\tEXT3_PIN15_SPI_SS_A = PC14\n\tEXT3_PIN16_SPI_SDO  = PC04\n\tEXT3_PIN17_SPI_SDI  = PC07\n\tEXT3_PIN18_SPI_SCK  = PC05\n\n\t// SD_CARD\n\tSD_CARD_MCDA0   = PB18\n\tSD_CARD_MCDA1   = PB19\n\tSD_CARD_MCDA2   = PB20\n\tSD_CARD_MCDA3   = PB21\n\tSD_CARD_MCCK    = PA21\n\tSD_CARD_MCCDA   = PA20\n\tSD_CARD_DETECT  = PD20\n\tSD_CARD_PROTECT = PD21\n\n\t// I2C\n\tI2C_SDA = PD08\n\tI2C_SCL = PD09\n\n\t// CAN\n\tCAN0_TX = PA22\n\tCAN0_RX = PA23\n\n\tCAN1_STANDBY = PC13\n\tCAN1_TX      = PB12\n\tCAN1_RX      = PB13\n\n\tCAN_STANDBY = CAN1_STANDBY\n\tCAN_TX      = CAN1_TX\n\tCAN_RX      = CAN1_RX\n\n\t// PDEC\n\tPDEC_PHASE_A = PC16\n\tPDEC_PHASE_B = PC17\n\tPDEC_INDEX   = PC18\n\n\t// PCC\n\tPCC_I2C_SDA    = PD08\n\tPCC_I2C_SCL    = PD09\n\tPCC_VSYNC_DEN1 = PA12\n\tPCC_HSYNC_DEN2 = PA13\n\tPCC_CLK        = PA14\n\tPCC_XCLK       = PA15\n\tPCC_DATA00     = PA16\n\tPCC_DATA01     = PA17\n\tPCC_DATA02     = PA18\n\tPCC_DATA03     = PA19\n\tPCC_DATA04     = PA20\n\tPCC_DATA05     = PA21\n\tPCC_DATA06     = PA22\n\tPCC_DATA07     = PA23\n\tPCC_DATA08     = PB14\n\tPCC_DATA09     = PB15\n\tPCC_RESET      = PC12\n\tPCC_PWDN       = PC11\n\n\t// Ethernet\n\tETHERNET_TXCK  = PA14\n\tETHERNET_TXEN  = PA17\n\tETHERNET_TX0   = PA18\n\tETHERNET_TX1   = PA19\n\tETHERNET_RXER  = PA15\n\tETHERNET_RX0   = PA13\n\tETHERNET_RX1   = PA12\n\tETHERNET_RXDV  = PC20\n\tETHERNET_MDIO  = PC12\n\tETHERNET_MDC   = PC11\n\tETHERNET_INT   = PD12\n\tETHERNET_RESET = PC21\n\n\tPIN_QT_BUTTON   = PA16\n\tPIN_BTN0        = PB31\n\tPIN_ETH_LED     = PC15\n\tPIN_LED0        = PC18\n\tPIN_ADC_DAC     = PA02\n\tPIN_VBUS_DETECT = PC00\n\tPIN_USB_ID      = PC19\n)\n\n// USBCDC pins\nconst (\n\tUSBCDC_DM_PIN = PA24\n\tUSBCDC_DP_PIN = PA25\n)\n\n// UART pins\nconst (\n\t// Extension Header EXT1\n\tUART_TX_PIN = PA04 // TX : SERCOM0/PAD[0]\n\tUART_RX_PIN = PA05 // RX : SERCOM0/PAD[1]\n\n\t// Extension Header EXT2\n\tUART2_TX_PIN = PB16 // TX : SERCOM5/PAD[0]\n\tUART2_RX_PIN = PB17 // RX : SERCOM5/PAD[1]\n\n\t// Extension Header EXT3\n\tUART3_TX_PIN = PC22 // TX : SERCOM1/PAD[0]\n\tUART3_RX_PIN = PC23 // RX : SERCOM1/PAD[1]\n\n\t// Virtual COM Port\n\tUART4_TX_PIN = PB25 // TX : SERCOM2/PAD[0]\n\tUART4_RX_PIN = PB24 // RX : SERCOM2/PAD[1]\n)\n\n// I2C pins\nconst (\n\t// Extension Header EXT1\n\tSDA0_PIN = PA22 // SDA: SERCOM3/PAD[0]\n\tSCL0_PIN = PA23 // SCL: SERCOM3/PAD[1]\n\n\t// Extension Header EXT2\n\tSDA1_PIN = PD08 // SDA: SERCOM7/PAD[0]\n\tSCL1_PIN = PD09 // SCL: SERCOM7/PAD[1]\n\n\t// Extension Header EXT3\n\tSDA2_PIN = PD08 // SDA: SERCOM7/PAD[0]\n\tSCL2_PIN = PD09 // SCL: SERCOM7/PAD[1]\n\n\t// Data Gateway Interface\n\tSDA_DGI_PIN = PD08 // SDA: SERCOM7/PAD[0]\n\tSCL_DGI_PIN = PD09 // SCL: SERCOM7/PAD[1]\n\n\tSDA_PIN = SDA0_PIN\n\tSCL_PIN = SCL0_PIN\n)\n\n// SPI pins\nconst (\n\t// Extension Header EXT1\n\tSPI0_SCK_PIN = PB26 // SCK: SERCOM4/PAD[1]\n\tSPI0_SDO_PIN = PB27 // SDO: SERCOM4/PAD[0]\n\tSPI0_SDI_PIN = PB29 // SDI: SERCOM4/PAD[3]\n\tSPI0_SS_PIN  = PB28 // SS : SERCOM4/PAD[2]\n\n\t// Extension Header EXT2\n\tSPI1_SCK_PIN = PC05 // SCK: SERCOM6/PAD[1]\n\tSPI1_SDO_PIN = PC04 // SDO: SERCOM6/PAD[0]\n\tSPI1_SDI_PIN = PC07 // SDI: SERCOM6/PAD[3]\n\tSPI1_SS_PIN  = PC06 // SS : SERCOM6/PAD[2]\n\n\t// Extension Header EXT3\n\tSPI2_SCK_PIN = PC05 // SCK: SERCOM6/PAD[1]\n\tSPI2_SDO_PIN = PC04 // SDO: SERCOM6/PAD[0]\n\tSPI2_SDI_PIN = PC07 // SDI: SERCOM6/PAD[3]\n\tSPI2_SS_PIN  = PC14 // SS : GPIO\n\n\t// Data Gateway Interface\n\tSPI_DGI_SCK_PIN = PC05 // SCK: SERCOM6/PAD[1]\n\tSPI_DGI_SDO_PIN = PC04 // SDO: SERCOM6/PAD[0]\n\tSPI_DGI_SDI_PIN = PC07 // SDI: SERCOM6/PAD[3]\n\tSPI_DGI_SS_PIN  = PD01 // SS : GPIO\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"SAM E54 Xplained Pro\"\n\tusb_STRING_MANUFACTURER = \"Atmel\"\n)\n\nvar (\n\tusb_VID uint16 = 0x03EB\n\tusb_PID uint16 = 0x2404\n)\n\n// UART on the SAM E54 Xplained Pro\nvar (\n\t// Extension Header EXT1\n\tUART1 = &sercomUSART0\n\n\t// Extension Header EXT2\n\tUART2 = &sercomUSART5\n\n\t// Extension Header EXT3\n\tUART3 = &sercomUSART1\n\n\t// EDBG Virtual COM Port\n\tUART4 = &sercomUSART2\n)\n\n// I2C on the SAM E54 Xplained Pro\nvar (\n\t// Extension Header EXT1\n\tI2C0 = sercomI2CM3\n\n\t// Extension Header EXT2\n\tI2C1 = sercomI2CM7\n\n\t// Extension Header EXT3\n\tI2C2 = sercomI2CM7\n\n\t// Data Gateway Interface\n\tI2C3 = sercomI2CM7\n)\n\n// SPI on the SAM E54 Xplained Pro\nvar (\n\t// Extension Header EXT1\n\tSPI0 = sercomSPIM4\n\n\t// Extension Header EXT2\n\tSPI1 = sercomSPIM6\n\n\t// Extension Header EXT3\n\tSPI2 = sercomSPIM6\n\n\t// Data Gateway Interface\n\tSPI3 = sercomSPIM6\n)\n\n// CAN on the SAM E54 Xplained Pro\nvar (\n\tCAN0 = CAN{\n\t\tBus: sam.CAN0,\n\t}\n\n\tCAN1 = CAN{\n\t\tBus: sam.CAN1,\n\t}\n)\n"
  },
  {
    "path": "src/machine/board_badger2040-w.go",
    "content": "//go:build badger2040_w\n\n// This contains the pin mappings for the Badger 2040 W board.\n//\n// For more information, see: https://shop.pimoroni.com/products/badger-2040-w\n// Also\n// - Badger 2040 W schematic: https://cdn.shopify.com/s/files/1/0174/1800/files/badger_w_schematic.pdf?v=1675859004\npackage machine\n\nconst (\n\tLED Pin = GPIO22\n\n\tBUTTON_A    Pin = GPIO12\n\tBUTTON_B    Pin = GPIO13\n\tBUTTON_C    Pin = GPIO14\n\tBUTTON_UP   Pin = GPIO15\n\tBUTTON_DOWN Pin = GPIO11\n\tBUTTON_USER Pin = NoPin // Not available on Badger 2040 W\n\n\tEPD_BUSY_PIN  Pin = GPIO26\n\tEPD_RESET_PIN Pin = GPIO21\n\tEPD_DC_PIN    Pin = GPIO20\n\tEPD_CS_PIN    Pin = GPIO17\n\tEPD_SCK_PIN   Pin = GPIO18\n\tEPD_SDO_PIN   Pin = GPIO19\n\n\tVBUS_DETECT Pin = GPIO24\n\tVREF_POWER  Pin = GPIO27\n\tVREF_1V24   Pin = GPIO28\n\tVBAT_SENSE  Pin = GPIO29\n\tENABLE_3V3  Pin = GPIO10\n\n\tBATTERY   = VBAT_SENSE\n\tRTC_ALARM = GPIO8\n)\n\n// I2C pins\nconst (\n\tI2C0_SDA_PIN Pin = GPIO4\n\tI2C0_SCL_PIN Pin = GPIO5\n\n\tI2C1_SDA_PIN Pin = NoPin\n\tI2C1_SCL_PIN Pin = NoPin\n)\n\n// SPI pins.\nconst (\n\tSPI0_SCK_PIN Pin = GPIO18\n\tSPI0_SDO_PIN Pin = GPIO19\n\tSPI0_SDI_PIN Pin = GPIO16\n\n\tSPI1_SCK_PIN Pin = NoPin\n\tSPI1_SDO_PIN Pin = NoPin\n\tSPI1_SDI_PIN Pin = NoPin\n)\n\n// QSPI pins¿?\nconst (\n/*\n\tTODO\n\nSPI0_SD0_PIN Pin = QSPI_SD0\nSPI0_SD1_PIN Pin = QSPI_SD1\nSPI0_SD2_PIN Pin = QSPI_SD2\nSPI0_SD3_PIN Pin = QSPI_SD3\nSPI0_SCK_PIN Pin = QSPI_SCLKGPIO6\nSPI0_CS_PIN  Pin = QSPI_CS\n*/\n)\n\n// Onboard crystal oscillator frequency, in MHz.\nconst (\n\txoscFreq = 12 // MHz\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Badger 2040 W\"\n\tusb_STRING_MANUFACTURER = \"Pimoroni\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2e8a\n\tusb_PID uint16 = 0x0003\n)\n\n// UART pins\nconst (\n\tUART0_TX_PIN = GPIO0\n\tUART0_RX_PIN = GPIO1\n\tUART_TX_PIN  = UART0_TX_PIN\n\tUART_RX_PIN  = UART0_RX_PIN\n)\n\nvar DefaultUART = UART0\n"
  },
  {
    "path": "src/machine/board_badger2040.go",
    "content": "//go:build badger2040\n\n// This contains the pin mappings for the Badger 2040 board.\n//\n// For more information, see: https://shop.pimoroni.com/products/badger-2040\n// Also\n// - Badger 2040 schematic: https://cdn.shopify.com/s/files/1/0174/1800/files/badger_2040_schematic.pdf?v=1645702148\npackage machine\n\nconst (\n\tLED Pin = GPIO25\n\n\tBUTTON_A    Pin = GPIO12\n\tBUTTON_B    Pin = GPIO13\n\tBUTTON_C    Pin = GPIO14\n\tBUTTON_UP   Pin = GPIO15\n\tBUTTON_DOWN Pin = GPIO11\n\tBUTTON_USER Pin = GPIO23\n\n\tEPD_BUSY_PIN  Pin = GPIO26\n\tEPD_RESET_PIN Pin = GPIO21\n\tEPD_DC_PIN    Pin = GPIO20\n\tEPD_CS_PIN    Pin = GPIO17\n\tEPD_SCK_PIN   Pin = GPIO18\n\tEPD_SDO_PIN   Pin = GPIO19\n\n\tVBUS_DETECT Pin = GPIO24\n\tVREF_POWER  Pin = GPIO27\n\tVREF_1V24   Pin = GPIO28\n\tVBAT_SENSE  Pin = GPIO29\n\tENABLE_3V3  Pin = GPIO10\n\n\tBATTERY = VBAT_SENSE\n)\n\n// I2C pins\nconst (\n\tI2C0_SDA_PIN Pin = GPIO4\n\tI2C0_SCL_PIN Pin = GPIO5\n\n\tI2C1_SDA_PIN Pin = NoPin\n\tI2C1_SCL_PIN Pin = NoPin\n)\n\n// SPI pins.\nconst (\n\tSPI0_SCK_PIN Pin = GPIO18\n\tSPI0_SDO_PIN Pin = GPIO19\n\tSPI0_SDI_PIN Pin = GPIO16\n\n\tSPI1_SCK_PIN Pin = NoPin\n\tSPI1_SDO_PIN Pin = NoPin\n\tSPI1_SDI_PIN Pin = NoPin\n)\n\n// QSPI pins¿?\nconst (\n/*\n\tTODO\n\nSPI0_SD0_PIN Pin = QSPI_SD0\nSPI0_SD1_PIN Pin = QSPI_SD1\nSPI0_SD2_PIN Pin = QSPI_SD2\nSPI0_SD3_PIN Pin = QSPI_SD3\nSPI0_SCK_PIN Pin = QSPI_SCLKGPIO6\nSPI0_CS_PIN  Pin = QSPI_CS\n*/\n)\n\n// Onboard crystal oscillator frequency, in MHz.\nconst (\n\txoscFreq = 12 // MHz\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Badger 2040\"\n\tusb_STRING_MANUFACTURER = \"Pimoroni\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2e8a\n\tusb_PID uint16 = 0x0003\n)\n\n// UART pins\nconst (\n\tUART0_TX_PIN = GPIO0\n\tUART0_RX_PIN = GPIO1\n\tUART_TX_PIN  = UART0_TX_PIN\n\tUART_RX_PIN  = UART0_RX_PIN\n)\n\nvar DefaultUART = UART0\n"
  },
  {
    "path": "src/machine/board_bluemicro840.go",
    "content": "//go:build bluemicro840\n\npackage machine\n\nconst HasLowFrequencyCrystal = true\n\n// GPIO Pins\nconst (\n\tD006 = P0_06\n\tD008 = P0_08\n\tD015 = P0_15\n\tD017 = P0_17\n\tD020 = P0_20\n\tD013 = P0_13\n\tD024 = P0_24\n\tD009 = P0_09\n\tD010 = P0_10\n\tD106 = P1_06\n\n\tD031 = P0_31 // AIN7; P0.31 (AIN7) is used to read the voltage of the battery via ADC. It can’t be used for any other function.\n\tD012 = P0_12 // VCC 3.3V; P0.12 on VCC shuts off the power to VCC when you set it to high; This saves on battery immensely for LEDs of all kinds that eat power even when off\n\n\tD030 = P0_30\n\tD026 = P0_26\n\tD029 = P0_29\n\tD002 = P0_02\n\tD113 = P1_13\n\tD003 = P0_03\n\tD028 = P0_28\n\tD111 = P1_11\n)\n\n// Analog Pins\nconst (\n\tAIN0 = P0_02\n\tAIN1 = P0_03\n\tAIN2 = P0_04 // Not Connected\n\tAIN3 = P0_05 // Not Connected\n\tAIN4 = P0_28\n\tAIN5 = P0_29\n\tAIN6 = P0_30\n\tAIN7 = P0_31 // Battery\n)\n\nconst (\n\tLED1 Pin = P1_04 // Red LED\n\tLED2 Pin = P1_10 // Blue LED\n\tLED  Pin = LED1\n)\n\n// UART0 pins (logical UART1) - Maps to same location as Pro Micro\nconst (\n\tUART_RX_PIN = P0_08\n\tUART_TX_PIN = P0_06\n)\n\n// I2C pins\nconst (\n\tSDA_PIN = P0_15 // I2C0 external\n\tSCL_PIN = P0_17 // I2C0 external\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = P1_13 // SCK\n\tSPI0_SDI_PIN = P0_03 // SDI\n\tSPI0_SDO_PIN = P0_28 // SDO\n\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"bluemicro840\"\n\tusb_STRING_MANUFACTURER = \"BlueMicro\"\n)\n\nvar (\n\tusb_VID uint16 = 0x1d50\n\tusb_PID uint16 = 0x6161\n)\n"
  },
  {
    "path": "src/machine/board_bluepill.go",
    "content": "//go:build bluepill\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/interrupt\"\n)\n\n// Pins printed on the silkscreen\nconst (\n\tC13 = PC13\n\tC14 = PC14\n\tC15 = PC15\n\tA0  = PA0\n\tA1  = PA1\n\tA2  = PA2\n\tA3  = PA3\n\tA4  = PA4\n\tA5  = PA5\n\tA6  = PA6\n\tA7  = PA7\n\tB0  = PB0\n\tB1  = PB1\n\tB10 = PB10\n\tB11 = PB11\n\tB12 = PB12\n\tB13 = PB13\n\tB14 = PB14\n\tB15 = PB15\n\tA8  = PA8\n\tA9  = PA9\n\tA10 = PA10\n\tA11 = PA11\n\tA12 = PA12\n\tA13 = PA13\n\tA14 = PA14\n\tA15 = PA15\n\tB3  = PB3\n\tB4  = PB4\n\tB5  = PB5\n\tB6  = PB6\n\tB7  = PB7\n\tB8  = PB8\n\tB9  = PB9\n)\n\n// Analog Pins\nconst (\n\tADC0 = PA0\n\tADC1 = PA1\n\tADC2 = PA2\n\tADC3 = PA3\n\tADC4 = PA4\n\tADC5 = PA5\n\tADC6 = PA6\n\tADC7 = PA7\n\tADC8 = PB0\n\tADC9 = PB1\n)\n\nconst (\n\t// This board does not have a user button, so\n\t// use first GPIO pin by default\n\tBUTTON = PA0\n\n\tLED = PC13\n)\n\nvar DefaultUART = UART1\n\n// UART pins\nconst (\n\tUART_TX_PIN     = PA9\n\tUART_RX_PIN     = PA10\n\tUART_ALT_TX_PIN = PB6\n\tUART_ALT_RX_PIN = PB7\n)\n\nvar (\n\t// USART1 is the first hardware serial port on the STM32.\n\tUART1  = &_UART1\n\t_UART1 = UART{\n\t\tBuffer: NewRingBuffer(),\n\t\tBus:    stm32.USART1,\n\t}\n\tUART2  = &_UART2\n\t_UART2 = UART{\n\t\tBuffer: NewRingBuffer(),\n\t\tBus:    stm32.USART2,\n\t}\n)\n\nfunc init() {\n\tUART1.Interrupt = interrupt.New(stm32.IRQ_USART1, _UART1.handleInterrupt)\n\tUART2.Interrupt = interrupt.New(stm32.IRQ_USART2, _UART2.handleInterrupt)\n}\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = PA5\n\tSPI0_SDO_PIN = PA7\n\tSPI0_SDI_PIN = PA6\n)\n\n// I2C pins\nconst (\n\tI2C0_SDA_PIN = PB7\n\tI2C0_SCL_PIN = PB6\n)\n"
  },
  {
    "path": "src/machine/board_btt_skr_pico.go",
    "content": "//go:build btt_skr_pico\n\n// This contains the pin mappings for the BigTreeTech SKR Pico.\n//\n// Purchase link: https://biqu.equipment/products/btt-skr-pico-v1-0\n// Board schematic: https://github.com/bigtreetech/SKR-Pico/blob/master/Hardware/BTT%20SKR%20Pico%20V1.0-SCH.pdf\n// Pin diagram: https://github.com/bigtreetech/SKR-Pico/blob/master/Hardware/BTT%20SKR%20Pico%20V1.0-PIN.pdf\n\npackage machine\n\n// TMC stepper driver motor direction.\n// X/Y/Z/E refers to motors for X/Y/Z and the extruder.\nconst (\n\tX_DIR = GPIO10\n\tY_DIR = GPIO5\n\tZ_DIR = GPIO28\n\tE_DIR = GPIO13\n)\n\n// TMC stepper driver motor step\nconst (\n\tX_STEP = GPIO11\n\tY_STEP = GPIO6\n\tZ_STEP = GPIO19\n\tE_STEP = GPIO14\n)\n\n// TMC stepper driver enable\nconst (\n\tX_ENABLE = GPIO12\n\tY_ENABLE = GPIO7\n\tZ_ENABLE = GPIO2\n\tE_ENABLE = GPIO15\n)\n\n// TMC stepper driver UART\nconst (\n\tTMC_UART_TX = UART1_TX_PIN\n\tTMC_UART_RX = UART1_RX_PIN\n)\n\n// Endstops\nconst (\n\tX_ENDSTOP = GPIO4\n\tY_ENDSTOP = GPIO3\n\tZ_ENDSTOP = GPIO25\n\tE_ENDSTOP = GPIO16\n)\n\n// Fan PWM\nconst (\n\tFAN1_PWM = GPIO17\n\tFAN2_PWM = GPIO18\n\tFAN3_PWM = GPIO20\n)\n\n// Heater PWM\nconst (\n\tHEATER_BED_PWM      = GPIO21\n\tHEATER_EXTRUDER_PWM = GPIO23\n)\n\n// Thermistors\nconst (\n\tTHERM_BED      = GPIO26 // Bed heater\n\tTHERM_EXTRUDER = GPIO27 // Toolhead heater\n)\n\n// Misc\nconst (\n\tRGB   = GPIO24 // Neopixel\n\tSERVO = GPIO29 // Servo\n\tPROBE = GPIO22 // Probe\n)\n\n// Onboard crystal oscillator frequency, in MHz.\nconst (\n\txoscFreq = 12 // MHz\n)\n\n// I2C. We don't have this available\nconst (\n\tI2C0_SDA_PIN = NoPin\n\tI2C0_SCL_PIN = NoPin\n\n\tI2C1_SDA_PIN = NoPin\n\tI2C1_SCL_PIN = NoPin\n)\n\n// SPI. We don't have this available\nconst (\n\tSPI0_SCK_PIN = NoPin\n\tSPI0_SDO_PIN = NoPin\n\tSPI0_SDI_PIN = NoPin\n\tSPI1_SCK_PIN = NoPin\n\tSPI1_SDO_PIN = NoPin\n\tSPI1_SDI_PIN = NoPin\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"SKR Pico\"\n\tusb_STRING_MANUFACTURER = \"BigTreeTech\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2e8a\n\tusb_PID uint16 = 0x0003\n)\n\n// UART pins\nconst (\n\tUART0_TX_PIN = GPIO0\n\tUART0_RX_PIN = GPIO1\n\tUART1_TX_PIN = GPIO8\n\tUART1_RX_PIN = GPIO9\n\tUART_TX_PIN  = UART0_TX_PIN\n\tUART_RX_PIN  = UART0_RX_PIN\n)\n\nvar DefaultUART = UART0\n"
  },
  {
    "path": "src/machine/board_challenger_rp2040.go",
    "content": "//go:build challenger_rp2040\n\npackage machine\n\nconst (\n\tLED = GPIO24\n\n\t// Onboard crystal oscillator frequency, in MHz.\n\txoscFreq = 12 // MHz\n)\n\n// GPIO Pins\nconst (\n\tD5  = GPIO2\n\tD6  = GPIO3\n\tD9  = GPIO4\n\tD10 = GPIO5\n\tD11 = GPIO6\n\tD12 = GPIO7\n\tD13 = GPIO8\n)\n\n// Analog pins\nconst (\n\tA0 = ADC0\n\tA1 = ADC1\n\tA2 = ADC2\n\tA3 = ADC3\n)\n\n// I2C Pins.\nconst (\n\tI2C0_SDA_PIN = GPIO24\n\tI2C0_SCL_PIN = GPIO25\n\n\tI2C1_SDA_PIN = GPIO2\n\tI2C1_SCL_PIN = GPIO3\n\n\tSDA_PIN = I2C1_SDA_PIN\n\tSCL_PIN = I2C1_SCL_PIN\n)\n\n// SPI default pins\nconst (\n\t// Default Serial Clock Bus 0 for SPI communications\n\tSPI0_SCK_PIN = GPIO22\n\t// Default Serial Out Bus 0 for SPI communications\n\tSPI0_SDO_PIN = GPIO23 // Tx\n\t// Default Serial In Bus 0 for SPI communications\n\tSPI0_SDI_PIN = GPIO20 // Rx\n\n\t// Default Serial Clock Bus 1 for SPI communications\n\tSPI1_SCK_PIN = GPIO10\n\t// Default Serial Out Bus 1 for SPI communications\n\tSPI1_SDO_PIN = GPIO11 // Tx\n\t// Default Serial In Bus 1 for SPI communications\n\tSPI1_SDI_PIN = GPIO12 // Rx\n)\n\n// LoRa default pins\nconst (\n\tLORA_CS    = GPIO9\n\tLORA_SCK   = GPIO10\n\tLORA_SDO   = GPIO11\n\tLORA_SDI   = GPIO12\n\tLORA_RESET = GPIO13\n\tLORA_DIO0  = GPIO14\n\tLORA_DIO1  = GPIO15\n\tLORA_DIO2  = GPIO18\n)\n\n// UART pins\nconst (\n\tUART0_TX_PIN = GPIO16\n\tUART0_RX_PIN = GPIO17\n\tUART1_TX_PIN = GPIO4\n\tUART1_RX_PIN = GPIO5\n\tUART_TX_PIN  = UART0_TX_PIN\n\tUART_RX_PIN  = UART0_RX_PIN\n)\n\nvar DefaultUART = UART0\n\n// USB identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Challenger 2040 LoRa\"\n\tusb_STRING_MANUFACTURER = \"iLabs\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2e8a\n\tusb_PID uint16 = 0x1023\n)\n"
  },
  {
    "path": "src/machine/board_circuitplay_bluefruit.go",
    "content": "//go:build circuitplay_bluefruit\n\npackage machine\n\nconst HasLowFrequencyCrystal = false\n\n// GPIO Pins\nconst (\n\tD0  = P0_30\n\tD1  = P0_14\n\tD2  = P0_05\n\tD3  = P0_04\n\tD4  = P1_02\n\tD5  = P1_15\n\tD6  = P0_02\n\tD7  = P1_06\n\tD8  = P0_13\n\tD9  = P0_29\n\tD10 = P0_03\n\tD11 = P1_04\n\tD12 = P0_26\n\tD13 = P1_14\n)\n\n// Analog Pins\nconst (\n\tA1 = P0_02\n\tA2 = P0_29\n\tA3 = P0_03\n\tA4 = P0_04\n\tA5 = P0_05\n\tA6 = P0_30\n\tA7 = P0_14\n\tA8 = P0_28\n\tA9 = P0_31\n)\n\nconst (\n\tLED       = D13\n\tNEOPIXELS = D8\n\tWS2812    = D8\n\n\tBUTTONA = D4\n\tBUTTONB = D5\n\tSLIDER  = D7 // built-in slide switch\n\n\tBUTTON  = BUTTONA\n\tBUTTON1 = BUTTONB\n\n\tLIGHTSENSOR = A8\n\tTEMPSENSOR  = A9\n)\n\n// UART0 pins (logical UART1)\nconst (\n\tUART_TX_PIN = P0_14 // PORTB\n\tUART_RX_PIN = P0_30 // PORTB\n)\n\n// I2C pins\nconst (\n\tSDA_PIN = P0_05 // I2C0 external\n\tSCL_PIN = P0_04 // I2C0 external\n\n\tSDA1_PIN = P1_10 // I2C1 internal\n\tSCL1_PIN = P1_12 // I2C1 internal\n)\n\n// SPI pins (internal flash)\nconst (\n\tSPI0_SCK_PIN = P0_19 // SCK\n\tSPI0_SDO_PIN = P0_21 // SDO\n\tSPI0_SDI_PIN = P0_23 // SDI\n)\n\n// PDM pins\nconst (\n\tPDM_CLK_PIN = P0_17 // CLK\n\tPDM_DIN_PIN = P0_16 // DIN\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Adafruit Circuit Playground Bluefruit\"\n\tusb_STRING_MANUFACTURER = \"Adafruit\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x8045\n)\n\nvar (\n\tDefaultUART = UART0\n)\n"
  },
  {
    "path": "src/machine/board_circuitplay_express.go",
    "content": "//go:build circuitplay_express\n\npackage machine\n\n// used to reset into bootloader\nconst resetMagicValue = 0xf01669ef\n\n// GPIO Pins\nconst (\n\tD0  = PB09\n\tD1  = PB08\n\tD2  = PB02\n\tD3  = PB03\n\tD4  = PA28\n\tD5  = PA14\n\tD6  = PA05\n\tD7  = PA15\n\tD8  = PB23\n\tD9  = PA06\n\tD10 = PA07\n\tD11 = NoPin // does not seem to exist\n\tD12 = PA02\n\tD13 = PA17 // PWM available\n)\n\n// Analog Pins\nconst (\n\tA0  = PA02 // ADC/AIN[0]\n\tA1  = PA05 // PWM available, also ADC/AIN[5]\n\tA2  = PA06 // PWM available, also ADC/AIN[6]\n\tA3  = PA07 // PWM available, also ADC/AIN[7]\n\tA4  = PB03 // PORTB\n\tA5  = PB02 // PORTB\n\tA6  = PB09 // PORTB\n\tA7  = PB08 // PORTB\n\tA8  = PA11 // ADC/AIN[19]\n\tA9  = PA09 // ADC/AIN[17]\n\tA10 = PA04\n)\n\nconst (\n\tLED       = D13\n\tNEOPIXELS = D8\n\tWS2812    = D8\n\n\tBUTTONA = D4\n\tBUTTONB = D5\n\tSLIDER  = D7 // built-in slide switch\n\n\tBUTTON  = BUTTONA\n\tBUTTON1 = BUTTONB\n\n\tLIGHTSENSOR = A8\n\tTEMPSENSOR  = A9\n\tPROXIMITY   = A10\n)\n\n// USBCDC pins (logical UART0)\nconst (\n\tUSBCDC_DM_PIN = PA24\n\tUSBCDC_DP_PIN = PA25\n)\n\n// UART0 pins (logical UART1)\nconst (\n\tUART_TX_PIN = PB08 // PORTB\n\tUART_RX_PIN = PB09 // PORTB\n)\n\n// UART1 on the Circuit Playground Express.\nvar (\n\tUART1 = &sercomUSART4\n\n\tDefaultUART = UART1\n)\n\n// I2C pins\nconst (\n\tSDA_PIN = PB02 // I2C0 external\n\tSCL_PIN = PB03 // I2C0 external\n\n\tSDA1_PIN = PA00 // I2C1 internal\n\tSCL1_PIN = PA01 // I2C1 internal\n)\n\n// I2C on the Circuit Playground Express.\nvar (\n\tI2C0 = sercomI2CM5 // external device\n\tI2C1 = sercomI2CM1 // internal device\n)\n\n// SPI pins (internal flash)\nconst (\n\tSPI0_SCK_PIN = PA21 // SCK: SERCOM3/PAD[3]\n\tSPI0_SDO_PIN = PA20 // SDO: SERCOM3/PAD[2]\n\tSPI0_SDI_PIN = PA16 // SDI: SERCOM3/PAD[0]\n)\n\n// SPI on the Circuit Playground Express.\nvar SPI0 = sercomSPIM3\n\n// I2S pins\nconst (\n\tI2S_SCK_PIN = PA10\n\tI2S_SDO_PIN = PA08\n\tI2S_SDI_PIN = NoPin\n\tI2S_WS_PIN  = NoPin // no WS, instead uses SCK to sync\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Adafruit Circuit Playground Express\"\n\tusb_STRING_MANUFACTURER = \"Adafruit\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x8018\n)\n"
  },
  {
    "path": "src/machine/board_clue_alpha.go",
    "content": "//go:build clue_alpha\n\npackage machine\n\nconst HasLowFrequencyCrystal = false\n\n// GPIO Pins\nconst (\n\tD0  = P0_04\n\tD1  = P0_05\n\tD2  = P0_03\n\tD3  = P0_28\n\tD4  = P0_02\n\tD5  = P1_02\n\tD6  = P1_09\n\tD7  = P0_07\n\tD8  = P1_07\n\tD9  = P0_27\n\tD10 = P0_30\n\tD11 = P1_10\n\tD12 = P0_31\n\tD13 = P0_08\n\tD14 = P0_06\n\tD15 = P0_26\n\tD16 = P0_29\n\tD17 = P1_01\n\tD18 = P0_16\n\tD19 = P0_25\n\tD20 = P0_24\n\tD29 = P0_14\n\tD30 = P0_15\n\tD31 = P0_12\n\tD32 = P0_13\n\tD33 = P1_03\n\tD34 = P1_05\n\tD35 = P0_00\n\tD36 = P0_01\n\tD37 = P0_19\n\tD38 = P0_20\n\tD39 = P0_17\n\tD40 = P0_22\n\tD41 = P0_23\n\tD42 = P0_21\n\tD43 = P0_10\n\tD44 = P0_09\n\tD45 = P1_06\n\tD46 = P1_00\n)\n\n// Analog Pins\nconst (\n\tA0 = D12\n\tA1 = D16\n\tA2 = D0\n\tA3 = D1\n\tA4 = D2\n\tA5 = D3\n\tA6 = D4\n\tA7 = D10\n)\n\nconst (\n\tLED      = D17\n\tLED1     = LED\n\tLED2     = D43\n\tNEOPIXEL = D18\n\tWS2812   = D18\n\n\tBUTTON_LEFT  = D5\n\tBUTTON_RIGHT = D11\n\n\t// 240x240 ST7789 display is connected to these pins (use RowOffset = 80)\n\tTFT_SCK   = D29\n\tTFT_SDO   = D30\n\tTFT_CS    = D31\n\tTFT_DC    = D32\n\tTFT_RESET = D33\n\tTFT_LITE  = D34\n\n\tPDM_DAT = D35\n\tPDM_CLK = D36\n\n\tQSPI_SCK   = D37\n\tQSPI_CS    = D38\n\tQSPI_DATA0 = D39\n\tQSPI_DATA1 = D40\n\tQSPI_DATA2 = D41\n\tQSPI_DATA3 = D42\n\n\tSPEAKER = D46\n)\n\n// UART0 pins (logical UART1)\nconst (\n\tUART_RX_PIN = D0\n\tUART_TX_PIN = D1\n)\n\n// I2C pins\nconst (\n\tSDA_PIN = D20 // I2C0 external\n\tSCL_PIN = D19 // I2C0 external\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = D13 // SCK\n\tSPI0_SDO_PIN = D15 // SDO\n\tSPI0_SDI_PIN = D14 // SDI\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Adafruit CLUE\"\n\tusb_STRING_MANUFACTURER = \"Adafruit\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x8072\n)\n\nvar (\n\tDefaultUART = UART0\n)\n"
  },
  {
    "path": "src/machine/board_digispark.go",
    "content": "//go:build digispark\n\npackage machine\n\n// Return the current CPU frequency in hertz.\nfunc CPUFrequency() uint32 {\n\treturn 16000000\n}\n\nconst (\n\tP0 Pin = PB0\n\tP1 Pin = PB1\n\tP2 Pin = PB2\n\tP3 Pin = PB3\n\tP4 Pin = PB4\n\tP5 Pin = PB5\n\n\tLED = P1\n)\n"
  },
  {
    "path": "src/machine/board_elecrow-rp2040-w5.go",
    "content": "//go:build elecrow_rp2040\n\n// This file contains the pin mappings for the Elecrow Pico rp2040 W5 boards.\n//\n// Elecrow Pico rp2040 W5 is a microcontroller using the Raspberry Pi RP2040\n// chip and rtl8720d Wifi chip.\n//\n// - https://www.elecrow.com/wiki/PICO_W5_RP2040_Dev_Board.html\npackage machine\n\n// GPIO pins\nconst (\n\tGP0  Pin = GPIO0\n\tGP1  Pin = GPIO1\n\tGP2  Pin = GPIO2\n\tGP3  Pin = GPIO3\n\tGP4  Pin = GPIO4\n\tGP5  Pin = GPIO5\n\tGP6  Pin = GPIO6\n\tGP7  Pin = GPIO7\n\tGP8  Pin = GPIO8\n\tGP9  Pin = GPIO9\n\tGP10 Pin = GPIO10\n\tGP11 Pin = GPIO11\n\tGP12 Pin = GPIO12\n\tGP13 Pin = GPIO13\n\tGP14 Pin = GPIO14\n\tGP15 Pin = GPIO15\n\tGP16 Pin = GPIO16\n\tGP17 Pin = GPIO17\n\tGP18 Pin = GPIO18\n\tGP19 Pin = GPIO19\n\tGP20 Pin = GPIO20\n\tGP21 Pin = GPIO21\n\tGP22 Pin = GPIO22\n\tGP26 Pin = GPIO26\n\tGP27 Pin = GPIO27\n\tGP28 Pin = GPIO28\n\n\t// Onboard LED\n\tLED Pin = GPIO25\n\n\t// Onboard crystal oscillator frequency, in MHz.\n\txoscFreq = 12 // MHz\n)\n\n// I2C Default pins on Raspberry Pico.\nconst (\n\tI2C0_SDA_PIN = GP4\n\tI2C0_SCL_PIN = GP5\n\n\tI2C1_SDA_PIN = GP2\n\tI2C1_SCL_PIN = GP3\n)\n\n// SPI default pins\nconst (\n\t// Default Serial Clock Bus 0 for SPI communications\n\tSPI0_SCK_PIN = GPIO18\n\t// Default Serial Out Bus 0 for SPI communications\n\tSPI0_SDO_PIN = GPIO19 // Tx\n\t// Default Serial In Bus 0 for SPI communications\n\tSPI0_SDI_PIN = GPIO16 // Rx\n\n\t// Default Serial Clock Bus 1 for SPI communications\n\tSPI1_SCK_PIN = GPIO10\n\t// Default Serial Out Bus 1 for SPI communications\n\tSPI1_SDO_PIN = GPIO11 // Tx\n\t// Default Serial In Bus 1 for SPI communications\n\tSPI1_SDI_PIN = GPIO12 // Rx\n)\n\n// UART pins\nconst (\n\tUART0_TX_PIN = GPIO0\n\tUART0_RX_PIN = GPIO1\n\tUART1_TX_PIN = GPIO4 // Wired to rtl8720d UART1_Tx\n\tUART1_RX_PIN = GPIO5 // Wired to rtl8720n UART1_Rx\n\tUART_TX_PIN  = UART0_TX_PIN\n\tUART_RX_PIN  = UART0_RX_PIN\n)\n\nvar DefaultUART = UART0\n\n// USB identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Pico\"\n\tusb_STRING_MANUFACTURER = \"Raspberry Pi\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2E8A\n\tusb_PID uint16 = 0x000A\n)\n"
  },
  {
    "path": "src/machine/board_elecrow-rp2350-w5.go",
    "content": "//go:build elecrow_rp2350\n\n// This file contains the pin mappings for the Elecrow Pico rp2350 W5 boards.\n//\n// Elecrow Pico rp2350 W5 is a microcontroller using the Raspberry Pi RP2350\n// chip and rtl8720d Wifi chip.\n//\n// - https://www.elecrow.com/pico-w5-microcontroller-development-boards-rp2350-microcontroller-board.html\npackage machine\n\n// GPIO pins\nconst (\n\tGP0  Pin = GPIO0\n\tGP1  Pin = GPIO1\n\tGP2  Pin = GPIO2\n\tGP3  Pin = GPIO3\n\tGP4  Pin = GPIO4\n\tGP5  Pin = GPIO5\n\tGP6  Pin = GPIO6\n\tGP7  Pin = GPIO7\n\tGP8  Pin = GPIO8\n\tGP9  Pin = GPIO9\n\tGP10 Pin = GPIO10\n\tGP11 Pin = GPIO11\n\tGP12 Pin = GPIO12\n\tGP13 Pin = GPIO13\n\tGP14 Pin = GPIO14\n\tGP15 Pin = GPIO15\n\tGP16 Pin = GPIO16\n\tGP17 Pin = GPIO17\n\tGP18 Pin = GPIO18\n\tGP19 Pin = GPIO19\n\tGP20 Pin = GPIO20\n\tGP21 Pin = GPIO21\n\tGP22 Pin = GPIO22\n\tGP26 Pin = GPIO26\n\tGP27 Pin = GPIO27\n\tGP28 Pin = GPIO28\n\n\t// Onboard LED\n\tLED Pin = GPIO25\n\n\t// Onboard crystal oscillator frequency, in MHz.\n\txoscFreq = 12 // MHz\n)\n\n// I2C Default pins on Raspberry Pico.\nconst (\n\tI2C0_SDA_PIN = GP4\n\tI2C0_SCL_PIN = GP5\n\n\tI2C1_SDA_PIN = GP2\n\tI2C1_SCL_PIN = GP3\n)\n\n// SPI default pins\nconst (\n\t// Default Serial Clock Bus 0 for SPI communications\n\tSPI0_SCK_PIN = GPIO18\n\t// Default Serial Out Bus 0 for SPI communications\n\tSPI0_SDO_PIN = GPIO19 // Tx\n\t// Default Serial In Bus 0 for SPI communications\n\tSPI0_SDI_PIN = GPIO16 // Rx\n\n\t// Default Serial Clock Bus 1 for SPI communications\n\tSPI1_SCK_PIN = GPIO10\n\t// Default Serial Out Bus 1 for SPI communications\n\tSPI1_SDO_PIN = GPIO11 // Tx\n\t// Default Serial In Bus 1 for SPI communications\n\tSPI1_SDI_PIN = GPIO12 // Rx\n)\n\n// UART pins\nconst (\n\tUART0_TX_PIN = GPIO0\n\tUART0_RX_PIN = GPIO1\n\tUART1_TX_PIN = GPIO4 // Wired to rtl8720d UART1_Tx\n\tUART1_RX_PIN = GPIO5 // Wired to rtl8720n UART1_Rx\n\tUART_TX_PIN  = UART0_TX_PIN\n\tUART_RX_PIN  = UART0_RX_PIN\n)\n\nvar DefaultUART = UART0\n\n// USB identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Pico2\"\n\tusb_STRING_MANUFACTURER = \"Raspberry Pi\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2E8A\n\tusb_PID uint16 = 0x000F\n)\n"
  },
  {
    "path": "src/machine/board_esp-c3-32s-kit.go",
    "content": "//go:build esp_c3_32s_kit\n\npackage machine\n\n// See:\n//  * https://www.waveshare.com/w/upload/8/8f/Esp32-c3s_specification.pdf\n//  * https://www.waveshare.com/w/upload/4/46/Nodemcu-esp-c3-32s-kit-schematics.pdf\n\n// Digital Pins\nconst (\n\tIO0  = GPIO0\n\tIO1  = GPIO1\n\tIO2  = GPIO2\n\tIO3  = GPIO3\n\tIO4  = GPIO4\n\tIO5  = GPIO5\n\tIO6  = GPIO6\n\tIO7  = GPIO7\n\tIO8  = GPIO8\n\tIO9  = GPIO9\n\tIO18 = GPIO18\n\tIO19 = GPIO19\n)\n\nconst (\n\tLED_RED   = IO3\n\tLED_GREEN = IO4\n\tLED_BLUE  = IO5\n\n\tLED = LED_RED\n\n\tLED1 = LED_RED\n\tLED2 = LED_GREEN\n)\n\n// I2C pins\nconst (\n\tSDA_PIN = NoPin\n\tSCL_PIN = NoPin\n)\n"
  },
  {
    "path": "src/machine/board_esp32-c3-devkit-rust-1.go",
    "content": "//go:build esp32_c3_devkit_rust_1\n\n// This file contains the pin mappings for the Espressif ESP32-C3 Development Board for Rust.\n//\n// The Espressif ESP32-C3-DevKit-RUST-1 development board is powered\n// by the Espressif ESP32-C3 SoC featuring an open-source RISC-V architecture.\n//\n// Specifications:\n//   SoC: ESP32-C3-MINI-1, 4MB Flash, RISCV-32bit, 160MHz, 400KB SRAM\n//   Wireless: WiFi & Bluetooth 5.0 (BLE)\n//   ICM-42670-P 6-Axis IMU  (I2C Addr 0x68)\n//   SHTC3 Humidity and Temperature Sensor (I2C Addr 0x70)\n//   WS2812B LED\n\n// GitHub:    https://github.com/esp-rs/esp-rust-board\n// Schematic: https://github.com/esp-rs/esp-rust-board/blob/master/hardware/esp-rust-board/schematic/esp-rust-board.pdf\n// Datasheet: https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf\n\npackage machine\n\n// Digital pins\nconst (\n\t//    Pin    // Function\n\t//    -----  // ---------------\n\tD0  = GPIO0  //\n\tD1  = GPIO1  //\n\tD2  = GPIO2  // WS2812\n\tD3  = GPIO3  //\n\tD4  = GPIO4  // MTMS\n\tD5  = GPIO5  // MTDI\n\tD6  = GPIO6  // MTCK\n\tD7  = GPIO7  // Red LED / MTDO\n\tD8  = GPIO8  // I2C SCL\n\tD9  = GPIO9  // Boot Button\n\tD10 = GPIO10 // I2C SDA\n\tD18 = GPIO18 // USB DM\n\tD19 = GPIO19 // USB DP\n\tD20 = GPIO20 // UART RX\n\tD21 = GPIO21 // UART TX\n)\n\n// Analog pins\nconst (\n\tA0 = GPIO0\n\tA1 = GPIO1\n\tA2 = GPIO2\n\tA3 = GPIO3\n\tA4 = GPIO4\n\tA5 = GPIO5\n)\n\n// Button pin\nconst (\n\tBUTTON      = BUTTON_BOOT\n\tBUTTON_BOOT = D9\n)\n\n// LED pins\nconst (\n\tLED         = LED_BUILTIN\n\tWS2812      = D2\n\tLED_BUILTIN = D7\n)\n\n// I2C pins\nconst (\n\tSCL_PIN = D8\n\tSDA_PIN = D10\n)\n\n// USBCDC pins\nconst (\n\tUSBCDC_DM_PIN = D18\n\tUSBCDC_DP_PIN = D19\n)\n\n// UART pins\nconst (\n\tUART_RX_PIN = D20\n\tUART_TX_PIN = D21\n)\n"
  },
  {
    "path": "src/machine/board_esp32-coreboard-v2.go",
    "content": "//go:build esp32_coreboard_v2\n\npackage machine\n\nconst (\n\tCLK  = GPIO6\n\tCMD  = GPIO11\n\tIO0  = GPIO0\n\tIO1  = GPIO1\n\tIO2  = GPIO2\n\tIO3  = GPIO3\n\tIO4  = GPIO4\n\tIO5  = GPIO5\n\tIO9  = GPIO9\n\tIO10 = GPIO10\n\tIO16 = GPIO16\n\tIO17 = GPIO17\n\tIO18 = GPIO18\n\tIO19 = GPIO19\n\tIO21 = GPIO21\n\tIO22 = GPIO22\n\tIO23 = GPIO23\n\tIO25 = GPIO25\n\tIO26 = GPIO26\n\tIO27 = GPIO27\n\tIO32 = GPIO32\n\tIO33 = GPIO33\n\tIO34 = GPIO34\n\tIO35 = GPIO35\n\tIO36 = GPIO36\n\tIO39 = GPIO39\n\tRXD  = GPIO3\n\tSD0  = GPIO7\n\tSD1  = GPIO8\n\tSD2  = GPIO9\n\tSD3  = GPIO10\n\tSVN  = GPIO39\n\tSVP  = GPIO36\n\tTCK  = GPIO13\n\tTD0  = GPIO15\n\tTDI  = GPIO12\n\tTMS  = GPIO14\n\tTXD  = GPIO1\n)\n\n// Built-in LED on some ESP32 boards.\nconst LED = IO2\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = IO18\n\tSPI0_SDO_PIN = IO23\n\tSPI0_SDI_PIN = IO19\n\tSPI0_CS0_PIN = IO5\n)\n\n// I2C pins\nconst (\n\tSDA_PIN = IO21\n\tSCL_PIN = IO22\n)\n\n// ADC pins\nconst (\n\tADC0 Pin = IO34\n\tADC1 Pin = IO35\n\tADC2 Pin = IO36\n\tADC3 Pin = IO39\n)\n\n// UART0 pins\nconst (\n\tUART_TX_PIN = IO1\n\tUART_RX_PIN = IO3\n)\n\n// UART1 pins\nconst (\n\tUART1_TX_PIN = IO9\n\tUART1_RX_PIN = IO10\n)\n\n// PWM pins\nconst (\n\tPWM0_PIN Pin = IO2\n\tPWM1_PIN Pin = IO0\n\tPWM2_PIN Pin = IO4\n)\n"
  },
  {
    "path": "src/machine/board_esp32c3-12f.go",
    "content": "//go:build esp32c312f\n\npackage machine\n\n// Built-in RGB LED\nconst (\n\tLED_RED   = IO3\n\tLED_GREEN = IO4\n\tLED_BLUE  = IO5\n\tLED       = LED_RED\n)\n\nconst (\n\tIO0  = GPIO0\n\tIO1  = GPIO1\n\tIO2  = GPIO2\n\tIO3  = GPIO3\n\tIO4  = GPIO4\n\tIO5  = GPIO5\n\tIO6  = GPIO6\n\tIO7  = GPIO7\n\tIO8  = GPIO8\n\tIO9  = GPIO9\n\tIO10 = GPIO10\n\tIO18 = GPIO18\n\tIO19 = GPIO19\n\tRXD  = GPIO20\n\tTXD  = GPIO21\n)\n\n// ADC pins\nconst (\n\tADC0 Pin = ADC1_0\n\tADC1 Pin = ADC2_0\n\n\tADC1_0 Pin = IO0\n\tADC1_1 Pin = IO1\n\tADC1_2 Pin = IO2\n\tADC1_3 Pin = IO3\n\tADC1_4 Pin = IO4\n\tADC2_0 Pin = IO5\n)\n\n// UART0 pins\nconst (\n\tUART_TX_PIN = TXD\n\tUART_RX_PIN = RXD\n)\n\n// I2C pins\nconst (\n\tSCL_PIN = NoPin\n\tSDA_PIN = NoPin\n)\n"
  },
  {
    "path": "src/machine/board_esp32c3-supermini.go",
    "content": "//go:build esp32c3_supermini\n\n// This file contains the pin mappings for the ESP32 supermini boards.\n//\n// - https://web.archive.org/web/20240805232453/https://dl.artronshop.co.th/ESP32-C3%20SuperMini%20datasheet.pdf\n\npackage machine\n\n// Digital Pins\nconst (\n\tIO0  = GPIO0\n\tIO1  = GPIO1\n\tIO2  = GPIO2\n\tIO3  = GPIO3\n\tIO4  = GPIO4\n\tIO5  = GPIO5\n\tIO6  = GPIO6\n\tIO7  = GPIO7\n\tIO8  = GPIO8\n\tIO9  = GPIO9\n\tIO10 = GPIO10\n\tIO20 = GPIO20\n\tIO21 = GPIO21\n)\n\n// Built-in LED\nconst LED = GPIO8\n\n// Analog pins\nconst (\n\tA0 = GPIO0\n\tA1 = GPIO1\n\tA2 = GPIO2\n\tA3 = GPIO3\n\tA4 = GPIO4\n\tA5 = GPIO5\n)\n\n// UART pins\nconst (\n\tUART_RX_PIN = GPIO20\n\tUART_TX_PIN = GPIO21\n)\n\n// I2C pins\nconst (\n\tSDA_PIN = GPIO8\n\tSCL_PIN = GPIO9\n)\n\n// SPI pins\nconst (\n\tSPI_MISO_PIN = GPIO5\n\tSPI_MOSI_PIN = GPIO6\n\tSPI_SS_PIN   = GPIO7\n\tSPI_SCK_PIN  = GPIO4\n)\n"
  },
  {
    "path": "src/machine/board_fe310.go",
    "content": "//go:build hifive1b\n\npackage machine\n\nconst (\n\tP00 Pin = 0\n\tP01 Pin = 1\n\tP02 Pin = 2\n\tP03 Pin = 3\n\tP04 Pin = 4\n\tP05 Pin = 5\n\tP06 Pin = 6\n\tP07 Pin = 7\n\tP08 Pin = 8\n\tP09 Pin = 9\n\tP10 Pin = 10\n\tP11 Pin = 11\n\tP12 Pin = 12 // peripherals: I2C0 SDA\n\tP13 Pin = 13 // peripherals: I2C0 SCL\n\tP14 Pin = 14\n\tP15 Pin = 15\n\tP16 Pin = 16\n\tP17 Pin = 17\n\tP18 Pin = 18\n\tP19 Pin = 19\n\tP20 Pin = 20\n\tP21 Pin = 21\n\tP22 Pin = 22\n\tP23 Pin = 23\n\tP24 Pin = 24\n\tP25 Pin = 25\n\tP26 Pin = 26\n\tP27 Pin = 27\n\tP28 Pin = 28\n\tP29 Pin = 29\n\tP30 Pin = 30\n\tP31 Pin = 31\n)\n"
  },
  {
    "path": "src/machine/board_feather-m0-express.go",
    "content": "//go:build sam && atsamd21 && feather_m0_express\n\npackage machine\n\n// used to reset into bootloader\nconst resetMagicValue = 0xf01669ef\n\n// GPIO Pins\nconst (\n\tD0  = PA11  // UART0 RX\n\tD1  = PA10  // UART0 TX\n\tD2  = NoPin // does not seem to exist\n\tD3  = NoPin // does not seem to exist\n\tD4  = NoPin // does not seem to exist\n\tD5  = PA15\n\tD6  = PA20\n\tD7  = NoPin // does not seem to exist\n\tD8  = PA06  // NEOPIXEL\n\tD9  = PA07\n\tD10 = PA18\n\tD11 = PA16\n\tD12 = PA19\n\tD13 = PA17\n)\n\n// Analog pins\nconst (\n\tA0 = PA02 // ADC/AIN[0]\n\tA1 = PB08 // ADC/AIN[2]\n\tA2 = PB09 // ADC/AIN[3]\n\tA3 = PA04 // ADC/AIN[4]\n\tA4 = PA05 // ADC/AIN[5]\n\tA5 = PB02 // ADC/AIN[10]\n)\n\nconst (\n\tLED      = D13\n\tNEOPIXEL = D8\n)\n\n// USBCDC pins\nconst (\n\tUSBCDC_DM_PIN = PA24\n\tUSBCDC_DP_PIN = PA25\n)\n\n// UART1 pins\nconst (\n\tUART_TX_PIN = D1\n\tUART_RX_PIN = D0\n\n\tUART1_TX_PIN = D10\n\tUART1_RX_PIN = D12\n)\n\n// UART0 on the Feather M0 Express.\nvar UART0 = &sercomUSART0\nvar UART1 = &sercomUSART1\n\n// I2C pins\nconst (\n\tSDA_PIN = PA22 // SDA: SERCOM3/PAD[0]\n\tSCL_PIN = PA23 // SCL: SERCOM3/PAD[1]\n)\n\n// I2C on the Feather M0 Express.\nvar (\n\tI2C0 = sercomI2CM3\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = PB11 // SCK: SERCOM4/PAD[3]\n\tSPI0_SDO_PIN = PB10 // SDO: SERCOM4/PAD[2]\n\tSPI0_SDI_PIN = PA12 // SDI: SERCOM4/PAD[0]\n)\n\n// SPI on the Feather M0.\nvar SPI0 = sercomSPIM4\n\n// I2S pins\nconst (\n\tI2S_SCK_PIN = PA10\n\tI2S_SDO_PIN = PA07\n\tI2S_SDI_PIN = NoPin\n\tI2S_WS_PIN  = NoPin // TODO: figure out what this is on Feather M0 Express.\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Adafruit Feather M0 Express\"\n\tusb_STRING_MANUFACTURER = \"Adafruit\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x801B\n)\n\nvar (\n\tDefaultUART = UART0\n)\n"
  },
  {
    "path": "src/machine/board_feather-m0.go",
    "content": "//go:build sam && atsamd21 && feather_m0\n\npackage machine\n\n// used to reset into bootloader\nconst resetMagicValue = 0xf01669ef\n\n// GPIO Pins\nconst (\n\tD0  = PA11  // UART0 RX\n\tD1  = PA10  // UART0 TX\n\tD2  = NoPin // does not seem to exist\n\tD3  = PA09\n\tD4  = PA08\n\tD5  = PA15  // PWM available\n\tD6  = PA20  // PWM available\n\tD7  = NoPin // does not seem to exist\n\tD8  = PA06\n\tD9  = PA07 // PWM available\n\tD10 = PA18 // can be used for PWM or UART1 TX\n\tD11 = PA16 // can be used for PWM or UART1 RX\n\tD12 = PA19 // PWM available\n\tD13 = PA17 // PWM available\n)\n\n// Analog pins\nconst (\n\tA0 = PA02 // ADC/AIN[0]\n\tA1 = PB08 // ADC/AIN[2]\n\tA2 = PB09 // ADC/AIN[3]\n\tA3 = PA04 // ADC/AIN[4]\n\tA4 = PA05 // ADC/AIN[5]\n\tA5 = PB02 // ADC/AIN[10]\n)\n\nconst (\n\tLED = D13\n)\n\n// USBCDC pins\nconst (\n\tUSBCDC_DM_PIN = PA24\n\tUSBCDC_DP_PIN = PA25\n)\n\n// UART1 pins\nconst (\n\tUART_TX_PIN = D10\n\tUART_RX_PIN = D11\n)\n\n// UART1 on the Feather M0.\nvar UART1 = &sercomUSART1\n\n// I2C pins\nconst (\n\tSDA_PIN = PA22 // SDA: SERCOM3/PAD[0]\n\tSCL_PIN = PA23 // SCL: SERCOM3/PAD[1]\n)\n\n// I2C on the Feather M0.\nvar (\n\tI2C0 = sercomI2CM3\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = PB11 // SCK: SERCOM4/PAD[3]\n\tSPI0_SDO_PIN = PB10 // SDO: SERCOM4/PAD[2]\n\tSPI0_SDI_PIN = PA12 // SDI: SERCOM4/PAD[0]\n)\n\n// SPI on the Feather M0.\nvar SPI0 = sercomSPIM4\n\n// I2S pins\nconst (\n\tI2S_SCK_PIN = PA10\n\tI2S_SDO_PIN = PA08\n\tI2S_SDI_PIN = NoPin\n\tI2S_WS_PIN  = NoPin // TODO: figure out what this is on Feather M0.\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Adafruit Feather M0 Express\"\n\tusb_STRING_MANUFACTURER = \"Adafruit\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x801B\n)\n\nvar (\n\tDefaultUART = UART1\n)\n"
  },
  {
    "path": "src/machine/board_feather-m4-can.go",
    "content": "//go:build feather_m4_can\n\npackage machine\n\nimport (\n\t\"device/sam\"\n)\n\n// used to reset into bootloader\nconst resetMagicValue = 0xf01669ef\n\n// GPIO Pins\nconst (\n\tD0  = PB17 // UART0 RX/PWM available\n\tD1  = PB16 // UART0 TX/PWM available\n\tD4  = PA14 // PWM available\n\tD5  = PA16 // PWM available\n\tD6  = PA18 // PWM available\n\tD7  = PB03 // neopixel power\n\tD8  = PB02 // built-in neopixel\n\tD9  = PA19 // PWM available\n\tD10 = PA20 // can be used for PWM or UART1 TX\n\tD11 = PA21 // can be used for PWM or UART1 RX\n\tD12 = PA22 // PWM available\n\tD13 = PA23 // PWM available\n\tD21 = PA13 // PWM available\n\tD22 = PA12 // PWM available\n\tD23 = PB22 // PWM available\n\tD24 = PB23 // PWM available\n\tD25 = PA17 // PWM available\n)\n\n// Analog pins\nconst (\n\tA0 = PA02 // ADC/AIN[0]\n\tA1 = PA05 // ADC/AIN[2]\n\tA2 = PB08 // ADC/AIN[3]\n\tA3 = PB09 // ADC/AIN[4]\n\tA4 = PA04 // ADC/AIN[5]\n\tA5 = PA06 // ADC/AIN[10]\n)\n\nconst (\n\tLED       = D13\n\tNEOPIXELS = D8\n\tWS2812    = D8\n)\n\n// USBCDC pins\nconst (\n\tUSBCDC_DM_PIN = PA24\n\tUSBCDC_DP_PIN = PA25\n)\n\nconst (\n\tUART_TX_PIN = D1\n\tUART_RX_PIN = D0\n)\n\nconst (\n\tUART2_TX_PIN = A4\n\tUART2_RX_PIN = A5\n)\n\n// I2C pins\nconst (\n\tSDA_PIN = D22 // SDA: SERCOM2/PAD[0]\n\tSCL_PIN = D21 // SCL: SERCOM2/PAD[1]\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = D25 // SCK: SERCOM1/PAD[1]\n\tSPI0_SDO_PIN = D24 // SDO: SERCOM1/PAD[3]\n\tSPI0_SDI_PIN = D23 // SDI: SERCOM1/PAD[2]\n)\n\n// CAN pins\nconst (\n\tCAN0_TX = PA22\n\tCAN0_RX = PA23\n\n\tCAN1_STANDBY = PB12\n\tCAN1_TX      = PB14\n\tCAN1_RX      = PB15\n\tBOOST_EN     = PB13 // power control of CAN1's TCAN1051HGV (H: enable)\n\n\tCAN_STANDBY = CAN1_STANDBY\n\tCAN_S       = CAN1_STANDBY\n\tCAN_TX      = CAN1_TX\n\tCAN_RX      = CAN1_RX\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Adafruit Feather M4 CAN\"\n\tusb_STRING_MANUFACTURER = \"Adafruit\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x80CD\n)\n\nvar (\n\tUART1 = &sercomUSART5\n\n\tUART2 = &sercomUSART0\n)\n\nfunc init() {\n\t// turn on neopixel\n\tD7.Configure(PinConfig{Mode: PinOutput})\n\tD7.High()\n}\n\n// I2C on the Feather M4 CAN.\nvar (\n\tI2C0 = sercomI2CM2\n)\n\n// SPI on the Feather M4 CAN.\nvar SPI0 = sercomSPIM1\n\n// CAN on the Feather M4 CAN.\nvar (\n\tCAN0 = CAN{\n\t\tBus: sam.CAN0,\n\t}\n\n\tCAN1 = CAN{\n\t\tBus: sam.CAN1,\n\t}\n)\n\nvar (\n\tDefaultUART = UART1\n)\n"
  },
  {
    "path": "src/machine/board_feather-m4.go",
    "content": "//go:build feather_m4\n\npackage machine\n\n// used to reset into bootloader\nconst resetMagicValue = 0xf01669ef\n\n// GPIO Pins\nconst (\n\tD0  = PB17 // UART0 RX/PWM available\n\tD1  = PB16 // UART0 TX/PWM available\n\tD4  = PA14 // PWM available\n\tD5  = PA16 // PWM available\n\tD6  = PA18 // PWM available\n\tD8  = PB03 // built-in neopixel\n\tD9  = PA19 // PWM available\n\tD10 = PA20 // can be used for PWM or UART1 TX\n\tD11 = PA21 // can be used for PWM or UART1 RX\n\tD12 = PA22 // PWM available\n\tD13 = PA23 // PWM available\n\tD21 = PA13 // PWM available\n\tD22 = PA12 // PWM available\n\tD23 = PB22 // PWM available\n\tD24 = PB23 // PWM available\n\tD25 = PA17 // PWM available\n)\n\n// Analog pins\nconst (\n\tA0 = PA02 // ADC/AIN[0]\n\tA1 = PA05 // ADC/AIN[2]\n\tA2 = PB08 // ADC/AIN[3]\n\tA3 = PB09 // ADC/AIN[4]\n\tA4 = PA04 // ADC/AIN[5]\n\tA5 = PA06 // ADC/AIN[10]\n)\n\nconst (\n\tLED    = D13\n\tWS2812 = D8\n)\n\n// USBCDC pins\nconst (\n\tUSBCDC_DM_PIN = PA24\n\tUSBCDC_DP_PIN = PA25\n)\n\nconst (\n\tUART_TX_PIN = D1\n\tUART_RX_PIN = D0\n)\n\nconst (\n\tUART2_TX_PIN = A4\n\tUART2_RX_PIN = A5\n)\n\nvar (\n\tUART1 = &sercomUSART5\n\tUART2 = &sercomUSART0\n\n\tDefaultUART = UART1\n)\n\n// I2C pins\nconst (\n\tSDA_PIN = D22 // SDA: SERCOM2/PAD[0]\n\tSCL_PIN = D21 // SCL: SERCOM2/PAD[1]\n)\n\n// I2C on the Feather M4.\nvar (\n\tI2C0 = sercomI2CM2\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = D25 // SCK: SERCOM1/PAD[1]\n\tSPI0_SDO_PIN = D24 // SDO: SERCOM1/PAD[3]\n\tSPI0_SDI_PIN = D23 // SDI: SERCOM1/PAD[2]\n)\n\n// SPI on the Feather M4.\nvar SPI0 = sercomSPIM1\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Adafruit Feather M4\"\n\tusb_STRING_MANUFACTURER = \"Adafruit\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x8022\n)\n"
  },
  {
    "path": "src/machine/board_feather-nrf52840-sense.go",
    "content": "//go:build feather_nrf52840_sense\n\npackage machine\n\nconst HasLowFrequencyCrystal = false\n\n// GPIO Pins\nconst (\n\tD0  = P0_25 // UART TX\n\tD1  = P0_24 // UART RX\n\tD2  = P0_10 // NFC2\n\tD3  = P1_11\n\tD4  = P1_10 // LED2\n\tD5  = P1_08\n\tD6  = P0_07\n\tD7  = P1_02 // Button\n\tD8  = P0_16 // NeoPixel\n\tD9  = P0_26\n\tD10 = P0_27\n\tD11 = P0_06\n\tD12 = P0_08\n\tD13 = P1_09 // LED1\n\tD14 = P0_04 // A0\n\tD15 = P0_05 // A1\n\tD16 = P0_30 // A2\n\tD17 = P0_28 // A3\n\tD18 = P0_02 // A4\n\tD19 = P0_03 // A5\n\tD20 = P0_29 // Battery\n\tD21 = P0_31 // AREF\n\tD22 = P0_12 // I2C SDA\n\tD23 = P0_11 // I2C SCL\n\tD24 = P0_15 // SPI MISO\n\tD25 = P0_13 // SPI MOSI\n\tD26 = P0_14 // SPI SCK\n\tD27 = P0_19 // QSPI CLK\n\tD28 = P0_20 // QSPI CS\n\tD29 = P0_17 // QSPI Data 0\n\tD30 = P0_22 // QSPI Data 1\n\tD31 = P0_23 // QSPI Data 2\n\tD32 = P0_21 // QSPI Data 3\n\tD33 = P0_09 // NFC1 (test point on bottom of board)\n)\n\n// Analog Pins\nconst (\n\tA0 = D14\n\tA1 = D15\n\tA2 = D16\n\tA3 = D17\n\tA4 = D18\n\tA5 = D19\n\tA6 = D20 // Battery\n\tA7 = D21 // ARef\n)\n\nconst (\n\tLED      = D13\n\tLED1     = LED\n\tLED2     = D4\n\tNEOPIXEL = D8\n\tWS2812   = D8\n\tBUTTON   = D7\n\n\tQSPI_SCK   = D27\n\tQSPI_CS    = D28\n\tQSPI_DATA0 = D29\n\tQSPI_DATA1 = D30\n\tQSPI_DATA2 = D31\n\tQSPI_DATA3 = D32\n)\n\n// UART0 pins (logical UART1)\nconst (\n\tUART_RX_PIN = D1\n\tUART_TX_PIN = D0\n)\n\n// I2C pins\nconst (\n\tSDA_PIN = D22 // I2C0 external\n\tSCL_PIN = D23 // I2C0 external\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = D26 // SCK\n\tSPI0_SDO_PIN = D25 // SDO\n\tSPI0_SDI_PIN = D24 // SDI\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Feather nRF52840 Express\"\n\tusb_STRING_MANUFACTURER = \"Adafruit Industries LLC\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x8088\n)\n\nvar (\n\tDefaultUART = UART0\n)\n"
  },
  {
    "path": "src/machine/board_feather-nrf52840.go",
    "content": "//go:build feather_nrf52840\n\npackage machine\n\nconst HasLowFrequencyCrystal = true\n\n// GPIO Pins\nconst (\n\tD0  = P0_25 // UART TX\n\tD1  = P0_24 // UART RX\n\tD2  = P0_10 // NFC2\n\tD3  = P1_15 // LED1\n\tD4  = P1_10 // LED2\n\tD5  = P1_08\n\tD6  = P0_07\n\tD7  = P1_02 // Button\n\tD8  = P0_16 // NeoPixel\n\tD9  = P0_26\n\tD10 = P0_27\n\tD11 = P0_06\n\tD12 = P0_08\n\tD13 = P1_09\n\tD14 = P0_04 // A0\n\tD15 = P0_05 // A1\n\tD16 = P0_30 // A2\n\tD17 = P0_28 // A3\n\tD18 = P0_02 // A4\n\tD19 = P0_03 // A5\n\tD20 = P0_29 // Battery\n\tD21 = P0_31 // AREF\n\tD22 = P0_12 // I2C SDA\n\tD23 = P0_11 // I2C SCL\n\tD24 = P0_15 // SPI MISO\n\tD25 = P0_13 // SPI MOSI\n\tD26 = P0_14 // SPI SCK\n\tD27 = P0_19 // QSPI CLK\n\tD28 = P0_20 // QSPI CS\n\tD29 = P0_17 // QSPI Data 0\n\tD30 = P0_22 // QSPI Data 1\n\tD31 = P0_23 // QSPI Data 2\n\tD32 = P0_21 // QSPI Data 3\n\tD33 = P0_09 // NFC1 (test point on bottom of board)\n)\n\n// Analog Pins\nconst (\n\tA0 = D14\n\tA1 = D15\n\tA2 = D16\n\tA3 = D17\n\tA4 = D18\n\tA5 = D19\n\tA6 = D20 // Battery\n\tA7 = D21 // ARef\n)\n\nconst (\n\tLED      = D3\n\tLED1     = LED\n\tLED2     = D4\n\tNEOPIXEL = D8\n\tWS2812   = D8\n\tBUTTON   = D7\n\n\tQSPI_SCK   = D27\n\tQSPI_CS    = D28\n\tQSPI_DATA0 = D29\n\tQSPI_DATA1 = D30\n\tQSPI_DATA2 = D31\n\tQSPI_DATA3 = D32\n)\n\n// UART0 pins (logical UART1)\nconst (\n\tUART_RX_PIN = D1\n\tUART_TX_PIN = D0\n)\n\n// I2C pins\nconst (\n\tSDA_PIN = D22 // I2C0 external\n\tSCL_PIN = D23 // I2C0 external\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = D26 // SCK\n\tSPI0_SDO_PIN = D25 // SDO\n\tSPI0_SDI_PIN = D24 // SDI\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Feather nRF52840 Express\"\n\tusb_STRING_MANUFACTURER = \"Adafruit Industries LLC\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x802A\n)\n\nvar (\n\tDefaultUART = UART0\n)\n"
  },
  {
    "path": "src/machine/board_feather-stm32f405.go",
    "content": "//go:build feather_stm32f405\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/interrupt\"\n)\n\nconst (\n\tNUM_DIGITAL_IO_PINS = 39\n\tNUM_ANALOG_IO_PINS  = 7\n)\n\n// Digital pins\nconst (\n\t// Arduino pin = MCU port pin // primary functions (alternate functions)\n\tD0  = PB11 // USART3 RX, PWM TIM2_CH4 (I2C2 SDA)\n\tD1  = PB10 // USART3 TX, PWM TIM2_CH3 (I2C2 SCL, I2S2 BCK)\n\tD2  = PB3  // GPIO, SPI3 FLASH SCK\n\tD3  = PB4  // GPIO, SPI3 FLASH MISO\n\tD4  = PB5  // GPIO, SPI3 FLASH MOSI\n\tD5  = PC7  // GPIO, PWM TIM3_CH2 (USART6 RX, I2S3 MCK)\n\tD6  = PC6  // GPIO, PWM TIM3_CH1 (USART6 TX, I2S2 MCK)\n\tD7  = PA15 // GPIO, SPI3 FLASH CS\n\tD8  = PC0  // GPIO, Neopixel\n\tD9  = PB8  // GPIO, PWM TIM4_CH3 (CAN1 RX, I2C1 SCL)\n\tD10 = PB9  // GPIO, PWM TIM4_CH4 (CAN1 TX, I2C1 SDA, I2S2 WSL)\n\tD11 = PC3  // GPIO (I2S2 SD, SPI2 MOSI)\n\tD12 = PC2  // GPIO (I2S2ext SD, SPI2 MISO)\n\tD13 = PC1  // GPIO, Builtin LED\n\tD14 = PB7  // I2C1 SDA, PWM TIM4_CH2 (USART1 RX)\n\tD15 = PB6  // I2C1 SCL, PWM TIM4_CH1 (USART1 TX, CAN2 TX)\n\tD16 = PA4  // A0 (DAC OUT1)\n\tD17 = PA5  // A1 (DAC OUT2, SPI1 SCK)\n\tD18 = PA6  // A2, PWM TIM3_CH1 (SPI1 MISO)\n\tD19 = PA7  // A3, PWM TIM3_CH2 (SPI1 MOSI)\n\tD20 = PC4  // A4\n\tD21 = PC5  // A5\n\tD22 = PA3  // A6\n\tD23 = PB13 // SPI2 SCK, PWM TIM1_CH1N (I2S2 BCK, CAN2 TX)\n\tD24 = PB14 // SPI2 MISO, PWM TIM1_CH2N (I2S2ext SD)\n\tD25 = PB15 // SPI2 MOSI, PWM TIM1_CH3N (I2S2 SD)\n\tD26 = PC8  // SDIO\n\tD27 = PC9  // SDIO\n\tD28 = PC10 // SDIO\n\tD29 = PC11 // SDIO\n\tD30 = PC12 // SDIO\n\tD31 = PD2  // SDIO\n\tD32 = PB12 // SD Detect\n\tD33 = PC14 // OSC32\n\tD34 = PC15 // OSC32\n\tD35 = PA11 // USB D+\n\tD36 = PA12 // USB D-\n\tD37 = PA13 // SWDIO\n\tD38 = PA14 // SWCLK\n)\n\n// Analog pins\nconst (\n\tA0 = D16 // ADC12 IN4\n\tA1 = D17 // ADC12 IN5\n\tA2 = D18 // ADC12 IN6\n\tA3 = D19 // ADC12 IN7\n\tA4 = D20 // ADC12 IN14\n\tA5 = D21 // ADC12 IN15\n\tA6 = D22 // VBAT\n)\n\nfunc init() {\n\tinitLED()\n\tinitUART()\n\tinitSPI()\n\tinitI2C()\n}\n\n// -- LEDs ---------------------------------------------------------------------\n\nconst (\n\tNUM_BOARD_LED      = 1\n\tNUM_BOARD_NEOPIXEL = 1\n\n\tLED_RED      = D13\n\tLED_NEOPIXEL = D8\n\tLED_BUILTIN  = LED_RED\n\tLED          = LED_BUILTIN\n\tWS2812       = D8\n)\n\nfunc initLED() {}\n\n// -- UART ---------------------------------------------------------------------\n\nconst (\n\t// #===========#==========#==============#============#=======#=======#\n\t// | Interface | Hardware |  Bus(Freq)   | RX/TX Pins | AltFn | Alias |\n\t// #===========#==========#==============#============#=======#=======#\n\t// |   UART1   |  USART3  | APB1(42 MHz) |   D0/D1    |   7   |   ~   |\n\t// |   UART2   |  USART6  | APB2(84 MHz) |   D5/D6    |   8   |   ~   |\n\t// |   UART3   |  USART1  | APB2(84 MHz) |  D14/D15   |   7   |   ~   |\n\t// | --------- | -------- | ------------ | ---------- | ----- | ----- |\n\t// |   UART0   |  USART3  | APB1(42 MHz) |   D0/D1    |   7   | UART1 |\n\t// #===========#==========#==============#============#=======#=======#\n\tNUM_UART_INTERFACES = 3\n\n\tUART1_RX_PIN = D0 // UART1 = hardware: USART3\n\tUART1_TX_PIN = D1 //\n\n\tUART2_RX_PIN = D5 // UART2 = hardware: USART6\n\tUART2_TX_PIN = D6 //\n\n\tUART3_RX_PIN = D14 // UART3 = hardware: USART1\n\tUART3_TX_PIN = D15 //\n\n\tUART0_RX_PIN = UART1_RX_PIN // UART0 = alias: UART1\n\tUART0_TX_PIN = UART1_TX_PIN //\n\n\tUART_RX_PIN = UART0_RX_PIN // default/primary UART pins\n\tUART_TX_PIN = UART0_TX_PIN //\n)\n\nvar (\n\tUART1  = &_UART1\n\t_UART1 = UART{\n\t\tBuffer:            NewRingBuffer(),\n\t\tBus:               stm32.USART3,\n\t\tTxAltFuncSelector: AF7_USART1_2_3,\n\t\tRxAltFuncSelector: AF7_USART1_2_3,\n\t}\n\tUART2  = &_UART2\n\t_UART2 = UART{\n\t\tBuffer:            NewRingBuffer(),\n\t\tBus:               stm32.USART6,\n\t\tTxAltFuncSelector: AF8_USART4_5_6,\n\t\tRxAltFuncSelector: AF8_USART4_5_6,\n\t}\n\tUART3  = &_UART3\n\t_UART3 = UART{\n\t\tBuffer:            NewRingBuffer(),\n\t\tBus:               stm32.USART1,\n\t\tTxAltFuncSelector: AF7_USART1_2_3,\n\t\tRxAltFuncSelector: AF7_USART1_2_3,\n\t}\n\tDefaultUART = UART1\n)\n\nfunc initUART() {\n\tUART1.Interrupt = interrupt.New(stm32.IRQ_USART3, _UART1.handleInterrupt)\n\tUART2.Interrupt = interrupt.New(stm32.IRQ_USART6, _UART2.handleInterrupt)\n\tUART3.Interrupt = interrupt.New(stm32.IRQ_USART1, _UART3.handleInterrupt)\n}\n\n// -- SPI ----------------------------------------------------------------------\n\nconst (\n\t// #===========#==========#==============#==================#=======#=======#\n\t// | Interface | Hardware |  Bus(Freq)   | SCK/SDI/SDO Pins | AltFn | Alias |\n\t// #===========#==========#==============#==================#=======#=======#\n\t// |   SPI1    |   SPI2   | APB1(42 MHz) |    D23/D24/D25   |   5   |   ~   |\n\t// |   SPI2    |   SPI3   | APB1(42 MHz) |     D2/D3/D4     |   6   |   ~   |\n\t// |   SPI3    |   SPI1   | APB2(84 MHz) |    D17/D18/D19   |   5   |   ~   |\n\t// | --------- | -------- | ------------ | ---------------- | ----- | ----- |\n\t// |   SPI0    |   SPI2   | APB1(42 MHz) |    D23/D24/D25   |   5   | SPI1  |\n\t// #===========#==========#==============#==================#=======#=======#\n\tNUM_SPI_INTERFACES = 3\n\n\tSPI1_SCK_PIN = D23 //\n\tSPI1_SDI_PIN = D24 // SPI1 = hardware: SPI2\n\tSPI1_SDO_PIN = D25 //\n\n\tSPI2_SCK_PIN = D2 //\n\tSPI2_SDI_PIN = D3 // SPI2 = hardware: SPI3\n\tSPI2_SDO_PIN = D4 //\n\n\tSPI3_SCK_PIN = D17 //\n\tSPI3_SDI_PIN = D18 // SPI3 = hardware: SPI1\n\tSPI3_SDO_PIN = D19 //\n\n\tSPI0_SCK_PIN = SPI1_SCK_PIN //\n\tSPI0_SDI_PIN = SPI1_SDI_PIN // SPI0 = alias: SPI1\n\tSPI0_SDO_PIN = SPI1_SDO_PIN //\n\n\tSPI_SCK_PIN = SPI0_SCK_PIN //\n\tSPI_SDI_PIN = SPI0_SDI_PIN // default/primary SPI pins\n\tSPI_SDO_PIN = SPI0_SDO_PIN //\n)\n\nvar (\n\tSPI1 = &SPI{\n\t\tBus:             stm32.SPI2,\n\t\tAltFuncSelector: AF5_SPI1_SPI2,\n\t}\n\tSPI2 = &SPI{\n\t\tBus:             stm32.SPI3,\n\t\tAltFuncSelector: AF6_SPI3,\n\t}\n\tSPI3 = &SPI{\n\t\tBus:             stm32.SPI1,\n\t\tAltFuncSelector: AF5_SPI1_SPI2,\n\t}\n\tSPI0 = SPI1\n)\n\nfunc initSPI() {}\n\n// -- I2C ----------------------------------------------------------------------\n\nconst (\n\t// #===========#==========#==============#==============#=======#=======#\n\t// | Interface | Hardware |  Bus(Freq)   | SDA/SCL Pins | AltFn | Alias |\n\t// #===========#==========#==============#==============#=======#=======#\n\t// |   I2C1    |   I2C1   | APB1(42 MHz) |   D14/D15    |   4   |   ~   |\n\t// |   I2C2    |   I2C2   | APB1(42 MHz) |    D0/D1     |   4   |   ~   |\n\t// |   I2C3    |   I2C1   | APB1(42 MHz) |    D9/D10    |   4   |   ~   |\n\t// | --------- | -------- | ------------ | ------------ | ----- | ----- |\n\t// |   I2C0    |   I2C1   | APB1(42 MHz) |   D14/D15    |   4   | I2C1  |\n\t// #===========#==========#==============#==============#=======#=======#\n\tNUM_I2C_INTERFACES = 3\n\n\tI2C1_SDA_PIN = D14 // I2C1 = hardware: I2C1\n\tI2C1_SCL_PIN = D15 //\n\n\tI2C2_SDA_PIN = D0 // I2C2 = hardware: I2C2\n\tI2C2_SCL_PIN = D1 //\n\n\tI2C3_SDA_PIN = D9  // I2C3 = hardware: I2C1\n\tI2C3_SCL_PIN = D10 //   (interface duplicated on second pair of pins)\n\n\tI2C0_SDA_PIN = I2C1_SDA_PIN // I2C0 = alias: I2C1\n\tI2C0_SCL_PIN = I2C1_SCL_PIN //\n\n\tI2C_SDA_PIN = I2C0_SDA_PIN // default/primary I2C pins\n\tI2C_SCL_PIN = I2C0_SCL_PIN //\n\n\tSDA_PIN = I2C0_SDA_PIN\n\tSCL_PIN = I2C0_SCL_PIN\n)\n\nvar (\n\tI2C1 = &I2C{\n\t\tBus:             stm32.I2C1,\n\t\tAltFuncSelector: AF4_I2C1_2_3,\n\t}\n\tI2C2 = &I2C{\n\t\tBus:             stm32.I2C2,\n\t\tAltFuncSelector: AF4_I2C1_2_3,\n\t}\n\tI2C3 = &I2C{\n\t\tBus:             stm32.I2C1,\n\t\tAltFuncSelector: AF4_I2C1_2_3,\n\t}\n\tI2C0 = I2C1\n)\n\nfunc initI2C() {}\n"
  },
  {
    "path": "src/machine/board_feather_rp2040.go",
    "content": "//go:build feather_rp2040\n\npackage machine\n\n// Onboard crystal oscillator frequency, in MHz.\nconst xoscFreq = 12 // MHz\n\n// GPIO Pins\nconst (\n\tD4  = GPIO6\n\tD5  = GPIO7\n\tD6  = GPIO8\n\tD9  = GPIO9\n\tD10 = GPIO10\n\tD11 = GPIO11\n\tD12 = GPIO12\n\tD13 = GPIO13\n\tD24 = GPIO24\n\tD25 = GPIO25\n)\n\n// Analog pins\nconst (\n\tA0 = GPIO26\n\tA1 = GPIO27\n\tA2 = GPIO28\n\tA3 = GPIO29\n)\n\nconst LED = GPIO13\n\n// I2C Pins.\nconst (\n\tI2C0_SDA_PIN = GPIO24\n\tI2C0_SCL_PIN = GPIO25\n\n\tI2C1_SDA_PIN = GPIO2\n\tI2C1_SCL_PIN = GPIO3\n\n\tSDA_PIN = I2C1_SDA_PIN\n\tSCL_PIN = I2C1_SCL_PIN\n)\n\n// SPI default pins\nconst (\n\t// Default Serial Clock Bus 0 for SPI communications\n\tSPI0_SCK_PIN = GPIO18\n\t// Default Serial Out Bus 0 for SPI communications\n\tSPI0_SDO_PIN = GPIO19 // Tx\n\t// Default Serial In Bus 0 for SPI communications\n\tSPI0_SDI_PIN = GPIO20 // Rx\n\n\t// Default Serial Clock Bus 1 for SPI communications\n\tSPI1_SCK_PIN = GPIO10\n\t// Default Serial Out Bus 1 for SPI communications\n\tSPI1_SDO_PIN = GPIO11 // Tx\n\t// Default Serial In Bus 1 for SPI communications\n\tSPI1_SDI_PIN = GPIO12 // Rx\n)\n\n// UART pins\nconst (\n\tUART0_TX_PIN = GPIO0\n\tUART0_RX_PIN = GPIO1\n\tUART1_TX_PIN = GPIO8\n\tUART1_RX_PIN = GPIO9\n\tUART_TX_PIN  = UART0_TX_PIN\n\tUART_RX_PIN  = UART0_RX_PIN\n)\n\nvar DefaultUART = UART0\n\n// USB identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Feather RP2040\"\n\tusb_STRING_MANUFACTURER = \"Adafruit\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x80F1\n)\n"
  },
  {
    "path": "src/machine/board_gemma-m0.go",
    "content": "//go:build sam && atsamd21 && gemma_m0\n\npackage machine\n\n// Used to reset into bootloader.\nconst resetMagicValue = 0xf01669ef\n\n// GPIO Pins.\nconst (\n\tD0  = PA04 // SERCOM0/PAD[0]\n\tD1  = PA02\n\tD2  = PA05 // SERCOM0/PAD[1]\n\tD3  = PA00 // DotStar LED: SERCOM1/PAD[0]: APA102/MOSI\n\tD4  = PA01 // DotStar LED: SERCOM1/PAD[1]: APA102/SCK\n\tD11 = PA30 // Flash Access: SERCOM1/PAD[2]\n\tD12 = PA31 // Flash Access: SERCOM1/PAD[3]\n\tD13 = PA23 // LED: SERCOM3/PAD[1] SERCOM5/PAD[1]\n)\n\n// Analog pins.\nconst (\n\tA0 = D1\n\tA1 = D2\n\tA2 = D0\n)\n\nconst (\n\tLED = PA23\n)\n\n// USBCDC pins.\nconst (\n\tUSBCDC_DM_PIN = PA24\n\tUSBCDC_DP_PIN = PA25\n)\n\n// UART0 pins.\nconst (\n\tUART_TX_PIN = PA04 // TX: SERCOM0/PAD[0]\n\tUART_RX_PIN = PA05 // RX: SERCOM0/PAD[1]\n)\n\n// UART0s on the Gemma M0.\nvar UART0 = &sercomUSART0\n\n// SPI pins.\nconst (\n\tSPI0_SCK_PIN = PA05 // SCK: SERCOM0/PAD[1]\n\tSPI0_SDO_PIN = PA04 // MOSI: SERCOM0/PAD[0]\n\tSPI0_SDI_PIN = NoPin\n\tSPI0_CS_PIN  = NoPin\n)\n\n// SPI on the Gemma M0.\nvar SPI0 = sercomSPIM0\n\n// SPI pins for DotStar LED (using APA102 software SPI) and Flash.\nconst (\n\tSPI1_SCK_PIN = PA01 // SCK: SERCOM1/PAD[0]\n\tSPI1_SDO_PIN = PA00 // MOSI: SERCOM1/PAD[1]\n\tSPI1_SDI_PIN = PA31 // MISO: SERCOM1/PAD[3]\n\tSPI1_CS_PIN  = PA30 // CS: SERCOM1/PAD[2]\n)\n\n// I2C pins.\nconst (\n\tSDA_PIN = PA04 // SDA: SERCOM0/PAD[0]\n\tSCL_PIN = PA05 // SCL: SERCOM0/PAD[1]\n)\n\n// I2C on the Gemma M0.\nvar (\n\tI2C0 = sercomI2CM0\n)\n\n// I2S (not connected, needed for atsamd21).\nconst (\n\tI2S_SCK_PIN = NoPin\n\tI2S_SDO_PIN = NoPin\n\tI2S_SDI_PIN = NoPin\n\tI2S_WS_PIN  = NoPin\n)\n\n// USB CDC identifiers.\nconst (\n\tusb_STRING_PRODUCT      = \"Adafruit Gemma M0\"\n\tusb_STRING_MANUFACTURER = \"Adafruit\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x801E\n)\n\nvar (\n\tDefaultUART = UART0\n)\n"
  },
  {
    "path": "src/machine/board_gnse.go",
    "content": "//go:build gnse\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/interrupt\"\n)\n\nconst (\n\tLED_RED   = PB5\n\tLED_GREEN = PB6\n\tLED_BLUE  = PB7\n\tLED1      = LED_RED   // Red\n\tLED2      = LED_GREEN // Green\n\tLED3      = LED_BLUE  // Blue\n\tLED       = LED_GREEN // Default\n\n\tBUTTON    = PB3\n\tBUZZER    = PA15\n\tVBATT_ADC = PB2\n\tSENSOR_EN = PB12\n\tFLASH_EN  = PC13\n\n\t// SPI0\n\tSPI0_NSS_PIN = PA4\n\tSPI0_SCK_PIN = PA5\n\tSPI0_SDO_PIN = PA6\n\tSPI0_SDI_PIN = PA7\n\n\t//MCU USART2\n\tUART2_RX_PIN = PA3\n\tUART2_TX_PIN = PA2\n\n\t// DEFAULT USART\n\tUART_RX_PIN = UART2_RX_PIN\n\tUART_TX_PIN = UART2_TX_PIN\n\n\t// I2C1 pins\n\t// I2C1 is connected to Flash, Accelerometer, Env. Sensor, Crypto Element)\n\tI2C1_SCL_PIN  = PA9\n\tI2C1_SDA_PIN  = PA10\n\tI2C1_ALT_FUNC = 4\n\n\t// I2C2 pins\n\t// I2C2 is expansion J10 QWIIC Connector\n\tI2C2_SCL_PIN  = PA12\n\tI2C2_SDA_PIN  = PA11\n\tI2C2_ALT_FUNC = 4\n\n\t// I2C0 alias for I2C1\n\tI2C0_SDA_PIN = I2C1_SDA_PIN\n\tI2C0_SCL_PIN = I2C1_SCL_PIN\n)\n\nvar (\n\t// STM32 UART2 is connected to the embedded STLINKV3 Virtual Com Port\n\tUART0  = &_UART0\n\t_UART0 = UART{\n\t\tBuffer:            NewRingBuffer(),\n\t\tBus:               stm32.USART2,\n\t\tTxAltFuncSelector: 7,\n\t\tRxAltFuncSelector: 7,\n\t}\n\n\tDefaultUART = UART0\n\n\t// I2C Busses\n\tI2C1 = &I2C{\n\t\tBus:             stm32.I2C1,\n\t\tAltFuncSelector: I2C1_ALT_FUNC,\n\t}\n\tI2C2 = &I2C{\n\t\tBus:             stm32.I2C2,\n\t\tAltFuncSelector: I2C2_ALT_FUNC,\n\t}\n\tI2C0 = I2C1\n\n\t// SPI\n\tSPI3 = &SPI{\n\t\tBus: stm32.SPI3,\n\t}\n)\n\nfunc init() {\n\t// Enable UARTs Interrupts\n\tUART0.Interrupt = interrupt.New(stm32.IRQ_USART2, _UART0.handleInterrupt)\n}\n"
  },
  {
    "path": "src/machine/board_gopher-arcade.go",
    "content": "//go:build gopher_arcade\n\npackage machine\n\n// Return the current CPU frequency in hertz.\nfunc CPUFrequency() uint32 {\n\treturn 8000000\n}\n\nconst (\n\tP5 Pin = PB0\n\tP6 Pin = PB1\n\tP7 Pin = PB2\n\tP2 Pin = PB3\n\tP3 Pin = PB4\n\tP1 Pin = PB5\n\n\tLED          = P1\n\tBUTTON_LEFT  = P7\n\tBUTTON_RIGHT = P5\n\tSPEAKER      = P6\n)\n"
  },
  {
    "path": "src/machine/board_gopher-badge.go",
    "content": "//go:build gopher_badge\n\n// This contains the pin mappings for the Gopher Badge.\n//\n// For more information, see: https://gopherbadge.com/\npackage machine\n\nconst (\n\t/*ADC0 Pin = GPIO26\n\tADC1 Pin = GPIO27\n\tADC2 Pin = GPIO28\n\tGPIO4 Pin = GPIO4\n\tGPIO5 Pin = GPIO5\n\tGPIO6 Pin = GPIO6\n\tGPIO7 Pin = GPIO7\n\tGPIO8 Pin = GPIO8\n\tGPIO9 Pin = GPIO9*/\n\n\tPENIRQ Pin = GPIO13\n\n\tLED       Pin = GPIO2\n\tNEOPIXELS Pin = GPIO15\n\tWS2812    Pin = GPIO15\n\n\tBUTTON_A     Pin = GPIO10\n\tBUTTON_B     Pin = GPIO11\n\tBUTTON_LEFT  Pin = GPIO25\n\tBUTTON_UP    Pin = GPIO24\n\tBUTTON_RIGHT Pin = GPIO22\n\tBUTTON_DOWN  Pin = GPIO23\n\n\tTFT_RST       Pin = GPIO21\n\tTFT_SDI       Pin = GPIO19\n\tTFT_SDO       Pin = GPIO16\n\tTFT_CS        Pin = GPIO17\n\tTFT_SCL       Pin = GPIO18\n\tTFT_WRX       Pin = GPIO20\n\tTFT_BACKLIGHT Pin = GPIO12\n\n\tSPEAKER        Pin = GPIO14\n\tSPEAKER_ENABLE Pin = GPIO3\n)\n\n// I2C pins\nconst (\n\tI2C0_SDA_PIN Pin = GPIO0\n\tI2C0_SCL_PIN Pin = GPIO1\n\n\tI2C1_SDA_PIN Pin = NoPin\n\tI2C1_SCL_PIN Pin = NoPin\n)\n\n// SPI pins.\nconst (\n\tSPI0_SCK_PIN Pin = GPIO18\n\tSPI0_SDO_PIN Pin = GPIO19\n\tSPI0_SDI_PIN Pin = GPIO16\n\n\tSPI1_SCK_PIN Pin = NoPin\n\tSPI1_SDO_PIN Pin = NoPin\n\tSPI1_SDI_PIN Pin = NoPin\n)\n\n// Onboard crystal oscillator frequency, in MHz.\nconst (\n\txoscFreq = 12 // MHz\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Gopher Badge\"\n\tusb_STRING_MANUFACTURER = \"TinyGo\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2e8a\n\tusb_PID uint16 = 0x0003\n)\n\n// UART pins\nconst (\n\tUART0_TX_PIN = GPIO0\n\tUART0_RX_PIN = GPIO1\n\tUART1_TX_PIN = GPIO4\n\tUART1_RX_PIN = GPIO5\n\tUART_TX_PIN  = UART0_TX_PIN\n\tUART_RX_PIN  = UART0_RX_PIN\n)\n\nvar DefaultUART = UART1\n"
  },
  {
    "path": "src/machine/board_grandcentral-m4.go",
    "content": "//go:build grandcentral_m4\n\npackage machine\n\n// Digital pins\nconst (\n\t//  = Pin     Alt. Function        SERCOM   PWM Timer   Interrupt\n\t//   ------  -------------------- -------- ----------- -----------\n\tD0  = PB25 // UART1 RX              0[1]                 EXTI9\n\tD1  = PB24 // UART1 TX              0[0]                 EXTI8\n\tD2  = PC18 //                                TCC0[2]     EXTI2\n\tD3  = PC19 //                                TCC0[3]     EXTI3\n\tD4  = PC20 //                                TCC0[4]     EXTI4\n\tD5  = PC21 //                                TCC0[5]     EXTI5\n\tD6  = PD20 //                                TCC1[0]     EXTI10\n\tD7  = PD21 //                                TCC1[1]     EXTI11\n\tD8  = PB18 //                                TCC1[0]     EXTI2\n\tD9  = PB02 //                                TC6[0]      EXTI3\n\tD10 = PB22 //                                TC7[0]      EXTI6\n\tD11 = PB23 //                                            EXTI7\n\tD12 = PB00 //                                TC7[0]      EXTI0\n\tD13 = PB01 // On-board LED                   TC7[1]      EXTI1\n\tD14 = PB16 // UART4 TX, I2S0 SCK    5[0]     TC6[0]      EXTI0\n\tD15 = PB17 // UART4 RX, I2S0 MCK    5[1]                 EXTI1\n\tD16 = PC22 // UART3 TX              1[0]                 EXTI6\n\tD17 = PC23 // UART3 RX              1[1]                 EXTI6\n\tD18 = PB12 // UART2 TX              4[0]     TCC3[0]     EXTI12\n\tD19 = PB13 // UART2 RX              4[1]     TCC3[1]     EXTI13\n\tD20 = PB20 // I2C0 SDA              3[0]                 EXTI4\n\tD21 = PB21 // I2C0 SCL              3[1]                 EXTI5\n\tD22 = PD12 //                                            EXTI7\n\tD23 = PA15 //                                TCC2[1]     EXTI15\n\tD24 = PC17 // I2C1 SCL              6[1]     TCC0[1]     EXTI1\n\tD25 = PC16 // I2C1 SDA              6[0]     TCC0[0]     EXTI0\n\tD26 = PA12 // PCC DEN1                       TC2[0]      EXTI12\n\tD27 = PA13 // PCC DEN2                       TC2[1]      EXTI13\n\tD28 = PA14 // PCC CLK                        TCC2[0]     EXTI14\n\tD29 = PB19 // PCC XCLK                                   EXTI3\n\tD30 = PA23 // PCC D7                         TC4[1]      EXTI7\n\tD31 = PA22 // PCC D6, I2S0 SDI               TC4[0]      EXTI6\n\tD32 = PA21 // PCC D5, I2S0 SDO                           EXTI5\n\tD33 = PA20 // PCC D4, I2S0 FS                            EXTI4\n\tD34 = PA19 // PCC D3                         TC3[1]      EXTI3\n\tD35 = PA18 // PCC D2                         TC3[0]      EXTI2\n\tD36 = PA17 // PCC D1                                     EXTI1\n\tD37 = PA16 // PCC D0                                     EXTI0\n\tD38 = PB15 // PCC D9                         TCC4[1]     EXTI15\n\tD39 = PB14 // PCC D8                         TCC4[0]     EXTI14\n\tD40 = PC13 // PCC D11                                    EXTI13\n\tD41 = PC12 // PCC D10                                    EXTI12\n\tD42 = PC15 // PCC D13                                    EXTI15\n\tD43 = PC14 // PCC D12                                    EXTI14\n\tD44 = PC11 //                                            EXTI11\n\tD45 = PC10 //                                            EXTI10\n\tD46 = PC06 //                                            EXTI6\n\tD47 = PC07 //                                            EXTI5\n\tD48 = PC04 //                                            EXTI4\n\tD49 = PC05 //                                            EXTI5\n\tD50 = PD11 // SPI0 SDI              7[3]                 EXTI11\n\tD51 = PD08 // SPI0 SDO              7[0]                 EXTI8\n\tD52 = PD09 // SPI0 SCK              7[1]                 EXTI9\n\tD53 = PD10 // SPI0 CS                                    EXTI10\n\tD54 = PB05 // ADC1 (A8)                                  EXTI5\n\tD55 = PB06 // ADC1 (A9)                                  EXTI6\n\tD56 = PB07 // ADC1 (A10)                                 EXTI7\n\tD57 = PB08 // ADC1 (A11)                                 EXTI8\n\tD58 = PB09 // ADC1 (A12)                                 EXTI9\n\tD59 = PA04 // ADC0 (A13)                     TC0[0]      EXTI4\n\tD60 = PA06 // ADC0 (A14)                     TC1[0]      EXTI6\n\tD61 = PA07 // ADC0 (A15)                     TC1[1]      EXTI7\n\tD62 = PB20 // I2C0 SDA              3[0]     TCC1[2]     EXTI4\n\tD63 = PB21 // I2C0 SCL              3[1]     TCC1[3]     EXTI5\n\tD64 = PD11 // SPI0 SDI              7[3]                 EXTI6\n\tD65 = PD08 // SPI0 SDO              7[0]                 EXTI3\n\tD66 = PD09 // SPI0 SCK              7[1]                 EXTI4\n\tD67 = PA02 // ADC0 (A0), DAC0                            EXTI2\n\tD68 = PA05 // ADC0 (A1), DAC1                            EXTI5\n\tD69 = PB03 // ADC0 (A2)                      TC6[1]      EXTI3\n\tD70 = PC00 // ADC1 (A3)                                  EXTI0\n\tD71 = PC01 // ADC1 (A4)                                  EXTI1\n\tD72 = PC02 // ADC1 (A5)                                  EXTI2\n\tD73 = PC03 // ADC1 (A6)                                  EXTI3\n\tD74 = PB04 // ADC1 (A7)                                  EXTI4\n\tD75 = PC31 // UART RX LED\n\tD76 = PC30 // UART TX LED\n\tD77 = PA27 // USB HOST EN\n\tD78 = PA24 // USB DM                                     EXTI8\n\tD79 = PA25 // USB DP                                     EXTI9\n\tD80 = PB29 // SD/SPI1 SDI           2[3]\n\tD81 = PB27 // SD/SPI1 SCK           2[1]\n\tD82 = PB26 // SD/SPI1 SDO           2[0]\n\tD83 = PB28 // SD/SPI1 CS\n\tD84 = PA03 // AREF                                       EXTI3\n\tD85 = PA02 // DAC0                                       EXTI2\n\tD86 = PA05 // DAC1                                       EXTI5\n\tD87 = PB01 // On-board LED (D13)             TC7[1]      EXTI1\n\tD88 = PC24 // On-board NeoPixel\n\tD89 = PB10 // QSPI SCK                                   EXTI10\n\tD90 = PB11 // QSPI CS                                    EXTI11\n\tD91 = PA08 // QSPI ID0                                   EXTI(NMI)\n\tD92 = PA09 // QSPI ID1                                   EXTI9\n\tD93 = PA10 // QSPI ID2                                   EXTI10\n\tD94 = PA11 // QSPI ID3                                   EXTI11\n\tD95 = PB31 // SD Detect                                  EXTI15\n\tD96 = PB30 // SWO                                        EXTI14\n)\n\n// Analog pins\nconst (\n\tA0  = D67 // (PA02) ADC0 ch. 0,\n\tA1  = D68 // (PA05) ADC0 ch. 5,\n\tA2  = D69 // (PB03) ADC0 ch. 15\n\tA3  = D70 // (PC00) ADC1 ch. 10\n\tA4  = D71 // (PC01) ADC1 ch. 11\n\tA5  = D72 // (PC02) ADC1 ch. 4\n\tA6  = D73 // (PC03) ADC1 ch. 5\n\tA7  = D74 // (PB04) ADC1 ch. 6\n\tA8  = D54 // (PB05) ADC1 ch. 7\n\tA9  = D55 // (PB06) ADC1 ch. 8\n\tA10 = D56 // (PB07) ADC1 ch. 9\n\tA11 = D57 // (PB08) ADC1 ch. 0\n\tA12 = D58 // (PB09) ADC1 ch. 1\n\tA13 = D59 // (PA04) ADC0 ch. 4\n\tA14 = D60 // (PA06) ADC0 ch. 6\n\tA15 = D61 // (PA07) ADC0 ch. 7\n\n\tAREF = D84 // (PA03)\n)\n\n// LED pins\nconst (\n\tLED_PIN         = D13 // (PB01), also on D87\n\tUART_RX_LED_PIN = D75 // (PC31)\n\tUART_TX_LED_PIN = D76 // (PC30)\n\tNEOPIXEL_PIN    = D88 // (PC24)\n\n\t// aliases used by examples and drivers\n\tLED      = LED_PIN\n\tLED_RX   = UART_RX_LED_PIN\n\tLED_TX   = UART_TX_LED_PIN\n\tNEOPIXEL = NEOPIXEL_PIN\n\tWS2812   = NEOPIXEL_PIN\n)\n\n// UART pins\nconst (\n\tUART1_RX_PIN = D0 // (PB25)\n\tUART1_TX_PIN = D1 // (PB24)\n\n\tUART2_RX_PIN = D19 // (PB13)\n\tUART2_TX_PIN = D18 // (PB12)\n\n\tUART3_RX_PIN = D17 // (PC23)\n\tUART3_TX_PIN = D16 // (PC22)\n\n\tUART4_RX_PIN = D15 // (PB17)\n\tUART4_TX_PIN = D14 // (PB16)\n\n\tUART_RX_PIN = UART1_RX_PIN // default pins\n\tUART_TX_PIN = UART1_TX_PIN //\n)\n\n// UART on the Grand Central M4\nvar (\n\tUART1 = &sercomUSART0\n\tUART2 = &sercomUSART4\n\tUART3 = &sercomUSART1\n\tUART4 = &sercomUSART5\n\n\tDefaultUART = UART1\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = D66 // (PD09), also on D52\n\tSPI0_SDO_PIN = D65 // (PD08), also on D51\n\tSPI0_SDI_PIN = D64 // (PD11), also on D50\n\tSPI0_CS_PIN  = D53 // (PD10)\n\n\tSPI1_SCK_PIN = D81 // (PB27)\n\tSPI1_SDO_PIN = D82 // (PB26)\n\tSPI1_SDI_PIN = D80 // (PB29)\n\n\tSPI_SCK_PIN = SPI0_SCK_PIN // default pins\n\tSPI_SDO_PIN = SPI0_SDO_PIN //\n\tSPI_SDI_PIN = SPI0_SDI_PIN //\n\tSPI_CS_PIN  = SPI0_CS_PIN  //\n)\n\n// SPI on the Grand Central M4\nvar (\n\tSPI0 = sercomSPIM7\n\tSPI1 = sercomSPIM2 // SD card\n)\n\n// I2C pins\nconst (\n\tI2C0_SDA_PIN = D62 // (PB20), also on D20\n\tI2C0_SCL_PIN = D63 // (PB21), also on D21\n\n\tI2C1_SDA_PIN = D25 // (PC16)\n\tI2C1_SCL_PIN = D24 // (PC17)\n\n\tI2C_SDA_PIN = I2C0_SDA_PIN // default pins\n\tI2C_SCL_PIN = I2C0_SCL_PIN //\n\n\tSDA_PIN = I2C_SDA_PIN // unconventional pin names\n\tSCL_PIN = I2C_SCL_PIN //  (required by machine_atsamd51.go)\n)\n\n// I2C on the Grand Central M4\nvar (\n\tI2C0 = sercomI2CM3\n\tI2C1 = sercomI2CM6\n)\n\n// I2S pins\nconst (\n\tI2S0_SCK_PIN = D14 // (PB16)\n\tI2S0_MCK_PIN = D15 // (PB17)\n\tI2S0_FS_PIN  = D33 // (PA20)\n\tI2S0_SDO_PIN = D32 // (PA21)\n\tI2S0_SDI_PIN = D31 // (PA22)\n\n\tI2S_SCK_PIN = I2S0_SCK_PIN // default pins\n\tI2S_WS_PIN  = I2S0_FS_PIN  //\n\tI2S_SDO_PIN = I2S0_SDO_PIN\n\tI2S_SDI_PIN = NoPin\n)\n\n// SD card pins\nconst (\n\tSD0_SCK_PIN = D81 // (PB27)\n\tSD0_SDO_PIN = D82 // (PB26)\n\tSD0_SDI_PIN = D80 // (PB29)\n\tSD0_CS_PIN  = D83 // (PB28)\n\tSD0_DET_PIN = D95 // (PB31)\n\n\tSDCARD_SCK_PIN = SD0_SCK_PIN // default pins\n\tSDCARD_SDO_PIN = SD0_SDO_PIN //\n\tSDCARD_SDI_PIN = SD0_SDI_PIN //\n\tSDCARD_CS_PIN  = SD0_CS_PIN  //\n\tSDCARD_DET_PIN = SD0_DET_PIN //\n)\n\n// Other peripheral constants\nconst (\n\tresetMagicValue = 0xF01669EF // Used to reset into bootloader\n)\n\n// USB CDC pins\nconst (\n\tUSBCDC_HOSTEN_PIN = D77 // (PA27) host enable\n\tUSBCDC_DM_PIN     = D78 // (PA24) D-\n\tUSBCDC_DP_PIN     = D79 // (PA25) D+\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Adafruit Grand Central M4\"\n\tusb_STRING_MANUFACTURER = \"Adafruit\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x8031\n)\n"
  },
  {
    "path": "src/machine/board_hifive1b.go",
    "content": "//go:build hifive1b\n\npackage machine\n\nconst (\n\tD0  = P16\n\tD1  = P17\n\tD2  = P18\n\tD3  = P19 // Green LED/PWM (PWM1_PWM1)\n\tD4  = P20 // PWM (PWM1_PWM0)\n\tD5  = P21 // Blue LED/PWM (PWM1_PWM2)\n\tD6  = P22 // Red LED/PWM (PWM1_PWM3)\n\tD7  = P16\n\tD8  = NoPin // PWM?\n\tD9  = P01\n\tD10 = P02   // SPI1_CS0\n\tD11 = P03   // SPI1_DQ0\n\tD12 = P04   // SPI1_DQ1\n\tD13 = P05   // SPI1_SCK\n\tD14 = NoPin // not connected\n\tD15 = P09   // does not seem to work?\n\tD16 = P10   // PWM (PWM2_PWM0)\n\tD17 = P11   // PWM (PWM2_PWM1)\n\tD18 = P12   // SDA (I2C0_SDA)/PWM (PWM2_PWM2)\n\tD19 = P13   // SDL (I2C0_SCL)/PWM (PWM2_PWM3)\n)\n\nconst (\n\tLED       = LED1\n\tLED1      = LED_RED\n\tLED2      = LED_GREEN\n\tLED3      = LED_BLUE\n\tLED_RED   = P22\n\tLED_GREEN = P19\n\tLED_BLUE  = P21\n)\n\nvar DefaultUART = UART0\n\nconst (\n\t// TODO: figure out the pin numbers for these.\n\tUART_TX_PIN = D1\n\tUART_RX_PIN = D0\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = NoPin\n\tSPI0_SDO_PIN = NoPin\n\tSPI0_SDI_PIN = NoPin\n\n\tSPI1_SCK_PIN = D13\n\tSPI1_SDO_PIN = D11\n\tSPI1_SDI_PIN = D12\n)\n\n// I2C pins\nconst (\n\tI2C0_SDA_PIN = D18\n\tI2C0_SCL_PIN = D19\n)\n"
  },
  {
    "path": "src/machine/board_hifive1b_baremetal.go",
    "content": "//go:build fe310 && hifive1b\n\npackage machine\n\nimport \"device/sifive\"\n\n// SPI on the HiFive1.\nvar (\n\tSPI1 = &SPI{\n\t\tBus: sifive.QSPI1,\n\t}\n)\n"
  },
  {
    "path": "src/machine/board_hw-651.go",
    "content": "//go:build hw_651\n\npackage machine\n\n// No-name brand board based on the nRF51822 chip with low frequency crystal on board.\n// Pinout (reverse engineered from the board) can be found here:\n// https://aviatorahmet.blogspot.com/2020/12/pinout-of-nrf51822-board.html\n// https://cr0wg4n.medium.com/pinout-nrf51822-board-hw-651-78da2eda8894\n\nconst HasLowFrequencyCrystal = true\n\nvar DefaultUART = UART0\n\n// GPIO pins on header J1\nconst (\n\tJ1_01 = P0_21\n\tJ1_03 = P0_23\n\tJ1_04 = P0_22\n\tJ1_05 = P0_25\n\tJ1_06 = P0_24\n\tJ1_09 = P0_29\n\tJ1_10 = P0_28\n\tJ1_11 = P0_30\n\tJ1_13 = P0_00\n\tJ1_15 = P0_02\n\tJ1_17 = P0_04\n\tJ1_16 = P0_01\n\tJ1_18 = P0_03\n)\n\n// GPIO pins on header J2\nconst (\n\tJ2_01 = P0_20\n\tJ2_03 = P0_18\n\tJ2_04 = P0_19\n\tJ2_07 = P0_16\n\tJ2_08 = P0_15\n\tJ2_09 = P0_14\n\tJ2_10 = P0_13\n\tJ2_11 = P0_12\n\tJ2_12 = P0_11\n\tJ2_13 = P0_10\n\tJ2_14 = P0_09\n\tJ2_15 = P0_08\n\tJ2_16 = P0_07\n\tJ2_17 = P0_06\n\tJ2_18 = P0_05\n)\n\n// UART pins\nconst (\n\tUART_TX_PIN = P0_24 // J1_06 on the board\n\tUART_RX_PIN = P0_25 // J1_05 on the board\n)\n\n// ADC pins\nconst (\n\tADC0 = P0_03 // J1_18 on the board\n\tADC1 = P0_02 // J1_15 on the board\n\tADC2 = P0_01 // J1_16 on the board\n\tADC3 = P0_04 // J1_17 on the board\n\tADC4 = P0_05 // J2_18 on the board\n\tADC5 = P0_06 // J2_17 on the board\n)\n\n// I2C pins\nconst (\n\tSDA_PIN = P0_30 // J1_11 on the board\n\tSCL_PIN = P0_00 // J1_13 on the board\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = P0_23 // J1_03 on the board\n\tSPI0_SDO_PIN = P0_21 // J1_01 on the board\n\tSPI0_SDI_PIN = P0_22 // J1_04 on the board\n)\n"
  },
  {
    "path": "src/machine/board_itsybitsy-m0.go",
    "content": "//go:build sam && atsamd21 && itsybitsy_m0\n\npackage machine\n\n// used to reset into bootloader\nconst resetMagicValue = 0xf01669ef\n\n// GPIO Pins\nconst (\n\tD0  = PA11 // UART0 RX\n\tD1  = PA10 // UART0 TX\n\tD2  = PA14\n\tD3  = PA09 // PWM available\n\tD4  = PA08 // PWM available\n\tD5  = PA15 // PWM available\n\tD6  = PA20 // PWM available\n\tD7  = PA21 // PWM available\n\tD8  = PA06 // PWM available\n\tD9  = PA07 // PWM available\n\tD10 = PA18 // can be used for PWM or UART1 TX\n\tD11 = PA16 // can be used for PWM or UART1 RX\n\tD12 = PA19 // PWM available\n\tD13 = PA17 // PWM available\n)\n\n// Analog pins\nconst (\n\tA0 = PA02 // ADC/AIN[0]\n\tA1 = PB08 // ADC/AIN[2]\n\tA2 = PB09 // ADC/AIN[3]\n\tA3 = PA04 // ADC/AIN[4]\n\tA4 = PA05 // ADC/AIN[5]\n\tA5 = PB02 // ADC/AIN[10]\n)\n\nconst (\n\tLED = D13\n)\n\n// USBCDC pins\nconst (\n\tUSBCDC_DM_PIN = PA24\n\tUSBCDC_DP_PIN = PA25\n)\n\n// UART1 pins\nconst (\n\tUART_TX_PIN = D10\n\tUART_RX_PIN = D11\n)\n\n// UART1 on the ItsyBitsy M0.\nvar (\n\tUART1 = &sercomUSART1\n)\n\n// I2C pins\nconst (\n\tSDA_PIN = PA22 // SDA: SERCOM3/PAD[0]\n\tSCL_PIN = PA23 // SCL: SERCOM3/PAD[1]\n)\n\n// I2C on the ItsyBitsy M0.\nvar (\n\tI2C0 = sercomI2CM3\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = PB11 // SCK: SERCOM4/PAD[3]\n\tSPI0_SDO_PIN = PB10 // SDO: SERCOM4/PAD[2]\n\tSPI0_SDI_PIN = PA12 // SDI: SERCOM4/PAD[0]\n)\n\n// SPI on the ItsyBitsy M0.\nvar SPI0 = sercomSPIM4\n\n// \"Internal\" SPI pins; SPI flash is attached to these on ItsyBitsy M0\nconst (\n\tSPI1_CS_PIN  = PA27\n\tSPI1_SCK_PIN = PB23\n\tSPI1_SDO_PIN = PB22\n\tSPI1_SDI_PIN = PB03\n)\n\n// \"Internal\" SPI on Sercom 5\nvar SPI1 = sercomSPIM5\n\n// I2S pins\nconst (\n\tI2S_SCK_PIN = PA10\n\tI2S_SDO_PIN = PA08\n\tI2S_SDI_PIN = NoPin\n\tI2S_WS_PIN  = NoPin // TODO: figure out what this is on ItsyBitsy M0.\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Adafruit ItsyBitsy M0 Express\"\n\tusb_STRING_MANUFACTURER = \"Adafruit\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x800F\n)\n\nvar (\n\tDefaultUART = UART1\n)\n"
  },
  {
    "path": "src/machine/board_itsybitsy-m4.go",
    "content": "//go:build itsybitsy_m4\n\npackage machine\n\n// used to reset into bootloader\nconst resetMagicValue = 0xf01669ef\n\n// GPIO Pins\nconst (\n\tD0  = PA16 // UART0 RX/PWM available\n\tD1  = PA17 // UART0 TX/PWM available\n\tD2  = PA07\n\tD3  = PB22\n\tD4  = PA14 // PWM available\n\tD5  = PA15 // PWM available\n\tD6  = PB02 // dotStar clock\n\tD7  = PA18 // PWM available\n\tD8  = PB03 // dotStar data\n\tD9  = PA19 // PWM available\n\tD10 = PA20 // can be used for PWM or UART1 TX\n\tD11 = PA21 // can be used for PWM or UART1 RX\n\tD12 = PA23 // PWM available\n\tD13 = PA22 // PWM available\n)\n\n// Analog pins\nconst (\n\tA0 = PA02 // ADC/AIN[0]\n\tA1 = PA05 // ADC/AIN[2]\n\tA2 = PB08 // ADC/AIN[3]\n\tA3 = PB09 // ADC/AIN[4]\n\tA4 = PA04 // ADC/AIN[5]\n\tA5 = PA06 // ADC/AIN[10]\n)\n\nconst (\n\tLED = D13\n)\n\n// USBCDC pins\nconst (\n\tUSBCDC_DM_PIN = PA24\n\tUSBCDC_DP_PIN = PA25\n)\n\n// UART1 pins\nconst (\n\tUART_TX_PIN = D1\n\tUART_RX_PIN = D0\n)\n\nconst (\n\tUART2_TX_PIN = A4\n\tUART2_RX_PIN = D2\n)\n\nvar (\n\tUART1 = &sercomUSART3\n\tUART2 = &sercomUSART0\n\n\tDefaultUART = UART1\n)\n\n// I2C pins\nconst (\n\tSDA_PIN = PA12 // SDA: SERCOM2/PAD[0]\n\tSCL_PIN = PA13 // SCL: SERCOM2/PAD[1]\n)\n\n// I2C on the ItsyBitsy M4.\nvar (\n\tI2C0 = sercomI2CM2\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = PA01 // SCK: SERCOM1/PAD[1]\n\tSPI0_SDO_PIN = PA00 // SDO: SERCOM1/PAD[0]\n\tSPI0_SDI_PIN = PB23 // SDI: SERCOM1/PAD[3]\n)\n\n// SPI on the ItsyBitsy M4.\nvar SPI0 = sercomSPIM1\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Adafruit ItsyBitsy M4\"\n\tusb_STRING_MANUFACTURER = \"Adafruit\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x802B\n)\n"
  },
  {
    "path": "src/machine/board_itsybitsy-nrf52840.go",
    "content": "//go:build itsybitsy_nrf52840\n\npackage machine\n\nconst HasLowFrequencyCrystal = true\n\n// GPIO Pins\nconst (\n\tD0  = P0_25 // UART TX\n\tD1  = P0_24 // UART RX\n\tD2  = P1_02\n\tD3  = P0_06 // LED1\n\tD4  = P0_29 // Button\n\tD5  = P0_27\n\tD6  = P1_09 // DotStar Clock\n\tD7  = P1_08\n\tD8  = P0_08 // DotStar Data\n\tD9  = P0_07\n\tD10 = P0_05\n\tD11 = P0_26\n\tD12 = P0_11\n\tD13 = P0_12\n\tD14 = P0_04 // A0\n\tD15 = P0_30 // A1\n\tD16 = P0_28 // A2\n\tD17 = P0_31 // A3\n\tD18 = P0_02 // A4\n\tD19 = P0_03 // A5\n\tD20 = P0_05 // A6\n\tD21 = P0_16 // I2C SDA\n\tD22 = P0_14 // I2C SCL\n\tD23 = P0_20 // SPI SDI\n\tD24 = P0_15 // SPI SDO\n\tD25 = P0_13 // SPI SCK\n\tD26 = P0_19 // QSPI SCK\n\tD27 = P0_23 // QSPI CS\n\tD28 = P0_21 // QSPI Data 0\n\tD29 = P0_22 // QSPI Data 1\n\tD30 = P1_00 // QSPI Data 2\n\tD31 = P0_17 // QSPI Data 3\n)\n\n// Analog Pins\nconst (\n\tA0 = D14\n\tA1 = D15\n\tA2 = D16\n\tA3 = D17\n\tA4 = D18\n\tA5 = D19\n\tA6 = D20\n)\n\nconst (\n\tLED    = D3\n\tLED1   = LED\n\tBUTTON = D4\n\n\tQSPI_SCK   = D26\n\tQSPI_CS    = D27\n\tQSPI_DATA0 = D28\n\tQSPI_DATA1 = D29\n\tQSPI_DATA2 = D30\n\tQSPI_DATA3 = D31\n)\n\n// UART0 pins (logical UART1)\nconst (\n\tUART_RX_PIN = D0\n\tUART_TX_PIN = D1\n)\n\n// I2C pins\nconst (\n\tSDA_PIN = D21 // I2C0 external\n\tSCL_PIN = D22 // I2C0 external\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = D25\n\tSPI0_SDO_PIN = D24\n\tSPI0_SDI_PIN = D23\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Adafruit ItsyBitsy nRF52840 Express\"\n\tusb_STRING_MANUFACTURER = \"Adafruit\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x8051\n)\n\nvar (\n\tDefaultUART = UART0\n)\n"
  },
  {
    "path": "src/machine/board_k210.go",
    "content": "//go:build maixbit\n\n// Chip datasheet: https://s3.cn-north-1.amazonaws.com.cn/dl.kendryte.com/documents/kendryte_datasheet_20181011163248_en.pdf\n\npackage machine\n\n// K210 IO pins.\nconst (\n\tP00 Pin = 0\n\tP01 Pin = 1\n\tP02 Pin = 2\n\tP03 Pin = 3\n\tP04 Pin = 4\n\tP05 Pin = 5\n\tP06 Pin = 6\n\tP07 Pin = 7\n\tP08 Pin = 8\n\tP09 Pin = 9\n\tP10 Pin = 10\n\tP11 Pin = 11\n\tP12 Pin = 12\n\tP13 Pin = 13\n\tP14 Pin = 14\n\tP15 Pin = 15\n\tP16 Pin = 16\n\tP17 Pin = 17\n\tP18 Pin = 18\n\tP19 Pin = 19\n\tP20 Pin = 20\n\tP21 Pin = 21\n\tP22 Pin = 22\n\tP23 Pin = 23\n\tP24 Pin = 24\n\tP25 Pin = 25\n\tP26 Pin = 26\n\tP27 Pin = 27\n\tP28 Pin = 28\n\tP29 Pin = 29\n\tP30 Pin = 30\n\tP31 Pin = 31\n\tP32 Pin = 32\n\tP33 Pin = 33\n\tP34 Pin = 34\n\tP35 Pin = 35\n\tP36 Pin = 36\n\tP37 Pin = 37\n\tP38 Pin = 38\n\tP39 Pin = 39\n\tP40 Pin = 40\n\tP41 Pin = 41\n\tP42 Pin = 42\n\tP43 Pin = 43\n\tP44 Pin = 44\n\tP45 Pin = 45\n\tP46 Pin = 46\n\tP47 Pin = 47\n)\n\ntype FPIOAFunction uint8\n\n// Every pin on the Kendryte K210 is assigned to an FPIOA function.\n// Each pin can be configured with every function below.\nconst (\n\tFUNC_JTAG_TCLK           FPIOAFunction = 0   // JTAG Test Clock\n\tFUNC_JTAG_TDI            FPIOAFunction = 1   // JTAG Test Data In\n\tFUNC_JTAG_TMS            FPIOAFunction = 2   // JTAG Test Mode Select\n\tFUNC_JTAG_TDO            FPIOAFunction = 3   // JTAG Test Data Out\n\tFUNC_SPI0_D0             FPIOAFunction = 4   // SPI0 Data 0\n\tFUNC_SPI0_D1             FPIOAFunction = 5   // SPI0 Data 1\n\tFUNC_SPI0_D2             FPIOAFunction = 6   // SPI0 Data 2\n\tFUNC_SPI0_D3             FPIOAFunction = 7   // SPI0 Data 3\n\tFUNC_SPI0_D4             FPIOAFunction = 8   // SPI0 Data 4\n\tFUNC_SPI0_D5             FPIOAFunction = 9   // SPI0 Data 5\n\tFUNC_SPI0_D6             FPIOAFunction = 10  // SPI0 Data 6\n\tFUNC_SPI0_D7             FPIOAFunction = 11  // SPI0 Data 7\n\tFUNC_SPI0_SS0            FPIOAFunction = 12  // SPI0 Chip Select 0\n\tFUNC_SPI0_SS1            FPIOAFunction = 13  // SPI0 Chip Select 1\n\tFUNC_SPI0_SS2            FPIOAFunction = 14  // SPI0 Chip Select 2\n\tFUNC_SPI0_SS3            FPIOAFunction = 15  // SPI0 Chip Select 3\n\tFUNC_SPI0_ARB            FPIOAFunction = 16  // SPI0 Arbitration\n\tFUNC_SPI0_SCLK           FPIOAFunction = 17  // SPI0 Serial Clock\n\tFUNC_UARTHS_RX           FPIOAFunction = 18  // UART High speed Receiver\n\tFUNC_UARTHS_TX           FPIOAFunction = 19  // UART High speed Transmitter\n\tFUNC_RESV6               FPIOAFunction = 20  // Reserved function\n\tFUNC_RESV7               FPIOAFunction = 21  // Reserved function\n\tFUNC_CLK_SPI1            FPIOAFunction = 22  // Clock SPI1\n\tFUNC_CLK_I2C1            FPIOAFunction = 23  // Clock I2C1\n\tFUNC_GPIOHS0             FPIOAFunction = 24  // GPIO High speed 0\n\tFUNC_GPIOHS1             FPIOAFunction = 25  // GPIO High speed 1\n\tFUNC_GPIOHS2             FPIOAFunction = 26  // GPIO High speed 2\n\tFUNC_GPIOHS3             FPIOAFunction = 27  // GPIO High speed 3\n\tFUNC_GPIOHS4             FPIOAFunction = 28  // GPIO High speed 4\n\tFUNC_GPIOHS5             FPIOAFunction = 29  // GPIO High speed 5\n\tFUNC_GPIOHS6             FPIOAFunction = 30  // GPIO High speed 6\n\tFUNC_GPIOHS7             FPIOAFunction = 31  // GPIO High speed 7\n\tFUNC_GPIOHS8             FPIOAFunction = 32  // GPIO High speed 8\n\tFUNC_GPIOHS9             FPIOAFunction = 33  // GPIO High speed 9\n\tFUNC_GPIOHS10            FPIOAFunction = 34  // GPIO High speed 10\n\tFUNC_GPIOHS11            FPIOAFunction = 35  // GPIO High speed 11\n\tFUNC_GPIOHS12            FPIOAFunction = 36  // GPIO High speed 12\n\tFUNC_GPIOHS13            FPIOAFunction = 37  // GPIO High speed 13\n\tFUNC_GPIOHS14            FPIOAFunction = 38  // GPIO High speed 14\n\tFUNC_GPIOHS15            FPIOAFunction = 39  // GPIO High speed 15\n\tFUNC_GPIOHS16            FPIOAFunction = 40  // GPIO High speed 16\n\tFUNC_GPIOHS17            FPIOAFunction = 41  // GPIO High speed 17\n\tFUNC_GPIOHS18            FPIOAFunction = 42  // GPIO High speed 18\n\tFUNC_GPIOHS19            FPIOAFunction = 43  // GPIO High speed 19\n\tFUNC_GPIOHS20            FPIOAFunction = 44  // GPIO High speed 20\n\tFUNC_GPIOHS21            FPIOAFunction = 45  // GPIO High speed 21\n\tFUNC_GPIOHS22            FPIOAFunction = 46  // GPIO High speed 22\n\tFUNC_GPIOHS23            FPIOAFunction = 47  // GPIO High speed 23\n\tFUNC_GPIOHS24            FPIOAFunction = 48  // GPIO High speed 24\n\tFUNC_GPIOHS25            FPIOAFunction = 49  // GPIO High speed 25\n\tFUNC_GPIOHS26            FPIOAFunction = 50  // GPIO High speed 26\n\tFUNC_GPIOHS27            FPIOAFunction = 51  // GPIO High speed 27\n\tFUNC_GPIOHS28            FPIOAFunction = 52  // GPIO High speed 28\n\tFUNC_GPIOHS29            FPIOAFunction = 53  // GPIO High speed 29\n\tFUNC_GPIOHS30            FPIOAFunction = 54  // GPIO High speed 30\n\tFUNC_GPIOHS31            FPIOAFunction = 55  // GPIO High speed 31\n\tFUNC_GPIO0               FPIOAFunction = 56  // GPIO pin 0\n\tFUNC_GPIO1               FPIOAFunction = 57  // GPIO pin 1\n\tFUNC_GPIO2               FPIOAFunction = 58  // GPIO pin 2\n\tFUNC_GPIO3               FPIOAFunction = 59  // GPIO pin 3\n\tFUNC_GPIO4               FPIOAFunction = 60  // GPIO pin 4\n\tFUNC_GPIO5               FPIOAFunction = 61  // GPIO pin 5\n\tFUNC_GPIO6               FPIOAFunction = 62  // GPIO pin 6\n\tFUNC_GPIO7               FPIOAFunction = 63  // GPIO pin 7\n\tFUNC_UART1_RX            FPIOAFunction = 64  // UART1 Receiver\n\tFUNC_UART1_TX            FPIOAFunction = 65  // UART1 Transmitter\n\tFUNC_UART2_RX            FPIOAFunction = 66  // UART2 Receiver\n\tFUNC_UART2_TX            FPIOAFunction = 67  // UART2 Transmitter\n\tFUNC_UART3_RX            FPIOAFunction = 68  // UART3 Receiver\n\tFUNC_UART3_TX            FPIOAFunction = 69  // UART3 Transmitter\n\tFUNC_SPI1_D0             FPIOAFunction = 70  // SPI1 Data 0\n\tFUNC_SPI1_D1             FPIOAFunction = 71  // SPI1 Data 1\n\tFUNC_SPI1_D2             FPIOAFunction = 72  // SPI1 Data 2\n\tFUNC_SPI1_D3             FPIOAFunction = 73  // SPI1 Data 3\n\tFUNC_SPI1_D4             FPIOAFunction = 74  // SPI1 Data 4\n\tFUNC_SPI1_D5             FPIOAFunction = 75  // SPI1 Data 5\n\tFUNC_SPI1_D6             FPIOAFunction = 76  // SPI1 Data 6\n\tFUNC_SPI1_D7             FPIOAFunction = 77  // SPI1 Data 7\n\tFUNC_SPI1_SS0            FPIOAFunction = 78  // SPI1 Chip Select 0\n\tFUNC_SPI1_SS1            FPIOAFunction = 79  // SPI1 Chip Select 1\n\tFUNC_SPI1_SS2            FPIOAFunction = 80  // SPI1 Chip Select 2\n\tFUNC_SPI1_SS3            FPIOAFunction = 81  // SPI1 Chip Select 3\n\tFUNC_SPI1_ARB            FPIOAFunction = 82  // SPI1 Arbitration\n\tFUNC_SPI1_SCLK           FPIOAFunction = 83  // SPI1 Serial Clock\n\tFUNC_SPI_PERIPHERAL_D0   FPIOAFunction = 84  // SPI Peripheral Data 0\n\tFUNC_SPI_PERIPHERAL_SS   FPIOAFunction = 85  // SPI Peripheral Select\n\tFUNC_SPI_PERIPHERAL_SCLK FPIOAFunction = 86  // SPI Peripheral Serial Clock\n\tFUNC_I2S0_MCLK           FPIOAFunction = 87  // I2S0 Main Clock\n\tFUNC_I2S0_SCLK           FPIOAFunction = 88  // I2S0 Serial Clock(BCLK)\n\tFUNC_I2S0_WS             FPIOAFunction = 89  // I2S0 Word Select(LRCLK)\n\tFUNC_I2S0_IN_D0          FPIOAFunction = 90  // I2S0 Serial Data Input 0\n\tFUNC_I2S0_IN_D1          FPIOAFunction = 91  // I2S0 Serial Data Input 1\n\tFUNC_I2S0_IN_D2          FPIOAFunction = 92  // I2S0 Serial Data Input 2\n\tFUNC_I2S0_IN_D3          FPIOAFunction = 93  // I2S0 Serial Data Input 3\n\tFUNC_I2S0_OUT_D0         FPIOAFunction = 94  // I2S0 Serial Data Output 0\n\tFUNC_I2S0_OUT_D1         FPIOAFunction = 95  // I2S0 Serial Data Output 1\n\tFUNC_I2S0_OUT_D2         FPIOAFunction = 96  // I2S0 Serial Data Output 2\n\tFUNC_I2S0_OUT_D3         FPIOAFunction = 97  // I2S0 Serial Data Output 3\n\tFUNC_I2S1_MCLK           FPIOAFunction = 98  // I2S1 Main Clock\n\tFUNC_I2S1_SCLK           FPIOAFunction = 99  // I2S1 Serial Clock(BCLK)\n\tFUNC_I2S1_WS             FPIOAFunction = 100 // I2S1 Word Select(LRCLK)\n\tFUNC_I2S1_IN_D0          FPIOAFunction = 101 // I2S1 Serial Data Input 0\n\tFUNC_I2S1_IN_D1          FPIOAFunction = 102 // I2S1 Serial Data Input 1\n\tFUNC_I2S1_IN_D2          FPIOAFunction = 103 // I2S1 Serial Data Input 2\n\tFUNC_I2S1_IN_D3          FPIOAFunction = 104 // I2S1 Serial Data Input 3\n\tFUNC_I2S1_OUT_D0         FPIOAFunction = 105 // I2S1 Serial Data Output 0\n\tFUNC_I2S1_OUT_D1         FPIOAFunction = 106 // I2S1 Serial Data Output 1\n\tFUNC_I2S1_OUT_D2         FPIOAFunction = 107 // I2S1 Serial Data Output 2\n\tFUNC_I2S1_OUT_D3         FPIOAFunction = 108 // I2S1 Serial Data Output 3\n\tFUNC_I2S2_MCLK           FPIOAFunction = 109 // I2S2 Main Clock\n\tFUNC_I2S2_SCLK           FPIOAFunction = 110 // I2S2 Serial Clock(BCLK)\n\tFUNC_I2S2_WS             FPIOAFunction = 111 // I2S2 Word Select(LRCLK)\n\tFUNC_I2S2_IN_D0          FPIOAFunction = 112 // I2S2 Serial Data Input 0\n\tFUNC_I2S2_IN_D1          FPIOAFunction = 113 // I2S2 Serial Data Input 1\n\tFUNC_I2S2_IN_D2          FPIOAFunction = 114 // I2S2 Serial Data Input 2\n\tFUNC_I2S2_IN_D3          FPIOAFunction = 115 // I2S2 Serial Data Input 3\n\tFUNC_I2S2_OUT_D0         FPIOAFunction = 116 // I2S2 Serial Data Output 0\n\tFUNC_I2S2_OUT_D1         FPIOAFunction = 117 // I2S2 Serial Data Output 1\n\tFUNC_I2S2_OUT_D2         FPIOAFunction = 118 // I2S2 Serial Data Output 2\n\tFUNC_I2S2_OUT_D3         FPIOAFunction = 119 // I2S2 Serial Data Output 3\n\tFUNC_RESV0               FPIOAFunction = 120 // Reserved function\n\tFUNC_RESV1               FPIOAFunction = 121 // Reserved function\n\tFUNC_RESV2               FPIOAFunction = 122 // Reserved function\n\tFUNC_RESV3               FPIOAFunction = 123 // Reserved function\n\tFUNC_RESV4               FPIOAFunction = 124 // Reserved function\n\tFUNC_RESV5               FPIOAFunction = 125 // Reserved function\n\tFUNC_I2C0_SCLK           FPIOAFunction = 126 // I2C0 Serial Clock\n\tFUNC_I2C0_SDA            FPIOAFunction = 127 // I2C0 Serial Data\n\tFUNC_I2C1_SCLK           FPIOAFunction = 128 // I2C1 Serial Clock\n\tFUNC_I2C1_SDA            FPIOAFunction = 129 // I2C1 Serial Data\n\tFUNC_I2C2_SCLK           FPIOAFunction = 130 // I2C2 Serial Clock\n\tFUNC_I2C2_SDA            FPIOAFunction = 131 // I2C2 Serial Data\n\tFUNC_CMOS_XCLK           FPIOAFunction = 132 // DVP System Clock\n\tFUNC_CMOS_RST            FPIOAFunction = 133 // DVP System Reset\n\tFUNC_CMOS_PWDN           FPIOAFunction = 134 // DVP Power Down Mode\n\tFUNC_CMOS_VSYNC          FPIOAFunction = 135 // DVP Vertical Sync\n\tFUNC_CMOS_HREF           FPIOAFunction = 136 // DVP Horizontal Reference output\n\tFUNC_CMOS_PCLK           FPIOAFunction = 137 // Pixel Clock\n\tFUNC_CMOS_D0             FPIOAFunction = 138 // Data Bit 0\n\tFUNC_CMOS_D1             FPIOAFunction = 139 // Data Bit 1\n\tFUNC_CMOS_D2             FPIOAFunction = 140 // Data Bit 2\n\tFUNC_CMOS_D3             FPIOAFunction = 141 // Data Bit 3\n\tFUNC_CMOS_D4             FPIOAFunction = 142 // Data Bit 4\n\tFUNC_CMOS_D5             FPIOAFunction = 143 // Data Bit 5\n\tFUNC_CMOS_D6             FPIOAFunction = 144 // Data Bit 6\n\tFUNC_CMOS_D7             FPIOAFunction = 145 // Data Bit 7\n\tFUNC_SCCB_SCLK           FPIOAFunction = 146 // SCCB Serial Clock\n\tFUNC_SCCB_SDA            FPIOAFunction = 147 // SCCB Serial Data\n\tFUNC_UART1_CTS           FPIOAFunction = 148 // UART1 Clear To Send\n\tFUNC_UART1_DSR           FPIOAFunction = 149 // UART1 Data Set Ready\n\tFUNC_UART1_DCD           FPIOAFunction = 150 // UART1 Data Carrier Detect\n\tFUNC_UART1_RI            FPIOAFunction = 151 // UART1 Ring Indicator\n\tFUNC_UART1_SIR_IN        FPIOAFunction = 152 // UART1 Serial Infrared Input\n\tFUNC_UART1_DTR           FPIOAFunction = 153 // UART1 Data Terminal Ready\n\tFUNC_UART1_RTS           FPIOAFunction = 154 // UART1 Request To Send\n\tFUNC_UART1_OUT2          FPIOAFunction = 155 // UART1 User-designated Output 2\n\tFUNC_UART1_OUT1          FPIOAFunction = 156 // UART1 User-designated Output 1\n\tFUNC_UART1_SIR_OUT       FPIOAFunction = 157 // UART1 Serial Infrared Output\n\tFUNC_UART1_BAUD          FPIOAFunction = 158 // UART1 Transmit Clock Output\n\tFUNC_UART1_RE            FPIOAFunction = 159 // UART1 Receiver Output Enable\n\tFUNC_UART1_DE            FPIOAFunction = 160 // UART1 Driver Output Enable\n\tFUNC_UART1_RS485_EN      FPIOAFunction = 161 // UART1 RS485 Enable\n\tFUNC_UART2_CTS           FPIOAFunction = 162 // UART2 Clear To Send\n\tFUNC_UART2_DSR           FPIOAFunction = 163 // UART2 Data Set Ready\n\tFUNC_UART2_DCD           FPIOAFunction = 164 // UART2 Data Carrier Detect\n\tFUNC_UART2_RI            FPIOAFunction = 165 // UART2 Ring Indicator\n\tFUNC_UART2_SIR_IN        FPIOAFunction = 166 // UART2 Serial Infrared Input\n\tFUNC_UART2_DTR           FPIOAFunction = 167 // UART2 Data Terminal Ready\n\tFUNC_UART2_RTS           FPIOAFunction = 168 // UART2 Request To Send\n\tFUNC_UART2_OUT2          FPIOAFunction = 169 // UART2 User-designated Output 2\n\tFUNC_UART2_OUT1          FPIOAFunction = 170 // UART2 User-designated Output 1\n\tFUNC_UART2_SIR_OUT       FPIOAFunction = 171 // UART2 Serial Infrared Output\n\tFUNC_UART2_BAUD          FPIOAFunction = 172 // UART2 Transmit Clock Output\n\tFUNC_UART2_RE            FPIOAFunction = 173 // UART2 Receiver Output Enable\n\tFUNC_UART2_DE            FPIOAFunction = 174 // UART2 Driver Output Enable\n\tFUNC_UART2_RS485_EN      FPIOAFunction = 175 // UART2 RS485 Enable\n\tFUNC_UART3_CTS           FPIOAFunction = 176 // UART3 Clear To Send\n\tFUNC_UART3_DSR           FPIOAFunction = 177 // UART3 Data Set Ready\n\tFUNC_UART3_DCD           FPIOAFunction = 178 // UART3 Data Carrier Detect\n\tFUNC_UART3_RI            FPIOAFunction = 179 // UART3 Ring Indicator\n\tFUNC_UART3_SIR_IN        FPIOAFunction = 180 // UART3 Serial Infrared Input\n\tFUNC_UART3_DTR           FPIOAFunction = 181 // UART3 Data Terminal Ready\n\tFUNC_UART3_RTS           FPIOAFunction = 182 // UART3 Request To Send\n\tFUNC_UART3_OUT2          FPIOAFunction = 183 // UART3 User-designated Output 2\n\tFUNC_UART3_OUT1          FPIOAFunction = 184 // UART3 User-designated Output 1\n\tFUNC_UART3_SIR_OUT       FPIOAFunction = 185 // UART3 Serial Infrared Output\n\tFUNC_UART3_BAUD          FPIOAFunction = 186 // UART3 Transmit Clock Output\n\tFUNC_UART3_RE            FPIOAFunction = 187 // UART3 Receiver Output Enable\n\tFUNC_UART3_DE            FPIOAFunction = 188 // UART3 Driver Output Enable\n\tFUNC_UART3_RS485_EN      FPIOAFunction = 189 // UART3 RS485 Enable\n\tFUNC_TIMER0_TOGGLE1      FPIOAFunction = 190 // TIMER0 Toggle Output 1\n\tFUNC_TIMER0_TOGGLE2      FPIOAFunction = 191 // TIMER0 Toggle Output 2\n\tFUNC_TIMER0_TOGGLE3      FPIOAFunction = 192 // TIMER0 Toggle Output 3\n\tFUNC_TIMER0_TOGGLE4      FPIOAFunction = 193 // TIMER0 Toggle Output 4\n\tFUNC_TIMER1_TOGGLE1      FPIOAFunction = 194 // TIMER1 Toggle Output 1\n\tFUNC_TIMER1_TOGGLE2      FPIOAFunction = 195 // TIMER1 Toggle Output 2\n\tFUNC_TIMER1_TOGGLE3      FPIOAFunction = 196 // TIMER1 Toggle Output 3\n\tFUNC_TIMER1_TOGGLE4      FPIOAFunction = 197 // TIMER1 Toggle Output 4\n\tFUNC_TIMER2_TOGGLE1      FPIOAFunction = 198 // TIMER2 Toggle Output 1\n\tFUNC_TIMER2_TOGGLE2      FPIOAFunction = 199 // TIMER2 Toggle Output 2\n\tFUNC_TIMER2_TOGGLE3      FPIOAFunction = 200 // TIMER2 Toggle Output 3\n\tFUNC_TIMER2_TOGGLE4      FPIOAFunction = 201 // TIMER2 Toggle Output 4\n\tFUNC_CLK_SPI2            FPIOAFunction = 202 // Clock SPI2\n\tFUNC_CLK_I2C2            FPIOAFunction = 203 // Clock I2C2\n\tFUNC_INTERNAL0           FPIOAFunction = 204 // Internal function signal 0\n\tFUNC_INTERNAL1           FPIOAFunction = 205 // Internal function signal 1\n\tFUNC_INTERNAL2           FPIOAFunction = 206 // Internal function signal 2\n\tFUNC_INTERNAL3           FPIOAFunction = 207 // Internal function signal 3\n\tFUNC_INTERNAL4           FPIOAFunction = 208 // Internal function signal 4\n\tFUNC_INTERNAL5           FPIOAFunction = 209 // Internal function signal 5\n\tFUNC_INTERNAL6           FPIOAFunction = 210 // Internal function signal 6\n\tFUNC_INTERNAL7           FPIOAFunction = 211 // Internal function signal 7\n\tFUNC_INTERNAL8           FPIOAFunction = 212 // Internal function signal 8\n\tFUNC_INTERNAL9           FPIOAFunction = 213 // Internal function signal 9\n\tFUNC_INTERNAL10          FPIOAFunction = 214 // Internal function signal 10\n\tFUNC_INTERNAL11          FPIOAFunction = 215 // Internal function signal 11\n\tFUNC_INTERNAL12          FPIOAFunction = 216 // Internal function signal 12\n\tFUNC_INTERNAL13          FPIOAFunction = 217 // Internal function signal 13\n\tFUNC_INTERNAL14          FPIOAFunction = 218 // Internal function signal 14\n\tFUNC_INTERNAL15          FPIOAFunction = 219 // Internal function signal 15\n\tFUNC_INTERNAL16          FPIOAFunction = 220 // Internal function signal 16\n\tFUNC_INTERNAL17          FPIOAFunction = 221 // Internal function signal 17\n\tFUNC_CONSTANT            FPIOAFunction = 222 // Constant function\n\tFUNC_INTERNAL18          FPIOAFunction = 223 // Internal function signal 18\n\tFUNC_DEBUG0              FPIOAFunction = 224 // Debug function 0\n\tFUNC_DEBUG1              FPIOAFunction = 225 // Debug function 1\n\tFUNC_DEBUG2              FPIOAFunction = 226 // Debug function 2\n\tFUNC_DEBUG3              FPIOAFunction = 227 // Debug function 3\n\tFUNC_DEBUG4              FPIOAFunction = 228 // Debug function 4\n\tFUNC_DEBUG5              FPIOAFunction = 229 // Debug function 5\n\tFUNC_DEBUG6              FPIOAFunction = 230 // Debug function 6\n\tFUNC_DEBUG7              FPIOAFunction = 231 // Debug function 7\n\tFUNC_DEBUG8              FPIOAFunction = 232 // Debug function 8\n\tFUNC_DEBUG9              FPIOAFunction = 233 // Debug function 9\n\tFUNC_DEBUG10             FPIOAFunction = 234 // Debug function 10\n\tFUNC_DEBUG11             FPIOAFunction = 235 // Debug function 11\n\tFUNC_DEBUG12             FPIOAFunction = 236 // Debug function 12\n\tFUNC_DEBUG13             FPIOAFunction = 237 // Debug function 13\n\tFUNC_DEBUG14             FPIOAFunction = 238 // Debug function 14\n\tFUNC_DEBUG15             FPIOAFunction = 239 // Debug function 15\n\tFUNC_DEBUG16             FPIOAFunction = 240 // Debug function 16\n\tFUNC_DEBUG17             FPIOAFunction = 241 // Debug function 17\n\tFUNC_DEBUG18             FPIOAFunction = 242 // Debug function 18\n\tFUNC_DEBUG19             FPIOAFunction = 243 // Debug function 19\n\tFUNC_DEBUG20             FPIOAFunction = 244 // Debug function 20\n\tFUNC_DEBUG21             FPIOAFunction = 245 // Debug function 21\n\tFUNC_DEBUG22             FPIOAFunction = 246 // Debug function 22\n\tFUNC_DEBUG23             FPIOAFunction = 247 // Debug function 23\n\tFUNC_DEBUG24             FPIOAFunction = 248 // Debug function 24\n\tFUNC_DEBUG25             FPIOAFunction = 249 // Debug function 25\n\tFUNC_DEBUG26             FPIOAFunction = 250 // Debug function 26\n\tFUNC_DEBUG27             FPIOAFunction = 251 // Debug function 27\n\tFUNC_DEBUG28             FPIOAFunction = 252 // Debug function 28\n\tFUNC_DEBUG29             FPIOAFunction = 253 // Debug function 29\n\tFUNC_DEBUG30             FPIOAFunction = 254 // Debug function 30\n\tFUNC_DEBUG31             FPIOAFunction = 255 // Debug function 31\n)\n\n// These are the default FPIOA values for each function.\n// (source: https://github.com/kendryte/kendryte-standalone-sdk/blob/develop/lib/drivers/fpioa.c#L69)\nvar fpioaFuncDefaults [256]uint32 = [256]uint32{\n\t0x00900000, 0x00900001, 0x00900002, 0x00001f03, 0x00b03f04, 0x00b03f05, 0x00b03f06, 0x00b03f07, 0x00b03f08,\n\t0x00b03f09, 0x00b03f0a, 0x00b03f0b, 0x00001f0c, 0x00001f0d, 0x00001f0e, 0x00001f0f, 0x03900010, 0x00001f11,\n\t0x00900012, 0x00001f13, 0x00900014, 0x00900015, 0x00001f16, 0x00001f17, 0x00901f18, 0x00901f19, 0x00901f1a,\n\t0x00901f1b, 0x00901f1c, 0x00901f1d, 0x00901f1e, 0x00901f1f, 0x00901f20, 0x00901f21, 0x00901f22, 0x00901f23,\n\t0x00901f24, 0x00901f25, 0x00901f26, 0x00901f27, 0x00901f28, 0x00901f29, 0x00901f2a, 0x00901f2b, 0x00901f2c,\n\t0x00901f2d, 0x00901f2e, 0x00901f2f, 0x00901f30, 0x00901f31, 0x00901f32, 0x00901f33, 0x00901f34, 0x00901f35,\n\t0x00901f36, 0x00901f37, 0x00901f38, 0x00901f39, 0x00901f3a, 0x00901f3b, 0x00901f3c, 0x00901f3d, 0x00901f3e,\n\t0x00901f3f, 0x00900040, 0x00001f41, 0x00900042, 0x00001f43, 0x00900044, 0x00001f45, 0x00b03f46, 0x00b03f47,\n\t0x00b03f48, 0x00b03f49, 0x00b03f4a, 0x00b03f4b, 0x00b03f4c, 0x00b03f4d, 0x00001f4e, 0x00001f4f, 0x00001f50,\n\t0x00001f51, 0x03900052, 0x00001f53, 0x00b03f54, 0x00900055, 0x00900056, 0x00001f57, 0x00001f58, 0x00001f59,\n\t0x0090005a, 0x0090005b, 0x0090005c, 0x0090005d, 0x00001f5e, 0x00001f5f, 0x00001f60, 0x00001f61, 0x00001f62,\n\t0x00001f63, 0x00001f64, 0x00900065, 0x00900066, 0x00900067, 0x00900068, 0x00001f69, 0x00001f6a, 0x00001f6b,\n\t0x00001f6c, 0x00001f6d, 0x00001f6e, 0x00001f6f, 0x00900070, 0x00900071, 0x00900072, 0x00900073, 0x00001f74,\n\t0x00001f75, 0x00001f76, 0x00001f77, 0x00000078, 0x00000079, 0x0000007a, 0x0000007b, 0x0000007c, 0x0000007d,\n\t0x0099107e, 0x0099107f, 0x00991080, 0x00991081, 0x00991082, 0x00991083, 0x00001f84, 0x00001f85, 0x00001f86,\n\t0x00900087, 0x00900088, 0x00900089, 0x0090008a, 0x0090008b, 0x0090008c, 0x0090008d, 0x0090008e, 0x0090008f,\n\t0x00900090, 0x00900091, 0x00993092, 0x00993093, 0x00900094, 0x00900095, 0x00900096, 0x00900097, 0x00900098,\n\t0x00001f99, 0x00001f9a, 0x00001f9b, 0x00001f9c, 0x00001f9d, 0x00001f9e, 0x00001f9f, 0x00001fa0, 0x00001fa1,\n\t0x009000a2, 0x009000a3, 0x009000a4, 0x009000a5, 0x009000a6, 0x00001fa7, 0x00001fa8, 0x00001fa9, 0x00001faa,\n\t0x00001fab, 0x00001fac, 0x00001fad, 0x00001fae, 0x00001faf, 0x009000b0, 0x009000b1, 0x009000b2, 0x009000b3,\n\t0x009000b4, 0x00001fb5, 0x00001fb6, 0x00001fb7, 0x00001fb8, 0x00001fb9, 0x00001fba, 0x00001fbb, 0x00001fbc,\n\t0x00001fbd, 0x00001fbe, 0x00001fbf, 0x00001fc0, 0x00001fc1, 0x00001fc2, 0x00001fc3, 0x00001fc4, 0x00001fc5,\n\t0x00001fc6, 0x00001fc7, 0x00001fc8, 0x00001fc9, 0x00001fca, 0x00001fcb, 0x00001fcc, 0x00001fcd, 0x00001fce,\n\t0x00001fcf, 0x00001fd0, 0x00001fd1, 0x00001fd2, 0x00001fd3, 0x00001fd4, 0x009000d5, 0x009000d6, 0x009000d7,\n\t0x009000d8, 0x009100d9, 0x00991fda, 0x009000db, 0x009000dc, 0x009000dd, 0x000000de, 0x009000df, 0x00001fe0,\n\t0x00001fe1, 0x00001fe2, 0x00001fe3, 0x00001fe4, 0x00001fe5, 0x00001fe6, 0x00001fe7, 0x00001fe8, 0x00001fe9,\n\t0x00001fea, 0x00001feb, 0x00001fec, 0x00001fed, 0x00001fee, 0x00001fef, 0x00001ff0, 0x00001ff1, 0x00001ff2,\n\t0x00001ff3, 0x00001ff4, 0x00001ff5, 0x00001ff6, 0x00001ff7, 0x00001ff8, 0x00001ff9, 0x00001ffa, 0x00001ffb,\n\t0x00001ffc, 0x00001ffd, 0x00001ffe, 0x00001fff,\n}\n"
  },
  {
    "path": "src/machine/board_kb2040.go",
    "content": "//go:build kb2040\n\npackage machine\n\n// Onboard crystal oscillator frequency, in MHz.\nconst xoscFreq = 12 // MHz\n\n// GPIO Pins\nconst (\n\tD0  = GPIO0\n\tD1  = GPIO1\n\tD2  = GPIO2\n\tD3  = GPIO3\n\tD4  = GPIO4\n\tD5  = GPIO5\n\tD6  = GPIO6\n\tD7  = GPIO7\n\tD8  = GPIO8\n\tD9  = GPIO9\n\tD10 = GPIO10\n)\n\n// Analog pins\nconst (\n\tA0 = GPIO26\n\tA1 = GPIO27\n\tA2 = GPIO28\n\tA3 = GPIO29\n)\n\n// Note: there is no user-controllable LED on the KB2040 board\n// const LED = notConnected\n\n// I2C Pins.\nconst (\n\tI2C0_SDA_PIN = GPIO12\n\tI2C0_SCL_PIN = GPIO13\n\n\tI2C1_SDA_PIN = GPIO2\n\tI2C1_SCL_PIN = GPIO3\n\n\tSDA_PIN = I2C0_SDA_PIN\n\tSCL_PIN = I2C0_SCL_PIN\n)\n\n// SPI default pins\nconst (\n\t// Default Serial Clock Bus 0 for SPI communications\n\tSPI0_SCK_PIN = GPIO18\n\t// Default Serial Out Bus 0 for SPI communications\n\tSPI0_SDO_PIN = GPIO19 // Tx\n\t// Default Serial In Bus 0 for SPI communications\n\tSPI0_SDI_PIN = GPIO20 // Rx\n\n\t// Default Serial Clock Bus 1 for SPI communications\n\tSPI1_SCK_PIN = GPIO26\n\t// Default Serial Out Bus 1 for SPI communications\n\tSPI1_SDO_PIN = GPIO27 // Tx\n\t// Default Serial In Bus 1 for SPI communications\n\tSPI1_SDI_PIN = GPIO28 // Rx\n)\n\n// UART pins\nconst (\n\tUART0_TX_PIN = GPIO0\n\tUART0_RX_PIN = GPIO1\n\tUART1_TX_PIN = GPIO8\n\tUART1_RX_PIN = GPIO9\n\tUART_TX_PIN  = UART0_TX_PIN\n\tUART_RX_PIN  = UART0_RX_PIN\n)\n\nvar DefaultUART = UART0\n\n// USB identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"KB2040\"\n\tusb_STRING_MANUFACTURER = \"Adafruit\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x8106\n)\n"
  },
  {
    "path": "src/machine/board_lgt92.go",
    "content": "//go:build lgt92\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/interrupt\"\n)\n\nconst (\n\tLED1 = PA12\n\tLED2 = PA8\n\tLED3 = PA11\n\n\tLED_RED   = LED1\n\tLED_BLUE  = LED2\n\tLED_GREEN = LED3\n\n\t// Default led\n\tLED = LED1\n\n\tBUTTON = PB14\n\n\t// LG GPS module\n\tGPS_STANDBY_PIN = PB3\n\tGPS_RESET_PIN   = PB4\n\tGPS_POWER_PIN   = PB5\n\n\tMEMS_ACCEL_CS   = PE3\n\tMEMS_ACCEL_INT1 = PE0\n\tMEMS_ACCEL_INT2 = PE1\n\n\t// SPI\n\tSPI1_SCK_PIN = PA5\n\tSPI1_SDI_PIN = PA6\n\tSPI1_SDO_PIN = PA7\n\tSPI0_SCK_PIN = SPI1_SCK_PIN\n\tSPI0_SDI_PIN = SPI1_SDI_PIN\n\tSPI0_SDO_PIN = SPI1_SDO_PIN\n\n\t// LORA RFM95 Radio\n\tRFM95_DIO0_PIN = PC13\n\n\t// TinyGo UART is MCU LPUSART1\n\tUART_RX_PIN = PA13\n\tUART_TX_PIN = PA14\n\n\t// TinyGo UART1 is MCU USART1\n\tUART1_RX_PIN = PB6\n\tUART1_TX_PIN = PB7\n\n\t// MPU9250 Nine-Axis (Gyro + Accelerometer + Compass)\n\tI2C0_SCL_PIN = PA9\n\tI2C0_SDA_PIN = PA10\n)\n\nvar DefaultUART = UART0\n\nvar (\n\n\t// Console UART (LPUSART1)\n\tUART0  = &_UART0\n\t_UART0 = UART{\n\t\tBuffer:            NewRingBuffer(),\n\t\tBus:               stm32.LPUART1,\n\t\tTxAltFuncSelector: 6,\n\t\tRxAltFuncSelector: 6,\n\t}\n\n\t// Gps UART\n\tUART1  = &_UART1\n\t_UART1 = UART{\n\t\tBuffer:            NewRingBuffer(),\n\t\tBus:               stm32.USART1,\n\t\tTxAltFuncSelector: 0,\n\t\tRxAltFuncSelector: 0,\n\t}\n\n\t// MPU9250 Nine-Axis (Gyro + Accelerometer + Compass)\n\tI2C1 = &I2C{\n\t\tBus:             stm32.I2C1,\n\t\tAltFuncSelector: 6,\n\t}\n\tI2C0 = I2C1\n\n\t// SPI\n\tSPI0 = &SPI{\n\t\tBus: stm32.SPI1,\n\t}\n\tSPI1 = SPI0\n)\n\nfunc init() {\n\t// Enable UARTs Interrupts\n\tUART0.Interrupt = interrupt.New(stm32.IRQ_AES_RNG_LPUART1, _UART0.handleInterrupt)\n\tUART1.Interrupt = interrupt.New(stm32.IRQ_USART1, _UART1.handleInterrupt)\n}\n"
  },
  {
    "path": "src/machine/board_lorae5.go",
    "content": "//go:build lorae5\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/interrupt\"\n)\n\nconst (\n\t// We assume a LED is connected on PB5\n\tLED = PB5 // Default LED\n\n\t// Set the POWER_EN3V3 pin to high to turn\n\t// on the 3.3V power for all peripherals\n\tPOWER_EN3V3 = PA9\n\n\t// Set the POWER_EN5V pin to high to turn\n\t// on the 5V bus power for all peripherals\n\tPOWER_EN5V = PB10\n)\n\n// SubGhz (SPI3)\nconst (\n\tSPI0_NSS_PIN = PA4\n\tSPI0_SCK_PIN = PA5\n\tSPI0_SDO_PIN = PA6\n\tSPI0_SDI_PIN = PA7\n)\n\n// UARTS\nconst (\n\t// MCU USART1\n\tUART1_TX_PIN = PB6\n\tUART1_RX_PIN = PB7\n\n\t// MCU USART2\n\tUART2_TX_PIN = PA2\n\tUART2_RX_PIN = PA3\n\n\t// DEFAULT USART\n\tUART_TX_PIN = UART1_TX_PIN\n\tUART_RX_PIN = UART1_RX_PIN\n\n\t// I2C2 pins\n\tI2C2_SCL_PIN  = PB15\n\tI2C2_SDA_PIN  = PA15\n\tI2C2_ALT_FUNC = 4\n\n\t// I2C0 alias for I2C2\n\tI2C0_SDA_PIN = I2C2_SDA_PIN\n\tI2C0_SCL_PIN = I2C2_SCL_PIN\n)\n\nvar (\n\t// Console UART\n\tUART0  = &_UART0\n\t_UART0 = UART{\n\t\tBuffer:            NewRingBuffer(),\n\t\tBus:               stm32.USART1,\n\t\tTxAltFuncSelector: AF7_USART1_2,\n\t\tRxAltFuncSelector: AF7_USART1_2,\n\t}\n\tDefaultUART = UART0\n\n\t// Since we treat UART1 as zero, let's also call it by the real name\n\tUART1 = UART0\n\n\t// UART2\n\tUART2  = &_UART2\n\t_UART2 = UART{\n\t\tBuffer:            NewRingBuffer(),\n\t\tBus:               stm32.USART2,\n\t\tTxAltFuncSelector: AF7_USART1_2,\n\t\tRxAltFuncSelector: AF7_USART1_2,\n\t}\n\n\t// I2C Busses\n\tI2C2 = &I2C{\n\t\tBus:             stm32.I2C2,\n\t\tAltFuncSelector: I2C2_ALT_FUNC,\n\t}\n\n\t// Set \"default\" I2C bus to I2C2\n\tI2C0 = I2C2\n\n\t// SPI\n\tSPI3 = &SPI{\n\t\tBus: stm32.SPI3,\n\t}\n)\n\nfunc init() {\n\t// Enable UARTs Interrupts\n\tUART0.Interrupt = interrupt.New(stm32.IRQ_USART1, _UART0.handleInterrupt)\n\tUART2.Interrupt = interrupt.New(stm32.IRQ_USART2, _UART2.handleInterrupt)\n}\n"
  },
  {
    "path": "src/machine/board_m5paper.go",
    "content": "//go:build m5paper\n\npackage machine\n\nconst (\n\tIO0  = GPIO0\n\tIO1  = GPIO1\n\tIO2  = GPIO2\n\tIO3  = GPIO3\n\tIO4  = GPIO4\n\tIO5  = GPIO5\n\tIO6  = GPIO6\n\tIO7  = GPIO7\n\tIO8  = GPIO8\n\tIO9  = GPIO9\n\tIO10 = GPIO10\n\tIO11 = GPIO11\n\tIO12 = GPIO12\n\tIO13 = GPIO13\n\tIO14 = GPIO14\n\tIO15 = GPIO15\n\tIO16 = GPIO16\n\tIO17 = GPIO17\n\tIO18 = GPIO18\n\tIO19 = GPIO19\n\tIO21 = GPIO21\n\tIO22 = GPIO22\n\tIO23 = GPIO23\n\tIO25 = GPIO25\n\tIO26 = GPIO26\n\tIO27 = GPIO27\n\tIO32 = GPIO32\n\tIO33 = GPIO33\n\tIO34 = GPIO34\n\tIO35 = GPIO35\n\tIO36 = GPIO36\n\tIO37 = GPIO37\n\tIO38 = GPIO38\n\tIO39 = GPIO39\n)\n\nconst (\n\tPOWER_PIN     = IO2\n\tEXT_POWER_PIN = IO5\n\tEPD_POWER_PIN = IO23\n\n\t// Buttons\n\tBUTTON_RIGHT = IO39\n\tBUTTON_PUSH  = IO38\n\tBUTTON_LEFT  = IO37\n\tBUTTON       = BUTTON_PUSH\n\n\t// Touch Screen Interrupt\n\tTOUCH_INT = IO36\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = IO14\n\tSPI0_SDO_PIN = IO12\n\tSPI0_SDI_PIN = IO13\n\n\t// EPD (IT8951)\n\tEPD_SCK_PIN  = SPI0_SCK_PIN\n\tEPD_SDO_PIN  = SPI0_SDO_PIN\n\tEPD_SDI_PIN  = SPI0_SDI_PIN\n\tEPD_CS_PIN   = IO15\n\tEPD_BUSY_PIN = IO27\n\n\t// SD CARD\n\tSDCARD_SCK_PIN = SPI0_SCK_PIN\n\tSDCARD_SDO_PIN = SPI0_SDO_PIN\n\tSDCARD_SDI_PIN = SPI0_SDI_PIN\n\tSDCARD_CS_PIN  = IO4\n)\n\n// I2C pins\nconst (\n\tSDA0_PIN = IO21\n\tSCL0_PIN = IO22\n\n\tSDA_PIN = SDA0_PIN\n\tSCL_PIN = SCL0_PIN\n\n\tI2C_TEMP_ADDR  = 0x44 // temperature sensor (SHT30)\n\tI2C_CLOCK_ADDR = 0x51 // real time clock (BM8563)\n\tI2C_TOUCH_ADDR = 0x5D // touch screen controller (GT911)\n)\n\n// ADC pins\nconst (\n\tADC1 Pin = IO35\n\tADC2 Pin = IO36\n\n\tBATTERY_ADC_PIN = ADC1\n)\n\n// DAC pins\nconst (\n\tDAC1 Pin = IO25\n\tDAC2 Pin = IO26\n)\n\n// UART pins\nconst (\n\t// UART0 (CP2104)\n\tUART0_TX_PIN = IO1\n\tUART0_RX_PIN = IO3\n\n\tUART_TX_PIN = UART0_TX_PIN\n\tUART_RX_PIN = UART0_RX_PIN\n)\n"
  },
  {
    "path": "src/machine/board_m5stack.go",
    "content": "//go:build m5stack\n\npackage machine\n\nconst (\n\t//     GND     | ADC     G35\n\t//     GND     | ADC     G36\n\t//     GND     | RST     EN\n\t// G23 MOSI    | DAC/SPK G25\n\t// G19 MISO    | DAC     G26\n\t// G18 SCK     | 3.3V\n\t// G3  RXD1    | TXD1    G1\n\t// G16 RXD2    | TXD2    G17\n\t// G21 SDA     | DCL     G22\n\t// G2  GPIO    | GPIO    G5\n\t// G12 IIS_SK  | IIS_WS  G13\n\t// G15 IIS_OUT | IIS_MK  G0\n\t//     HPWR    | IIS_IN  G34\n\t//     HPWR    | 5V\n\t//     HPWR    | BATTERY\n\n\tIO0  = GPIO0\n\tIO1  = GPIO1\n\tIO2  = GPIO2\n\tIO3  = GPIO3\n\tIO4  = GPIO4\n\tIO5  = GPIO5\n\tIO6  = GPIO6\n\tIO7  = GPIO7\n\tIO8  = GPIO8\n\tIO9  = GPIO9\n\tIO10 = GPIO10\n\tIO11 = GPIO11\n\tIO12 = GPIO12\n\tIO13 = GPIO13\n\tIO14 = GPIO14\n\tIO15 = GPIO15\n\tIO16 = GPIO16\n\tIO17 = GPIO17\n\tIO18 = GPIO18\n\tIO19 = GPIO19\n\tIO21 = GPIO21\n\tIO22 = GPIO22\n\tIO23 = GPIO23\n\tIO25 = GPIO25\n\tIO26 = GPIO26\n\tIO27 = GPIO27\n\tIO32 = GPIO32\n\tIO33 = GPIO33\n\tIO34 = GPIO34\n\tIO35 = GPIO35\n\tIO36 = GPIO36\n\tIO37 = GPIO37\n\tIO38 = GPIO38\n\tIO39 = GPIO39\n)\n\nconst (\n\t// Buttons\n\tBUTTON_A = IO39\n\tBUTTON_B = IO38\n\tBUTTON_C = IO37\n\tBUTTON   = BUTTON_A\n\n\t// Speaker\n\tSPEAKER_PIN = IO25\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = IO18\n\tSPI0_SDO_PIN = IO23\n\tSPI0_SDI_PIN = IO19\n\tSPI0_CS0_PIN = IO14\n\n\t// LCD (ILI9342C)\n\tLCD_SCK_PIN = SPI0_SCK_PIN\n\tLCD_SDO_PIN = SPI0_SDO_PIN\n\tLCD_SDI_PIN = SPI0_SDI_PIN // NoPin ?\n\tLCD_SS_PIN  = SPI0_CS0_PIN\n\tLCD_DC_PIN  = IO27\n\tLCD_RST_PIN = IO33\n\tLCD_BL_PIN  = IO32\n\n\t// SD CARD\n\tSDCARD_SCK_PIN = SPI0_SCK_PIN\n\tSDCARD_SDO_PIN = SPI0_SDO_PIN\n\tSDCARD_SDI_PIN = SPI0_SDI_PIN\n\tSDCARD_SS_PIN  = IO4\n)\n\n// I2C pins\nconst (\n\tSDA0_PIN = IO21\n\tSCL0_PIN = IO22\n\n\tSDA_PIN = SDA0_PIN\n\tSCL_PIN = SCL0_PIN\n)\n\n// ADC pins\nconst (\n\tADC1 Pin = IO35\n\tADC2 Pin = IO36\n)\n\n// DAC pins\nconst (\n\tDAC1 Pin = IO25\n\tDAC2 Pin = IO26\n)\n\n// UART pins\nconst (\n\t// UART0 (CP2104)\n\tUART0_TX_PIN = IO1\n\tUART0_RX_PIN = IO3\n\n\tUART1_TX_PIN = IO17\n\tUART1_RX_PIN = IO16\n\n\tUART_TX_PIN = UART0_TX_PIN\n\tUART_RX_PIN = UART0_RX_PIN\n)\n"
  },
  {
    "path": "src/machine/board_m5stack_core2.go",
    "content": "//go:build m5stack_core2\n\npackage machine\n\nconst (\n\t//     GND      | ADC       G35\n\t//     GND      | ADC       G36\n\t//     GND      | RST       EN\n\t// G23 MOSI     | DAC       G25\n\t// G38 MISO     | DAC       G26\n\t// G18 SCK      | 3.3V\n\t// G3  RXD0     | TXD0      G1\n\t// G13 RXD2     | TXD2      G14\n\t// G21 intSDA   | intSC     G22\n\t// G32 PA_SDA   | PA_SCL     G33\n\t// G27 GPIO     | GPIO      G19\n\t// G2  I2S_DOUT | I2S_LRCKC G0\n\t//     N/C      | PDM_DAT   G34\n\t//     N/C      | 5V\n\t//     N/C      | BAT\n\n\tIO0  = GPIO0\n\tIO1  = GPIO1 // U0TXD\n\tIO2  = GPIO2\n\tIO3  = GPIO3 // U0RXD\n\tIO4  = GPIO4\n\tIO5  = GPIO5\n\tIO6  = GPIO6  // SD_CLK\n\tIO7  = GPIO7  // SD_DATA0\n\tIO8  = GPIO8  // SD_DATA1\n\tIO9  = GPIO9  // SD_DATA2\n\tIO10 = GPIO10 // SD_DATA3\n\tIO11 = GPIO11 // SD_CMD\n\tIO12 = GPIO12\n\tIO13 = GPIO13 // U0RXD\n\tIO14 = GPIO14 // U1TXD\n\tIO15 = GPIO15\n\tIO16 = GPIO16\n\tIO17 = GPIO17\n\tIO18 = GPIO18 // SPI0_SCK\n\tIO19 = GPIO19\n\tIO21 = GPIO21 // SDA0\n\tIO22 = GPIO22 // SCL0\n\tIO23 = GPIO23 // SPI0_SDO\n\tIO25 = GPIO25\n\tIO26 = GPIO26\n\tIO27 = GPIO27\n\tIO32 = GPIO32 // SDA1\n\tIO33 = GPIO33 // SCL1\n\tIO34 = GPIO34\n\tIO35 = GPIO35 // ADC1\n\tIO36 = GPIO36 // ADC2\n\tIO38 = GPIO38 // SPI0_SDI\n\tIO39 = GPIO39\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = IO18\n\tSPI0_SDO_PIN = IO23\n\tSPI0_SDI_PIN = IO38\n\tSPI0_CS0_PIN = IO5\n\n\t// LCD (ILI9342C)\n\tLCD_SCK_PIN = SPI0_SCK_PIN\n\tLCD_SDO_PIN = SPI0_SDO_PIN\n\tLCD_SDI_PIN = SPI0_SDI_PIN\n\tLCD_SS_PIN  = SPI0_CS0_PIN\n\tLCD_DC_PIN  = IO15\n\n\t// SD CARD\n\tSDCARD_SCK_PIN = SPI0_SCK_PIN\n\tSDCARD_SDO_PIN = SPI0_SDO_PIN\n\tSDCARD_SDI_PIN = SPI0_SDI_PIN\n\tSDCARD_SS_PIN  = IO4\n)\n\n// I2C pins\nconst (\n\t// Internal I2C (AXP192 / FT6336U / BM8563 / MPU6886)\n\tSDA0_PIN = IO21\n\tSCL0_PIN = IO22\n\n\t// External I2C (PORT A)\n\tSDA1_PIN = IO32\n\tSCL1_PIN = IO33\n\n\tSDA_PIN = SDA1_PIN\n\tSCL_PIN = SCL1_PIN\n)\n\n// ADC pins\nconst (\n\tADC1 Pin = IO35\n\tADC2 Pin = IO36\n)\n\n// DAC pins\nconst (\n\tDAC1 Pin = IO25\n\tDAC2 Pin = IO26\n)\n\n// UART pins\nconst (\n\t// UART0 (CP2104)\n\tUART0_TX_PIN = IO1\n\tUART0_RX_PIN = IO3\n\n\tUART1_TX_PIN = IO14\n\tUART1_RX_PIN = IO13\n\n\tUART_TX_PIN = UART0_TX_PIN\n\tUART_RX_PIN = UART0_RX_PIN\n)\n"
  },
  {
    "path": "src/machine/board_m5stamp_c3.go",
    "content": "//go:build m5stamp_c3\n\npackage machine\n\nconst (\n\tIO0  = GPIO0\n\tIO1  = GPIO1\n\tIO2  = GPIO2\n\tIO3  = GPIO3\n\tIO4  = GPIO4\n\tIO5  = GPIO5\n\tIO6  = GPIO6\n\tIO7  = GPIO7\n\tIO8  = GPIO8\n\tIO9  = GPIO9\n\tIO10 = GPIO10\n\tIO11 = GPIO11\n\tIO12 = GPIO12\n\tIO13 = GPIO13\n\tIO14 = GPIO14\n\tIO15 = GPIO15\n\tIO16 = GPIO16\n\tIO17 = GPIO17\n\tIO18 = GPIO18\n\tIO19 = GPIO19\n\tIO20 = GPIO20\n\tIO21 = GPIO21\n\n\tXTAL_32K_P = IO0\n\tXTAL_32K_N = IO1\n\tMTMS       = IO4\n\tMTDI       = IO5\n\tMTCK       = IO6\n\tMTDO       = IO7\n\tVDD_SPI    = IO11\n\tSPIHD      = IO12\n\tSPISP      = IO13\n\tSPICS0     = IO14\n\tSPICLK     = IO15\n\tSPID       = IO16\n\tSPIQ       = IO17\n\tU0RXD      = IO20\n\tU0TXD      = IO21\n\n\tUART_TX_PIN = U0TXD\n\tUART_RX_PIN = U0RXD\n)\n\nconst (\n\tWS2812 = IO2\n)\n"
  },
  {
    "path": "src/machine/board_m5stick_c.go",
    "content": "//go:build m5stick_c\n\n// This file contains the pin mapping for the M5STACK M5Stick-C device.\n// doc: https://docs.m5stack.com/en/core/m5stickc\n\npackage machine\n\nconst (\n\t// HAT     | HY2.0-4P\n\t//         |\n\t// GND     | GND\n\t// 5V OUT  | VOUT\n\t// G26     | G32   SDA\n\t// G36     | G33   SCL\n\t// G0      |\n\t// BAT     |\n\t// 3V3     |\n\t// 5V IN   |\n\n\tIO0  = GPIO0 // CLK\n\tIO1  = GPIO1 // U0TXD\n\tIO2  = GPIO2\n\tIO3  = GPIO3 // U0RXD\n\tIO4  = GPIO4\n\tIO5  = GPIO5 // TFT_CS LCD_SS SPI0_SS\n\tIO6  = GPIO6\n\tIO7  = GPIO7\n\tIO8  = GPIO8\n\tIO9  = GPIO9  // IR\n\tIO10 = GPIO10 // LED\n\tIO11 = GPIO11\n\tIO12 = GPIO12\n\tIO13 = GPIO13 // TFT_CLK  LCD_SCK  SPI0_SCK\n\tIO14 = GPIO14\n\tIO15 = GPIO15 // TFT_MOSI LCD_MOSI SPI0_MOSI\n\tIO16 = GPIO16\n\tIO17 = GPIO17\n\tIO18 = GPIO18 // TFT_RST LCD_RST\n\tIO19 = GPIO19\n\tIO21 = GPIO21 // SDA0\n\tIO22 = GPIO22 // SCL0\n\tIO23 = GPIO23 // TFT_DC LCD_DC\n\tIO25 = GPIO25 // -   DAC1\n\tIO26 = GPIO26 // HAT DAC2\n\tIO27 = GPIO27\n\tIO32 = GPIO32 // SDA1 / PIN 32 / RXD2\n\tIO33 = GPIO33 // SCL1 / PIN 33 / TXD2\n\tIO34 = GPIO34 // MIC_DATA\n\tIO35 = GPIO35 // IRQ0   ADC1\n\tIO36 = GPIO36 // HAT    ADC2  LCD_MISO SPI0_MISO\n\tIO37 = GPIO37 // BUTTON_A, BUTTON_HOME, BUTTON\n\tIO38 = GPIO38\n\tIO39 = GPIO39 // BUTTON_B, BUTTON_RST\n)\n\nconst (\n\t// Buttons\n\tBUTTON_A    = IO37\n\tBUTTON_B    = IO39\n\tBUTTON_HOME = BUTTON_A\n\tBUTTON_RST  = BUTTON_B\n\tBUTTON      = BUTTON_A\n\n\t// LED\n\tIR  = IO9\n\tLED = IO10\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = IO13\n\tSPI0_SDO_PIN = IO15\n\tSPI0_CS0_PIN = IO5\n\n\t// LCD ()\n\tLCD_SCK_PIN = SPI0_SCK_PIN\n\tLCD_SDO_PIN = SPI0_SDO_PIN\n\tLCD_SS_PIN  = SPI0_CS0_PIN\n\tLCD_DC_PIN  = IO23\n\tLCD_RST_PIN = IO18\n)\n\n// I2C pins\nconst (\n\t// Internal I2C (AXP192 / BM8563 / MPU6886)\n\tSDA0_PIN = IO21\n\tSCL0_PIN = IO22\n\n\t// External I2C (GROOVE PORT)\n\tSDA1_PIN = IO32\n\tSCL1_PIN = IO33\n\n\tSDA_PIN = SDA1_PIN\n\tSCL_PIN = SCL1_PIN\n)\n\n// ADC pins\nconst (\n\tADC1 Pin = IO35\n\tADC2 Pin = IO36\n)\n\n// DAC pins\nconst (\n\tDAC1 Pin = IO25\n\tDAC2 Pin = IO26\n)\n\n// UART pins\nconst (\n\t// UART0 (CP2104)\n\tUART0_TX_PIN = IO1\n\tUART0_RX_PIN = IO3\n\n\tUART_TX_PIN = UART0_TX_PIN\n\tUART_RX_PIN = UART0_RX_PIN\n)\n"
  },
  {
    "path": "src/machine/board_macropad-rp2040.go",
    "content": "//go:build macropad_rp2040\n\npackage machine\n\nconst (\n\tNeopixelCount = 12\n\n\t// Onboard crystal oscillator frequency, in MHz.\n\txoscFreq = 12 // MHz\n)\n\nconst (\n\tSWITCH = GPIO0\n\tBUTTON = GPIO0\n\n\tKEY1  = GPIO1\n\tKEY2  = GPIO2\n\tKEY3  = GPIO3\n\tKEY4  = GPIO4\n\tKEY5  = GPIO5\n\tKEY6  = GPIO6\n\tKEY7  = GPIO7\n\tKEY8  = GPIO8\n\tKEY9  = GPIO9\n\tKEY10 = GPIO10\n\tKEY11 = GPIO11\n\tKEY12 = GPIO12\n\n\tLED = GPIO13\n\n\tSPEAKER_ENABLE = GPIO14\n\tSPEAKER        = GPIO16\n\n\tROT_A = GPIO18\n\tROT_B = GPIO17\n\n\tOLED_CS  = GPIO22\n\tOLED_RST = GPIO23\n\tOLED_DC  = GPIO24\n\n\tNEOPIXEL = GPIO19\n\tWS2812   = NEOPIXEL\n)\n\n// I2C Default pins on Raspberry Pico.\nconst (\n\tI2C0_SDA_PIN = GPIO20\n\tI2C0_SCL_PIN = GPIO21\n\n\tI2C1_SDA_PIN = NoPin // not pinned out\n\tI2C1_SCL_PIN = NoPin // not pinned out\n)\n\n// SPI default pins\nconst (\n\t// Default Serial Clock Bus 1 for SPI communications\n\tSPI1_SCK_PIN = GPIO26\n\t// Default Serial Out Bus 1 for SPI communications\n\tSPI1_SDO_PIN = GPIO27 // Tx\n\t// Default Serial In Bus 1 for SPI communications\n\tSPI1_SDI_PIN = GPIO28 // Rx\n\n\tSPI0_SCK_PIN = NoPin // not pinned out\n\tSPI0_SDO_PIN = NoPin // not pinned out\n\tSPI0_SDI_PIN = NoPin // not pinned out\n)\n\n// UART pins\nconst (\n\tUART0_TX_PIN = GPIO0\n\tUART0_RX_PIN = GPIO1\n\tUART_TX_PIN  = UART0_TX_PIN\n\tUART_RX_PIN  = UART0_RX_PIN\n)\n\nvar DefaultUART = UART0\n\n// USB identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"MacroPad RP2040\"\n\tusb_STRING_MANUFACTURER = \"Adafruit\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x8107\n)\n"
  },
  {
    "path": "src/machine/board_maixbit.go",
    "content": "//go:build maixbit\n\npackage machine\n\n// Pins on the MAix Bit.\nconst (\n\tD0  = P00 // JTAG_TCLK\n\tD1  = P01 // JTAG_TDI\n\tD2  = P02 // JTAG_TMS\n\tD3  = P03 // JTAG_TDO\n\tD4  = P04 // UARTHS_RX\n\tD5  = P05 // UARTHS_TX\n\tD6  = P06 // RESV0\n\tD7  = P07 // RESV0\n\tD8  = P08 // GPIO1\n\tD9  = P09 // GPIO2\n\tD10 = P10 // GPIO3\n\tD11 = P11 // GPIO4\n\tD12 = P12 // GPIO5\n\tD13 = P13 // GPIO6\n\tD14 = P14 // GPIO7\n\tD15 = P15 // GPIO8\n\tD16 = P16 // GPIOHS0\n\tD17 = P17 // GPIOHS1\n\tD18 = P18 // GPIOHS2\n\tD19 = P19 // GPIOHS3\n\tD20 = P20 // GPIOHS4\n\tD21 = P21 // GPIOHS5\n\tD22 = P22 // GPIOHS6\n\tD23 = P23 // GPIOHS7\n\tD24 = P24 // GPIOHS8\n\tD25 = P25 // GPIOHS9\n\tD26 = P26 // GPIOHS10 / SPI0_SDI\n\tD27 = P27 // GPIOHS11 / SPI0_SCLK\n\tD28 = P28 // GPIOHS12 / SPI0_SDO\n\tD29 = P29 // GPIOHS13\n\tD30 = P30 // GPIOHS14\n\tD31 = P31 // GPIOHS15\n\tD32 = P32 // GPIOHS16\n\tD33 = P33 // GPIOHS17\n\tD34 = P34 // GPIOHS18\n\tD35 = P35 // GPIOHS19\n)\n\nconst (\n\tLED       = LED1\n\tLED1      = LED_RED\n\tLED2      = LED_GREEN\n\tLED3      = LED_BLUE\n\tLED_RED   = D13\n\tLED_GREEN = D12\n\tLED_BLUE  = D14\n)\n\nvar DefaultUART = UART0\n\n// Default pins for UARTHS.\nconst (\n\tUART_TX_PIN = D5\n\tUART_RX_PIN = D4\n)\n\n// SPI pins.\nconst (\n\tSPI0_SCK_PIN = D27\n\tSPI0_SDO_PIN = D28\n\tSPI0_SDI_PIN = D26\n)\n\n// I2C pins.\nconst (\n\tI2C0_SDA_PIN = D34\n\tI2C0_SCL_PIN = D35\n)\n"
  },
  {
    "path": "src/machine/board_maixbit_baremetal.go",
    "content": "//go:build k210 && maixbit\n\npackage machine\n\nimport \"device/kendryte\"\n\n// SPI on the MAix Bit.\nvar (\n\tSPI0 = &SPI{\n\t\tBus: kendryte.SPI0,\n\t}\n\tSPI1 = &SPI{\n\t\tBus: kendryte.SPI1,\n\t}\n)\n"
  },
  {
    "path": "src/machine/board_makerfabs-esp32c3spi35.go",
    "content": "//go:build makerfabs_esp32c3spi35\n\n// This file contains the pin mappings for the Makerfabs ESP32C3SPI35 board.\n//\n// The Makerfabs ESP32C3SPI35 is an LCD Touchscreen development board powered\n// by the Espressif ESP32-C3 SoC featuring an open-source RISC-V architecture.\n//\n// Specifications:\n//   SoC: ESP32-C3-MINI-1-N4, 4MB Flash, RISCV-32bit, 160MHz, 400KB SRAM\n//   Wireless: WiFi & Bluetooth 5.0 (BLE)\n//   LCD: 3.5inch TFT LCD (480x320)\n//   LCD Driver: ILI9488 SPI\n//   Touch Panel: Capacitive\n//   Touch Panel Driver: FT6236\n//   MicroSD Card Slot\n//   Mabee Interface\n//   Dual USB Type-C (one for USB-to-UART and one for native USB)\n//\n// Website:   https://www.makerfabs.com/ep32-c3-risc-v-spi-tft-touch.html\n// Wiki:      https://wiki.makerfabs.com/ESP32_C3_SPI_3.5_TFT_with_Touch.html\n// GitHub:    https://github.com/Makerfabs/Makerfabs-ESP32-C3-SPI-TFT-with-Touch\n// Schematic: https://github.com/Makerfabs/Makerfabs-ESP32-C3-SPI-TFT-with-Touch/raw/main/Hardware/ESP32-C3%20TFT%20Touch%20v1.1(3.5''%20ili9488).PDF\n// Datasheet: https://www.espressif.com/sites/default/files/documentation/esp32-c3-mini-1_datasheet_en.pdf\n\npackage machine\n\n// Digital pins\nconst (\n\t//    Pin    // Function\n\t//    -----  // ---------------------\n\tD0  = GPIO0  // Touchscreen CS\n\tD1  = GPIO1  // MicroSD CS\n\tD2  = GPIO2  // I2C SDA\n\tD3  = GPIO3  // I2C SCL\n\tD4  = GPIO4  // SPI CS\n\tD5  = GPIO5  // SPI SCK\n\tD6  = GPIO6  // SPI SDO\n\tD7  = GPIO7  // SPI SDI\n\tD8  = GPIO8  // Touchscreen Backlight\n\tD9  = GPIO9  // Boot Button\n\tD10 = GPIO10 // TFT D/C\n\tD18 = GPIO18 // USB DM\n\tD19 = GPIO19 // USB DP\n\tD20 = GPIO20 // UART RX\n\tD21 = GPIO21 // UART TX\n)\n\n// Button pin\nconst (\n\tBUTTON      = BUTTON_BOOT\n\tBUTTON_BOOT = D9\n)\n\n// TFT pins\nconst (\n\tTFT_BL_PIN  = D8\n\tTFT_CS_PIN  = SPI_CS_PIN\n\tTFT_DC_PIN  = D10\n\tTFT_SCK_PIN = SPI_SCK_PIN\n\tTFT_SDI_PIN = SPI_SDI_PIN\n\tTFT_SDO_PIN = SPI_SDO_PIN\n)\n\n// Touchscreen pins\nconst (\n\tTS_CS_PIN  = D0\n\tTS_SDA_PIN = SDA_PIN\n\tTS_SCL_PIN = SCL_PIN\n)\n\n// MicroSD pins\nconst (\n\tSD_CS_PIN  = D1\n\tSD_SCK_PIN = SPI_SCK_PIN\n\tSD_SDI_PIN = SPI_SDI_PIN\n\tSD_SDO_PIN = SPI_SDO_PIN\n)\n\n// USBCDC pins\nconst (\n\tUSBCDC_DM_PIN = D18\n\tUSBCDC_DP_PIN = D19\n)\n\n// UART pins\nconst (\n\tUART_RX_PIN = D20\n\tUART_TX_PIN = D21\n)\n\n// I2C pins\nconst (\n\tSDA_PIN = D2\n\tSCL_PIN = D3\n)\n\n// SPI pins\nconst (\n\tSPI_CS_PIN  = D4\n\tSPI_SCK_PIN = D5\n\tSPI_SDI_PIN = D7\n\tSPI_SDO_PIN = D6\n)\n"
  },
  {
    "path": "src/machine/board_matrixportal-m4.go",
    "content": "//go:build matrixportal_m4\n\npackage machine\n\n// used to reset into bootloader\nconst resetMagicValue = 0xF01669EF\n\n// Digital pins\nconst (\n\t//    Pin   // Function          SERCOM  PWM  Interrupt\n\t//    ----  // ----------------  ------  ---  ---------\n\tD0  = PA01  // UART RX            1[1]   PWM  EXTI1\n\tD1  = PA00  // UART TX            1[0]   PWM  EXTI0\n\tD2  = PB22  // Button \"Up\"                    EXTI6\n\tD3  = PB23  // Button \"Down\"                  EXTI7\n\tD4  = PA23  // NeoPixel                       EXTI7\n\tD5  = PB31  // I2C SDA            5[1]        EXTI15\n\tD6  = PB30  // I2C SCL            5[0]        EXTI14\n\tD7  = PB00  // HUB75 R1                       EXTI0\n\tD8  = PB01  // HUB75 G1                       EXTI1\n\tD9  = PB02  // HUB75 B1                       EXTI2\n\tD10 = PB03  // HUB75 R2                       EXTI3\n\tD11 = PB04  // HUB75 G2                       EXTI4\n\tD12 = PB05  // HUB75 B2                       EXTI5\n\tD13 = PA14  // LED                       PWM  EXTI14\n\tD14 = PB06  // HUB75 CLK                      EXTI6\n\tD15 = PB14  // HUB75 LAT                      EXTI14\n\tD16 = PB12  // HUB75 OE                       EXTI12\n\tD17 = PB07  // HUB75 ADDR A                   EXTI7\n\tD18 = PB08  // HUB75 ADDR B                   EXTI8\n\tD19 = PB09  // HUB75 ADDR C                   EXTI9\n\tD20 = PB15  // HUB75 ADDR D                   EXTI15\n\tD21 = PB13  // HUB75 ADDR E                   EXTI13\n\tD22 = PA02  // ADC (A0)                       EXTI2\n\tD23 = PA05  // ADC (A1)                       EXTI5\n\tD24 = PA04  // ADC (A2)                  PWM  EXTI4\n\tD25 = PA06  // ADC (A3)                  PWM  EXTI6\n\tD26 = PA07  // ADC (A4)                       EXTI7\n\tD27 = PA12  // ESP32 UART RX      4[1]   PWM  EXTI12\n\tD28 = PA13  // ESP32 UART TX      4[0]   PWM  EXTI13\n\tD29 = PA20  // ESP32 GPIO0               PWM  EXTI4\n\tD30 = PA21  // ESP32 Reset               PWM  EXTI5\n\tD31 = PA22  // ESP32 Busy                PWM  EXTI6\n\tD32 = PA18  // ESP32 RTS                 PWM  EXTI2\n\tD33 = PB17  // ESP32 SPI CS              PWM  EXTI1\n\tD34 = PA16  // ESP32 SPI SCK      3[1]   PWM  EXTI0\n\tD35 = PA17  // ESP32 SPI SDI      3[0]   PWM  EXTI1\n\tD36 = PA19  // ESP32 SPI SDO      1[3]   PWM  EXTI3\n\tD37 = NoPin // USB Host enable\n\tD38 = PA24  // USB DM\n\tD39 = PA25  // USB DP\n\tD40 = PA03  // DAC/VREFP\n\tD41 = PB10  // Flash QSPI SCK\n\tD42 = PB11  // Flash QSPI CS\n\tD43 = PA08  // Flash QSPI I00\n\tD44 = PA09  // Flash QSPI IO1\n\tD45 = PA10  // Flash QSPI IO2\n\tD46 = PA11  // Flash QSPI IO3\n\tD47 = PA27  // LIS3DH IRQ                     EXTI11\n\tD48 = PA05  // SPI SCK            0[1]        EXTI5\n\tD49 = PA04  // SPI SDO            0[0]   PWM  EXTI4\n\tD50 = PA07  // SPI SDI            0[3]        EXTI7\n)\n\n// Analog pins\nconst (\n\tA0 = PA02 // ADC Channel 0\n\tA1 = PA05 // ADC Channel 5\n\tA2 = PA04 // ADC Channel 4\n\tA3 = PA06 // ADC Channel 6\n\tA4 = PA07 // ADC Channel 7\n)\n\n// LED pins\nconst (\n\tLED      = D13\n\tNEOPIXEL = D4\n\tWS2812   = D4\n)\n\n// Button pins\nconst (\n\tBUTTON_UP   = D2\n\tBUTTON_DOWN = D3\n)\n\n// UART pins\nconst (\n\tUART1_RX_PIN = D0 // SERCOM1[1]\n\tUART1_TX_PIN = D1 // SERCOM1[0]\n\n\tUART2_RX_PIN = D27 // SERCOM4[1] (ESP32 RX)\n\tUART2_TX_PIN = D28 // SERCOM4[0] (ESP32 TX)\n\n\tUART_RX_PIN = UART1_RX_PIN\n\tUART_TX_PIN = UART1_TX_PIN\n)\n\n// UART on the MatrixPortal M4\nvar (\n\tUART1 = &sercomUSART1\n\tUART2 = &sercomUSART4\n\n\tDefaultUART = UART1\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = D34 // SERCOM3[1] (ESP32 SCK)\n\tSPI0_SDO_PIN = D36 // SERCOM1[3] (ESP32 SDO)\n\tSPI0_SDI_PIN = D35 // SERCOM3[0] (ESP32 SDI)\n\n\tSPI1_SCK_PIN = D48 // SERCOM0[1]\n\tSPI1_SDO_PIN = D49 // SERCOM0[0]\n\tSPI1_SDI_PIN = D50 // SERCOM0[3]\n\n\tSPI_SCK_PIN = SPI0_SCK_PIN\n\tSPI_SDO_PIN = SPI0_SDO_PIN\n\tSPI_SDI_PIN = SPI0_SDI_PIN\n)\n\n// I2C pins\nconst (\n\tI2C0_SDA_PIN = D5 // SERCOM5[1]\n\tI2C0_SCL_PIN = D6 // SERCOM5[0]\n\n\tI2C_SDA_PIN = I2C0_SDA_PIN\n\tI2C_SCL_PIN = I2C0_SCL_PIN\n\n\tSDA_PIN = I2C_SDA_PIN // awkward naming required by machine_atsamd51.go\n\tSCL_PIN = I2C_SCL_PIN //\n)\n\n// I2C on the MatrixPortal M4\nvar (\n\tI2C0 = sercomI2CM5\n)\n\n// ESP32 pins\nconst (\n\tNINA_ACK    = D31\n\tNINA_GPIO0  = D29\n\tNINA_RESETN = D30\n\n\tNINA_RX  = UART2_RX_PIN\n\tNINA_TX  = UART2_TX_PIN\n\tNINA_RTS = D32\n\n\tNINA_CS  = D33\n\tNINA_SDO = SPI0_SDO_PIN\n\tNINA_SDI = SPI0_SDI_PIN\n\tNINA_SCK = SPI0_SCK_PIN\n)\n\n// SPI on the MatrixPortal M4\nvar (\n\tSPI0     = sercomSPIM3 // BUG: SDO on SERCOM1!\n\tNINA_SPI = SPI0\n\n\tSPI1 = sercomSPIM0\n)\n\n// HUB75 pins\nconst (\n\tHUB75_R1 = D7\n\tHUB75_G1 = D8\n\tHUB75_B1 = D9\n\tHUB75_R2 = D10\n\tHUB75_G2 = D11\n\tHUB75_B2 = D12\n\n\tHUB75_CLK    = D14\n\tHUB75_LAT    = D15\n\tHUB75_OE     = D16\n\tHUB75_ADDR_A = D17\n\tHUB75_ADDR_B = D18\n\tHUB75_ADDR_C = D19\n\tHUB75_ADDR_D = D20\n\tHUB75_ADDR_E = D21\n)\n\n// USB CDC pins (UART0)\nconst (\n\tUSBCDC_DM_PIN = D38\n\tUSBCDC_DP_PIN = D39\n\n\tUART0_RX_PIN = USBCDC_DM_PIN\n\tUART0_TX_PIN = USBCDC_DP_PIN\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Matrix Portal M4\"\n\tusb_STRING_MANUFACTURER = \"Adafruit Industries\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x80C9\n)\n"
  },
  {
    "path": "src/machine/board_mch2022.go",
    "content": "//go:build mch2022\n\npackage machine\n\n// See: https://badge.team/docs/badges/mch2022/pinout/\n\nconst (\n\tUART_TX_PIN Pin = 1\n\tUART_RX_PIN Pin = 3\n\n\tWS2812 Pin = 5\n\n\tPowerOn Pin = 19 // Set high to enable power to LEDs and SD card\n\n\t// I2C pins\n\tSDA_PIN Pin = 22\n\tSCL_PIN Pin = 21\n\n\t// SPI and related pins (ICE40 and LCD).\n\tLCD_RESET         Pin = 25\n\tLCD_MODE          Pin = 26\n\tLCD_DC            Pin = 33\n\tSPI0_SCK_PIN      Pin = 18\n\tSPI0_SDO_PIN      Pin = 23\n\tSPI0_SDI_PIN      Pin = 35 // connected to ICE40\n\tSPI0_CS_ICE40_PIN Pin = 27\n\tSPI0_CS_LCD_PIN   Pin = 32\n)\n"
  },
  {
    "path": "src/machine/board_mdbt50qrx.go",
    "content": "//go:build mdbt50qrx\n\npackage machine\n\nconst HasLowFrequencyCrystal = false\n\n// GPIO Pins\nconst (\n\tD0 = P1_13 // LED1\n\tD1 = P1_11 // LED2 (not populated by default)\n\tD2 = P0_15 // Button\n)\n\nconst (\n\tLED = D0\n)\n\n// MDBT50Q-RX dongle does not have pins broken out for the peripherals below,\n// however the machine_nrf*.go implementations of I2C/SPI/etc expect the pin\n// constants to be defined, so we are defining them all as NoPin\nconst (\n\tUART_TX_PIN  = NoPin\n\tUART_RX_PIN  = NoPin\n\tSDA_PIN      = NoPin\n\tSCL_PIN      = NoPin\n\tSPI0_SCK_PIN = NoPin\n\tSPI0_SDO_PIN = NoPin\n\tSPI0_SDI_PIN = NoPin\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Raytac MDBT50Q - RX\"\n\tusb_STRING_MANUFACTURER = \"Raytac Corporation\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x810B\n)\n"
  },
  {
    "path": "src/machine/board_metro-m4-airlift.go",
    "content": "//go:build metro_m4_airlift\n\npackage machine\n\n// used to reset into bootloader\nconst resetMagicValue = 0xf01669ef\n\n// GPIO Pins\nconst (\n\tD0 = PA23 // UART0 RX/PWM available\n\tD1 = PA22 // UART0 TX/PWM available\n\tD2 = PB17 // PWM available\n\tD3 = PB16 // PWM available\n\tD4 = PB13 // PWM available\n\tD5 = PB14 // PWM available\n\tD6 = PB15 // PWM available\n\tD7 = PB12 // PWM available\n\n\tD8  = PA21 // PWM available\n\tD9  = PA20 // PWM available\n\tD10 = PA18 // can be used for PWM or UART1 TX\n\tD11 = PA19 // can be used for PWM or UART1 RX\n\tD12 = PA17 // PWM available\n\tD13 = PA16 // PWM available\n\n\tD40 = PB22 // built-in neopixel\n)\n\n// Analog pins\nconst (\n\tA0 = PA02 // ADC/AIN[0]\n\tA1 = PA05 // ADC/AIN[2]\n\tA2 = PB06 // ADC/AIN[3]\n\tA3 = PB00 // ADC/AIN[4] // NOTE: different between \"airlift\" and non-airlift versions\n\tA4 = PB08 // ADC/AIN[5]\n\tA5 = PB09 // ADC/AIN[10]\n)\n\nconst (\n\tLED    = D13\n\tWS2812 = D40\n)\n\n// USBCDC pins\nconst (\n\tUSBCDC_DM_PIN = PA24\n\tUSBCDC_DP_PIN = PA25\n)\n\nconst (\n\tUART_TX_PIN = D1\n\tUART_RX_PIN = D0\n)\n\nconst (\n\tUART2_TX_PIN = PA04\n\tUART2_RX_PIN = PA07\n)\n\nvar (\n\tUART1 = &sercomUSART3\n\tUART2 = &sercomUSART0\n\n\tDefaultUART = UART1\n\n\tUART_NINA = UART2\n)\n\n// NINA-W102 settings\nconst (\n\tNINA_BAUDRATE         = 115200\n\tNINA_RESET_INVERTED   = true\n\tNINA_SOFT_FLOWCONTROL = true\n)\n\nconst (\n\tNINA_CS     = PA15\n\tNINA_ACK    = PB04\n\tNINA_GPIO0  = PB01\n\tNINA_RESETN = PB05\n\n\t// pins used for the ESP32 connection do not allow hardware\n\t// flow control, which is required. have to emulate with software.\n\tNINA_TX  = PA04\n\tNINA_RX  = PA07\n\tNINA_CTS = NINA_ACK\n\tNINA_RTS = NINA_GPIO0\n)\n\n// I2C pins\nconst (\n\tSDA_PIN = PB02 // SDA: SERCOM5/PAD[0]\n\tSCL_PIN = PB03 // SCL: SERCOM5/PAD[1]\n)\n\n// I2C on the Metro M4.\nvar (\n\tI2C0 = sercomI2CM5\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = PA13 // SCK:  SERCOM2/PAD[1]\n\tSPI0_SDO_PIN = PA12 // SDO: SERCOM2/PAD[0]\n\tSPI0_SDI_PIN = PA14 // SDI: SERCOM2/PAD[2]\n\n\tNINA_SDO = SPI0_SDO_PIN\n\tNINA_SDI = SPI0_SDI_PIN\n\tNINA_SCK = SPI0_SCK_PIN\n)\n\nconst (\n\tSPI1_SCK_PIN = D12 // SDI: SERCOM1/PAD[1]\n\tSPI1_SDO_PIN = D11 // SDO: SERCOM1/PAD[3]\n\tSPI1_SDI_PIN = D13 // SCK:  SERCOM1/PAD[0]\n)\n\n// SPI on the Metro M4.\nvar (\n\tSPI0     = sercomSPIM2\n\tNINA_SPI = SPI0\n)\n\n// SPI1 on the Metro M4 on pins 11,12,13\nvar SPI1 = sercomSPIM1\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Adafruit Metro M4 Airlift Lite\"\n\tusb_STRING_MANUFACTURER = \"Adafruit\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x8037\n)\n"
  },
  {
    "path": "src/machine/board_metro_rp2350.go",
    "content": "//go:build metro_rp2350\n\npackage machine\n\n// GPIO pins\nconst (\n\tGP0  Pin = GPIO0\n\tGP1  Pin = GPIO1\n\tGP2  Pin = GPIO2\n\tGP3  Pin = GPIO3\n\tGP4  Pin = GPIO4\n\tGP5  Pin = GPIO5\n\tGP6  Pin = GPIO6\n\tGP7  Pin = GPIO7\n\tGP8  Pin = GPIO8\n\tGP9  Pin = GPIO9\n\tGP10 Pin = GPIO10\n\tGP11 Pin = GPIO11\n\tGP12 Pin = GPIO12\n\tGP13 Pin = GPIO13\n\tGP14 Pin = GPIO14\n\tGP15 Pin = GPIO15\n\tGP16 Pin = GPIO16\n\tGP17 Pin = GPIO17\n\tGP18 Pin = GPIO18\n\tGP19 Pin = GPIO19\n\tGP20 Pin = GPIO20\n\tGP21 Pin = GPIO21\n\tGP22 Pin = GPIO22\n\tGP23 Pin = GPIO23\n\tGP24 Pin = GPIO24\n\tGP25 Pin = GPIO25\n\tGP26 Pin = GPIO26\n\tGP27 Pin = GPIO27\n\tGP28 Pin = GPIO28\n\tGP29 Pin = GPIO29\n\tGP30 Pin = GPIO30\n\tGP31 Pin = GPIO31\n\tGP32 Pin = GPIO32\n\tGP33 Pin = GPIO33\n\tGP34 Pin = GPIO34\n\tGP35 Pin = GPIO35\n\tGP36 Pin = GPIO36\n\tGP37 Pin = GPIO37\n\tGP38 Pin = GPIO38\n\tGP39 Pin = GPIO39\n\tGP40 Pin = GPIO40\n\tGP41 Pin = GPIO41\n\tGP42 Pin = GPIO42\n\tGP43 Pin = GPIO43\n\tGP44 Pin = GPIO44\n\tGP45 Pin = GPIO45\n\tGP46 Pin = GPIO46\n\n\t// Boot button\n\tBUTTON Pin = GPIO24\n\n\t// Onboard LED\n\tLED Pin = GPIO23\n\n\t// Onboard NeoPixel\n\tNEOPIXEL Pin = GPIO25\n\tWS2812   Pin = GPIO25\n\n\t// Onboard crystal oscillator frequency, in MHz.\n\txoscFreq = 12 // MHz\n)\n\n// Arduino-header digital pins\nconst (\n\tRX  Pin = GPIO1\n\tTX  Pin = GPIO0\n\tD2  Pin = GPIO2\n\tD3  Pin = GPIO3\n\tD4  Pin = GPIO4\n\tD5  Pin = GPIO5\n\tD6  Pin = GPIO6\n\tD7  Pin = GPIO7\n\tD8  Pin = GPIO8\n\tD9  Pin = GPIO9\n\tD10 Pin = GPIO10\n\tD11 Pin = GPIO11\n\tD22 Pin = GPIO22\n\tD23 Pin = GPIO23\n)\n\n// Arduino-header analog pins\nconst (\n\tA0 Pin = GPIO41\n\tA1 Pin = GPIO42\n\tA2 Pin = GPIO43\n\tA3 Pin = GPIO44\n\tA4 Pin = GPIO45\n\tA5 Pin = GPIO46\n)\n\n// I2C Default pins on Raspberry Pico.\nconst (\n\tI2C0_SDA_PIN = GP20\n\tI2C0_SCL_PIN = GP21\n\n\tI2C1_SDA_PIN = GP2\n\tI2C1_SCL_PIN = GP3\n)\n\n// SPI default pins\nconst (\n\t// Default Serial Clock Bus 0 for SPI communications\n\tSPI0_SCK_PIN = GPIO18\n\t// Default Serial Out Bus 0 for SPI communications\n\tSPI0_SDO_PIN = GPIO19 // Tx\n\t// Default Serial In Bus 0 for SPI communications\n\tSPI0_SDI_PIN = GPIO16 // Rx\n\n\t// Default Serial Clock Bus 1 for SPI communications\n\tSPI1_SCK_PIN = GPIO30\n\t// Default Serial Out Bus 1 for SPI communications\n\tSPI1_SDO_PIN = GPIO31 // Tx\n\t// Default Serial In Bus 1 for SPI communications\n\tSPI1_SDI_PIN = GPIO28 // Rx\n\n\t// SPI header pins\n\tMOSI Pin = SPI1_SDO_PIN\n\tMISO Pin = SPI1_SDI_PIN\n\tSCK  Pin = SPI1_SCK_PIN\n)\n\n// SD card reader pins\nconst (\n\tSD_SCK         = GPIO34\n\tSD_MOSI        = GPIO35\n\tSD_MISO        = GPIO36\n\tSDIO_DATA1     = GPIO37\n\tSDIO_DATA2     = GPIO38\n\tSD_CS          = GPIO39\n\tSD_CARD_DETECT = GPIO40\n)\n\n// HSTX pins\nconst (\n\tCKN Pin = GPIO15\n\tCKP Pin = GPIO14\n\tD0N Pin = GPIO19\n\tD0P Pin = GPIO18\n\tD1N Pin = GPIO17\n\tD1P Pin = GPIO16\n\tD2N Pin = GPIO13\n\tD2P Pin = GPIO12\n\tD26 Pin = GPIO26\n\tD27 Pin = GPIO27\n\tSCL Pin = GPIO21\n\tSDA Pin = GPIO20\n)\n\n// USB host header pins\nconst (\n\tUSB_HOST_DATA_PLUS  Pin = GPIO32\n\tUSB_HOST_DATA_MINUS Pin = GPIO33\n\tUSB_HOST_5V_POWER   Pin = GPIO29\n)\n\n// UART pins\nconst (\n\tUART0_TX_PIN = GPIO0\n\tUART0_RX_PIN = GPIO1\n\tUART1_TX_PIN = GPIO8\n\tUART1_RX_PIN = GPIO9\n\tUART_TX_PIN  = UART0_TX_PIN\n\tUART_RX_PIN  = UART0_RX_PIN\n)\n\nvar DefaultUART = UART0\n\n// USB identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Metro RP2350\"\n\tusb_STRING_MANUFACTURER = \"Adafruit\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x814E\n)\n"
  },
  {
    "path": "src/machine/board_microbit-v2.go",
    "content": "//go:build microbit_v2\n\npackage machine\n\n// The micro:bit does not have a 32kHz crystal on board.\nconst HasLowFrequencyCrystal = false\n\n// Buttons on the micro:bit v2 (A and B)\nconst (\n\tBUTTON  Pin = BUTTONA\n\tBUTTONA Pin = P5\n\tBUTTONB Pin = P11\n)\n\nvar DefaultUART = UART0\n\n// UART pins\nconst (\n\tUART_TX_PIN Pin = P34\n\tUART_RX_PIN Pin = P33\n)\n\n// ADC pins\nconst (\n\tADC0 Pin = P0\n\tADC1 Pin = P1\n\tADC2 Pin = P2\n)\n\n// I2C0 (internal) pins\nconst (\n\tSDA_PIN  Pin = SDA0_PIN\n\tSCL_PIN  Pin = SCL0_PIN\n\tSDA0_PIN Pin = P30\n\tSCL0_PIN Pin = P31\n)\n\n// I2C1 (external) pins\nconst (\n\tSDA1_PIN Pin = P20\n\tSCL1_PIN Pin = P19\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN Pin = P13\n\tSPI0_SDO_PIN Pin = P15\n\tSPI0_SDI_PIN Pin = P14\n)\n\n// GPIO/Analog pins\nconst (\n\tP0  Pin = 2\n\tP1  Pin = 3\n\tP2  Pin = 4\n\tP3  Pin = 31\n\tP4  Pin = 28\n\tP5  Pin = 14\n\tP6  Pin = 37\n\tP7  Pin = 11\n\tP8  Pin = 10\n\tP9  Pin = 9\n\tP10 Pin = 30\n\tP11 Pin = 23\n\tP12 Pin = 12\n\tP13 Pin = 17\n\tP14 Pin = 1\n\tP15 Pin = 13\n\tP16 Pin = 34\n\tP19 Pin = 26\n\tP20 Pin = 32\n\tP21 Pin = 21\n\tP22 Pin = 22\n\tP23 Pin = 15\n\tP24 Pin = 24\n\tP25 Pin = 19\n\tP26 Pin = 36\n\tP27 Pin = 0\n\tP28 Pin = 20\n\tP29 Pin = 5\n\tP30 Pin = 16\n\tP31 Pin = 8\n\tP32 Pin = 25\n\tP33 Pin = 40\n\tP34 Pin = 6\n)\n\n// LED matrix pins\nconst (\n\tLED_COL_1 Pin = P0_28\n\tLED_COL_2 Pin = P0_11\n\tLED_COL_3 Pin = P0_31\n\tLED_COL_4 Pin = P1_05\n\tLED_COL_5 Pin = P0_30\n\tLED_ROW_1 Pin = P0_21\n\tLED_ROW_2 Pin = P0_22\n\tLED_ROW_3 Pin = P0_15\n\tLED_ROW_4 Pin = P0_24\n\tLED_ROW_5 Pin = P0_19\n)\n\n// Peripherals\nconst (\n\tBUZZER    = P27\n\tCAP_TOUCH = P26\n\tMIC       = P29\n\tMIC_LED   = P28\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"BBC micro:bit V2\"\n\tusb_STRING_MANUFACTURER = \"BBC\"\n)\n\nvar (\n\tusb_VID uint16 = 0x0d28\n\tusb_PID uint16 = 0x0204\n)\n"
  },
  {
    "path": "src/machine/board_microbit.go",
    "content": "//go:build microbit\n\npackage machine\n\n// The micro:bit does not have a 32kHz crystal on board.\nconst HasLowFrequencyCrystal = false\n\nvar DefaultUART = UART0\n\n// GPIO/Analog pins\nconst (\n\tP0  = P0_03\n\tP1  = P0_02\n\tP2  = P0_01\n\tP3  = P0_04\n\tP4  = P0_05\n\tP5  = P0_17\n\tP6  = P0_12\n\tP7  = P0_11\n\tP8  = P0_18\n\tP9  = P0_10\n\tP10 = P0_06\n\tP11 = P0_26\n\tP12 = P0_20\n\tP13 = P0_23\n\tP14 = P0_22\n\tP15 = P0_21\n\tP16 = P0_16\n)\n\n// Buttons on the micro:bit (A and B)\nconst (\n\tBUTTONA = P0_17\n\tBUTTONB = P0_26\n\tBUTTON  = BUTTONA\n)\n\n// UART pins\nconst (\n\tUART_TX_PIN = P0_24\n\tUART_RX_PIN = P0_25\n)\n\n// ADC pins\nconst (\n\tADC0 = P0_03 // P0 on the board\n\tADC1 = P0_02 // P1 on the board\n\tADC2 = P0_01 // P2 on the board\n)\n\n// I2C pins\nconst (\n\tSDA_PIN = P0_30 // P20 on the board\n\tSCL_PIN = P0_00 // P19 on the board\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = P0_23 // P13 on the board\n\tSPI0_SDO_PIN = P0_21 // P15 on the board\n\tSPI0_SDI_PIN = P0_22 // P14 on the board\n)\n\n// LED matrix pins\nconst (\n\tLED_COL_1 = P0_04\n\tLED_COL_2 = P0_05\n\tLED_COL_3 = P0_06\n\tLED_COL_4 = P0_07\n\tLED_COL_5 = P0_08\n\tLED_COL_6 = P0_09\n\tLED_COL_7 = P0_10\n\tLED_COL_8 = P0_11\n\tLED_COL_9 = P0_12\n\tLED_ROW_1 = P0_13\n\tLED_ROW_2 = P0_14\n\tLED_ROW_3 = P0_15\n)\n"
  },
  {
    "path": "src/machine/board_mksnanov3.go",
    "content": "//go:build mksnanov3\n\n// The MKS Robin Nano V3.X board.\n// Documented at https://github.com/makerbase-mks/MKS-Robin-Nano-V3.X.\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/interrupt\"\n)\n\n// LED is also wired to the SD card card detect (CD) pin.\nconst LED = PD12\n\n// UART pins\nconst (\n\tUART_TX_PIN = PB10\n\tUART_RX_PIN = PB11\n)\n\n// EXP1 and EXP2 expansion ports for connecting\n// the MKS TS35 V2.0 expansion board.\nconst (\n\tBEEPER = EXP1_1\n\n\t// LCD pins.\n\tLCD_DC        = EXP1_8\n\tLCD_CS        = EXP1_7\n\tLCD_RS        = EXP1_4\n\tLCD_BACKLIGHT = EXP1_3\n\n\t// Touch pins. Note that some pins are shared with the\n\t// LCD SPI1 interface.\n\tTOUCH_CLK  = EXP2_2\n\tTOUCH_CS   = EXP1_5\n\tTOUCH_DIN  = EXP2_6\n\tTOUCH_DOUT = EXP2_1\n\tTOUCH_IRQ  = EXP1_6\n\n\tBUTTON         = BUTTON_JOG\n\tBUTTON_JOG     = EXP1_2\n\tBUTTON_JOG_CCW = EXP2_3\n\tBUTTON_JOG_CW  = EXP2_5\n\n\tEXP1_1 = PC5\n\tEXP1_2 = PE13\n\tEXP1_3 = PD13\n\tEXP1_4 = PC6\n\tEXP1_5 = PE14\n\tEXP1_6 = PE15\n\tEXP1_7 = PD11\n\tEXP1_8 = PD10\n\n\tEXP2_1 = PA6\n\tEXP2_2 = PA5\n\tEXP2_3 = PE8\n\tEXP2_4 = PE10\n\tEXP2_5 = PE11\n\tEXP2_6 = PA7\n\tEXP2_7 = PE12\n)\n\nvar (\n\tUART3  = &_UART3\n\t_UART3 = UART{\n\t\tBuffer:            NewRingBuffer(),\n\t\tBus:               stm32.USART3,\n\t\tTxAltFuncSelector: AF7_USART1_2_3,\n\t\tRxAltFuncSelector: AF7_USART1_2_3,\n\t}\n\tDefaultUART = UART3\n)\n\n// set up RX IRQ handler. Follow similar pattern for other UARTx instances\nfunc init() {\n\tUART3.Interrupt = interrupt.New(stm32.IRQ_USART3, _UART3.handleInterrupt)\n}\n\n// SPI pins\nconst (\n\tSPI1_SCK_PIN = EXP2_2\n\tSPI1_SDI_PIN = EXP2_1\n\tSPI1_SDO_PIN = EXP2_6\n\tSPI0_SCK_PIN = SPI1_SCK_PIN\n\tSPI0_SDI_PIN = SPI1_SDI_PIN\n\tSPI0_SDO_PIN = SPI1_SDO_PIN\n)\n\n// Since the first interface is named SPI1, both SPI0 and SPI1 refer to SPI1.\nvar (\n\tSPI0 = &SPI{\n\t\tBus:             stm32.SPI1,\n\t\tAltFuncSelector: AF5_SPI1_SPI2,\n\t}\n\tSPI1 = SPI0\n)\n\nconst (\n\tI2C0_SCL_PIN = PB6\n\tI2C0_SDA_PIN = PB7\n)\n\nvar (\n\tI2C0 = &I2C{\n\t\tBus:             stm32.I2C1,\n\t\tAltFuncSelector: AF4_I2C1_2_3,\n\t}\n)\n\n// Motor control pins.\nconst (\n\tX_ENABLE = PE4\n\tX_STEP   = PE3\n\tX_DIR    = PE2\n\tX_DIAG   = PA15\n\tX_UART   = PD5\n\n\tY_ENABLE = PE1\n\tY_STEP   = PE0\n\tY_DIR    = PB9\n\tY_DIAG   = PD2\n\tY_UART   = PD7\n\n\tZ_ENABLE = PB8\n\tZ_STEP   = PB5\n\tZ_DIR    = PB4\n\tZ_DIAG   = PC8\n\tZ_UART   = PD4\n\n\tE0_ENABLE = PB3\n\tE0_STEP   = PD6\n\tE0_DIR    = PD3\n\tE0_DIAG   = PC4\n\tE0_UART   = PD9\n\n\tE1_ENABLE = PA3\n\tE1_STEP   = PD15\n\tE1_DIR    = PA1\n\tE1_DIAG   = PE7\n\tE1_UART   = PD8\n)\n"
  },
  {
    "path": "src/machine/board_nano-33-ble.go",
    "content": "//go:build nano_33_ble\n\n// This contains the pin mappings for the Arduino Nano 33 BLE [Sense] boards.\n// - https://store.arduino.cc/arduino-nano-33-ble\n// - https://store.arduino.cc/arduino-nano-33-ble-sense\n//\n// ----------------------------------------------------------------------------\n// Flashing\n//\n// Special version of bossac is required.\n// This executable can be obtained two ways:\n//  1. In Arduino IDE, install support for the board (\"Arduino Mbed OS Nano Boards\")\n//     Search for \"tools/bossac/1.9.1-arduino2/bossac\" in Arduino IDEs directory\n//  2. Download https://downloads.arduino.cc/packages/package_index.json\n//     Search for \"bossac-1.9.1-arduino2\" in that file\n//     Download tarball for your OS and unpack it\n//\n// Once you have the executable, make it accessible in your PATH as \"bossac_arduino2\".\n//\n// It is possible to replace original bossac with this new one (this only adds support for nrf chip).\n// In that case make \"bossac_arduino2\" symlink on it, for the board target to be able to find it.\n//\n// ----------------------------------------------------------------------------\n// Bluetooth\n//\n// SoftDevice (s140v7) must be flashed first to enable use of bluetooth on this board.\n// See https://github.com/tinygo-org/bluetooth\n//\n// SoftDevice overwrites original bootloader and flashing method described above is not available anymore.\n// Instead, please use debug probe and flash your code with \"nano-33-ble-s140v7\" target.\npackage machine\n\nconst HasLowFrequencyCrystal = true\n\n// Digital Pins\nconst (\n\tD2  Pin = P1_11\n\tD3  Pin = P1_12\n\tD4  Pin = P1_15\n\tD5  Pin = P1_13\n\tD6  Pin = P1_14\n\tD7  Pin = P0_23\n\tD8  Pin = P0_21\n\tD9  Pin = P0_27\n\tD10 Pin = P1_02\n\tD11 Pin = P1_01\n\tD12 Pin = P1_08\n\tD13 Pin = P0_13\n)\n\n// Analog pins\nconst (\n\tA0 Pin = P0_04\n\tA1 Pin = P0_05\n\tA2 Pin = P0_30\n\tA3 Pin = P0_29\n\tA4 Pin = P0_31\n\tA5 Pin = P0_02\n\tA6 Pin = P0_28\n\tA7 Pin = P0_03\n)\n\n// Onboard LEDs\nconst (\n\tLED         = LED_BUILTIN\n\tLED1        = LED_RED\n\tLED2        = LED_GREEN\n\tLED3        = LED_BLUE\n\tLED_BUILTIN = P0_13\n\tLED_RED     = P0_24\n\tLED_GREEN   = P0_16\n\tLED_BLUE    = P0_06\n\tLED_PWR     = P1_09\n)\n\n// UART0 pins\nconst (\n\tUART_RX_PIN = P1_10\n\tUART_TX_PIN = P1_03\n)\n\n// I2C pins\nconst (\n\t// Defaults to internal\n\tSDA_PIN = SDA1_PIN\n\tSCL_PIN = SCL1_PIN\n\n\t// I2C0 (external) pins\n\tSDA0_PIN = P0_31\n\tSCL0_PIN = P0_02\n\n\t// I2C1 (internal) pins\n\tSDA1_PIN = P0_14\n\tSCL1_PIN = P0_15\n\n\tI2C_PULLUP = P1_00 // Set high for I2C to work\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = P0_13\n\tSPI0_SDO_PIN = P1_01\n\tSPI0_SDI_PIN = P1_08\n)\n\n// Peripherals\nconst (\n\tAPDS_INT = P0_19 // Proximity (APDS9960) interrupt pin\n\n\tLSM_PWR = P0_22 // IMU (LSM9DS1) power\n\tLPS_PWR = P0_22 // Pressure (LPS22HB) power\n\tHTS_PWR = P0_22 // Humidity (HTS221) power\n\n\tMIC_PWR = P0_17 // Microphone (MP34DT06JTR) power\n\tMIC_CLK = P0_26\n\tMIC_DIN = P0_25\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Nano 33 BLE\"\n\tusb_STRING_MANUFACTURER = \"Arduino\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2341\n\tusb_PID uint16 = 0x805a\n)\n"
  },
  {
    "path": "src/machine/board_nano-rp2040.go",
    "content": "//go:build nano_rp2040\n\n// This contains the pin mappings for the Arduino Nano RP2040 Connect board.\n//\n// Sometimes the board is not detected even when the board is connected to your computer.\n// To solve this, place a jumper wire between the REC and GND pins, then connect the board to your computer.\n//\n// For more information, see: https://store.arduino.cc/nano-rp2040-connect\n// Also\n// - Datasheets: https://docs.arduino.cc/hardware/nano-rp2040-connect\n// - Nano RP2040 Connect technical reference: https://docs.arduino.cc/tutorials/nano-rp2040-connect/rp2040-01-technical-reference\npackage machine\n\n// Digital Pins\nconst (\n\tD2  Pin = GPIO25\n\tD3  Pin = GPIO15\n\tD4  Pin = GPIO16\n\tD5  Pin = GPIO17\n\tD6  Pin = GPIO18\n\tD7  Pin = GPIO19\n\tD8  Pin = GPIO20\n\tD9  Pin = GPIO21\n\tD10 Pin = GPIO5\n\tD11 Pin = GPIO7\n\tD12 Pin = GPIO4\n\tD13 Pin = GPIO6\n\tD14 Pin = GPIO26\n\tD15 Pin = GPIO27\n\tD16 Pin = GPIO28\n\tD17 Pin = GPIO29\n\tD18 Pin = GPIO12\n\tD19 Pin = GPIO13\n)\n\n// Analog pins\nconst (\n\tA0 Pin = ADC0\n\tA1 Pin = ADC1\n\tA2 Pin = ADC2\n\tA3 Pin = ADC3\n)\n\n// Onboard LED\nconst (\n\tLED = GPIO6\n)\n\n// I2C pins\nconst (\n\tI2C0_SDA_PIN Pin = GPIO12\n\tI2C0_SCL_PIN Pin = GPIO13\n\n\tI2C1_SDA_PIN Pin = GPIO18\n\tI2C1_SCL_PIN Pin = GPIO19\n)\n\n// SPI pins. SPI1 not available on Nano RP2040 Connect.\nconst (\n\tSPI0_SCK_PIN Pin = GPIO6\n\tSPI0_SDO_PIN Pin = GPIO7\n\tSPI0_SDI_PIN Pin = GPIO4\n\n\t// GPIO22 does not have SPI functionality so we set it to avoid interfering with NINA.\n\tSPI1_SCK_PIN Pin = GPIO22\n\tSPI1_SDO_PIN Pin = GPIO22\n\tSPI1_SDI_PIN Pin = GPIO22\n)\n\nvar (\n\tNINA_SPI = SPI1\n)\n\n// NINA-W102 Pins\nconst (\n\tNINA_SCK Pin = GPIO14\n\tNINA_SDO Pin = GPIO11\n\tNINA_SDI Pin = GPIO8\n\n\tNINA_CS     Pin = GPIO9\n\tNINA_ACK    Pin = GPIO10\n\tNINA_GPIO0  Pin = GPIO2\n\tNINA_RESETN Pin = GPIO3\n\n\tNINA_TX  Pin = GPIO8\n\tNINA_RX  Pin = GPIO9\n\tNINA_CTS Pin = GPIO10\n\tNINA_RTS Pin = GPIO11\n)\n\n// NINA-W102 settings\nconst (\n\tNINA_BAUDRATE         = 115200\n\tNINA_RESET_INVERTED   = true\n\tNINA_SOFT_FLOWCONTROL = false\n)\n\n// Onboard crystal oscillator frequency, in MHz.\nconst (\n\txoscFreq = 12 // MHz\n)\n\n// USB CDC identifiers\n// https://github.com/arduino/ArduinoCore-mbed/blob/master/variants/NANO_RP2040_CONNECT/pins_arduino.h\nconst (\n\tusb_STRING_PRODUCT      = \"Nano RP2040 Connect\"\n\tusb_STRING_MANUFACTURER = \"Arduino\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2341\n\tusb_PID uint16 = 0x005e\n)\n\n// UART pins\nconst (\n\tUART0_TX_PIN = GPIO0\n\tUART0_RX_PIN = GPIO1\n\tUART_TX_PIN  = UART0_TX_PIN\n\tUART_RX_PIN  = UART0_RX_PIN\n)\n\n// UART_NINA on the Arduino Nano RP2040 connects to the NINA HCI.\nvar UART_NINA = UART1\n\nvar DefaultUART = UART0\n"
  },
  {
    "path": "src/machine/board_nicenano.go",
    "content": "//go:build nicenano\n\npackage machine\n\nconst HasLowFrequencyCrystal = true\n\n// GPIO Pins\nconst (\n\tD006 = P0_06\n\tD008 = P0_08\n\tD017 = P0_17\n\tD020 = P0_20\n\tD022 = P0_22\n\tD024 = P0_24\n\tD100 = P1_00\n\tD011 = P0_11\n\tD104 = P1_04\n\tD106 = P1_06\n\n\tD004 = P0_04 // AIN2; P0.04 (AIN2) is used to read the voltage of the battery via ADC. It can’t be used for any other function.\n\tD013 = P0_13 // VCC 3.3V; P0.13 on VCC shuts off the power to VCC when you set it to high; This saves on battery immensely for LEDs of all kinds that eat power even when off\n\tD115 = P1_15\n\tD113 = P1_13\n\tD031 = P0_31 // AIN7\n\tD029 = P0_29 // AIN5\n\tD002 = P0_02 // AIN0\n\n\tD111 = P1_11\n\tD010 = P0_10 // NFC2\n\tD009 = P0_09 // NFC1\n\n\tD026 = P0_26\n\tD012 = P0_12\n\tD101 = P1_01\n\tD102 = P1_02\n\tD107 = P1_07\n)\n\n// Analog Pins\nconst (\n\tAIN2 = P0_04 // Battery\n\tAIN7 = P0_31\n\tAIN5 = P0_29\n\tAIN0 = P0_02\n)\n\nconst (\n\tLED = P0_15\n)\n\n// UART0 pins (logical UART1)\nconst (\n\tUART_RX_PIN = P0_06\n\tUART_TX_PIN = P0_08\n)\n\n// I2C pins\nconst (\n\tSDA_PIN = P0_17 // I2C0 external\n\tSCL_PIN = P0_20 // I2C0 external\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = P0_22 // SCK\n\tSPI0_SDO_PIN = P0_24 // SDO\n\tSPI0_SDI_PIN = P1_00 // SDI\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"nice!nano\"\n\tusb_STRING_MANUFACTURER = \"Nice Keyboards\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x0029\n)\n"
  },
  {
    "path": "src/machine/board_nodemcu.go",
    "content": "//go:build nodemcu\n\n// Pinout for the NodeMCU dev kit.\n\npackage machine\n\n// GPIO pins on the NodeMCU board.\nconst (\n\tD0 = GPIO16\n\tD1 = GPIO5\n\tD2 = GPIO4\n\tD3 = GPIO0\n\tD4 = GPIO2\n\tD5 = GPIO14\n\tD6 = GPIO12\n\tD7 = GPIO13\n\tD8 = GPIO15\n)\n\n// Onboard blue LED (on the AI-Thinker module).\nconst LED = D4\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = D5\n\tSPI0_SDO_PIN = D7\n\tSPI0_SDI_PIN = D6\n\tSPI0_CS0_PIN = D8\n)\n\n// I2C pins\nconst (\n\tSDA_PIN = D2\n\tSCL_PIN = D1\n)\n"
  },
  {
    "path": "src/machine/board_nrf51.go",
    "content": "//go:build nrf51 || microbit\n\npackage machine\n\nfunc CPUFrequency() uint32 {\n\treturn 16000000\n}\n\n// Hardware pins\nconst (\n\tP0_00 Pin = 0\n\tP0_01 Pin = 1\n\tP0_02 Pin = 2\n\tP0_03 Pin = 3\n\tP0_04 Pin = 4\n\tP0_05 Pin = 5\n\tP0_06 Pin = 6\n\tP0_07 Pin = 7\n\tP0_08 Pin = 8\n\tP0_09 Pin = 9\n\tP0_10 Pin = 10\n\tP0_11 Pin = 11\n\tP0_12 Pin = 12\n\tP0_13 Pin = 13\n\tP0_14 Pin = 14\n\tP0_15 Pin = 15\n\tP0_16 Pin = 16\n\tP0_17 Pin = 17\n\tP0_18 Pin = 18\n\tP0_19 Pin = 19\n\tP0_20 Pin = 20\n\tP0_21 Pin = 21\n\tP0_22 Pin = 22\n\tP0_23 Pin = 23\n\tP0_24 Pin = 24\n\tP0_25 Pin = 25\n\tP0_26 Pin = 26\n\tP0_27 Pin = 27\n\tP0_28 Pin = 28\n\tP0_29 Pin = 29\n\tP0_30 Pin = 30\n\tP0_31 Pin = 31\n)\n"
  },
  {
    "path": "src/machine/board_nrf52840-mdk-usb-dongle.go",
    "content": "//go:build nrf52840_mdk_usb_dongle\n\npackage machine\n\nconst HasLowFrequencyCrystal = true\n\n// LEDs on the nrf52840-mdk-usb-dongle\nconst (\n\tLED       Pin = LED_GREEN\n\tLED_GREEN Pin = 22\n\tLED_RED   Pin = 23\n\tLED_BLUE  Pin = 24\n)\n\n// RESET/USR button, depending on value of PSELRESET UICR register\nconst (\n\tBUTTON Pin = 18\n)\n\n// UART pins\nconst (\n\tUART_TX_PIN Pin = NoPin\n\tUART_RX_PIN Pin = NoPin\n)\n\n// I2C pins (unused)\nconst (\n\tSDA_PIN = NoPin\n\tSCL_PIN = NoPin\n)\n\n// SPI pins (unused)\nconst (\n\tSPI0_SCK_PIN = NoPin\n\tSPI0_SDO_PIN = NoPin\n\tSPI0_SDI_PIN = NoPin\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Makerdiary nRF52840 MDK USB Dongle\"\n\tusb_STRING_MANUFACTURER = \"Nordic Semiconductor ASA\"\n)\n\nvar (\n\tusb_VID uint16 = 0x1915\n\tusb_PID uint16 = 0xCAFE\n)\n"
  },
  {
    "path": "src/machine/board_nrf52840-mdk.go",
    "content": "//go:build nrf52840_mdk\n\npackage machine\n\nconst HasLowFrequencyCrystal = true\n\n// LEDs on the nrf52840-mdk (nRF52840 dev board)\nconst (\n\tLED_GREEN Pin = 22\n\tLED_RED   Pin = 23\n\tLED_BLUE  Pin = 24\n\tLED       Pin = LED_GREEN\n)\n\n// UART pins\nconst (\n\tUART_TX_PIN Pin = 20\n\tUART_RX_PIN Pin = 19\n)\n\n// I2C pins (unused)\nconst (\n\tSDA_PIN = NoPin\n\tSCL_PIN = NoPin\n)\n\n// SPI pins (unused)\nconst (\n\tSPI0_SCK_PIN = NoPin\n\tSPI0_SDO_PIN = NoPin\n\tSPI0_SDI_PIN = NoPin\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Makerdiary nRF52840 MDK\"\n\tusb_STRING_MANUFACTURER = \"Nordic Semiconductor ASA\"\n)\n\nvar (\n\tusb_VID uint16 = 0x1915\n\tusb_PID uint16 = 0xCAFE\n)\n"
  },
  {
    "path": "src/machine/board_nrf52840.go",
    "content": "//go:build nrf52840 || circuitplay_bluefruit || reelboard || clue || itsybitsy_nrf52840\n\npackage machine\n\n// Hardware pins\nconst (\n\tP0_00 Pin = 0\n\tP0_01 Pin = 1\n\tP0_02 Pin = 2\n\tP0_03 Pin = 3\n\tP0_04 Pin = 4\n\tP0_05 Pin = 5\n\tP0_06 Pin = 6\n\tP0_07 Pin = 7\n\tP0_08 Pin = 8\n\tP0_09 Pin = 9\n\tP0_10 Pin = 10\n\tP0_11 Pin = 11\n\tP0_12 Pin = 12\n\tP0_13 Pin = 13\n\tP0_14 Pin = 14\n\tP0_15 Pin = 15\n\tP0_16 Pin = 16\n\tP0_17 Pin = 17\n\tP0_18 Pin = 18\n\tP0_19 Pin = 19\n\tP0_20 Pin = 20\n\tP0_21 Pin = 21\n\tP0_22 Pin = 22\n\tP0_23 Pin = 23\n\tP0_24 Pin = 24\n\tP0_25 Pin = 25\n\tP0_26 Pin = 26\n\tP0_27 Pin = 27\n\tP0_28 Pin = 28\n\tP0_29 Pin = 29\n\tP0_30 Pin = 30\n\tP0_31 Pin = 31\n\tP1_00 Pin = 32\n\tP1_01 Pin = 33\n\tP1_02 Pin = 34\n\tP1_03 Pin = 35\n\tP1_04 Pin = 36\n\tP1_05 Pin = 37\n\tP1_06 Pin = 38\n\tP1_07 Pin = 39\n\tP1_08 Pin = 40\n\tP1_09 Pin = 41\n\tP1_10 Pin = 42\n\tP1_11 Pin = 43\n\tP1_12 Pin = 44\n\tP1_13 Pin = 45\n\tP1_14 Pin = 46\n\tP1_15 Pin = 47\n)\n"
  },
  {
    "path": "src/machine/board_nrf52840_generic.go",
    "content": "//go:build nrf52840 && nrf52840_generic\n\npackage machine\n\nvar (\n\tLED          = NoPin\n\tSDA_PIN      = NoPin\n\tSCL_PIN      = NoPin\n\tUART_TX_PIN  = NoPin\n\tUART_RX_PIN  = NoPin\n\tSPI0_SCK_PIN = NoPin\n\tSPI0_SDO_PIN = NoPin\n\tSPI0_SDI_PIN = NoPin\n\n\t// https://pid.codes/org/TinyGo/\n\tusb_VID uint16 = 0x1209\n\tusb_PID uint16 = 0x9090\n\n\tusb_STRING_MANUFACTURER = \"TinyGo\"\n\tusb_STRING_PRODUCT      = \"nRF52840 Generic board\"\n)\n\nvar (\n\tDefaultUART = UART0\n)\n"
  },
  {
    "path": "src/machine/board_nucleof103rb.go",
    "content": "//go:build nucleof103rb\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/interrupt\"\n)\n\nconst (\n\tLED         = LED_BUILTIN\n\tLED_BUILTIN = LED_GREEN\n\tLED_GREEN   = PA5\n)\n\nconst (\n\tBUTTON      = BUTTON_USER\n\tBUTTON_USER = PC13\n)\n\n// UART pins\nconst (\n\tUART_TX_PIN     = PA2\n\tUART_RX_PIN     = PA3\n\tUART_ALT_TX_PIN = PD5\n\tUART_ALT_RX_PIN = PD6\n)\n\nvar (\n\t// USART2 is the hardware serial port connected to the onboard ST-LINK\n\t// debugger to be exposed as virtual COM port over USB on Nucleo boards.\n\tUART2  = &_UART2\n\t_UART2 = UART{\n\t\tBuffer: NewRingBuffer(),\n\t\tBus:    stm32.USART2,\n\t}\n\tDefaultUART = UART2\n)\n\nfunc init() {\n\tUART2.Interrupt = interrupt.New(stm32.IRQ_USART2, _UART2.handleInterrupt)\n}\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = PA5\n\tSPI0_SDI_PIN = PA6\n\tSPI0_SDO_PIN = PA7\n)\n\n// I2C pins\nconst (\n\tI2C0_SCL_PIN = PB6\n\tI2C0_SDA_PIN = PB7\n)\n"
  },
  {
    "path": "src/machine/board_nucleof722ze.go",
    "content": "//go:build nucleof722ze\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/interrupt\"\n)\n\nconst (\n\tLED         = LED_BUILTIN\n\tLED_BUILTIN = LED_GREEN\n\tLED_GREEN   = PB0\n\tLED_BLUE    = PB7\n\tLED_RED     = PB14\n)\n\nconst (\n\tBUTTON      = BUTTON_USER\n\tBUTTON_USER = PC13\n)\n\n// UART pins\nconst (\n\t// PD8 and PD9 are connected to the ST-Link Virtual Com Port (VCP)\n\tUART_TX_PIN = PD8\n\tUART_RX_PIN = PD9\n\tUART_ALT_FN = 7 // GPIO_AF7_UART3\n)\n\nvar (\n\t// USART3 is the hardware serial port connected to the onboard ST-LINK\n\t// debugger to be exposed as virtual COM port over USB on Nucleo boards.\n\tUART1  = &_UART1\n\t_UART1 = UART{\n\t\tBuffer:            NewRingBuffer(),\n\t\tBus:               stm32.USART3,\n\t\tTxAltFuncSelector: UART_ALT_FN,\n\t\tRxAltFuncSelector: UART_ALT_FN,\n\t}\n\tDefaultUART = UART1\n)\n\nfunc init() {\n\tUART1.Interrupt = interrupt.New(stm32.IRQ_USART3, _UART1.handleInterrupt)\n}\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = PA5\n\tSPI0_SDI_PIN = PA6\n\tSPI0_SDO_PIN = PA7\n)\n\n// I2C pins\nconst (\n\tI2C0_SCL_PIN = PB8\n\tI2C0_SDA_PIN = PB9\n)\n\nvar (\n\t// I2C1 is documented, alias to I2C0 as well\n\tI2C1 = &I2C{\n\t\tBus:             stm32.I2C1,\n\t\tAltFuncSelector: 4,\n\t}\n\tI2C0 = I2C1\n)\n"
  },
  {
    "path": "src/machine/board_nucleol031k6.go",
    "content": "//go:build nucleol031k6\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/interrupt\"\n)\n\nconst (\n\t// Arduino Pins\n\tA0 = PA0 // ADC_IN0\n\tA1 = PA1 // ADC_IN1\n\tA2 = PA3 // ADC_IN3\n\tA3 = PA4 // ADC_IN4\n\tA4 = PA5 // ADC_IN5 || I2C1_SDA\n\tA5 = PA6 // ADC_IN6 || I2C1_SCL\n\tA6 = PA7 // ADC_IN7\n\tA7 = PA2 // ADC_IN2\n\n\tD0  = PA10 // USART1_TX\n\tD1  = PA9  // USART1_RX\n\tD2  = PA12\n\tD3  = PB0 // TIM2_CH3\n\tD4  = PB7\n\tD5  = PB6  // TIM16_CH1N\n\tD6  = PB1  // TIM14_CH1\n\tD9  = PA8  // TIM1_CH1\n\tD10 = PA11 // SPI_CS || TIM1_CH4\n\tD11 = PB5  // SPI1_MOSI || TIM3_CH2\n\tD12 = PB4  // SPI1_MISO\n\tD13 = PB3  // SPI1_SCK\n)\n\nconst (\n\tLED         = LED_BUILTIN\n\tLED_BUILTIN = LED_GREEN\n\tLED_GREEN   = PB3\n)\n\nconst (\n\t// This board does not have a user button, so\n\t// use first GPIO pin by default\n\tBUTTON = PA0\n)\n\nconst (\n\t// UART pins\n\t// PA2 and PA15 are connected to the ST-Link Virtual Com Port (VCP)\n\tUART_TX_PIN = PA2\n\tUART_RX_PIN = PA15\n\n\t// SPI\n\tSPI1_SCK_PIN = PB3\n\tSPI1_SDI_PIN = PB5\n\tSPI1_SDO_PIN = PB4\n\tSPI0_SCK_PIN = SPI1_SCK_PIN\n\tSPI0_SDI_PIN = SPI1_SDI_PIN\n\tSPI0_SDO_PIN = SPI1_SDO_PIN\n\n\t// I2C pins\n\t// PB6 and PB7 are mapped to CN4 pin 7 and CN4 pin 8 respectively with the\n\t// default solder bridge settings\n\tI2C0_SCL_PIN  = PB7\n\tI2C0_SDA_PIN  = PB6\n\tI2C0_ALT_FUNC = 1\n)\n\nvar (\n\t// USART2 is the hardware serial port connected to the onboard ST-LINK\n\t// debugger to be exposed as virtual COM port over USB on Nucleo boards.\n\tUART1  = &_UART1\n\t_UART1 = UART{\n\t\tBuffer:            NewRingBuffer(),\n\t\tBus:               stm32.USART2,\n\t\tTxAltFuncSelector: 4,\n\t\tRxAltFuncSelector: 4,\n\t}\n\tDefaultUART = UART1\n\n\t// I2C1 is documented, alias to I2C0 as well\n\tI2C1 = &I2C{\n\t\tBus:             stm32.I2C1,\n\t\tAltFuncSelector: 1,\n\t}\n\tI2C0 = I2C1\n\n\t// SPI\n\tSPI0 = &SPI{\n\t\tBus:             stm32.SPI1,\n\t\tAltFuncSelector: 0,\n\t}\n\tSPI1 = SPI0\n)\n\nfunc init() {\n\tUART1.Interrupt = interrupt.New(stm32.IRQ_USART2, _UART1.handleInterrupt)\n}\n"
  },
  {
    "path": "src/machine/board_nucleol432kc.go",
    "content": "//go:build nucleol432kc\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/interrupt\"\n)\n\nconst (\n\t// Arduino Pins\n\tA0 = PA0\n\tA1 = PA1\n\tA2 = PA3\n\tA3 = PA4\n\tA4 = PA5\n\tA5 = PA6\n\tA6 = PA7\n\tA7 = PA2\n\n\tD0  = PA10\n\tD1  = PA9\n\tD2  = PA12\n\tD3  = PB0\n\tD4  = PB7\n\tD5  = PB6\n\tD6  = PB1\n\tD7  = PC14\n\tD8  = PC15\n\tD9  = PA8\n\tD10 = PA11\n\tD11 = PB5\n\tD12 = PB4\n\tD13 = PB3\n)\n\nconst (\n\tLED         = LED_BUILTIN\n\tLED_BUILTIN = LED_GREEN\n\tLED_GREEN   = PB3\n)\n\nconst (\n\t// This board does not have a user button, so\n\t// use first GPIO pin by default\n\tBUTTON = PA0\n)\n\nconst (\n\t// UART pins\n\t// PA2 and PA15 are connected to the ST-Link Virtual Com Port (VCP)\n\tUART_TX_PIN = PA2\n\tUART_RX_PIN = PA15\n\n\t// I2C pins\n\t// With default solder bridge settings:\n\t//    PB6 / Arduino D5 / CN3 Pin 8 is SCL\n\t//    PB7 / Arduino D4 / CN3 Pin 7 is SDA\n\tI2C0_SCL_PIN = PB6\n\tI2C0_SDA_PIN = PB7\n\n\t// SPI pins\n\tSPI1_SCK_PIN = PB3\n\tSPI1_SDI_PIN = PB5\n\tSPI1_SDO_PIN = PB4\n\tSPI0_SCK_PIN = SPI1_SCK_PIN\n\tSPI0_SDI_PIN = SPI1_SDI_PIN\n\tSPI0_SDO_PIN = SPI1_SDO_PIN\n)\n\nvar (\n\t// USART2 is the hardware serial port connected to the onboard ST-LINK\n\t// debugger to be exposed as virtual COM port over USB on Nucleo boards.\n\tUART1  = &_UART1\n\t_UART1 = UART{\n\t\tBuffer:            NewRingBuffer(),\n\t\tBus:               stm32.USART2,\n\t\tTxAltFuncSelector: 7,\n\t\tRxAltFuncSelector: 3,\n\t}\n\tDefaultUART = UART1\n\n\t// I2C1 is documented, alias to I2C0 as well\n\tI2C1 = &I2C{\n\t\tBus:             stm32.I2C1,\n\t\tAltFuncSelector: 4,\n\t}\n\tI2C0 = I2C1\n\n\t// SPI1 is documented, alias to SPI0 as well\n\tSPI1 = &SPI{\n\t\tBus:             stm32.SPI1,\n\t\tAltFuncSelector: 5,\n\t}\n\tSPI0 = SPI1\n)\n\nfunc init() {\n\tUART1.Interrupt = interrupt.New(stm32.IRQ_USART2, _UART1.handleInterrupt)\n}\n"
  },
  {
    "path": "src/machine/board_nucleol476rg.go",
    "content": "//go:build nucleol476rg\n\n// Schematic: https://www.st.com/resource/en/user_manual/um1724-stm32-nucleo64-boards-mb1136-stmicroelectronics.pdf\n// Datasheet: https://www.st.com/resource/en/datasheet/stm32l476je.pdf\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/interrupt\"\n)\n\nconst (\n\t// Arduino Pins\n\tA0 = PA0\n\tA1 = PA1\n\tA2 = PA4\n\tA3 = PB0\n\tA4 = PC1\n\tA5 = PC0\n\n\tD0  = PA3\n\tD1  = PA2\n\tD2  = PA10\n\tD3  = PB3\n\tD4  = PB5\n\tD5  = PB4\n\tD6  = PB10\n\tD7  = PA8\n\tD8  = PA9\n\tD9  = PC7\n\tD10 = PB6\n\tD11 = PA7\n\tD12 = PA6\n\tD13 = PA5\n\tD14 = PB9\n\tD15 = PB8\n)\n\n// User LD2: the green LED is a user LED connected to ARDUINO® signal D13 corresponding\n// to STM32 I/O PA5 (pin 21) or PB13 (pin 34) depending on the STM32 target.\nconst (\n\tLED         = LED_BUILTIN\n\tLED_BUILTIN = LED_GREEN\n\tLED_GREEN   = PA5\n)\n\nconst (\n\t// This board does not have a user button, so\n\t// use first GPIO pin by default\n\tBUTTON = PA0\n)\n\nconst (\n\t// UART pins\n\t// PA2 and PA3 are connected to the ST-Link Virtual Com Port (VCP)\n\tUART_TX_PIN = PA2\n\tUART_RX_PIN = PA3\n\n\t// I2C pins\n\t// With default solder bridge settings:\n\t//    PB8 / Arduino D5 / CN3 Pin 8 is SCL\n\t//    PB7 / Arduino D4 / CN3 Pin 7 is SDA\n\tI2C0_SCL_PIN = PB8\n\tI2C0_SDA_PIN = PB9\n\n\t// SPI pins\n\tSPI1_SCK_PIN = PA5\n\tSPI1_SDI_PIN = PA6\n\tSPI1_SDO_PIN = PA7\n\tSPI0_SCK_PIN = SPI1_SCK_PIN\n\tSPI0_SDI_PIN = SPI1_SDI_PIN\n\tSPI0_SDO_PIN = SPI1_SDO_PIN\n)\n\nvar (\n\t// USART2 is the hardware serial port connected to the onboard ST-LINK\n\t// debugger to be exposed as virtual COM port over USB on Nucleo boards.\n\tUART1  = &_UART1\n\t_UART1 = UART{\n\t\tBuffer:            NewRingBuffer(),\n\t\tBus:               stm32.USART2,\n\t\tTxAltFuncSelector: AF7_USART1_2_3,\n\t\tRxAltFuncSelector: AF7_USART1_2_3,\n\t}\n\tDefaultUART = UART1\n\n\t// I2C1 is documented, alias to I2C0 as well\n\tI2C1 = &I2C{\n\t\tBus:             stm32.I2C1,\n\t\tAltFuncSelector: AF4_I2C1_2_3,\n\t}\n\tI2C0 = I2C1\n\n\t// SPI1 is documented, alias to SPI0 as well\n\tSPI1 = &SPI{\n\t\tBus:             stm32.SPI1,\n\t\tAltFuncSelector: AF5_SPI1_2,\n\t}\n\tSPI0 = SPI1\n)\n\nfunc init() {\n\tUART1.Interrupt = interrupt.New(stm32.IRQ_USART2, _UART1.handleInterrupt)\n}\n"
  },
  {
    "path": "src/machine/board_nucleol552ze.go",
    "content": "//go:build nucleol552ze\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/interrupt\"\n)\n\nconst (\n\tLED_GREEN   = PC7\n\tLED_BLUE    = PB7\n\tLED_RED     = PA9\n\tLED_BUILTIN = LED_GREEN\n\tLED         = LED_BUILTIN\n)\n\nconst (\n\tBUTTON      = BUTTON_USER\n\tBUTTON_USER = PC13\n)\n\n// UART pins\nconst (\n\t// PG7 and PG8 are connected to the ST-Link Virtual Com Port (VCP)\n\tUART_TX_PIN = PG7\n\tUART_RX_PIN = PG8\n\tUART_ALT_FN = 8 // GPIO_AF8_LPUART1\n)\n\nvar (\n\t// LPUART1 is the hardware serial port connected to the onboard ST-LINK\n\t// debugger to be exposed as virtual COM port over USB on Nucleo boards.\n\tUART1  = &_UART1\n\t_UART1 = UART{\n\t\tBuffer:            NewRingBuffer(),\n\t\tBus:               stm32.LPUART1,\n\t\tTxAltFuncSelector: UART_ALT_FN,\n\t\tRxAltFuncSelector: UART_ALT_FN,\n\t}\n\tDefaultUART = UART1\n)\n\nconst (\n\tI2C0_SCL_PIN = PB8\n\tI2C0_SDA_PIN = PB9\n)\n\nvar (\n\t// I2C1 is documented, alias to I2C0 as well\n\tI2C1 = &I2C{\n\t\tBus:             stm32.I2C1,\n\t\tAltFuncSelector: 4,\n\t}\n\tI2C0 = I2C1\n)\n\nfunc init() {\n\tUART1.Interrupt = interrupt.New(stm32.IRQ_LPUART1, _UART1.handleInterrupt)\n}\n"
  },
  {
    "path": "src/machine/board_nucleowl55jc.go",
    "content": "//go:build nucleowl55jc\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/interrupt\"\n)\n\nconst (\n\tLED_BLUE  = PB15\n\tLED_GREEN = PB9\n\tLED_RED   = PB11\n\tLED       = LED_RED\n\n\tBTN1   = PA0\n\tBTN2   = PA1\n\tBTN3   = PC6\n\tBUTTON = BTN1\n\n\t// SubGhz (SPI3)\n\tSPI0_NSS_PIN = PA4\n\tSPI0_SCK_PIN = PA5\n\tSPI0_SDO_PIN = PA6\n\tSPI0_SDI_PIN = PA7\n\n\t//MCU USART1\n\tUART1_TX_PIN = PB6\n\tUART1_RX_PIN = PB7\n\n\t//MCU USART2\n\tUART2_RX_PIN = PA3\n\tUART2_TX_PIN = PA2\n\n\t// DEFAULT USART\n\tUART_RX_PIN = UART2_RX_PIN\n\tUART_TX_PIN = UART2_TX_PIN\n\n\t// I2C1 pins\n\tI2C1_SCL_PIN  = PA9\n\tI2C1_SDA_PIN  = PA10\n\tI2C1_ALT_FUNC = 4\n\n\t// I2C2 pins\n\tI2C2_SCL_PIN  = PA12\n\tI2C2_SDA_PIN  = PA11\n\tI2C2_ALT_FUNC = 4\n\n\t// I2C0 alias for I2C1\n\tI2C0_SDA_PIN = I2C1_SDA_PIN\n\tI2C0_SCL_PIN = I2C1_SCL_PIN\n)\n\nvar (\n\t// STM32 UART2 is connected to the embedded STLINKV3 Virtual Com Port\n\tUART0  = &_UART0\n\t_UART0 = UART{\n\t\tBuffer:            NewRingBuffer(),\n\t\tBus:               stm32.USART2,\n\t\tTxAltFuncSelector: 7,\n\t\tRxAltFuncSelector: 7,\n\t}\n\n\t// UART1 is free\n\tUART1  = &_UART1\n\t_UART1 = UART{\n\t\tBuffer:            NewRingBuffer(),\n\t\tBus:               stm32.USART1,\n\t\tTxAltFuncSelector: 7,\n\t\tRxAltFuncSelector: 7,\n\t}\n\n\tDefaultUART = UART0\n\n\t// I2C Busses\n\tI2C1 = &I2C{\n\t\tBus:             stm32.I2C1,\n\t\tAltFuncSelector: I2C1_ALT_FUNC,\n\t}\n\tI2C2 = &I2C{\n\t\tBus:             stm32.I2C2,\n\t\tAltFuncSelector: I2C2_ALT_FUNC,\n\t}\n\tI2C0 = I2C1\n\n\t// SPI\n\tSPI3 = &SPI{\n\t\tBus: stm32.SPI3,\n\t}\n)\n\nfunc init() {\n\t// Enable UARTs Interrupts\n\tUART0.Interrupt = interrupt.New(stm32.IRQ_USART2, _UART0.handleInterrupt)\n\tUART1.Interrupt = interrupt.New(stm32.IRQ_USART1, _UART1.handleInterrupt)\n}\n"
  },
  {
    "path": "src/machine/board_p1am-100.go",
    "content": "//go:build p1am_100\n\n// This contains the pin mappings for the ProductivityOpen P1AM-100 board.\n//\n// For more information, see: https://facts-engineering.github.io/\npackage machine\n\n// used to reset into bootloader\nconst resetMagicValue = 0x07738135\n\n// Note: On the P1AM-100, pins D8, D9, D10, A3, and A4 are used for\n// communication with the base controller.\n\n// GPIO Pins\nconst (\n\tD0 Pin = PA22 // PWM available\n\tD1 Pin = PA23 // PWM available\n\tD2 Pin = PA10 // PWM available\n\tD3 Pin = PA11 // PWM available\n\tD4 Pin = PB10 // PWM available\n\tD5 Pin = PB11 // PWM available\n\tD6 Pin = PA20 // PWM available\n\tD7 Pin = PA21 // PWM available\n\n\tD8  Pin = PA16 // PWM available\n\tD9  Pin = PA17\n\tD10 Pin = PA19 // PWM available\n\tD11 Pin = PA08\n\tD12 Pin = PA09\n\tD13 Pin = PB23\n\tD14 Pin = PB22\n\n\t// Remaining pins are shared with analog pins\n\tD15 Pin = PA02\n\n\tD16 Pin = PB02\n\tD17 Pin = PB03\n\tD18 Pin = PA04 // PWM available\n\tD19 Pin = PA05 // PWM available\n\tD20 Pin = PA06\n\tD21 Pin = PA07\n)\n\n// Analog pins\nconst (\n\tA0 Pin = PA02 // ADC/AIN[0]\n\tA1 Pin = PB02 // ADC/AIN[10]\n\tA2 Pin = PB03 // ADC/AIN[11]\n\tA3 Pin = PA04 // ADC/AIN[4]\n\tA4 Pin = PA05 // ADC/AIN[5]\n\tA5 Pin = PA06 // ADC/AIN[6]\n\tA6 Pin = PA07 // ADC/AIN[7]\n)\n\nconst (\n\tSWITCH      Pin = PA28\n\tLED         Pin = PB08\n\tADC_BATTERY Pin = PB09 // ADC/AIN[3]\n)\n\n// P1AM Base Controller\nconst (\n\tBASE_SLAVE_SELECT_PIN Pin = A3\n\tBASE_SLAVE_ACK_PIN    Pin = A4\n\tBASE_ENABLE_PIN       Pin = PB09\n)\n\n// USBCDC pins\nconst (\n\tUSBCDC_DM_PIN          Pin = PA24\n\tUSBCDC_DP_PIN          Pin = PA25\n\tUSBCDC_HOST_ENABLE_PIN Pin = PA18\n)\n\n// UART1 pins\nconst (\n\tUART_RX_PIN Pin = PB23 // RX: SERCOM5/PAD[3]\n\tUART_TX_PIN Pin = PB22 // TX: SERCOM5/PAD[2]\n)\n\n// UART1 on the P1AM-100 connects to the normal TX/RX pins.\nvar UART1 = &sercomUSART5\n\n// I2C pins\nconst (\n\tSDA_PIN Pin = PA08 // SDA:  SERCOM0/PAD[0]\n\tSCL_PIN Pin = PA09 // SCL:  SERCOM0/PAD[1]\n)\n\n// I2C on the P1AM-100.\nvar (\n\tI2C0 = sercomI2CM0\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN Pin = D9  // SCK: SERCOM1/PAD[1]\n\tSPI0_SDO_PIN Pin = D8  // SDO: SERCOM1/PAD[0]\n\tSPI0_SDI_PIN Pin = D10 // SDI: SERCOM1/PAD[3]\n)\n\n// SD card pins\nconst (\n\tSDCARD_SDI_PIN Pin = PA15 // SDI: SERCOM2/PAD[3]\n\tSDCARD_SDO_PIN Pin = PA12 // SDO: SERCOM2/PAD[0]\n\tSDCARD_SCK_PIN Pin = PA13 // SCK: SERCOM2/PAD[1]\n\tSDCARD_SS_PIN  Pin = PA14 // SS: as GPIO\n\tSDCARD_CD_PIN  Pin = PA27\n)\n\n// SPI on the P1AM-100 is used for Base Controller.\nvar (\n\tSPI0                = sercomSPIM1\n\tBASE_CONTROLLER_SPI = SPI0\n)\n\n// SPI1 is connected to the SD card slot on the P1AM-100\nvar (\n\tSPI1       = sercomSPIM2\n\tSDCARD_SPI = SPI1\n)\n\n// I2S pins\nconst (\n\tI2S_SCK_PIN Pin = D2\n\tI2S_SDO_PIN Pin = A6\n\tI2S_SDI_PIN     = NoPin\n\tI2S_WS_PIN      = D3\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"P1AM-100\"\n\tusb_STRING_MANUFACTURER = \"Facts Engineering\"\n)\n\nvar (\n\tusb_VID uint16 = 0x1354\n\tusb_PID uint16 = 0x4000\n)\n"
  },
  {
    "path": "src/machine/board_particle_argon.go",
    "content": "//go:build particle_argon\n\npackage machine\n\nconst HasLowFrequencyCrystal = true\n\n// More info: https://docs.particle.io/datasheets/wi-fi/argon-datasheet/\n// Board diagram: https://docs.particle.io/assets/images/argon/argon-block-diagram.png\n\n// GPIOs\nconst (\n\tA0  Pin = 3\n\tA1  Pin = 4\n\tA2  Pin = 28\n\tA3  Pin = 29\n\tA4  Pin = 30\n\tA5  Pin = 31\n\tD0  Pin = 26 // Also SDA\n\tD1  Pin = 27 // Also SCL\n\tD2  Pin = 33\n\tD3  Pin = 34\n\tD4  Pin = 40\n\tD5  Pin = 42\n\tD6  Pin = 43\n\tD7  Pin = 44 // Also LED\n\tD8  Pin = 35\n\tD9  Pin = 6  // Also TX\n\tD10 Pin = 8  // Also RX\n\tD11 Pin = 46 // Also SDI\n\tD12 Pin = 45 // Also SDO\n\tD13 Pin = 47 // Also SCK\n)\n\n// LEDs\nconst (\n\tLED       Pin = 44\n\tLED_GREEN Pin = 14\n\tLED_RED   Pin = 13\n\tLED_BLUE  Pin = 15\n)\n\n// UART\nvar (\n\tDefaultUART = UART0\n)\n\nconst (\n\tUART_TX_PIN Pin = 6\n\tUART_RX_PIN Pin = 8\n)\n\n// I2C pins\nconst (\n\tSDA_PIN Pin = 26\n\tSCL_PIN Pin = 27\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN Pin = 47\n\tSPI0_SDO_PIN Pin = 45\n\tSPI0_SDI_PIN Pin = 46\n)\n\n// Internal 4MB SPI Flash\nconst (\n\tSPI1_SCK_PIN  Pin = 19\n\tSPI1_SDO_PIN  Pin = 20\n\tSPI1_SDI_PIN  Pin = 21\n\tSPI1_CS_PIN   Pin = 17\n\tSPI1_WP_PIN   Pin = 22\n\tSPI1_HOLD_PIN Pin = 23\n)\n\n// ESP32 coprocessor\nconst (\n\tESP32_TXD_PIN       Pin = 36\n\tESP32_RXD_PIN       Pin = 37\n\tESP32_CTS_PIN       Pin = 39\n\tESP32_RTS_PIN       Pin = 38\n\tESP32_BOOT_MODE_PIN Pin = 16\n\tESP32_WIFI_EN_PIN   Pin = 24\n\tESP32_HOST_WK_PIN   Pin = 7\n)\n\n// Other peripherals\nconst (\n\tMODE_BUTTON_PIN   Pin = 11\n\tCHARGE_STATUS_PIN Pin = 41\n\tLIPO_VOLTAGE_PIN  Pin = 5\n\tPCB_ANTENNA_PIN   Pin = 2\n\tEXTERNAL_UFL_PIN  Pin = 25\n\tNFC1_PIN          Pin = 9\n\tNFC2_PIN          Pin = 10\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Argon\"\n\tusb_STRING_MANUFACTURER = \"Particle\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2B04\n\tusb_PID uint16 = 0xD00C\n)\n"
  },
  {
    "path": "src/machine/board_particle_boron.go",
    "content": "//go:build particle_boron\n\npackage machine\n\nconst HasLowFrequencyCrystal = true\n\n// More info: https://docs.particle.io/datasheets/cellular/boron-datasheet/\n// Board diagram: https://docs.particle.io/assets/images/boron/boron-block-diagram.png\n\n// GPIOs\nconst (\n\tA0  Pin = 3\n\tA1  Pin = 4\n\tA2  Pin = 28\n\tA3  Pin = 29\n\tA4  Pin = 30\n\tA5  Pin = 31\n\tD0  Pin = 26 // Also SDA\n\tD1  Pin = 27 // Also SCL\n\tD2  Pin = 33\n\tD3  Pin = 34\n\tD4  Pin = 40\n\tD5  Pin = 42\n\tD6  Pin = 43\n\tD7  Pin = 44 // Also LED\n\tD8  Pin = 35\n\tD9  Pin = 6  // Also TX\n\tD10 Pin = 8  // Also RX\n\tD11 Pin = 46 // Also SDI\n\tD12 Pin = 45 // Also SDO\n\tD13 Pin = 47 // Also SCK\n)\n\n// LEDs\nconst (\n\tLED       Pin = 44\n\tLED_GREEN Pin = 14\n\tLED_RED   Pin = 13\n\tLED_BLUE  Pin = 15\n)\n\n// UART\nvar (\n\tDefaultUART = UART0\n)\n\nconst (\n\tUART_TX_PIN Pin = 6\n\tUART_RX_PIN Pin = 8\n)\n\n// I2C pins\nconst (\n\tSDA_PIN Pin = 26\n\tSCL_PIN Pin = 27\n\n\t// Internal I2C with MAX17043 (Fuel gauge) and BQ24195 (Power management) chips on it\n\tSDA1_PIN Pin = 24\n\tSCL1_PIN Pin = 41\n\tINT1_PIN Pin = 5\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN Pin = 47\n\tSPI0_SDO_PIN Pin = 45\n\tSPI0_SDI_PIN Pin = 46\n)\n\n// Internal 4MB SPI Flash\nconst (\n\tSPI1_SCK_PIN  Pin = 19\n\tSPI1_SDO_PIN  Pin = 20\n\tSPI1_SDI_PIN  Pin = 21\n\tSPI1_CS_PIN   Pin = 17\n\tSPI1_WP_PIN   Pin = 22\n\tSPI1_HOLD_PIN Pin = 23\n)\n\n// u-blox SARA coprocessor\nconst (\n\tSARA_TXD_PIN      Pin = 37\n\tSARA_RXD_PIN      Pin = 36\n\tSARA_CTS_PIN      Pin = 38\n\tSARA_RTS_PIN      Pin = 39\n\tSARA_RESET_PIN    Pin = 12\n\tSARA_POWER_ON_PIN Pin = 16\n\tSARA_BUFF_EN_PIN  Pin = 25\n\tSARA_VINT_PIN     Pin = 2\n)\n\n// Other peripherals\nconst (\n\tMODE_BUTTON_PIN Pin = 11\n\tANTENNA_SEL_PIN Pin = 7 // Low: chip antenna, High: External uFL\n\tNFC1_PIN        Pin = 9\n\tNFC2_PIN        Pin = 10\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Boron\"\n\tusb_STRING_MANUFACTURER = \"Particle\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2B04\n\tusb_PID uint16 = 0xD00D\n)\n"
  },
  {
    "path": "src/machine/board_particle_xenon.go",
    "content": "//go:build particle_xenon\n\npackage machine\n\nconst HasLowFrequencyCrystal = true\n\n// More info: https://docs.particle.io/datasheets/discontinued/xenon-datasheet/\n// Board diagram: https://docs.particle.io/assets/images/xenon/xenon-block-diagram.png\n\n// GPIOs\nconst (\n\tA0  Pin = 3\n\tA1  Pin = 4\n\tA2  Pin = 28\n\tA3  Pin = 29\n\tA4  Pin = 30\n\tA5  Pin = 31\n\tD0  Pin = 26 // Also SDA\n\tD1  Pin = 27 // Also SCL\n\tD2  Pin = 33\n\tD3  Pin = 34\n\tD4  Pin = 40\n\tD5  Pin = 42\n\tD6  Pin = 43\n\tD7  Pin = 44 // Also LED\n\tD8  Pin = 35\n\tD9  Pin = 6  // Also TX\n\tD10 Pin = 8  // Also RX\n\tD11 Pin = 46 // Also SDI\n\tD12 Pin = 45 // Also SDO\n\tD13 Pin = 47 // Also SCK\n)\n\n// LEDs\nconst (\n\tLED       Pin = 44\n\tLED_GREEN Pin = 14\n\tLED_RED   Pin = 13\n\tLED_BLUE  Pin = 15\n)\n\n// UART\nvar (\n\tDefaultUART = UART0\n)\n\nconst (\n\tUART_TX_PIN Pin = 6\n\tUART_RX_PIN Pin = 8\n)\n\n// I2C pins\nconst (\n\tSDA_PIN Pin = 26\n\tSCL_PIN Pin = 27\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN Pin = 47\n\tSPI0_SDO_PIN Pin = 45\n\tSPI0_SDI_PIN Pin = 46\n)\n\n// Internal 4MB SPI Flash\nconst (\n\tSPI1_SCK_PIN  Pin = 19\n\tSPI1_SDO_PIN  Pin = 20\n\tSPI1_SDI_PIN  Pin = 21\n\tSPI1_CS_PIN   Pin = 17\n\tSPI1_WP_PIN   Pin = 22\n\tSPI1_HOLD_PIN Pin = 23\n)\n\n// Other peripherals\nconst (\n\tMODE_BUTTON_PIN   Pin = 11\n\tCHARGE_STATUS_PIN Pin = 41\n\tLIPO_VOLTAGE_PIN  Pin = 5\n\tPCB_ANTENNA_PIN   Pin = 24\n\tEXTERNAL_UFL_PIN  Pin = 25\n\tNFC1_PIN          Pin = 9\n\tNFC2_PIN          Pin = 10\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Xenon\"\n\tusb_STRING_MANUFACTURER = \"Particle\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2B04\n\tusb_PID uint16 = 0xD00E\n)\n"
  },
  {
    "path": "src/machine/board_pca10031.go",
    "content": "//go:build pca10031\n\n// pca10031 is a nrf51 based dongle, intended for use in wireless applications.\n//\n// https://infocenter.nordicsemi.com/pdf/nRF51_Dongle_UG_v1.0.pdf\npackage machine\n\n// The pca10031 has a 32kHz crystal on board.\nconst HasLowFrequencyCrystal = true\n\n// LED on the pca10031\nconst (\n\tLED1      = LED_RED\n\tLED2      = LED_GREEN\n\tLED3      = LED_BLUE\n\tLED_RED   = P0_21\n\tLED_GREEN = P0_22\n\tLED_BLUE  = P0_23\n\tLED       = LED_RED\n)\n\nvar DefaultUART = UART0\n\n// UART pins\nconst (\n\tUART_TX_PIN = P0_09\n\tUART_RX_PIN = P0_11\n)\n\n// I2C pins (disabled)\nconst (\n\tSDA_PIN = NoPin\n\tSCL_PIN = NoPin\n)\n\n// SPI pins (unused)\nconst (\n\tSPI0_SCK_PIN = NoPin\n\tSPI0_SDO_PIN = NoPin\n\tSPI0_SDI_PIN = NoPin\n)\n"
  },
  {
    "path": "src/machine/board_pca10040.go",
    "content": "//go:build pca10040\n\npackage machine\n\n// The PCA10040 has a low-frequency (32kHz) crystal oscillator on board.\nconst HasLowFrequencyCrystal = true\n\n// LEDs on the PCA10040 (nRF52832 dev board)\nconst (\n\tLED1 Pin = 17\n\tLED2 Pin = 18\n\tLED3 Pin = 19\n\tLED4 Pin = 20\n\tLED  Pin = LED1\n)\n\n// Buttons on the PCA10040 (nRF52832 dev board)\nconst (\n\tBUTTON1 Pin = 13\n\tBUTTON2 Pin = 14\n\tBUTTON3 Pin = 15\n\tBUTTON4 Pin = 16\n\tBUTTON  Pin = BUTTON1\n)\n\nvar DefaultUART = UART0\n\n// UART pins for NRF52840-DK\nconst (\n\tUART_TX_PIN Pin = 6\n\tUART_RX_PIN Pin = 8\n)\n\n// ADC pins\nconst (\n\tADC0 Pin = 3\n\tADC1 Pin = 4\n\tADC2 Pin = 28\n\tADC3 Pin = 29\n\tADC4 Pin = 30\n\tADC5 Pin = 31\n)\n\n// I2C pins\nconst (\n\tSDA_PIN Pin = 26\n\tSCL_PIN Pin = 27\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN Pin = 25\n\tSPI0_SDO_PIN Pin = 23\n\tSPI0_SDI_PIN Pin = 24\n)\n"
  },
  {
    "path": "src/machine/board_pca10056.go",
    "content": "//go:build pca10056\n\npackage machine\n\nconst HasLowFrequencyCrystal = true\n\n// LEDs on the pca10056\nconst (\n\tLED1 Pin = 13\n\tLED2 Pin = 14\n\tLED3 Pin = 15\n\tLED4 Pin = 16\n\tLED  Pin = LED1\n)\n\n// Buttons on the pca10056\nconst (\n\tBUTTON1 Pin = 11\n\tBUTTON2 Pin = 12\n\tBUTTON3 Pin = 24\n\tBUTTON4 Pin = 25\n\tBUTTON  Pin = BUTTON1\n)\n\nvar DefaultUART = UART0\n\n// UART pins\nconst (\n\tUART_TX_PIN Pin = 6\n\tUART_RX_PIN Pin = 8\n)\n\n// ADC pins\nconst (\n\tADC0 Pin = 3\n\tADC1 Pin = 4\n\tADC2 Pin = 28\n\tADC3 Pin = 29\n\tADC4 Pin = 30\n\tADC5 Pin = 31\n)\n\n// I2C pins\nconst (\n\tSDA_PIN Pin = 26 // P0.26\n\tSCL_PIN Pin = 27 // P0.27\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN Pin = 47 // P1.15\n\tSPI0_SDO_PIN Pin = 45 // P1.13\n\tSPI0_SDI_PIN Pin = 46 // P1.14\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Nordic nRF52840DK (PCA10056)\"\n\tusb_STRING_MANUFACTURER = \"Nordic Semiconductor\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x8029\n)\n"
  },
  {
    "path": "src/machine/board_pca10059.go",
    "content": "//go:build pca10059\n\npackage machine\n\n// The PCA10040 has a low-frequency (32kHz) crystal oscillator on board.\nconst HasLowFrequencyCrystal = true\n\n// LEDs on the PCA10059 (nRF52840 dongle)\nconst (\n\tLED1 Pin = 6\n\tLED2 Pin = 8\n\tLED3 Pin = (1 << 5) | 9\n\tLED4 Pin = 12\n\tLED  Pin = LED1\n)\n\n// Buttons on the PCA10059 (nRF52840 dongle)\nconst (\n\tBUTTON1 Pin = (1 << 5) | 6\n\tBUTTON  Pin = BUTTON1\n)\n\n// ADC pins\nconst (\n\tADC1 Pin = 2\n\tADC2 Pin = 4\n\tADC3 Pin = 29\n\tADC4 Pin = 31\n)\n\n// UART pins\nconst (\n\tUART_TX_PIN Pin = NoPin\n\tUART_RX_PIN Pin = NoPin\n)\n\n// I2C pins (unused)\nconst (\n\tSDA_PIN = NoPin\n\tSCL_PIN = NoPin\n)\n\n// SPI pins (unused)\nconst (\n\tSPI0_SCK_PIN = NoPin\n\tSPI0_SDO_PIN = NoPin\n\tSPI0_SDI_PIN = NoPin\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"nRF52840 Dongle\"\n\tusb_STRING_MANUFACTURER = \"Nordic Semiconductor ASA\"\n)\n\nvar (\n\tusb_VID uint16 = 0x1915\n\tusb_PID uint16 = 0xCAFE\n)\n"
  },
  {
    "path": "src/machine/board_pga2350.go",
    "content": "//go:build pga2350\n\npackage machine\n\n// PGA2350 pin definitions.\nconst (\n\tGP0  = GPIO0\n\tGP1  = GPIO1\n\tGP2  = GPIO2\n\tGP3  = GPIO3\n\tGP4  = GPIO4\n\tGP5  = GPIO5\n\tGP6  = GPIO6\n\tGP7  = GPIO7\n\tGP8  = GPIO8\n\tGP9  = GPIO9\n\tGP10 = GPIO10\n\tGP11 = GPIO11\n\tGP12 = GPIO12\n\tGP13 = GPIO13\n\tGP14 = GPIO14\n\tGP15 = GPIO15\n\tGP16 = GPIO16\n\tGP17 = GPIO17\n\tGP18 = GPIO18\n\tGP19 = GPIO19\n\tGP20 = GPIO20\n\tGP21 = GPIO21\n\tGP22 = GPIO22\n\tGP26 = GPIO26\n\tGP27 = GPIO27\n\tGP28 = GPIO28\n\tGP29 = GPIO29\n\tGP30 = GPIO30\n\tGP31 = GPIO31\n\tGP32 = GPIO32\n\tGP33 = GPIO33\n\tGP34 = GPIO34\n\tGP35 = GPIO35\n\tGP36 = GPIO36\n\tGP37 = GPIO37\n\tGP38 = GPIO38\n\tGP39 = GPIO39\n\tGP40 = GPIO40\n\tGP41 = GPIO41\n\tGP42 = GPIO42\n\tGP43 = GPIO43\n\tGP44 = GPIO44\n\tGP45 = GPIO45\n\tGP46 = GPIO46\n\tGP47 = GPIO47\n)\n\nvar DefaultUART = UART0\n\n// Peripheral defaults.\nconst (\n\txoscFreq = 12 // MHz\n\n\tI2C0_SDA_PIN = GP4\n\tI2C0_SCL_PIN = GP5\n\n\tI2C1_SDA_PIN = GP2\n\tI2C1_SCL_PIN = GP3\n\n\t// Default Serial Clock Bus 0 for SPI communications\n\tSPI0_SCK_PIN = GPIO18\n\t// Default Serial Out Bus 0 for SPI communications\n\tSPI0_SDO_PIN = GPIO19 // Tx\n\t// Default Serial In Bus 0 for SPI communications\n\tSPI0_SDI_PIN = GPIO16 // Rx\n\n\t// Default Serial Clock Bus 1 for SPI communications\n\tSPI1_SCK_PIN = GPIO10\n\t// Default Serial Out Bus 1 for SPI communications\n\tSPI1_SDO_PIN = GPIO11 // Tx\n\t// Default Serial In Bus 1 for SPI communications\n\tSPI1_SDI_PIN = GPIO12 // Rx\n\n\tUART0_TX_PIN = GPIO0\n\tUART0_RX_PIN = GPIO1\n\tUART1_TX_PIN = GPIO8\n\tUART1_RX_PIN = GPIO9\n\tUART_TX_PIN  = UART0_TX_PIN\n\tUART_RX_PIN  = UART0_RX_PIN\n)\n\n// USB identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"PGA2350\"\n\tusb_STRING_MANUFACTURER = \"Pimoroni\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2E8A\n\tusb_PID uint16 = 0x000A\n)\n"
  },
  {
    "path": "src/machine/board_pico.go",
    "content": "//go:build pico\n\npackage machine\n\n// GPIO pins\nconst (\n\tGP0  Pin = GPIO0\n\tGP1  Pin = GPIO1\n\tGP2  Pin = GPIO2\n\tGP3  Pin = GPIO3\n\tGP4  Pin = GPIO4\n\tGP5  Pin = GPIO5\n\tGP6  Pin = GPIO6\n\tGP7  Pin = GPIO7\n\tGP8  Pin = GPIO8\n\tGP9  Pin = GPIO9\n\tGP10 Pin = GPIO10\n\tGP11 Pin = GPIO11\n\tGP12 Pin = GPIO12\n\tGP13 Pin = GPIO13\n\tGP14 Pin = GPIO14\n\tGP15 Pin = GPIO15\n\tGP16 Pin = GPIO16\n\tGP17 Pin = GPIO17\n\tGP18 Pin = GPIO18\n\tGP19 Pin = GPIO19\n\tGP20 Pin = GPIO20\n\tGP21 Pin = GPIO21\n\tGP22 Pin = GPIO22\n\tGP26 Pin = GPIO26\n\tGP27 Pin = GPIO27\n\tGP28 Pin = GPIO28\n\n\t// Onboard LED\n\tLED Pin = GPIO25\n\n\t// Onboard crystal oscillator frequency, in MHz.\n\txoscFreq = 12 // MHz\n)\n\n// I2C Default pins on Raspberry Pico.\nconst (\n\tI2C0_SDA_PIN = GP4\n\tI2C0_SCL_PIN = GP5\n\n\tI2C1_SDA_PIN = GP2\n\tI2C1_SCL_PIN = GP3\n)\n\n// SPI default pins\nconst (\n\t// Default Serial Clock Bus 0 for SPI communications\n\tSPI0_SCK_PIN = GPIO18\n\t// Default Serial Out Bus 0 for SPI communications\n\tSPI0_SDO_PIN = GPIO19 // Tx\n\t// Default Serial In Bus 0 for SPI communications\n\tSPI0_SDI_PIN = GPIO16 // Rx\n\n\t// Default Serial Clock Bus 1 for SPI communications\n\tSPI1_SCK_PIN = GPIO10\n\t// Default Serial Out Bus 1 for SPI communications\n\tSPI1_SDO_PIN = GPIO11 // Tx\n\t// Default Serial In Bus 1 for SPI communications\n\tSPI1_SDI_PIN = GPIO12 // Rx\n)\n\n// UART pins\nconst (\n\tUART0_TX_PIN = GPIO0\n\tUART0_RX_PIN = GPIO1\n\tUART1_TX_PIN = GPIO8\n\tUART1_RX_PIN = GPIO9\n\tUART_TX_PIN  = UART0_TX_PIN\n\tUART_RX_PIN  = UART0_RX_PIN\n)\n\nvar DefaultUART = UART0\n\n// USB identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Pico\"\n\tusb_STRING_MANUFACTURER = \"Raspberry Pi\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2E8A\n\tusb_PID uint16 = 0x000A\n)\n"
  },
  {
    "path": "src/machine/board_pico2.go",
    "content": "//go:build pico2\n\npackage machine\n\n// GPIO pins\nconst (\n\tGP0  Pin = GPIO0\n\tGP1  Pin = GPIO1\n\tGP2  Pin = GPIO2\n\tGP3  Pin = GPIO3\n\tGP4  Pin = GPIO4\n\tGP5  Pin = GPIO5\n\tGP6  Pin = GPIO6\n\tGP7  Pin = GPIO7\n\tGP8  Pin = GPIO8\n\tGP9  Pin = GPIO9\n\tGP10 Pin = GPIO10\n\tGP11 Pin = GPIO11\n\tGP12 Pin = GPIO12\n\tGP13 Pin = GPIO13\n\tGP14 Pin = GPIO14\n\tGP15 Pin = GPIO15\n\tGP16 Pin = GPIO16\n\tGP17 Pin = GPIO17\n\tGP18 Pin = GPIO18\n\tGP19 Pin = GPIO19\n\tGP20 Pin = GPIO20\n\tGP21 Pin = GPIO21\n\tGP22 Pin = GPIO22\n\tGP26 Pin = GPIO26\n\tGP27 Pin = GPIO27\n\tGP28 Pin = GPIO28\n\n\t// Onboard LED\n\tLED Pin = GPIO25\n\n\t// Onboard crystal oscillator frequency, in MHz.\n\txoscFreq = 12 // MHz\n)\n\n// I2C Default pins on Raspberry Pico.\nconst (\n\tI2C0_SDA_PIN = GP4\n\tI2C0_SCL_PIN = GP5\n\n\tI2C1_SDA_PIN = GP2\n\tI2C1_SCL_PIN = GP3\n)\n\n// SPI default pins\nconst (\n\t// Default Serial Clock Bus 0 for SPI communications\n\tSPI0_SCK_PIN = GPIO18\n\t// Default Serial Out Bus 0 for SPI communications\n\tSPI0_SDO_PIN = GPIO19 // Tx\n\t// Default Serial In Bus 0 for SPI communications\n\tSPI0_SDI_PIN = GPIO16 // Rx\n\n\t// Default Serial Clock Bus 1 for SPI communications\n\tSPI1_SCK_PIN = GPIO10\n\t// Default Serial Out Bus 1 for SPI communications\n\tSPI1_SDO_PIN = GPIO11 // Tx\n\t// Default Serial In Bus 1 for SPI communications\n\tSPI1_SDI_PIN = GPIO12 // Rx\n)\n\n// UART pins\nconst (\n\tUART0_TX_PIN = GPIO0\n\tUART0_RX_PIN = GPIO1\n\tUART1_TX_PIN = GPIO8\n\tUART1_RX_PIN = GPIO9\n\tUART_TX_PIN  = UART0_TX_PIN\n\tUART_RX_PIN  = UART0_RX_PIN\n)\n\nvar DefaultUART = UART0\n\n// USB identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Pico2\"\n\tusb_STRING_MANUFACTURER = \"Raspberry Pi\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2E8A\n\tusb_PID uint16 = 0x000A\n)\n"
  },
  {
    "path": "src/machine/board_pico2_ice.go",
    "content": "//go:build pico2_ice\n\n// Most of the info is from\n// https://pico2-ice.tinyvision.ai/md_pinout.html although\n// (2025-09-07) RP4 appears twice in that pinout - the schematic is\n// more clear. Consistent with other RPi boards, we use GPn instead of\n// RPn to reference the RPi connected pins.\n\npackage machine\n\n// GPIO pins\nconst (\n\tGP0  = GPIO0\n\tGP1  = GPIO1\n\tGP2  = GPIO2\n\tGP3  = GPIO3\n\tGP4  = GPIO4\n\tGP5  = GPIO5\n\tGP6  = GPIO6\n\tGP7  = GPIO7\n\tGP8  = GPIO8\n\tGP9  = GPIO9\n\tGP10 = GPIO10\n\tGP11 = GPIO11\n\tGP12 = GPIO12\n\tGP13 = GPIO13\n\tGP14 = GPIO14\n\tGP15 = GPIO15\n\tGP16 = GPIO16\n\tGP17 = GPIO17\n\tGP18 = GPIO18\n\tGP19 = GPIO19\n\tGP20 = GPIO20\n\tGP21 = GPIO21\n\tGP22 = GPIO22\n\tGP23 = GPIO23\n\tGP24 = GPIO24\n\tGP25 = GPIO25\n\tGP26 = GPIO26\n\tGP27 = GPIO27\n\tGP28 = GPIO28\n\tGP29 = GPIO29\n\tGP30 = GPIO30\n\tGP31 = GPIO31\n\tGP32 = GPIO32\n\tGP33 = GPIO33\n\tGP34 = GPIO34\n\tGP35 = GPIO35\n\tGP36 = GPIO36\n\tGP37 = GPIO37\n\tGP38 = GPIO38\n\tGP39 = GPIO39\n\tGP40 = GPIO40\n\tGP41 = GPIO41\n\tGP42 = GPIO42\n\tGP43 = GPIO43\n\tGP44 = GPIO44\n\tGP45 = GPIO45\n\tGP46 = GPIO46\n\tGP47 = GPIO47\n\n\t// RPi pins shared with ICE. The ICE number is what appears on\n\t// the board silkscreen.\n\tICE9  = GP28\n\tICE11 = GP29\n\tICE14 = GP7\n\tICE15 = GP6\n\tICE16 = GP5\n\tICE17 = GP4\n\tICE18 = GP27\n\tICE19 = GP23\n\tICE20 = GP22\n\tICE21 = GP26\n\tICE23 = GP25\n\tICE25 = GP30\n\tICE26 = GP24\n\tICE27 = GP20\n\n\t// FPGA Clock pin.\n\tICE35_G0 = GP21\n\n\t// Silkscreen & Pinout names\n\tICE_SSN = ICE16\n\tICE_SO  = ICE14\n\tICE_SI  = ICE17\n\tICE_CK  = ICE15\n\tSD      = GP2\n\tSC      = GP3\n\n\tFPGA_RSTN = GP31\n\tA3        = GP32\n\tA1        = GP33\n\tA4        = GP34\n\tA2        = GP35\n\tB3        = GP36\n\tB1        = GP37\n\tB4        = GP38\n\tB2        = GP39\n\tN0        = GP40 // On the board these are labeled \"~0\"\n\tN1        = GP41\n\tN2        = GP42\n\tN3        = GP43\n\tN4        = GP44\n\tN5        = GP45\n\tN6        = GP46\n\n\t// Functions from Schematic.\n\tICE_DONE = GP40\n\tUSB_BOOT = GP42\n\n\t// Button\n\tSW1     = GP42\n\tBOOTSEL = GP42\n\n\t// Tricolor LEDs\n\tLED_RED   = GP1\n\tLED_GREEN = GP0\n\tLED_BLUE  = GP9\n\n\t// Onboard LED\n\tLED = LED_GREEN\n\n\t// Onboard crystal oscillator frequency, in MHz.\n\txoscFreq = 12 // MHz\n)\n\n// This board does not define default i2c pins.\nconst (\n\tI2C0_SDA_PIN = NoPin\n\tI2C0_SCL_PIN = NoPin\n\tI2C1_SDA_PIN = NoPin\n\tI2C1_SCL_PIN = NoPin\n)\n\n// SPI default pins\nconst (\n\t// Default Serial Clock Bus 0 for SPI communications\n\tSPI0_SCK_PIN = GPIO18\n\t// Default Serial Out Bus 0 for SPI communications\n\tSPI0_SDO_PIN = GPIO19 // Tx\n\t// Default Serial In Bus 0 for SPI communications\n\tSPI0_SDI_PIN = GPIO16 // Rx\n\n\t// Default Serial Clock Bus 1 for SPI communications\n\tSPI1_SCK_PIN = GPIO10\n\t// Default Serial Out Bus 1 for SPI communications\n\tSPI1_SDO_PIN = GPIO11 // Tx\n\t// Default Serial In Bus 1 for SPI communications\n\tSPI1_SDI_PIN = GPIO12 // Rx\n)\n\n// UART pins\nconst (\n\tUART0_TX_PIN = GPIO0\n\tUART0_RX_PIN = GPIO1\n\tUART1_TX_PIN = GPIO8\n\tUART1_RX_PIN = GPIO9\n\tUART_TX_PIN  = UART0_TX_PIN\n\tUART_RX_PIN  = UART0_RX_PIN\n)\n\nvar DefaultUART = UART0\n\n// USB identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Pico2\"\n\tusb_STRING_MANUFACTURER = \"Raspberry Pi\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2E8A\n\tusb_PID uint16 = 0x000A\n)\n"
  },
  {
    "path": "src/machine/board_pico_plus2.go",
    "content": "//go:build pico_plus2\n\npackage machine\n\n// GPIO pins\nconst (\n\tGP0  Pin = GPIO0\n\tGP1  Pin = GPIO1\n\tGP2  Pin = GPIO2\n\tGP3  Pin = GPIO3\n\tGP4  Pin = GPIO4\n\tGP5  Pin = GPIO5\n\tGP6  Pin = GPIO6\n\tGP7  Pin = GPIO7\n\tGP8  Pin = GPIO8\n\tGP9  Pin = GPIO9\n\tGP10 Pin = GPIO10\n\tGP11 Pin = GPIO11\n\tGP12 Pin = GPIO12\n\tGP13 Pin = GPIO13\n\tGP14 Pin = GPIO14\n\tGP15 Pin = GPIO15\n\tGP16 Pin = GPIO16\n\tGP17 Pin = GPIO17\n\tGP18 Pin = GPIO18\n\tGP19 Pin = GPIO19\n\tGP20 Pin = GPIO20\n\tGP21 Pin = GPIO21\n\tGP22 Pin = GPIO22\n\tGP26 Pin = GPIO26\n\tGP27 Pin = GPIO27\n\tGP28 Pin = GPIO28\n\tGP32 Pin = GPIO32\n\tGP33 Pin = GPIO33\n\tGP34 Pin = GPIO34\n\tGP35 Pin = GPIO35\n\tGP36 Pin = GPIO36\n\n\t// Onboard LED\n\tLED Pin = GPIO25\n\n\t// Onboard crystal oscillator frequency, in MHz.\n\txoscFreq = 12 // MHz\n)\n\n// I2C Default pins on Raspberry Pico.\nconst (\n\tI2C0_SDA_PIN = GP4\n\tI2C0_SCL_PIN = GP5\n\n\tI2C1_SDA_PIN = GP2\n\tI2C1_SCL_PIN = GP3\n)\n\n// SPI default pins\nconst (\n\t// Default Serial Clock Bus 0 for SPI communications\n\tSPI0_SCK_PIN = GPIO18\n\t// Default Serial Out Bus 0 for SPI communications\n\tSPI0_SDO_PIN = GPIO19 // Tx\n\t// Default Serial In Bus 0 for SPI communications\n\tSPI0_SDI_PIN = GPIO16 // Rx\n\n\t// Default Serial Clock Bus 1 for SPI communications\n\tSPI1_SCK_PIN = GPIO10\n\t// Default Serial Out Bus 1 for SPI communications\n\tSPI1_SDO_PIN = GPIO11 // Tx\n\t// Default Serial In Bus 1 for SPI communications\n\tSPI1_SDI_PIN = GPIO12 // Rx\n)\n\n// UART pins\nconst (\n\tUART0_TX_PIN = GPIO0\n\tUART0_RX_PIN = GPIO1\n\tUART1_TX_PIN = GPIO8\n\tUART1_RX_PIN = GPIO9\n\tUART_TX_PIN  = UART0_TX_PIN\n\tUART_RX_PIN  = UART0_RX_PIN\n)\n\nvar DefaultUART = UART0\n\n// USB identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Pico Plus2\"\n\tusb_STRING_MANUFACTURER = \"Pimoroni\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2E8A\n\tusb_PID uint16 = 0x000F\n)\n"
  },
  {
    "path": "src/machine/board_pinetime.go",
    "content": "//go:build pinetime\n\npackage machine\n\n// Board pins for the PineTime.\n// Details: https://wiki.pine64.org/index.php/PineTime\n\n// The PineTime has a low-frequency (32kHz) crystal oscillator on board.\nconst HasLowFrequencyCrystal = true\n\n// LEDs simply expose the three brightness level LEDs on the PineTime. They can\n// be useful for simple \"hello world\" style programs.\nconst (\n\tLED1 = LCD_BACKLIGHT_HIGH\n\tLED2 = LCD_BACKLIGHT_MID\n\tLED3 = LCD_BACKLIGHT_LOW\n\tLED  = LED1\n)\n\n// The PineTime doesn't have a UART output.\n// Additionally, leaving the UART on results in a pretty big current drain.\nconst (\n\tUART_TX_PIN Pin = NoPin\n\tUART_RX_PIN Pin = NoPin\n)\n\n// SPI pins for the PineTime.\nconst (\n\tSPI0_SCK_PIN Pin = 2\n\tSPI0_SDO_PIN Pin = 3\n\tSPI0_SDI_PIN Pin = 4\n)\n\n// I2C pins for the PineTime.\nconst (\n\tSDA_PIN Pin = 6\n\tSCL_PIN Pin = 7\n)\n\n// Button pins. For some reason, there are two pins for the button.\nconst (\n\tBUTTON_IN  Pin = 13\n\tBUTTON_OUT Pin = 15\n)\n\n// Pin for the vibrator.\nconst VIBRATOR_PIN Pin = 16\n\n// LCD pins, using the naming convention of the official docs:\n// http://files.pine64.org/doc/PineTime/PineTime%20Port%20Assignment%20rev1.0.pdf\nconst (\n\tLCD_SCK                = SPI0_SCK_PIN\n\tLCD_SDI                = SPI0_SDO_PIN\n\tLCD_RS             Pin = 18\n\tLCD_CS             Pin = 25\n\tLCD_RESET          Pin = 26\n\tLCD_BACKLIGHT_LOW  Pin = 14\n\tLCD_BACKLIGHT_MID  Pin = 22\n\tLCD_BACKLIGHT_HIGH Pin = 23\n)\n"
  },
  {
    "path": "src/machine/board_pybadge.go",
    "content": "//go:build pybadge\n\npackage machine\n\n// used to reset into bootloader\nconst resetMagicValue = 0xf01669ef\n\n// GPIO Pins\nconst (\n\tD0  = PB17 // UART0 RX/PWM available\n\tD1  = PB16 // UART0 TX/PWM available\n\tD2  = PB03\n\tD3  = PB02\n\tD4  = PA14 // PWM available\n\tD5  = PA16 // PWM available\n\tD6  = PA18 // PWM available\n\tD7  = PB14\n\tD8  = PA15 // built-in neopixel\n\tD9  = PA19 // PWM available\n\tD10 = PA20 // can be used for PWM or UART1 TX\n\tD11 = PA21 // can be used for PWM or UART1 RX\n\tD12 = PA22 // PWM available\n\tD13 = PA23 // PWM available\n)\n\n// Analog pins\nconst (\n\tA0 = PA02 // ADC/AIN[0]\n\tA1 = PA05 // ADC/AIN[2]\n\tA2 = PB08 // ADC/AIN[3]\n\tA3 = PB09 // ADC/AIN[4]\n\tA4 = PA04 // ADC/AIN[5]\n\tA5 = PA06 // ADC/AIN[6]\n\tA6 = PB01 // ADC/AIN[12]/VMEAS\n\tA7 = PB04 // ADC/AIN[6]/LIGHT\n\tA8 = D2   // ADC/AIN[14]\n\tA9 = D3   // ADC/AIN[15]\n)\n\nconst (\n\tLED       = D13\n\tNEOPIXELS = D8\n\tWS2812    = D8\n\n\tLIGHTSENSOR = A7\n\n\tBUTTON_LATCH = PB00\n\tBUTTON_OUT   = PB30\n\tBUTTON_CLK   = PB31\n\n\tTFT_DC   = PB05\n\tTFT_CS   = PB07\n\tTFT_RST  = PA00\n\tTFT_LITE = PA01\n\n\tSPEAKER_ENABLE = PA27\n)\n\nconst (\n\tBUTTON_LEFT_MASK   = 1\n\tBUTTON_UP_MASK     = 2\n\tBUTTON_DOWN_MASK   = 4\n\tBUTTON_RIGHT_MASK  = 8\n\tBUTTON_SELECT_MASK = 16\n\tBUTTON_START_MASK  = 32\n\tBUTTON_A_MASK      = 64\n\tBUTTON_B_MASK      = 128\n)\n\n// USBCDC pins\nconst (\n\tUSBCDC_DM_PIN = PA24\n\tUSBCDC_DP_PIN = PA25\n)\n\n// UART1 pins\nconst (\n\tUART_TX_PIN = D1\n\tUART_RX_PIN = D0\n)\n\nconst (\n\tUART2_TX_PIN = A4\n\tUART2_RX_PIN = A5\n)\n\nvar (\n\tUART1 = &sercomUSART5\n\tUART2 = &sercomUSART0\n\n\tDefaultUART = UART1\n)\n\n// I2C pins\nconst (\n\tSDA_PIN = PA12 // SDA: SERCOM2/PAD[0]\n\tSCL_PIN = PA13 // SCL: SERCOM2/PAD[1]\n)\n\n// I2C on the ItsyBitsy M4.\nvar I2C0 = sercomI2CM2\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = PA17 // SCK: SERCOM1/PAD[1]\n\tSPI0_SDO_PIN = PB23 // SDO: SERCOM1/PAD[3]\n\tSPI0_SDI_PIN = PB22 // SDI: SERCOM1/PAD[2]\n)\n\n// TFT SPI pins\nconst (\n\tSPI1_SCK_PIN = PB13 // SCK: SERCOM4/PAD[1]\n\tSPI1_SDO_PIN = PB15 // SDO: SERCOM4/PAD[3]\n\tSPI1_SDI_PIN = NoPin\n)\n\n// SPI on the PyBadge.\nvar SPI0 = sercomSPIM1\n\n// TFT SPI on the PyBadge.\nvar SPI1 = sercomSPIM4\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Adafruit pyBadge M4\"\n\tusb_STRING_MANUFACTURER = \"Adafruit\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x8033\n)\n\n// NINA-W102 settings when using AirLift WiFi FeatherWing\nconst (\n\tNINA_BAUDRATE         = 115200\n\tNINA_RESET_INVERTED   = true\n\tNINA_SOFT_FLOWCONTROL = true\n)\n\nconst (\n\tNINA_CS     = D13\n\tNINA_ACK    = D11\n\tNINA_GPIO0  = D10\n\tNINA_RESETN = D12\n\n\t// pins used for the ESP32 connection do not allow hardware\n\t// flow control, which is required. have to emulate with software.\n\tNINA_TX  = UART_TX_PIN\n\tNINA_RX  = UART_RX_PIN\n\tNINA_CTS = NINA_ACK\n\tNINA_RTS = NINA_GPIO0\n\n\tNINA_SDO = SPI0_SDO_PIN\n\tNINA_SDI = SPI0_SDI_PIN\n\tNINA_SCK = SPI0_SCK_PIN\n)\n\nvar (\n\tNINA_SPI  = SPI0\n\tUART_NINA = UART1\n)\n"
  },
  {
    "path": "src/machine/board_pygamer.go",
    "content": "//go:build sam && atsamd51 && pygamer\n\npackage machine\n\n// used to reset into bootloader\nconst resetMagicValue = 0xf01669ef\n\n// GPIO Pins\nconst (\n\tD0  = PB17 // UART0 RX/PWM available\n\tD1  = PB16 // UART0 TX/PWM available\n\tD2  = PB03\n\tD3  = PB02\n\tD4  = PA14 // PWM available\n\tD5  = PA16 // PWM available\n\tD6  = PA18 // PWM available\n\tD7  = PB14 // CS for microSD card slot\n\tD8  = PA15 // built-in neopixel\n\tD9  = PA19 // PWM available\n\tD10 = PA20 // can be used for PWM or UART1 TX\n\tD11 = PA21 // can be used for PWM or UART1 RX\n\tD12 = PA22 // PWM available\n\tD13 = PA23 // PWM available\n)\n\n// Analog pins\nconst (\n\tA0 = PA02 // ADC/AIN[0]\n\tA1 = PA05 // ADC/AIN[2]\n\tA2 = PB08 // ADC/AIN[3]\n\tA3 = PB09 // ADC/AIN[4]\n\tA4 = PA04 // ADC/AIN[5]\n\tA5 = PA06 // ADC/AIN[6]\n\tA6 = PB01 // ADC/AIN[12]/VMEAS\n\tA7 = PB04 // ADC/AIN[6]/LIGHT\n\tA8 = D2   // ADC/AIN[14]\n\tA9 = D3   // ADC/AIN[15]\n)\n\nconst (\n\tLED       = D13\n\tNEOPIXELS = D8\n\tWS2812    = D8\n\n\tSD_CS = D7\n\n\tLIGHTSENSOR = A7\n\n\tBUTTON_LATCH = PB00\n\tBUTTON_OUT   = PB30\n\tBUTTON_CLK   = PB31\n\n\tJOYY = PB06\n\tJOYX = PB07\n\n\tTFT_DC   = PB05\n\tTFT_CS   = PB12\n\tTFT_RST  = PA00\n\tTFT_LITE = PA01\n\n\tSPEAKER_ENABLE = PA27\n)\n\nconst (\n\tBUTTON_SELECT_MASK = 16\n\tBUTTON_START_MASK  = 32\n\tBUTTON_A_MASK      = 64\n\tBUTTON_B_MASK      = 128\n)\n\n// USBCDC pins\nconst (\n\tUSBCDC_DM_PIN = PA24\n\tUSBCDC_DP_PIN = PA25\n)\n\n// UART1 pins\nconst (\n\tUART_TX_PIN = D1\n\tUART_RX_PIN = D0\n)\n\n// UART1 var is on SERCOM3, defined in atsamd51.go\n\n// UART2 pins\nconst (\n\tUART2_TX_PIN = A4\n\tUART2_RX_PIN = A5\n)\n\n// UART2 var is on SERCOM0, defined in atsamd51.go\n\n// I2C pins\nconst (\n\tSDA_PIN = PA12 // SDA: SERCOM2/PAD[0]\n\tSCL_PIN = PA13 // SCL: SERCOM2/PAD[1]\n)\n\n// I2C on the PyGamer.\nvar (\n\tI2C0 = sercomI2CM2\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = PA17 // SCK: SERCOM1/PAD[1]\n\tSPI0_SDO_PIN = PB23 // SDO: SERCOM1/PAD[3]\n\tSPI0_SDI_PIN = PB22 // SDI: SERCOM1/PAD[2]\n)\n\n// SPI on the PyGamer.\nvar SPI0 = sercomSPIM1\n\n// TFT SPI pins\nconst (\n\tSPI1_SCK_PIN = PB13 // SCK: SERCOM4/PAD[1]\n\tSPI1_SDO_PIN = PB15 // SDO: SERCOM4/PAD[3]\n\tSPI1_SDI_PIN = NoPin\n)\n\n// TFT SPI on the PyGamer.\nvar SPI1 = sercomSPIM4\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Adafruit pyGamer M4\"\n\tusb_STRING_MANUFACTURER = \"Adafruit\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x8033\n)\n"
  },
  {
    "path": "src/machine/board_pyportal.go",
    "content": "//go:build pyportal\n\npackage machine\n\n// used to reset into bootloader\nconst resetMagicValue = 0xf01669ef\n\n// GPIO Pins\nconst (\n\tD0  = PB13 // NINA_RX\n\tD1  = PB12 // NINA_TX\n\tD2  = PB22 // built-in neopixel\n\tD3  = PA04 // PWM available\n\tD4  = PA05 // PWM available\n\tD5  = PB16 // NINA_ACK\n\tD6  = PB15 // NINA_GPIO0\n\tD7  = PB17 // NINA_RESETN\n\tD8  = PB14 // NINA_CS\n\tD9  = PB04 // TFT_RD\n\tD10 = PB05 // TFT_DC\n\tD11 = PB06 // TFT_CS\n\tD12 = PB07 // TFT_TE\n\tD13 = PB23 // built-in LED\n\tD24 = PA00 // TFT_RESET\n\tD25 = PB31 // TFT_BACKLIGHT\n\tD26 = PB09 // TFT_WR\n\tD27 = PB02 // SDA\n\tD28 = PB03 // SCL\n\tD29 = PA12 // SDO\n\tD30 = PA13 // SCK\n\tD31 = PA14 // SDI\n\tD32 = PB30 // SD_CS\n\tD33 = PA01 // SD_CARD_DETECT\n\tD34 = PA16 // LCD_DATA0\n\tD35 = PA17 // LCD_DATA1\n\tD36 = PA18 // LCD_DATA2\n\tD37 = PA19 // LCD_DATA3\n\tD38 = PA20 // LCD_DATA4\n\tD39 = PA21 // LCD_DATA5\n\tD40 = PA22 // LCD_DATA6\n\tD41 = PA23 // LCD_DATA7\n\tD42 = PB10 // QSPI\n\tD43 = PB11 // QSPI\n\tD44 = PA08 // QSPI\n\tD45 = PA09 // QSPI\n\tD46 = PA10 // QSPI\n\tD47 = PA11 // QSPI\n\tD50 = PA02 // speaker amplifier shutdown\n\tD51 = PA15 // NINA_RTS\n\n\tNINA_CS     = D8\n\tNINA_ACK    = D5\n\tNINA_GPIO0  = D6\n\tNINA_RESETN = D7\n\n\t// pins used for the ESP32 connection do not allow hardware\n\t// flow control, which is required. have to emulate with software.\n\tNINA_TX  = D1\n\tNINA_RX  = D0\n\tNINA_CTS = NINA_ACK\n\tNINA_RTS = NINA_GPIO0\n\n\tLCD_DATA0 = D34\n\n\tTFT_RD        = D9\n\tTFT_DC        = D10\n\tTFT_CS        = D11\n\tTFT_TE        = D12\n\tTFT_RESET     = D24\n\tTFT_BACKLIGHT = D25\n\tTFT_WR        = D26\n\n\tNEOPIXEL = D2\n\tWS2812   = D2\n\tSPK_SD   = D50\n)\n\n// Analog pins\nconst (\n\tA0 = PA02 // ADC0/AIN[0]\n\tA1 = D3   // ADC0/AIN[4]\n\tA2 = PA07 // ADC0/AIN[7]\n\tA3 = D4   // ADC0/AIN[5]\n\tA4 = PB00 // ADC0/AIN[12]\n\tA5 = PB01 // ADC0/AIN[13]\n\tA6 = PA06 // ADC0/AIN[6]\n\tA7 = PB08 // ADC1/AIN[0]\n\n\tAUDIO_OUT = A0\n\tLIGHT     = A2\n\tTOUCH_YD  = A4\n\tTOUCH_XL  = A5\n\tTOUCH_YU  = A6\n\tTOUCH_XR  = A7\n)\n\nconst (\n\tLED = D13\n)\n\n// USBCDC pins\nconst (\n\tUSBCDC_DM_PIN = PA24\n\tUSBCDC_DP_PIN = PA25\n)\n\n// UART1 aka NINA_TX/NINA_RX\nconst (\n\tUART_TX_PIN = D1\n\tUART_RX_PIN = D0\n)\n\nvar (\n\tUART1 = &sercomUSART4\n\n\tDefaultUART = UART1\n\n\tUART_NINA = UART1\n)\n\n// NINA-W102 settings\nconst (\n\tNINA_BAUDRATE         = 115200\n\tNINA_RESET_INVERTED   = true\n\tNINA_SOFT_FLOWCONTROL = true\n)\n\n// I2C pins\nconst (\n\tSDA_PIN = PB02 // SDA: SERCOM2/PAD[0]\n\tSCL_PIN = PB03 // SCL: SERCOM2/PAD[1]\n)\n\n// I2C on the PyPortal.\nvar (\n\tI2C0 = sercomI2CM5\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = PA13 // SCK: SERCOM1/PAD[1]\n\tSPI0_SDO_PIN = PA12 // SDO: SERCOM1/PAD[3]\n\tSPI0_SDI_PIN = PA14 // SDI: SERCOM1/PAD[2]\n\n\tNINA_SDO = SPI0_SDO_PIN\n\tNINA_SDI = SPI0_SDI_PIN\n\tNINA_SCK = SPI0_SCK_PIN\n)\n\n// SPI on the PyPortal.\nvar (\n\tSPI0     = sercomSPIM2\n\tNINA_SPI = SPI0\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Adafruit PyPortal M4\"\n\tusb_STRING_MANUFACTURER = \"Adafruit\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x8035\n)\n"
  },
  {
    "path": "src/machine/board_qtpy.go",
    "content": "//go:build sam && atsamd21 && qtpy\n\npackage machine\n\n// used to reset into bootloader\nconst resetMagicValue = 0xf01669ef\n\n// GPIO Pins\nconst (\n\tD0  = PA02 // PWM available\n\tD1  = PA03\n\tD2  = PA04 // PWM available\n\tD3  = PA05 // PWM available\n\tD4  = PA16 // PWM available\n\tD5  = PA17 // PWM available\n\tD6  = PA06\n\tD7  = PA07\n\tD8  = PA11\n\tD9  = PA09\n\tD10 = PA10\n\tD11 = PA18\n\tD12 = PA15\n\tD13 = PA27\n\tD14 = PA23\n\tD15 = PA19\n\tD16 = PA22\n\tD17 = PA08\n)\n\n// Analog pins\nconst (\n\tA0 = D0\n\tA1 = D1\n\tA2 = D2\n\tA3 = D3\n\tA4 = D4\n)\n\nconst (\n\tNEOPIXELS       = D11\n\tWS2812          = D11\n\tNEOPIXELS_POWER = D12\n)\n\n// USBCDC pins\nconst (\n\tUSBCDC_DM_PIN = PA24\n\tUSBCDC_DP_PIN = PA25\n)\n\n// UART1 pins\nconst (\n\tUART_TX_PIN = D6\n\tUART_RX_PIN = D7\n)\n\n// UART1 on the QT Py M0.\nvar UART1 = &sercomUSART0\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = D8\n\tSPI0_SDO_PIN = D10\n\tSPI0_SDI_PIN = D9\n)\n\n// SPI on the QT Py M0.\nvar SPI0 = sercomSPIM0\n\n// I2C pins\nconst (\n\tSDA_PIN = D4 // SDA\n\tSCL_PIN = D5 // SCL\n)\n\n// I2C on the QT Py M0.\nvar (\n\tI2C0 = sercomI2CM1\n)\n\n// I2S pins\nconst (\n\tI2S_SCK_PIN = PA10\n\tI2S_SDO_PIN = PA08\n\tI2S_SDI_PIN = NoPin // TODO: figure out what this is on QT Py M0.\n\tI2S_WS_PIN  = NoPin // TODO: figure out what this is on QT Py M0.\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Adafruit QTPy M0\"\n\tusb_STRING_MANUFACTURER = \"Adafruit\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x80CB\n)\n\nvar (\n\tDefaultUART = UART1\n)\n"
  },
  {
    "path": "src/machine/board_qtpy_esp32c3.go",
    "content": "//go:build qtpy_esp32c3\n\n// This file contains the pin mappings for the Adafruit QtPy ESP32C3 boards.\n//\n// https://learn.adafruit.com/adafruit-qt-py-esp32-c3-wifi-dev-board/pinouts\npackage machine\n\n// Digital Pins\nconst (\n\tD0 = GPIO4\n\tD1 = GPIO3\n\tD2 = GPIO1\n\tD3 = GPIO0\n)\n\n// Analog pins (ADC1)\nconst (\n\tA0 = GPIO4\n\tA1 = GPIO3\n\tA2 = GPIO1\n\tA3 = GPIO0\n)\n\n// UART pins\nconst (\n\tRX_PIN = GPIO20\n\tTX_PIN = GPIO21\n\n\tUART_RX_PIN = RX_PIN\n\tUART_TX_PIN = TX_PIN\n)\n\n// I2C pins\nconst (\n\tSDA_PIN = GPIO5\n\tSCL_PIN = GPIO6\n\n\tI2C0_SDA_PIN = SDA_PIN\n\tI2C0_SCL_PIN = SCL_PIN\n)\n\n// SPI pins\nconst (\n\tSCK_PIN = GPIO10\n\tMI_PIN  = GPIO8\n\tMO_PIN  = GPIO7\n\n\tSPI_SCK_PIN = SCK_PIN\n\tSPI_SDI_PIN = MI_PIN\n\tSPI_SDO_PIN = MO_PIN\n)\n\nconst (\n\tNEOPIXEL = GPIO2\n\tWS2812   = GPIO2\n\n\t// also used for boot button.\n\t// set it to be an input-with-pullup\n\tBUTTON = GPIO9\n)\n"
  },
  {
    "path": "src/machine/board_qtpy_rp2040.go",
    "content": "//go:build qtpy_rp2040\n\npackage machine\n\n// Onboard crystal oscillator frequency, in MHz.\nconst xoscFreq = 12 // MHz\n\n// GPIO Pins\nconst (\n\tSDA  = GPIO24\n\tSCL  = GPIO25\n\tTX   = GPIO20\n\tMO   = GPIO3\n\tMOSI = GPIO3\n\tMI   = GPIO4\n\tMISO = GPIO4\n\tSCK  = GPIO6\n\tRX   = GPIO5\n\n\tQT_SCL1 = GPIO23\n\tQT_SDA1 = GPIO22\n)\n\n// Analog pins\nconst (\n\tA0 = GPIO29\n\tA1 = GPIO28\n\tA2 = GPIO27\n\tA3 = GPIO26\n)\n\nconst (\n\tNEOPIXEL       = GPIO12\n\tWS2812         = GPIO12\n\tNEOPIXEL_POWER = GPIO11\n)\n\n// I2C Pins.\nconst (\n\tI2C0_SDA_PIN = GPIO24\n\tI2C0_SCL_PIN = GPIO25\n\n\tI2C1_SDA_PIN = GPIO26\n\tI2C1_SCL_PIN = GPIO27\n\n\tI2C1_QT_SDA_PIN = GPIO22\n\tI2C1_QT_SCL_PIN = GPIO23\n\n\tSDA_PIN = GPIO24\n\tSCL_PIN = GPIO25\n)\n\n// SPI default pins\nconst (\n\t// Default Serial Clock Bus 0 for SPI communications\n\tSPI0_SCK_PIN = GPIO6\n\t// Default Serial Out Bus 0 for SPI communications\n\tSPI0_SDO_PIN = GPIO3 // Tx\n\t// Default Serial In Bus 0 for SPI communications\n\tSPI0_SDI_PIN = GPIO4 // Rx\n\tSPI0_CS      = GPIO5\n\n\t// Default Serial Clock Bus 1 for SPI communications\n\tSPI1_SCK_PIN = GPIO26\n\t// Default Serial Out Bus 1 for SPI communications\n\tSPI1_SDO_PIN = GPIO27 // Tx\n\t// Default Serial In Bus 1 for SPI communications\n\tSPI1_SDI_PIN = GPIO24 // Rx\n\tSPI1_CS      = GPIO25\n)\n\n// UART pins\nconst (\n\tUART0_TX_PIN = GPIO28\n\tUART0_RX_PIN = GPIO29\n\tUART1_TX_PIN = GPIO20\n\tUART1_RX_PIN = GPIO5\n\tUART_TX_PIN  = UART0_TX_PIN\n\tUART_RX_PIN  = UART0_RX_PIN\n)\n\nvar DefaultUART = UART0\n\n// USB identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"QT Py RP2040\"\n\tusb_STRING_MANUFACTURER = \"Adafruit\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x80F7\n)\n"
  },
  {
    "path": "src/machine/board_rak4631.go",
    "content": "//go:build rak4631\n\npackage machine\n\nconst HasLowFrequencyCrystal = true\n\n// Digital Pins\nconst (\n\tD0 Pin = P0_28\n\tD1 Pin = P0_02\n)\n\n// Analog pins\nconst (\n\tA0 Pin = P0_17\n\tA1 Pin = P1_02\n\tA2 Pin = P0_21\n)\n\n// Onboard LEDs\nconst (\n\tLED  = LED2\n\tLED1 = P1_03\n\tLED2 = P1_04\n)\n\n// UART pins\nconst (\n\t// Default to UART1\n\tUART_RX_PIN = UART0_RX_PIN\n\tUART_TX_PIN = UART0_TX_PIN\n\n\t// UART1\n\tUART0_RX_PIN = P0_19\n\tUART0_TX_PIN = P0_20\n\n\t// UART2\n\tUART1_RX_PIN = P0_15\n\tUART1_TX_PIN = P0_16\n)\n\n// I2C pins\nconst (\n\tSDA_PIN = SDA1_PIN\n\tSCL_PIN = SCL1_PIN\n\n\tSDA1_PIN = P0_13\n\tSCL1_PIN = P0_14\n\n\tSDA2_PIN = P0_24\n\tSCL2_PIN = P0_25\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = P0_03\n\tSPI0_SDO_PIN = P0_29\n\tSPI0_SDI_PIN = P0_30\n)\n\n// Peripherals\nconst (\n\tLORA_NSS    = P1_10\n\tLORA_SCK    = P1_11\n\tLORA_MOSI   = P1_12\n\tLORA_MISO   = P1_13\n\tLORA_BUSY   = P1_14\n\tLORA_DIO1   = P1_15\n\tLORA_NRESET = P1_06\n\tLORA_POWER  = P1_05\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"WisCore RAK4631 Board\"\n\tusb_STRING_MANUFACTURER = \"RAKwireless\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239a\n\tusb_PID uint16 = 0x8029\n)\n\nvar (\n\tDefaultUART = UART0\n)\n"
  },
  {
    "path": "src/machine/board_reelboard.go",
    "content": "//go:build reelboard\n\npackage machine\n\nconst HasLowFrequencyCrystal = true\n\n// Pins on the reel board\nconst (\n\tLED_RED          Pin = 11\n\tLED_GREEN        Pin = 12\n\tLED_BLUE         Pin = 41\n\tLED_YELLOW       Pin = 13\n\tLED1             Pin = LED_YELLOW\n\tLED2             Pin = LED_RED\n\tLED3             Pin = LED_GREEN\n\tLED4             Pin = LED_BLUE\n\tLED              Pin = LED1\n\tEPD_BUSY_PIN     Pin = 14\n\tEPD_RESET_PIN    Pin = 15\n\tEPD_DC_PIN       Pin = 16\n\tEPD_CS_PIN       Pin = 17\n\tEPD_SCK_PIN      Pin = 19\n\tEPD_SDO_PIN      Pin = 20\n\tPOWER_SUPPLY_PIN Pin = 32\n)\n\n// User \"a\" button on the reel board\nconst (\n\tBUTTON Pin = 7\n)\n\nvar DefaultUART = UART0\n\n// UART pins\nconst (\n\tUART_TX_PIN Pin = 6\n\tUART_RX_PIN Pin = 8\n)\n\n// I2C pins\nconst (\n\tSDA_PIN Pin = 26\n\tSCL_PIN Pin = 27\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN Pin = 47\n\tSPI0_SDO_PIN Pin = 45\n\tSPI0_SDI_PIN Pin = 46\n)\n\n// PowerSupplyActive enables the supply voltages for nRF52840 and peripherals (true) or only for nRF52840 (false)\n// This controls the TPS610981 boost converter. You must turn the power supply active in order to use the EPD and\n// other onboard peripherals.\nfunc PowerSupplyActive(active bool) {\n\tPOWER_SUPPLY_PIN.Configure(PinConfig{Mode: PinOutput})\n\tif active {\n\t\tPOWER_SUPPLY_PIN.High()\n\t} else {\n\t\tPOWER_SUPPLY_PIN.Low()\n\t}\n}\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"PHYTEC reelboard\"\n\tusb_STRING_MANUFACTURER = \"PHYTEC\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2FE3\n\tusb_PID uint16 = 0x100\n)\n"
  },
  {
    "path": "src/machine/board_stm32f469disco.go",
    "content": "//go:build stm32f469disco\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/interrupt\"\n)\n\nconst (\n\tLED         = LED_BUILTIN\n\tLED1        = LED_GREEN\n\tLED2        = LED_ORANGE\n\tLED3        = LED_RED\n\tLED4        = LED_BLUE\n\tLED_BUILTIN = LED_GREEN\n\tLED_GREEN   = PG6\n\tLED_ORANGE  = PD4\n\tLED_RED     = PD5\n\tLED_BLUE    = PK3\n)\n\nconst (\n\tBUTTON = PA0\n)\n\n// UART pins\nconst (\n\tUART_TX_PIN = PB10\n\tUART_RX_PIN = PB11\n)\n\nvar (\n\tUART3  = &_UART3\n\t_UART3 = UART{\n\t\tBuffer:            NewRingBuffer(),\n\t\tBus:               stm32.USART3,\n\t\tTxAltFuncSelector: AF7_USART1_2_3,\n\t\tRxAltFuncSelector: AF7_USART1_2_3,\n\t}\n\tDefaultUART = UART3\n)\n\n// set up RX IRQ handler. Follow similar pattern for other UARTx instances\nfunc init() {\n\tUART3.Interrupt = interrupt.New(stm32.IRQ_USART3, _UART3.handleInterrupt)\n}\n\n// SPI pins\nconst (\n\tSPI1_SCK_PIN = PA5\n\tSPI1_SDI_PIN = PA6\n\tSPI1_SDO_PIN = PA7\n\tSPI0_SCK_PIN = SPI1_SCK_PIN\n\tSPI0_SDI_PIN = SPI1_SDI_PIN\n\tSPI0_SDO_PIN = SPI1_SDO_PIN\n)\n\n// Since the first interface is named SPI1, both SPI0 and SPI1 refer to SPI1.\n// TODO: implement SPI2 and SPI3.\nvar (\n\tSPI0 = &SPI{\n\t\tBus:             stm32.SPI1,\n\t\tAltFuncSelector: AF5_SPI1_SPI2,\n\t}\n\tSPI1 = SPI0\n)\n\nconst (\n\tI2C0_SCL_PIN = PB6\n\tI2C0_SDA_PIN = PB9\n)\n\nvar (\n\tI2C0 = &I2C{\n\t\tBus:             stm32.I2C1,\n\t\tAltFuncSelector: AF4_I2C1_2_3,\n\t}\n)\n"
  },
  {
    "path": "src/machine/board_stm32f4disco.go",
    "content": "//go:build stm32f4disco\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/interrupt\"\n)\n\nconst (\n\tLED1        = LED_GREEN\n\tLED2        = LED_ORANGE\n\tLED3        = LED_RED\n\tLED4        = LED_BLUE\n\tLED_GREEN   = PD12\n\tLED_ORANGE  = PD13\n\tLED_RED     = PD14\n\tLED_BLUE    = PD15\n\tLED         = LED_BUILTIN\n\tLED_BUILTIN = LED_GREEN\n)\n\nconst (\n\tBUTTON = PA0\n)\n\n// Analog Pins\nconst (\n\tADC0  = PA0\n\tADC1  = PA1\n\tADC2  = PA2\n\tADC3  = PA3\n\tADC4  = PA4\n\tADC5  = PA5\n\tADC6  = PA6\n\tADC7  = PA7\n\tADC8  = PB0\n\tADC9  = PB1\n\tADC10 = PC0\n\tADC11 = PC1\n\tADC12 = PC2\n\tADC13 = PC3\n\tADC14 = PC4\n\tADC15 = PC5\n)\n\n// UART pins\nconst (\n\tUART_TX_PIN = PA2\n\tUART_RX_PIN = PA3\n)\n\nvar (\n\tUART1  = &_UART1\n\t_UART1 = UART{\n\t\tBuffer:            NewRingBuffer(),\n\t\tBus:               stm32.USART2,\n\t\tTxAltFuncSelector: AF7_USART1_2_3,\n\t\tRxAltFuncSelector: AF7_USART1_2_3,\n\t}\n\tDefaultUART = UART1\n)\n\n// set up RX IRQ handler. Follow similar pattern for other UARTx instances\nfunc init() {\n\tUART1.Interrupt = interrupt.New(stm32.IRQ_USART2, _UART1.handleInterrupt)\n}\n\n// SPI pins\nconst (\n\tSPI1_SCK_PIN = PA5\n\tSPI1_SDI_PIN = PA6\n\tSPI1_SDO_PIN = PA7\n\tSPI0_SCK_PIN = SPI1_SCK_PIN\n\tSPI0_SDI_PIN = SPI1_SDI_PIN\n\tSPI0_SDO_PIN = SPI1_SDO_PIN\n)\n\n// MEMs accelerometer\nconst (\n\tMEMS_ACCEL_CS   = PE3\n\tMEMS_ACCEL_INT1 = PE0\n\tMEMS_ACCEL_INT2 = PE1\n)\n\n// Since the first interface is named SPI1, both SPI0 and SPI1 refer to SPI1.\n// TODO: implement SPI2 and SPI3.\nvar (\n\tSPI0 = &SPI{\n\t\tBus:             stm32.SPI1,\n\t\tAltFuncSelector: AF5_SPI1_SPI2,\n\t}\n\tSPI1 = SPI0\n)\n\nconst (\n\tI2C0_SCL_PIN = PB6\n\tI2C0_SDA_PIN = PB9\n)\n\nvar (\n\tI2C0 = &I2C{\n\t\tBus:             stm32.I2C1,\n\t\tAltFuncSelector: AF4_I2C1_2_3,\n\t}\n)\n"
  },
  {
    "path": "src/machine/board_stm32l0x1.go",
    "content": "//go:build stm32l0x1 && !nucleol031k6\n\n// This file is for the bare STM32L0x1 (not for any specific board that is based\n// on the STM32L0x1).\n\npackage machine\n\nconst (\n\tI2C0_SCL_PIN = NoPin\n\tI2C0_SDA_PIN = NoPin\n\n\tUART_TX_PIN = NoPin\n\tUART_RX_PIN = NoPin\n\n\tSPI0_SDI_PIN = NoPin\n\tSPI0_SDO_PIN = NoPin\n\tSPI0_SCK_PIN = NoPin\n)\n"
  },
  {
    "path": "src/machine/board_swan.go",
    "content": "//go:build swan\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/interrupt\"\n)\n\nconst (\n\t// LED on the SWAN\n\tLED = PE2\n\n\t// UART pins\n\t//    PA9 and PA10 are connected to the SWAN Tx/Rx\n\tUART_TX_PIN = PA9\n\tUART_RX_PIN = PA10\n\n\t// I2C pins\n\t//    PB6 is SCL\n\t//    PB7 is SDA\n\tI2C0_SCL_PIN = PB6\n\tI2C0_SDA_PIN = PB7\n\n\t// SPI pins\n\tSPI1_SCK_PIN = PD1\n\tSPI1_SDI_PIN = PB14\n\tSPI1_SDO_PIN = PB15\n\tSPI0_SCK_PIN = SPI1_SCK_PIN\n\tSPI0_SDI_PIN = SPI1_SDI_PIN\n\tSPI0_SDO_PIN = SPI1_SDO_PIN\n)\n\nvar (\n\t// USART1 is connected to the TX/RX pins\n\tUART1  = &_UART1\n\t_UART1 = UART{\n\t\tBuffer:            NewRingBuffer(),\n\t\tBus:               stm32.USART1,\n\t\tTxAltFuncSelector: 7,\n\t\tRxAltFuncSelector: 7,\n\t}\n\tDefaultUART = UART1\n\n\t// I2C1 is documented, alias to I2C0 as well\n\tI2C1 = &I2C{\n\t\tBus:             stm32.I2C1,\n\t\tAltFuncSelector: 4,\n\t}\n\tI2C0 = I2C1\n\n\t// SPI1 is documented, alias to SPI0 as well\n\tSPI1 = &SPI{\n\t\tBus:             stm32.SPI2,\n\t\tAltFuncSelector: 5,\n\t}\n\tSPI0 = SPI1\n)\n\nfunc init() {\n\tUART1.Interrupt = interrupt.New(stm32.IRQ_USART1, _UART1.handleInterrupt)\n}\n"
  },
  {
    "path": "src/machine/board_teensy36.go",
    "content": "//go:build nxp && mk66f18 && teensy36\n\npackage machine\n\n// CPUFrequency returns the frequency of the ARM core clock (180MHz)\nfunc CPUFrequency() uint32 { return 180000000 }\n\n// ClockFrequency returns the frequency of the external oscillator (16MHz)\nfunc ClockFrequency() uint32 { return 16000000 }\n\n// digital IO\nconst (\n\tD00 = PB16\n\tD01 = PB17\n\tD02 = PD00\n\tD03 = PA12\n\tD04 = PA13\n\tD05 = PD07\n\tD06 = PD04\n\tD07 = PD02\n\tD08 = PD03\n\tD09 = PC03\n\tD10 = PC04\n\tD11 = PC06\n\tD12 = PC07\n\tD13 = PC05\n\tD14 = PD01\n\tD15 = PC00\n\tD16 = PB00\n\tD17 = PB01\n\tD18 = PB03\n\tD19 = PB02\n\tD20 = PD05\n\tD21 = PD06\n\tD22 = PC01\n\tD23 = PC02\n\tD24 = PE26\n\tD25 = PA05\n\tD26 = PA14\n\tD27 = PA15\n\tD28 = PA16\n\tD29 = PB18\n\tD30 = PB19\n\tD31 = PB10\n\tD32 = PB11\n\tD33 = PE24\n\tD34 = PE25\n\tD35 = PC08\n\tD36 = PC09\n\tD37 = PC10\n\tD38 = PC11\n\tD39 = PA17\n\tD40 = PA28\n\tD41 = PA29\n\tD42 = PA26\n\tD43 = PB20\n\tD44 = PB22\n\tD45 = PB23\n\tD46 = PB21\n\tD47 = PD08\n\tD48 = PD09\n\tD49 = PB04\n\tD50 = PB05\n\tD51 = PD14\n\tD52 = PD13\n\tD53 = PD12\n\tD54 = PD15\n\tD55 = PD11\n\tD56 = PE10\n\tD57 = PE11\n\tD58 = PE00\n\tD59 = PE01\n\tD60 = PE02\n\tD61 = PE03\n\tD62 = PE04\n\tD63 = PE05\n)\n\n// LED on the Teensy\nconst LED = PC05\n\nvar (\n\tTeensyUART1 = UART0\n\tTeensyUART2 = UART1\n\tTeensyUART3 = UART2\n\tTeensyUART4 = UART3\n\tTeensyUART5 = UART4\n)\n\nvar DefaultUART = UART0\n\nconst (\n\tdefaultUART0RX = D00\n\tdefaultUART0TX = D01\n\tdefaultUART1RX = D09\n\tdefaultUART1TX = D10\n\tdefaultUART2RX = D07\n\tdefaultUART2TX = D08\n\tdefaultUART3RX = D31\n\tdefaultUART3TX = D32\n\tdefaultUART4RX = D34\n\tdefaultUART4TX = D33\n)\n"
  },
  {
    "path": "src/machine/board_teensy40.go",
    "content": "//go:build teensy40\n\npackage machine\n\nimport (\n\t\"device/nxp\"\n\t\"runtime/interrupt\"\n)\n\n// Digital pins\nconst (\n\t//  = Pin  // [Pad]:       Alt Func 0       Alt Func 1       Alt Func 2       Alt Func 3      Alt Func 4            Alt Func 5  Alt Func 6            Alt Func 7             Alt Func 8             Alt Func 9\n\t//  = ----    -----------  ---------------  ---------------  ---------------  --------------  --------------------  ----------  --------------------  ---------------------  ---------------------  ----------------\n\tD0  = PA3  // [AD_B0_03]:  FLEXCAN2_RX      XBAR1_INOUT17    LPUART6_RX       USB_OTG1_OC     FLEXPWM1_PWMX01       GPIO1_IO03  REF_CLK_24M           LPSPI3_PCS0             ~                      ~\n\tD1  = PA2  // [AD_B0_02]:  FLEXCAN2_TX      XBAR1_INOUT16    LPUART6_TX       USB_OTG1_PWR    FLEXPWM1_PWMX00       GPIO1_IO02  LPI2C1_HREQ           LPSPI3_SDI              ~                      ~\n\tD2  = PD4  // [EMC_04]:    SEMC_DATA04      FLEXPWM4_PWMA02  SAI2_TX_DATA     XBAR1_INOUT06   FLEXIO1_FLEXIO04      GPIO4_IO04   ~                     ~                      ~                      ~\n\tD3  = PD5  // [EMC_05]:    SEMC_DATA05      FLEXPWM4_PWMB02  SAI2_TX_SYNC     XBAR1_INOUT07   FLEXIO1_FLEXIO05      GPIO4_IO05   ~                     ~                      ~                      ~\n\tD4  = PD6  // [EMC_06]:    SEMC_DATA06      FLEXPWM2_PWMA00  SAI2_TX_BCLK     XBAR1_INOUT08   FLEXIO1_FLEXIO06      GPIO4_IO06   ~                     ~                      ~                      ~\n\tD5  = PD8  // [EMC_08]:    SEMC_DM00        FLEXPWM2_PWMA01  SAI2_RX_DATA     XBAR1_INOUT17   FLEXIO1_FLEXIO08      GPIO4_IO08   ~                     ~                      ~                      ~\n\tD6  = PB10 // [B0_10]:     LCD_DATA06       QTIMER4_TIMER1   FLEXPWM2_PWMA02  SAI1_TX_DATA03  FLEXIO2_FLEXIO10      GPIO2_IO10  SRC_BOOT_CFG06        ENET2_CRS               ~                      ~\n\tD7  = PB17 // [B1_01]:     LCD_DATA13       XBAR1_INOUT15    LPUART4_RX       SAI1_TX_DATA00  FLEXIO2_FLEXIO17      GPIO2_IO17  FLEXPWM1_PWMB03       ENET2_RDATA00          FLEXIO3_FLEXIO17        ~\n\tD8  = PB16 // [B1_00]:     LCD_DATA12       XBAR1_INOUT14    LPUART4_TX       SAI1_RX_DATA00  FLEXIO2_FLEXIO16      GPIO2_IO16  FLEXPWM1_PWMA03       ENET2_RX_ER            FLEXIO3_FLEXIO16        ~\n\tD9  = PB11 // [B0_11]:     LCD_DATA07       QTIMER4_TIMER2   FLEXPWM2_PWMB02  SAI1_TX_DATA02  FLEXIO2_FLEXIO11      GPIO2_IO11  SRC_BOOT_CFG07        ENET2_COL               ~                      ~\n\tD10 = PB0  // [B0_00]:     LCD_CLK          QTIMER1_TIMER0   MQS_RIGHT        LPSPI4_PCS0     FLEXIO2_FLEXIO00      GPIO2_IO00  SEMC_CSX01            ENET2_MDC               ~                      ~\n\tD11 = PB2  // [B0_02]:     LCD_HSYNC        QTIMER1_TIMER2   FLEXCAN1_TX      LPSPI4_SDO      FLEXIO2_FLEXIO02      GPIO2_IO02  SEMC_CSX03            ENET2_1588_EVENT0_OUT   ~                      ~\n\tD12 = PB1  // [B0_01]:     LCD_ENABLE       QTIMER1_TIMER1   MQS_LEFT         LPSPI4_SDI      FLEXIO2_FLEXIO01      GPIO2_IO01  SEMC_CSX02            ENET2_MDIO              ~                      ~\n\tD13 = PB3  // [B0_03]:     LCD_VSYNC        QTIMER2_TIMER0   FLEXCAN1_RX      LPSPI4_SCK      FLEXIO2_FLEXIO03      GPIO2_IO03  WDOG2_RESET_B_DEB     ENET2_1588_EVENT0_IN    ~                      ~\n\tD14 = PA18 // [AD_B1_02]:  USB_OTG1_ID      QTIMER3_TIMER2   LPUART2_TX       SPDIF_OUT       ENET_1588_EVENT2_OUT  GPIO1_IO18  USDHC1_CD_B           KPP_ROW06              GPT2_CLK               FLEXIO3_FLEXIO02\n\tD15 = PA19 // [AD_B1_03]:  USB_OTG1_OC      QTIMER3_TIMER3   LPUART2_RX       SPDIF_IN        ENET_1588_EVENT2_IN   GPIO1_IO19  USDHC2_CD_B           KPP_COL06              GPT2_CAPTURE1          FLEXIO3_FLEXIO03\n\tD16 = PA23 // [AD_B1_07]:  FLEXSPIB_DATA00  LPI2C3_SCL       LPUART3_RX       SPDIF_EXT_CLK   CSI_HSYNC             GPIO1_IO23  USDHC2_DATA3          KPP_COL04              GPT2_COMPARE3          FLEXIO3_FLEXIO07\n\tD17 = PA22 // [AD_B1_06]:  FLEXSPIB_DATA01  LPI2C3_SDA       LPUART3_TX       SPDIF_LOCK      CSI_VSYNC             GPIO1_IO22  USDHC2_DATA2          KPP_ROW04              GPT2_COMPARE2          FLEXIO3_FLEXIO06\n\tD18 = PA17 // [AD_B1_01]:  USB_OTG1_PWR     QTIMER3_TIMER1   LPUART2_RTS_B    LPI2C1_SDA      CCM_PMIC_READY        GPIO1_IO17  USDHC1_VSELECT        KPP_COL07              ENET2_1588_EVENT0_IN   FLEXIO3_FLEXIO01\n\tD19 = PA16 // [AD_B1_00]:  USB_OTG2_ID      QTIMER3_TIMER0   LPUART2_CTS_B    LPI2C1_SCL      WDOG1_B               GPIO1_IO16  USDHC1_WP             KPP_ROW07              ENET2_1588_EVENT0_OUT  FLEXIO3_FLEXIO00\n\tD20 = PA26 // [AD_B1_10]:  FLEXSPIA_DATA03  WDOG1_B          LPUART8_TX       SAI1_RX_SYNC    CSI_DATA07            GPIO1_IO26  USDHC2_WP             KPP_ROW02              ENET2_1588_EVENT1_OUT  FLEXIO3_FLEXIO10\n\tD21 = PA27 // [AD_B1_11]:  FLEXSPIA_DATA02  EWM_OUT_B        LPUART8_RX       SAI1_RX_BCLK    CSI_DATA06            GPIO1_IO27  USDHC2_RESET_B        KPP_COL02              ENET2_1588_EVENT1_IN   FLEXIO3_FLEXIO11\n\tD22 = PA24 // [AD_B1_08]:  FLEXSPIA_SS1_B   FLEXPWM4_PWMA00  FLEXCAN1_TX      CCM_PMIC_READY  CSI_DATA09            GPIO1_IO24  USDHC2_CMD            KPP_ROW03              FLEXIO3_FLEXIO08        ~\n\tD23 = PA25 // [AD_B1_09]:  FLEXSPIA_DQS     FLEXPWM4_PWMA01  FLEXCAN1_RX      SAI1_MCLK       CSI_DATA08            GPIO1_IO25  USDHC2_CLK            KPP_COL03              FLEXIO3_FLEXIO09        ~\n\tD24 = PA12 // [AD_B0_12]:  LPI2C4_SCL       CCM_PMIC_READY   LPUART1_TX       WDOG2_WDOG_B    FLEXPWM1_PWMX02       GPIO1_IO12  ENET_1588_EVENT1_OUT  NMI_GLUE_NMI            ~                      ~\n\tD25 = PA13 // [AD_B0_13]:  LPI2C4_SDA       GPT1_CLK         LPUART1_RX       EWM_OUT_B       FLEXPWM1_PWMX03       GPIO1_IO13  ENET_1588_EVENT1_IN   REF_CLK_24M             ~                      ~\n\tD26 = PA30 // [AD_B1_14]:  FLEXSPIA_SCLK    ACMP_OUT02       LPSPI3_SDO       SAI1_TX_BCLK    CSI_DATA03            GPIO1_IO30  USDHC2_DATA6          KPP_ROW00              ENET2_1588_EVENT3_OUT  FLEXIO3_FLEXIO14\n\tD27 = PA31 // [AD_B1_15]:  FLEXSPIA_SS0_B   ACMP_OUT03       LPSPI3_SCK       SAI1_TX_SYNC    CSI_DATA02            GPIO1_IO31  USDHC2_DATA7          KPP_COL00              ENET2_1588_EVENT3_IN   FLEXIO3_FLEXIO15\n\tD28 = PC18 // [EMC_32]:    SEMC_DATA10      FLEXPWM3_PWMB01  LPUART7_RX       CCM_PMIC_RDY    CSI_DATA21            GPIO3_IO18  ENET2_TX_EN            ~                      ~                      ~\n\tD29 = PD31 // [EMC_31]:    SEMC_DATA09      FLEXPWM3_PWMA01  LPUART7_TX       LPSPI1_PCS1     CSI_DATA22            GPIO4_IO31  ENET2_TDATA01          ~                      ~                      ~\n\tD30 = PC23 // [EMC_37]:    SEMC_DATA15      XBAR1_IN23       GPT1_COMPARE3    SAI3_MCLK       CSI_DATA16            GPIO3_IO23  USDHC2_WP             ENET2_RX_EN            FLEXCAN3_RX             ~\n\tD31 = PC22 // [EMC_36]:    SEMC_DATA14      XBAR1_IN22       GPT1_COMPARE2    SAI3_TX_DATA    CSI_DATA17            GPIO3_IO22  USDHC1_WP             ENET2_RDATA01          FLEXCAN3_TX             ~\n\tD32 = PB12 // [B0_12]:     LCD_DATA08       XBAR1_INOUT10    ARM_TRACE_CLK    SAI1_TX_DATA01  FLEXIO2_FLEXIO12      GPIO2_IO12  SRC_BOOT_CFG08        ENET2_TDATA00           ~                      ~\n\tD33 = PD7  // [EMC_07]:    SEMC_DATA07      FLEXPWM2_PWMB00  SAI2_MCLK        XBAR1_INOUT09   FLEXIO1_FLEXIO07      GPIO4_IO07   ~                     ~                      ~                      ~\n\tD34 = PC15 // [SD_B0_03]:  USDHC1_DATA1     FLEXPWM1_PWMB01  LPUART8_RTS_B    XBAR1_INOUT07   LPSPI1_SDI            GPIO3_IO15  ENET2_RDATA00         SEMC_CLK6               ~                      ~\n\tD35 = PC14 // [SD_B0_02]:  USDHC1_DATA0     FLEXPWM1_PWMA01  LPUART8_CTS_B    XBAR1_INOUT06   LPSPI1_SDO            GPIO3_IO14  ENET2_RX_ER           SEMC_CLK5               ~                      ~\n\tD36 = PC13 // [SD_B0_01]:  USDHC1_CLK       FLEXPWM1_PWMB00  LPI2C3_SDA       XBAR1_INOUT05   LPSPI1_PCS0           GPIO3_IO13  FLEXSPIB_SS1_B        ENET2_TX_CLK           ENET2_REF_CLK2          ~\n\tD37 = PC12 // [SD_B0_00]:  USDHC1_CMD       FLEXPWM1_PWMA00  LPI2C3_SCL       XBAR1_INOUT04   LPSPI1_SCK            GPIO3_IO12  FLEXSPIA_SS1_B        ENET2_TX_EN            SEMC_DQS4               ~\n\tD38 = PC17 // [SD_B0_05]:  USDHC1_DATA3     FLEXPWM1_PWMB02  LPUART8_RX       XBAR1_INOUT09   FLEXSPIB_DQS          GPIO3_IO17  CCM_CLKO2             ENET2_RX_EN             ~                      ~\n\tD39 = PC16 // [SD_B0_04]:  USDHC1_DATA2     FLEXPWM1_PWMA02  LPUART8_TX       XBAR1_INOUT08   FLEXSPIB_SS0_B        GPIO3_IO16  CCM_CLKO1             ENET2_RDATA01           ~                      ~\n)\n\n// Analog pins\nconst (\n\t//  = Pin  // Dig | [Pad]      {ADC1/ADC2}\n\tA0  = PA18 // D14 | [AD_B1_02] {  7 / 7  }\n\tA1  = PA19 // D15 | [AD_B1_03] {  8 / 8  }\n\tA2  = PA23 // D16 | [AD_B1_07] { 12 / 12 }\n\tA3  = PA22 // D17 | [AD_B1_06] { 11 / 11 }\n\tA4  = PA17 // D18 | [AD_B1_01] {  6 / 6  }\n\tA5  = PA16 // D19 | [AD_B1_00] {  5 / 5  }\n\tA6  = PA26 // D20 | [AD_B1_10] { 15 / 15 }\n\tA7  = PA27 // D21 | [AD_B1_11] {  0 / 0  }\n\tA8  = PA24 // D22 | [AD_B1_08] { 13 / 13 }\n\tA9  = PA25 // D23 | [AD_B1_09] { 14 / 14 }\n\tA10 = PA12 // D24 | [AD_B0_12] {  1 / -  }\n\tA11 = PA13 // D25 | [AD_B0_13] {  2 / -  }\n\tA12 = PA30 // D26 | [AD_B1_14] {  - / 3  }\n\tA13 = PA31 // D27 | [AD_B1_15] {  - / 4  }\n)\n\n// Default peripheral pins\nconst (\n\tLED = D13\n\n\tUART_RX_PIN = UART1_RX_PIN // D0\n\tUART_TX_PIN = UART1_TX_PIN // D1\n\n\tSPI_SDI_PIN = SPI1_SDI_PIN // D12\n\tSPI_SDO_PIN = SPI1_SDO_PIN // D11\n\tSPI_SCK_PIN = SPI1_SCK_PIN // D13\n\tSPI_CS_PIN  = SPI1_CS_PIN  // D10\n\n\tI2C_SDA_PIN = I2C1_SDA_PIN // D18/A4\n\tI2C_SCL_PIN = I2C1_SCL_PIN // D19/A5\n)\n\n// Default peripherals\nvar (\n\tDefaultUART = UART1\n)\n\nfunc init() {\n\t// register any interrupt handlers for this board's peripherals\n\t_UART1.Interrupt = interrupt.New(nxp.IRQ_LPUART6, _UART1.handleInterrupt)\n\t_UART2.Interrupt = interrupt.New(nxp.IRQ_LPUART4, _UART2.handleInterrupt)\n\t_UART3.Interrupt = interrupt.New(nxp.IRQ_LPUART2, _UART3.handleInterrupt)\n\t_UART4.Interrupt = interrupt.New(nxp.IRQ_LPUART3, _UART4.handleInterrupt)\n\t_UART5.Interrupt = interrupt.New(nxp.IRQ_LPUART8, _UART5.handleInterrupt)\n\t_UART6.Interrupt = interrupt.New(nxp.IRQ_LPUART1, _UART6.handleInterrupt)\n\t_UART7.Interrupt = interrupt.New(nxp.IRQ_LPUART7, _UART7.handleInterrupt)\n}\n\n// #=====================================================#\n// |                        UART                         |\n// #===========#===========#=============#===============#\n// | Interface | Hardware  | Clock(Freq) |  RX/TX  : Alt |\n// #===========#===========#=============#=========-=====#\n// |   UART1   |  LPUART6  | OSC(24 MHz) |  D0/D1  : 2/2 |\n// |   UART2   |  LPUART4  | OSC(24 MHz) |  D7/D8  : 2/2 |\n// |   UART3   |  LPUART2  | OSC(24 MHz) | D15/D14 : 2/2 |\n// |   UART4   |  LPUART3  | OSC(24 MHz) | D16/D17 : 2/2 |\n// |   UART5   |  LPUART8  | OSC(24 MHz) | D21/D20 : 2/2 |\n// |   UART6   |  LPUART1  | OSC(24 MHz) | D25/D24 : 2/2 |\n// |   UART7   |  LPUART7  | OSC(24 MHz) | D28/D29 : 2/2 |\n// #===========#===========#=============#=========-=====#\nconst (\n\tUART1_RX_PIN = D0\n\tUART1_TX_PIN = D1\n\n\tUART2_RX_PIN = D7\n\tUART2_TX_PIN = D8\n\n\tUART3_RX_PIN = D15\n\tUART3_TX_PIN = D14\n\n\tUART4_RX_PIN = D16\n\tUART4_TX_PIN = D17\n\n\tUART5_RX_PIN = D21\n\tUART5_TX_PIN = D20\n\n\tUART6_RX_PIN = D25\n\tUART6_TX_PIN = D24\n\n\tUART7_RX_PIN = D28\n\tUART7_TX_PIN = D29\n)\n\nvar (\n\tUART1  = &_UART1\n\t_UART1 = UART{\n\t\tBus:      nxp.LPUART6,\n\t\tBuffer:   NewRingBuffer(),\n\t\ttxBuffer: NewRingBuffer(),\n\t\tmuxRX: muxSelect{ // D0 (PA3 [AD_B0_03])\n\t\t\tmux: nxp.IOMUXC_LPUART6_RX_SELECT_INPUT_DAISY_GPIO_AD_B0_03_ALT2,\n\t\t\tsel: &nxp.IOMUXC.LPUART6_RX_SELECT_INPUT,\n\t\t},\n\t\tmuxTX: muxSelect{ // D1 (PA2 [AD_B0_02])\n\t\t\tmux: nxp.IOMUXC_LPUART6_TX_SELECT_INPUT_DAISY_GPIO_AD_B0_02_ALT2,\n\t\t\tsel: &nxp.IOMUXC.LPUART6_TX_SELECT_INPUT,\n\t\t},\n\t}\n\tUART2  = &_UART2\n\t_UART2 = UART{\n\t\tBus:      nxp.LPUART4,\n\t\tBuffer:   NewRingBuffer(),\n\t\ttxBuffer: NewRingBuffer(),\n\t\tmuxRX: muxSelect{ // D7 (PB17 [B1_01])\n\t\t\tmux: nxp.IOMUXC_LPUART4_RX_SELECT_INPUT_DAISY_GPIO_B1_01_ALT2,\n\t\t\tsel: &nxp.IOMUXC.LPUART4_RX_SELECT_INPUT,\n\t\t},\n\t\tmuxTX: muxSelect{ // D8 (PB16 [B1_00])\n\t\t\tmux: nxp.IOMUXC_LPUART4_TX_SELECT_INPUT_DAISY_GPIO_B1_00_ALT2,\n\t\t\tsel: &nxp.IOMUXC.LPUART4_TX_SELECT_INPUT,\n\t\t},\n\t}\n\tUART3  = &_UART3\n\t_UART3 = UART{\n\t\tBus:      nxp.LPUART2,\n\t\tBuffer:   NewRingBuffer(),\n\t\ttxBuffer: NewRingBuffer(),\n\t\tmuxRX: muxSelect{ // D15 (PA19 [AD_B1_03])\n\t\t\tmux: nxp.IOMUXC_LPUART2_RX_SELECT_INPUT_DAISY_GPIO_AD_B1_03_ALT2,\n\t\t\tsel: &nxp.IOMUXC.LPUART2_RX_SELECT_INPUT,\n\t\t},\n\t\tmuxTX: muxSelect{ // D14 (PA18 [AD_B1_02])\n\t\t\tmux: nxp.IOMUXC_LPUART2_TX_SELECT_INPUT_DAISY_GPIO_AD_B1_02_ALT2,\n\t\t\tsel: &nxp.IOMUXC.LPUART2_TX_SELECT_INPUT,\n\t\t},\n\t}\n\tUART4  = &_UART4\n\t_UART4 = UART{\n\t\tBus:      nxp.LPUART3,\n\t\tBuffer:   NewRingBuffer(),\n\t\ttxBuffer: NewRingBuffer(),\n\t\tmuxRX: muxSelect{ // D16 (PA23 [AD_B1_07])\n\t\t\tmux: nxp.IOMUXC_LPUART3_RX_SELECT_INPUT_DAISY_GPIO_AD_B1_07_ALT2,\n\t\t\tsel: &nxp.IOMUXC.LPUART3_RX_SELECT_INPUT,\n\t\t},\n\t\tmuxTX: muxSelect{ // D17 (PA22 [AD_B1_06])\n\t\t\tmux: nxp.IOMUXC_LPUART3_TX_SELECT_INPUT_DAISY_GPIO_AD_B1_06_ALT2,\n\t\t\tsel: &nxp.IOMUXC.LPUART3_TX_SELECT_INPUT,\n\t\t},\n\t}\n\tUART5  = &_UART5\n\t_UART5 = UART{\n\t\tBus:      nxp.LPUART8,\n\t\tBuffer:   NewRingBuffer(),\n\t\ttxBuffer: NewRingBuffer(),\n\t\tmuxRX: muxSelect{ // D21 (PA27 [AD_B1_11])\n\t\t\tmux: nxp.IOMUXC_LPUART8_RX_SELECT_INPUT_DAISY_GPIO_AD_B1_11_ALT2,\n\t\t\tsel: &nxp.IOMUXC.LPUART8_RX_SELECT_INPUT,\n\t\t},\n\t\tmuxTX: muxSelect{ // D20 (PA26 [AD_B1_10])\n\t\t\tmux: nxp.IOMUXC_LPUART8_TX_SELECT_INPUT_DAISY_GPIO_AD_B1_10_ALT2,\n\t\t\tsel: &nxp.IOMUXC.LPUART8_TX_SELECT_INPUT,\n\t\t},\n\t}\n\tUART6  = &_UART6\n\t_UART6 = UART{\n\t\tBus:      nxp.LPUART1,\n\t\tBuffer:   NewRingBuffer(),\n\t\ttxBuffer: NewRingBuffer(),\n\t\t// LPUART1 not connected via IOMUXC\n\t\t//   RX: D24 (PA12 [AD_B0_12])\n\t\t//   TX: D25 (PA13 [AD_B0_13])\n\t}\n\tUART7  = &_UART7\n\t_UART7 = UART{\n\t\tBus:      nxp.LPUART7,\n\t\tBuffer:   NewRingBuffer(),\n\t\ttxBuffer: NewRingBuffer(),\n\t\tmuxRX: muxSelect{ // D28 (PC18 [EMC_32])\n\t\t\tmux: nxp.IOMUXC_LPUART7_RX_SELECT_INPUT_DAISY_GPIO_EMC_32_ALT2,\n\t\t\tsel: &nxp.IOMUXC.LPUART7_RX_SELECT_INPUT,\n\t\t},\n\t\tmuxTX: muxSelect{ // D29 (PD31 [EMC_31])\n\t\t\tmux: nxp.IOMUXC_LPUART7_TX_SELECT_INPUT_DAISY_GPIO_EMC_31_ALT2,\n\t\t\tsel: &nxp.IOMUXC.LPUART7_TX_SELECT_INPUT,\n\t\t},\n\t}\n)\n\n// #==================================================================#\n// |                               SPI                                |\n// #===========#==========#===============#===========================#\n// | Interface | Hardware |  Clock(Freq)  | SDI/SDO/SCK/CS  :   Alt   |\n// #===========#==========#===============#=================-=========#\n// |   SPI1    |  LPSPI4  | PLL2(132 MHz) | D12/D11/D13/D10 : 3/3/3/3 |\n// |   SPI2    |  LPSPI3  | PLL2(132 MHz) |  D1/D26/D27/D0  : 7/2/2/7 |\n// |   SPI3    |  LPSPI1  | PLL2(132 MHz) | D34/D35/D37/D36 : 4/4/4/4 |\n// #===========#==========#===============#=================-=========#\nconst (\n\tSPI1_SDI_PIN = D12\n\tSPI1_SDO_PIN = D11\n\tSPI1_SCK_PIN = D13\n\tSPI1_CS_PIN  = D10\n\n\tSPI2_SDI_PIN = D1\n\tSPI2_SDO_PIN = D26\n\tSPI2_SCK_PIN = D27\n\tSPI2_CS_PIN  = D0\n\n\tSPI3_SDI_PIN = D34\n\tSPI3_SDO_PIN = D35\n\tSPI3_SCK_PIN = D37\n\tSPI3_CS_PIN  = D36\n)\n\nvar (\n\tSPI0 = SPI1 // SPI0 is an alias of SPI1 (LPSPI4)\n\tSPI1 = &SPI{\n\t\tBus: nxp.LPSPI4,\n\t\tmuxSDI: muxSelect{ // D12 (PB1 [B0_01])\n\t\t\tmux: nxp.IOMUXC_LPSPI4_SDI_SELECT_INPUT_DAISY_GPIO_B0_01_ALT3,\n\t\t\tsel: &nxp.IOMUXC.LPSPI4_SDI_SELECT_INPUT,\n\t\t},\n\t\tmuxSDO: muxSelect{ // D11 (PB2 [B0_02])\n\t\t\tmux: nxp.IOMUXC_LPSPI4_SDO_SELECT_INPUT_DAISY_GPIO_B0_02_ALT3,\n\t\t\tsel: &nxp.IOMUXC.LPSPI4_SDO_SELECT_INPUT,\n\t\t},\n\t\tmuxSCK: muxSelect{ // D13 (PB3 [B0_03])\n\t\t\tmux: nxp.IOMUXC_LPSPI4_SCK_SELECT_INPUT_DAISY_GPIO_B0_03_ALT3,\n\t\t\tsel: &nxp.IOMUXC.LPSPI4_SCK_SELECT_INPUT,\n\t\t},\n\t\tmuxCS: muxSelect{ // D10 (PB0 [B0_00])\n\t\t\tmux: nxp.IOMUXC_LPSPI4_PCS0_SELECT_INPUT_DAISY_GPIO_B0_00_ALT3,\n\t\t\tsel: &nxp.IOMUXC.LPSPI4_PCS0_SELECT_INPUT,\n\t\t},\n\t}\n\tSPI2 = &SPI{\n\t\tBus: nxp.LPSPI3,\n\t\tmuxSDI: muxSelect{ // D1 (PA2 [AD_B0_02])\n\t\t\tmux: nxp.IOMUXC_LPSPI3_SDI_SELECT_INPUT_DAISY_GPIO_AD_B0_02_ALT7,\n\t\t\tsel: &nxp.IOMUXC.LPSPI3_SDI_SELECT_INPUT,\n\t\t},\n\t\tmuxSDO: muxSelect{ // D26 (PA30 [AD_B1_14])\n\t\t\tmux: nxp.IOMUXC_LPSPI3_SDO_SELECT_INPUT_DAISY_GPIO_AD_B1_14_ALT2,\n\t\t\tsel: &nxp.IOMUXC.LPSPI3_SDO_SELECT_INPUT,\n\t\t},\n\t\tmuxSCK: muxSelect{ // D27 (PA31 [AD_B1_15])\n\t\t\tmux: nxp.IOMUXC_LPSPI3_SCK_SELECT_INPUT_DAISY_GPIO_AD_B1_15,\n\t\t\tsel: &nxp.IOMUXC.LPSPI3_SCK_SELECT_INPUT,\n\t\t},\n\t\tmuxCS: muxSelect{ // D0 (PA3 [AD_B0_03])\n\t\t\tmux: nxp.IOMUXC_LPSPI3_PCS0_SELECT_INPUT_DAISY_GPIO_AD_B0_03_ALT7,\n\t\t\tsel: &nxp.IOMUXC.LPSPI3_PCS0_SELECT_INPUT,\n\t\t},\n\t}\n\tSPI3 = &SPI{\n\t\tBus: nxp.LPSPI1,\n\t\tmuxSDI: muxSelect{ // D34 (PC15 [SD_B0_03])\n\t\t\tmux: nxp.IOMUXC_LPSPI1_SDI_SELECT_INPUT_DAISY_GPIO_SD_B0_03_ALT4,\n\t\t\tsel: &nxp.IOMUXC.LPSPI1_SDI_SELECT_INPUT,\n\t\t},\n\t\tmuxSDO: muxSelect{ // D35 (PC14 [SD_B0_02])\n\t\t\tmux: nxp.IOMUXC_LPSPI1_SDO_SELECT_INPUT_DAISY_GPIO_SD_B0_02_ALT4,\n\t\t\tsel: &nxp.IOMUXC.LPSPI1_SDO_SELECT_INPUT,\n\t\t},\n\t\tmuxSCK: muxSelect{ // D37 (PC12 [SD_B0_00])\n\t\t\tmux: nxp.IOMUXC_LPSPI1_SCK_SELECT_INPUT_DAISY_GPIO_SD_B0_00_ALT4,\n\t\t\tsel: &nxp.IOMUXC.LPSPI1_SCK_SELECT_INPUT,\n\t\t},\n\t\tmuxCS: muxSelect{ // D36 (PC13 [SD_B0_01])\n\t\t\tmux: nxp.IOMUXC_LPSPI1_PCS0_SELECT_INPUT_DAISY_GPIO_SD_B0_01_ALT4,\n\t\t\tsel: &nxp.IOMUXC.LPSPI1_PCS0_SELECT_INPUT,\n\t\t},\n\t}\n)\n\n// #====================================================#\n// |                         I2C                        |\n// #===========#==========#=============#===============#\n// | Interface | Hardware | Clock(Freq) | SDA/SCL : Alt |\n// #===========#==========#=============#=========-=====#\n// |   I2C1    |  LPI2C1  | OSC(24 MHz) | D18/D19 : 3/3 |\n// |   I2C2    |  LPI2C3  | OSC(24 MHz) | D17/D16 : 1/1 |\n// |   I2C3    |  LPI2C4  | OSC(24 MHz) | D25/D24 : 0/0 |\n// #===========#==========#=============#=========-=====#\nconst (\n\tI2C1_SDA_PIN = D18\n\tI2C1_SCL_PIN = D19\n\n\tI2C2_SDA_PIN = D17\n\tI2C2_SCL_PIN = D16\n\n\tI2C3_SDA_PIN = D25\n\tI2C3_SCL_PIN = D24\n)\n\nvar (\n\tI2C0  = I2C1 // I2C0 is an alias for I2C1 (LPI2C1)\n\tI2C1  = &_I2C1\n\t_I2C1 = I2C{\n\t\tBus: nxp.LPI2C1,\n\t\tsda: I2C1_SDA_PIN, // D18 (PA17 [AD_B1_01])\n\t\tscl: I2C1_SCL_PIN, // D19 (PA16 [AD_B1_00])\n\t\tmuxSDA: muxSelect{\n\t\t\tmux: nxp.IOMUXC_LPI2C1_SDA_SELECT_INPUT_DAISY_GPIO_AD_B1_01_ALT3,\n\t\t\tsel: &nxp.IOMUXC.LPI2C1_SDA_SELECT_INPUT,\n\t\t},\n\t\tmuxSCL: muxSelect{\n\t\t\tmux: nxp.IOMUXC_LPI2C1_SCL_SELECT_INPUT_DAISY_GPIO_AD_B1_00_ALT3,\n\t\t\tsel: &nxp.IOMUXC.LPI2C1_SCL_SELECT_INPUT,\n\t\t},\n\t}\n\tI2C2  = &_I2C2\n\t_I2C2 = I2C{\n\t\tBus: nxp.LPI2C3,\n\t\tsda: I2C2_SDA_PIN, // D17 (PA22 [AD_B1_06])\n\t\tscl: I2C2_SCL_PIN, // D16 (PA23 [AD_B1_07])\n\t\tmuxSDA: muxSelect{\n\t\t\tmux: nxp.IOMUXC_LPI2C3_SDA_SELECT_INPUT_DAISY_GPIO_AD_B1_06_ALT1,\n\t\t\tsel: &nxp.IOMUXC.LPI2C3_SDA_SELECT_INPUT,\n\t\t},\n\t\tmuxSCL: muxSelect{\n\t\t\tmux: nxp.IOMUXC_LPI2C3_SCL_SELECT_INPUT_DAISY_GPIO_AD_B1_07_ALT1,\n\t\t\tsel: &nxp.IOMUXC.LPI2C3_SCL_SELECT_INPUT,\n\t\t},\n\t}\n\tI2C3  = &_I2C3\n\t_I2C3 = I2C{\n\t\tBus: nxp.LPI2C4,\n\t\tsda: I2C3_SDA_PIN, // D25 (PA13 [AD_B0_13])\n\t\tscl: I2C3_SCL_PIN, // D24 (PA12 [AD_B0_12])\n\t\tmuxSDA: muxSelect{\n\t\t\tmux: nxp.IOMUXC_LPI2C4_SDA_SELECT_INPUT_DAISY_GPIO_AD_B0_13_ALT0,\n\t\t\tsel: &nxp.IOMUXC.LPI2C4_SDA_SELECT_INPUT,\n\t\t},\n\t\tmuxSCL: muxSelect{\n\t\t\tmux: nxp.IOMUXC_LPI2C4_SCL_SELECT_INPUT_DAISY_GPIO_AD_B0_12_ALT0,\n\t\t\tsel: &nxp.IOMUXC.LPI2C4_SCL_SELECT_INPUT,\n\t\t},\n\t}\n)\n"
  },
  {
    "path": "src/machine/board_teensy41.go",
    "content": "//go:build teensy41\n\npackage machine\n\nimport (\n\t\"device/nxp\"\n\t\"runtime/interrupt\"\n)\n\n// Digital pins\nconst (\n\t//  = Pin  // [Pad]:       Alt Func 0       Alt Func 1       Alt Func 2       Alt Func 3      Alt Func 4            Alt Func 5  Alt Func 6            Alt Func 7             Alt Func 8             Alt Func 9\n\t//  = ----    -----------  ---------------  ---------------  ---------------  --------------  --------------------  ----------  --------------------  ---------------------  ---------------------  ----------------\n\tD0  = PA3  // [AD_B0_03]:  FLEXCAN2_RX      XBAR1_INOUT17    LPUART6_RX       USB_OTG1_OC     FLEXPWM1_PWMX01       GPIO1_IO03  REF_CLK_24M           LPSPI3_PCS0             ~                      ~\n\tD1  = PA2  // [AD_B0_02]:  FLEXCAN2_TX      XBAR1_INOUT16    LPUART6_TX       USB_OTG1_PWR    FLEXPWM1_PWMX00       GPIO1_IO02  LPI2C1_HREQ           LPSPI3_SDI              ~                      ~\n\tD2  = PD4  // [EMC_04]:    SEMC_DATA04      FLEXPWM4_PWMA02  SAI2_TX_DATA     XBAR1_INOUT06   FLEXIO1_FLEXIO04      GPIO4_IO04   ~                     ~                      ~                      ~\n\tD3  = PD5  // [EMC_05]:    SEMC_DATA05      FLEXPWM4_PWMB02  SAI2_TX_SYNC     XBAR1_INOUT07   FLEXIO1_FLEXIO05      GPIO4_IO05   ~                     ~                      ~                      ~\n\tD4  = PD6  // [EMC_06]:    SEMC_DATA06      FLEXPWM2_PWMA00  SAI2_TX_BCLK     XBAR1_INOUT08   FLEXIO1_FLEXIO06      GPIO4_IO06   ~                     ~                      ~                      ~\n\tD5  = PD8  // [EMC_08]:    SEMC_DM00        FLEXPWM2_PWMA01  SAI2_RX_DATA     XBAR1_INOUT17   FLEXIO1_FLEXIO08      GPIO4_IO08   ~                     ~                      ~                      ~\n\tD6  = PB10 // [B0_10]:     LCD_DATA06       QTIMER4_TIMER1   FLEXPWM2_PWMA02  SAI1_TX_DATA03  FLEXIO2_FLEXIO10      GPIO2_IO10  SRC_BOOT_CFG06        ENET2_CRS               ~                      ~\n\tD7  = PB17 // [B1_01]:     LCD_DATA13       XBAR1_INOUT15    LPUART4_RX       SAI1_TX_DATA00  FLEXIO2_FLEXIO17      GPIO2_IO17  FLEXPWM1_PWMB03       ENET2_RDATA00          FLEXIO3_FLEXIO17        ~\n\tD8  = PB16 // [B1_00]:     LCD_DATA12       XBAR1_INOUT14    LPUART4_TX       SAI1_RX_DATA00  FLEXIO2_FLEXIO16      GPIO2_IO16  FLEXPWM1_PWMA03       ENET2_RX_ER            FLEXIO3_FLEXIO16        ~\n\tD9  = PB11 // [B0_11]:     LCD_DATA07       QTIMER4_TIMER2   FLEXPWM2_PWMB02  SAI1_TX_DATA02  FLEXIO2_FLEXIO11      GPIO2_IO11  SRC_BOOT_CFG07        ENET2_COL               ~                      ~\n\tD10 = PB0  // [B0_00]:     LCD_CLK          QTIMER1_TIMER0   MQS_RIGHT        LPSPI4_PCS0     FLEXIO2_FLEXIO00      GPIO2_IO00  SEMC_CSX01            ENET2_MDC               ~                      ~\n\tD11 = PB2  // [B0_02]:     LCD_HSYNC        QTIMER1_TIMER2   FLEXCAN1_TX      LPSPI4_SDO      FLEXIO2_FLEXIO02      GPIO2_IO02  SEMC_CSX03            ENET2_1588_EVENT0_OUT   ~                      ~\n\tD12 = PB1  // [B0_01]:     LCD_ENABLE       QTIMER1_TIMER1   MQS_LEFT         LPSPI4_SDI      FLEXIO2_FLEXIO01      GPIO2_IO01  SEMC_CSX02            ENET2_MDIO              ~                      ~\n\tD13 = PB3  // [B0_03]:     LCD_VSYNC        QTIMER2_TIMER0   FLEXCAN1_RX      LPSPI4_SCK      FLEXIO2_FLEXIO03      GPIO2_IO03  WDOG2_RESET_B_DEB     ENET2_1588_EVENT0_IN    ~                      ~\n\tD14 = PA18 // [AD_B1_02]:  USB_OTG1_ID      QTIMER3_TIMER2   LPUART2_TX       SPDIF_OUT       ENET_1588_EVENT2_OUT  GPIO1_IO18  USDHC1_CD_B           KPP_ROW06              GPT2_CLK               FLEXIO3_FLEXIO02\n\tD15 = PA19 // [AD_B1_03]:  USB_OTG1_OC      QTIMER3_TIMER3   LPUART2_RX       SPDIF_IN        ENET_1588_EVENT2_IN   GPIO1_IO19  USDHC2_CD_B           KPP_COL06              GPT2_CAPTURE1          FLEXIO3_FLEXIO03\n\tD16 = PA23 // [AD_B1_07]:  FLEXSPIB_DATA00  LPI2C3_SCL       LPUART3_RX       SPDIF_EXT_CLK   CSI_HSYNC             GPIO1_IO23  USDHC2_DATA3          KPP_COL04              GPT2_COMPARE3          FLEXIO3_FLEXIO07\n\tD17 = PA22 // [AD_B1_06]:  FLEXSPIB_DATA01  LPI2C3_SDA       LPUART3_TX       SPDIF_LOCK      CSI_VSYNC             GPIO1_IO22  USDHC2_DATA2          KPP_ROW04              GPT2_COMPARE2          FLEXIO3_FLEXIO06\n\tD18 = PA17 // [AD_B1_01]:  USB_OTG1_PWR     QTIMER3_TIMER1   LPUART2_RTS_B    LPI2C1_SDA      CCM_PMIC_READY        GPIO1_IO17  USDHC1_VSELECT        KPP_COL07              ENET2_1588_EVENT0_IN   FLEXIO3_FLEXIO01\n\tD19 = PA16 // [AD_B1_00]:  USB_OTG2_ID      QTIMER3_TIMER0   LPUART2_CTS_B    LPI2C1_SCL      WDOG1_B               GPIO1_IO16  USDHC1_WP             KPP_ROW07              ENET2_1588_EVENT0_OUT  FLEXIO3_FLEXIO00\n\tD20 = PA26 // [AD_B1_10]:  FLEXSPIA_DATA03  WDOG1_B          LPUART8_TX       SAI1_RX_SYNC    CSI_DATA07            GPIO1_IO26  USDHC2_WP             KPP_ROW02              ENET2_1588_EVENT1_OUT  FLEXIO3_FLEXIO10\n\tD21 = PA27 // [AD_B1_11]:  FLEXSPIA_DATA02  EWM_OUT_B        LPUART8_RX       SAI1_RX_BCLK    CSI_DATA06            GPIO1_IO27  USDHC2_RESET_B        KPP_COL02              ENET2_1588_EVENT1_IN   FLEXIO3_FLEXIO11\n\tD22 = PA24 // [AD_B1_08]:  FLEXSPIA_SS1_B   FLEXPWM4_PWMA00  FLEXCAN1_TX      CCM_PMIC_READY  CSI_DATA09            GPIO1_IO24  USDHC2_CMD            KPP_ROW03              FLEXIO3_FLEXIO08        ~\n\tD23 = PA25 // [AD_B1_09]:  FLEXSPIA_DQS     FLEXPWM4_PWMA01  FLEXCAN1_RX      SAI1_MCLK       CSI_DATA08            GPIO1_IO25  USDHC2_CLK            KPP_COL03              FLEXIO3_FLEXIO09        ~\n\tD24 = PA12 // [AD_B0_12]:  LPI2C4_SCL       CCM_PMIC_READY   LPUART1_TX       WDOG2_WDOG_B    FLEXPWM1_PWMX02       GPIO1_IO12  ENET_1588_EVENT1_OUT  NMI_GLUE_NMI            ~                      ~\n\tD25 = PA13 // [AD_B0_13]:  LPI2C4_SDA       GPT1_CLK         LPUART1_RX       EWM_OUT_B       FLEXPWM1_PWMX03       GPIO1_IO13  ENET_1588_EVENT1_IN   REF_CLK_24M             ~                      ~\n\tD26 = PA30 // [AD_B1_14]:  FLEXSPIA_SCLK    ACMP_OUT02       LPSPI3_SDO       SAI1_TX_BCLK    CSI_DATA03            GPIO1_IO30  USDHC2_DATA6          KPP_ROW00              ENET2_1588_EVENT3_OUT  FLEXIO3_FLEXIO14\n\tD27 = PA31 // [AD_B1_15]:  FLEXSPIA_SS0_B   ACMP_OUT03       LPSPI3_SCK       SAI1_TX_SYNC    CSI_DATA02            GPIO1_IO31  USDHC2_DATA7          KPP_COL00              ENET2_1588_EVENT3_IN   FLEXIO3_FLEXIO15\n\tD28 = PC18 // [EMC_32]:    SEMC_DATA10      FLEXPWM3_PWMB01  LPUART7_RX       CCM_PMIC_RDY    CSI_DATA21            GPIO3_IO18  ENET2_TX_EN            ~                      ~                      ~\n\tD29 = PD31 // [EMC_31]:    SEMC_DATA09      FLEXPWM3_PWMA01  LPUART7_TX       LPSPI1_PCS1     CSI_DATA22            GPIO4_IO31  ENET2_TDATA01          ~                      ~                      ~\n\tD30 = PC23 // [EMC_37]:    SEMC_DATA15      XBAR1_IN23       GPT1_COMPARE3    SAI3_MCLK       CSI_DATA16            GPIO3_IO23  USDHC2_WP             ENET2_RX_EN            FLEXCAN3_RX             ~\n\tD31 = PC22 // [EMC_36]:    SEMC_DATA14      XBAR1_IN22       GPT1_COMPARE2    SAI3_TX_DATA    CSI_DATA17            GPIO3_IO22  USDHC1_WP             ENET2_RDATA01          FLEXCAN3_TX             ~\n\tD32 = PB12 // [B0_12]:     LCD_DATA08       XBAR1_INOUT10    ARM_TRACE_CLK    SAI1_TX_DATA01  FLEXIO2_FLEXIO12      GPIO2_IO12  SRC_BOOT_CFG08        ENET2_TDATA00           ~                      ~\n\tD33 = PD7  // [EMC_07]:    SEMC_DATA07      FLEXPWM2_PWMB00  SAI2_MCLK        XBAR1_INOUT09   FLEXIO1_FLEXIO07      GPIO4_IO07   ~                     ~                      ~                      ~\n\tD34 = PB29 // [B1_13]:     WDOG1_B          LPUART5_RX       CSI_VSYNC            ENET_1588_EVENT0_OUT  FLEXIO2_FLEXIO29      GPIO2_IO29   USDHC1_WP             SEMC_DQS4             FLEXIO3_FLEXIO29        ~\n\tD35 = PB28 // [B1_12]:     LPUART5_TX       CSI_PIXCLK       ENET_1588_EVENT0_IN  FLEXIO2_FLEXIO28      GPIO2_IO28            USDHC1_CD_B  FLEXIO3_FLEXIO28       ~                     ~                      ~\n\tD36 = PB18 // [B1_02]:     LCD_DATA14       XBAR1_INOUT16    LPSPI4_PCS2          SAI1_TX_BCLK          FLEXIO2_FLEXIO18      GPIO2_IO18   FLEXPWM2_PWMA03       ENET2_RDATA01         FLEXIO3_FLEXIO18        ~\n\tD37 = PB19 // [B1_03]:     LCD_DATA15       XBAR1_INOUT17    LPSPI4_PCS1          SAI1_TX_SYNC          FLEXIO2_FLEXIO19      GPIO2_IO19   FLEXPWM2_PWMB03       ENET2_RX_EN           FLEXIO3_FLEXIO19        ~\n\tD38 = PA28 // [AD_B1_12]:  FLEXSPIA_DATA01  ACMP_OUT00       LPSPI3_PCS0          SAI1_RX_DATA00        CSI_DATA05            GPIO1_IO28   USDHC2_DATA4          KPP_ROW01             ENET2_1588_EVENT2_OUT  FLEXIO3_FLEXIO12\n\tD39 = PA29 // [AD_B1_13]:  FLEXSPIA_DATA00  ACMP_OUT01       LPSPI3_SDI           SAI1_TX_DATA00        CSI_DATA04            GPIO1_IO29   USDHC2_DATA5          KPP_COL01             ENET2_1588_EVENT2_IN   FLEXIO3_FLEXIO13\n\tD40 = PA20 // [AD_B1_04]:  FLEXSPIB_DATA03  ENET_MDC         LPUART3_CTS_B        SPDIF_SR_CLK          CSI_PIXCLK            GPIO1_IO20   USDHC2_DATA0          KPP_ROW05             GPT2_CAPTURE2          FLEXIO3_FLEXIO04\n\tD41 = PA21 // [AD_B1_05]:  FLEXSPIB_DATA02  ENET_MDIO        LPUART3_RTS_B        SPDIF_OUT             CSI_MCLK              GPIO1_IO21   USDHC2_DATA1          KPP_COL05             GPT2_COMPARE1          FLEXIO3_FLEXIO05\n\tD42 = PC15 // [SD_B0_03]:  USDHC1_DATA1     FLEXPWM1_PWMB01  LPUART8_RTS_B        XBAR1_INOUT07         LPSPI1_SDI            GPIO3_IO15   ENET2_RDATA00         SEMC_CLK6              ~                      ~\n\tD43 = PC14 // [SD_B0_02]:  USDHC1_DATA0     FLEXPWM1_PWMA01  LPUART8_CTS_B        XBAR1_INOUT06         LPSPI1_SDO            GPIO3_IO14   ENET2_RX_ER           SEMC_CLK5              ~                      ~\n\tD44 = PC13 // [SD_B0_01]:  USDHC1_CLK       FLEXPWM1_PWMB00  LPI2C3_SDA           XBAR1_INOUT05         LPSPI1_PCS0           GPIO3_IO13   FLEXSPIB_SS1_B        ENET2_TX_CLK          ENET2_REF_CLK2          ~\n\tD45 = PC12 // [SD_B0_00]:  USDHC1_CMD       FLEXPWM1_PWMA00  LPI2C3_SCL           XBAR1_INOUT04         LPSPI1_SCK            GPIO3_IO12   FLEXSPIA_SS1_B        ENET2_TX_EN           SEMC_DQS4               ~\n\tD46 = PC17 // [SD_B0_05]:  USDHC1_DATA3     FLEXPWM1_PWMB02  LPUART8_RX           XBAR1_INOUT09         FLEXSPIB_DQS          GPIO3_IO17   CCM_CLKO2             ENET2_RX_EN            ~                      ~\n\tD47 = PC16 // [SD_B0_04]:  USDHC1_DATA2     FLEXPWM1_PWMA02  LPUART8_TX           XBAR1_INOUT08         FLEXSPIB_SS0_B        GPIO3_IO16   CCM_CLKO1             ENET2_RDATA01          ~                      ~\n\tD48 = PD24 // [EMC_24]:    SEMC_CAS         FLEXPWM1_PWMB00  LPUART5_RX           ENET_TX_EN            GPT1_CAPTURE1         GPIO4_IO24   FLEXSPI2_A_SS0_B       ~                     ~                      ~\n\tD49 = PD27 // [EMC_27]:    SEMC_CKE         FLEXPWM1_PWMA02  LPUART5_RTS_B        LPSPI1_SCK            FLEXIO1_FLEXIO13      GPIO4_IO27   FLEXSPI2_A_DATA01      ~                     ~                      ~\n\tD50 = PD28 // [EMC_28]:    SEMC_WE          FLEXPWM1_PWMB02  LPUART5_CTS_B        LPSPI1_SDO            FLEXIO1_FLEXIO14      GPIO4_IO28   FLEXSPI2_A_DATA02      ~                     ~                      ~\n\tD51 = PD22 // [EMC_22]:    SEMC_BA1         FLEXPWM3_PWMB03  LPI2C3_SCL           ENET_TDATA00          QTIMER2_TIMER3        GPIO4_IO22   FLEXSPI2_A_SS1_B       ~                     ~                      ~\n\tD52 = PD26 // [EMC_26]:    SEMC_CLK         FLEXPWM1_PWMB01  LPUART6_RX           ENET_RX_ER            FLEXIO1_FLEXIO12      GPIO4_IO26   FLEXSPI2_A_DATA00      ~                     ~                      ~\n\tD53 = PD25 // [EMC_25]:    SEMC_RAS         FLEXPWM1_PWMA01  LPUART6_TX           ENET_TX_CLK           ENET_REF_CLK          GPIO4_IO25   FLEXSPI2_A_SCLK        ~                     ~                      ~\n\tD54 = PD29 // [EMC_29]:    SEMC_CS0         FLEXPWM3_PWMA00  LPUART6_RTS_B        LPSPI1_SDI            FLEXIO1_FLEXIO15      GPIO4_IO29   FLEXSPI2_A_DATA03      ~                     ~                      ~\n)\n\n// Analog pins\nconst (\n\t//  = Pin  // Dig | [Pad]      {ADC1/ADC2}\n\tA0  = PA18 // D14 | [AD_B1_02] {  7 / 7  }\n\tA1  = PA19 // D15 | [AD_B1_03] {  8 / 8  }\n\tA2  = PA23 // D16 | [AD_B1_07] { 12 / 12 }\n\tA3  = PA22 // D17 | [AD_B1_06] { 11 / 11 }\n\tA4  = PA17 // D18 | [AD_B1_01] {  6 / 6  }\n\tA5  = PA16 // D19 | [AD_B1_00] {  5 / 5  }\n\tA6  = PA26 // D20 | [AD_B1_10] { 15 / 15 }\n\tA7  = PA27 // D21 | [AD_B1_11] {  0 / 0  }\n\tA8  = PA24 // D22 | [AD_B1_08] { 13 / 13 }\n\tA9  = PA25 // D23 | [AD_B1_09] { 14 / 14 }\n\tA10 = PA12 // D24 | [AD_B0_12] {  1 / -  }\n\tA11 = PA13 // D25 | [AD_B0_13] {  2 / -  }\n\tA12 = PA30 // D26 | [AD_B1_14] {  - / 3  }\n\tA13 = PA31 // D27 | [AD_B1_15] {  - / 4  }\n\tA14 = PA28 // D38 | [AD_B1_12] {  ? / ?  } // FIXME\n\tA15 = PA29 // D39 | [AD_B1_13] {  ? / ?  } // FIXME\n\tA16 = PA20 // D40 | [AD_B1_04] {  ? / ?  } // FIXME\n\tA17 = PA21 // D41 | [AD_B1_05] {  ? / ?  } // FIXME\n)\n\n// Default peripheral pins\nconst (\n\tLED = D13\n\n\tUART_RX_PIN = UART1_RX_PIN // D0\n\tUART_TX_PIN = UART1_TX_PIN // D1\n\n\tSPI_SDI_PIN = SPI1_SDI_PIN // D12\n\tSPI_SDO_PIN = SPI1_SDO_PIN // D11\n\tSPI_SCK_PIN = SPI1_SCK_PIN // D13\n\tSPI_CS_PIN  = SPI1_CS_PIN  // D10\n\n\tI2C_SDA_PIN = I2C1_SDA_PIN // D18/A4\n\tI2C_SCL_PIN = I2C1_SCL_PIN // D19/A5\n)\n\n// Default peripherals\nvar (\n\tDefaultUART = UART1\n)\n\nfunc init() {\n\t// register any interrupt handlers for this board's peripherals\n\t_UART1.Interrupt = interrupt.New(nxp.IRQ_LPUART6, _UART1.handleInterrupt)\n\t_UART2.Interrupt = interrupt.New(nxp.IRQ_LPUART4, _UART2.handleInterrupt)\n\t_UART3.Interrupt = interrupt.New(nxp.IRQ_LPUART2, _UART3.handleInterrupt)\n\t_UART4.Interrupt = interrupt.New(nxp.IRQ_LPUART3, _UART4.handleInterrupt)\n\t_UART5.Interrupt = interrupt.New(nxp.IRQ_LPUART8, _UART5.handleInterrupt)\n\t_UART6.Interrupt = interrupt.New(nxp.IRQ_LPUART1, _UART6.handleInterrupt)\n\t_UART7.Interrupt = interrupt.New(nxp.IRQ_LPUART7, _UART7.handleInterrupt)\n\t_UART8.Interrupt = interrupt.New(nxp.IRQ_LPUART5, _UART8.handleInterrupt)\n}\n\n// #=====================================================#\n// |                        UART                         |\n// #===========#===========#=============#===============#\n// | Interface | Hardware  | Clock(Freq) |  RX/TX  : Alt |\n// #===========#===========#=============#=========-=====#\n// |   UART1   |  LPUART6  | OSC(24 MHz) |  D0/D1  : 2/2 |\n// |   UART2   |  LPUART4  | OSC(24 MHz) |  D7/D8  : 2/2 |\n// |   UART3   |  LPUART2  | OSC(24 MHz) | D15/D14 : 2/2 |\n// |   UART4   |  LPUART3  | OSC(24 MHz) | D16/D17 : 2/2 |\n// |   UART5   |  LPUART8  | OSC(24 MHz) | D21/D20 : 2/2 |\n// |   UART6   |  LPUART1  | OSC(24 MHz) | D25/D24 : 2/2 |\n// |   UART7   |  LPUART7  | OSC(24 MHz) | D28/D29 : 2/2 |\n// |   UART8   |  LPUART5  | OSC(24 MHz) | D34/D35 : 1/1 |\n// #===========#===========#=============#=========-=====#\nconst (\n\tUART1_RX_PIN = D0\n\tUART1_TX_PIN = D1\n\n\tUART2_RX_PIN = D7\n\tUART2_TX_PIN = D8\n\n\tUART3_RX_PIN = D15\n\tUART3_TX_PIN = D14\n\n\tUART4_RX_PIN = D16\n\tUART4_TX_PIN = D17\n\n\tUART5_RX_PIN = D21\n\tUART5_TX_PIN = D20\n\n\tUART6_RX_PIN = D25\n\tUART6_TX_PIN = D24\n\n\tUART7_RX_PIN = D28\n\tUART7_TX_PIN = D29\n\n\tUART8_RX_PIN = D34\n\tUART8_TX_PIN = D35\n)\n\nvar (\n\tUART1  = &_UART1\n\t_UART1 = UART{\n\t\tBus:      nxp.LPUART6,\n\t\tBuffer:   NewRingBuffer(),\n\t\ttxBuffer: NewRingBuffer(),\n\t\tmuxRX: muxSelect{ // D0 (PA3 [AD_B0_03])\n\t\t\tmux: nxp.IOMUXC_LPUART6_RX_SELECT_INPUT_DAISY_GPIO_AD_B0_03_ALT2,\n\t\t\tsel: &nxp.IOMUXC.LPUART6_RX_SELECT_INPUT,\n\t\t},\n\t\tmuxTX: muxSelect{ // D1 (PA2 [AD_B0_02])\n\t\t\tmux: nxp.IOMUXC_LPUART6_TX_SELECT_INPUT_DAISY_GPIO_AD_B0_02_ALT2,\n\t\t\tsel: &nxp.IOMUXC.LPUART6_TX_SELECT_INPUT,\n\t\t},\n\t}\n\tUART2  = &_UART2\n\t_UART2 = UART{\n\t\tBus:      nxp.LPUART4,\n\t\tBuffer:   NewRingBuffer(),\n\t\ttxBuffer: NewRingBuffer(),\n\t\tmuxRX: muxSelect{ // D7 (PB17 [B1_01])\n\t\t\tmux: nxp.IOMUXC_LPUART4_RX_SELECT_INPUT_DAISY_GPIO_B1_01_ALT2,\n\t\t\tsel: &nxp.IOMUXC.LPUART4_RX_SELECT_INPUT,\n\t\t},\n\t\tmuxTX: muxSelect{ // D8 (PB16 [B1_00])\n\t\t\tmux: nxp.IOMUXC_LPUART4_TX_SELECT_INPUT_DAISY_GPIO_B1_00_ALT2,\n\t\t\tsel: &nxp.IOMUXC.LPUART4_TX_SELECT_INPUT,\n\t\t},\n\t}\n\tUART3  = &_UART3\n\t_UART3 = UART{\n\t\tBus:      nxp.LPUART2,\n\t\tBuffer:   NewRingBuffer(),\n\t\ttxBuffer: NewRingBuffer(),\n\t\tmuxRX: muxSelect{ // D15 (PA19 [AD_B1_03])\n\t\t\tmux: nxp.IOMUXC_LPUART2_RX_SELECT_INPUT_DAISY_GPIO_AD_B1_03_ALT2,\n\t\t\tsel: &nxp.IOMUXC.LPUART2_RX_SELECT_INPUT,\n\t\t},\n\t\tmuxTX: muxSelect{ // D14 (PA18 [AD_B1_02])\n\t\t\tmux: nxp.IOMUXC_LPUART2_TX_SELECT_INPUT_DAISY_GPIO_AD_B1_02_ALT2,\n\t\t\tsel: &nxp.IOMUXC.LPUART2_TX_SELECT_INPUT,\n\t\t},\n\t}\n\tUART4  = &_UART4\n\t_UART4 = UART{\n\t\tBus:      nxp.LPUART3,\n\t\tBuffer:   NewRingBuffer(),\n\t\ttxBuffer: NewRingBuffer(),\n\t\tmuxRX: muxSelect{ // D16 (PA23 [AD_B1_07])\n\t\t\tmux: nxp.IOMUXC_LPUART3_RX_SELECT_INPUT_DAISY_GPIO_AD_B1_07_ALT2,\n\t\t\tsel: &nxp.IOMUXC.LPUART3_RX_SELECT_INPUT,\n\t\t},\n\t\tmuxTX: muxSelect{ // D17 (PA22 [AD_B1_06])\n\t\t\tmux: nxp.IOMUXC_LPUART3_TX_SELECT_INPUT_DAISY_GPIO_AD_B1_06_ALT2,\n\t\t\tsel: &nxp.IOMUXC.LPUART3_TX_SELECT_INPUT,\n\t\t},\n\t}\n\tUART5  = &_UART5\n\t_UART5 = UART{\n\t\tBus:      nxp.LPUART8,\n\t\tBuffer:   NewRingBuffer(),\n\t\ttxBuffer: NewRingBuffer(),\n\t\tmuxRX: muxSelect{ // D21 (PA27 [AD_B1_11])\n\t\t\tmux: nxp.IOMUXC_LPUART8_RX_SELECT_INPUT_DAISY_GPIO_AD_B1_11_ALT2,\n\t\t\tsel: &nxp.IOMUXC.LPUART8_RX_SELECT_INPUT,\n\t\t},\n\t\tmuxTX: muxSelect{ // D20 (PA26 [AD_B1_10])\n\t\t\tmux: nxp.IOMUXC_LPUART8_TX_SELECT_INPUT_DAISY_GPIO_AD_B1_10_ALT2,\n\t\t\tsel: &nxp.IOMUXC.LPUART8_TX_SELECT_INPUT,\n\t\t},\n\t}\n\tUART6  = &_UART6\n\t_UART6 = UART{\n\t\tBus:      nxp.LPUART1,\n\t\tBuffer:   NewRingBuffer(),\n\t\ttxBuffer: NewRingBuffer(),\n\t\t// LPUART1 not connected via IOMUXC\n\t\t//   RX: D24 (PA12 [AD_B0_12])\n\t\t//   TX: D25 (PA13 [AD_B0_13])\n\t}\n\tUART7  = &_UART7\n\t_UART7 = UART{\n\t\tBus:      nxp.LPUART7,\n\t\tBuffer:   NewRingBuffer(),\n\t\ttxBuffer: NewRingBuffer(),\n\t\tmuxRX: muxSelect{ // D28 (PC18 [EMC_32])\n\t\t\tmux: nxp.IOMUXC_LPUART7_RX_SELECT_INPUT_DAISY_GPIO_EMC_32_ALT2,\n\t\t\tsel: &nxp.IOMUXC.LPUART7_RX_SELECT_INPUT,\n\t\t},\n\t\tmuxTX: muxSelect{ // D29 (PD31 [EMC_31])\n\t\t\tmux: nxp.IOMUXC_LPUART7_TX_SELECT_INPUT_DAISY_GPIO_EMC_31_ALT2,\n\t\t\tsel: &nxp.IOMUXC.LPUART7_TX_SELECT_INPUT,\n\t\t},\n\t}\n\tUART8  = &_UART8\n\t_UART8 = UART{\n\t\tBus:      nxp.LPUART5,\n\t\tBuffer:   NewRingBuffer(),\n\t\ttxBuffer: NewRingBuffer(),\n\t\tmuxRX: muxSelect{ // D34 (PB29 [B1_13])\n\t\t\tmux: nxp.IOMUXC_LPUART5_RX_SELECT_INPUT_DAISY_GPIO_B1_13_ALT1,\n\t\t\tsel: &nxp.IOMUXC.LPUART5_RX_SELECT_INPUT,\n\t\t},\n\t\tmuxTX: muxSelect{ // D35 (PB28 [B1_12])\n\t\t\tmux: nxp.IOMUXC_LPUART5_TX_SELECT_INPUT_DAISY_GPIO_B1_12_ALT1,\n\t\t\tsel: &nxp.IOMUXC.LPUART5_TX_SELECT_INPUT,\n\t\t},\n\t}\n)\n\n// #===========#==========#===============#===========================#\n// | Interface | Hardware |  Clock(Freq)  | SDI/SDO/SCK/CS  :   Alt   |\n// #===========#==========#===============#=================-=========#\n// |   SPI1    |  LPSPI4  | PLL2(132 MHz) | D12/D11/D13/D10 : 3/3/3/3 |\n// |   SPI2    |  LPSPI3  | PLL2(132 MHz) |  D1/D26/D27/D0  : 7/2/2/7 |\n// |   SPI3    |  LPSPI1  | PLL2(132 MHz) | D42/D43/D45/D44 : 4/4/4/4 |\n// #===========#==========#===============#=================-=========#\nconst (\n\tSPI1_SDI_PIN = D12\n\tSPI1_SDO_PIN = D11\n\tSPI1_SCK_PIN = D13\n\tSPI1_CS_PIN  = D10\n\n\tSPI2_SDI_PIN = D1\n\tSPI2_SDO_PIN = D26\n\tSPI2_SCK_PIN = D27\n\tSPI2_CS_PIN  = D0\n\n\tSPI3_SDI_PIN = D42\n\tSPI3_SDO_PIN = D43\n\tSPI3_SCK_PIN = D45\n\tSPI3_CS_PIN  = D44\n)\n\nvar (\n\tSPI0 = SPI1 // SPI0 is an alias of SPI1 (LPSPI4)\n\tSPI1 = &SPI{\n\t\tBus: nxp.LPSPI4,\n\t\tmuxSDI: muxSelect{ // D12 (PB1 [B0_01])\n\t\t\tmux: nxp.IOMUXC_LPSPI4_SDI_SELECT_INPUT_DAISY_GPIO_B0_01_ALT3,\n\t\t\tsel: &nxp.IOMUXC.LPSPI4_SDI_SELECT_INPUT,\n\t\t},\n\t\tmuxSDO: muxSelect{ // D11 (PB2 [B0_02])\n\t\t\tmux: nxp.IOMUXC_LPSPI4_SDO_SELECT_INPUT_DAISY_GPIO_B0_02_ALT3,\n\t\t\tsel: &nxp.IOMUXC.LPSPI4_SDO_SELECT_INPUT,\n\t\t},\n\t\tmuxSCK: muxSelect{ // D13 (PB3 [B0_03])\n\t\t\tmux: nxp.IOMUXC_LPSPI4_SCK_SELECT_INPUT_DAISY_GPIO_B0_03_ALT3,\n\t\t\tsel: &nxp.IOMUXC.LPSPI4_SCK_SELECT_INPUT,\n\t\t},\n\t\tmuxCS: muxSelect{ // D10 (PB0 [B0_00])\n\t\t\tmux: nxp.IOMUXC_LPSPI4_PCS0_SELECT_INPUT_DAISY_GPIO_B0_00_ALT3,\n\t\t\tsel: &nxp.IOMUXC.LPSPI4_PCS0_SELECT_INPUT,\n\t\t},\n\t}\n\tSPI2 = &SPI{\n\t\tBus: nxp.LPSPI3,\n\t\tmuxSDI: muxSelect{ // D1 (PA2 [AD_B0_02])\n\t\t\tmux: nxp.IOMUXC_LPSPI3_SDI_SELECT_INPUT_DAISY_GPIO_AD_B0_02_ALT7,\n\t\t\tsel: &nxp.IOMUXC.LPSPI3_SDI_SELECT_INPUT,\n\t\t},\n\t\tmuxSDO: muxSelect{ // D26 (PA30 [AD_B1_14])\n\t\t\tmux: nxp.IOMUXC_LPSPI3_SDO_SELECT_INPUT_DAISY_GPIO_AD_B1_14_ALT2,\n\t\t\tsel: &nxp.IOMUXC.LPSPI3_SDO_SELECT_INPUT,\n\t\t},\n\t\tmuxSCK: muxSelect{ // D27 (PA31 [AD_B1_15])\n\t\t\tmux: nxp.IOMUXC_LPSPI3_SCK_SELECT_INPUT_DAISY_GPIO_AD_B1_15,\n\t\t\tsel: &nxp.IOMUXC.LPSPI3_SCK_SELECT_INPUT,\n\t\t},\n\t\tmuxCS: muxSelect{ // D0 (PA3 [AD_B0_03])\n\t\t\tmux: nxp.IOMUXC_LPSPI3_PCS0_SELECT_INPUT_DAISY_GPIO_AD_B0_03_ALT7,\n\t\t\tsel: &nxp.IOMUXC.LPSPI3_PCS0_SELECT_INPUT,\n\t\t},\n\t}\n)\n\n// #====================================================#\n// |                         I2C                        |\n// #===========#==========#=============#===============#\n// | Interface | Hardware | Clock(Freq) | SDA/SCL : Alt |\n// #===========#==========#=============#=========-=====#\n// |   I2C1    |  LPI2C1  | OSC(24 MHz) | D18/D19 : 3/3 |\n// |   I2C2    |  LPI2C3  | OSC(24 MHz) | D17/D16 : 1/1 |\n// |   I2C3    |  LPI2C4  | OSC(24 MHz) | D25/D24 : 0/0 |\n// #===========#==========#=============#=========-=====#\nconst (\n\tI2C1_SDA_PIN = D18\n\tI2C1_SCL_PIN = D19\n\n\tI2C2_SDA_PIN = D17\n\tI2C2_SCL_PIN = D16\n\n\tI2C3_SDA_PIN = D25\n\tI2C3_SCL_PIN = D24\n)\n\nvar (\n\tI2C0  = I2C1 // I2C0 is an alias for I2C1 (LPI2C1)\n\tI2C1  = &_I2C1\n\t_I2C1 = I2C{\n\t\tBus: nxp.LPI2C1,\n\t\tsda: I2C1_SDA_PIN, // D18 (PA17 [AD_B1_01])\n\t\tscl: I2C1_SCL_PIN, // D19 (PA16 [AD_B1_00])\n\t\tmuxSDA: muxSelect{\n\t\t\tmux: nxp.IOMUXC_LPI2C1_SDA_SELECT_INPUT_DAISY_GPIO_AD_B1_01_ALT3,\n\t\t\tsel: &nxp.IOMUXC.LPI2C1_SDA_SELECT_INPUT,\n\t\t},\n\t\tmuxSCL: muxSelect{\n\t\t\tmux: nxp.IOMUXC_LPI2C1_SCL_SELECT_INPUT_DAISY_GPIO_AD_B1_00_ALT3,\n\t\t\tsel: &nxp.IOMUXC.LPI2C1_SCL_SELECT_INPUT,\n\t\t},\n\t}\n\tI2C2  = &_I2C2\n\t_I2C2 = I2C{\n\t\tBus: nxp.LPI2C3,\n\t\tsda: I2C2_SDA_PIN, // D17 (PA22 [AD_B1_06])\n\t\tscl: I2C2_SCL_PIN, // D16 (PA23 [AD_B1_07])\n\t\tmuxSDA: muxSelect{\n\t\t\tmux: nxp.IOMUXC_LPI2C3_SDA_SELECT_INPUT_DAISY_GPIO_AD_B1_06_ALT1,\n\t\t\tsel: &nxp.IOMUXC.LPI2C3_SDA_SELECT_INPUT,\n\t\t},\n\t\tmuxSCL: muxSelect{\n\t\t\tmux: nxp.IOMUXC_LPI2C3_SCL_SELECT_INPUT_DAISY_GPIO_AD_B1_07_ALT1,\n\t\t\tsel: &nxp.IOMUXC.LPI2C3_SCL_SELECT_INPUT,\n\t\t},\n\t}\n\tI2C3  = &_I2C3\n\t_I2C3 = I2C{\n\t\tBus: nxp.LPI2C4,\n\t\tsda: I2C3_SDA_PIN, // D25 (PA13 [AD_B0_13])\n\t\tscl: I2C3_SCL_PIN, // D24 (PA12 [AD_B0_12])\n\t\tmuxSDA: muxSelect{\n\t\t\tmux: nxp.IOMUXC_LPI2C4_SDA_SELECT_INPUT_DAISY_GPIO_AD_B0_13_ALT0,\n\t\t\tsel: &nxp.IOMUXC.LPI2C4_SDA_SELECT_INPUT,\n\t\t},\n\t\tmuxSCL: muxSelect{\n\t\t\tmux: nxp.IOMUXC_LPI2C4_SCL_SELECT_INPUT_DAISY_GPIO_AD_B0_12_ALT0,\n\t\t\tsel: &nxp.IOMUXC.LPI2C4_SCL_SELECT_INPUT,\n\t\t},\n\t}\n)\n"
  },
  {
    "path": "src/machine/board_thingplus_rp2040.go",
    "content": "//go:build thingplus_rp2040\n\npackage machine\n\n// Onboard crystal oscillator frequency, in MHz.\nconst xoscFreq = 12 // MHz\n\n// GPIO Pins\nconst (\n\tGP0 Pin = GPIO0 // TX\n\tGP1 Pin = GPIO1 // RX\n\tGP2 Pin = GPIO2 // SCK\n\tGP3 Pin = GPIO3 // COPI\n\tGP4 Pin = GPIO4 // CIPO\n\n\tGP6  Pin = GPIO6  // SDA\n\tGP7  Pin = GPIO7  // SCL (connected to GPIO23 as well)\n\tGP8  Pin = GPIO8  // WS2812 RGB LED\n\tGP9  Pin = GPIO9  // muSDcard DATA3 / CS\n\tGP10 Pin = GPIO10 // muSDcard DATA2\n\tGP11 Pin = GPIO11 // muSDcard DATA1\n\tGP12 Pin = GPIO12 // muSDcard DATA0 / CIPO\n\n\tGP14 Pin = GPIO14 // muSDcard CLK /SCLK\n\tGP15 Pin = GPIO15 // muSDcard CMD / COPI\n\tGP16 Pin = GPIO16 // 16\n\tGP17 Pin = GPIO17 // 17\n\tGP18 Pin = GPIO18 // 18\n\tGP19 Pin = GPIO19 // 19\n\tGP20 Pin = GPIO20 // 20\n\tGP21 Pin = GPIO21 // 21\n\tGP22 Pin = GPIO22 // 22\n\tGP23 Pin = GPIO23 // Connected to GPIO7\n\tGP25 Pin = GPIO25 // Status blue LED\n\tGP26 Pin = GPIO26 // ADC0\n\tGP27 Pin = GPIO27 // ADC1\n\tGP28 Pin = GPIO28 // ADC2\n\tGP29 Pin = GPIO29 // ADC3\n)\n\n// Analog pins\nconst (\n\tA0 = GPIO26\n\tA1 = GPIO27\n\tA2 = GPIO28\n\tA3 = GPIO29\n)\n\n// Onboard LEDs\nconst (\n\tLED    = GPIO25\n\tWS2812 = GPIO8\n)\n\n// I2C Pins.\nconst (\n\tI2C0_SCL_PIN = GPIO6 // N/A\n\tI2C0_SDA_PIN = GPIO7 // N/A\n\n\tI2C1_SDA_PIN = GPIO6\n\tI2C1_SCL_PIN = GPIO7\n\n\tSDA_PIN = I2C1_SDA_PIN\n\tSCL_PIN = I2C1_SCL_PIN\n)\n\n// SPI default pins\nconst (\n\t// Default Serial Clock Bus 0 for SPI communications\n\tSPI0_SCK_PIN = GPIO2\n\t// Default Serial Out Bus 0 for SPI communications\n\tSPI0_SDO_PIN = GPIO3 // Tx\n\t// Default Serial In Bus 0 for SPI communications\n\tSPI0_SDI_PIN = GPIO4 // Rx\n\n\t// Default Serial Clock Bus 1 for SPI communications to muSDcard\n\tSPI1_SCK_PIN = GPIO14\n\t// Default Serial Out Bus 1 for SPI communications to muSDcard\n\tSPI1_SDO_PIN = GPIO15 // Tx\n\t// Default Serial In Bus 1 for SPI communications to muSDcard\n\tSPI1_SDI_PIN = GPIO12 // Rx\n)\n\n// UART pins\nconst (\n\tUART0_TX_PIN = GPIO0\n\tUART0_RX_PIN = GPIO1\n\tUART_TX_PIN  = UART0_TX_PIN\n\tUART_RX_PIN  = UART0_RX_PIN\n)\n\nvar DefaultUART = UART0\n\n// USB identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Thing Plus RP2040\"\n\tusb_STRING_MANUFACTURER = \"SparkFun\"\n)\n\nvar (\n\tusb_VID uint16 = 0x1B4F\n\tusb_PID uint16 = 0x0026\n)\n"
  },
  {
    "path": "src/machine/board_thumby.go",
    "content": "//go:build thumby\n\n// This contains the pin mappings for the Thumby.\n//\n// https://thumby.us/\npackage machine\n\nconst (\n\tTHUMBY_SCK_PIN = I2C1_SDA_PIN\n\tTHUMBY_SDA_PIN = I2C1_SCL_PIN\n\n\tTHUMBY_CS_PIN    = GPIO16\n\tTHUMBY_DC_PIN    = GPIO17\n\tTHUMBY_RESET_PIN = GPIO20\n\n\tTHUMBY_LINK_TX_PIN = UART0_TX_PIN\n\tTHUMBY_LINK_RX_PIN = UART0_RX_PIN\n\tTHUMBY_LINK_PU_PIN = GPIO2\n\n\tTHUMBY_BTN_LDPAD_PIN = GPIO3\n\tTHUMBY_BTN_RDPAD_PIN = GPIO5\n\tTHUMBY_BTN_UDPAD_PIN = GPIO4\n\tTHUMBY_BTN_DDPAD_PIN = GPIO6\n\tTHUMBY_BTN_B_PIN     = GPIO24\n\tTHUMBY_BTN_A_PIN     = GPIO27\n\n\tTHUMBY_AUDIO_PIN = GPIO28\n\n\tTHUMBY_SCREEN_RESET_PIN = GPIO20\n)\n\n// I2C pins\nconst (\n\tI2C0_SDA_PIN Pin = NoPin\n\tI2C0_SCL_PIN Pin = NoPin\n\n\tI2C1_SDA_PIN Pin = GPIO18\n\tI2C1_SCL_PIN Pin = GPIO19\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = GPIO18\n\tSPI0_SDO_PIN = GPIO19\n\tSPI0_SDI_PIN = GPIO16\n\n\tSPI1_SCK_PIN = NoPin\n\tSPI1_SDO_PIN = NoPin\n\tSPI1_SDI_PIN = NoPin\n)\n\n// Onboard crystal oscillator frequency, in MHz.\nconst (\n\txoscFreq = 12 // MHz\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Thumby\"\n\tusb_STRING_MANUFACTURER = \"TinyCircuits\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2E8A\n\tusb_PID uint16 = 0x0005\n)\n\n// UART pins\nconst (\n\tUART0_TX_PIN = GPIO0\n\tUART0_RX_PIN = GPIO1\n\tUART_TX_PIN  = UART0_TX_PIN\n\tUART_RX_PIN  = UART0_RX_PIN\n)\n\nvar DefaultUART = UART0\n"
  },
  {
    "path": "src/machine/board_tiny2350.go",
    "content": "//go:build tiny2350\n\npackage machine\n\n// GPIO pins\nconst (\n\tGP0  Pin = GPIO0\n\tGP1  Pin = GPIO1\n\tGP2  Pin = GPIO2\n\tGP3  Pin = GPIO3\n\tGP4  Pin = GPIO4\n\tGP5  Pin = GPIO5\n\tGP6  Pin = GPIO6\n\tGP7  Pin = GPIO7\n\tGP12 Pin = GPIO12\n\tGP13 Pin = GPIO13\n\tGP18 Pin = GPIO18\n\tGP19 Pin = GPIO19\n\tGP20 Pin = GPIO20\n\tGP26 Pin = GPIO26\n\tGP27 Pin = GPIO27\n\tGP28 Pin = GPIO28\n\tGP29 Pin = GPIO29\n\n\t// Onboard LED\n\tLED_RED   Pin = GPIO18\n\tLED_GREEN Pin = GPIO19\n\tLED_BLUE  Pin = GPIO20\n\tLED           = LED_RED\n\n\t// Onboard crystal oscillator frequency, in MHz.\n\txoscFreq = 12 // MHz\n)\n\n// I2C Default pins on Tiny2350.\nconst (\n\tI2C0_SDA_PIN = GP12\n\tI2C0_SCL_PIN = GP13\n\n\tI2C1_SDA_PIN = GP2\n\tI2C1_SCL_PIN = GP3\n)\n\n// SPI default pins\nconst (\n\t// Default Serial Clock Bus 0 for SPI communications\n\tSPI0_SCK_PIN = GPIO6\n\t// Default Serial Out Bus 0 for SPI communications\n\tSPI0_SDO_PIN = GPIO7 // Tx\n\t// Default Serial In Bus 0 for SPI communications\n\tSPI0_SDI_PIN = GPIO4 // Rx\n\n\t// Default Serial Clock Bus 1 for SPI communications\n\tSPI1_SCK_PIN = GPIO26\n\t// Default Serial Out Bus 1 for SPI communications\n\tSPI1_SDO_PIN = GPIO27 // Tx\n\t// Default Serial In Bus 1 for SPI communications\n\tSPI1_SDI_PIN = GPIO28 // Rx\n)\n\n// UART pins\nconst (\n\tUART0_TX_PIN = GPIO0\n\tUART0_RX_PIN = GPIO1\n\tUART1_TX_PIN = GPIO4\n\tUART1_RX_PIN = GPIO5\n\tUART_TX_PIN  = UART0_TX_PIN\n\tUART_RX_PIN  = UART0_RX_PIN\n)\n\nvar DefaultUART = UART0\n\n// USB identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Tiny2350\"\n\tusb_STRING_MANUFACTURER = \"Pimoroni\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2E8A\n\tusb_PID uint16 = 0x000F\n)\n"
  },
  {
    "path": "src/machine/board_trinket.go",
    "content": "//go:build sam && atsamd21 && trinket_m0\n\npackage machine\n\n// used to reset into bootloader\nconst resetMagicValue = 0xf01669ef\n\n// GPIO Pins\nconst (\n\tD0  = PA08 // PWM available\n\tD1  = PA02\n\tD2  = PA09 // PWM available\n\tD3  = PA07 // PWM available / UART0 RX\n\tD4  = PA06 // PWM available / UART0 TX\n\tD13 = PA10 // LED\n)\n\n// Analog pins\nconst (\n\tA0 = D1\n\tA1 = D2\n\tA2 = D0\n\tA3 = D3\n\tA4 = D4\n)\n\nconst (\n\tLED = D13\n)\n\n// USBCDC pins\nconst (\n\tUSBCDC_DM_PIN = PA24\n\tUSBCDC_DP_PIN = PA25\n)\n\n// UART1 pins\nconst (\n\tUART_TX_PIN = D4\n\tUART_RX_PIN = D3\n)\n\n// UART1 on the Trinket M0.\nvar UART1 = &sercomUSART0\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = D3\n\tSPI0_SDO_PIN = D4\n\tSPI0_SDI_PIN = D2\n)\n\n// SPI on the Trinket M0.\nvar SPI0 = sercomSPIM0\n\n// I2C pins\nconst (\n\tSDA_PIN = D0 // SDA\n\tSCL_PIN = D2 // SCL\n)\n\n// I2C on the Trinket M0.\nvar (\n\tI2C0 = sercomI2CM2\n)\n\n// I2S pins\nconst (\n\tI2S_SCK_PIN = PA10\n\tI2S_SDO_PIN = PA08\n\tI2S_SDI_PIN = NoPin // TODO: figure out what this is on Trinket M0.\n\tI2S_WS_PIN  = NoPin // TODO: figure out what this is on Trinket M0.\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Adafruit Trinket M0\"\n\tusb_STRING_MANUFACTURER = \"Adafruit\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239A\n\tusb_PID uint16 = 0x801E\n)\n\nvar (\n\tDefaultUART = UART1\n)\n"
  },
  {
    "path": "src/machine/board_trinkey_qt2040.go",
    "content": "//go:build trinkey_qt2040\n\n// This file contains the pin mappings for the Adafruit Trinkey QT2040 board.\n//\n// The Trinkey QT2040 is a small development board based on the RP2040 which\n// plugs into a USB A port. The board has a minimal pinout: an integrated\n// NeoPixel LED and a STEMMA QT I2C port.\n//\n// - Product:    https://www.adafruit.com/product/5056\n// - Overview:   https://learn.adafruit.com/adafruit-trinkey-qt2040\n// - Pinouts:    https://learn.adafruit.com/adafruit-trinkey-qt2040/pinouts\n// - Datasheets: https://learn.adafruit.com/adafruit-trinkey-qt2040/downloads\n\npackage machine\n\n// Onboard crystal oscillator frequency, in MHz\nconst xoscFreq = 12 // MHz\n\n// Onboard LEDs\nconst (\n\tNEOPIXEL = GPIO27\n\tWS2812   = NEOPIXEL\n)\n\n// I2C pins\nconst (\n\tI2C0_SDA_PIN = GPIO16\n\tI2C0_SCL_PIN = GPIO17\n\n\tI2C1_SDA_PIN = NoPin\n\tI2C1_SCL_PIN = NoPin\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = NoPin\n\tSPI0_SDO_PIN = NoPin\n\tSPI0_SDI_PIN = NoPin\n\n\tSPI1_SCK_PIN = NoPin\n\tSPI1_SDO_PIN = NoPin\n\tSPI1_SDI_PIN = NoPin\n)\n\n// UART pins\nconst (\n\tUART0_TX_PIN = NoPin\n\tUART0_RX_PIN = NoPin\n\tUART_TX_PIN  = UART0_TX_PIN\n\tUART_RX_PIN  = UART0_RX_PIN\n)\n\n// USB identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Trinkey QT2040\"\n\tusb_STRING_MANUFACTURER = \"Adafruit\"\n)\n\nvar (\n\tusb_VID uint16 = 0x239a\n\tusb_PID uint16 = 0x8109\n)\n"
  },
  {
    "path": "src/machine/board_tufty2040.go",
    "content": "//go:build tufty2040\n\n// This contains the pin mappings for the Badger 2040 Connect board.\n//\n// For more information, see: https://shop.pimoroni.com/products/tufty-2040\n// Also\n// - Tufty 2040 schematic: https://cdn.shopify.com/s/files/1/0174/1800/files/tufty_schematic.pdf?v=1655385675\npackage machine\n\nconst (\n\tLED Pin = GPIO25\n\n\tBUTTON_A    Pin = GPIO7\n\tBUTTON_B    Pin = GPIO8\n\tBUTTON_C    Pin = GPIO9\n\tBUTTON_UP   Pin = GPIO22\n\tBUTTON_DOWN Pin = GPIO6\n\tBUTTON_USER Pin = GPIO23\n\n\tLCD_BACKLIGHT Pin = GPIO2\n\tLCD_CS        Pin = GPIO10\n\tLCD_DC        Pin = GPIO11\n\tLCD_WR        Pin = GPIO12\n\tLCD_RD        Pin = GPIO13\n\tLCD_DB0       Pin = GPIO14\n\tLCD_DB1       Pin = GPIO15\n\tLCD_DB2       Pin = GPIO16\n\tLCD_DB3       Pin = GPIO17\n\tLCD_DB4       Pin = GPIO18\n\tLCD_DB5       Pin = GPIO19\n\tLCD_DB6       Pin = GPIO20\n\tLCD_DB7       Pin = GPIO21\n\n\tVBUS_DETECT  Pin = GPIO24\n\tBATTERY      Pin = GPIO29\n\tUSER_LED     Pin = GPIO25\n\tLIGHT_SENSE  Pin = GPIO26\n\tSENSOR_POWER Pin = GPIO27\n)\n\n// I2C pins\nconst (\n\tI2C0_SDA_PIN Pin = GPIO4\n\tI2C0_SCL_PIN Pin = GPIO5\n\n\tI2C1_SDA_PIN Pin = NoPin\n\tI2C1_SCL_PIN Pin = NoPin\n)\n\n// SPI pins.\nconst (\n\tSPI0_SCK_PIN Pin = NoPin\n\tSPI0_SDO_PIN Pin = NoPin\n\tSPI0_SDI_PIN Pin = NoPin\n\n\tSPI1_SCK_PIN Pin = NoPin\n\tSPI1_SDO_PIN Pin = NoPin\n\tSPI1_SDI_PIN Pin = NoPin\n)\n\n// Onboard crystal oscillator frequency, in MHz.\nconst (\n\txoscFreq = 12 // MHz\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Tufty 2040\"\n\tusb_STRING_MANUFACTURER = \"Pimoroni\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2e8a\n\tusb_PID uint16 = 0x1002\n)\n\n// UART pins\nconst (\n\tUART0_TX_PIN = GPIO0\n\tUART0_RX_PIN = GPIO1\n\tUART_TX_PIN  = UART0_TX_PIN\n\tUART_RX_PIN  = UART0_RX_PIN\n)\n\nvar DefaultUART = UART0\n"
  },
  {
    "path": "src/machine/board_waveshare-rp2040-zero.go",
    "content": "//go:build waveshare_rp2040_zero\n\n// This file contains the pin mappings for the Waveshare RP2040-Zero boards.\n//\n// Waveshare RP2040-Zero is a microcontroller using the Raspberry Pi RP2040 chip.\n//\n// - https://www.waveshare.com/wiki/RP2040-Zero\npackage machine\n\n// Digital Pins\nconst (\n\tD0  Pin = GPIO0\n\tD1  Pin = GPIO1\n\tD2  Pin = GPIO2\n\tD3  Pin = GPIO3\n\tD4  Pin = GPIO4\n\tD5  Pin = GPIO5\n\tD6  Pin = GPIO6\n\tD7  Pin = GPIO7\n\tD8  Pin = GPIO8\n\tD9  Pin = GPIO9\n\tD10 Pin = GPIO10\n\tD11 Pin = GPIO11\n\tD12 Pin = GPIO12\n\tD13 Pin = GPIO13\n\tD14 Pin = GPIO14\n\tD15 Pin = GPIO15\n\tD16 Pin = GPIO16\n\tD17 Pin = GPIO17\n\tD18 Pin = GPIO18\n\tD19 Pin = GPIO19\n\tD20 Pin = GPIO20\n\tD21 Pin = GPIO21\n\tD22 Pin = GPIO22\n\tD23 Pin = GPIO23\n\tD24 Pin = GPIO24\n\tD25 Pin = GPIO25\n\tD26 Pin = GPIO26\n\tD27 Pin = GPIO27\n\tD28 Pin = GPIO28\n\tD29 Pin = GPIO29\n)\n\n// Analog pins\nconst (\n\tA0 Pin = D26\n\tA1 Pin = D27\n\tA2 Pin = D28\n\tA3 Pin = D29\n)\n\n// Onboard LEDs\nconst (\n\tNEOPIXEL = GPIO16\n\tWS2812   = GPIO16\n)\n\n// I2C pins\nconst (\n\tI2C0_SDA_PIN Pin = D0\n\tI2C0_SCL_PIN Pin = D1\n\n\tI2C1_SDA_PIN Pin = D2\n\tI2C1_SCL_PIN Pin = D3\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN Pin = D6\n\tSPI0_SDO_PIN Pin = D3\n\tSPI0_SDI_PIN Pin = D4\n\n\tSPI1_SCK_PIN Pin = D10\n\tSPI1_SDO_PIN Pin = D11\n\tSPI1_SDI_PIN Pin = D12\n)\n\n// Onboard crystal oscillator frequency, in MHz.\nconst (\n\txoscFreq = 12 // MHz\n)\n\n// UART pins\nconst (\n\tUART0_TX_PIN = GPIO0\n\tUART0_RX_PIN = GPIO1\n\tUART_TX_PIN  = UART0_TX_PIN\n\tUART_RX_PIN  = UART0_RX_PIN\n\tUART1_TX_PIN = GPIO8\n\tUART1_RX_PIN = GPIO9\n)\n\nvar DefaultUART = UART0\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"RP2040-Zero\"\n\tusb_STRING_MANUFACTURER = \"Waveshare\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2e8a\n\tusb_PID uint16 = 0x0003\n)\n"
  },
  {
    "path": "src/machine/board_waveshare_rp2040_tiny.go",
    "content": "//go:build waveshare_rp2040_tiny\n\n// This file contains the pin mappings for the Waveshare RP2040-Tiny boards.\n//\n// Waveshare RP2040-Tiny is a microcontroller using the Raspberry Pi RP2040 chip.\n//\n// - https://www.waveshare.com/wiki/RP2040-Tiny\npackage machine\n\n// Digital Pins\nconst (\n\tGP0  Pin = GPIO0\n\tGP1  Pin = GPIO1\n\tGP2  Pin = GPIO2\n\tGP3  Pin = GPIO3\n\tGP4  Pin = GPIO4\n\tGP5  Pin = GPIO5\n\tGP6  Pin = GPIO6\n\tGP7  Pin = GPIO7\n\tGP8  Pin = GPIO8\n\tGP9  Pin = GPIO9\n\tGP10 Pin = GPIO10\n\tGP11 Pin = GPIO11\n\tGP12 Pin = GPIO12\n\tGP13 Pin = GPIO13\n\tGP14 Pin = GPIO14\n\tGP15 Pin = GPIO15\n\tGP16 Pin = GPIO16\n\tGP17 Pin = NoPin\n\tGP18 Pin = NoPin\n\tGP19 Pin = NoPin\n\tGP20 Pin = NoPin\n\tGP21 Pin = NoPin\n\tGP22 Pin = NoPin\n\tGP23 Pin = NoPin\n\tGP24 Pin = GPIO24\n\tGP25 Pin = GPIO25\n\tGP26 Pin = GPIO26\n\tGP27 Pin = GPIO27\n\tGP28 Pin = GPIO28\n\tGP29 Pin = GPIO29\n)\n\n// Analog pins\nconst (\n\tA0 Pin = GP26\n\tA1 Pin = GP27\n\tA2 Pin = GP28\n\tA3 Pin = GP29\n)\n\n// Onboard LEDs\nconst (\n\tLED    = GP16\n\tWS2812 = GP16\n)\n\n// I2C pins\nconst (\n\tI2C0_SDA_PIN Pin = GP0\n\tI2C0_SCL_PIN Pin = GP1\n\tI2C1_SDA_PIN Pin = GP2\n\tI2C1_SCL_PIN Pin = GP3\n\n\t// default I2C0\n\tI2C_SDA_PIN Pin = I2C0_SDA_PIN\n\tI2C_SCL_PIN Pin = I2C0_SCL_PIN\n)\n\n// SPI pins\nconst (\n\tSPI0_RX_PIN  Pin = GP0\n\tSPI0_CSN_PIN Pin = GP1\n\tSPI0_SCK_PIN Pin = GP2\n\tSPI0_TX_PIN  Pin = GP3\n\tSPI0_SDO_PIN Pin = SPI0_TX_PIN\n\tSPI0_SDI_PIN Pin = SPI0_RX_PIN\n\n\tSPI1_RX_PIN  Pin = GP8\n\tSPI1_CSN_PIN Pin = GP9\n\tSPI1_SCK_PIN Pin = GP10\n\tSPI1_TX_PIN  Pin = GP11\n\tSPI1_SDO_PIN Pin = SPI1_TX_PIN\n\tSPI1_SDI_PIN Pin = SPI1_RX_PIN\n\n\t// default SPI0\n\tSPI_RX_PIN  Pin = SPI0_RX_PIN\n\tSPI_CSN_PIN Pin = SPI0_CSN_PIN\n\tSPI_SCK_PIN Pin = SPI0_SCK_PIN\n\tSPI_TX_PIN  Pin = SPI0_TX_PIN\n\tSPI_SDO_PIN Pin = SPI0_TX_PIN\n\tSPI_SDI_PIN Pin = SPI0_RX_PIN\n)\n\n// Onboard crystal oscillator frequency, in MHz.\nconst (\n\txoscFreq = 12 // MHz\n)\n\n// UART pins\nconst (\n\tUART0_TX_PIN = GP0\n\tUART0_RX_PIN = GP1\n\tUART1_TX_PIN = GP8\n\tUART1_RX_PIN = GP9\n\n\t// default UART0\n\tUART_TX_PIN = UART0_TX_PIN\n\tUART_RX_PIN = UART0_RX_PIN\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"RP2040-Tiny\"\n\tusb_STRING_MANUFACTURER = \"Waveshare\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2e8a\n\tusb_PID uint16 = 0x0003\n)\n"
  },
  {
    "path": "src/machine/board_wioterminal.go",
    "content": "//go:build wioterminal\n\npackage machine\n\n// used to reset into bootloader\nconst resetMagicValue = 0xf01669ef\n\nconst (\n\tADC0 = A0\n\tADC1 = A1\n\tADC2 = A2\n\tADC3 = A3\n\tADC4 = A4\n\tADC5 = A5\n\tADC6 = A6\n\tADC7 = A7\n\tADC8 = A8\n\n\tLED    = PIN_LED\n\tBUTTON = BUTTON_1\n)\n\nconst (\n\t// https://github.com/Seeed-Studio/ArduinoCore-samd/blob/master/variants/wio_terminal/variant.h\n\n\t// LEDs\n\tPIN_LED_13   = PA15\n\tPIN_LED_RXL  = PA15\n\tPIN_LED_TXL  = PA15\n\tPIN_LED      = PIN_LED_13\n\tPIN_LED2     = PIN_LED_RXL\n\tPIN_LED3     = PIN_LED_TXL\n\tLED_BUILTIN  = PIN_LED_13\n\tPIN_NEOPIXEL = PA15\n\n\t//Digital PINs\n\tD0 = PB08\n\tD1 = PB09\n\tD2 = PA07\n\tD3 = PB04\n\tD4 = PB05\n\tD5 = PB06\n\tD6 = PA04\n\tD7 = PB07\n\tD8 = PA06\n\n\t//Analog PINs\n\tA0 = PB08 // ADC/AIN[0]\n\tA1 = PB09 // ADC/AIN[2]\n\tA2 = PA07 // ADC/AIN[3]\n\tA3 = PB04 // ADC/AIN[4]\n\tA4 = PB05 // ADC/AIN[5]\n\tA5 = PB06 // ADC/AIN[10]\n\tA6 = PA04 // ADC/AIN[10]\n\tA7 = PB07 // ADC/AIN[10]\n\tA8 = PA06 // ADC/AIN[10]\n\n\t// 3.3V    ||    5V\n\t// BCM2    ||    5V\n\t// BCM3    ||    GND\n\t// BCM4    ||    BCM14\n\t// GND     ||    BCM15\n\t// BCM17   ||    BCM18\n\t// BCM27   ||    GND\n\t// BCM22   ||    BCM23\n\t// GND     ||    BCM24\n\t// BCM10   ||    GND\n\t// BCM9    ||    BCM25\n\t// BCM11   ||    BCM8\n\t// GND     ||    BCM7\n\t// BCM0    ||    BCM1\n\t// BCM5    ||    GND\n\t// BCM6    ||    BCM12\n\t// BCM13   ||    GND\n\t// BCM19   ||    BCM16\n\t// BCM26   ||    BCM20\n\t// GND     ||    BCM21\n\n\t//PIN DEFINE FOR RPI\n\tBCM0  = PA13 // I2C Wire1\n\tBCM1  = PA12 // I2C Wire1\n\tBCM2  = PA17 // I2C Wire2\n\tBCM3  = PA16 // I2C Wire2\n\tBCM4  = PB14 // GCLK\n\tBCM5  = PB12 // GCLK\n\tBCM6  = PB13 // GCLK\n\tBCM7  = PA05 // DAC1\n\tBCM8  = PB01 // SPI SS\n\tBCM9  = PB00 // SPI SDI\n\tBCM10 = PB02 // SPI SDO\n\tBCM11 = PB03 // SPI SCK\n\tBCM12 = PB06\n\tBCM13 = PA04\n\tBCM14 = PB27 // UART Serial1\n\tBCM15 = PB26 // UART Serial1\n\tBCM16 = PB07\n\tBCM17 = PA02 // DAC0\n\tBCM18 = PB28 // FPC Digital & AD pins\n\tBCM19 = PA20 // WIO_IR\n\tBCM20 = PA21 // I2S SDO\n\tBCM21 = PA22 // I2S SDI\n\tBCM22 = PB09\n\tBCM23 = PA07\n\tBCM24 = PB04\n\tBCM25 = PB05\n\tBCM26 = PA06\n\tBCM27 = PB08\n\n\t// FPC NEW DEFINE\n\tFPC1  = PB28 // FPC Digital & AD pins\n\tFPC2  = PB17\n\tFPC3  = PB29\n\tFPC4  = PA14\n\tFPC5  = PC01\n\tFPC6  = PC02\n\tFPC7  = PC03\n\tFPC8  = PC04\n\tFPC9  = PC31\n\tFPC10 = PD00\n\n\t// RPI Analog RPIs\n\tRPI_A0 = PB08\n\tRPI_A1 = PB09\n\tRPI_A2 = PA07\n\tRPI_A3 = PB04\n\tRPI_A4 = PB05\n\tRPI_A5 = PB06\n\tRPI_A6 = PA04\n\tRPI_A7 = PB07\n\tRPI_A8 = PA06\n\n\tPIN_DAC0 = PA02\n\tPIN_DAC1 = PA05\n\n\t// FPO Analog RPIs\n\t//FPC_A7  = FPC_D7\n\t//FPC_A8  = FPC_D8\n\t//FPC_A9  = FPC_D9\n\t//FPC_A11 = FPC_D11\n\t//FPC_A12 = FPC_D12\n\t//FPC_A13 = FPC_D13\n\n\t// USB\n\tPIN_USB_DM          = PA24\n\tPIN_USB_DP          = PA25\n\tPIN_USB_HOST_ENABLE = PA27\n\n\t// BUTTON\n\tBUTTON_1  = PC26\n\tBUTTON_2  = PC27\n\tBUTTON_3  = PC28\n\tWIO_KEY_A = PC26\n\tWIO_KEY_B = PC27\n\tWIO_KEY_C = PC28\n\n\t// SWITCH\n\tSWITCH_X = PD20\n\tSWITCH_Y = PD12\n\tSWITCH_Z = PD09\n\tSWITCH_B = PD08\n\tSWITCH_U = PD10\n\n\tWIO_5S_UP    = PD20\n\tWIO_5S_LEFT  = PD12\n\tWIO_5S_RIGHT = PD09\n\tWIO_5S_DOWN  = PD08\n\tWIO_5S_PRESS = PD10\n\n\t// IRQ0 : RTL8720D\n\tIRQ0 = PC20\n\n\t// BUZZER_CTR\n\tBUZZER_CTR = PD11\n\tWIO_BUZZER = PD11\n\n\t// MIC_INPUT\n\tMIC_INPUT = PC30\n\tWIO_MIC   = PC30\n\n\t// GCLK\n\tGCLK0 = PB14\n\tGCLK1 = PB12\n\tGCLK2 = PB13\n\n\t// Serial interfaces\n\t// Serial1\n\tPIN_SERIAL1_RX = PB27\n\tPIN_SERIAL1_TX = PB26\n\n\t// Serial2 : RTL8720D\n\tPIN_SERIAL2_RX = PC23\n\tPIN_SERIAL2_TX = PC22\n\n\t// Wire Interfaces\n\t// I2C Wire2\n\t// I2C1\n\tPIN_WIRE_SDA = PA17\n\tPIN_WIRE_SCL = PA16\n\tSDA          = PIN_WIRE_SDA\n\tSCL          = PIN_WIRE_SCL\n\n\t// I2C Wire1\n\t// I2C0 : LIS3DHTR and ATECC608\n\tPIN_WIRE1_SDA = PA13\n\tPIN_WIRE1_SCL = PA12\n\n\tSDA1 = PIN_WIRE1_SDA\n\tSCL1 = PIN_WIRE1_SCL\n\n\tPIN_GYROSCOPE_WIRE_SDA = PIN_WIRE1_SDA\n\tPIN_GYROSCOPE_WIRE_SCL = PIN_WIRE1_SCL\n\tGYROSCOPE_INT1         = PC21\n\n\tWIO_LIS3DH_SDA = PIN_WIRE1_SDA\n\tWIO_LIS3DH_SCL = PIN_WIRE1_SCL\n\tWIO_LIS3DH_INT = PC21\n\n\t// SPI\n\tPIN_SPI_SDI = PB00\n\tPIN_SPI_SDO = PB02\n\tPIN_SPI_SCK = PB03\n\tPIN_SPI_SS  = PB01\n\n\tSS  = PIN_SPI_SS\n\tSDO = PIN_SPI_SDO\n\tSDI = PIN_SPI_SDI\n\tSCK = PIN_SPI_SCK\n\n\t// SPI1 RTL8720D_SPI\n\tPIN_SPI1_SDI = PC24\n\tPIN_SPI1_SDO = PB24\n\tPIN_SPI1_SCK = PB25\n\tPIN_SPI1_SS  = PC25\n\n\tSS1  = PIN_SPI1_SS\n\tSDO1 = PIN_SPI1_SDO\n\tSDI1 = PIN_SPI1_SDI\n\tSCK1 = PIN_SPI1_SCK\n\n\t// SPI2 SD_SPI\n\tPIN_SPI2_SDI = PC18\n\tPIN_SPI2_SDO = PC16\n\tPIN_SPI2_SCK = PC17\n\tPIN_SPI2_SS  = PC19\n\n\tSS2  = PIN_SPI2_SS\n\tSDO2 = PIN_SPI2_SDO\n\tSDI2 = PIN_SPI2_SDI\n\tSCK2 = PIN_SPI2_SCK\n\n\t// SPI3 LCD_SPI\n\tPIN_SPI3_SDI = PB18\n\tPIN_SPI3_SDO = PB19\n\tPIN_SPI3_SCK = PB20\n\tPIN_SPI3_SS  = PB21\n\n\tSS3  = PIN_SPI3_SS\n\tSDO3 = PIN_SPI3_SDO\n\tSDI3 = PIN_SPI3_SDI\n\tSCK3 = PIN_SPI3_SCK\n\n\t// Needed for SD library\n\tSDCARD_SDI_PIN = PIN_SPI2_SDI\n\tSDCARD_SDO_PIN = PIN_SPI2_SDO\n\tSDCARD_SCK_PIN = PIN_SPI2_SCK\n\tSDCARD_SS_PIN  = PIN_SPI2_SS\n\tSDCARD_DET_PIN = PD21\n\n\tLCD_SDI_PIN   = PIN_SPI3_SDI\n\tLCD_SDO_PIN   = PIN_SPI3_SDO\n\tLCD_SCK_PIN   = PIN_SPI3_SCK\n\tLCD_SS_PIN    = PIN_SPI3_SS\n\tLCD_DC        = PC06\n\tLCD_RESET     = PC07\n\tLCD_BACKLIGHT = PC05\n\n\t// 4 WIRE LCD TOUCH\n\tLCD_XL = PC10\n\tLCD_YU = PC11\n\tLCD_XR = PC12\n\tLCD_YD = PC13\n\n\t// Needed for RTL8720D\n\tRTL8720D_SDI_PIN = PIN_SPI1_SDI\n\tRTL8720D_SDO_PIN = PIN_SPI1_SDO\n\tRTL8720D_SCK_PIN = PIN_SPI1_SCK\n\tRTL8720D_SS_PIN  = PIN_SPI1_SS\n\n\t//QSPI Pins\n\tPIN_QSPI_IO0 = PA08\n\tPIN_QSPI_IO1 = PA09\n\tPIN_QSPI_IO2 = PA10\n\tPIN_QSPI_IO3 = PA11\n\tPIN_QSPI_SCK = PB10\n\tPIN_QSPI_CS  = PB11\n\n\t// I2S Interfaces\n\tPIN_I2S_FS  = PA20\n\tPIN_I2S_SCK = PB16\n\tPIN_I2S_SDO = PA22\n\tPIN_I2S_SDI = PA21\n\n\tI2S_LRCLK = PA20\n\tI2S_BLCK  = PB16\n\tI2S_SDOUT = PA22\n\tI2S_SDIN  = PA21\n\n\t// RTL8720D Interfaces\n\tRTL8720D_CHIP_PU = PA18\n\tRTL8720D_GPIO0   = PA19 // SYNC\n\n\t// SWD\n\tSWDCLK = PA30\n\tSWDIO  = PA31\n\tSWO    = PB30\n\n\t// light sensor\n\tWIO_LIGHT = PD01\n\n\t// ir sensor\n\tWIO_IR = PB31\n\n\t// OUTPUT_CTR\n\tOUTPUT_CTR_5V  = PC14\n\tOUTPUT_CTR_3V3 = PC15\n)\n\n// USBCDC pins\nconst (\n\tUSBCDC_DM_PIN = PIN_USB_DM\n\tUSBCDC_DP_PIN = PIN_USB_DP\n)\n\n// UART1 pins\nconst (\n\tUART_TX_PIN = PIN_SERIAL1_TX\n\tUART_RX_PIN = PIN_SERIAL1_RX\n)\n\n// UART2 pins RTL8720D\nconst (\n\tUART2_TX_PIN = PIN_SERIAL2_TX\n\tUART2_RX_PIN = PIN_SERIAL2_RX\n)\n\nvar (\n\tDefaultUART = UART1\n\n\tUART1 = &sercomUSART2\n\n\t// RTL8720D (tx: PC22, rx: PC23)\n\tUART2 = &sercomUSART1\n\n\t// RTL8720D (tx: PB24, rx: PC24)\n\tUART3 = &sercomUSART0\n\n\t// Right-hand grove port (tx: D0, rx: D1)\n\tUART4 = &sercomUSART4\n)\n\n// I2C pins\nconst (\n\tSDA1_PIN = PA17 // SDA: SERCOM3/PAD[0]\n\tSCL1_PIN = PA16 // SCL: SERCOM3/PAD[1]\n\n\tSDA0_PIN = PA13 // SDA: SERCOM4/PAD[0]\n\tSCL0_PIN = PA12 // SCL: SERCOM4/PAD[1]\n\n\tSDA_PIN = SDA1_PIN\n\tSCL_PIN = SCL1_PIN\n)\n\n// I2C on the Wio Terminal\nvar (\n\tI2C0 = sercomI2CM4\n\tI2C1 = sercomI2CM3\n)\n\n// I2S pins\nconst (\n\tI2S_SCK_PIN = BCM18\n\tI2S_SDO_PIN = BCM21\n\tI2S_SDI_PIN = BCM20\n\tI2S_WS_PIN  = BCM19\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = SCK // SCK:  SERCOM5/PAD[1]\n\tSPI0_SDO_PIN = SDO // SDO: SERCOM5/PAD[0]\n\tSPI0_SDI_PIN = SDI // SDI: SERCOM5/PAD[2]\n\n\t// RTL8720D\n\tSPI1_SCK_PIN = SCK1 // SCK:  SERCOM0/PAD[1]\n\tSPI1_SDO_PIN = SDO1 // SDO: SERCOM0/PAD[0]\n\tSPI1_SDI_PIN = SDI1 // SDI: SERCOM0/PAD[2]\n\n\t// SD\n\tSPI2_SCK_PIN = SCK2 // SCK:  SERCOM6/PAD[1]\n\tSPI2_SDO_PIN = SDO2 // SDO: SERCOM6/PAD[0]\n\tSPI2_SDI_PIN = SDI2 // SDI: SERCOM6/PAD[2]\n\n\t// LCD\n\tSPI3_SCK_PIN = SCK3 // SCK:  SERCOM7/PAD[1]\n\tSPI3_SDO_PIN = SDO3 // SDO: SERCOM7/PAD[3]\n\tSPI3_SDI_PIN = SDI3 // SDI: SERCOM7/PAD[2]\n)\n\n// SPI on the Wio Terminal\nvar (\n\tSPI0 = sercomSPIM5\n\n\t// RTL8720D\n\tSPI1 = sercomSPIM0\n\n\t// SD\n\tSPI2 = sercomSPIM6\n\n\t// LCD\n\tSPI3 = sercomSPIM7\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Seeed Wio Terminal\"\n\tusb_STRING_MANUFACTURER = \"Seeed\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2886\n\tusb_PID uint16 = 0x802D\n)\n"
  },
  {
    "path": "src/machine/board_x9pro.go",
    "content": "//go:build x9pro\n\npackage machine\n\n// https://hackaday.io/project/144350-hacking-wearables-for-mental-health-and-more/details\nconst (\n\tLED          Pin = 4 // HR LED pin\n\tUART_TX_PIN  Pin = NoPin\n\tUART_RX_PIN  Pin = NoPin\n\tSCL_PIN      Pin = NoPin\n\tSDA_PIN      Pin = NoPin\n\tSPI0_SCK_PIN Pin = 18\n\tSPI0_SDI_PIN Pin = 19\n\tSPI0_SDO_PIN Pin = 20\n)\n\n// LCD pins.\nconst (\n\tOLED_CS      Pin = 15 // chip select\n\tOLED_RES     Pin = 14 // reset pin\n\tOLED_DC      Pin = 13 // data/command\n\tOLED_SCK     Pin = 12 // SPI clock\n\tOLED_SDO     Pin = 11 // SPI SDO (chip-out, peripheral-in)\n\tOLED_LED_POW Pin = 16\n\tOLED_IC_POW  Pin = 17\n)\n\nconst HasLowFrequencyCrystal = true\n\nvar DefaultUART = UART0\n"
  },
  {
    "path": "src/machine/board_xiao-ble.go",
    "content": "//go:build xiao_ble\n\n// This file contains the pin mappings for the Seeed XIAO BLE nRF52840 [Sense] boards.\n//\n// Seeed XIAO BLE is an ultra-small size, ultra-low power Bluetooth development board based on the Nordic nRF52840.\n// It features an onboard Bluetooth antenna, onboard battery charging chip, and 21*17.5mm thumb size, which makes it ideal for IoT projects.\n//\n// Seeed XIAO BLE nRF52840 Sense is a tiny Bluetooth LE development board designed for IoT and AI applications.\n// It features an onboard antenna, 6 Dof IMU, microphone, all of which make it an ideal board to run AI using TinyML and TensorFlow Lite.\n//\n// SoftDevice (s140v7) is pre-flashed on this board already.\n// See https://github.com/tinygo-org/bluetooth\n//\n// - https://www.seeedstudio.com/Seeed-XIAO-BLE-nRF52840-p-5201.html\n// - https://www.seeedstudio.com/Seeed-XIAO-BLE-Sense-nRF52840-p-5253.html\n//\n// - https://wiki.seeedstudio.com/XIAO_BLE/\n// - https://github.com/Seeed-Studio/ArduinoCore-mbed/tree/master/variants/SEEED_XIAO_NRF52840_SENSE\npackage machine\n\nconst HasLowFrequencyCrystal = true\n\n// Digital Pins\nconst (\n\tD0  Pin = P0_02\n\tD1  Pin = P0_03\n\tD2  Pin = P0_28\n\tD3  Pin = P0_29\n\tD4  Pin = P0_04\n\tD5  Pin = P0_05\n\tD6  Pin = P1_11\n\tD7  Pin = P1_12\n\tD8  Pin = P1_13\n\tD9  Pin = P1_14\n\tD10 Pin = P1_15\n)\n\n// Analog pins\nconst (\n\tA0 Pin = P0_02\n\tA1 Pin = P0_03\n\tA2 Pin = P0_28\n\tA3 Pin = P0_29\n\tA4 Pin = P0_04\n\tA5 Pin = P0_05\n)\n\n// Onboard LEDs\nconst (\n\tLED       = LED_CHG\n\tLED1      = LED_RED\n\tLED2      = LED_GREEN\n\tLED3      = LED_BLUE\n\tLED_CHG   = P0_17\n\tLED_RED   = P0_26\n\tLED_GREEN = P0_30\n\tLED_BLUE  = P0_06\n)\n\n// UART0 pins\nconst (\n\tUART_RX_PIN = P1_12\n\tUART_TX_PIN = P1_11\n)\n\n// I2C pins\nconst (\n\t// Defaults to internal\n\tSDA_PIN = SDA1_PIN\n\tSCL_PIN = SCL1_PIN\n\n\t// I2C0 (external) pins\n\tSDA0_PIN = P0_04\n\tSCL0_PIN = P0_05\n\n\t// I2C1 (internal) pins\n\tSDA1_PIN = P0_07\n\tSCL1_PIN = P0_27\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = P1_13\n\tSPI0_SDO_PIN = P1_14\n\tSPI0_SDI_PIN = P1_15\n)\n\n// Peripherals\nconst (\n\tLSM_PWR = P1_08 // IMU (LSM6DS3TR) power\n\tLSM_INT = P0_11 // IMU (LSM6DS3TR) interrupt\n\n\tMIC_PWR = P1_10 // Microphone (MSM261D3526H1CPM) power\n\tMIC_CLK = P1_00\n\tMIC_DIN = P0_16\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"XIAO nRF52840 Sense\"\n\tusb_STRING_MANUFACTURER = \"Seeed\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2886\n\tusb_PID uint16 = 0x8045\n)\n\nvar (\n\tDefaultUART = UART0\n)\n"
  },
  {
    "path": "src/machine/board_xiao-esp32c3.go",
    "content": "//go:build xiao_esp32c3\n\n// This file contains the pin mappings for the Seeed XIAO ESP32C3 boards.\n//\n// Seeed Studio XIAO ESP32C3 is an IoT mini development board based on\n// the Espressif ESP32-C3 WiFi/Bluetooth dual-mode chip.\n//\n// - https://www.seeedstudio.com/Seeed-XIAO-ESP32C3-p-5431.html\n// - https://wiki.seeedstudio.com/XIAO_ESP32C3_Getting_Started/\n\npackage machine\n\n// Digital Pins\nconst (\n\tD0  = GPIO2\n\tD1  = GPIO3\n\tD2  = GPIO4\n\tD3  = GPIO5\n\tD4  = GPIO6\n\tD5  = GPIO7\n\tD6  = GPIO21\n\tD7  = GPIO20\n\tD8  = GPIO8\n\tD9  = GPIO9\n\tD10 = GPIO10\n)\n\n// Analog pins\nconst (\n\tA0 = GPIO2\n\tA1 = GPIO3\n\tA2 = GPIO4\n\tA3 = GPIO5\n)\n\n// UART pins\nconst (\n\tUART_RX_PIN = GPIO20\n\tUART_TX_PIN = GPIO21\n)\n\n// I2C pins\nconst (\n\tSDA_PIN = GPIO6\n\tSCL_PIN = GPIO7\n)\n\n// SPI pins\nconst (\n\tSPI_SCK_PIN = GPIO8\n\tSPI_SDI_PIN = GPIO9\n\tSPI_SDO_PIN = GPIO10\n)\n"
  },
  {
    "path": "src/machine/board_xiao-esp32s3.go",
    "content": "//go:build xiao_esp32s3\n\n// This file contains the pin mappings for the Seeed XIAO ESP32S3 boards.\n//\n// Seeed Studio XIAO ESP32S3 is an IoT mini development board based on\n// the Espressif ESP32-S3 WiFi/Bluetooth dual-mode chip.\n//\n// - https://www.seeedstudio.com/XIAO-ESP32S3-p-5627.html\n// - https://wiki.seeedstudio.com/xiao_esp32s3_getting_started/\n\npackage machine\n\n// Digital Pins\nconst (\n\tD0  = GPIO1\n\tD1  = GPIO2\n\tD2  = GPIO3\n\tD3  = GPIO4\n\tD4  = GPIO5\n\tD5  = GPIO6\n\tD6  = GPIO43\n\tD7  = GPIO44\n\tD8  = GPIO7\n\tD9  = GPIO8\n\tD10 = GPIO9\n)\n\n// Analog pins\nconst (\n\tA0 = GPIO1\n\tA1 = GPIO2\n\tA2 = GPIO3\n\tA3 = GPIO4\n)\n\n// UART pins\nconst (\n\tUART_RX_PIN = GPIO44\n\tUART_TX_PIN = GPIO43\n)\n\n// I2C pins\nconst (\n\tSDA_PIN = GPIO5\n\tSCL_PIN = GPIO6\n)\n\n// SPI pins\nconst (\n\tSPI_SCK_PIN = GPIO7\n\tSPI_SDI_PIN = GPIO9\n\tSPI_SDO_PIN = GPIO8\n)\n\n// Onboard LEDs\nconst (\n\tLED = GPIO21\n)\n"
  },
  {
    "path": "src/machine/board_xiao-rp2040.go",
    "content": "//go:build xiao_rp2040\n\n// This file contains the pin mappings for the Seeed XIAO RP2040 boards.\n//\n// XIAO RP2040 is a microcontroller using the Raspberry Pi RP2040 chip.\n//\n// - https://wiki.seeedstudio.com/XIAO-RP2040/\npackage machine\n\n// Digital Pins\nconst (\n\tD0  Pin = GPIO26\n\tD1  Pin = GPIO27\n\tD2  Pin = GPIO28\n\tD3  Pin = GPIO29\n\tD4  Pin = GPIO6\n\tD5  Pin = GPIO7\n\tD6  Pin = GPIO0\n\tD7  Pin = GPIO1\n\tD8  Pin = GPIO2\n\tD9  Pin = GPIO4\n\tD10 Pin = GPIO3\n)\n\n// Analog pins\nconst (\n\tA0 Pin = D0\n\tA1 Pin = D1\n\tA2 Pin = D2\n\tA3 Pin = D3\n)\n\n// Onboard LEDs\nconst (\n\tNEOPIXEL       = GPIO12\n\tWS2812         = GPIO12\n\tNEO_PWR        = GPIO11\n\tNEOPIXEL_POWER = GPIO11\n\n\tLED       = GPIO17\n\tLED_RED   = GPIO17\n\tLED_GREEN = GPIO16\n\tLED_BLUE  = GPIO25\n)\n\n// I2C pins\nconst (\n\tI2C0_SDA_PIN Pin = D2\n\tI2C0_SCL_PIN Pin = D3\n\n\tI2C1_SDA_PIN Pin = D4\n\tI2C1_SCL_PIN Pin = D5\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN Pin = D8\n\tSPI0_SDO_PIN Pin = D10\n\tSPI0_SDI_PIN Pin = D9\n\n\tSPI1_SCK_PIN Pin = NoPin\n\tSPI1_SDO_PIN Pin = NoPin\n\tSPI1_SDI_PIN Pin = NoPin\n)\n\n// Onboard crystal oscillator frequency, in MHz.\nconst (\n\txoscFreq = 12 // MHz\n)\n\n// UART pins\nconst (\n\tUART0_TX_PIN = GPIO0\n\tUART0_RX_PIN = GPIO1\n\tUART_TX_PIN  = UART0_TX_PIN\n\tUART_RX_PIN  = UART0_RX_PIN\n)\n\nvar DefaultUART = UART0\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"XIAO RP2040\"\n\tusb_STRING_MANUFACTURER = \"Seeed\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2e8a\n\tusb_PID uint16 = 0x000a\n)\n"
  },
  {
    "path": "src/machine/board_xiao.go",
    "content": "//go:build sam && atsamd21 && xiao\n\npackage machine\n\n// used to reset into bootloader\nconst resetMagicValue = 0xf01669ef\n\n// GPIO Pins\nconst (\n\tD0  = PA02 // can be used for PWM or DAC\n\tD1  = PA04 // PWM available\n\tD2  = PA10 // PWM available\n\tD3  = PA11 // PWM available\n\tD4  = PA08 // can be used for PWM or I2C SDA\n\tD5  = PA09 // can be used for PWM or I2C SCL\n\tD6  = PB08 // can be used for PWM or UART1 TX\n\tD7  = PB09 // can be used for PWM or UART1 RX\n\tD8  = PA07 // can be used for PWM or SPI SCK\n\tD9  = PA05 // can be used for PWM or SPI SDI\n\tD10 = PA06 // can be used for PWM or SPI SDO\n)\n\n// Analog pins\nconst (\n\tA0  = PA02 // ADC/AIN[0]\n\tA1  = PA04 // ADC/AIN[4]\n\tA2  = PA10 // ADC/AIN[18]\n\tA3  = PA11 // ADC/AIN[19]\n\tA4  = PA08 // ADC/AIN[16]\n\tA5  = PA09 // ADC/AIN[17]\n\tA6  = PB08 // ADC/AIN[2]\n\tA7  = PB09 // ADC/AIN[3]\n\tA8  = PA07 // ADC/AIN[7]\n\tA9  = PA05 // ADC/AIN[6]\n\tA10 = PA06 // ADC/AIN[5]\n)\n\nconst (\n\tLED     = PA17\n\tLED_RXL = PA18\n\tLED_TXL = PA19\n\tLED2    = LED_RXL\n\tLED3    = LED_TXL\n)\n\n// USBCDC pins\nconst (\n\tUSBCDC_DM_PIN = PA24\n\tUSBCDC_DP_PIN = PA25\n)\n\n// UART1 pins\nconst (\n\tUART_TX_PIN = D6\n\tUART_RX_PIN = D7\n)\n\n// UART1 on the Xiao\nvar UART1 = &sercomUSART4\n\n// I2C pins\nconst (\n\tSDA_PIN = PA08 // SDA: SERCOM2/PAD[0]\n\tSCL_PIN = PA09 // SCL: SERCOM2/PAD[1]\n)\n\n// I2C on the Xiao\nvar (\n\tI2C0 = sercomI2CM2\n)\n\n// SPI pins\nconst (\n\tSPI0_SCK_PIN = PA07 // SCK: SERCOM0/PAD[3]\n\tSPI0_SDO_PIN = PA06 // SDO: SERCOM0/PAD[2]\n\tSPI0_SDI_PIN = PA05 // SDI: SERCOM0/PAD[1]\n)\n\n// SPI on the Xiao\nvar SPI0 = sercomSPIM0\n\n// I2S pins\nconst (\n\tI2S_SCK_PIN = PA10\n\tI2S_SDO_PIN = PA08\n\tI2S_SDI_PIN = NoPin // TODO: figure out what this is on Xiao\n\tI2S_WS_PIN  = NoPin // TODO: figure out what this is on Xiao\n)\n\n// USB CDC identifiers\nconst (\n\tusb_STRING_PRODUCT      = \"Seeed XIAO M0\"\n\tusb_STRING_MANUFACTURER = \"Seeed\"\n)\n\nvar (\n\tusb_VID uint16 = 0x2886\n\tusb_PID uint16 = 0x802F\n)\n\nvar (\n\tDefaultUART = UART1\n)\n"
  },
  {
    "path": "src/machine/buffer.go",
    "content": "package machine\n\nimport (\n\t\"runtime/volatile\"\n)\n\n// RingBuffer is ring buffer implementation inspired by post at\n// https://www.embeddedrelated.com/showthread/comp.arch.embedded/77084-1.php\ntype RingBuffer struct {\n\trxbuffer [bufferSize]volatile.Register8\n\thead     volatile.Register8\n\ttail     volatile.Register8\n}\n\n// NewRingBuffer returns a new ring buffer.\nfunc NewRingBuffer() *RingBuffer {\n\treturn &RingBuffer{}\n}\n\n// Used returns how many bytes in buffer have been used.\nfunc (rb *RingBuffer) Used() uint8 {\n\treturn uint8(rb.head.Get() - rb.tail.Get())\n}\n\n// Put stores a byte in the buffer. If the buffer is already\n// full, the method will return false.\nfunc (rb *RingBuffer) Put(val byte) bool {\n\tif rb.Used() != bufferSize {\n\t\trb.head.Set(rb.head.Get() + 1)\n\t\trb.rxbuffer[rb.head.Get()%bufferSize].Set(val)\n\t\treturn true\n\t}\n\treturn false\n}\n\n// Get returns a byte from the buffer. If the buffer is empty,\n// the method will return a false as the second value.\nfunc (rb *RingBuffer) Get() (byte, bool) {\n\tif rb.Used() != 0 {\n\t\trb.tail.Set(rb.tail.Get() + 1)\n\t\treturn rb.rxbuffer[rb.tail.Get()%bufferSize].Get(), true\n\t}\n\treturn 0, false\n}\n\n// Clear resets the head and tail pointer to zero.\nfunc (rb *RingBuffer) Clear() {\n\trb.head.Set(0)\n\trb.tail.Set(0)\n}\n"
  },
  {
    "path": "src/machine/buffer_atmega.go",
    "content": "//go:build atmega\n\npackage machine\n\nconst bufferSize = 32\n"
  },
  {
    "path": "src/machine/buffer_generic.go",
    "content": "//go:build !atmega\n\npackage machine\n\nconst bufferSize = 128\n"
  },
  {
    "path": "src/machine/deviceid.go",
    "content": "//go:build rp2040 || nrf || sam\n\npackage machine\n\n// DeviceID returns an identifier that is unique within\n// a particular chipset.\n//\n// The identity is one burnt into the MCU itself, or the\n// flash chip at time of manufacture.\n//\n// It's possible that two different vendors may allocate\n// the same DeviceID, so callers should take this into\n// account if needing to generate a globally unique id.\n//\n// The length of the hardware ID is vendor-specific, but\n// 8 bytes (64 bits) and 16 bytes (128 bits) are common.\nvar _ = (func() []byte)(DeviceID)\n"
  },
  {
    "path": "src/machine/flash.go",
    "content": "//go:build nrf || nrf51 || nrf52 || nrf528xx || stm32f4 || stm32l4 || stm32wlx || atsamd21 || atsamd51 || atsame5x || rp2040 || rp2350\n\npackage machine\n\nimport (\n\t\"errors\"\n\t\"io\"\n\t\"unsafe\"\n)\n\n//go:extern __flash_data_start\nvar flashDataStart [0]byte\n\n//go:extern __flash_data_end\nvar flashDataEnd [0]byte\n\n// Return the start of the writable flash area, aligned on a page boundary. This\n// is usually just after the program and static data.\nfunc FlashDataStart() uintptr {\n\tpagesize := uintptr(eraseBlockSize())\n\treturn (uintptr(unsafe.Pointer(&flashDataStart)) + pagesize - 1) &^ (pagesize - 1)\n}\n\n// Return the end of the writable flash area. Usually this is the address one\n// past the end of the on-chip flash.\nfunc FlashDataEnd() uintptr {\n\treturn uintptr(unsafe.Pointer(&flashDataEnd))\n}\n\nvar (\n\terrFlashCannotErasePage     = errors.New(\"cannot erase flash page\")\n\terrFlashInvalidWriteLength  = errors.New(\"write flash data must align to correct number of bits\")\n\terrFlashNotAllowedWriteData = errors.New(\"not allowed to write flash data\")\n\terrFlashCannotWriteData     = errors.New(\"cannot write flash data\")\n\terrFlashCannotReadPastEOF   = errors.New(\"cannot read beyond end of flash data\")\n\terrFlashCannotWritePastEOF  = errors.New(\"cannot write beyond end of flash data\")\n\terrFlashCannotErasePastEOF  = errors.New(\"cannot erase beyond end of flash data\")\n)\n\n// BlockDevice is the raw device that is meant to store flash data.\ntype BlockDevice interface {\n\t// ReadAt reads the given number of bytes from the block device.\n\tio.ReaderAt\n\n\t// WriteAt writes the given number of bytes to the block device.\n\t//\n\t// This interface directly writes data to the underlying block device.\n\t// Different kinds of devices have different requirements: most can only\n\t// write data after the page has been erased, and many can only write data\n\t// with specific alignment (such as 4-byte alignment).\n\tio.WriterAt\n\n\t// Size returns the number of bytes in this block device.\n\tSize() int64\n\n\t// WriteBlockSize returns the block size in which data can be written to\n\t// memory. It can be used by a client to optimize writes, non-aligned writes\n\t// should always work correctly.\n\tWriteBlockSize() int64\n\n\t// EraseBlockSize returns the smallest erasable area on this particular chip\n\t// in bytes. This is used for the block size in EraseBlocks.\n\t// It must be a power of two, and may be as small as 1. A typical size is 4096.\n\tEraseBlockSize() int64\n\n\t// EraseBlocks erases the given number of blocks. An implementation may\n\t// transparently coalesce ranges of blocks into larger bundles if the chip\n\t// supports this. The start and len parameters are in block numbers, use\n\t// EraseBlockSize to map addresses to blocks.\n\tEraseBlocks(start, len int64) error\n}\n\n// pad data if needed so it is long enough for correct byte alignment on writes.\nfunc flashPad(p []byte, writeBlockSize int) []byte {\n\toverflow := len(p) % writeBlockSize\n\tif overflow != 0 {\n\t\tfor i := 0; i < writeBlockSize-overflow; i++ {\n\t\t\tp = append(p, 0xff)\n\t\t}\n\t}\n\treturn p\n}\n"
  },
  {
    "path": "src/machine/i2c.go",
    "content": "//go:build !baremetal || atmega || nrf || sam || stm32 || fe310 || k210 || rp2040 || rp2350 || mimxrt1062 || (esp32c3 && !m5stamp_c3) || esp32\n\npackage machine\n\nimport (\n\t\"errors\"\n)\n\n// If you are getting a compile error on this line please check to see you've\n// correctly implemented the methods on the I2C type. They must match\n// the i2cController interface method signatures type to type perfectly.\n// If not implementing the I2C type please remove your target from the build tags\n// at the top of this file.\nvar _ interface { // 2\n\tConfigure(config I2CConfig) error\n\tTx(addr uint16, w, r []byte) error\n\tSetBaudRate(br uint32) error\n} = (*I2C)(nil)\n\n// TWI_FREQ is the I2C bus speed. Normally either 100 kHz, or 400 kHz for high-speed bus.\n//\n// Deprecated: use 100 * machine.KHz or 400 * machine.KHz instead.\nconst (\n\tTWI_FREQ_100KHZ = 100000\n\tTWI_FREQ_400KHZ = 400000\n)\n\nvar (\n\terrI2CWriteTimeout       = errors.New(\"i2c: timeout during write\")\n\terrI2CReadTimeout        = errors.New(\"i2c: timeout during read\")\n\terrI2CBusReadyTimeout    = errors.New(\"i2c: timeout on bus ready\")\n\terrI2CSignalStartTimeout = errors.New(\"i2c: timeout on signal start\")\n\terrI2CSignalReadTimeout  = errors.New(\"i2c: timeout on signal read\")\n\terrI2CSignalStopTimeout  = errors.New(\"i2c: timeout on signal stop\")\n\terrI2CAckExpected        = errors.New(\"i2c: error: expected ACK not NACK\")\n\terrI2CBusError           = errors.New(\"i2c: bus error\")\n\terrI2COverflow           = errors.New(\"i2c: receive buffer overflow\")\n\terrI2COverread           = errors.New(\"i2c: transmit buffer overflow\")\n\terrI2CNotImplemented     = errors.New(\"i2c: operation not yet implemented\")\n\terrI2CNoDevices          = errors.New(\"i2c: bus has no devices\")                         // simulator only\n\terrI2CMultipleDevices    = errors.New(\"i2c: bus has address conflict\")                   // simulator only\n\terrI2CWrongAddress       = errors.New(\"i2c: bus has devices but none with this address\") // simulator only\n)\n\n// I2CTargetEvent reflects events on the I2C bus\ntype I2CTargetEvent uint8\n\nconst (\n\t// I2CReceive indicates target has received a message from the controller.\n\tI2CReceive I2CTargetEvent = iota\n\n\t// I2CRequest indicates the controller is expecting a message from the target.\n\tI2CRequest\n\n\t// I2CFinish indicates the controller has ended the transaction.\n\t//\n\t// I2C controllers can chain multiple receive/request messages without\n\t// relinquishing the bus by doing 'restarts'.  I2CFinish indicates the\n\t// bus has been relinquished by an I2C 'stop'.\n\tI2CFinish\n)\n\n// I2CMode determines if an I2C peripheral is in Controller or Target mode.\ntype I2CMode int\n\nconst (\n\t// I2CModeController represents an I2C peripheral in controller mode.\n\tI2CModeController I2CMode = iota\n\n\t// I2CModeTarget represents an I2C peripheral in target mode.\n\tI2CModeTarget\n)\n\n// WriteRegister transmits first the register and then the data to the\n// peripheral device.\n//\n// Many I2C-compatible devices are organized in terms of registers. This method\n// is a shortcut to easily write to such registers. Also, it only works for\n// devices with 7-bit addresses, which is the vast majority.\nfunc (i2c *I2C) WriteRegister(address uint8, register uint8, data []byte) error {\n\tbuf := make([]uint8, len(data)+1)\n\tbuf[0] = register\n\tcopy(buf[1:], data)\n\treturn i2c.Tx(uint16(address), buf, nil)\n}\n\n// ReadRegister transmits the register, restarts the connection as a read\n// operation, and reads the response.\n//\n// Many I2C-compatible devices are organized in terms of registers. This method\n// is a shortcut to easily read such registers. Also, it only works for devices\n// with 7-bit addresses, which is the vast majority.\nfunc (i2c *I2C) ReadRegister(address uint8, register uint8, data []byte) error {\n\treturn i2c.Tx(uint16(address), []byte{register}, data)\n}\n"
  },
  {
    "path": "src/machine/i2s.go",
    "content": "//go:build sam && atsamd21\n\n// This is the definition for I2S bus functions.\n// Actual implementations if available for any given hardware\n// are to be found in its the board definition.\n//\n// For more info about I2S, see: https://en.wikipedia.org/wiki/I%C2%B2S\n//\n\npackage machine\n\nimport \"errors\"\n\n// If you are getting a compile error on this line please check to see you've\n// correctly implemented the methods on the I2S type. They must match\n// the interface method signatures type to type perfectly.\n// If not implementing the I2S type please remove your target from the build tags\n// at the top of this file.\nvar _ interface {\n\tSetSampleFrequency(freq uint32) error\n\tReadMono(b []uint16) (int, error)\n\tReadStereo(b []uint32) (int, error)\n\tWriteMono(b []uint16) (int, error)\n\tWriteStereo(b []uint32) (int, error)\n\tEnable(enabled bool)\n} = (*I2S)(nil)\n\ntype I2SMode uint8\ntype I2SStandard uint8\ntype I2SClockSource uint8\ntype I2SDataFormat uint8\n\nconst (\n\tI2SModeSource I2SMode = iota\n\tI2SModeReceiver\n\tI2SModePDM\n\tI2SModeSourceReceiver\n)\n\nconst (\n\tI2StandardPhilips I2SStandard = iota\n\tI2SStandardMSB\n\tI2SStandardLSB\n)\n\nconst (\n\tI2SClockSourceInternal I2SClockSource = iota\n\tI2SClockSourceExternal\n)\n\nconst (\n\tI2SDataFormatDefault I2SDataFormat = 0\n\tI2SDataFormat8bit                  = 8\n\tI2SDataFormat16bit                 = 16\n\tI2SDataFormat24bit                 = 24\n\tI2SDataFormat32bit                 = 32\n)\n\nvar (\n\tErrInvalidSampleFrequency = errors.New(\"i2s: invalid sample frequency\")\n)\n\n// All fields are optional and may not be required or used on a particular platform.\ntype I2SConfig struct {\n\t// clock\n\tSCK Pin\n\t// word select\n\tWS Pin\n\t// data out\n\tSDO Pin\n\t// data in\n\tSDI             Pin\n\tMode            I2SMode\n\tStandard        I2SStandard\n\tClockSource     I2SClockSource\n\tDataFormat      I2SDataFormat\n\tAudioFrequency  uint32\n\tMainClockOutput bool\n\tStereo          bool\n}\n"
  },
  {
    "path": "src/machine/machine.go",
    "content": "package machine\n\nimport (\n\t\"errors\"\n\t\"unsafe\"\n)\n\nvar (\n\tErrTimeoutRNG         = errors.New(\"machine: RNG Timeout\")\n\tErrClockRNG           = errors.New(\"machine: RNG Clock Error\")\n\tErrSeedRNG            = errors.New(\"machine: RNG Seed Error\")\n\tErrInvalidInputPin    = errors.New(\"machine: invalid input pin\")\n\tErrInvalidOutputPin   = errors.New(\"machine: invalid output pin\")\n\tErrInvalidClockPin    = errors.New(\"machine: invalid clock pin\")\n\tErrInvalidDataPin     = errors.New(\"machine: invalid data pin\")\n\tErrNoPinChangeChannel = errors.New(\"machine: no channel available for pin interrupt\")\n)\n\n// Device is the running program's chip name, such as \"ATSAMD51J19A\" or\n// \"nrf52840\". It is not the same as the CPU name.\n//\n// The constant is some hardcoded default value if the program does not target a\n// particular chip but instead runs in WebAssembly for example.\nconst Device = deviceName\n\n// Generic constants.\nconst (\n\tKHz = 1000\n\tMHz = 1000_000\n\tGHz = 1000_000_000\n)\n\n// PinMode sets the direction and pull mode of the pin. For example, PinOutput\n// sets the pin as an output and PinInputPullup sets the pin as an input with a\n// pull-up.\ntype PinMode uint8\n\ntype PinConfig struct {\n\tMode PinMode\n}\n\n// Pin is a single pin on a chip, which may be connected to other hardware\n// devices. It can either be used directly as GPIO pin or it can be used in\n// other peripherals like ADC, I2C, etc.\ntype Pin uint8\n\n// NoPin explicitly indicates \"not a pin\". Use this pin if you want to leave one\n// of the pins in a peripheral unconfigured (if supported by the hardware).\nconst NoPin = Pin(0xff)\n\n// High sets this GPIO pin to high, assuming it has been configured as an output\n// pin. It is hardware dependent (and often undefined) what happens if you set a\n// pin to high that is not configured as an output pin.\nfunc (p Pin) High() {\n\tp.Set(true)\n}\n\n// Low sets this GPIO pin to low, assuming it has been configured as an output\n// pin. It is hardware dependent (and often undefined) what happens if you set a\n// pin to low that is not configured as an output pin.\nfunc (p Pin) Low() {\n\tp.Set(false)\n}\n\ntype ADC struct {\n\tPin Pin\n}\n\n// Convert the pointer to a uintptr, to be used for memory I/O (DMA for\n// example). It also means the pointer is \"gone\" as far as the compiler is\n// concerned, and a GC cycle might deallocate the object. To prevent this from\n// happening, also call keepAliveNoEscape at a point after the address isn't\n// accessed anymore by the hardware.\n// The only exception is if the pointer is accessed later in a volatile way\n// (volatile read/write), which also forces the value to stay alive until that\n// point.\n//\n// This function is treated specially by the compiler to mark the 'ptr'\n// parameter as not escaping.\n//\n// TODO: this function should eventually be replaced with the proposed ptrtoaddr\n// instruction in LLVM. See:\n// https://discourse.llvm.org/t/clarifiying-the-semantics-of-ptrtoint/83987/10\n// https://github.com/llvm/llvm-project/pull/139357\nfunc unsafeNoEscape(ptr unsafe.Pointer) uintptr {\n\treturn uintptr(ptr)\n}\n\n// Make sure the given pointer stays alive until this point. This is similar to\n// runtime.KeepAlive, with the difference that it won't let the pointer escape.\n// This is typically used together with unsafeNoEscape.\n//\n// This is a compiler intrinsic.\nfunc keepAliveNoEscape(ptr unsafe.Pointer)\n"
  },
  {
    "path": "src/machine/machine_atmega.go",
    "content": "//go:build avr && atmega\n\npackage machine\n\nimport (\n\t\"device/avr\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\n// I2C on AVR.\ntype I2C struct {\n\tsrReg *volatile.Register8\n\tbrReg *volatile.Register8\n\tcrReg *volatile.Register8\n\tdrReg *volatile.Register8\n\n\tsrPS0 byte\n\tsrPS1 byte\n\tcrEN  byte\n\tcrINT byte\n\tcrSTO byte\n\tcrEA  byte\n\tcrSTA byte\n}\n\n// I2CConfig is used to store config info for I2C.\ntype I2CConfig struct {\n\tFrequency uint32\n}\n\n// Configure is intended to setup the I2C interface.\nfunc (i2c *I2C) Configure(config I2CConfig) error {\n\t// Default I2C bus speed is 100 kHz.\n\tif config.Frequency == 0 {\n\t\tconfig.Frequency = 100 * KHz\n\t}\n\n\t// Activate internal pullups for twi.\n\tavr.PORTC.SetBits((avr.DIDR0_ADC4D | avr.DIDR0_ADC5D))\n\n\treturn i2c.SetBaudRate(config.Frequency)\n}\n\n// SetBaudRate sets the communication speed for I2C.\nfunc (i2c *I2C) SetBaudRate(br uint32) error {\n\t// Initialize twi prescaler and bit rate.\n\ti2c.srReg.SetBits((i2c.srPS0 | i2c.srPS1))\n\n\t// twi bit rate formula from atmega128 manual pg. 204:\n\t// SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR))\n\t// NOTE: TWBR should be 10 or higher for controller mode.\n\t// It is 72 for a 16mhz board with 100kHz TWI\n\ti2c.brReg.Set(uint8(((CPUFrequency() / br) - 16) / 2))\n\n\t// Enable twi module.\n\ti2c.crReg.Set(i2c.crEN)\n\n\treturn nil\n}\n\n// Tx does a single I2C transaction at the specified address.\n// It clocks out the given address, writes the bytes in w, reads back len(r)\n// bytes and stores them in r, and generates a stop condition on the bus.\nfunc (i2c *I2C) Tx(addr uint16, w, r []byte) error {\n\tif len(w) != 0 {\n\t\ti2c.start(uint8(addr), true) // start transmission for writing\n\t\tfor _, b := range w {\n\t\t\ti2c.writeByte(b)\n\t\t}\n\t}\n\tif len(r) != 0 {\n\t\ti2c.start(uint8(addr), false) // re-start transmission for reading\n\t\tfor i := range r {            // read each char\n\t\t\tr[i] = i2c.readByte()\n\t\t}\n\t}\n\tif len(w) != 0 || len(r) != 0 {\n\t\t// Stop the transmission after it has been started.\n\t\ti2c.stop()\n\t}\n\treturn nil\n}\n\n// start starts an I2C communication session.\nfunc (i2c *I2C) start(address uint8, write bool) {\n\t// Clear TWI interrupt flag, put start condition on SDA, and enable TWI.\n\ti2c.crReg.Set((i2c.crINT | i2c.crSTA | i2c.crEN))\n\n\t// Wait till start condition is transmitted.\n\tfor !i2c.crReg.HasBits(i2c.crINT) {\n\t}\n\n\t// Write 7-bit shifted peripheral address.\n\taddress <<= 1\n\tif !write {\n\t\taddress |= 1 // set read flag\n\t}\n\ti2c.writeByte(address)\n}\n\n// stop ends an I2C communication session.\nfunc (i2c *I2C) stop() {\n\t// Send stop condition.\n\ti2c.crReg.Set(i2c.crEN | i2c.crINT | i2c.crSTO)\n\n\t// Wait for stop condition to be executed on bus.\n\tfor !i2c.crReg.HasBits(i2c.crSTO) {\n\t}\n}\n\n// writeByte writes a single byte to the I2C bus.\nfunc (i2c *I2C) writeByte(data byte) error {\n\t// Write data to register.\n\ti2c.drReg.Set(data)\n\n\t// Clear TWI interrupt flag and enable TWI.\n\ti2c.crReg.Set(i2c.crEN | i2c.crINT)\n\n\t// Wait till data is transmitted.\n\tfor !i2c.crReg.HasBits(i2c.crINT) {\n\t}\n\treturn nil\n}\n\n// readByte reads a single byte from the I2C bus.\nfunc (i2c *I2C) readByte() byte {\n\t// Clear TWI interrupt flag and enable TWI.\n\ti2c.crReg.Set(i2c.crEN | i2c.crINT | i2c.crEA)\n\n\t// Wait till read request is transmitted.\n\tfor !i2c.crReg.HasBits(i2c.crINT) {\n\t}\n\n\treturn byte(i2c.drReg.Get())\n}\n\n// Always use UART0 as the serial output.\nvar DefaultUART = UART0\n\n// UART\nvar (\n\t// UART0 is the hardware serial port on the AVR.\n\tUART0  = &_UART0\n\t_UART0 = UART{\n\t\tBuffer: NewRingBuffer(),\n\n\t\tdataReg:    avr.UDR0,\n\t\tbaudRegH:   avr.UBRR0H,\n\t\tbaudRegL:   avr.UBRR0L,\n\t\tstatusRegA: avr.UCSR0A,\n\t\tstatusRegB: avr.UCSR0B,\n\t\tstatusRegC: avr.UCSR0C,\n\t}\n)\n\nfunc init() {\n\t// Register the UART interrupt.\n\tinterrupt.New(irq_USART0_RX, _UART0.handleInterrupt)\n}\n\n// UART on the AVR.\ntype UART struct {\n\tBuffer *RingBuffer\n\n\tdataReg  *volatile.Register8\n\tbaudRegH *volatile.Register8\n\tbaudRegL *volatile.Register8\n\n\tstatusRegA *volatile.Register8\n\tstatusRegB *volatile.Register8\n\tstatusRegC *volatile.Register8\n}\n\n// Configure the UART on the AVR. Defaults to 9600 baud on Arduino.\nfunc (uart *UART) Configure(config UARTConfig) {\n\tif config.BaudRate == 0 {\n\t\tconfig.BaudRate = 9600\n\t}\n\n\t// Prescale formula for u2x mode from AVR MiniCore source code.\n\t// Same as formula from specification but taking into account rounding error.\n\tps := (CPUFrequency()/4/config.BaudRate - 1) / 2\n\tuart.statusRegA.SetBits(avr.UCSR0A_U2X0)\n\n\t// Hardcoded exception for 57600 for compatibility with older bootloaders.\n\t// Also, prescale cannot be > 4095, so switch back to non-u2x mode if the baud rate is too low.\n\tif (CPUFrequency() == 16000000 && config.BaudRate == 57600) || ps > 0xfff {\n\t\tps = (CPUFrequency()/8/config.BaudRate - 1) / 2\n\t\tuart.statusRegA.ClearBits(avr.UCSR0A_U2X0)\n\t}\n\n\tuart.baudRegH.Set(uint8(ps >> 8))\n\tuart.baudRegL.Set(uint8(ps & 0xff))\n\n\t// enable RX, TX and RX interrupt\n\tuart.statusRegB.Set(avr.UCSR0B_RXEN0 | avr.UCSR0B_TXEN0 | avr.UCSR0B_RXCIE0)\n\n\t// 8-bits data\n\tuart.statusRegC.Set(avr.UCSR0C_UCSZ01 | avr.UCSR0C_UCSZ00)\n}\n\nfunc (uart *UART) handleInterrupt(intr interrupt.Interrupt) {\n\t// Read register to clear it.\n\tdata := uart.dataReg.Get()\n\n\t// Ensure no error.\n\tif !uart.statusRegA.HasBits(avr.UCSR0A_FE0 | avr.UCSR0A_DOR0 | avr.UCSR0A_UPE0) {\n\t\t// Put data from UDR register into buffer.\n\t\tuart.Receive(byte(data))\n\t}\n}\n\n// WriteByte writes a byte of data to the UART.\nfunc (uart *UART) writeByte(c byte) error {\n\t// Wait until UART buffer is not busy.\n\tfor !uart.statusRegA.HasBits(avr.UCSR0A_UDRE0) {\n\t}\n\tuart.dataReg.Set(c) // send char\n\treturn nil\n}\n\nfunc (uart *UART) flush() {}\n\n// SPIConfig is used to store config info for SPI.\ntype SPIConfig struct {\n\tFrequency uint32\n\tLSBFirst  bool\n\tMode      uint8\n}\n\n// SPI is for the Serial Peripheral Interface\n// Data is taken from http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf page 169 and following\ntype SPI struct {\n\t// The registers for the SPIx port set by the chip\n\tspcr *volatile.Register8\n\tspdr *volatile.Register8\n\tspsr *volatile.Register8\n\n\tspcrR0   byte\n\tspcrR1   byte\n\tspcrCPHA byte\n\tspcrCPOL byte\n\tspcrDORD byte\n\tspcrSPE  byte\n\tspcrMSTR byte\n\n\tspsrI2X  byte\n\tspsrSPIF byte\n\n\t// The io pins for the SPIx port set by the chip\n\tsck Pin\n\tsdi Pin\n\tsdo Pin\n\tcs  Pin\n}\n\n// Configure is intended to setup the SPI interface.\nfunc (s *SPI) Configure(config SPIConfig) error {\n\n\t// This is only here to help catch a bug with the configuration\n\t// where a machine missed a value.\n\tif s.spcr == (*volatile.Register8)(unsafe.Pointer(uintptr(0))) ||\n\t\ts.spsr == (*volatile.Register8)(unsafe.Pointer(uintptr(0))) ||\n\t\ts.spdr == (*volatile.Register8)(unsafe.Pointer(uintptr(0))) ||\n\t\ts.sck == 0 || s.sdi == 0 || s.sdo == 0 || s.cs == 0 {\n\t\treturn errSPIInvalidMachineConfig\n\t}\n\n\t// Make the defaults meaningful\n\tif config.Frequency == 0 {\n\t\tconfig.Frequency = 4000000\n\t}\n\n\t// Default all port configuration bits to 0 for simplicity\n\ts.spcr.Set(0)\n\ts.spsr.Set(0)\n\n\t// Setup pins output configuration\n\ts.sck.Configure(PinConfig{Mode: PinOutput})\n\ts.sdi.Configure(PinConfig{Mode: PinInput})\n\ts.sdo.Configure(PinConfig{Mode: PinOutput})\n\n\t// Prevent CS glitches if the pin is enabled Low (0, default)\n\ts.cs.High()\n\t// If the CS pin is not configured as output the SPI port operates in\n\t// slave mode.\n\ts.cs.Configure(PinConfig{Mode: PinOutput})\n\n\tfrequencyDivider := CPUFrequency() / config.Frequency\n\n\tswitch {\n\tcase frequencyDivider >= 128:\n\t\ts.spcr.SetBits(s.spcrR0 | s.spcrR1)\n\tcase frequencyDivider >= 64:\n\t\ts.spcr.SetBits(s.spcrR1)\n\tcase frequencyDivider >= 32:\n\t\ts.spcr.SetBits(s.spcrR1)\n\t\ts.spsr.SetBits(s.spsrI2X)\n\tcase frequencyDivider >= 16:\n\t\ts.spcr.SetBits(s.spcrR0)\n\tcase frequencyDivider >= 8:\n\t\ts.spcr.SetBits(s.spcrR0)\n\t\ts.spsr.SetBits(s.spsrI2X)\n\tcase frequencyDivider >= 4:\n\t\t// The clock is already set to all 0's.\n\tdefault: // defaults to fastest which is /2\n\t\ts.spsr.SetBits(s.spsrI2X)\n\t}\n\n\tswitch config.Mode {\n\tcase Mode1:\n\t\ts.spcr.SetBits(s.spcrCPHA)\n\tcase Mode2:\n\t\ts.spcr.SetBits(s.spcrCPHA)\n\tcase Mode3:\n\t\ts.spcr.SetBits(s.spcrCPHA | s.spcrCPOL)\n\tdefault: // default is mode 0\n\t}\n\n\tif config.LSBFirst {\n\t\ts.spcr.SetBits(s.spcrDORD)\n\t}\n\n\t// enable SPI, set controller, set clock rate\n\ts.spcr.SetBits(s.spcrSPE | s.spcrMSTR)\n\n\treturn nil\n}\n\n// Transfer writes the byte into the register and returns the read content\nfunc (s *SPI) Transfer(b byte) (byte, error) {\n\ts.spdr.Set(uint8(b))\n\n\tfor !s.spsr.HasBits(s.spsrSPIF) {\n\t}\n\n\treturn byte(s.spdr.Get()), nil\n}\n"
  },
  {
    "path": "src/machine/machine_atmega1280.go",
    "content": "//go:build avr && atmega1280\n\npackage machine\n\nimport (\n\t\"device/avr\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n)\n\nconst irq_USART0_RX = avr.IRQ_USART0_RX\n\nconst (\n\tportA Pin = iota * 8\n\tportB\n\tportC\n\tportD\n\tportE\n\tportF\n\tportG\n\tportH\n\tportJ\n\tportK\n\tportL\n)\n\nconst (\n\tPA0 = portA + 0\n\tPA1 = portA + 1\n\tPA2 = portA + 2\n\tPA3 = portA + 3\n\tPA4 = portA + 4\n\tPA5 = portA + 5\n\tPA6 = portA + 6\n\tPA7 = portA + 7\n\tPB0 = portB + 0\n\tPB1 = portB + 1\n\tPB2 = portB + 2\n\tPB3 = portB + 3\n\tPB4 = portB + 4 // peripherals: Timer2 channel A\n\tPB5 = portB + 5 // peripherals: Timer1 channel A\n\tPB6 = portB + 6 // peripherals: Timer1 channel B\n\tPB7 = portB + 7 // peripherals: Timer0 channel A\n\tPC0 = portC + 0\n\tPC1 = portC + 1\n\tPC2 = portC + 2\n\tPC3 = portC + 3\n\tPC4 = portC + 4\n\tPC5 = portC + 5\n\tPC6 = portC + 6\n\tPC7 = portC + 7\n\tPD0 = portD + 0 // peripherals: I2C0 SCL\n\tPD1 = portD + 1 // peripherals: I2C0 SDA\n\tPD2 = portD + 2\n\tPD3 = portD + 3\n\tPD7 = portD + 7\n\tPE0 = portE + 0\n\tPE1 = portE + 1\n\tPE3 = portE + 3 // peripherals: Timer3 channel A\n\tPE4 = portE + 4 // peripherals: Timer3 channel B\n\tPE5 = portE + 5 // peripherals: Timer3 channel C\n\tPE6 = portE + 6\n\tPF0 = portF + 0\n\tPF1 = portF + 1\n\tPF2 = portF + 2\n\tPF3 = portF + 3\n\tPF4 = portF + 4\n\tPF5 = portF + 5\n\tPF6 = portF + 6\n\tPF7 = portF + 7\n\tPG0 = portG + 0\n\tPG1 = portG + 1\n\tPG2 = portG + 2\n\tPG5 = portG + 5 // peripherals: Timer0 channel B\n\tPH0 = portH + 0\n\tPH1 = portH + 1\n\tPH3 = portH + 3 // peripherals: Timer4 channel A\n\tPH4 = portH + 4 // peripherals: Timer4 channel B\n\tPH5 = portH + 5 // peripherals: Timer4 channel C\n\tPH6 = portH + 6 // peripherals: Timer0 channel B\n\tPJ0 = portJ + 0\n\tPJ1 = portJ + 1\n\tPK0 = portK + 0\n\tPK1 = portK + 1\n\tPK2 = portK + 2\n\tPK3 = portK + 3\n\tPK4 = portK + 4\n\tPK5 = portK + 5\n\tPK6 = portK + 6\n\tPK7 = portK + 7\n\tPL0 = portL + 0\n\tPL1 = portL + 1\n\tPL2 = portL + 2\n\tPL3 = portL + 3 // peripherals: Timer5 channel A\n\tPL4 = portL + 4 // peripherals: Timer5 channel B\n\tPL5 = portL + 5 // peripherals: Timer5 channel C\n\tPL6 = portL + 6\n\tPL7 = portL + 7\n)\n\n// getPortMask returns the PORTx register and mask for the pin.\nfunc (p Pin) getPortMask() (*volatile.Register8, uint8) {\n\tswitch {\n\tcase p >= PA0 && p <= PA7:\n\t\treturn avr.PORTA, 1 << uint8(p-portA)\n\tcase p >= PB0 && p <= PB7:\n\t\treturn avr.PORTB, 1 << uint8(p-portB)\n\tcase p >= PC0 && p <= PC7:\n\t\treturn avr.PORTC, 1 << uint8(p-portC)\n\tcase p >= PD0 && p <= PD7:\n\t\treturn avr.PORTD, 1 << uint8(p-portD)\n\tcase p >= PE0 && p <= PE6:\n\t\treturn avr.PORTE, 1 << uint8(p-portE)\n\tcase p >= PF0 && p <= PF7:\n\t\treturn avr.PORTF, 1 << uint8(p-portF)\n\tcase p >= PG0 && p <= PG5:\n\t\treturn avr.PORTG, 1 << uint8(p-portG)\n\tcase p >= PH0 && p <= PH6:\n\t\treturn avr.PORTH, 1 << uint8(p-portH)\n\tcase p >= PJ0 && p <= PJ1:\n\t\treturn avr.PORTJ, 1 << uint8(p-portJ)\n\tcase p >= PK0 && p <= PK7:\n\t\treturn avr.PORTK, 1 << uint8(p-portK)\n\tcase p >= PL0 && p <= PL7:\n\t\treturn avr.PORTL, 1 << uint8(p-portL)\n\tdefault:\n\t\treturn avr.PORTA, 255\n\t}\n}\n\n// PWM is one PWM peripheral, which consists of a counter and two output\n// channels (that can be connected to two fixed pins). You can set the frequency\n// using SetPeriod, but only for all the channels in this PWM peripheral at\n// once.\ntype PWM struct {\n\tnum uint8\n}\n\nvar (\n\tTimer0 = PWM{0} // 8 bit timer for PB7 and PG5\n\tTimer1 = PWM{1} // 16 bit timer for PB5 and PB6\n\tTimer2 = PWM{2} // 8 bit timer for PB4 and PH6\n\tTimer3 = PWM{3} // 16 bit timer for PE3, PE4 and PE5\n\tTimer4 = PWM{4} // 16 bit timer for PH3, PH4 and PH5\n\tTimer5 = PWM{5} // 16 bit timer for PL3, PL4 and PL5\n)\n\n// Configure enables and configures this PWM.\n//\n// For the two 8 bit timers, there is only a limited number of periods\n// available, namely the CPU frequency divided by 256 and again divided by 1, 8,\n// 64, 256, or 1024. For a MCU running at 16MHz, this would be a period of 16µs,\n// 128µs, 1024µs, 4096µs, or 16384µs.\nfunc (pwm PWM) Configure(config PWMConfig) error {\n\n\tswitch pwm.num {\n\tcase 0, 2: // 8-bit timers (Timer/counter 0 and Timer/counter 2)\n\t\t// Calculate the timer prescaler.\n\t\t// While we could configure a flexible top, that would sacrifice one of\n\t\t// the PWM output compare registers and thus a PWM channel. I've chosen\n\t\t// to instead limit this timer to a fixed number of frequencies.\n\t\tvar prescaler uint8\n\t\tswitch config.Period {\n\t\tcase 0, (uint64(1e9) * 256 * 1) / uint64(CPUFrequency()):\n\t\t\tprescaler = 1\n\t\tcase (uint64(1e9) * 256 * 8) / uint64(CPUFrequency()):\n\t\t\tprescaler = 2\n\t\tcase (uint64(1e9) * 256 * 64) / uint64(CPUFrequency()):\n\t\t\tprescaler = 3\n\t\tcase (uint64(1e9) * 256 * 256) / uint64(CPUFrequency()):\n\t\t\tprescaler = 4\n\t\tcase (uint64(1e9) * 256 * 1024) / uint64(CPUFrequency()):\n\t\t\tprescaler = 5\n\t\tdefault:\n\t\t\treturn ErrPWMPeriodTooLong\n\t\t}\n\n\t\tif pwm.num == 0 {\n\t\t\tavr.TCCR0B.Set(prescaler)\n\t\t\t// Set the PWM mode to fast PWM (mode = 3).\n\t\t\tavr.TCCR0A.Set(avr.TCCR0A_WGM00 | avr.TCCR0A_WGM01)\n\t\t\t// monotonic timer is using the same time as PWM:0\n\t\t\t// we must adjust internal settings of monotonic timer when PWM:0 settings changed\n\t\t\tadjustMonotonicTimer()\n\t\t} else {\n\t\t\tavr.TCCR2B.Set(prescaler)\n\t\t\t// Set the PWM mode to fast PWM (mode = 3).\n\t\t\tavr.TCCR2A.Set(avr.TCCR2A_WGM20 | avr.TCCR2A_WGM21)\n\t\t}\n\tcase 1, 3, 4, 5:\n\t\t// The top value is the number of PWM ticks a PWM period takes. It is\n\t\t// initially picked assuming an unlimited counter top and no PWM\n\t\t// prescaler.\n\t\tvar top uint64\n\t\tif config.Period == 0 {\n\t\t\t// Use a top appropriate for LEDs. Picking a relatively low period\n\t\t\t// here (0xff) for consistency with the other timers.\n\t\t\ttop = 0xff\n\t\t} else {\n\t\t\t// The formula below calculates the following formula, optimized:\n\t\t\t//     top = period * (CPUFrequency() / 1e9)\n\t\t\t// By dividing the CPU frequency first (an operation that is easily\n\t\t\t// optimized away) the period has less chance of overflowing.\n\t\t\ttop = config.Period * (uint64(CPUFrequency()) / 1000000) / 1000\n\t\t}\n\n\t\t// The ideal PWM period may be larger than would fit in the PWM counter,\n\t\t// which is 16 bits (see maxTop). Therefore, try to make the PWM clock\n\t\t// speed lower with a prescaler to make the top value fit the maximum\n\t\t// top value.\n\n\t\tconst maxTop = 0x10000\n\t\tvar prescalingTop uint8\n\t\tswitch {\n\t\tcase top <= maxTop:\n\t\t\tprescalingTop = 3<<3 | 1 // no prescaling\n\t\tcase top/8 <= maxTop:\n\t\t\tprescalingTop = 3<<3 | 2 // divide by 8\n\t\t\ttop /= 8\n\t\tcase top/64 <= maxTop:\n\t\t\tprescalingTop = 3<<3 | 3 // divide by 64\n\t\t\ttop /= 64\n\t\tcase top/256 <= maxTop:\n\t\t\tprescalingTop = 3<<3 | 4 // divide by 256\n\t\t\ttop /= 256\n\t\tcase top/1024 <= maxTop:\n\t\t\tprescalingTop = 3<<3 | 5 // divide by 1024\n\t\t\ttop /= 1024\n\t\tdefault:\n\t\t\treturn ErrPWMPeriodTooLong\n\t\t}\n\n\t\t// A top of 0x10000 is at 100% duty cycle. Subtract one because the\n\t\t// counter counts from 0, not 1 (avoiding an off-by-one).\n\t\ttop -= 1\n\n\t\tswitch pwm.num {\n\t\tcase 1:\n\t\t\tavr.TCCR1A.Set(avr.TCCR1A_WGM11)\n\t\t\tavr.TCCR1B.Set(prescalingTop)\n\t\t\tavr.ICR1H.Set(uint8(top >> 8))\n\t\t\tavr.ICR1L.Set(uint8(top))\n\t\tcase 3:\n\t\t\tavr.TCCR3A.Set(avr.TCCR3A_WGM31)\n\t\t\tavr.TCCR3B.Set(prescalingTop)\n\t\t\tavr.ICR3H.Set(uint8(top >> 8))\n\t\t\tavr.ICR3L.Set(uint8(top))\n\t\tcase 4:\n\t\t\tavr.TCCR4A.Set(avr.TCCR4A_WGM41)\n\t\t\tavr.TCCR4B.Set(prescalingTop)\n\t\t\tavr.ICR4H.Set(uint8(top >> 8))\n\t\t\tavr.ICR4L.Set(uint8(top))\n\t\tcase 5:\n\t\t\tavr.TCCR5A.Set(avr.TCCR5A_WGM51)\n\t\t\tavr.TCCR5B.Set(prescalingTop)\n\t\t\tavr.ICR5H.Set(uint8(top >> 8))\n\t\t\tavr.ICR5L.Set(uint8(top))\n\t\t}\n\t}\n\treturn nil\n}\n\n// SetPeriod updates the period of this PWM peripheral.\n// To set a particular frequency, use the following formula:\n//\n//\tperiod = 1e9 / frequency\n//\n// If you use a period of 0, a period that works well for LEDs will be picked.\n//\n// SetPeriod will not change the prescaler, but also won't change the current\n// value in any of the channels. This means that you may need to update the\n// value for the particular channel.\n//\n// Note that you cannot pick any arbitrary period after the PWM peripheral has\n// been configured. If you want to switch between frequencies, pick the lowest\n// frequency (longest period) once when calling Configure and adjust the\n// frequency here as needed.\nfunc (pwm PWM) SetPeriod(period uint64) error {\n\tif pwm.num == 0 || pwm.num == 2 {\n\t\treturn ErrPWMPeriodTooLong // TODO better error message\n\t}\n\n\t// The top value is the number of PWM ticks a PWM period takes. It is\n\t// initially picked assuming an unlimited counter top and no PWM\n\t// prescaler.\n\tvar top uint64\n\tif period == 0 {\n\t\t// Use a top appropriate for LEDs. Picking a relatively low period\n\t\t// here (0xff) for consistency with the other timers.\n\t\ttop = 0xff\n\t} else {\n\t\t// The formula below calculates the following formula, optimized:\n\t\t//     top = period * (CPUFrequency() / 1e9)\n\t\t// By dividing the CPU frequency first (an operation that is easily\n\t\t// optimized away) the period has less chance of overflowing.\n\t\ttop = period * (uint64(CPUFrequency()) / 1000000) / 1000\n\t}\n\n\tvar prescaler uint8\n\n\tswitch pwm.num {\n\tcase 1:\n\t\tprescaler = avr.TCCR1B.Get() & 0x7\n\tcase 3:\n\t\tprescaler = avr.TCCR3B.Get() & 0x7\n\tcase 4:\n\t\tprescaler = avr.TCCR4B.Get() & 0x7\n\tcase 5:\n\t\tprescaler = avr.TCCR5B.Get() & 0x7\n\t}\n\n\tswitch prescaler {\n\tcase 1:\n\t\ttop /= 1\n\tcase 2:\n\t\ttop /= 8\n\tcase 3:\n\t\ttop /= 64\n\tcase 4:\n\t\ttop /= 256\n\tcase 5:\n\t\ttop /= 1024\n\t}\n\n\t// A top of 0x10000 is at 100% duty cycle. Subtract one because the counter\n\t// counts from 0, not 1 (avoiding an off-by-one).\n\ttop -= 1\n\n\tif top > 0xffff {\n\t\treturn ErrPWMPeriodTooLong\n\t}\n\n\tswitch pwm.num {\n\tcase 1:\n\t\t// Warning: this change is not atomic!\n\t\tavr.ICR1H.Set(uint8(top >> 8))\n\t\tavr.ICR1L.Set(uint8(top))\n\n\t\t// ... and because of that, set the counter back to zero to avoid most of\n\t\t// the effects of this non-atomicity.\n\t\tavr.TCNT1H.Set(0)\n\t\tavr.TCNT1L.Set(0)\n\tcase 3:\n\t\t// Warning: this change is not atomic!\n\t\tavr.ICR3H.Set(uint8(top >> 8))\n\t\tavr.ICR3L.Set(uint8(top))\n\n\t\t// ... and because of that, set the counter back to zero to avoid most of\n\t\t// the effects of this non-atomicity.\n\t\tavr.TCNT3H.Set(0)\n\t\tavr.TCNT3L.Set(0)\n\tcase 4:\n\t\t// Warning: this change is not atomic!\n\t\tavr.ICR4H.Set(uint8(top >> 8))\n\t\tavr.ICR4L.Set(uint8(top))\n\n\t\t// ... and because of that, set the counter back to zero to avoid most of\n\t\t// the effects of this non-atomicity.\n\t\tavr.TCNT4H.Set(0)\n\t\tavr.TCNT4L.Set(0)\n\tcase 5:\n\t\t// Warning: this change is not atomic!\n\t\tavr.ICR5H.Set(uint8(top >> 8))\n\t\tavr.ICR5L.Set(uint8(top))\n\n\t\t// ... and because of that, set the counter back to zero to avoid most of\n\t\t// the effects of this non-atomicity.\n\t\tavr.TCNT5H.Set(0)\n\t\tavr.TCNT5L.Set(0)\n\t}\n\n\treturn nil\n}\n\n// Top returns the current counter top, for use in duty cycle calculation. It\n// will only change with a call to Configure or SetPeriod, otherwise it is\n// constant.\n//\n// The value returned here is hardware dependent. In general, it's best to treat\n// it as an opaque value that can be divided by some number and passed to Set\n// (see Set documentation for more information).\nfunc (pwm PWM) Top() uint32 {\n\tswitch pwm.num {\n\tcase 1:\n\t\t// Timer 1 has a configurable top value.\n\t\tlow := avr.ICR1L.Get()\n\t\thigh := avr.ICR1H.Get()\n\t\treturn uint32(high)<<8 | uint32(low) + 1\n\tcase 3:\n\t\t// Timer 3 has a configurable top value.\n\t\tlow := avr.ICR3L.Get()\n\t\thigh := avr.ICR3H.Get()\n\t\treturn uint32(high)<<8 | uint32(low) + 1\n\tcase 4:\n\t\t// Timer 4 has a configurable top value.\n\t\tlow := avr.ICR4L.Get()\n\t\thigh := avr.ICR4H.Get()\n\t\treturn uint32(high)<<8 | uint32(low) + 1\n\tcase 5:\n\t\t// Timer 5 has a configurable top value.\n\t\tlow := avr.ICR5L.Get()\n\t\thigh := avr.ICR5H.Get()\n\t\treturn uint32(high)<<8 | uint32(low) + 1\n\t}\n\n\t// Other timers go from 0 to 0xff (0x100 or 256 in total).\n\treturn 256\n}\n\n// Counter returns the current counter value of the timer in this PWM\n// peripheral. It may be useful for debugging.\nfunc (pwm PWM) Counter() uint32 {\n\tswitch pwm.num {\n\tcase 0:\n\t\treturn uint32(avr.TCNT0.Get())\n\tcase 1:\n\t\tmask := interrupt.Disable()\n\t\tlow := avr.TCNT1L.Get()\n\t\thigh := avr.TCNT1H.Get()\n\t\tinterrupt.Restore(mask)\n\t\treturn uint32(high)<<8 | uint32(low)\n\tcase 2:\n\t\treturn uint32(avr.TCNT2.Get())\n\tcase 3:\n\t\tmask := interrupt.Disable()\n\t\tlow := avr.TCNT3L.Get()\n\t\thigh := avr.TCNT3H.Get()\n\t\tinterrupt.Restore(mask)\n\t\treturn uint32(high)<<8 | uint32(low)\n\tcase 4:\n\t\tmask := interrupt.Disable()\n\t\tlow := avr.TCNT4L.Get()\n\t\thigh := avr.TCNT4H.Get()\n\t\tinterrupt.Restore(mask)\n\t\treturn uint32(high)<<8 | uint32(low)\n\tcase 5:\n\t\tmask := interrupt.Disable()\n\t\tlow := avr.TCNT5L.Get()\n\t\thigh := avr.TCNT5H.Get()\n\t\tinterrupt.Restore(mask)\n\t\treturn uint32(high)<<8 | uint32(low)\n\t}\n\n\t// Unknown PWM.\n\treturn 0\n}\n\n// Period returns the used PWM period in nanoseconds. It might deviate slightly\n// from the configured period due to rounding.\nfunc (pwm PWM) Period() uint64 {\n\tvar prescaler uint8\n\tswitch pwm.num {\n\tcase 0:\n\t\tprescaler = avr.TCCR0B.Get() & 0x7\n\tcase 1:\n\t\tprescaler = avr.TCCR1B.Get() & 0x7\n\tcase 2:\n\t\tprescaler = avr.TCCR2B.Get() & 0x7\n\tcase 3:\n\t\tprescaler = avr.TCCR3B.Get() & 0x7\n\tcase 4:\n\t\tprescaler = avr.TCCR4B.Get() & 0x7\n\tcase 5:\n\t\tprescaler = avr.TCCR5B.Get() & 0x7\n\t}\n\ttop := uint64(pwm.Top())\n\tswitch prescaler {\n\tcase 1: // prescaler 1\n\t\treturn 1 * top * 1000 / uint64(CPUFrequency()/1e6)\n\tcase 2: // prescaler 8\n\t\treturn 8 * top * 1000 / uint64(CPUFrequency()/1e6)\n\tcase 3: // prescaler 64\n\t\treturn 64 * top * 1000 / uint64(CPUFrequency()/1e6)\n\tcase 4: // prescaler 256\n\t\treturn 256 * top * 1000 / uint64(CPUFrequency()/1e6)\n\tcase 5: // prescaler 1024\n\t\treturn 1024 * top * 1000 / uint64(CPUFrequency()/1e6)\n\tdefault: // unknown clock source\n\t\treturn 0\n\t}\n}\n\n// Channel returns a PWM channel for the given pin.\nfunc (pwm PWM) Channel(pin Pin) (uint8, error) {\n\tpin.Configure(PinConfig{Mode: PinOutput})\n\tpin.Low()\n\tswitch pwm.num {\n\tcase 0:\n\t\tswitch pin {\n\t\tcase PB7: // channel A\n\t\t\tavr.TCCR0A.SetBits(avr.TCCR0A_COM0A1)\n\t\t\treturn 0, nil\n\t\tcase PG5: // channel B\n\t\t\tavr.TCCR0A.SetBits(avr.TCCR0A_COM0B1)\n\t\t\treturn 1, nil\n\t\t}\n\tcase 1:\n\t\tswitch pin {\n\t\tcase PB5: // channel A\n\t\t\tavr.TCCR1A.SetBits(avr.TCCR1A_COM1A1)\n\t\t\treturn 0, nil\n\t\tcase PB6: // channel B\n\t\t\tavr.TCCR1A.SetBits(avr.TCCR1A_COM1B1)\n\t\t\treturn 1, nil\n\t\t}\n\tcase 2:\n\t\tswitch pin {\n\t\tcase PB4: // channel A\n\t\t\tavr.TCCR2A.SetBits(avr.TCCR2A_COM2A1)\n\t\t\treturn 0, nil\n\t\tcase PH6: // channel B\n\t\t\tavr.TCCR2A.SetBits(avr.TCCR2A_COM2B1)\n\t\t\treturn 1, nil\n\t\t}\n\tcase 3:\n\t\tswitch pin {\n\t\tcase PE3: // channel A\n\t\t\tavr.TCCR3A.SetBits(avr.TCCR3A_COM3A1)\n\t\t\treturn 0, nil\n\t\tcase PE4: //channel B\n\t\t\tavr.TCCR3A.SetBits(avr.TCCR3A_COM3B1)\n\t\t\treturn 1, nil\n\t\tcase PE5: //channel C\n\t\t\tavr.TCCR3A.SetBits(avr.TCCR3A_COM3C1)\n\t\t\treturn 2, nil\n\t\t}\n\tcase 4:\n\t\tswitch pin {\n\t\tcase PH3: // channel A\n\t\t\tavr.TCCR4A.SetBits(avr.TCCR4A_COM4A1)\n\t\t\treturn 0, nil\n\t\tcase PH4: //channel B\n\t\t\tavr.TCCR4A.SetBits(avr.TCCR4A_COM4B1)\n\t\t\treturn 1, nil\n\t\tcase PH5: //channel C\n\t\t\tavr.TCCR4A.SetBits(avr.TCCR4A_COM4C1)\n\t\t\treturn 2, nil\n\t\t}\n\tcase 5:\n\t\tswitch pin {\n\t\tcase PL3: // channel A\n\t\t\tavr.TCCR5A.SetBits(avr.TCCR5A_COM5A1)\n\t\t\treturn 0, nil\n\t\tcase PL4: //channel B\n\t\t\tavr.TCCR5A.SetBits(avr.TCCR5A_COM5B1)\n\t\t\treturn 1, nil\n\t\tcase PL5: //channel C\n\t\t\tavr.TCCR5A.SetBits(avr.TCCR5A_COM5C1)\n\t\t\treturn 2, nil\n\t\t}\n\t}\n\treturn 0, ErrInvalidOutputPin\n}\n\n// SetInverting sets whether to invert the output of this channel.\n// Without inverting, a 25% duty cycle would mean the output is high for 25% of\n// the time and low for the rest. Inverting flips the output as if a NOT gate\n// was placed at the output, meaning that the output would be 25% low and 75%\n// high with a duty cycle of 25%.\n//\n// Note: the invert state may not be applied on the AVR until the next call to\n// ch.Set().\nfunc (pwm PWM) SetInverting(channel uint8, inverting bool) {\n\tswitch pwm.num {\n\tcase 0:\n\t\tswitch channel {\n\t\tcase 0: // channel A, PB7\n\t\t\tif inverting {\n\t\t\t\tavr.PORTB.SetBits(1 << 7) // PB7 high\n\t\t\t\tavr.TCCR0A.SetBits(avr.TCCR0A_COM0A0)\n\t\t\t} else {\n\t\t\t\tavr.PORTB.ClearBits(1 << 7) // PB7 low\n\t\t\t\tavr.TCCR0A.ClearBits(avr.TCCR0A_COM0A0)\n\t\t\t}\n\t\tcase 1: // channel B, PG5\n\t\t\tif inverting {\n\t\t\t\tavr.PORTG.SetBits(1 << 5) // PG5 high\n\t\t\t\tavr.TCCR0A.SetBits(avr.TCCR0A_COM0B0)\n\t\t\t} else {\n\t\t\t\tavr.PORTG.ClearBits(1 << 5) // PG5 low\n\t\t\t\tavr.TCCR0A.ClearBits(avr.TCCR0A_COM0B0)\n\t\t\t}\n\t\t}\n\tcase 1:\n\t\t// Note: the COM1A0/COM1B0 bit is not set with the configuration below.\n\t\t// It will be set the following call to Set(), however.\n\t\tswitch channel {\n\t\tcase 0: // channel A, PB5\n\t\t\tif inverting {\n\t\t\t\tavr.PORTB.SetBits(1 << 5) // PB5 high\n\t\t\t} else {\n\t\t\t\tavr.PORTB.ClearBits(1 << 5) // PB5 low\n\t\t\t}\n\t\tcase 1: // channel B, PB6\n\t\t\tif inverting {\n\t\t\t\tavr.PORTB.SetBits(1 << 6) // PB6 high\n\t\t\t} else {\n\t\t\t\tavr.PORTB.ClearBits(1 << 6) // PB6 low\n\t\t\t}\n\t\t}\n\tcase 2:\n\t\tswitch channel {\n\t\tcase 0: // channel A, PB4\n\t\t\tif inverting {\n\t\t\t\tavr.PORTB.SetBits(1 << 4) // PB4 high\n\t\t\t\tavr.TCCR2A.SetBits(avr.TCCR2A_COM2A0)\n\t\t\t} else {\n\t\t\t\tavr.PORTB.ClearBits(1 << 4) // PB4 low\n\t\t\t\tavr.TCCR2A.ClearBits(avr.TCCR2A_COM2A0)\n\t\t\t}\n\t\tcase 1: // channel B, PH6\n\t\t\tif inverting {\n\t\t\t\tavr.PORTH.SetBits(1 << 6) // PH6 high\n\t\t\t\tavr.TCCR2A.SetBits(avr.TCCR2A_COM2B0)\n\t\t\t} else {\n\t\t\t\tavr.PORTH.ClearBits(1 << 6) // PH6 low\n\t\t\t\tavr.TCCR2A.ClearBits(avr.TCCR2A_COM2B0)\n\t\t\t}\n\t\t}\n\tcase 3:\n\t\t// Note: the COM3A0/COM3B0 bit is not set with the configuration below.\n\t\t// It will be set the following call to Set(), however.\n\t\tswitch channel {\n\t\tcase 0: // channel A, PE3\n\t\t\tif inverting {\n\t\t\t\tavr.PORTE.SetBits(1 << 3) // PE3 high\n\t\t\t} else {\n\t\t\t\tavr.PORTE.ClearBits(1 << 3) // PE3 low\n\t\t\t}\n\t\tcase 1: // channel B, PE4\n\t\t\tif inverting {\n\t\t\t\tavr.PORTE.SetBits(1 << 4) // PE4 high\n\t\t\t} else {\n\t\t\t\tavr.PORTE.ClearBits(1 << 4) // PE4 low\n\t\t\t}\n\t\tcase 2: // channel C, PE5\n\t\t\tif inverting {\n\t\t\t\tavr.PORTE.SetBits(1 << 5) // PE4 high\n\t\t\t} else {\n\t\t\t\tavr.PORTE.ClearBits(1 << 5) // PE4 low\n\t\t\t}\n\t\t}\n\tcase 4:\n\t\t// Note: the COM3A0/COM3B0 bit is not set with the configuration below.\n\t\t// It will be set the following call to Set(), however.\n\t\tswitch channel {\n\t\tcase 0: // channel A, PH3\n\t\t\tif inverting {\n\t\t\t\tavr.PORTH.SetBits(1 << 3) // PH3 high\n\t\t\t} else {\n\t\t\t\tavr.PORTH.ClearBits(1 << 3) // PH3 low\n\t\t\t}\n\t\tcase 1: // channel B, PH4\n\t\t\tif inverting {\n\t\t\t\tavr.PORTH.SetBits(1 << 4) // PH4 high\n\t\t\t} else {\n\t\t\t\tavr.PORTH.ClearBits(1 << 4) // PH4 low\n\t\t\t}\n\t\tcase 2: // channel C, PH5\n\t\t\tif inverting {\n\t\t\t\tavr.PORTH.SetBits(1 << 5) // PH4 high\n\t\t\t} else {\n\t\t\t\tavr.PORTH.ClearBits(1 << 5) // PH4 low\n\t\t\t}\n\t\t}\n\tcase 5:\n\t\t// Note: the COM3A0/COM3B0 bit is not set with the configuration below.\n\t\t// It will be set the following call to Set(), however.\n\t\tswitch channel {\n\t\tcase 0: // channel A, PL3\n\t\t\tif inverting {\n\t\t\t\tavr.PORTL.SetBits(1 << 3) // PL3 high\n\t\t\t} else {\n\t\t\t\tavr.PORTL.ClearBits(1 << 3) // PL3 low\n\t\t\t}\n\t\tcase 1: // channel B, PL4\n\t\t\tif inverting {\n\t\t\t\tavr.PORTL.SetBits(1 << 4) // PL4 high\n\t\t\t} else {\n\t\t\t\tavr.PORTL.ClearBits(1 << 4) // PL4 low\n\t\t\t}\n\t\tcase 2: // channel C, PH5\n\t\t\tif inverting {\n\t\t\t\tavr.PORTL.SetBits(1 << 5) // PL4 high\n\t\t\t} else {\n\t\t\t\tavr.PORTL.ClearBits(1 << 5) // PL4 low\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Set updates the channel value. This is used to control the channel duty\n// cycle, in other words the fraction of time the channel output is high (or low\n// when inverted). For example, to set it to a 25% duty cycle, use:\n//\n//\tpwm.Set(channel, pwm.Top() / 4)\n//\n// pwm.Set(channel, 0) will set the output to low and pwm.Set(channel,\n// pwm.Top()) will set the output to high, assuming the output isn't inverted.\nfunc (pwm PWM) Set(channel uint8, value uint32) {\n\tswitch pwm.num {\n\tcase 0:\n\t\tvalue := uint16(value)\n\t\tswitch channel {\n\t\tcase 0: // channel A\n\t\t\tif value == 0 {\n\t\t\t\tavr.TCCR0A.ClearBits(avr.TCCR0A_COM0A1)\n\t\t\t} else {\n\t\t\t\tavr.OCR0A.Set(uint8(value - 1))\n\t\t\t\tavr.TCCR0A.SetBits(avr.TCCR0A_COM0A1)\n\t\t\t}\n\t\tcase 1: // channel B\n\t\t\tif value == 0 {\n\t\t\t\tavr.TCCR0A.ClearBits(avr.TCCR0A_COM0B1)\n\t\t\t} else {\n\t\t\t\tavr.OCR0B.Set(uint8(value) - 1)\n\t\t\t\tavr.TCCR0A.SetBits(avr.TCCR0A_COM0B1)\n\t\t\t}\n\t\t}\n\t\t// monotonic timer is using the same time as PWM:0\n\t\t// we must adjust internal settings of monotonic timer when PWM:0 settings changed\n\t\tadjustMonotonicTimer()\n\tcase 1:\n\t\tmask := interrupt.Disable()\n\t\tswitch channel {\n\t\tcase 0: // channel A, PB5\n\t\t\tif value == 0 {\n\t\t\t\tavr.TCCR1A.ClearBits(avr.TCCR1A_COM1A1 | avr.TCCR1A_COM1A0)\n\t\t\t} else {\n\t\t\t\tvalue := uint16(value) - 1 // yes, this is safe (it relies on underflow)\n\t\t\t\tavr.OCR1AH.Set(uint8(value >> 8))\n\t\t\t\tavr.OCR1AL.Set(uint8(value))\n\t\t\t\tif avr.PORTB.HasBits(1 << 5) { // is PB1 high?\n\t\t\t\t\t// Yes, set the inverting bit.\n\t\t\t\t\tavr.TCCR1A.SetBits(avr.TCCR1A_COM1A1 | avr.TCCR1A_COM1A0)\n\t\t\t\t} else {\n\t\t\t\t\t// No, output is non-inverting.\n\t\t\t\t\tavr.TCCR1A.SetBits(avr.TCCR1A_COM1A1)\n\t\t\t\t}\n\t\t\t}\n\t\tcase 1: // channel B, PB6\n\t\t\tif value == 0 {\n\t\t\t\tavr.TCCR1A.ClearBits(avr.TCCR1A_COM1B1 | avr.TCCR1A_COM1B0)\n\t\t\t} else {\n\t\t\t\tvalue := uint16(value) - 1 // yes, this is safe (it relies on underflow)\n\t\t\t\tavr.OCR1BH.Set(uint8(value >> 8))\n\t\t\t\tavr.OCR1BL.Set(uint8(value))\n\t\t\t\tif avr.PORTB.HasBits(1 << 6) { // is PB6 high?\n\t\t\t\t\t// Yes, set the inverting bit.\n\t\t\t\t\tavr.TCCR1A.SetBits(avr.TCCR1A_COM1B1 | avr.TCCR1A_COM1B0)\n\t\t\t\t} else {\n\t\t\t\t\t// No, output is non-inverting.\n\t\t\t\t\tavr.TCCR1A.SetBits(avr.TCCR1A_COM1B1)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tinterrupt.Restore(mask)\n\tcase 2:\n\t\tvalue := uint16(value)\n\t\tswitch channel {\n\t\tcase 0: // channel A\n\t\t\tif value == 0 {\n\t\t\t\tavr.TCCR2A.ClearBits(avr.TCCR2A_COM2A1)\n\t\t\t} else {\n\t\t\t\tavr.OCR2A.Set(uint8(value - 1))\n\t\t\t\tavr.TCCR2A.SetBits(avr.TCCR2A_COM2A1)\n\t\t\t}\n\t\tcase 1: // channel B\n\t\t\tif value == 0 {\n\t\t\t\tavr.TCCR2A.ClearBits(avr.TCCR2A_COM2B1)\n\t\t\t} else {\n\t\t\t\tavr.OCR2B.Set(uint8(value - 1))\n\t\t\t\tavr.TCCR2A.SetBits(avr.TCCR2A_COM2B1)\n\t\t\t}\n\t\t}\n\tcase 3:\n\t\tmask := interrupt.Disable()\n\t\tswitch channel {\n\t\tcase 0: // channel A, PE3\n\t\t\tif value == 0 {\n\t\t\t\tavr.TCCR3A.ClearBits(avr.TCCR3A_COM3A1 | avr.TCCR3A_COM3A0)\n\t\t\t} else {\n\t\t\t\tvalue := uint16(value) - 1 // yes, this is safe (it relies on underflow)\n\t\t\t\tavr.OCR3AH.Set(uint8(value >> 8))\n\t\t\t\tavr.OCR3AL.Set(uint8(value))\n\t\t\t\tif avr.PORTE.HasBits(1 << 3) { // is PE3 high?\n\t\t\t\t\t// Yes, set the inverting bit.\n\t\t\t\t\tavr.TCCR3A.SetBits(avr.TCCR3A_COM3A1 | avr.TCCR3A_COM3A0)\n\t\t\t\t} else {\n\t\t\t\t\t// No, output is non-inverting.\n\t\t\t\t\tavr.TCCR3A.SetBits(avr.TCCR3A_COM3A1)\n\t\t\t\t}\n\t\t\t}\n\t\tcase 1: // channel B, PE4\n\t\t\tif value == 0 {\n\t\t\t\tavr.TCCR3A.ClearBits(avr.TCCR3A_COM3B1 | avr.TCCR3A_COM3B0)\n\t\t\t} else {\n\t\t\t\tvalue := uint16(value) - 1 // yes, this is safe (it relies on underflow)\n\t\t\t\tavr.OCR3BH.Set(uint8(value >> 8))\n\t\t\t\tavr.OCR3BL.Set(uint8(value))\n\t\t\t\tif avr.PORTE.HasBits(1 << 4) { // is PE4 high?\n\t\t\t\t\t// Yes, set the inverting bit.\n\t\t\t\t\tavr.TCCR3A.SetBits(avr.TCCR3A_COM3B1 | avr.TCCR3A_COM3B0)\n\t\t\t\t} else {\n\t\t\t\t\t// No, output is non-inverting.\n\t\t\t\t\tavr.TCCR3A.SetBits(avr.TCCR3A_COM3B1)\n\t\t\t\t}\n\t\t\t}\n\t\tcase 2: // channel C, PE5\n\t\t\tif value == 0 {\n\t\t\t\tavr.TCCR3A.ClearBits(avr.TCCR3A_COM3C1 | avr.TCCR3A_COM3C0)\n\t\t\t} else {\n\t\t\t\tvalue := uint16(value) - 1 // yes, this is safe (it relies on underflow)\n\t\t\t\tavr.OCR3CH.Set(uint8(value >> 8))\n\t\t\t\tavr.OCR3CL.Set(uint8(value))\n\t\t\t\tif avr.PORTE.HasBits(1 << 5) { // is PE5 high?\n\t\t\t\t\t// Yes, set the inverting bit.\n\t\t\t\t\tavr.TCCR3A.SetBits(avr.TCCR3A_COM3C1 | avr.TCCR3A_COM3C0)\n\t\t\t\t} else {\n\t\t\t\t\t// No, output is non-inverting.\n\t\t\t\t\tavr.TCCR3A.SetBits(avr.TCCR3A_COM3C1)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tinterrupt.Restore(mask)\n\tcase 4:\n\t\tmask := interrupt.Disable()\n\t\tswitch channel {\n\t\tcase 0: // channel A, PH3\n\t\t\tif value == 0 {\n\t\t\t\tavr.TCCR4A.ClearBits(avr.TCCR4A_COM4A1 | avr.TCCR4A_COM4A0)\n\t\t\t} else {\n\t\t\t\tvalue := uint16(value) - 1 // yes, this is safe (it relies on underflow)\n\t\t\t\tavr.OCR4AH.Set(uint8(value >> 8))\n\t\t\t\tavr.OCR4AL.Set(uint8(value))\n\t\t\t\tif avr.PORTH.HasBits(1 << 3) { // is PH3 high?\n\t\t\t\t\t// Yes, set the inverting bit.\n\t\t\t\t\tavr.TCCR4A.SetBits(avr.TCCR4A_COM4A1 | avr.TCCR4A_COM4A0)\n\t\t\t\t} else {\n\t\t\t\t\t// No, output is non-inverting.\n\t\t\t\t\tavr.TCCR4A.SetBits(avr.TCCR4A_COM4A1)\n\t\t\t\t}\n\t\t\t}\n\t\tcase 1: // channel B, PH4\n\t\t\tif value == 0 {\n\t\t\t\tavr.TCCR4A.ClearBits(avr.TCCR4A_COM4B1 | avr.TCCR4A_COM4B0)\n\t\t\t} else {\n\t\t\t\tvalue := uint16(value) - 1 // yes, this is safe (it relies on underflow)\n\t\t\t\tavr.OCR4BH.Set(uint8(value >> 8))\n\t\t\t\tavr.OCR4BL.Set(uint8(value))\n\t\t\t\tif avr.PORTH.HasBits(1 << 4) { // is PH4 high?\n\t\t\t\t\t// Yes, set the inverting bit.\n\t\t\t\t\tavr.TCCR4A.SetBits(avr.TCCR4A_COM4B1 | avr.TCCR4A_COM4B0)\n\t\t\t\t} else {\n\t\t\t\t\t// No, output is non-inverting.\n\t\t\t\t\tavr.TCCR4A.SetBits(avr.TCCR4A_COM4B1)\n\t\t\t\t}\n\t\t\t}\n\t\tcase 2: // channel C, PH5\n\t\t\tif value == 0 {\n\t\t\t\tavr.TCCR4A.ClearBits(avr.TCCR4A_COM4C1 | avr.TCCR4A_COM4C0)\n\t\t\t} else {\n\t\t\t\tvalue := uint16(value) - 1 // yes, this is safe (it relies on underflow)\n\t\t\t\tavr.OCR4CH.Set(uint8(value >> 8))\n\t\t\t\tavr.OCR4CL.Set(uint8(value))\n\t\t\t\tif avr.PORTH.HasBits(1 << 5) { // is PH5 high?\n\t\t\t\t\t// Yes, set the inverting bit.\n\t\t\t\t\tavr.TCCR4A.SetBits(avr.TCCR4A_COM4C1 | avr.TCCR4A_COM4C0)\n\t\t\t\t} else {\n\t\t\t\t\t// No, output is non-inverting.\n\t\t\t\t\tavr.TCCR4A.SetBits(avr.TCCR4A_COM4C1)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tinterrupt.Restore(mask)\n\tcase 5:\n\t\tmask := interrupt.Disable()\n\t\tswitch channel {\n\t\tcase 0: // channel A, PL3\n\t\t\tif value == 0 {\n\t\t\t\tavr.TCCR5A.ClearBits(avr.TCCR5A_COM5A1 | avr.TCCR5A_COM5A0)\n\t\t\t} else {\n\t\t\t\tvalue := uint16(value) - 1 // yes, this is safe (it relies on underflow)\n\t\t\t\tavr.OCR5AH.Set(uint8(value >> 8))\n\t\t\t\tavr.OCR5AL.Set(uint8(value))\n\t\t\t\tif avr.PORTL.HasBits(1 << 3) { // is PL3 high?\n\t\t\t\t\t// Yes, set the inverting bit.\n\t\t\t\t\tavr.TCCR5A.SetBits(avr.TCCR5A_COM5A1 | avr.TCCR5A_COM5A0)\n\t\t\t\t} else {\n\t\t\t\t\t// No, output is non-inverting.\n\t\t\t\t\tavr.TCCR5A.SetBits(avr.TCCR5A_COM5A1)\n\t\t\t\t}\n\t\t\t}\n\t\tcase 1: // channel B, PL4\n\t\t\tif value == 0 {\n\t\t\t\tavr.TCCR5A.ClearBits(avr.TCCR5A_COM5B1 | avr.TCCR5A_COM5B0)\n\t\t\t} else {\n\t\t\t\tvalue := uint16(value) - 1 // yes, this is safe (it relies on underflow)\n\t\t\t\tavr.OCR5BH.Set(uint8(value >> 8))\n\t\t\t\tavr.OCR5BL.Set(uint8(value))\n\t\t\t\tif avr.PORTL.HasBits(1 << 4) { // is PL4 high?\n\t\t\t\t\t// Yes, set the inverting bit.\n\t\t\t\t\tavr.TCCR5A.SetBits(avr.TCCR5A_COM5B1 | avr.TCCR5A_COM5B0)\n\t\t\t\t} else {\n\t\t\t\t\t// No, output is non-inverting.\n\t\t\t\t\tavr.TCCR5A.SetBits(avr.TCCR5A_COM5B1)\n\t\t\t\t}\n\t\t\t}\n\t\tcase 2: // channel C, PL5\n\t\t\tif value == 0 {\n\t\t\t\tavr.TCCR5A.ClearBits(avr.TCCR5A_COM5C1 | avr.TCCR5A_COM5C0)\n\t\t\t} else {\n\t\t\t\tvalue := uint16(value) - 1 // yes, this is safe (it relies on underflow)\n\t\t\t\tavr.OCR5CH.Set(uint8(value >> 8))\n\t\t\t\tavr.OCR5CL.Set(uint8(value))\n\t\t\t\tif avr.PORTL.HasBits(1 << 5) { // is PL5 high?\n\t\t\t\t\t// Yes, set the inverting bit.\n\t\t\t\t\tavr.TCCR5A.SetBits(avr.TCCR5A_COM5C1 | avr.TCCR5A_COM5C0)\n\t\t\t\t} else {\n\t\t\t\t\t// No, output is non-inverting.\n\t\t\t\t\tavr.TCCR5A.SetBits(avr.TCCR5A_COM5C1)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tinterrupt.Restore(mask)\n\t}\n}\n\n// SPI configuration\nvar SPI0 = &SPI{\n\tspcr: avr.SPCR,\n\tspdr: avr.SPDR,\n\tspsr: avr.SPSR,\n\tsck:  PB1,\n\tsdo:  PB2,\n\tsdi:  PB3,\n\tcs:   PB0}\n"
  },
  {
    "path": "src/machine/machine_atmega1284p.go",
    "content": "//go:build avr && atmega1284p\n\npackage machine\n\nimport (\n\t\"device/avr\"\n\t\"runtime/volatile\"\n)\n\nconst irq_USART0_RX = avr.IRQ_USART0_RX\n\n// Return the current CPU frequency in hertz.\nfunc CPUFrequency() uint32 {\n\treturn 20000000\n}\n\nconst (\n\tportA Pin = iota * 8\n\tportB\n\tportC\n\tportD\n)\n\nconst (\n\tPA0 = portA + 0\n\tPA1 = portA + 1\n\tPA2 = portA + 2\n\tPA3 = portA + 3\n\tPA4 = portA + 4\n\tPA5 = portA + 5\n\tPA6 = portA + 6\n\tPA7 = portA + 7\n\tPB0 = portB + 0\n\tPB1 = portB + 1\n\tPB2 = portB + 2\n\tPB3 = portB + 3\n\tPB4 = portB + 4\n\tPB5 = portB + 5\n\tPB6 = portB + 6\n\tPB7 = portB + 7\n\tPC0 = portC + 0\n\tPC1 = portC + 1\n\tPC2 = portC + 2\n\tPC3 = portC + 3\n\tPC4 = portC + 4\n\tPC5 = portC + 5\n\tPC6 = portC + 6\n\tPC7 = portC + 7\n\tPD0 = portD + 0\n\tPD1 = portD + 1\n\tPD2 = portD + 2\n\tPD3 = portD + 3\n\tPD4 = portD + 4\n\tPD5 = portD + 5\n\tPD6 = portD + 6\n\tPD7 = portD + 7\n)\n\n// getPortMask returns the PORTx register and mask for the pin.\nfunc (p Pin) getPortMask() (*volatile.Register8, uint8) {\n\tswitch {\n\tcase p >= PA0 && p <= PA7:\n\t\treturn avr.PORTA, 1 << uint8(p-portA)\n\tcase p >= PB0 && p <= PB7:\n\t\treturn avr.PORTB, 1 << uint8(p-portB)\n\tcase p >= PC0 && p <= PC7:\n\t\treturn avr.PORTC, 1 << uint8(p-portC)\n\tdefault:\n\t\treturn avr.PORTD, 1 << uint8(p-portD)\n\t}\n}\n\n// SPI configuration\nvar SPI0 = &SPI{\n\tspcr: avr.SPCR,\n\tspsr: avr.SPSR,\n\tspdr: avr.SPDR,\n\tsck:  PB7,\n\tsdo:  PB5,\n\tsdi:  PB6,\n\tcs:   PB4}\n"
  },
  {
    "path": "src/machine/machine_atmega2560.go",
    "content": "//go:build avr && atmega2560\n\npackage machine\n\nimport (\n\t\"device/avr\"\n\t\"runtime/volatile\"\n)\n\nconst irq_USART0_RX = avr.IRQ_USART0_RX\nconst irq_USART1_RX = avr.IRQ_USART1_RX\nconst irq_USART2_RX = avr.IRQ_USART2_RX\nconst irq_USART3_RX = avr.IRQ_USART3_RX\n\nconst (\n\tportA Pin = iota * 8\n\tportB\n\tportC\n\tportD\n\tportE\n\tportF\n\tportG\n\tportH\n\tportJ\n\tportK\n\tportL\n)\n\nconst (\n\tPA0 = portA + 0\n\tPA1 = portA + 1\n\tPA2 = portA + 2\n\tPA3 = portA + 3\n\tPA4 = portA + 4\n\tPA5 = portA + 5\n\tPA6 = portA + 6\n\tPA7 = portA + 7\n\tPB0 = portB + 0\n\tPB1 = portB + 1\n\tPB2 = portB + 2\n\tPB3 = portB + 3\n\tPB4 = portB + 4\n\tPB5 = portB + 5\n\tPB6 = portB + 6\n\tPB7 = portB + 7\n\tPC0 = portC + 0\n\tPC1 = portC + 1\n\tPC2 = portC + 2\n\tPC3 = portC + 3\n\tPC4 = portC + 4\n\tPC5 = portC + 5\n\tPC6 = portC + 6\n\tPC7 = portC + 7\n\tPD0 = portD + 0\n\tPD1 = portD + 1\n\tPD2 = portD + 2\n\tPD3 = portD + 3\n\tPD7 = portD + 7\n\tPE0 = portE + 0\n\tPE1 = portE + 1\n\tPE3 = portE + 3\n\tPE4 = portE + 4\n\tPE5 = portE + 5\n\tPE6 = portE + 6\n\tPF0 = portF + 0\n\tPF1 = portF + 1\n\tPF2 = portF + 2\n\tPF3 = portF + 3\n\tPF4 = portF + 4\n\tPF5 = portF + 5\n\tPF6 = portF + 6\n\tPF7 = portF + 7\n\tPG0 = portG + 0\n\tPG1 = portG + 1\n\tPG2 = portG + 2\n\tPG5 = portG + 5\n\tPH0 = portH + 0\n\tPH1 = portH + 1\n\tPH3 = portH + 3\n\tPH4 = portH + 4\n\tPH5 = portH + 5\n\tPH6 = portH + 6\n\tPJ0 = portJ + 0\n\tPJ1 = portJ + 1\n\tPK0 = portK + 0\n\tPK1 = portK + 1\n\tPK2 = portK + 2\n\tPK3 = portK + 3\n\tPK4 = portK + 4\n\tPK5 = portK + 5\n\tPK6 = portK + 6\n\tPK7 = portK + 7\n\tPL0 = portL + 0\n\tPL1 = portL + 1\n\tPL2 = portL + 2\n\tPL3 = portL + 3\n\tPL4 = portL + 4\n\tPL5 = portL + 5\n\tPL6 = portL + 6\n\tPL7 = portL + 7\n)\n\n// getPortMask returns the PORTx register and mask for the pin.\nfunc (p Pin) getPortMask() (*volatile.Register8, uint8) {\n\tswitch {\n\tcase p >= PA0 && p <= PA7:\n\t\treturn avr.PORTA, 1 << uint8(p-portA)\n\tcase p >= PB0 && p <= PB7:\n\t\treturn avr.PORTB, 1 << uint8(p-portB)\n\tcase p >= PC0 && p <= PC7:\n\t\treturn avr.PORTC, 1 << uint8(p-portC)\n\tcase p >= PD0 && p <= PD7:\n\t\treturn avr.PORTD, 1 << uint8(p-portD)\n\tcase p >= PE0 && p <= PE6:\n\t\treturn avr.PORTE, 1 << uint8(p-portE)\n\tcase p >= PF0 && p <= PF7:\n\t\treturn avr.PORTF, 1 << uint8(p-portF)\n\tcase p >= PG0 && p <= PG5:\n\t\treturn avr.PORTG, 1 << uint8(p-portG)\n\tcase p >= PH0 && p <= PH6:\n\t\treturn avr.PORTH, 1 << uint8(p-portH)\n\tcase p >= PJ0 && p <= PJ1:\n\t\treturn avr.PORTJ, 1 << uint8(p-portJ)\n\tcase p >= PK0 && p <= PK7:\n\t\treturn avr.PORTK, 1 << uint8(p-portK)\n\tcase p >= PL0 && p <= PL7:\n\t\treturn avr.PORTL, 1 << uint8(p-portL)\n\tdefault:\n\t\treturn avr.PORTA, 255\n\t}\n}\n\n// SPI configuration\nvar SPI0 = &SPI{\n\tspcr: avr.SPCR,\n\tspdr: avr.SPDR,\n\tspsr: avr.SPSR,\n\tsck:  PB1,\n\tsdo:  PB2,\n\tsdi:  PB3,\n\tcs:   PB0}\n"
  },
  {
    "path": "src/machine/machine_atmega328.go",
    "content": "//go:build avr && (atmega328p || atmega328pb)\n\npackage machine\n\nimport (\n\t\"device/avr\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n)\n\n// PWM is one PWM peripheral, which consists of a counter and two output\n// channels (that can be connected to two fixed pins). You can set the frequency\n// using SetPeriod, but only for all the channels in this PWM peripheral at\n// once.\ntype PWM struct {\n\tnum uint8\n}\n\nvar (\n\tTimer0 = PWM{0} // 8 bit timer for PD5 and PD6\n\tTimer1 = PWM{1} // 16 bit timer for PB1 and PB2\n\tTimer2 = PWM{2} // 8 bit timer for PB3 and PD3\n)\n\n// Configure enables and configures this PWM.\n//\n// For the two 8 bit timers, there is only a limited number of periods\n// available, namely the CPU frequency divided by 256 and again divided by 1, 8,\n// 64, 256, or 1024. For a MCU running at 16MHz, this would be a period of 16µs,\n// 128µs, 1024µs, 4096µs, or 16384µs.\nfunc (pwm PWM) Configure(config PWMConfig) error {\n\tswitch pwm.num {\n\tcase 0, 2: // 8-bit timers (Timer/counter 0 and Timer/counter 2)\n\t\t// Calculate the timer prescaler.\n\t\t// While we could configure a flexible top, that would sacrifice one of\n\t\t// the PWM output compare registers and thus a PWM channel. I've chosen\n\t\t// to instead limit this timer to a fixed number of frequencies.\n\t\tvar prescaler uint8\n\t\tswitch config.Period {\n\t\tcase 0, (uint64(1e9) * 256 * 1) / uint64(CPUFrequency()):\n\t\t\tprescaler = 1\n\t\tcase (uint64(1e9) * 256 * 8) / uint64(CPUFrequency()):\n\t\t\tprescaler = 2\n\t\tcase (uint64(1e9) * 256 * 64) / uint64(CPUFrequency()):\n\t\t\tprescaler = 3\n\t\tcase (uint64(1e9) * 256 * 256) / uint64(CPUFrequency()):\n\t\t\tprescaler = 4\n\t\tcase (uint64(1e9) * 256 * 1024) / uint64(CPUFrequency()):\n\t\t\tprescaler = 5\n\t\tdefault:\n\t\t\treturn ErrPWMPeriodTooLong\n\t\t}\n\n\t\tif pwm.num == 0 {\n\t\t\tavr.TCCR0B.Set(prescaler)\n\t\t\t// Set the PWM mode to fast PWM (mode = 3).\n\t\t\tavr.TCCR0A.Set(avr.TCCR0A_WGM00 | avr.TCCR0A_WGM01)\n\t\t\t// monotonic timer is using the same time as PWM:0\n\t\t\t// we must adjust internal settings of monotonic timer when PWM:0 settings changed\n\t\t\tadjustMonotonicTimer()\n\t\t} else {\n\t\t\tavr.TCCR2B.Set(prescaler)\n\t\t\t// Set the PWM mode to fast PWM (mode = 3).\n\t\t\tavr.TCCR2A.Set(avr.TCCR2A_WGM20 | avr.TCCR2A_WGM21)\n\t\t}\n\tcase 1: // Timer/counter 1\n\t\t// The top value is the number of PWM ticks a PWM period takes. It is\n\t\t// initially picked assuming an unlimited counter top and no PWM\n\t\t// prescaler.\n\t\tvar top uint64\n\t\tif config.Period == 0 {\n\t\t\t// Use a top appropriate for LEDs. Picking a relatively low period\n\t\t\t// here (0xff) for consistency with the other timers.\n\t\t\ttop = 0xff\n\t\t} else {\n\t\t\t// The formula below calculates the following formula, optimized:\n\t\t\t//     top = period * (CPUFrequency() / 1e9)\n\t\t\t// By dividing the CPU frequency first (an operation that is easily\n\t\t\t// optimized away) the period has less chance of overflowing.\n\t\t\ttop = config.Period * (uint64(CPUFrequency()) / 1000000) / 1000\n\t\t}\n\n\t\tavr.TCCR1A.Set(avr.TCCR1A_WGM11)\n\n\t\t// The ideal PWM period may be larger than would fit in the PWM counter,\n\t\t// which is 16 bits (see maxTop). Therefore, try to make the PWM clock\n\t\t// speed lower with a prescaler to make the top value fit the maximum\n\t\t// top value.\n\t\tconst maxTop = 0x10000\n\t\tswitch {\n\t\tcase top <= maxTop:\n\t\t\tavr.TCCR1B.Set(3<<3 | 1) // no prescaling\n\t\tcase top/8 <= maxTop:\n\t\t\tavr.TCCR1B.Set(3<<3 | 2) // divide by 8\n\t\t\ttop /= 8\n\t\tcase top/64 <= maxTop:\n\t\t\tavr.TCCR1B.Set(3<<3 | 3) // divide by 64\n\t\t\ttop /= 64\n\t\tcase top/256 <= maxTop:\n\t\t\tavr.TCCR1B.Set(3<<3 | 4) // divide by 256\n\t\t\ttop /= 256\n\t\tcase top/1024 <= maxTop:\n\t\t\tavr.TCCR1B.Set(3<<3 | 5) // divide by 1024\n\t\t\ttop /= 1024\n\t\tdefault:\n\t\t\treturn ErrPWMPeriodTooLong\n\t\t}\n\n\t\t// A top of 0x10000 is at 100% duty cycle. Subtract one because the\n\t\t// counter counts from 0, not 1 (avoiding an off-by-one).\n\t\ttop -= 1\n\n\t\tavr.ICR1H.Set(uint8(top >> 8))\n\t\tavr.ICR1L.Set(uint8(top))\n\t}\n\treturn nil\n}\n\n// SetPeriod updates the period of this PWM peripheral.\n// To set a particular frequency, use the following formula:\n//\n//\tperiod = 1e9 / frequency\n//\n// If you use a period of 0, a period that works well for LEDs will be picked.\n//\n// SetPeriod will not change the prescaler, but also won't change the current\n// value in any of the channels. This means that you may need to update the\n// value for the particular channel.\n//\n// Note that you cannot pick any arbitrary period after the PWM peripheral has\n// been configured. If you want to switch between frequencies, pick the lowest\n// frequency (longest period) once when calling Configure and adjust the\n// frequency here as needed.\nfunc (pwm PWM) SetPeriod(period uint64) error {\n\tif pwm.num != 1 {\n\t\treturn ErrPWMPeriodTooLong // TODO better error message\n\t}\n\n\t// The top value is the number of PWM ticks a PWM period takes. It is\n\t// initially picked assuming an unlimited counter top and no PWM\n\t// prescaler.\n\tvar top uint64\n\tif period == 0 {\n\t\t// Use a top appropriate for LEDs. Picking a relatively low period\n\t\t// here (0xff) for consistency with the other timers.\n\t\ttop = 0xff\n\t} else {\n\t\t// The formula below calculates the following formula, optimized:\n\t\t//     top = period * (CPUFrequency() / 1e9)\n\t\t// By dividing the CPU frequency first (an operation that is easily\n\t\t// optimized away) the period has less chance of overflowing.\n\t\ttop = period * (uint64(CPUFrequency()) / 1000000) / 1000\n\t}\n\n\tprescaler := avr.TCCR1B.Get() & 0x7\n\tswitch prescaler {\n\tcase 1:\n\t\ttop /= 1\n\tcase 2:\n\t\ttop /= 8\n\tcase 3:\n\t\ttop /= 64\n\tcase 4:\n\t\ttop /= 256\n\tcase 5:\n\t\ttop /= 1024\n\t}\n\n\t// A top of 0x10000 is at 100% duty cycle. Subtract one because the counter\n\t// counts from 0, not 1 (avoiding an off-by-one).\n\ttop -= 1\n\n\tif top > 0xffff {\n\t\treturn ErrPWMPeriodTooLong\n\t}\n\n\t// Warning: this change is not atomic!\n\tavr.ICR1H.Set(uint8(top >> 8))\n\tavr.ICR1L.Set(uint8(top))\n\n\t// ... and because of that, set the counter back to zero to avoid most of\n\t// the effects of this non-atomicity.\n\tavr.TCNT1H.Set(0)\n\tavr.TCNT1L.Set(0)\n\n\treturn nil\n}\n\n// Top returns the current counter top, for use in duty cycle calculation. It\n// will only change with a call to Configure or SetPeriod, otherwise it is\n// constant.\n//\n// The value returned here is hardware dependent. In general, it's best to treat\n// it as an opaque value that can be divided by some number and passed to Set\n// (see Set documentation for more information).\nfunc (pwm PWM) Top() uint32 {\n\tif pwm.num == 1 {\n\t\t// Timer 1 has a configurable top value.\n\t\tlow := avr.ICR1L.Get()\n\t\thigh := avr.ICR1H.Get()\n\t\treturn uint32(high)<<8 | uint32(low) + 1\n\t}\n\t// Other timers go from 0 to 0xff (0x100 or 256 in total).\n\treturn 256\n}\n\n// Counter returns the current counter value of the timer in this PWM\n// peripheral. It may be useful for debugging.\nfunc (pwm PWM) Counter() uint32 {\n\tswitch pwm.num {\n\tcase 0:\n\t\treturn uint32(avr.TCNT0.Get())\n\tcase 1:\n\t\tmask := interrupt.Disable()\n\t\tlow := avr.TCNT1L.Get()\n\t\thigh := avr.TCNT1H.Get()\n\t\tinterrupt.Restore(mask)\n\t\treturn uint32(high)<<8 | uint32(low)\n\tcase 2:\n\t\treturn uint32(avr.TCNT2.Get())\n\t}\n\t// Unknown PWM.\n\treturn 0\n}\n\n// Period returns the used PWM period in nanoseconds. It might deviate slightly\n// from the configured period due to rounding.\nfunc (pwm PWM) Period() uint64 {\n\tvar prescaler uint8\n\tswitch pwm.num {\n\tcase 0:\n\t\tprescaler = avr.TCCR0B.Get() & 0x7\n\tcase 1:\n\t\tprescaler = avr.TCCR1B.Get() & 0x7\n\tcase 2:\n\t\tprescaler = avr.TCCR2B.Get() & 0x7\n\t}\n\ttop := uint64(pwm.Top())\n\tswitch prescaler {\n\tcase 1: // prescaler 1\n\t\treturn 1 * top * 1000 / uint64(CPUFrequency()/1e6)\n\tcase 2: // prescaler 8\n\t\treturn 8 * top * 1000 / uint64(CPUFrequency()/1e6)\n\tcase 3: // prescaler 64\n\t\treturn 64 * top * 1000 / uint64(CPUFrequency()/1e6)\n\tcase 4: // prescaler 256\n\t\treturn 256 * top * 1000 / uint64(CPUFrequency()/1e6)\n\tcase 5: // prescaler 1024\n\t\treturn 1024 * top * 1000 / uint64(CPUFrequency()/1e6)\n\tdefault: // unknown clock source\n\t\treturn 0\n\t}\n}\n\n// Channel returns a PWM channel for the given pin.\nfunc (pwm PWM) Channel(pin Pin) (uint8, error) {\n\tpin.Configure(PinConfig{Mode: PinOutput})\n\tpin.Low()\n\tswitch pwm.num {\n\tcase 0:\n\t\tswitch pin {\n\t\tcase PD6: // channel A\n\t\t\tavr.TCCR0A.SetBits(avr.TCCR0A_COM0A1)\n\t\t\treturn 0, nil\n\t\tcase PD5: // channel B\n\t\t\tavr.TCCR0A.SetBits(avr.TCCR0A_COM0B1)\n\t\t\treturn 1, nil\n\t\t}\n\tcase 1:\n\t\tswitch pin {\n\t\tcase PB1: // channel A\n\t\t\tavr.TCCR1A.SetBits(avr.TCCR1A_COM1A1)\n\t\t\treturn 0, nil\n\t\tcase PB2: // channel B\n\t\t\tavr.TCCR1A.SetBits(avr.TCCR1A_COM1B1)\n\t\t\treturn 1, nil\n\t\t}\n\tcase 2:\n\t\tswitch pin {\n\t\tcase PB3: // channel A\n\t\t\tavr.TCCR2A.SetBits(avr.TCCR2A_COM2A1)\n\t\t\treturn 0, nil\n\t\tcase PD3: // channel B\n\t\t\tavr.TCCR2A.SetBits(avr.TCCR2A_COM2B1)\n\t\t\treturn 1, nil\n\t\t}\n\t}\n\treturn 0, ErrInvalidOutputPin\n}\n\n// SetInverting sets whether to invert the output of this channel.\n// Without inverting, a 25% duty cycle would mean the output is high for 25% of\n// the time and low for the rest. Inverting flips the output as if a NOT gate\n// was placed at the output, meaning that the output would be 25% low and 75%\n// high with a duty cycle of 25%.\n//\n// Note: the invert state may not be applied on the AVR until the next call to\n// ch.Set().\nfunc (pwm PWM) SetInverting(channel uint8, inverting bool) {\n\tswitch pwm.num {\n\tcase 0:\n\t\tswitch channel {\n\t\tcase 0: // channel A\n\t\t\tif inverting {\n\t\t\t\tavr.PORTB.SetBits(1 << 6) // PB6 high\n\t\t\t\tavr.TCCR0A.SetBits(avr.TCCR0A_COM0A0)\n\t\t\t} else {\n\t\t\t\tavr.PORTB.ClearBits(1 << 6) // PB6 low\n\t\t\t\tavr.TCCR0A.ClearBits(avr.TCCR0A_COM0A0)\n\t\t\t}\n\t\tcase 1: // channel B\n\t\t\tif inverting {\n\t\t\t\tavr.PORTB.SetBits(1 << 5) // PB5 high\n\t\t\t\tavr.TCCR0A.SetBits(avr.TCCR0A_COM0B0)\n\t\t\t} else {\n\t\t\t\tavr.PORTB.ClearBits(1 << 5) // PB5 low\n\t\t\t\tavr.TCCR0A.ClearBits(avr.TCCR0A_COM0B0)\n\t\t\t}\n\t\t}\n\tcase 1:\n\t\t// Note: the COM1A0/COM1B0 bit is not set with the configuration below.\n\t\t// It will be set the following call to Set(), however.\n\t\tswitch channel {\n\t\tcase 0: // channel A, PB1\n\t\t\tif inverting {\n\t\t\t\tavr.PORTB.SetBits(1 << 1) // PB1 high\n\t\t\t} else {\n\t\t\t\tavr.PORTB.ClearBits(1 << 1) // PB1 low\n\t\t\t}\n\t\tcase 1: // channel B, PB2\n\t\t\tif inverting {\n\t\t\t\tavr.PORTB.SetBits(1 << 2) // PB2 high\n\t\t\t} else {\n\t\t\t\tavr.PORTB.ClearBits(1 << 2) // PB2 low\n\t\t\t}\n\t\t}\n\tcase 2:\n\t\tswitch channel {\n\t\tcase 0: // channel A\n\t\t\tif inverting {\n\t\t\t\tavr.PORTB.SetBits(1 << 3) // PB3 high\n\t\t\t\tavr.TCCR2A.SetBits(avr.TCCR2A_COM2A0)\n\t\t\t} else {\n\t\t\t\tavr.PORTB.ClearBits(1 << 3) // PB3 low\n\t\t\t\tavr.TCCR2A.ClearBits(avr.TCCR2A_COM2A0)\n\t\t\t}\n\t\tcase 1: // channel B\n\t\t\tif inverting {\n\t\t\t\tavr.PORTD.SetBits(1 << 3) // PD3 high\n\t\t\t\tavr.TCCR2A.SetBits(avr.TCCR2A_COM2B0)\n\t\t\t} else {\n\t\t\t\tavr.PORTD.ClearBits(1 << 3) // PD3 low\n\t\t\t\tavr.TCCR2A.ClearBits(avr.TCCR2A_COM2B0)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Set updates the channel value. This is used to control the channel duty\n// cycle, in other words the fraction of time the channel output is high (or low\n// when inverted). For example, to set it to a 25% duty cycle, use:\n//\n//\tpwm.Set(channel, pwm.Top() / 4)\n//\n// pwm.Set(channel, 0) will set the output to low and pwm.Set(channel,\n// pwm.Top()) will set the output to high, assuming the output isn't inverted.\nfunc (pwm PWM) Set(channel uint8, value uint32) {\n\tswitch pwm.num {\n\tcase 0:\n\t\tvalue := uint16(value)\n\t\tswitch channel {\n\t\tcase 0: // channel A\n\t\t\tif value == 0 {\n\t\t\t\tavr.TCCR0A.ClearBits(avr.TCCR0A_COM0A1)\n\t\t\t} else {\n\t\t\t\tavr.OCR0A.Set(uint8(value - 1))\n\t\t\t\tavr.TCCR0A.SetBits(avr.TCCR0A_COM0A1)\n\t\t\t}\n\t\tcase 1: // channel B\n\t\t\tif value == 0 {\n\t\t\t\tavr.TCCR0A.ClearBits(avr.TCCR0A_COM0B1)\n\t\t\t} else {\n\t\t\t\tavr.OCR0B.Set(uint8(value) - 1)\n\t\t\t\tavr.TCCR0A.SetBits(avr.TCCR0A_COM0B1)\n\t\t\t}\n\t\t}\n\t\t// monotonic timer is using the same time as PWM:0\n\t\t// we must adjust internal settings of monotonic timer when PWM:0 settings changed\n\t\tadjustMonotonicTimer()\n\tcase 1:\n\t\tmask := interrupt.Disable()\n\t\tswitch channel {\n\t\tcase 0: // channel A, PB1\n\t\t\tif value == 0 {\n\t\t\t\tavr.TCCR1A.ClearBits(avr.TCCR1A_COM1A1 | avr.TCCR1A_COM1A0)\n\t\t\t} else {\n\t\t\t\tvalue := uint16(value) - 1 // yes, this is safe (it relies on underflow)\n\t\t\t\tavr.OCR1AH.Set(uint8(value >> 8))\n\t\t\t\tavr.OCR1AL.Set(uint8(value))\n\t\t\t\tif avr.PORTB.HasBits(1 << 1) { // is PB1 high?\n\t\t\t\t\t// Yes, set the inverting bit.\n\t\t\t\t\tavr.TCCR1A.SetBits(avr.TCCR1A_COM1A1 | avr.TCCR1A_COM1A0)\n\t\t\t\t} else {\n\t\t\t\t\t// No, output is non-inverting.\n\t\t\t\t\tavr.TCCR1A.SetBits(avr.TCCR1A_COM1A1)\n\t\t\t\t}\n\t\t\t}\n\t\tcase 1: // channel B, PB2\n\t\t\tif value == 0 {\n\t\t\t\tavr.TCCR1A.ClearBits(avr.TCCR1A_COM1B1 | avr.TCCR1A_COM1B0)\n\t\t\t} else {\n\t\t\t\tvalue := uint16(value) - 1 // yes, this is safe (it relies on underflow)\n\t\t\t\tavr.OCR1BH.Set(uint8(value >> 8))\n\t\t\t\tavr.OCR1BL.Set(uint8(value))\n\t\t\t\tif avr.PORTB.HasBits(1 << 2) { // is PB2 high?\n\t\t\t\t\t// Yes, set the inverting bit.\n\t\t\t\t\tavr.TCCR1A.SetBits(avr.TCCR1A_COM1B1 | avr.TCCR1A_COM1B0)\n\t\t\t\t} else {\n\t\t\t\t\t// No, output is non-inverting.\n\t\t\t\t\tavr.TCCR1A.SetBits(avr.TCCR1A_COM1B1)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tinterrupt.Restore(mask)\n\tcase 2:\n\t\tvalue := uint16(value)\n\t\tswitch channel {\n\t\tcase 0: // channel A\n\t\t\tif value == 0 {\n\t\t\t\tavr.TCCR2A.ClearBits(avr.TCCR2A_COM2A1)\n\t\t\t} else {\n\t\t\t\tavr.OCR2A.Set(uint8(value - 1))\n\t\t\t\tavr.TCCR2A.SetBits(avr.TCCR2A_COM2A1)\n\t\t\t}\n\t\tcase 1: // channel B\n\t\t\tif value == 0 {\n\t\t\t\tavr.TCCR2A.ClearBits(avr.TCCR2A_COM2B1)\n\t\t\t} else {\n\t\t\t\tavr.OCR2B.Set(uint8(value - 1))\n\t\t\t\tavr.TCCR2A.SetBits(avr.TCCR2A_COM2B1)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Pin Change Interrupts\ntype PinChange uint8\n\nconst (\n\tPinRising PinChange = 1 << iota\n\tPinFalling\n\tPinToggle = PinRising | PinFalling\n)\n\nfunc (pin Pin) SetInterrupt(pinChange PinChange, callback func(Pin)) (err error) {\n\n\tswitch {\n\tcase pin >= PB0 && pin <= PB7:\n\t\t// PCMSK0 - PCINT0-7\n\t\tpinStates[0] = avr.PINB.Get()\n\t\tpinIndex := pin - PB0\n\t\tif pinChange&PinRising > 0 {\n\t\t\tpinCallbacks[0][pinIndex][0] = callback\n\t\t}\n\t\tif pinChange&PinFalling > 0 {\n\t\t\tpinCallbacks[0][pinIndex][1] = callback\n\t\t}\n\t\tif callback != nil {\n\t\t\tavr.PCMSK0.SetBits(1 << pinIndex)\n\t\t} else {\n\t\t\tavr.PCMSK0.ClearBits(1 << pinIndex)\n\t\t}\n\t\tavr.PCICR.SetBits(avr.PCICR_PCIE0)\n\t\tinterrupt.New(avr.IRQ_PCINT0, handlePCINT0Interrupts)\n\tcase pin >= PC0 && pin <= PC7:\n\t\t// PCMSK1 - PCINT8-14\n\t\tpinStates[1] = avr.PINC.Get()\n\t\tpinIndex := pin - PC0\n\t\tif pinChange&PinRising > 0 {\n\t\t\tpinCallbacks[1][pinIndex][0] = callback\n\t\t}\n\t\tif pinChange&PinFalling > 0 {\n\t\t\tpinCallbacks[1][pinIndex][1] = callback\n\t\t}\n\t\tif callback != nil {\n\t\t\tavr.PCMSK1.SetBits(1 << pinIndex)\n\t\t} else {\n\t\t\tavr.PCMSK1.ClearBits(1 << pinIndex)\n\t\t}\n\t\tavr.PCICR.SetBits(avr.PCICR_PCIE1)\n\t\tinterrupt.New(avr.IRQ_PCINT1, handlePCINT1Interrupts)\n\tcase pin >= PD0 && pin <= PD7:\n\t\t// PCMSK2 - PCINT16-23\n\t\tpinStates[2] = avr.PIND.Get()\n\t\tpinIndex := pin - PD0\n\t\tif pinChange&PinRising > 0 {\n\t\t\tpinCallbacks[2][pinIndex][0] = callback\n\t\t}\n\t\tif pinChange&PinFalling > 0 {\n\t\t\tpinCallbacks[2][pinIndex][1] = callback\n\t\t}\n\t\tif callback != nil {\n\t\t\tavr.PCMSK2.SetBits(1 << pinIndex)\n\t\t} else {\n\t\t\tavr.PCMSK2.ClearBits(1 << pinIndex)\n\t\t}\n\t\tavr.PCICR.SetBits(avr.PCICR_PCIE2)\n\t\tinterrupt.New(avr.IRQ_PCINT2, handlePCINT2Interrupts)\n\tdefault:\n\t\treturn ErrInvalidInputPin\n\t}\n\n\treturn nil\n}\n\nvar pinCallbacks [3][8][2]func(Pin)\nvar pinStates [3]uint8\n\nfunc handlePCINTInterrupts(intr uint8, port *volatile.Register8) {\n\tcurrent := port.Get()\n\tchange := pinStates[intr] ^ current\n\tpinStates[intr] = current\n\tfor i := uint8(0); i < 8; i++ {\n\t\tif (change>>i)&0x01 != 0x01 {\n\t\t\tcontinue\n\t\t}\n\t\tpin := Pin(intr*8 + i)\n\t\tvalue := pin.Get()\n\t\tif value && pinCallbacks[intr][i][0] != nil {\n\t\t\tpinCallbacks[intr][i][0](pin)\n\t\t}\n\t\tif !value && pinCallbacks[intr][i][1] != nil {\n\t\t\tpinCallbacks[intr][i][1](pin)\n\t\t}\n\t}\n}\n\nfunc handlePCINT0Interrupts(intr interrupt.Interrupt) {\n\thandlePCINTInterrupts(0, avr.PINB)\n}\n\nfunc handlePCINT1Interrupts(intr interrupt.Interrupt) {\n\thandlePCINTInterrupts(1, avr.PINC)\n}\n\nfunc handlePCINT2Interrupts(intr interrupt.Interrupt) {\n\thandlePCINTInterrupts(2, avr.PIND)\n}\n"
  },
  {
    "path": "src/machine/machine_atmega328p.go",
    "content": "//go:build avr && atmega328p\n\npackage machine\n\nimport (\n\t\"device/avr\"\n\t\"runtime/volatile\"\n)\n\nconst irq_USART0_RX = avr.IRQ_USART_RX\n\n// I2C0 is the only I2C interface on most AVRs.\nvar I2C0 = &I2C{\n\tsrReg: avr.TWSR,\n\tbrReg: avr.TWBR,\n\tcrReg: avr.TWCR,\n\tdrReg: avr.TWDR,\n\tsrPS0: avr.TWSR_TWPS0,\n\tsrPS1: avr.TWSR_TWPS1,\n\tcrEN:  avr.TWCR_TWEN,\n\tcrINT: avr.TWCR_TWINT,\n\tcrSTO: avr.TWCR_TWSTO,\n\tcrEA:  avr.TWCR_TWEA,\n\tcrSTA: avr.TWCR_TWSTA,\n}\n\n// SPI configuration\nvar SPI0 = &SPI{\n\tspcr: avr.SPCR,\n\tspdr: avr.SPDR,\n\tspsr: avr.SPSR,\n\n\tspcrR0:   avr.SPCR_SPR0,\n\tspcrR1:   avr.SPCR_SPR1,\n\tspcrCPHA: avr.SPCR_CPHA,\n\tspcrCPOL: avr.SPCR_CPOL,\n\tspcrDORD: avr.SPCR_DORD,\n\tspcrSPE:  avr.SPCR_SPE,\n\tspcrMSTR: avr.SPCR_MSTR,\n\n\tspsrI2X:  avr.SPSR_SPI2X,\n\tspsrSPIF: avr.SPSR_SPIF,\n\n\tsck: PB5,\n\tsdo: PB3,\n\tsdi: PB4,\n\tcs:  PB2,\n}\n\n// getPortMask returns the PORTx register and mask for the pin.\nfunc (p Pin) getPortMask() (*volatile.Register8, uint8) {\n\tswitch {\n\tcase p >= PB0 && p <= PB7: // port B\n\t\treturn avr.PORTB, 1 << uint8(p-portB)\n\tcase p >= PC0 && p <= PC7: // port C\n\t\treturn avr.PORTC, 1 << uint8(p-portC)\n\tdefault: // port D\n\t\treturn avr.PORTD, 1 << uint8(p-portD)\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_atmega328p_simulator.go",
    "content": "//go:build !baremetal && (arduino || arduino_nano)\n\npackage machine\n\nvar I2C0 = &I2C{Bus: 0, PinsSDA: []Pin{PC4}, PinsSCL: []Pin{PC5}}\n"
  },
  {
    "path": "src/machine/machine_atmega328pb.go",
    "content": "//go:build avr && atmega328pb\n\npackage machine\n\nimport (\n\t\"device/avr\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n)\n\nconst irq_USART0_RX = avr.IRQ_USART0_RX\nconst irq_USART1_RX = avr.IRQ_USART1_RX\n\nvar (\n\tUART1  = &_UART1\n\t_UART1 = UART{\n\t\tBuffer: NewRingBuffer(),\n\n\t\tdataReg:    avr.UDR1,\n\t\tbaudRegH:   avr.UBRR1H,\n\t\tbaudRegL:   avr.UBRR1L,\n\t\tstatusRegA: avr.UCSR1A,\n\t\tstatusRegB: avr.UCSR1B,\n\t\tstatusRegC: avr.UCSR1C,\n\t}\n)\n\nfunc init() {\n\t// Register the UART interrupt.\n\tinterrupt.New(irq_USART1_RX, _UART1.handleInterrupt)\n}\n\n// I2C0 is the only I2C interface on most AVRs.\nvar I2C0 = &I2C{\n\tsrReg: avr.TWSR0,\n\tbrReg: avr.TWBR0,\n\tcrReg: avr.TWCR0,\n\tdrReg: avr.TWDR0,\n\tsrPS0: avr.TWSR0_TWPS0,\n\tsrPS1: avr.TWSR0_TWPS1,\n\tcrEN:  avr.TWCR0_TWEN,\n\tcrINT: avr.TWCR0_TWINT,\n\tcrSTO: avr.TWCR0_TWSTO,\n\tcrEA:  avr.TWCR0_TWEA,\n\tcrSTA: avr.TWCR0_TWSTA,\n}\n\nvar I2C1 = &I2C{\n\tsrReg: avr.TWSR1,\n\tbrReg: avr.TWBR1,\n\tcrReg: avr.TWCR1,\n\tdrReg: avr.TWDR1,\n\tsrPS0: avr.TWSR1_TWPS10,\n\tsrPS1: avr.TWSR1_TWPS11,\n\tcrEN:  avr.TWCR1_TWEN1,\n\tcrINT: avr.TWCR1_TWINT1,\n\tcrSTO: avr.TWCR1_TWSTO1,\n\tcrEA:  avr.TWCR1_TWEA1,\n\tcrSTA: avr.TWCR1_TWSTA1,\n}\n\n// SPI configuration\nvar SPI0 = &SPI{\n\tspcr: avr.SPCR0,\n\tspdr: avr.SPDR0,\n\tspsr: avr.SPSR0,\n\n\tspcrR0:   avr.SPCR0_SPR0,\n\tspcrR1:   avr.SPCR0_SPR1,\n\tspcrCPHA: avr.SPCR0_CPHA,\n\tspcrCPOL: avr.SPCR0_CPOL,\n\tspcrDORD: avr.SPCR0_DORD,\n\tspcrSPE:  avr.SPCR0_SPE,\n\tspcrMSTR: avr.SPCR0_MSTR,\n\n\tspsrI2X:  avr.SPSR0_SPI2X,\n\tspsrSPIF: avr.SPSR0_SPIF,\n\n\tsck: PB5,\n\tsdo: PB3,\n\tsdi: PB4,\n\tcs:  PB2,\n}\n\nvar SPI1 = &SPI{\n\tspcr: avr.SPCR1,\n\tspdr: avr.SPDR1,\n\tspsr: avr.SPSR1,\n\n\tspcrR0:   avr.SPCR1_SPR10,\n\tspcrR1:   avr.SPCR1_SPR11,\n\tspcrCPHA: avr.SPCR1_CPHA1,\n\tspcrCPOL: avr.SPCR1_CPOL1,\n\tspcrDORD: avr.SPCR1_DORD1,\n\tspcrSPE:  avr.SPCR1_SPE1,\n\tspcrMSTR: avr.SPCR1_MSTR1,\n\n\tspsrI2X:  avr.SPSR1_SPI2X1,\n\tspsrSPIF: avr.SPSR1_SPIF1,\n\n\tsck: PC1,\n\tsdo: PE3,\n\tsdi: PC0,\n\tcs:  PE2,\n}\n\n// getPortMask returns the PORTx register and mask for the pin.\nfunc (p Pin) getPortMask() (*volatile.Register8, uint8) {\n\tswitch {\n\tcase p >= PB0 && p <= PB7: // port B\n\t\treturn avr.PORTB, 1 << uint8(p-portB)\n\tcase p >= PC0 && p <= PC7: // port C\n\t\treturn avr.PORTC, 1 << uint8(p-portC)\n\tcase p >= PD0 && p <= PD7: // port D\n\t\treturn avr.PORTD, 1 << uint8(p-portD)\n\tdefault: // port E\n\t\treturn avr.PORTE, 1 << uint8(p-portE)\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_atmega32u4.go",
    "content": "//go:build avr && atmega32u4\n\npackage machine\n\nimport (\n\t\"device/avr\"\n\t\"runtime/volatile\"\n)\n\nconst (\n\t// Note: start at port B because there is no port A.\n\tportB Pin = iota * 8\n\tportC\n\tportD\n\tportE\n\tportF\n)\n\nconst (\n\tPB0 = portB + 0\n\tPB1 = portB + 1 // peripherals: Timer1 channel A\n\tPB2 = portB + 2 // peripherals: Timer1 channel B\n\tPB3 = portB + 3 // peripherals: Timer2 channel A\n\tPB4 = portB + 4\n\tPB5 = portB + 5\n\tPB6 = portB + 6\n\tPB7 = portB + 7\n\tPC0 = portC + 0\n\tPC1 = portC + 1\n\tPC2 = portC + 2\n\tPC3 = portC + 3\n\tPC4 = portC + 4\n\tPC5 = portC + 5\n\tPC6 = portC + 6\n\tPC7 = portC + 7\n\tPD0 = portD + 0\n\tPD1 = portD + 1\n\tPD2 = portD + 2\n\tPD3 = portD + 3\n\tPD4 = portD + 4\n\tPD5 = portD + 5\n\tPD6 = portD + 6\n\tPD7 = portD + 7\n\tPE0 = portE + 0\n\tPE1 = portE + 1\n\tPE2 = portE + 2\n\tPE3 = portE + 3\n\tPE4 = portE + 4\n\tPE5 = portE + 5\n\tPE6 = portE + 6\n\tPE7 = portE + 7\n\tPF0 = portF + 0\n\tPF1 = portF + 1\n\tPF2 = portF + 2\n\tPF3 = portF + 3\n\tPF4 = portF + 4\n\tPF5 = portF + 5\n\tPF6 = portF + 6\n\tPF7 = portF + 7\n)\n\n// getPortMask returns the PORTx register and mask for the pin.\nfunc (p Pin) getPortMask() (*volatile.Register8, uint8) {\n\tswitch {\n\tcase p >= PB0 && p <= PB7: // port B\n\t\treturn avr.PORTB, 1 << uint8(p-portB)\n\tcase p >= PC0 && p <= PC7: // port C\n\t\treturn avr.PORTC, 1 << uint8(p-portC)\n\tcase p >= PD0 && p <= PD7: // port D\n\t\treturn avr.PORTD, 1 << uint8(p-portD)\n\tcase p >= PE0 && p <= PE7: // port E\n\t\treturn avr.PORTE, 1 << uint8(p-portE)\n\tdefault: // port F\n\t\treturn avr.PORTF, 1 << uint8(p-portF)\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_atsam.go",
    "content": "//go:build sam\n\npackage machine\n\nimport (\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nvar deviceID [16]byte\n\n// DeviceID returns an identifier that is unique within\n// a particular chipset.\n//\n// The identity is one burnt into the MCU itself, or the\n// flash chip at time of manufacture.\n//\n// It's possible that two different vendors may allocate\n// the same DeviceID, so callers should take this into\n// account if needing to generate a globally unique id.\n//\n// The length of the hardware ID is vendor-specific, but\n// 8 bytes (64 bits) and 16 bytes (128 bits) are common.\nfunc DeviceID() []byte {\n\tfor i := 0; i < len(deviceID); i++ {\n\t\tword := (*volatile.Register32)(unsafe.Pointer(deviceIDAddr[i/4])).Get()\n\t\tdeviceID[i] = byte(word >> ((i % 4) * 8))\n\t}\n\n\treturn deviceID[:]\n}\n"
  },
  {
    "path": "src/machine/machine_atsamd21.go",
    "content": "//go:build sam && atsamd21\n\n// Peripheral abstraction layer for the atsamd21.\n//\n// Datasheet:\n// http://ww1.microchip.com/downloads/en/DeviceDoc/SAMD21-Family-DataSheet-DS40001882D.pdf\npackage machine\n\nimport (\n\t\"device/arm\"\n\t\"device/sam\"\n\t\"errors\"\n\t\"internal/binary\"\n\t\"runtime/interrupt\"\n\t\"unsafe\"\n)\n\nconst deviceName = sam.Device\n\n// DS40001882F, Section 10.3.3: Serial Number\nvar deviceIDAddr = []uintptr{0x0080A00C, 0x0080A040, 0x0080A044, 0x0080A048}\n\nconst (\n\tPinAnalog    PinMode = 1\n\tPinSERCOM    PinMode = 2\n\tPinSERCOMAlt PinMode = 3\n\tPinTimer     PinMode = 4\n\tPinTimerAlt  PinMode = 5\n\tPinCom       PinMode = 6\n\t//PinAC_CLK        PinMode = 7\n\tPinDigital       PinMode = 8\n\tPinInput         PinMode = 9\n\tPinInputPullup   PinMode = 10\n\tPinOutput        PinMode = 11\n\tPinTCC           PinMode = PinTimer\n\tPinTCCAlt        PinMode = PinTimerAlt\n\tPinInputPulldown PinMode = 12\n)\n\ntype PinChange uint8\n\n// Pin change interrupt constants for SetInterrupt.\nconst (\n\tPinRising  PinChange = sam.EIC_CONFIG_SENSE0_RISE\n\tPinFalling PinChange = sam.EIC_CONFIG_SENSE0_FALL\n\tPinToggle  PinChange = sam.EIC_CONFIG_SENSE0_BOTH\n)\n\n// Callbacks to be called for pins configured with SetInterrupt. Unfortunately,\n// we also need to keep track of which interrupt channel is used by which pin,\n// as the only alternative would be iterating through all pins.\n//\n// We're using the magic constant 16 here because the SAM D21 has 16 interrupt\n// channels configurable for pins.\nvar (\n\tinterruptPins [16]Pin // warning: the value is invalid when pinCallbacks[i] is not set!\n\tpinCallbacks  [16]func(Pin)\n)\n\nconst (\n\tpinPadMapSERCOM0Pad0 byte = (0x10 << 1) | 0x00\n\tpinPadMapSERCOM1Pad0 byte = (0x20 << 1) | 0x00\n\tpinPadMapSERCOM2Pad0 byte = (0x30 << 1) | 0x00\n\tpinPadMapSERCOM3Pad0 byte = (0x40 << 1) | 0x00\n\tpinPadMapSERCOM4Pad0 byte = (0x50 << 1) | 0x00\n\tpinPadMapSERCOM5Pad0 byte = (0x60 << 1) | 0x00\n\tpinPadMapSERCOM0Pad2 byte = (0x10 << 1) | 0x10\n\tpinPadMapSERCOM1Pad2 byte = (0x20 << 1) | 0x10\n\tpinPadMapSERCOM2Pad2 byte = (0x30 << 1) | 0x10\n\tpinPadMapSERCOM3Pad2 byte = (0x40 << 1) | 0x10\n\tpinPadMapSERCOM4Pad2 byte = (0x50 << 1) | 0x10\n\tpinPadMapSERCOM5Pad2 byte = (0x60 << 1) | 0x10\n\n\tpinPadMapSERCOM0AltPad0 byte = (0x01 << 1) | 0x00\n\tpinPadMapSERCOM1AltPad0 byte = (0x02 << 1) | 0x00\n\tpinPadMapSERCOM2AltPad0 byte = (0x03 << 1) | 0x00\n\tpinPadMapSERCOM3AltPad0 byte = (0x04 << 1) | 0x00\n\tpinPadMapSERCOM4AltPad0 byte = (0x05 << 1) | 0x00\n\tpinPadMapSERCOM5AltPad0 byte = (0x06 << 1) | 0x00\n\tpinPadMapSERCOM0AltPad2 byte = (0x01 << 1) | 0x01\n\tpinPadMapSERCOM1AltPad2 byte = (0x02 << 1) | 0x01\n\tpinPadMapSERCOM2AltPad2 byte = (0x03 << 1) | 0x01\n\tpinPadMapSERCOM3AltPad2 byte = (0x04 << 1) | 0x01\n\tpinPadMapSERCOM4AltPad2 byte = (0x05 << 1) | 0x01\n\tpinPadMapSERCOM5AltPad2 byte = (0x06 << 1) | 0x01\n)\n\n// pinPadMapping lists which pins have which SERCOMs attached to them.\n// The encoding is rather dense, with each byte encoding two pins and both\n// SERCOM and SERCOM-ALT.\n//\n// Observations:\n//   - There are six SERCOMs. Those SERCOM numbers can be encoded in 3 bits.\n//   - Even pad numbers are always on even pins, and odd pad numbers are always on\n//     odd pins.\n//   - Pin pads come in pairs. If PA00 has pad 0, then PA01 has pad 1.\n//\n// With this information, we can encode SERCOM pin/pad numbers much more\n// efficiently. First of all, due to pads coming in pairs, we can ignore half\n// the pins: the information for an odd pin can be calculated easily from the\n// preceding even pin. And second, if odd pads are always on odd pins and even\n// pads on even pins, we can drop a single bit from the pad number.\n//\n// Each byte below is split in two nibbles. The 4 high bits are for SERCOM and\n// the 4 low bits are for SERCOM-ALT. Of each nibble, the 3 high bits encode the\n// SERCOM + 1 while the low bit encodes whether this is PAD0 or PAD2 (0 means\n// PAD0, 1 means PAD2). It encodes SERCOM + 1 instead of just the SERCOM number,\n// to make it easy to check whether a nibble is set at all.\nvar pinPadMapping = [32]byte{\n\t// page 21\n\tPA00 / 2: 0 | pinPadMapSERCOM1AltPad0,\n\tPB08 / 2: 0 | pinPadMapSERCOM4AltPad0,\n\tPA04 / 2: 0 | pinPadMapSERCOM0AltPad0,\n\tPA06 / 2: 0 | pinPadMapSERCOM0AltPad2,\n\tPA08 / 2: pinPadMapSERCOM0Pad0 | pinPadMapSERCOM2AltPad0,\n\tPA10 / 2: pinPadMapSERCOM0Pad2 | pinPadMapSERCOM2AltPad2,\n\n\t// page 22\n\tPB10 / 2: 0 | pinPadMapSERCOM4AltPad2,\n\tPB12 / 2: pinPadMapSERCOM4Pad0 | 0,\n\tPB14 / 2: pinPadMapSERCOM4Pad2 | 0,\n\tPA12 / 2: pinPadMapSERCOM2Pad0 | pinPadMapSERCOM4AltPad0,\n\tPA14 / 2: pinPadMapSERCOM2Pad2 | pinPadMapSERCOM4AltPad2,\n\tPA16 / 2: pinPadMapSERCOM1Pad0 | pinPadMapSERCOM3AltPad0,\n\tPA18 / 2: pinPadMapSERCOM1Pad2 | pinPadMapSERCOM3AltPad2,\n\tPB16 / 2: pinPadMapSERCOM5Pad0 | 0,\n\tPA20 / 2: pinPadMapSERCOM5Pad2 | pinPadMapSERCOM3AltPad2,\n\tPA22 / 2: pinPadMapSERCOM3Pad0 | pinPadMapSERCOM5AltPad0,\n\tPA24 / 2: pinPadMapSERCOM3Pad2 | pinPadMapSERCOM5AltPad2,\n\n\t// page 23\n\tPB22 / 2: 0 | pinPadMapSERCOM5AltPad2,\n\tPA30 / 2: 0 | pinPadMapSERCOM1AltPad2,\n\tPB30 / 2: 0 | pinPadMapSERCOM5AltPad0,\n\tPB00 / 2: 0 | pinPadMapSERCOM5AltPad2,\n\tPB02 / 2: 0 | pinPadMapSERCOM5AltPad0,\n}\n\n// findPinPadMapping looks up the pad number and the pinmode for a given pin,\n// given a SERCOM number. The result can either be SERCOM, SERCOM-ALT, or \"not\n// found\" (indicated by returning ok=false). The pad number is returned to\n// calculate the DOPO/DIPO bitfields of the various serial peripherals.\nfunc findPinPadMapping(sercom uint8, pin Pin) (pinMode PinMode, pad uint32, ok bool) {\n\tif int(pin)/2 >= len(pinPadMapping) {\n\t\t// This is probably NoPin, for which no mapping is available.\n\t\treturn\n\t}\n\n\tnibbles := pinPadMapping[pin/2]\n\tupper := nibbles >> 4\n\tlower := nibbles & 0xf\n\n\tif upper != 0 {\n\t\t// SERCOM\n\t\tif (upper>>1)-1 == sercom {\n\t\t\tpinMode = PinSERCOM\n\t\t\tpad |= uint32((upper & 1) << 1)\n\t\t\tok = true\n\t\t}\n\t}\n\tif lower != 0 {\n\t\t// SERCOM-ALT\n\t\tif (lower>>1)-1 == sercom {\n\t\t\tpinMode = PinSERCOMAlt\n\t\t\tpad |= uint32((lower & 1) << 1)\n\t\t\tok = true\n\t\t}\n\t}\n\n\tif ok {\n\t\t// The lower bit of the pad is the same as the lower bit of the pin number.\n\t\tpad |= uint32(pin & 1)\n\t}\n\treturn\n}\n\n// SetInterrupt sets an interrupt to be executed when a particular pin changes\n// state. The pin should already be configured as an input, including a pull up\n// or down if no external pull is provided.\n//\n// This call will replace a previously set callback on this pin. You can pass a\n// nil func to unset the pin change interrupt. If you do so, the change\n// parameter is ignored and can be set to any value (such as 0).\nfunc (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error {\n\t// Most pins follow a common pattern where the EXTINT value is the pin\n\t// number modulo 16. However, there are a few exceptions, as you can see\n\t// below.\n\textint := uint8(0)\n\tswitch p {\n\tcase PA08:\n\t\t// Connected to NMI. This is not currently supported.\n\t\treturn ErrInvalidInputPin\n\tcase PA24:\n\t\textint = 12\n\tcase PA25:\n\t\textint = 13\n\tcase PA27:\n\t\textint = 15\n\tcase PA28:\n\t\textint = 8\n\tcase PA30:\n\t\textint = 10\n\tcase PA31:\n\t\textint = 11\n\tdefault:\n\t\t// All other pins follow a normal pattern.\n\t\textint = uint8(p) % 16\n\t}\n\n\tif callback == nil {\n\t\t// Disable this pin interrupt (if it was enabled).\n\t\tsam.EIC.INTENCLR.Set(1 << extint)\n\t\tif pinCallbacks[extint] != nil {\n\t\t\tpinCallbacks[extint] = nil\n\t\t}\n\t\treturn nil\n\t}\n\n\tif pinCallbacks[extint] != nil {\n\t\t// The pin was already configured.\n\t\t// To properly re-configure a pin, unset it first and set a new\n\t\t// configuration.\n\t\treturn ErrNoPinChangeChannel\n\t}\n\tpinCallbacks[extint] = callback\n\tinterruptPins[extint] = p\n\n\tif sam.EIC.CTRL.Get() == 0 {\n\t\t// EIC peripheral has not yet been initialized. Initialize it now.\n\n\t\t// The EIC needs two clocks: CLK_EIC_APB and GCLK_EIC. CLK_EIC_APB is\n\t\t// enabled by default, so doesn't have to be re-enabled. The other is\n\t\t// required for detecting edges and must be enabled manually.\n\t\tsam.GCLK.CLKCTRL.Set(sam.GCLK_CLKCTRL_ID_EIC<<sam.GCLK_CLKCTRL_ID_Pos |\n\t\t\tsam.GCLK_CLKCTRL_GEN_GCLK0<<sam.GCLK_CLKCTRL_GEN_Pos |\n\t\t\tsam.GCLK_CLKCTRL_CLKEN)\n\n\t\t// should not be necessary (CLKCTRL is not synchronized)\n\t\tfor sam.GCLK.STATUS.HasBits(sam.GCLK_STATUS_SYNCBUSY) {\n\t\t}\n\n\t\tsam.EIC.CTRL.Set(sam.EIC_CTRL_ENABLE)\n\t\tfor sam.EIC.STATUS.HasBits(sam.EIC_STATUS_SYNCBUSY) {\n\t\t}\n\t}\n\n\t// Configure this pin. Set the 4 bits of the EIC.CONFIGx register to the\n\t// sense value (filter bit set to 0, sense bits set to the change value).\n\taddr := &sam.EIC.CONFIG0\n\tif extint >= 8 {\n\t\taddr = &sam.EIC.CONFIG1\n\t}\n\tpos := (extint % 8) * 4 // bit position in register\n\taddr.ReplaceBits(uint32(change), 0xf, pos)\n\n\t// Enable external interrupt for this pin.\n\tsam.EIC.INTENSET.Set(1 << extint)\n\n\t// Set the PMUXEN flag, while keeping the INEN and PULLEN flags (if they\n\t// were set before). This avoids clearing the pin pull mode while\n\t// configuring the pin interrupt.\n\tp.setPinCfg(sam.PORT_PINCFG0_PMUXEN | (p.getPinCfg() & (sam.PORT_PINCFG0_INEN | sam.PORT_PINCFG0_PULLEN)))\n\tif p&1 > 0 {\n\t\t// odd pin, so save the even pins\n\t\tval := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk\n\t\tp.setPMux(val | (sam.PORT_PMUX0_PMUXO_A << sam.PORT_PMUX0_PMUXO_Pos))\n\t} else {\n\t\t// even pin, so save the odd pins\n\t\tval := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk\n\t\tp.setPMux(val | (sam.PORT_PMUX0_PMUXE_A << sam.PORT_PMUX0_PMUXE_Pos))\n\t}\n\n\tinterrupt.New(sam.IRQ_EIC, func(interrupt.Interrupt) {\n\t\tflags := sam.EIC.INTFLAG.Get()\n\t\tsam.EIC.INTFLAG.Set(flags)      // clear interrupt\n\t\tfor i := uint(0); i < 16; i++ { // there are 16 channels\n\t\t\tif flags&(1<<i) != 0 {\n\t\t\t\tpinCallbacks[i](interruptPins[i])\n\t\t\t}\n\t\t}\n\t}).Enable()\n\n\treturn nil\n}\n\n// InitADC initializes the ADC.\nfunc InitADC() {\n\t// ADC Bias Calibration\n\t// #define ADC_FUSES_BIASCAL_ADDR      (NVMCTRL_OTP4 + 4)\n\t// #define ADC_FUSES_BIASCAL_Pos       3            /**< \\brief (NVMCTRL_OTP4) ADC Bias Calibration */\n\t// #define ADC_FUSES_BIASCAL_Msk       (0x7u << ADC_FUSES_BIASCAL_Pos)\n\t// #define ADC_FUSES_BIASCAL(value)    ((ADC_FUSES_BIASCAL_Msk & ((value) << ADC_FUSES_BIASCAL_Pos)))\n\t// #define ADC_FUSES_LINEARITY_0_ADDR  NVMCTRL_OTP4\n\t// #define ADC_FUSES_LINEARITY_0_Pos   27           /**< \\brief (NVMCTRL_OTP4) ADC Linearity bits 4:0 */\n\t// #define ADC_FUSES_LINEARITY_0_Msk   (0x1Fu << ADC_FUSES_LINEARITY_0_Pos)\n\t// #define ADC_FUSES_LINEARITY_0(value) ((ADC_FUSES_LINEARITY_0_Msk & ((value) << ADC_FUSES_LINEARITY_0_Pos)))\n\t// #define ADC_FUSES_LINEARITY_1_ADDR  (NVMCTRL_OTP4 + 4)\n\t// #define ADC_FUSES_LINEARITY_1_Pos   0            /**< \\brief (NVMCTRL_OTP4) ADC Linearity bits 7:5 */\n\t// #define ADC_FUSES_LINEARITY_1_Msk   (0x7u << ADC_FUSES_LINEARITY_1_Pos)\n\t// #define ADC_FUSES_LINEARITY_1(value) ((ADC_FUSES_LINEARITY_1_Msk & ((value) << ADC_FUSES_LINEARITY_1_Pos)))\n\n\tbiasFuse := *(*uint32)(unsafe.Pointer(uintptr(0x00806020) + 4))\n\tbias := uint16(biasFuse>>3) & uint16(0x7)\n\n\t// ADC Linearity bits 4:0\n\tlinearity0Fuse := *(*uint32)(unsafe.Pointer(uintptr(0x00806020)))\n\tlinearity := uint16(linearity0Fuse>>27) & uint16(0x1f)\n\n\t// ADC Linearity bits 7:5\n\tlinearity1Fuse := *(*uint32)(unsafe.Pointer(uintptr(0x00806020) + 4))\n\tlinearity |= uint16(linearity1Fuse) & uint16(0x7) << 5\n\n\t// set calibration\n\tsam.ADC.CALIB.Set((bias << 8) | linearity)\n}\n\n// Configure configures a ADC pin to be able to be used to read data.\nfunc (a ADC) Configure(config ADCConfig) {\n\n\t// Wait for synchronization\n\twaitADCSync()\n\n\tvar resolution uint32\n\tswitch config.Resolution {\n\tcase 8:\n\t\tresolution = sam.ADC_CTRLB_RESSEL_8BIT\n\tcase 10:\n\t\tresolution = sam.ADC_CTRLB_RESSEL_10BIT\n\tcase 12:\n\t\tresolution = sam.ADC_CTRLB_RESSEL_12BIT\n\tcase 16:\n\t\tresolution = sam.ADC_CTRLB_RESSEL_16BIT\n\tdefault:\n\t\tresolution = sam.ADC_CTRLB_RESSEL_12BIT\n\t}\n\t// Divide Clock by 32 with 12 bits resolution as default\n\tsam.ADC.CTRLB.Set((sam.ADC_CTRLB_PRESCALER_DIV32 << sam.ADC_CTRLB_PRESCALER_Pos) |\n\t\tuint16(resolution<<sam.ADC_CTRLB_RESSEL_Pos))\n\n\t// Sampling Time Length\n\tsam.ADC.SAMPCTRL.Set(5)\n\n\t// Wait for synchronization\n\twaitADCSync()\n\n\t// Use internal ground\n\tsam.ADC.INPUTCTRL.Set(sam.ADC_INPUTCTRL_MUXNEG_GND << sam.ADC_INPUTCTRL_MUXNEG_Pos)\n\n\t// Averaging (see datasheet table in AVGCTRL register description)\n\tvar samples uint32\n\tswitch config.Samples {\n\tcase 1:\n\t\tsamples = sam.ADC_AVGCTRL_SAMPLENUM_1\n\tcase 2:\n\t\tsamples = sam.ADC_AVGCTRL_SAMPLENUM_2\n\tcase 4:\n\t\tsamples = sam.ADC_AVGCTRL_SAMPLENUM_4\n\tcase 8:\n\t\tsamples = sam.ADC_AVGCTRL_SAMPLENUM_8\n\tcase 16:\n\t\tsamples = sam.ADC_AVGCTRL_SAMPLENUM_16\n\tcase 32:\n\t\tsamples = sam.ADC_AVGCTRL_SAMPLENUM_32\n\tcase 64:\n\t\tsamples = sam.ADC_AVGCTRL_SAMPLENUM_64\n\tcase 128:\n\t\tsamples = sam.ADC_AVGCTRL_SAMPLENUM_128\n\tcase 256:\n\t\tsamples = sam.ADC_AVGCTRL_SAMPLENUM_256\n\tcase 512:\n\t\tsamples = sam.ADC_AVGCTRL_SAMPLENUM_512\n\tcase 1024:\n\t\tsamples = sam.ADC_AVGCTRL_SAMPLENUM_1024\n\tdefault:\n\t\tsamples = sam.ADC_AVGCTRL_SAMPLENUM_1\n\t}\n\tsam.ADC.AVGCTRL.Set(uint8(samples<<sam.ADC_AVGCTRL_SAMPLENUM_Pos) |\n\t\t(0x0 << sam.ADC_AVGCTRL_ADJRES_Pos))\n\n\t// TODO: use config.Reference to set AREF level\n\n\t// Analog Reference is AREF pin (3.3v)\n\tsam.ADC.INPUTCTRL.SetBits(sam.ADC_INPUTCTRL_GAIN_DIV2 << sam.ADC_INPUTCTRL_GAIN_Pos)\n\n\t// 1/2 VDDANA = 0.5 * 3V3 = 1.65V\n\tsam.ADC.REFCTRL.SetBits(sam.ADC_REFCTRL_REFSEL_INTVCC1 << sam.ADC_REFCTRL_REFSEL_Pos)\n\n\ta.Pin.Configure(PinConfig{Mode: PinAnalog})\n\treturn\n}\n\n// Get returns the current value of a ADC pin, in the range 0..0xffff.\nfunc (a ADC) Get() uint16 {\n\tch := a.getADCChannel()\n\n\t// Selection for the positive ADC input\n\tsam.ADC.INPUTCTRL.ClearBits(sam.ADC_INPUTCTRL_MUXPOS_Msk)\n\twaitADCSync()\n\tsam.ADC.INPUTCTRL.SetBits(uint32(ch << sam.ADC_INPUTCTRL_MUXPOS_Pos))\n\twaitADCSync()\n\n\t// Select internal ground for ADC input\n\tsam.ADC.INPUTCTRL.ClearBits(sam.ADC_INPUTCTRL_MUXNEG_Msk)\n\twaitADCSync()\n\tsam.ADC.INPUTCTRL.SetBits(sam.ADC_INPUTCTRL_MUXNEG_GND << sam.ADC_INPUTCTRL_MUXNEG_Pos)\n\twaitADCSync()\n\n\t// Enable ADC\n\tsam.ADC.CTRLA.SetBits(sam.ADC_CTRLA_ENABLE)\n\twaitADCSync()\n\n\t// Start conversion\n\tsam.ADC.SWTRIG.SetBits(sam.ADC_SWTRIG_START)\n\twaitADCSync()\n\n\t// wait for first conversion to finish to fix same issue as\n\t// https://github.com/arduino/ArduinoCore-samd/issues/446\n\tfor !sam.ADC.INTFLAG.HasBits(sam.ADC_INTFLAG_RESRDY) {\n\t}\n\n\t// Clear the Data Ready flag\n\tsam.ADC.INTFLAG.SetBits(sam.ADC_INTFLAG_RESRDY)\n\twaitADCSync()\n\n\t// Start conversion again, since first conversion after reference voltage changed is invalid.\n\tsam.ADC.SWTRIG.SetBits(sam.ADC_SWTRIG_START)\n\twaitADCSync()\n\n\t// Waiting for conversion to complete\n\tfor !sam.ADC.INTFLAG.HasBits(sam.ADC_INTFLAG_RESRDY) {\n\t}\n\tval := sam.ADC.RESULT.Get()\n\n\t// Disable ADC\n\tsam.ADC.CTRLA.ClearBits(sam.ADC_CTRLA_ENABLE)\n\twaitADCSync()\n\n\t// scales to 16-bit result\n\tswitch (sam.ADC.CTRLB.Get() & sam.ADC_CTRLB_RESSEL_Msk) >> sam.ADC_CTRLB_RESSEL_Pos {\n\tcase sam.ADC_CTRLB_RESSEL_8BIT:\n\t\tval = val << 8\n\tcase sam.ADC_CTRLB_RESSEL_10BIT:\n\t\tval = val << 6\n\tcase sam.ADC_CTRLB_RESSEL_16BIT:\n\t\tval = val << 4\n\tcase sam.ADC_CTRLB_RESSEL_12BIT:\n\t\tval = val << 4\n\t}\n\treturn val\n}\n\nfunc (a ADC) getADCChannel() uint8 {\n\tswitch a.Pin {\n\tcase PA02:\n\t\treturn 0\n\tcase PA03:\n\t\treturn 1\n\tcase PB04:\n\t\treturn 12\n\tcase PB05:\n\t\treturn 13\n\tcase PB06:\n\t\treturn 14\n\tcase PB07:\n\t\treturn 15\n\tcase PB08:\n\t\treturn 2\n\tcase PB09:\n\t\treturn 3\n\tcase PA04:\n\t\treturn 4\n\tcase PA05:\n\t\treturn 5\n\tcase PA06:\n\t\treturn 6\n\tcase PA07:\n\t\treturn 7\n\tcase PA08:\n\t\treturn 16\n\tcase PA09:\n\t\treturn 17\n\tcase PA10:\n\t\treturn 18\n\tcase PA11:\n\t\treturn 19\n\tcase PB00:\n\t\treturn 8\n\tcase PB01:\n\t\treturn 9\n\tcase PB02:\n\t\treturn 10\n\tcase PB03:\n\t\treturn 11\n\tdefault:\n\t\treturn 0\n\t}\n}\n\nfunc waitADCSync() {\n\tfor sam.ADC.STATUS.HasBits(sam.ADC_STATUS_SYNCBUSY) {\n\t}\n}\n\n// UART on the SAMD21.\ntype UART struct {\n\tBuffer    *RingBuffer\n\tBus       *sam.SERCOM_USART_Type\n\tSERCOM    uint8\n\tInterrupt interrupt.Interrupt\n}\n\nconst (\n\tsampleRate16X = 16\n\tlsbFirst      = 1\n)\n\n// Configure the UART.\nfunc (uart *UART) Configure(config UARTConfig) error {\n\t// Default baud rate to 115200.\n\tif config.BaudRate == 0 {\n\t\tconfig.BaudRate = 115200\n\t}\n\n\t// Use default pins if pins are not set.\n\tif config.TX == 0 && config.RX == 0 {\n\t\t// use default pins\n\t\tconfig.TX = UART_TX_PIN\n\t\tconfig.RX = UART_RX_PIN\n\t}\n\n\t// Determine transmit pinout.\n\ttxPinMode, txPad, ok := findPinPadMapping(uart.SERCOM, config.TX)\n\tif !ok {\n\t\treturn ErrInvalidOutputPin\n\t}\n\tvar txPadOut uint32\n\t// See table 25-9 of the datasheet (page 459) for how pads are mapped to\n\t// pinout values.\n\tswitch txPad {\n\tcase 0:\n\t\ttxPadOut = 0\n\tcase 2:\n\t\ttxPadOut = 1\n\tdefault:\n\t\t// this should be a flow control (RTS/CTS) pin\n\t\treturn ErrInvalidOutputPin\n\t}\n\n\t// Determine receive pinout.\n\trxPinMode, rxPad, ok := findPinPadMapping(uart.SERCOM, config.RX)\n\tif !ok {\n\t\treturn ErrInvalidInputPin\n\t}\n\t// As you can see in table 25-8 on page 459 of the datasheet, input pins\n\t// are mapped directly.\n\trxPadOut := rxPad\n\n\t// configure pins\n\tconfig.TX.Configure(PinConfig{Mode: txPinMode})\n\tconfig.RX.Configure(PinConfig{Mode: rxPinMode})\n\n\t// configure RTS/CTS pins if provided\n\tif config.RTS != 0 && config.CTS != 0 {\n\t\trtsPinMode, _, ok := findPinPadMapping(uart.SERCOM, config.RTS)\n\t\tif !ok {\n\t\t\treturn ErrInvalidOutputPin\n\t\t}\n\n\t\tctsPinMode, _, ok := findPinPadMapping(uart.SERCOM, config.CTS)\n\t\tif !ok {\n\t\t\treturn ErrInvalidInputPin\n\t\t}\n\n\t\t// See table 25-9 of the datasheet (page 459) for how pads are mapped to\n\t\t// pinout values.\n\t\tif txPadOut == 1 {\n\t\t\treturn ErrInvalidOutputPin\n\t\t}\n\t\ttxPadOut = 2\n\n\t\tconfig.RTS.Configure(PinConfig{Mode: rtsPinMode})\n\t\tconfig.CTS.Configure(PinConfig{Mode: ctsPinMode})\n\t}\n\n\t// reset SERCOM0\n\tuart.Bus.CTRLA.SetBits(sam.SERCOM_USART_CTRLA_SWRST)\n\tfor uart.Bus.CTRLA.HasBits(sam.SERCOM_USART_CTRLA_SWRST) ||\n\t\tuart.Bus.SYNCBUSY.HasBits(sam.SERCOM_USART_SYNCBUSY_SWRST) {\n\t}\n\n\t// set UART mode/sample rate\n\t// SERCOM_USART_CTRLA_MODE(mode) |\n\t// SERCOM_USART_CTRLA_SAMPR(sampleRate);\n\tuart.Bus.CTRLA.Set((sam.SERCOM_USART_CTRLA_MODE_USART_INT_CLK << sam.SERCOM_USART_CTRLA_MODE_Pos) |\n\t\t(1 << sam.SERCOM_USART_CTRLA_SAMPR_Pos)) // sample rate of 16x\n\n\t// Set baud rate\n\tuart.SetBaudRate(config.BaudRate)\n\n\t// setup UART frame\n\t// SERCOM_USART_CTRLA_FORM( (parityMode == SERCOM_NO_PARITY ? 0 : 1) ) |\n\t// dataOrder << SERCOM_USART_CTRLA_DORD_Pos;\n\tuart.Bus.CTRLA.SetBits((0 << sam.SERCOM_USART_CTRLA_FORM_Pos) | // no parity\n\t\t(lsbFirst << sam.SERCOM_USART_CTRLA_DORD_Pos)) // data order\n\n\t// set UART stop bits/parity\n\t// SERCOM_USART_CTRLB_CHSIZE(charSize) |\n\t// \tnbStopBits << SERCOM_USART_CTRLB_SBMODE_Pos |\n\t// \t(parityMode == SERCOM_NO_PARITY ? 0 : parityMode) << SERCOM_USART_CTRLB_PMODE_Pos; //If no parity use default value\n\tuart.Bus.CTRLB.SetBits((0 << sam.SERCOM_USART_CTRLB_CHSIZE_Pos) | // 8 bits is 0\n\t\t(0 << sam.SERCOM_USART_CTRLB_SBMODE_Pos) | // 1 stop bit is zero\n\t\t(0 << sam.SERCOM_USART_CTRLB_PMODE_Pos)) // no parity\n\n\t// set UART pads. This is not same as pins...\n\t//  SERCOM_USART_CTRLA_TXPO(txPad) |\n\t//   SERCOM_USART_CTRLA_RXPO(rxPad);\n\tuart.Bus.CTRLA.SetBits((txPadOut << sam.SERCOM_USART_CTRLA_TXPO_Pos) |\n\t\t(rxPadOut << sam.SERCOM_USART_CTRLA_RXPO_Pos))\n\n\t// Enable Transceiver and Receiver\n\t//sercom->USART.CTRLB.reg |= SERCOM_USART_CTRLB_TXEN | SERCOM_USART_CTRLB_RXEN ;\n\tuart.Bus.CTRLB.SetBits(sam.SERCOM_USART_CTRLB_TXEN | sam.SERCOM_USART_CTRLB_RXEN)\n\n\t// Enable USART1 port.\n\t// sercom->USART.CTRLA.bit.ENABLE = 0x1u;\n\tuart.Bus.CTRLA.SetBits(sam.SERCOM_USART_CTRLA_ENABLE)\n\tfor uart.Bus.SYNCBUSY.HasBits(sam.SERCOM_USART_SYNCBUSY_ENABLE) {\n\t}\n\n\t// setup interrupt on receive\n\tuart.Bus.INTENSET.Set(sam.SERCOM_USART_INTENSET_RXC)\n\n\t// Enable RX IRQ.\n\tuart.Interrupt.Enable()\n\n\treturn nil\n}\n\n// SetBaudRate sets the communication speed for the UART.\nfunc (uart *UART) SetBaudRate(br uint32) {\n\t// Asynchronous fractional mode (Table 24-2 in datasheet)\n\t//   BAUD = fref / (sampleRateValue * fbaud)\n\t// (multiply by 8, to calculate fractional piece)\n\t// uint32_t baudTimes8 = (SystemCoreClock * 8) / (16 * baudrate);\n\tbaud := (CPUFrequency() * 8) / (sampleRate16X * br)\n\n\t// sercom->USART.BAUD.FRAC.FP   = (baudTimes8 % 8);\n\t// sercom->USART.BAUD.FRAC.BAUD = (baudTimes8 / 8);\n\tuart.Bus.BAUD.Set(uint16(((baud % 8) << sam.SERCOM_USART_BAUD_FRAC_MODE_FP_Pos) |\n\t\t((baud / 8) << sam.SERCOM_USART_BAUD_FRAC_MODE_BAUD_Pos)))\n}\n\n// WriteByte writes a byte of data to the UART.\nfunc (uart *UART) writeByte(c byte) error {\n\t// wait until ready to receive\n\tfor !uart.Bus.INTFLAG.HasBits(sam.SERCOM_USART_INTFLAG_DRE) {\n\t}\n\tuart.Bus.DATA.Set(uint16(c))\n\treturn nil\n}\n\nfunc (uart *UART) flush() {}\n\n// handleInterrupt should be called from the appropriate interrupt handler for\n// this UART instance.\nfunc (uart *UART) handleInterrupt(interrupt.Interrupt) {\n\t// should reset IRQ\n\tuart.Receive(byte((uart.Bus.DATA.Get() & 0xFF)))\n\tuart.Bus.INTFLAG.SetBits(sam.SERCOM_USART_INTFLAG_RXC)\n}\n\n// I2C on the SAMD21.\ntype I2C struct {\n\tBus    *sam.SERCOM_I2CM_Type\n\tSERCOM uint8\n}\n\n// I2CConfig is used to store config info for I2C.\ntype I2CConfig struct {\n\tFrequency uint32\n\tSCL       Pin\n\tSDA       Pin\n}\n\nconst (\n\t// Default rise time in nanoseconds, based on 4.7K ohm pull up resistors\n\triseTimeNanoseconds = 125\n\n\t// wire bus states\n\twireUnknownState = 0\n\twireIdleState    = 1\n\twireOwnerState   = 2\n\twireBusyState    = 3\n\n\t// wire commands\n\twireCmdNoAction    = 0\n\twireCmdRepeatStart = 1\n\twireCmdRead        = 2\n\twireCmdStop        = 3\n)\n\nconst i2cTimeout = 1000\n\n// Configure is intended to setup the I2C interface.\nfunc (i2c *I2C) Configure(config I2CConfig) error {\n\t// Default I2C bus speed is 100 kHz.\n\tif config.Frequency == 0 {\n\t\tconfig.Frequency = 100 * KHz\n\t}\n\tif config.SDA == 0 && config.SCL == 0 {\n\t\tconfig.SDA = SDA_PIN\n\t\tconfig.SCL = SCL_PIN\n\t}\n\n\tsclPinMode, sclPad, ok := findPinPadMapping(i2c.SERCOM, config.SCL)\n\tif !ok || sclPad != 1 {\n\t\t// SCL must be on pad 1, according to section 27.5 of the datasheet.\n\t\t// Note: this is not an exhaustive test for I2C support on the pin: not\n\t\t// all pins support I2C.\n\t\treturn ErrInvalidClockPin\n\t}\n\tsdaPinMode, sdaPad, ok := findPinPadMapping(i2c.SERCOM, config.SDA)\n\tif !ok || sdaPad != 0 {\n\t\t// SDA must be on pad 0, according to section 27.5 of the datasheet.\n\t\t// Note: this is not an exhaustive test for I2C support on the pin: not\n\t\t// all pins support I2C.\n\t\treturn ErrInvalidDataPin\n\t}\n\n\t// reset SERCOM\n\ti2c.Bus.CTRLA.SetBits(sam.SERCOM_I2CM_CTRLA_SWRST)\n\tfor i2c.Bus.CTRLA.HasBits(sam.SERCOM_I2CM_CTRLA_SWRST) ||\n\t\ti2c.Bus.SYNCBUSY.HasBits(sam.SERCOM_I2CM_SYNCBUSY_SWRST) {\n\t}\n\n\t// Set i2c controller mode\n\t//SERCOM_I2CM_CTRLA_MODE( I2C_MASTER_OPERATION )\n\ti2c.Bus.CTRLA.Set(sam.SERCOM_I2CM_CTRLA_MODE_I2C_MASTER << sam.SERCOM_I2CM_CTRLA_MODE_Pos) // |\n\n\ti2c.SetBaudRate(config.Frequency)\n\n\t// Enable I2CM port.\n\t// sercom->USART.CTRLA.bit.ENABLE = 0x1u;\n\ti2c.Bus.CTRLA.SetBits(sam.SERCOM_I2CM_CTRLA_ENABLE)\n\tfor i2c.Bus.SYNCBUSY.HasBits(sam.SERCOM_I2CM_SYNCBUSY_ENABLE) {\n\t}\n\n\t// set bus idle mode\n\ti2c.Bus.STATUS.SetBits(wireIdleState << sam.SERCOM_I2CM_STATUS_BUSSTATE_Pos)\n\tfor i2c.Bus.SYNCBUSY.HasBits(sam.SERCOM_I2CM_SYNCBUSY_SYSOP) {\n\t}\n\n\t// enable pins\n\tconfig.SDA.Configure(PinConfig{Mode: sdaPinMode})\n\tconfig.SCL.Configure(PinConfig{Mode: sclPinMode})\n\n\treturn nil\n}\n\n// SetBaudRate sets the communication speed for I2C.\nfunc (i2c *I2C) SetBaudRate(br uint32) error {\n\t// Synchronous arithmetic baudrate, via Arduino SAMD implementation:\n\t// SystemCoreClock / ( 2 * baudrate) - 5 - (((SystemCoreClock / 1000000) * WIRE_RISE_TIME_NANOSECONDS) / (2 * 1000));\n\tbaud := CPUFrequency()/(2*br) - 5 - (((CPUFrequency() / 1000000) * riseTimeNanoseconds) / (2 * 1000))\n\ti2c.Bus.BAUD.Set(baud)\n\treturn nil\n}\n\n// Tx does a single I2C transaction at the specified address.\n// It clocks out the given address, writes the bytes in w, reads back len(r)\n// bytes and stores them in r, and generates a stop condition on the bus.\nfunc (i2c *I2C) Tx(addr uint16, w, r []byte) error {\n\tvar err error\n\tif len(w) != 0 {\n\t\t// send start/address for write\n\t\ti2c.sendAddress(addr, true)\n\n\t\t// wait until transmission complete\n\t\ttimeout := i2cTimeout\n\t\tfor !i2c.Bus.INTFLAG.HasBits(sam.SERCOM_I2CM_INTFLAG_MB) {\n\t\t\ttimeout--\n\t\t\tif timeout == 0 {\n\t\t\t\treturn errI2CWriteTimeout\n\t\t\t}\n\t\t}\n\n\t\t// ACK received (0: ACK, 1: NACK)\n\t\tif i2c.Bus.STATUS.HasBits(sam.SERCOM_I2CM_STATUS_RXNACK) {\n\t\t\treturn errI2CAckExpected\n\t\t}\n\n\t\t// write data\n\t\tfor _, b := range w {\n\t\t\terr = i2c.WriteByte(b)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\n\t\terr = i2c.signalStop()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tif len(r) != 0 {\n\t\t// send start/address for read\n\t\ti2c.sendAddress(addr, false)\n\n\t\t// wait transmission complete\n\t\tfor !i2c.Bus.INTFLAG.HasBits(sam.SERCOM_I2CM_INTFLAG_SB) {\n\t\t\t// If the peripheral NACKS the address, the MB bit will be set.\n\t\t\t// In that case, send a stop condition and return error.\n\t\t\tif i2c.Bus.INTFLAG.HasBits(sam.SERCOM_I2CM_INTFLAG_MB) {\n\t\t\t\ti2c.Bus.CTRLB.SetBits(wireCmdStop << sam.SERCOM_I2CM_CTRLB_CMD_Pos) // Stop condition\n\t\t\t\treturn errI2CAckExpected\n\t\t\t}\n\t\t}\n\n\t\t// ACK received (0: ACK, 1: NACK)\n\t\tif i2c.Bus.STATUS.HasBits(sam.SERCOM_I2CM_STATUS_RXNACK) {\n\t\t\treturn errI2CAckExpected\n\t\t}\n\n\t\t// read first byte\n\t\tr[0] = i2c.readByte()\n\t\tfor i := 1; i < len(r); i++ {\n\t\t\t// Send an ACK\n\t\t\ti2c.Bus.CTRLB.ClearBits(sam.SERCOM_I2CM_CTRLB_ACKACT)\n\n\t\t\ti2c.signalRead()\n\n\t\t\t// Read data and send the ACK\n\t\t\tr[i] = i2c.readByte()\n\t\t}\n\n\t\t// Send NACK to end transmission\n\t\ti2c.Bus.CTRLB.SetBits(sam.SERCOM_I2CM_CTRLB_ACKACT)\n\n\t\terr = i2c.signalStop()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// WriteByte writes a single byte to the I2C bus.\nfunc (i2c *I2C) WriteByte(data byte) error {\n\t// Send data byte\n\ti2c.Bus.DATA.Set(data)\n\n\t// wait until transmission successful\n\ttimeout := i2cTimeout\n\tfor !i2c.Bus.INTFLAG.HasBits(sam.SERCOM_I2CM_INTFLAG_MB) {\n\t\t// check for bus error\n\t\tif sam.SERCOM3_I2CM.STATUS.HasBits(sam.SERCOM_I2CM_STATUS_BUSERR) {\n\t\t\treturn errI2CBusError\n\t\t}\n\t\ttimeout--\n\t\tif timeout == 0 {\n\t\t\treturn errI2CWriteTimeout\n\t\t}\n\t}\n\n\tif i2c.Bus.STATUS.HasBits(sam.SERCOM_I2CM_STATUS_RXNACK) {\n\t\treturn errI2CAckExpected\n\t}\n\n\treturn nil\n}\n\n// sendAddress sends the address and start signal\nfunc (i2c *I2C) sendAddress(address uint16, write bool) error {\n\tdata := (address << 1)\n\tif !write {\n\t\tdata |= 1 // set read flag\n\t}\n\n\t// wait until bus ready\n\ttimeout := i2cTimeout\n\tfor !i2c.Bus.STATUS.HasBits(wireIdleState<<sam.SERCOM_I2CM_STATUS_BUSSTATE_Pos) &&\n\t\t!i2c.Bus.STATUS.HasBits(wireOwnerState<<sam.SERCOM_I2CM_STATUS_BUSSTATE_Pos) {\n\t\ttimeout--\n\t\tif timeout == 0 {\n\t\t\treturn errI2CBusReadyTimeout\n\t\t}\n\t}\n\ti2c.Bus.ADDR.Set(uint32(data))\n\n\treturn nil\n}\n\nfunc (i2c *I2C) signalStop() error {\n\ti2c.Bus.CTRLB.SetBits(wireCmdStop << sam.SERCOM_I2CM_CTRLB_CMD_Pos) // Stop command\n\ttimeout := i2cTimeout\n\tfor i2c.Bus.SYNCBUSY.HasBits(sam.SERCOM_I2CM_SYNCBUSY_SYSOP) {\n\t\ttimeout--\n\t\tif timeout == 0 {\n\t\t\treturn errI2CSignalStopTimeout\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (i2c *I2C) signalRead() error {\n\ti2c.Bus.CTRLB.SetBits(wireCmdRead << sam.SERCOM_I2CM_CTRLB_CMD_Pos) // Read command\n\ttimeout := i2cTimeout\n\tfor i2c.Bus.SYNCBUSY.HasBits(sam.SERCOM_I2CM_SYNCBUSY_SYSOP) {\n\t\ttimeout--\n\t\tif timeout == 0 {\n\t\t\treturn errI2CSignalReadTimeout\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (i2c *I2C) readByte() byte {\n\tfor !i2c.Bus.INTFLAG.HasBits(sam.SERCOM_I2CM_INTFLAG_SB) {\n\t}\n\treturn byte(i2c.Bus.DATA.Get())\n}\n\n// I2S on the SAMD21.\n\n// I2S\ntype I2S struct {\n\tBus        *sam.I2S_Type\n\tFrequency  uint32\n\tDataFormat I2SDataFormat\n}\n\nvar I2S0 = I2S{Bus: sam.I2S}\n\n// Configure is used to configure the I2S interface. You must call this\n// before you can use the I2S bus.\nfunc (i2s *I2S) Configure(config I2SConfig) error {\n\t// handle defaults\n\tif config.SCK == 0 {\n\t\tconfig.SCK = I2S_SCK_PIN\n\t\tconfig.WS = I2S_WS_PIN\n\t\tconfig.SDO = I2S_SDO_PIN\n\t\tconfig.SDI = I2S_SDI_PIN\n\t}\n\n\tif config.AudioFrequency == 0 {\n\t\tconfig.AudioFrequency = 44100\n\t}\n\n\tif config.DataFormat == I2SDataFormatDefault {\n\t\tif config.Stereo {\n\t\t\tconfig.DataFormat = I2SDataFormat16bit\n\t\t} else {\n\t\t\tconfig.DataFormat = I2SDataFormat32bit\n\t\t}\n\t}\n\ti2s.DataFormat = config.DataFormat\n\n\t// Turn on clock for I2S\n\tsam.PM.APBCMASK.SetBits(sam.PM_APBCMASK_I2S_)\n\n\tif err := i2s.SetSampleFrequency(config.AudioFrequency); err != nil {\n\t\treturn err\n\t}\n\n\t// disable device before continuing\n\ti2s.Enable(false)\n\n\t// setup clock\n\tif config.ClockSource == I2SClockSourceInternal {\n\t\t// TODO: make sure correct for I2S output\n\n\t\t// set serial clock select pin\n\t\ti2s.Bus.CLKCTRL0.SetBits(sam.I2S_CLKCTRL_SCKSEL)\n\n\t\t// set frame select pin\n\t\ti2s.Bus.CLKCTRL0.SetBits(sam.I2S_CLKCTRL_FSSEL)\n\t} else {\n\t\t// Configure FS generation from SCK clock.\n\t\ti2s.Bus.CLKCTRL0.ClearBits(sam.I2S_CLKCTRL_FSSEL)\n\t}\n\n\tif config.Standard == I2StandardPhilips {\n\t\t// set 1-bit delay\n\t\ti2s.Bus.CLKCTRL0.SetBits(sam.I2S_CLKCTRL_BITDELAY)\n\t} else {\n\t\t// set 0-bit delay\n\t\ti2s.Bus.CLKCTRL0.ClearBits(sam.I2S_CLKCTRL_BITDELAY)\n\t}\n\n\t// set number of slots.\n\tif config.Stereo {\n\t\ti2s.Bus.CLKCTRL0.SetBits(1 << sam.I2S_CLKCTRL_NBSLOTS_Pos)\n\t} else {\n\t\ti2s.Bus.CLKCTRL0.ClearBits(1 << sam.I2S_CLKCTRL_NBSLOTS_Pos)\n\t}\n\n\t// set slot size\n\tswitch config.DataFormat {\n\tcase I2SDataFormat8bit:\n\t\ti2s.Bus.CLKCTRL0.SetBits(sam.I2S_CLKCTRL_SLOTSIZE_8)\n\n\tcase I2SDataFormat16bit:\n\t\ti2s.Bus.CLKCTRL0.SetBits(sam.I2S_CLKCTRL_SLOTSIZE_16)\n\n\tcase I2SDataFormat24bit:\n\t\ti2s.Bus.CLKCTRL0.SetBits(sam.I2S_CLKCTRL_SLOTSIZE_24)\n\n\tcase I2SDataFormat32bit:\n\t\ti2s.Bus.CLKCTRL0.SetBits(sam.I2S_CLKCTRL_SLOTSIZE_32)\n\t}\n\n\t// configure pin for clock\n\tconfig.SCK.Configure(PinConfig{Mode: PinCom})\n\n\t// configure pin for WS, if needed\n\tif config.WS != NoPin {\n\t\tconfig.WS.Configure(PinConfig{Mode: PinCom})\n\t}\n\n\t// now set serializer data size.\n\tswitch config.DataFormat {\n\tcase I2SDataFormat8bit:\n\t\ti2s.Bus.SERCTRL1.SetBits(sam.I2S_SERCTRL_DATASIZE_8 << sam.I2S_SERCTRL_DATASIZE_Pos)\n\n\tcase I2SDataFormat16bit:\n\t\ti2s.Bus.SERCTRL1.SetBits(sam.I2S_SERCTRL_DATASIZE_16 << sam.I2S_SERCTRL_DATASIZE_Pos)\n\n\tcase I2SDataFormat24bit:\n\t\ti2s.Bus.SERCTRL1.SetBits(sam.I2S_SERCTRL_DATASIZE_24 << sam.I2S_SERCTRL_DATASIZE_Pos)\n\n\tcase I2SDataFormat32bit:\n\tcase I2SDataFormatDefault:\n\t\ti2s.Bus.SERCTRL1.SetBits(sam.I2S_SERCTRL_DATASIZE_32 << sam.I2S_SERCTRL_DATASIZE_Pos)\n\t}\n\n\t// set serializer slot adjustment\n\tif config.Standard == I2SStandardLSB {\n\t\t// adjust right\n\t\ti2s.Bus.SERCTRL1.ClearBits(sam.I2S_SERCTRL_SLOTADJ)\n\n\t\t// transfer LSB first\n\t\ti2s.Bus.SERCTRL1.SetBits(sam.I2S_SERCTRL_BITREV)\n\t} else {\n\t\t// adjust left\n\t\ti2s.Bus.SERCTRL1.SetBits(sam.I2S_SERCTRL_SLOTADJ)\n\t}\n\n\t// set serializer mode.\n\tswitch config.Mode {\n\tcase I2SModePDM:\n\t\ti2s.Bus.SERCTRL1.SetBits(sam.I2S_SERCTRL_SERMODE_PDM2)\n\tcase I2SModeSource:\n\t\ti2s.Bus.SERCTRL1.SetBits(sam.I2S_SERCTRL_SERMODE_TX)\n\tcase I2SModeReceiver:\n\t\ti2s.Bus.SERCTRL1.SetBits(sam.I2S_SERCTRL_SERMODE_RX)\n\t}\n\n\t// configure data pins\n\tif config.SDO != NoPin {\n\t\tconfig.SDO.Configure(PinConfig{Mode: PinCom})\n\t}\n\tif config.SDI != NoPin {\n\t\tconfig.SDI.Configure(PinConfig{Mode: PinCom})\n\t}\n\n\t// re-enable\n\ti2s.Enable(true)\n\n\t// enable i2s clock\n\ti2s.Bus.CTRLA.SetBits(sam.I2S_CTRLA_CKEN0)\n\tfor i2s.Bus.SYNCBUSY.HasBits(sam.I2S_SYNCBUSY_CKEN0) {\n\t}\n\n\t// enable i2s serializer\n\ti2s.Bus.CTRLA.SetBits(sam.I2S_CTRLA_SEREN1)\n\tfor i2s.Bus.SYNCBUSY.HasBits(sam.I2S_SYNCBUSY_SEREN1) {\n\t}\n\n\treturn nil\n}\n\n// Read mono data from the I2S bus into the provided slice.\n// The I2S bus must already have been configured correctly.\nfunc (i2s *I2S) ReadMono(p []uint16) (n int, err error) {\n\treturn i2sRead(i2s, p)\n}\n\n// Read stereo data from the I2S bus into the provided slice.\n// The I2S bus must already have been configured correctly.\nfunc (i2s *I2S) ReadStereo(p []uint32) (n int, err error) {\n\treturn i2sRead(i2s, p)\n}\n\nfunc i2sRead[T uint16 | uint32](i2s *I2S, p []T) (int, error) {\n\ti := 0\n\tfor i = 0; i < len(p); i++ {\n\t\t// Wait until ready\n\t\tfor !i2s.Bus.INTFLAG.HasBits(sam.I2S_INTFLAG_RXRDY1) {\n\t\t}\n\n\t\tfor i2s.Bus.SYNCBUSY.HasBits(sam.I2S_SYNCBUSY_DATA1) {\n\t\t}\n\n\t\t// read data\n\t\tp[i] = T(i2s.Bus.DATA1.Get())\n\n\t\t// indicate read complete\n\t\ti2s.Bus.INTFLAG.Set(sam.I2S_INTFLAG_RXRDY1)\n\t}\n\n\treturn i, nil\n}\n\n// Write mono data to the I2S bus from the provided slice.\n// The I2S bus must already have been configured correctly.\nfunc (i2s *I2S) WriteMono(p []uint16) (n int, err error) {\n\treturn i2sWrite(i2s, p)\n}\n\n// Write stereo data to the I2S bus from the provided slice.\n// The I2S bus must already have been configured correctly.\nfunc (i2s *I2S) WriteStereo(p []uint32) (n int, err error) {\n\treturn i2sWrite(i2s, p)\n}\n\nfunc i2sWrite[T uint16 | uint32](i2s *I2S, p []T) (int, error) {\n\ti := 0\n\tfor i = 0; i < len(p); i++ {\n\t\t// Wait until ready\n\t\tfor !i2s.Bus.INTFLAG.HasBits(sam.I2S_INTFLAG_TXRDY1) {\n\t\t}\n\n\t\tfor i2s.Bus.SYNCBUSY.HasBits(sam.I2S_SYNCBUSY_DATA1) {\n\t\t}\n\n\t\t// write data\n\t\ti2s.Bus.DATA1.Set(uint32(p[i]))\n\n\t\t// indicate write complete\n\t\ti2s.Bus.INTFLAG.Set(sam.I2S_INTFLAG_TXRDY1)\n\t}\n\n\treturn i, nil\n}\n\n// SetSampleFrequency is used to set the sample frequency for the I2S bus.\nfunc (i2s *I2S) SetSampleFrequency(freq uint32) error {\n\tif freq == 0 {\n\t\treturn ErrInvalidSampleFrequency\n\t}\n\n\tif i2s.Frequency == freq {\n\t\treturn nil\n\t}\n\n\ti2s.Frequency = freq\n\n\t// setting clock rate for sample.\n\tdivision_factor := CPUFrequency() / (i2s.Frequency * uint32(i2s.DataFormat))\n\n\t// Switch Generic Clock Generator 3 to DFLL48M.\n\tsam.GCLK.GENDIV.Set((sam.GCLK_CLKCTRL_GEN_GCLK3 << sam.GCLK_GENDIV_ID_Pos) |\n\t\t(division_factor << sam.GCLK_GENDIV_DIV_Pos))\n\twaitForSync()\n\n\tsam.GCLK.GENCTRL.Set((sam.GCLK_CLKCTRL_GEN_GCLK3 << sam.GCLK_GENCTRL_ID_Pos) |\n\t\t(sam.GCLK_GENCTRL_SRC_DFLL48M << sam.GCLK_GENCTRL_SRC_Pos) |\n\t\tsam.GCLK_GENCTRL_IDC |\n\t\tsam.GCLK_GENCTRL_GENEN)\n\twaitForSync()\n\n\t// Use Generic Clock Generator 3 as source for I2S.\n\tsam.GCLK.CLKCTRL.Set((sam.GCLK_CLKCTRL_ID_I2S_0 << sam.GCLK_CLKCTRL_ID_Pos) |\n\t\t(sam.GCLK_CLKCTRL_GEN_GCLK3 << sam.GCLK_CLKCTRL_GEN_Pos) |\n\t\tsam.GCLK_CLKCTRL_CLKEN)\n\twaitForSync()\n\n\t// reset the device\n\ti2s.Bus.CTRLA.SetBits(sam.I2S_CTRLA_SWRST)\n\tfor i2s.Bus.SYNCBUSY.HasBits(sam.I2S_SYNCBUSY_SWRST) {\n\t}\n\n\treturn nil\n}\n\n// Enabled is used to enable or disable the I2S bus.\nfunc (i2s *I2S) Enable(enabled bool) {\n\tif enabled {\n\t\ti2s.Bus.CTRLA.SetBits(sam.I2S_CTRLA_ENABLE)\n\t\tfor i2s.Bus.SYNCBUSY.HasBits(sam.I2S_SYNCBUSY_ENABLE) {\n\t\t}\n\n\t\treturn\n\t}\n\n\t// disable\n\tfor i2s.Bus.SYNCBUSY.HasBits(sam.I2S_SYNCBUSY_ENABLE) {\n\t}\n\ti2s.Bus.CTRLA.ClearBits(sam.I2S_CTRLA_ENABLE)\n\n\treturn\n}\n\nfunc waitForSync() {\n\tfor sam.GCLK.STATUS.HasBits(sam.GCLK_STATUS_SYNCBUSY) {\n\t}\n}\n\n// SPI\ntype SPI struct {\n\tBus    *sam.SERCOM_SPI_Type\n\tSERCOM uint8\n}\n\n// SPIConfig is used to store config info for SPI.\ntype SPIConfig struct {\n\tFrequency uint32\n\tSCK       Pin\n\tSDO       Pin\n\tSDI       Pin\n\tLSBFirst  bool\n\tMode      uint8\n}\n\n// Configure is intended to setup the SPI interface.\nfunc (spi *SPI) Configure(config SPIConfig) error {\n\t// Use default pins if not set.\n\tif config.SCK == 0 && config.SDO == 0 && config.SDI == 0 {\n\t\tconfig.SCK = SPI0_SCK_PIN\n\t\tconfig.SDO = SPI0_SDO_PIN\n\t\tconfig.SDI = SPI0_SDI_PIN\n\t}\n\n\t// set default frequency\n\tif config.Frequency == 0 {\n\t\tconfig.Frequency = 4000000\n\t}\n\n\t// Determine the input pinout (for SDI).\n\tSDIPinMode, SDIPad, ok := findPinPadMapping(spi.SERCOM, config.SDI)\n\tif !ok {\n\t\treturn ErrInvalidInputPin\n\t}\n\tdataInPinout := SDIPad // mapped directly\n\n\t// Determine the output pinout (for SDO/SCK).\n\t// See table 26-7 on page 494 of the datasheet.\n\tvar dataOutPinout uint32\n\tsckPinMode, sckPad, ok := findPinPadMapping(spi.SERCOM, config.SCK)\n\tif !ok {\n\t\treturn ErrInvalidOutputPin\n\t}\n\tSDOPinMode, SDOPad, ok := findPinPadMapping(spi.SERCOM, config.SDO)\n\tif !ok {\n\t\treturn ErrInvalidOutputPin\n\t}\n\tswitch sckPad {\n\tcase 1:\n\t\tswitch SDOPad {\n\t\tcase 0:\n\t\t\tdataOutPinout = 0x0\n\t\tcase 3:\n\t\t\tdataOutPinout = 0x2\n\t\tdefault:\n\t\t\treturn ErrInvalidOutputPin\n\t\t}\n\tcase 3:\n\t\tswitch SDOPad {\n\t\tcase 2:\n\t\t\tdataOutPinout = 0x1\n\t\tcase 0:\n\t\t\tdataOutPinout = 0x3\n\t\tdefault:\n\t\t\treturn ErrInvalidOutputPin\n\t\t}\n\tdefault:\n\t\treturn ErrInvalidOutputPin\n\t}\n\n\t// Disable SPI port.\n\tspi.Bus.CTRLA.ClearBits(sam.SERCOM_SPI_CTRLA_ENABLE)\n\tfor spi.Bus.SYNCBUSY.HasBits(sam.SERCOM_SPI_SYNCBUSY_ENABLE) {\n\t}\n\n\t// enable pins\n\tconfig.SCK.Configure(PinConfig{Mode: sckPinMode})\n\tconfig.SDO.Configure(PinConfig{Mode: SDOPinMode})\n\tconfig.SDI.Configure(PinConfig{Mode: SDIPinMode})\n\n\t// reset SERCOM\n\tspi.Bus.CTRLA.SetBits(sam.SERCOM_SPI_CTRLA_SWRST)\n\tfor spi.Bus.CTRLA.HasBits(sam.SERCOM_SPI_CTRLA_SWRST) ||\n\t\tspi.Bus.SYNCBUSY.HasBits(sam.SERCOM_SPI_SYNCBUSY_SWRST) {\n\t}\n\n\t// set bit transfer order\n\tdataOrder := uint32(0)\n\tif config.LSBFirst {\n\t\tdataOrder = 1\n\t}\n\n\t// Set SPI mode to controller\n\tspi.Bus.CTRLA.Set((sam.SERCOM_SPI_CTRLA_MODE_SPI_MASTER << sam.SERCOM_SPI_CTRLA_MODE_Pos) |\n\t\t(dataOutPinout << sam.SERCOM_SPI_CTRLA_DOPO_Pos) |\n\t\t(dataInPinout << sam.SERCOM_SPI_CTRLA_DIPO_Pos) |\n\t\t(dataOrder << sam.SERCOM_SPI_CTRLA_DORD_Pos))\n\n\tspi.Bus.CTRLB.SetBits((0 << sam.SERCOM_SPI_CTRLB_CHSIZE_Pos) | // 8bit char size\n\t\tsam.SERCOM_SPI_CTRLB_RXEN) // receive enable\n\n\tfor spi.Bus.SYNCBUSY.HasBits(sam.SERCOM_SPI_SYNCBUSY_CTRLB) {\n\t}\n\n\t// set mode\n\tswitch config.Mode {\n\tcase 0:\n\t\tspi.Bus.CTRLA.ClearBits(sam.SERCOM_SPI_CTRLA_CPHA)\n\t\tspi.Bus.CTRLA.ClearBits(sam.SERCOM_SPI_CTRLA_CPOL)\n\tcase 1:\n\t\tspi.Bus.CTRLA.SetBits(sam.SERCOM_SPI_CTRLA_CPHA)\n\t\tspi.Bus.CTRLA.ClearBits(sam.SERCOM_SPI_CTRLA_CPOL)\n\tcase 2:\n\t\tspi.Bus.CTRLA.ClearBits(sam.SERCOM_SPI_CTRLA_CPHA)\n\t\tspi.Bus.CTRLA.SetBits(sam.SERCOM_SPI_CTRLA_CPOL)\n\tcase 3:\n\t\tspi.Bus.CTRLA.SetBits(sam.SERCOM_SPI_CTRLA_CPHA | sam.SERCOM_SPI_CTRLA_CPOL)\n\tdefault: // to mode 0\n\t\tspi.Bus.CTRLA.ClearBits(sam.SERCOM_SPI_CTRLA_CPHA)\n\t\tspi.Bus.CTRLA.ClearBits(sam.SERCOM_SPI_CTRLA_CPOL)\n\t}\n\n\t// Set synch speed for SPI\n\tbaudRate := CPUFrequency() / (2 * config.Frequency)\n\tif baudRate > 0 {\n\t\tbaudRate--\n\t}\n\tspi.Bus.BAUD.Set(uint8(baudRate))\n\n\t// Enable SPI port.\n\tspi.Bus.CTRLA.SetBits(sam.SERCOM_SPI_CTRLA_ENABLE)\n\tfor spi.Bus.SYNCBUSY.HasBits(sam.SERCOM_SPI_SYNCBUSY_ENABLE) {\n\t}\n\n\treturn nil\n}\n\n// Transfer writes/reads a single byte using the SPI interface.\nfunc (spi *SPI) Transfer(w byte) (byte, error) {\n\t// write data\n\tspi.Bus.DATA.Set(uint32(w))\n\n\t// wait for receive\n\tfor !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPI_INTFLAG_RXC) {\n\t}\n\n\t// return data\n\treturn byte(spi.Bus.DATA.Get()), nil\n}\n\n// Tx handles read/write operation for SPI interface. Since SPI is a synchronous write/read\n// interface, there must always be the same number of bytes written as bytes read.\n// The Tx method knows about this, and offers a few different ways of calling it.\n//\n// This form sends the bytes in tx buffer, putting the resulting bytes read into the rx buffer.\n// Note that the tx and rx buffers must be the same size:\n//\n//\tspi.Tx(tx, rx)\n//\n// This form sends the tx buffer, ignoring the result. Useful for sending \"commands\" that return zeros\n// until all the bytes in the command packet have been received:\n//\n//\tspi.Tx(tx, nil)\n//\n// This form sends zeros, putting the result into the rx buffer. Good for reading a \"result packet\":\n//\n//\tspi.Tx(nil, rx)\nfunc (spi *SPI) Tx(w, r []byte) error {\n\tswitch {\n\tcase w == nil:\n\t\t// read only, so write zero and read a result.\n\t\tspi.rx(r)\n\tcase r == nil:\n\t\t// write only\n\t\tspi.tx(w)\n\n\tdefault:\n\t\t// write/read\n\t\tif len(w) != len(r) {\n\t\t\treturn ErrTxInvalidSliceSize\n\t\t}\n\n\t\tspi.txrx(w, r)\n\t}\n\n\treturn nil\n}\n\nfunc (spi *SPI) tx(tx []byte) {\n\tfor i := 0; i < len(tx); i++ {\n\t\tfor !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPI_INTFLAG_DRE) {\n\t\t}\n\t\tspi.Bus.DATA.Set(uint32(tx[i]))\n\t}\n\tfor !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPI_INTFLAG_TXC) {\n\t}\n\n\t// read to clear RXC register\n\tfor spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPI_INTFLAG_RXC) {\n\t\tspi.Bus.DATA.Get()\n\t}\n}\n\nfunc (spi *SPI) rx(rx []byte) {\n\tspi.Bus.DATA.Set(0)\n\tfor !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPI_INTFLAG_DRE) {\n\t}\n\n\tfor i := 1; i < len(rx); i++ {\n\t\tspi.Bus.DATA.Set(0)\n\t\tfor !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPI_INTFLAG_RXC) {\n\t\t}\n\t\trx[i-1] = byte(spi.Bus.DATA.Get())\n\t}\n\tfor !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPI_INTFLAG_RXC) {\n\t}\n\trx[len(rx)-1] = byte(spi.Bus.DATA.Get())\n}\n\nfunc (spi *SPI) txrx(tx, rx []byte) {\n\tspi.Bus.DATA.Set(uint32(tx[0]))\n\tfor !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPI_INTFLAG_DRE) {\n\t}\n\n\tfor i := 1; i < len(rx); i++ {\n\t\tspi.Bus.DATA.Set(uint32(tx[i]))\n\t\tfor !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPI_INTFLAG_RXC) {\n\t\t}\n\t\trx[i-1] = byte(spi.Bus.DATA.Get())\n\t}\n\tfor !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPI_INTFLAG_RXC) {\n\t}\n\trx[len(rx)-1] = byte(spi.Bus.DATA.Get())\n}\n\n// TCC is one timer/counter peripheral, which consists of a counter and multiple\n// output channels (that can be connected to actual pins). You can set the\n// frequency using SetPeriod, but only for all the channels in this TCC\n// peripheral at once.\ntype TCC sam.TCC_Type\n\n// The SAM D21 has three TCC peripherals, which have PWM as one feature.\nvar (\n\tTCC0 = (*TCC)(sam.TCC0)\n\tTCC1 = (*TCC)(sam.TCC1)\n\tTCC2 = (*TCC)(sam.TCC2)\n)\n\n//go:inline\nfunc (tcc *TCC) timer() *sam.TCC_Type {\n\treturn (*sam.TCC_Type)(tcc)\n}\n\n// Configure enables and configures this TCC.\nfunc (tcc *TCC) Configure(config PWMConfig) error {\n\t// Enable the clock source for this timer.\n\tswitch tcc.timer() {\n\tcase sam.TCC0:\n\t\tsam.PM.APBCMASK.SetBits(sam.PM_APBCMASK_TCC0_)\n\t\t// Use GCLK0 for TCC0/TCC1\n\t\tsam.GCLK.CLKCTRL.Set((sam.GCLK_CLKCTRL_ID_TCC0_TCC1 << sam.GCLK_CLKCTRL_ID_Pos) |\n\t\t\t(sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_CLKCTRL_CLKEN)\n\t\tfor sam.GCLK.STATUS.HasBits(sam.GCLK_STATUS_SYNCBUSY) {\n\t\t}\n\tcase sam.TCC1:\n\t\tsam.PM.APBCMASK.SetBits(sam.PM_APBCMASK_TCC1_)\n\t\t// Use GCLK0 for TCC0/TCC1\n\t\tsam.GCLK.CLKCTRL.Set((sam.GCLK_CLKCTRL_ID_TCC0_TCC1 << sam.GCLK_CLKCTRL_ID_Pos) |\n\t\t\t(sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_CLKCTRL_CLKEN)\n\t\tfor sam.GCLK.STATUS.HasBits(sam.GCLK_STATUS_SYNCBUSY) {\n\t\t}\n\tcase sam.TCC2:\n\t\tsam.PM.APBCMASK.SetBits(sam.PM_APBCMASK_TCC2_)\n\t\t// Use GCLK0 for TCC2/TC3\n\t\tsam.GCLK.CLKCTRL.Set((sam.GCLK_CLKCTRL_ID_TCC2_TC3 << sam.GCLK_CLKCTRL_ID_Pos) |\n\t\t\t(sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_CLKCTRL_CLKEN)\n\t\tfor sam.GCLK.STATUS.HasBits(sam.GCLK_STATUS_SYNCBUSY) {\n\t\t}\n\t}\n\n\t// Disable timer (if it was enabled). This is necessary because\n\t// tcc.setPeriod may want to change the prescaler bits in CTRLA, which is\n\t// only allowed when the TCC is disabled.\n\ttcc.timer().CTRLA.ClearBits(sam.TCC_CTRLA_ENABLE)\n\n\t// Use \"Normal PWM\" (single-slope PWM)\n\ttcc.timer().WAVE.Set(sam.TCC_WAVE_WAVEGEN_NPWM)\n\n\t// Wait for synchronization of all changed registers.\n\tfor tcc.timer().SYNCBUSY.Get() != 0 {\n\t}\n\n\t// Set the period and prescaler.\n\terr := tcc.setPeriod(config.Period, true)\n\n\t// Enable the timer.\n\ttcc.timer().CTRLA.SetBits(sam.TCC_CTRLA_ENABLE)\n\n\t// Wait for synchronization of all changed registers.\n\tfor tcc.timer().SYNCBUSY.Get() != 0 {\n\t}\n\n\t// Return any error that might have occurred in the tcc.setPeriod call.\n\treturn err\n}\n\n// SetPeriod updates the period of this TCC peripheral.\n// To set a particular frequency, use the following formula:\n//\n//\tperiod = 1e9 / frequency\n//\n// If you use a period of 0, a period that works well for LEDs will be picked.\n//\n// SetPeriod will not change the prescaler, but also won't change the current\n// value in any of the channels. This means that you may need to update the\n// value for the particular channel.\n//\n// Note that you cannot pick any arbitrary period after the TCC peripheral has\n// been configured. If you want to switch between frequencies, pick the lowest\n// frequency (longest period) once when calling Configure and adjust the\n// frequency here as needed.\nfunc (tcc *TCC) SetPeriod(period uint64) error {\n\terr := tcc.setPeriod(period, false)\n\tif err == nil {\n\t\tif tcc.Counter() >= tcc.Top() {\n\t\t\t// When setting the timer to a shorter period, there is a chance\n\t\t\t// that it passes the counter value and thus goes all the way to MAX\n\t\t\t// before wrapping back to zero.\n\t\t\t// To avoid this, reset the counter back to 0.\n\t\t\ttcc.timer().COUNT.Set(0)\n\t\t}\n\t}\n\treturn err\n}\n\n// setPeriod sets the period of this TCC, possibly updating the prescaler as\n// well. The prescaler can only modified when the TCC is disabled, that is, in\n// the Configure function.\nfunc (tcc *TCC) setPeriod(period uint64, updatePrescaler bool) error {\n\tvar top uint64\n\tif period == 0 {\n\t\t// Make sure the TOP value is at 0xffff (enough for a 16-bit timer).\n\t\ttop = 0xffff\n\t} else {\n\t\t// The formula below calculates the following formula, optimized:\n\t\t//     period * (48e6 / 1e9)\n\t\t// This assumes that the chip is running at the (default) 48MHz speed.\n\t\ttop = period * 6 / 125\n\t}\n\n\tmaxTop := uint64(0xffffff)\n\tif tcc.timer() == sam.TCC2 {\n\t\t// TCC2 is a 16-bit timer, not a 24-bit timer.\n\t\tmaxTop = 0xffff\n\t}\n\n\tif updatePrescaler {\n\t\t// This function was called during Configure(), with the timer disabled.\n\t\t// Note that updating the prescaler can only happen while the peripheral\n\t\t// is disabled.\n\t\tvar prescaler uint32\n\t\tswitch {\n\t\tcase top <= maxTop:\n\t\t\tprescaler = sam.TCC_CTRLA_PRESCALER_DIV1\n\t\tcase top/2 <= maxTop:\n\t\t\tprescaler = sam.TCC_CTRLA_PRESCALER_DIV2\n\t\t\ttop = top / 2\n\t\tcase top/4 <= maxTop:\n\t\t\tprescaler = sam.TCC_CTRLA_PRESCALER_DIV4\n\t\t\ttop = top / 4\n\t\tcase top/8 <= maxTop:\n\t\t\tprescaler = sam.TCC_CTRLA_PRESCALER_DIV8\n\t\t\ttop = top / 8\n\t\tcase top/16 <= maxTop:\n\t\t\tprescaler = sam.TCC_CTRLA_PRESCALER_DIV16\n\t\t\ttop = top / 16\n\t\tcase top/64 <= maxTop:\n\t\t\tprescaler = sam.TCC_CTRLA_PRESCALER_DIV64\n\t\t\ttop = top / 64\n\t\tcase top/256 <= maxTop:\n\t\t\tprescaler = sam.TCC_CTRLA_PRESCALER_DIV256\n\t\t\ttop = top / 256\n\t\tcase top/1024 <= maxTop:\n\t\t\tprescaler = sam.TCC_CTRLA_PRESCALER_DIV1024\n\t\t\ttop = top / 1024\n\t\tdefault:\n\t\t\treturn ErrPWMPeriodTooLong\n\t\t}\n\t\ttcc.timer().CTRLA.Set((tcc.timer().CTRLA.Get() &^ sam.TCC_CTRLA_PRESCALER_Msk) | (prescaler << sam.TCC_CTRLA_PRESCALER_Pos))\n\t} else {\n\t\t// Do not update the prescaler, but use the already-configured\n\t\t// prescaler. This is the normal SetPeriod case, where the prescaler\n\t\t// must not be changed.\n\t\tprescaler := (tcc.timer().CTRLA.Get() & sam.TCC_CTRLA_PRESCALER_Msk) >> sam.TCC_CTRLA_PRESCALER_Pos\n\t\tswitch prescaler {\n\t\tcase sam.TCC_CTRLA_PRESCALER_DIV1:\n\t\t\ttop /= 1 // no-op\n\t\tcase sam.TCC_CTRLA_PRESCALER_DIV2:\n\t\t\ttop /= 2\n\t\tcase sam.TCC_CTRLA_PRESCALER_DIV4:\n\t\t\ttop /= 4\n\t\tcase sam.TCC_CTRLA_PRESCALER_DIV8:\n\t\t\ttop /= 8\n\t\tcase sam.TCC_CTRLA_PRESCALER_DIV16:\n\t\t\ttop /= 16\n\t\tcase sam.TCC_CTRLA_PRESCALER_DIV64:\n\t\t\ttop /= 64\n\t\tcase sam.TCC_CTRLA_PRESCALER_DIV256:\n\t\t\ttop /= 256\n\t\tcase sam.TCC_CTRLA_PRESCALER_DIV1024:\n\t\t\ttop /= 1024\n\t\tdefault:\n\t\t\t// unreachable\n\t\t}\n\t\tif top > maxTop {\n\t\t\treturn ErrPWMPeriodTooLong\n\t\t}\n\t}\n\n\t// Set the period (the counter top).\n\ttcc.timer().PER.Set(uint32(top) - 1)\n\n\t// Wait for synchronization of CTRLA.PRESCALER and PER registers.\n\tfor tcc.timer().SYNCBUSY.Get() != 0 {\n\t}\n\n\treturn nil\n}\n\n// Top returns the current counter top, for use in duty cycle calculation. It\n// will only change with a call to Configure or SetPeriod, otherwise it is\n// constant.\n//\n// The value returned here is hardware dependent. In general, it's best to treat\n// it as an opaque value that can be divided by some number and passed to Set\n// (see Set documentation for more information).\nfunc (tcc *TCC) Top() uint32 {\n\treturn tcc.timer().PER.Get() + 1\n}\n\n// Counter returns the current counter value of the timer in this TCC\n// peripheral. It may be useful for debugging.\nfunc (tcc *TCC) Counter() uint32 {\n\ttcc.timer().CTRLBSET.Set(sam.TCC_CTRLBSET_CMD_READSYNC << sam.TCC_CTRLBSET_CMD_Pos)\n\tfor tcc.timer().SYNCBUSY.Get() != 0 {\n\t}\n\treturn tcc.timer().COUNT.Get()\n}\n\n// Some constants to make pinTimerMapping below easier to read.\nconst (\n\tpinTCC0     = 1\n\tpinTCC1     = 2\n\tpinTCC2     = 3\n\tpinTimerCh0 = 0 << 3\n\tpinTimerCh2 = 1 << 3\n\tpinTCC0Ch0  = pinTCC0 | pinTimerCh0\n\tpinTCC0Ch2  = pinTCC0 | pinTimerCh2\n\tpinTCC1Ch0  = pinTCC1 | pinTimerCh0\n\tpinTCC1Ch2  = pinTCC1 | pinTimerCh2\n\tpinTCC2Ch0  = pinTCC2 | pinTimerCh0\n)\n\n// Mapping from pin number to TCC peripheral and channel using a special\n// encoding. Note that only TCC0-TCC2 are included, not TC3 and up.\n// Every byte is split in two nibbles where the low nibble describes PinTCC and\n// the high nibble describes PinTCCAlt. Within a nibble, there is one bit that\n// indicates Ch0/Ch1 or Ch2/Ch3, and three other bits that contain the TCC\n// peripheral number plus one (to distinguish between TCC0Ch0 and 0).\n//\n// The encoding can be so compact because all pins are configured in pairs, so\n// if you know PA00 you can infer the configuration of PA01. And only channel 0\n// or 2 need to be included (taking up just one bit), because channel 0 and 2\n// are only ever used on odd pins and channel 1 and 3 on even pins, again using\n// the pin pair pattern to reduce the amount of information needed to be stored.\n//\n// Datasheet: https://cdn.sparkfun.com/datasheets/Dev/Arduino/Boards/Atmel-42181-SAM-D21_Datasheet.pdf\nvar pinTimerMapping = [...]uint8{\n\t// page 21\n\tPA00 / 2: pinTCC2Ch0 | 0,\n\tPA04 / 2: pinTCC0Ch0 | 0,\n\tPA06 / 2: pinTCC1Ch0 | 0,\n\tPA08 / 2: pinTCC0Ch0 | pinTCC1Ch2<<4,\n\tPA10 / 2: pinTCC1Ch0 | pinTCC0Ch2<<4,\n\t// page 22\n\tPB10 / 2: 0 | pinTCC0Ch0<<4,\n\tPB12 / 2: 0 | pinTCC0Ch2<<4,\n\tPA12 / 2: pinTCC2Ch0 | pinTCC0Ch2<<4,\n\tPA14 / 2: 0 | pinTCC0Ch0<<4,\n\tPA16 / 2: pinTCC2Ch0 | pinTCC0Ch2<<4,\n\tPA18 / 2: 0 | pinTCC0Ch2<<4,\n\tPB16 / 2: 0 | pinTCC0Ch0<<4,\n\tPA20 / 2: 0 | pinTCC0Ch2<<4,\n\tPA22 / 2: 0 | pinTCC0Ch0<<4,\n\tPA24 / 2: 0 | pinTCC1Ch2<<4,\n\t// page 23\n\tPA30 / 2: 0 | pinTCC1Ch0<<4,\n\tPB30 / 2: pinTCC0Ch0 | pinTCC1Ch2<<4,\n}\n\n// findPinTimerMapping returns the pin mode (PinTCC or PinTCCAlt) and the channel\n// number for a given timer and pin. A zero PinMode is returned if no mapping\n// could be found.\nfunc findPinTimerMapping(timer uint8, pin Pin) (PinMode, uint8) {\n\tmapping := pinTimerMapping[pin/2]\n\t// evenChannel below indicates the channel 0 or 2, for the even part of the\n\t// pin pair. The next pin will also have the next channel (1 or 3).\n\tif mapping&0x07 == timer+1 {\n\t\t// PWM output is on peripheral function E.\n\t\tevenChannel := ((mapping >> 3) & 1) * 2\n\t\treturn PinTCC, evenChannel + uint8(pin&1)\n\t}\n\tif (mapping&0x70)>>4 == timer+1 {\n\t\t// PWM output is on peripheral function F.\n\t\tevenChannel := ((mapping >> 7) & 1) * 2\n\t\treturn PinTCCAlt, evenChannel + uint8(pin&1)\n\t}\n\treturn 0, 0\n}\n\n// Channel returns a PWM channel for the given pin. Note that one channel may be\n// shared between multiple pins, and so will have the same duty cycle. If this\n// is not desirable, look for a different TCC peripheral or consider using a\n// different pin.\nfunc (tcc *TCC) Channel(pin Pin) (uint8, error) {\n\tvar pinMode PinMode\n\tvar channel uint8\n\tswitch tcc.timer() {\n\tcase sam.TCC0:\n\t\tpinMode, channel = findPinTimerMapping(0, pin)\n\tcase sam.TCC1:\n\t\tpinMode, channel = findPinTimerMapping(1, pin)\n\tcase sam.TCC2:\n\t\tpinMode, channel = findPinTimerMapping(2, pin)\n\t}\n\n\tif pinMode == 0 {\n\t\t// No pin could be found.\n\t\treturn 0, ErrInvalidOutputPin\n\t}\n\n\t// Enable the port multiplexer for pin\n\tpin.setPinCfg(sam.PORT_PINCFG0_PMUXEN)\n\n\tif pin&1 > 0 {\n\t\t// odd pin, so save the even pins\n\t\tval := pin.getPMux() & sam.PORT_PMUX0_PMUXE_Msk\n\t\tpin.setPMux(val | uint8(pinMode<<sam.PORT_PMUX0_PMUXO_Pos))\n\t} else {\n\t\t// even pin, so save the odd pins\n\t\tval := pin.getPMux() & sam.PORT_PMUX0_PMUXO_Msk\n\t\tpin.setPMux(val | uint8(pinMode<<sam.PORT_PMUX0_PMUXE_Pos))\n\t}\n\treturn channel, nil\n}\n\n// SetInverting sets whether to invert the output of this channel.\n// Without inverting, a 25% duty cycle would mean the output is high for 25% of\n// the time and low for the rest. Inverting flips the output as if a NOT gate\n// was placed at the output, meaning that the output would be 25% low and 75%\n// high with a duty cycle of 25%.\nfunc (tcc *TCC) SetInverting(channel uint8, inverting bool) {\n\tif inverting {\n\t\ttcc.timer().WAVE.SetBits(1 << (sam.TCC_WAVE_POL0_Pos + channel))\n\t} else {\n\t\ttcc.timer().WAVE.ClearBits(1 << (sam.TCC_WAVE_POL0_Pos + channel))\n\t}\n\n\t// Wait for synchronization of the WAVE register.\n\tfor tcc.timer().SYNCBUSY.Get() != 0 {\n\t}\n}\n\n// Set updates the channel value. This is used to control the channel duty\n// cycle, in other words the fraction of time the channel output is high (or low\n// when inverted). For example, to set it to a 25% duty cycle, use:\n//\n//\ttcc.Set(channel, tcc.Top() / 4)\n//\n// tcc.Set(channel, 0) will set the output to low and tcc.Set(channel,\n// tcc.Top()) will set the output to high, assuming the output isn't inverted.\nfunc (tcc *TCC) Set(channel uint8, value uint32) {\n\t// Set PWM signal to output duty cycle\n\tswitch channel {\n\tcase 0:\n\t\ttcc.timer().CC0.Set(value)\n\tcase 1:\n\t\ttcc.timer().CC1.Set(value)\n\tcase 2:\n\t\ttcc.timer().CC2.Set(value)\n\tcase 3:\n\t\ttcc.timer().CC3.Set(value)\n\tdefault:\n\t\t// invalid PWM channel, ignore.\n\t}\n\n\t// Wait for synchronization on all channels (or anything in this peripheral,\n\t// really).\n\tfor tcc.timer().SYNCBUSY.Get() != 0 {\n\t}\n}\n\n// EnterBootloader should perform a system reset in preparation\n// to switch to the bootloader to flash new firmware.\nfunc EnterBootloader() {\n\tarm.DisableInterrupts()\n\n\t// Perform magic reset into bootloader, as mentioned in\n\t// https://github.com/arduino/ArduinoCore-samd/issues/197\n\t*(*uint32)(unsafe.Pointer(uintptr(0x20007FFC))) = resetMagicValue\n\n\tarm.SystemReset()\n}\n\n// DAC on the SAMD21.\ntype DAC struct {\n}\n\nvar (\n\tDAC0 = DAC{}\n)\n\n// DACConfig placeholder for future expansion.\ntype DACConfig struct {\n}\n\n// Configure the DAC.\n// output pin must already be configured.\nfunc (dac DAC) Configure(config DACConfig) {\n\t// Turn on clock for DAC\n\tsam.PM.APBCMASK.SetBits(sam.PM_APBCMASK_DAC_)\n\n\t// Use Generic Clock Generator 0 as source for DAC.\n\tsam.GCLK.CLKCTRL.Set((sam.GCLK_CLKCTRL_ID_DAC << sam.GCLK_CLKCTRL_ID_Pos) |\n\t\t(sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |\n\t\tsam.GCLK_CLKCTRL_CLKEN)\n\twaitForSync()\n\n\t// reset DAC\n\tsam.DAC.CTRLA.Set(sam.DAC_CTRLA_SWRST)\n\tsyncDAC()\n\n\t// wait for reset complete\n\tfor sam.DAC.CTRLA.HasBits(sam.DAC_CTRLA_SWRST) {\n\t}\n\n\t// enable\n\tsam.DAC.CTRLB.Set(sam.DAC_CTRLB_EOEN | sam.DAC_CTRLB_REFSEL_AVCC)\n\tsam.DAC.CTRLA.Set(sam.DAC_CTRLA_ENABLE)\n}\n\n// Set writes a single 16-bit value to the DAC.\n// Since the ATSAMD21 only has a 10-bit DAC, the passed-in value will be scaled down.\nfunc (dac DAC) Set(value uint16) error {\n\tsam.DAC.DATA.Set(value >> 6)\n\tsyncDAC()\n\treturn nil\n}\n\nfunc syncDAC() {\n\tfor sam.DAC.STATUS.HasBits(sam.DAC_STATUS_SYNCBUSY) {\n\t}\n}\n\n// Flash related code\nconst memoryStart = 0x0\n\n// compile-time check for ensuring we fulfill BlockDevice interface\nvar _ BlockDevice = flashBlockDevice{}\n\nvar Flash flashBlockDevice\n\ntype flashBlockDevice struct {\n\tinitComplete bool\n}\n\n// ReadAt reads the given number of bytes from the block device.\nfunc (f flashBlockDevice) ReadAt(p []byte, off int64) (n int, err error) {\n\tif FlashDataStart()+uintptr(off)+uintptr(len(p)) > FlashDataEnd() {\n\t\treturn 0, errFlashCannotReadPastEOF\n\t}\n\n\tf.ensureInitComplete()\n\n\twaitWhileFlashBusy()\n\n\tdata := unsafe.Slice((*byte)(unsafe.Add(unsafe.Pointer(FlashDataStart()), uintptr(off))), len(p))\n\tcopy(p, data)\n\n\treturn len(p), nil\n}\n\n// WriteAt writes the given number of bytes to the block device.\n// Data is written to the page buffer in 4-byte chunks, then saved to flash memory.\n// See Atmel-42181G–SAM-D21_Datasheet–09/2015 page 359.\n// If the length of p is not long enough it will be padded with 0xFF bytes.\n// This method assumes that the destination is already erased.\nfunc (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) {\n\tif FlashDataStart()+uintptr(off)+uintptr(len(p)) > FlashDataEnd() {\n\t\treturn 0, errFlashCannotWritePastEOF\n\t}\n\n\tf.ensureInitComplete()\n\n\taddress := FlashDataStart() + uintptr(off)\n\tpadded := flashPad(p, int(f.WriteBlockSize()))\n\n\twaitWhileFlashBusy()\n\n\tfor j := 0; j < len(padded); j += int(f.WriteBlockSize()) {\n\t\t// page buffer is 64 bytes long, but only 4 bytes can be written at once\n\t\tfor k := 0; k < int(f.WriteBlockSize()); k += 4 {\n\t\t\t*(*uint32)(unsafe.Pointer(address + uintptr(k))) = binary.LittleEndian.Uint32(padded[j+k : j+k+4])\n\t\t}\n\n\t\tsam.NVMCTRL.SetADDR(uint32(address >> 1))\n\t\tsam.NVMCTRL.CTRLA.Set(sam.NVMCTRL_CTRLA_CMD_WP | (sam.NVMCTRL_CTRLA_CMDEX_KEY << sam.NVMCTRL_CTRLA_CMDEX_Pos))\n\n\t\twaitWhileFlashBusy()\n\n\t\tif err := checkFlashError(); err != nil {\n\t\t\treturn j, err\n\t\t}\n\n\t\taddress += uintptr(f.WriteBlockSize())\n\t}\n\n\treturn len(padded), nil\n}\n\n// Size returns the number of bytes in this block device.\nfunc (f flashBlockDevice) Size() int64 {\n\treturn int64(FlashDataEnd() - FlashDataStart())\n}\n\nconst writeBlockSize = 64\n\n// WriteBlockSize returns the block size in which data can be written to\n// memory. It can be used by a client to optimize writes, non-aligned writes\n// should always work correctly.\nfunc (f flashBlockDevice) WriteBlockSize() int64 {\n\treturn writeBlockSize\n}\n\nconst eraseBlockSizeValue = 256\n\nfunc eraseBlockSize() int64 {\n\treturn eraseBlockSizeValue\n}\n\n// EraseBlockSize returns the smallest erasable area on this particular chip\n// in bytes. This is used for the block size in EraseBlocks.\nfunc (f flashBlockDevice) EraseBlockSize() int64 {\n\treturn eraseBlockSize()\n}\n\n// EraseBlocks erases the given number of blocks. An implementation may\n// transparently coalesce ranges of blocks into larger bundles if the chip\n// supports this. The start and len parameters are in block numbers, use\n// EraseBlockSize to map addresses to blocks.\nfunc (f flashBlockDevice) EraseBlocks(start, len int64) error {\n\tf.ensureInitComplete()\n\n\taddress := FlashDataStart() + uintptr(start*f.EraseBlockSize())\n\twaitWhileFlashBusy()\n\n\tfor i := start; i < start+len; i++ {\n\t\tsam.NVMCTRL.SetADDR(uint32(address >> 1))\n\t\tsam.NVMCTRL.CTRLA.Set(sam.NVMCTRL_CTRLA_CMD_ER | (sam.NVMCTRL_CTRLA_CMDEX_KEY << sam.NVMCTRL_CTRLA_CMDEX_Pos))\n\n\t\twaitWhileFlashBusy()\n\n\t\tif err := checkFlashError(); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\taddress += uintptr(f.EraseBlockSize())\n\t}\n\n\treturn nil\n}\n\nfunc (f flashBlockDevice) ensureInitComplete() {\n\tif f.initComplete {\n\t\treturn\n\t}\n\n\tsam.NVMCTRL.SetCTRLB_READMODE(sam.NVMCTRL_CTRLB_READMODE_NO_MISS_PENALTY)\n\tsam.NVMCTRL.SetCTRLB_SLEEPPRM(sam.NVMCTRL_CTRLB_SLEEPPRM_WAKEONACCESS)\n\n\twaitWhileFlashBusy()\n\n\tf.initComplete = true\n}\n\nfunc waitWhileFlashBusy() {\n\tfor sam.NVMCTRL.GetINTFLAG_READY() != sam.NVMCTRL_INTFLAG_READY {\n\t}\n}\n\nvar (\n\terrFlashPROGE = errors.New(\"errFlashPROGE\")\n\terrFlashLOCKE = errors.New(\"errFlashLOCKE\")\n\terrFlashNVME  = errors.New(\"errFlashNVME\")\n)\n\nfunc checkFlashError() error {\n\tswitch {\n\tcase sam.NVMCTRL.GetSTATUS_PROGE() != 0:\n\t\treturn errFlashPROGE\n\tcase sam.NVMCTRL.GetSTATUS_LOCKE() != 0:\n\t\treturn errFlashLOCKE\n\tcase sam.NVMCTRL.GetSTATUS_NVME() != 0:\n\t\treturn errFlashNVME\n\t}\n\n\treturn nil\n}\n\n// Watchdog provides access to the hardware watchdog available\n// in the SAMD21.\nvar Watchdog = &watchdogImpl{}\n\nconst (\n\t// WatchdogMaxTimeout in milliseconds (16s)\n\tWatchdogMaxTimeout = (16384 * 1000) / 1024\n)\n\ntype watchdogImpl struct{}\n\n// Configure the watchdog.\n//\n// This method should not be called after the watchdog is started and on\n// some platforms attempting to reconfigure after starting the watchdog\n// is explicitly forbidden / will not work.\nfunc (wd *watchdogImpl) Configure(config WatchdogConfig) error {\n\t// Use OSCULP32K as source for Generic Clock Generator 8, divided by 32 to get 1.024kHz\n\tsam.GCLK.GENDIV.Set(sam.GCLK_CLKCTRL_GEN_GCLK8 | (32 << sam.GCLK_GENDIV_DIV_Pos))\n\tsam.GCLK.GENCTRL.Set(sam.GCLK_CLKCTRL_GEN_GCLK8 | (sam.GCLK_GENCTRL_SRC_OSCULP32K << sam.GCLK_GENCTRL_SRC_Pos) | sam.GCLK_GENCTRL_GENEN)\n\twaitForSync()\n\n\t// Use GCLK8 for watchdog\n\tsam.GCLK.CLKCTRL.Set(sam.GCLK_CLKCTRL_ID_WDT | (sam.GCLK_CLKCTRL_GEN_GCLK8 << sam.GCLK_CLKCTRL_GEN_Pos) | sam.GCLK_CLKCTRL_CLKEN)\n\n\t// Power on the watchdog peripheral\n\tsam.PM.APBAMASK.SetBits(sam.PM_APBAMASK_WDT_)\n\n\t// 1.024kHz clock\n\tcycles := int((int64(config.TimeoutMillis) * 1024) / 1000)\n\n\t// period is expressed as a power-of-two, starting at 8 / 1024ths of a second\n\tperiod := uint8(0)\n\tcfgCycles := 8\n\tfor cfgCycles < cycles {\n\t\tperiod++\n\t\tcfgCycles <<= 1\n\n\t\tif period >= 0xB {\n\t\t\tbreak\n\t\t}\n\t}\n\n\tsam.WDT.CONFIG.Set(period << sam.WDT_CONFIG_PER_Pos)\n\n\treturn nil\n}\n\n// Starts the watchdog.\nfunc (wd *watchdogImpl) Start() error {\n\tsam.WDT.CTRL.SetBits(sam.WDT_CTRL_ENABLE)\n\treturn nil\n}\n\n// Update the watchdog, indicating that `source` is healthy.\nfunc (wd *watchdogImpl) Update() {\n\tsam.WDT.CLEAR.Set(sam.WDT_CLEAR_CLEAR_KEY)\n}\n"
  },
  {
    "path": "src/machine/machine_atsamd21_simulator.go",
    "content": "//go:build !baremetal && (gemma_m0 || qtpy || trinket_m0 || arduino_mkr1000 || arduino_mkrwifi1010 || arduino_nano33 || arduino_zero || circuitplay_express || feather_m0_express || feather_m0 || itsybitsy_m0 || p1am_100 || xiao)\n\n// Simulated atsamd21 chips.\n\npackage machine\n\n// The timer channels/pins match the hardware, and encode the same information\n// as pinTimerMapping but in a more generic (less efficient) way.\n\nvar TCC0 = &timerType{\n\tinstance:   0,\n\tfrequency:  48e6,\n\tbits:       24,\n\tprescalers: []int{1, 2, 4, 8, 16, 64, 256, 1024},\n\tchannelPins: [][]Pin{\n\t\t{PA04, PA08, PB10, PA14, PB16, PA22, PB30}, // channel 0\n\t\t{PA05, PA09, PB11, PA15, PB17, PA23, PB31}, // channel 1\n\t\t{PA10, PB12, PA12, PA16, PA18, PA20},       // channel 2\n\t\t{PA11, PB13, PA13, PA17, PA19, PA21},       // channel 3\n\t},\n}\n\nvar TCC1 = &timerType{\n\tinstance:   1,\n\tfrequency:  48e6,\n\tbits:       24,\n\tprescalers: []int{1, 2, 4, 8, 16, 64, 256, 1024},\n\tchannelPins: [][]Pin{\n\t\t{PA06, PA10, PA30}, // channel 0\n\t\t{PA07, PA11, PA31}, // channel 1\n\t\t{PA08, PA24, PB30}, // channel 2\n\t\t{PA09, PA25, PB31}, // channel 3\n\t},\n}\n\nvar TCC2 = &timerType{\n\tinstance:   2,\n\tfrequency:  48e6,\n\tbits:       16,\n\tprescalers: []int{1, 2, 4, 8, 16, 64, 256, 1024},\n\tchannelPins: [][]Pin{\n\t\t{PA00, PA12, PA16}, // channel 0\n\t\t{PA01, PA13, PA17}, // channel 1\n\t},\n}\n\nvar (\n\t// According to the datasheet, only some pins have I2C support. However it\n\t// looks like many boards just use any SERCOM I2C instance, even if the\n\t// datasheet says those don't support I2C. I guess they do work in practice,\n\t// then.\n\t// These are:\n\t//   * PA00/PA01 for the Adafruit Circuit Playground Express (I2C1, SERCOM1).\n\t//   * PB02/PB03 for the Adafruit Circuit Playground Express (I2C0, SERCOM5).\n\t//   * PB08/PB09 for the Arduino Nano 33 IoT (I2C0, SERCOM4).\n\t// https://cdn.sparkfun.com/datasheets/Dev/Arduino/Boards/Atmel-42181-SAM-D21_Datasheet.pdf\n\tsercomI2CM0 = &I2C{Bus: 0, PinsSDA: []Pin{PA08}, PinsSCL: []Pin{PA09}}\n\tsercomI2CM1 = &I2C{Bus: 1, PinsSDA: []Pin{PA00, PA16}, PinsSCL: []Pin{PA01, PA17}}\n\tsercomI2CM2 = &I2C{Bus: 2, PinsSDA: []Pin{PA08, PA12}, PinsSCL: []Pin{PA09, PA13}}\n\tsercomI2CM3 = &I2C{Bus: 3, PinsSDA: []Pin{PA16, PA22}, PinsSCL: []Pin{PA17, PA23}}\n\tsercomI2CM4 = &I2C{Bus: 4, PinsSDA: []Pin{PA12, PB08, PB12}, PinsSCL: []Pin{PA13, PB09, PB13}}\n\tsercomI2CM5 = &I2C{Bus: 5, PinsSDA: []Pin{PA22, PB02, PB16, PB30}, PinsSCL: []Pin{PA23, PB03, PB17, PB31}}\n)\n"
  },
  {
    "path": "src/machine/machine_atsamd21_usb.go",
    "content": "//go:build sam && atsamd21\n\npackage machine\n\nimport (\n\t\"device/sam\"\n\t\"machine/usb\"\n\t\"runtime/interrupt\"\n\t\"unsafe\"\n)\n\nconst (\n\t// these are SAMD21 specific.\n\tusb_DEVICE_PCKSIZE_BYTE_COUNT_Pos  = 0\n\tusb_DEVICE_PCKSIZE_BYTE_COUNT_Mask = 0x3FFF\n\n\tusb_DEVICE_PCKSIZE_SIZE_Pos  = 28\n\tusb_DEVICE_PCKSIZE_SIZE_Mask = 0x7\n\n\tusb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Pos  = 14\n\tusb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Mask = 0x3FFF\n\n\tNumberOfUSBEndpoints = 8\n)\n\nvar (\n\tendPoints = []uint32{\n\t\tusb.CONTROL_ENDPOINT:  usb.ENDPOINT_TYPE_CONTROL,\n\t\tusb.CDC_ENDPOINT_ACM:  (usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn),\n\t\tusb.CDC_ENDPOINT_OUT:  (usb.ENDPOINT_TYPE_BULK | usb.EndpointOut),\n\t\tusb.CDC_ENDPOINT_IN:   (usb.ENDPOINT_TYPE_BULK | usb.EndpointIn),\n\t\tusb.HID_ENDPOINT_IN:   (usb.ENDPOINT_TYPE_DISABLE), // Interrupt In\n\t\tusb.HID_ENDPOINT_OUT:  (usb.ENDPOINT_TYPE_DISABLE), // Interrupt Out\n\t\tusb.MIDI_ENDPOINT_IN:  (usb.ENDPOINT_TYPE_DISABLE), // Bulk In\n\t\tusb.MIDI_ENDPOINT_OUT: (usb.ENDPOINT_TYPE_DISABLE), // Bulk Out\n\t}\n)\n\n// Configure the USB peripheral. The config is here for compatibility with the UART interface.\nfunc (dev *USBDevice) Configure(config UARTConfig) {\n\tif dev.initcomplete {\n\t\treturn\n\t}\n\n\t// reset USB interface\n\tsam.USB_DEVICE.CTRLA.SetBits(sam.USB_DEVICE_CTRLA_SWRST)\n\tfor sam.USB_DEVICE.SYNCBUSY.HasBits(sam.USB_DEVICE_SYNCBUSY_SWRST) ||\n\t\tsam.USB_DEVICE.SYNCBUSY.HasBits(sam.USB_DEVICE_SYNCBUSY_ENABLE) {\n\t}\n\n\tsam.USB_DEVICE.DESCADD.Set(uint32(uintptr(unsafe.Pointer(&usbEndpointDescriptors))))\n\n\t// configure pins\n\tUSBCDC_DM_PIN.Configure(PinConfig{Mode: PinCom})\n\tUSBCDC_DP_PIN.Configure(PinConfig{Mode: PinCom})\n\n\t// performs pad calibration from store fuses\n\thandlePadCalibration()\n\n\t// run in standby\n\tsam.USB_DEVICE.CTRLA.SetBits(sam.USB_DEVICE_CTRLA_RUNSTDBY)\n\n\t// set full speed\n\tsam.USB_DEVICE.CTRLB.SetBits(sam.USB_DEVICE_CTRLB_SPDCONF_FS << sam.USB_DEVICE_CTRLB_SPDCONF_Pos)\n\n\t// attach\n\tsam.USB_DEVICE.CTRLB.ClearBits(sam.USB_DEVICE_CTRLB_DETACH)\n\n\t// enable interrupt for end of reset\n\tsam.USB_DEVICE.INTENSET.SetBits(sam.USB_DEVICE_INTENSET_EORST)\n\n\t// enable interrupt for start of frame\n\tsam.USB_DEVICE.INTENSET.SetBits(sam.USB_DEVICE_INTENSET_SOF)\n\n\t// enable USB\n\tsam.USB_DEVICE.CTRLA.SetBits(sam.USB_DEVICE_CTRLA_ENABLE)\n\n\t// enable IRQ\n\tinterrupt.New(sam.IRQ_USB, handleUSBIRQ).Enable()\n\n\tdev.initcomplete = true\n}\n\nfunc handlePadCalibration() {\n\t// Load Pad Calibration data from non-volatile memory\n\t// This requires registers that are not included in the SVD file.\n\t// Modeled after defines from samd21g18a.h and nvmctrl.h:\n\t//\n\t// #define NVMCTRL_OTP4 0x00806020\n\t//\n\t// #define USB_FUSES_TRANSN_ADDR       (NVMCTRL_OTP4 + 4)\n\t// #define USB_FUSES_TRANSN_Pos        13           /**< \\brief (NVMCTRL_OTP4) USB pad Transn calibration */\n\t// #define USB_FUSES_TRANSN_Msk        (0x1Fu << USB_FUSES_TRANSN_Pos)\n\t// #define USB_FUSES_TRANSN(value)     ((USB_FUSES_TRANSN_Msk & ((value) << USB_FUSES_TRANSN_Pos)))\n\n\t// #define USB_FUSES_TRANSP_ADDR       (NVMCTRL_OTP4 + 4)\n\t// #define USB_FUSES_TRANSP_Pos        18           /**< \\brief (NVMCTRL_OTP4) USB pad Transp calibration */\n\t// #define USB_FUSES_TRANSP_Msk        (0x1Fu << USB_FUSES_TRANSP_Pos)\n\t// #define USB_FUSES_TRANSP(value)     ((USB_FUSES_TRANSP_Msk & ((value) << USB_FUSES_TRANSP_Pos)))\n\n\t// #define USB_FUSES_TRIM_ADDR         (NVMCTRL_OTP4 + 4)\n\t// #define USB_FUSES_TRIM_Pos          23           /**< \\brief (NVMCTRL_OTP4) USB pad Trim calibration */\n\t// #define USB_FUSES_TRIM_Msk          (0x7u << USB_FUSES_TRIM_Pos)\n\t// #define USB_FUSES_TRIM(value)       ((USB_FUSES_TRIM_Msk & ((value) << USB_FUSES_TRIM_Pos)))\n\t//\n\tfuse := *(*uint32)(unsafe.Pointer(uintptr(0x00806020) + 4))\n\tcalibTransN := uint16(fuse>>13) & uint16(0x1f)\n\tcalibTransP := uint16(fuse>>18) & uint16(0x1f)\n\tcalibTrim := uint16(fuse>>23) & uint16(0x7)\n\n\tif calibTransN == 0x1f {\n\t\tcalibTransN = 5\n\t}\n\tsam.USB_DEVICE.PADCAL.SetBits(calibTransN << sam.USB_DEVICE_PADCAL_TRANSN_Pos)\n\n\tif calibTransP == 0x1f {\n\t\tcalibTransP = 29\n\t}\n\tsam.USB_DEVICE.PADCAL.SetBits(calibTransP << sam.USB_DEVICE_PADCAL_TRANSP_Pos)\n\n\tif calibTrim == 0x7 {\n\t\tcalibTrim = 3\n\t}\n\tsam.USB_DEVICE.PADCAL.SetBits(calibTrim << sam.USB_DEVICE_PADCAL_TRIM_Pos)\n}\n\nfunc handleUSBIRQ(intr interrupt.Interrupt) {\n\t// reset all interrupt flags\n\tflags := sam.USB_DEVICE.INTFLAG.Get()\n\tsam.USB_DEVICE.INTFLAG.Set(flags)\n\n\t// End of reset\n\tif (flags & sam.USB_DEVICE_INTFLAG_EORST) > 0 {\n\t\t// Configure control endpoint\n\t\tinitEndpoint(0, usb.ENDPOINT_TYPE_CONTROL)\n\n\t\tusbConfiguration = 0\n\n\t\t// ack the End-Of-Reset interrupt\n\t\tsam.USB_DEVICE.INTFLAG.Set(sam.USB_DEVICE_INTFLAG_EORST)\n\t}\n\n\t// Start of frame\n\tif (flags & sam.USB_DEVICE_INTFLAG_SOF) > 0 {\n\t\t// if you want to blink LED showing traffic, this would be the place...\n\t}\n\n\t// Endpoint 0 Setup interrupt\n\tif getEPINTFLAG(0)&sam.USB_DEVICE_EPINTFLAG_RXSTP > 0 {\n\t\t// ack setup received\n\t\tsetEPINTFLAG(0, sam.USB_DEVICE_EPINTFLAG_RXSTP)\n\n\t\t// parse setup\n\t\tsetup := usb.NewSetup(udd_ep_out_cache_buffer[0][:])\n\n\t\t// Clear the Bank 0 ready flag on Control OUT\n\t\tusbEndpointDescriptors[0].DeviceDescBank[0].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[0]))))\n\t\tusbEndpointDescriptors[0].DeviceDescBank[0].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)\n\t\tsetEPSTATUSCLR(0, sam.USB_DEVICE_EPSTATUSCLR_BK0RDY)\n\n\t\tok := false\n\t\tif (setup.BmRequestType & usb.REQUEST_TYPE) == usb.REQUEST_STANDARD {\n\t\t\t// Standard Requests\n\t\t\tok = handleStandardSetup(setup)\n\t\t} else {\n\t\t\t// Class Interface Requests\n\t\t\tif setup.WIndex < uint16(len(usbSetupHandler)) && usbSetupHandler[setup.WIndex] != nil {\n\t\t\t\tok = usbSetupHandler[setup.WIndex](setup)\n\t\t\t}\n\t\t}\n\n\t\tif ok {\n\t\t\t// set Bank1 ready\n\t\t\tsetEPSTATUSSET(0, sam.USB_DEVICE_EPSTATUSSET_BK1RDY)\n\t\t} else {\n\t\t\t// Stall endpoint\n\t\t\tsetEPSTATUSSET(0, sam.USB_DEVICE_EPINTFLAG_STALL1)\n\t\t}\n\n\t\tif getEPINTFLAG(0)&sam.USB_DEVICE_EPINTFLAG_STALL1 > 0 {\n\t\t\t// ack the stall\n\t\t\tsetEPINTFLAG(0, sam.USB_DEVICE_EPINTFLAG_STALL1)\n\n\t\t\t// clear stall request\n\t\t\tsetEPINTENCLR(0, sam.USB_DEVICE_EPINTENCLR_STALL1)\n\t\t}\n\t}\n\n\t// Now the actual transfer handlers, ignore endpoint number 0 (setup)\n\tvar i uint32\n\tfor i = 1; i < uint32(len(endPoints)); i++ {\n\t\t// Check if endpoint has a pending interrupt\n\t\tepFlags := getEPINTFLAG(i)\n\t\tsetEPINTFLAG(i, epFlags)\n\t\tif (epFlags & sam.USB_DEVICE_EPINTFLAG_TRCPT0) > 0 {\n\t\t\tbuf := handleEndpointRx(i)\n\t\t\tif usbRxHandler[i] == nil || usbRxHandler[i](buf) {\n\t\t\t\tAckUsbOutTransfer(i)\n\t\t\t}\n\t\t} else if (epFlags & sam.USB_DEVICE_EPINTFLAG_TRCPT1) > 0 {\n\t\t\tif usbTxHandler[i] != nil {\n\t\t\t\tusbTxHandler[i]()\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc initEndpoint(ep, config uint32) {\n\tswitch config {\n\tcase usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn:\n\t\t// set packet size\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.SetBits(epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos)\n\n\t\t// set data buffer address\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[1].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_in_cache_buffer[ep]))))\n\n\t\t// set endpoint type\n\t\tsetEPCFG(ep, ((usb.ENDPOINT_TYPE_INTERRUPT + 1) << sam.USB_DEVICE_EPCFG_EPTYPE1_Pos))\n\n\t\tsetEPINTENSET(ep, sam.USB_DEVICE_EPINTENSET_TRCPT1)\n\n\tcase usb.ENDPOINT_TYPE_BULK | usb.EndpointOut:\n\t\t// set packet size\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.SetBits(epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos)\n\n\t\t// set data buffer address\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[0].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[ep]))))\n\n\t\t// set endpoint type\n\t\tsetEPCFG(ep, ((usb.ENDPOINT_TYPE_BULK + 1) << sam.USB_DEVICE_EPCFG_EPTYPE0_Pos))\n\n\t\t// receive interrupts when current transfer complete\n\t\tsetEPINTENSET(ep, sam.USB_DEVICE_EPINTENSET_TRCPT0)\n\n\t\t// set byte count to zero, we have not received anything yet\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)\n\n\t\t// ready for next transfer\n\t\tsetEPSTATUSCLR(ep, sam.USB_DEVICE_EPSTATUSCLR_BK0RDY)\n\n\tcase usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointOut:\n\t\t// set packet size\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.SetBits(epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos)\n\n\t\t// set data buffer address\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[0].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[ep]))))\n\n\t\t// set endpoint type\n\t\tsetEPCFG(ep, ((usb.ENDPOINT_TYPE_INTERRUPT + 1) << sam.USB_DEVICE_EPCFG_EPTYPE0_Pos))\n\n\t\t// receive interrupts when current transfer complete\n\t\tsetEPINTENSET(ep, sam.USB_DEVICE_EPINTENSET_TRCPT0)\n\n\t\t// set byte count to zero, we have not received anything yet\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)\n\n\t\t// ready for next transfer\n\t\tsetEPSTATUSCLR(ep, sam.USB_DEVICE_EPSTATUSCLR_BK0RDY)\n\n\tcase usb.ENDPOINT_TYPE_BULK | usb.EndpointIn:\n\t\t// set packet size\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.SetBits(epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos)\n\n\t\t// set data buffer address\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[1].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_in_cache_buffer[ep]))))\n\n\t\t// set endpoint type\n\t\tsetEPCFG(ep, ((usb.ENDPOINT_TYPE_BULK + 1) << sam.USB_DEVICE_EPCFG_EPTYPE1_Pos))\n\n\t\t// NAK on endpoint IN, the bank is not yet filled in.\n\t\tsetEPSTATUSCLR(ep, sam.USB_DEVICE_EPSTATUSCLR_BK1RDY)\n\n\t\tsetEPINTENSET(ep, sam.USB_DEVICE_EPINTENSET_TRCPT1)\n\n\tcase usb.ENDPOINT_TYPE_CONTROL:\n\t\t// Control OUT\n\t\t// set packet size\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.SetBits(epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos)\n\n\t\t// set data buffer address\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[0].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[ep]))))\n\n\t\t// set endpoint type\n\t\tsetEPCFG(ep, getEPCFG(ep)|((usb.ENDPOINT_TYPE_CONTROL+1)<<sam.USB_DEVICE_EPCFG_EPTYPE0_Pos))\n\n\t\t// Control IN\n\t\t// set packet size\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.SetBits(epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos)\n\n\t\t// set data buffer address\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[1].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_in_cache_buffer[ep]))))\n\n\t\t// set endpoint type\n\t\tsetEPCFG(ep, getEPCFG(ep)|((usb.ENDPOINT_TYPE_CONTROL+1)<<sam.USB_DEVICE_EPCFG_EPTYPE1_Pos))\n\n\t\t// Prepare OUT endpoint for receive\n\t\t// set multi packet size for expected number of receive bytes on control OUT\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.SetBits(64 << usb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Pos)\n\n\t\t// set byte count to zero, we have not received anything yet\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)\n\n\t\t// NAK on endpoint OUT to show we are ready to receive control data\n\t\tsetEPSTATUSSET(ep, sam.USB_DEVICE_EPSTATUSSET_BK0RDY)\n\n\t\t// Enable Setup-Received interrupt\n\t\tsetEPINTENSET(0, sam.USB_DEVICE_EPINTENSET_RXSTP)\n\t}\n}\n\nfunc handleUSBSetAddress(setup usb.Setup) bool {\n\t// set packet size 64 with auto Zlp after transfer\n\tusbEndpointDescriptors[0].DeviceDescBank[1].PCKSIZE.Set((epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos) |\n\t\tuint32(1<<31)) // autozlp\n\n\t// ack the transfer is complete from the request\n\tsetEPINTFLAG(0, sam.USB_DEVICE_EPINTFLAG_TRCPT1)\n\n\t// set bank ready for data\n\tsetEPSTATUSSET(0, sam.USB_DEVICE_EPSTATUSSET_BK1RDY)\n\n\t// wait for transfer to complete\n\ttimeout := 3000\n\tfor (getEPINTFLAG(0) & sam.USB_DEVICE_EPINTFLAG_TRCPT1) == 0 {\n\t\ttimeout--\n\t\tif timeout == 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\t// last, set the device address to that requested by host\n\tsam.USB_DEVICE.DADD.SetBits(setup.WValueL)\n\tsam.USB_DEVICE.DADD.SetBits(sam.USB_DEVICE_DADD_ADDEN)\n\n\treturn true\n}\n\n// SendUSBInPacket sends a packet for USB (interrupt in / bulk in).\nfunc SendUSBInPacket(ep uint32, data []byte) bool {\n\tsendUSBPacket(ep, data, 0)\n\n\t// clear transfer complete flag\n\tsetEPINTFLAG(ep, sam.USB_DEVICE_EPINTFLAG_TRCPT1)\n\n\t// send data by setting bank ready\n\tsetEPSTATUSSET(ep, sam.USB_DEVICE_EPSTATUSSET_BK1RDY)\n\n\treturn true\n}\n\n// Prevent file size increases: https://github.com/tinygo-org/tinygo/pull/998\n//\n//go:noinline\nfunc sendUSBPacket(ep uint32, data []byte, maxsize uint16) {\n\tl := uint16(len(data))\n\tif 0 < maxsize && maxsize < l {\n\t\tl = maxsize\n\t}\n\n\t// Set endpoint address for sending data\n\tif ep == 0 {\n\t\tcopy(udd_ep_control_cache_buffer[:], data[:l])\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[1].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_control_cache_buffer))))\n\t} else {\n\t\tcopy(udd_ep_in_cache_buffer[ep][:], data[:l])\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[1].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_in_cache_buffer[ep]))))\n\t}\n\n\t// clear multi-packet size which is total bytes already sent\n\tusbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Mask << usb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Pos)\n\n\t// set byte count, which is total number of bytes to be sent\n\tusbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)\n\tusbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.SetBits((uint32(l) & usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask) << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)\n}\n\nfunc ReceiveUSBControlPacket() ([cdcLineInfoSize]byte, error) {\n\tvar b [cdcLineInfoSize]byte\n\n\t// Wait until OUT transfer is ready.\n\ttimeout := 300000\n\tfor (getEPSTATUS(0) & sam.USB_DEVICE_EPSTATUS_BK0RDY) == 0 {\n\t\ttimeout--\n\t\tif timeout == 0 {\n\t\t\treturn b, ErrUSBReadTimeout\n\t\t}\n\t}\n\n\t// Wait until OUT transfer is completed.\n\ttimeout = 300000\n\tfor (getEPINTFLAG(0) & sam.USB_DEVICE_EPINTFLAG_TRCPT0) == 0 {\n\t\ttimeout--\n\t\tif timeout == 0 {\n\t\t\treturn b, ErrUSBReadTimeout\n\t\t}\n\t}\n\n\t// get data\n\tbytesread := uint32((usbEndpointDescriptors[0].DeviceDescBank[0].PCKSIZE.Get() >>\n\t\tusb_DEVICE_PCKSIZE_BYTE_COUNT_Pos) & usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask)\n\n\tif bytesread != cdcLineInfoSize {\n\t\treturn b, ErrUSBBytesRead\n\t}\n\n\tcopy(b[:7], udd_ep_out_cache_buffer[0][:7])\n\n\treturn b, nil\n}\n\nfunc handleEndpointRx(ep uint32) []byte {\n\t// get data\n\tcount := int((usbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.Get() >>\n\t\tusb_DEVICE_PCKSIZE_BYTE_COUNT_Pos) & usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask)\n\n\treturn udd_ep_out_cache_buffer[ep][:count]\n}\n\n// AckUsbOutTransfer is called to acknowledge the completion of a USB OUT transfer.\nfunc AckUsbOutTransfer(ep uint32) {\n\t// set byte count to zero\n\tusbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)\n\n\t// set multi packet size to 64\n\tusbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.SetBits(64 << usb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Pos)\n\n\t// set ready for next data\n\tsetEPSTATUSCLR(ep, sam.USB_DEVICE_EPSTATUSCLR_BK0RDY)\n\n}\n\nfunc SendZlp() {\n\tusbEndpointDescriptors[0].DeviceDescBank[1].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)\n}\n\nfunc epPacketSize(size uint16) uint32 {\n\tswitch size {\n\tcase 8:\n\t\treturn 0\n\tcase 16:\n\t\treturn 1\n\tcase 32:\n\t\treturn 2\n\tcase 64:\n\t\treturn 3\n\tcase 128:\n\t\treturn 4\n\tcase 256:\n\t\treturn 5\n\tcase 512:\n\t\treturn 6\n\tcase 1023:\n\t\treturn 7\n\tdefault:\n\t\treturn 0\n\t}\n}\n\nfunc getEPCFG(ep uint32) uint8 {\n\tswitch ep {\n\tcase 0:\n\t\treturn sam.USB_DEVICE.EPCFG0.Get()\n\tcase 1:\n\t\treturn sam.USB_DEVICE.EPCFG1.Get()\n\tcase 2:\n\t\treturn sam.USB_DEVICE.EPCFG2.Get()\n\tcase 3:\n\t\treturn sam.USB_DEVICE.EPCFG3.Get()\n\tcase 4:\n\t\treturn sam.USB_DEVICE.EPCFG4.Get()\n\tcase 5:\n\t\treturn sam.USB_DEVICE.EPCFG5.Get()\n\tcase 6:\n\t\treturn sam.USB_DEVICE.EPCFG6.Get()\n\tcase 7:\n\t\treturn sam.USB_DEVICE.EPCFG7.Get()\n\tdefault:\n\t\treturn 0\n\t}\n}\n\nfunc setEPCFG(ep uint32, val uint8) {\n\tswitch ep {\n\tcase 0:\n\t\tsam.USB_DEVICE.EPCFG0.Set(val)\n\tcase 1:\n\t\tsam.USB_DEVICE.EPCFG1.Set(val)\n\tcase 2:\n\t\tsam.USB_DEVICE.EPCFG2.Set(val)\n\tcase 3:\n\t\tsam.USB_DEVICE.EPCFG3.Set(val)\n\tcase 4:\n\t\tsam.USB_DEVICE.EPCFG4.Set(val)\n\tcase 5:\n\t\tsam.USB_DEVICE.EPCFG5.Set(val)\n\tcase 6:\n\t\tsam.USB_DEVICE.EPCFG6.Set(val)\n\tcase 7:\n\t\tsam.USB_DEVICE.EPCFG7.Set(val)\n\tdefault:\n\t\treturn\n\t}\n}\n\nfunc setEPSTATUSCLR(ep uint32, val uint8) {\n\tswitch ep {\n\tcase 0:\n\t\tsam.USB_DEVICE.EPSTATUSCLR0.Set(val)\n\tcase 1:\n\t\tsam.USB_DEVICE.EPSTATUSCLR1.Set(val)\n\tcase 2:\n\t\tsam.USB_DEVICE.EPSTATUSCLR2.Set(val)\n\tcase 3:\n\t\tsam.USB_DEVICE.EPSTATUSCLR3.Set(val)\n\tcase 4:\n\t\tsam.USB_DEVICE.EPSTATUSCLR4.Set(val)\n\tcase 5:\n\t\tsam.USB_DEVICE.EPSTATUSCLR5.Set(val)\n\tcase 6:\n\t\tsam.USB_DEVICE.EPSTATUSCLR6.Set(val)\n\tcase 7:\n\t\tsam.USB_DEVICE.EPSTATUSCLR7.Set(val)\n\tdefault:\n\t\treturn\n\t}\n}\n\nfunc setEPSTATUSSET(ep uint32, val uint8) {\n\tswitch ep {\n\tcase 0:\n\t\tsam.USB_DEVICE.EPSTATUSSET0.Set(val)\n\tcase 1:\n\t\tsam.USB_DEVICE.EPSTATUSSET1.Set(val)\n\tcase 2:\n\t\tsam.USB_DEVICE.EPSTATUSSET2.Set(val)\n\tcase 3:\n\t\tsam.USB_DEVICE.EPSTATUSSET3.Set(val)\n\tcase 4:\n\t\tsam.USB_DEVICE.EPSTATUSSET4.Set(val)\n\tcase 5:\n\t\tsam.USB_DEVICE.EPSTATUSSET5.Set(val)\n\tcase 6:\n\t\tsam.USB_DEVICE.EPSTATUSSET6.Set(val)\n\tcase 7:\n\t\tsam.USB_DEVICE.EPSTATUSSET7.Set(val)\n\tdefault:\n\t\treturn\n\t}\n}\n\nfunc getEPSTATUS(ep uint32) uint8 {\n\tswitch ep {\n\tcase 0:\n\t\treturn sam.USB_DEVICE.EPSTATUS0.Get()\n\tcase 1:\n\t\treturn sam.USB_DEVICE.EPSTATUS1.Get()\n\tcase 2:\n\t\treturn sam.USB_DEVICE.EPSTATUS2.Get()\n\tcase 3:\n\t\treturn sam.USB_DEVICE.EPSTATUS3.Get()\n\tcase 4:\n\t\treturn sam.USB_DEVICE.EPSTATUS4.Get()\n\tcase 5:\n\t\treturn sam.USB_DEVICE.EPSTATUS5.Get()\n\tcase 6:\n\t\treturn sam.USB_DEVICE.EPSTATUS6.Get()\n\tcase 7:\n\t\treturn sam.USB_DEVICE.EPSTATUS7.Get()\n\tdefault:\n\t\treturn 0\n\t}\n}\n\nfunc getEPINTFLAG(ep uint32) uint8 {\n\tswitch ep {\n\tcase 0:\n\t\treturn sam.USB_DEVICE.EPINTFLAG0.Get()\n\tcase 1:\n\t\treturn sam.USB_DEVICE.EPINTFLAG1.Get()\n\tcase 2:\n\t\treturn sam.USB_DEVICE.EPINTFLAG2.Get()\n\tcase 3:\n\t\treturn sam.USB_DEVICE.EPINTFLAG3.Get()\n\tcase 4:\n\t\treturn sam.USB_DEVICE.EPINTFLAG4.Get()\n\tcase 5:\n\t\treturn sam.USB_DEVICE.EPINTFLAG5.Get()\n\tcase 6:\n\t\treturn sam.USB_DEVICE.EPINTFLAG6.Get()\n\tcase 7:\n\t\treturn sam.USB_DEVICE.EPINTFLAG7.Get()\n\tdefault:\n\t\treturn 0\n\t}\n}\n\nfunc setEPINTFLAG(ep uint32, val uint8) {\n\tswitch ep {\n\tcase 0:\n\t\tsam.USB_DEVICE.EPINTFLAG0.Set(val)\n\tcase 1:\n\t\tsam.USB_DEVICE.EPINTFLAG1.Set(val)\n\tcase 2:\n\t\tsam.USB_DEVICE.EPINTFLAG2.Set(val)\n\tcase 3:\n\t\tsam.USB_DEVICE.EPINTFLAG3.Set(val)\n\tcase 4:\n\t\tsam.USB_DEVICE.EPINTFLAG4.Set(val)\n\tcase 5:\n\t\tsam.USB_DEVICE.EPINTFLAG5.Set(val)\n\tcase 6:\n\t\tsam.USB_DEVICE.EPINTFLAG6.Set(val)\n\tcase 7:\n\t\tsam.USB_DEVICE.EPINTFLAG7.Set(val)\n\tdefault:\n\t\treturn\n\t}\n}\n\nfunc setEPINTENCLR(ep uint32, val uint8) {\n\tswitch ep {\n\tcase 0:\n\t\tsam.USB_DEVICE.EPINTENCLR0.Set(val)\n\tcase 1:\n\t\tsam.USB_DEVICE.EPINTENCLR1.Set(val)\n\tcase 2:\n\t\tsam.USB_DEVICE.EPINTENCLR2.Set(val)\n\tcase 3:\n\t\tsam.USB_DEVICE.EPINTENCLR3.Set(val)\n\tcase 4:\n\t\tsam.USB_DEVICE.EPINTENCLR4.Set(val)\n\tcase 5:\n\t\tsam.USB_DEVICE.EPINTENCLR5.Set(val)\n\tcase 6:\n\t\tsam.USB_DEVICE.EPINTENCLR6.Set(val)\n\tcase 7:\n\t\tsam.USB_DEVICE.EPINTENCLR7.Set(val)\n\tdefault:\n\t\treturn\n\t}\n}\n\nfunc setEPINTENSET(ep uint32, val uint8) {\n\tswitch ep {\n\tcase 0:\n\t\tsam.USB_DEVICE.EPINTENSET0.Set(val)\n\tcase 1:\n\t\tsam.USB_DEVICE.EPINTENSET1.Set(val)\n\tcase 2:\n\t\tsam.USB_DEVICE.EPINTENSET2.Set(val)\n\tcase 3:\n\t\tsam.USB_DEVICE.EPINTENSET3.Set(val)\n\tcase 4:\n\t\tsam.USB_DEVICE.EPINTENSET4.Set(val)\n\tcase 5:\n\t\tsam.USB_DEVICE.EPINTENSET5.Set(val)\n\tcase 6:\n\t\tsam.USB_DEVICE.EPINTENSET6.Set(val)\n\tcase 7:\n\t\tsam.USB_DEVICE.EPINTENSET7.Set(val)\n\tdefault:\n\t\treturn\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_atsamd21e18.go",
    "content": "//go:build sam && atsamd21 && atsamd21e18\n\n// Peripheral abstraction layer for the atsamd21.\n//\n// Datasheet:\n// http://ww1.microchip.com/downloads/en/DeviceDoc/SAMD21-Family-DataSheet-DS40001882D.pdf\npackage machine\n\nimport (\n\t\"device/sam\"\n\t\"runtime/interrupt\"\n)\n\nvar (\n\tsercomUSART0 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM0_USART, SERCOM: 0}\n\tsercomUSART1 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM1_USART, SERCOM: 1}\n\tsercomUSART2 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM2_USART, SERCOM: 2}\n\tsercomUSART3 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM3_USART, SERCOM: 3}\n\n\tsercomI2CM0 = &I2C{Bus: sam.SERCOM0_I2CM, SERCOM: 0}\n\tsercomI2CM1 = &I2C{Bus: sam.SERCOM1_I2CM, SERCOM: 1}\n\tsercomI2CM2 = &I2C{Bus: sam.SERCOM2_I2CM, SERCOM: 2}\n\tsercomI2CM3 = &I2C{Bus: sam.SERCOM3_I2CM, SERCOM: 3}\n\n\tsercomSPIM0 = &SPI{Bus: sam.SERCOM0_SPI, SERCOM: 0}\n\tsercomSPIM1 = &SPI{Bus: sam.SERCOM1_SPI, SERCOM: 1}\n\tsercomSPIM2 = &SPI{Bus: sam.SERCOM2_SPI, SERCOM: 2}\n\tsercomSPIM3 = &SPI{Bus: sam.SERCOM3_SPI, SERCOM: 3}\n)\n\nfunc init() {\n\tsercomUSART0.Interrupt = interrupt.New(sam.IRQ_SERCOM0, sercomUSART0.handleInterrupt)\n\tsercomUSART1.Interrupt = interrupt.New(sam.IRQ_SERCOM1, sercomUSART1.handleInterrupt)\n\tsercomUSART2.Interrupt = interrupt.New(sam.IRQ_SERCOM2, sercomUSART2.handleInterrupt)\n\tsercomUSART3.Interrupt = interrupt.New(sam.IRQ_SERCOM3, sercomUSART3.handleInterrupt)\n}\n\n// Return the register and mask to enable a given GPIO pin. This can be used to\n// implement bit-banged drivers.\nfunc (p Pin) PortMaskSet() (*uint32, uint32) {\n\treturn &sam.PORT.OUTSET0.Reg, 1 << uint8(p)\n}\n\n// Return the register and mask to disable a given port. This can be used to\n// implement bit-banged drivers.\nfunc (p Pin) PortMaskClear() (*uint32, uint32) {\n\treturn &sam.PORT.OUTCLR0.Reg, 1 << uint8(p)\n}\n\n// Set the pin to high or low.\n// Warning: only use this on an output pin!\nfunc (p Pin) Set(high bool) {\n\tif high {\n\t\tsam.PORT.OUTSET0.Set(1 << uint8(p))\n\t} else {\n\t\tsam.PORT.OUTCLR0.Set(1 << uint8(p))\n\t}\n}\n\n// Get returns the current value of a GPIO pin when configured as an input or as\n// an output.\nfunc (p Pin) Get() bool {\n\treturn (sam.PORT.IN0.Get()>>uint8(p))&1 > 0\n}\n\n// Configure this pin with the given configuration.\nfunc (p Pin) Configure(config PinConfig) {\n\tswitch config.Mode {\n\tcase PinOutput:\n\t\tsam.PORT.DIRSET0.Set(1 << uint8(p))\n\t\t// output is also set to input enable so pin can read back its own value\n\t\tp.setPinCfg(sam.PORT_PINCFG0_INEN)\n\n\tcase PinInput:\n\t\tsam.PORT.DIRCLR0.Set(1 << uint8(p))\n\t\tp.setPinCfg(sam.PORT_PINCFG0_INEN)\n\n\tcase PinInputPulldown:\n\t\tsam.PORT.DIRCLR0.Set(1 << uint8(p))\n\t\tsam.PORT.OUTCLR0.Set(1 << uint8(p))\n\t\tp.setPinCfg(sam.PORT_PINCFG0_INEN | sam.PORT_PINCFG0_PULLEN)\n\n\tcase PinInputPullup:\n\t\tsam.PORT.DIRCLR0.Set(1 << uint8(p))\n\t\tsam.PORT.OUTSET0.Set(1 << uint8(p))\n\t\tp.setPinCfg(sam.PORT_PINCFG0_INEN | sam.PORT_PINCFG0_PULLEN)\n\n\tcase PinSERCOM:\n\t\tif uint8(p)&1 > 0 {\n\t\t\t// odd pin, so save the even pins\n\t\t\tval := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk\n\t\t\tp.setPMux(val | (uint8(PinSERCOM) << sam.PORT_PMUX0_PMUXO_Pos))\n\t\t} else {\n\t\t\t// even pin, so save the odd pins\n\t\t\tval := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk\n\t\t\tp.setPMux(val | (uint8(PinSERCOM) << sam.PORT_PMUX0_PMUXE_Pos))\n\t\t}\n\t\t// enable port config\n\t\tp.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR | sam.PORT_PINCFG0_INEN)\n\n\tcase PinSERCOMAlt:\n\t\tif uint8(p)&1 > 0 {\n\t\t\t// odd pin, so save the even pins\n\t\t\tval := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk\n\t\t\tp.setPMux(val | (uint8(PinSERCOMAlt) << sam.PORT_PMUX0_PMUXO_Pos))\n\t\t} else {\n\t\t\t// even pin, so save the odd pins\n\t\t\tval := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk\n\t\t\tp.setPMux(val | (uint8(PinSERCOMAlt) << sam.PORT_PMUX0_PMUXE_Pos))\n\t\t}\n\t\t// enable port config\n\t\tp.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR)\n\n\tcase PinCom:\n\t\tif uint8(p)&1 > 0 {\n\t\t\t// odd pin, so save the even pins\n\t\t\tval := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk\n\t\t\tp.setPMux(val | (uint8(PinCom) << sam.PORT_PMUX0_PMUXO_Pos))\n\t\t} else {\n\t\t\t// even pin, so save the odd pins\n\t\t\tval := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk\n\t\t\tp.setPMux(val | (uint8(PinCom) << sam.PORT_PMUX0_PMUXE_Pos))\n\t\t}\n\t\t// enable port config\n\t\tp.setPinCfg(sam.PORT_PINCFG0_PMUXEN)\n\tcase PinAnalog:\n\t\tif uint8(p)&1 > 0 {\n\t\t\t// odd pin, so save the even pins\n\t\t\tval := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk\n\t\t\tp.setPMux(val | (uint8(PinAnalog) << sam.PORT_PMUX0_PMUXO_Pos))\n\t\t} else {\n\t\t\t// even pin, so save the odd pins\n\t\t\tval := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk\n\t\t\tp.setPMux(val | (uint8(PinAnalog) << sam.PORT_PMUX0_PMUXE_Pos))\n\t\t}\n\t\t// enable port config\n\t\tp.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR)\n\t}\n}\n\n// getPMux returns the value for the correct PMUX register for this pin.\nfunc (p Pin) getPMux() uint8 {\n\tswitch p >> 1 {\n\tcase 0:\n\t\treturn sam.PORT.PMUX0_0.Get()\n\tcase 1:\n\t\treturn sam.PORT.PMUX0_1.Get()\n\tcase 2:\n\t\treturn sam.PORT.PMUX0_2.Get()\n\tcase 3:\n\t\treturn sam.PORT.PMUX0_3.Get()\n\tcase 4:\n\t\treturn sam.PORT.PMUX0_4.Get()\n\tcase 5:\n\t\treturn sam.PORT.PMUX0_5.Get()\n\tcase 6:\n\t\treturn sam.PORT.PMUX0_6.Get()\n\tcase 7:\n\t\treturn sam.PORT.PMUX0_7.Get()\n\tcase 8:\n\t\treturn sam.PORT.PMUX0_8.Get()\n\tcase 9:\n\t\treturn sam.PORT.PMUX0_9.Get()\n\tcase 10:\n\t\treturn sam.PORT.PMUX0_10.Get()\n\tcase 11:\n\t\treturn sam.PORT.PMUX0_11.Get()\n\tcase 12:\n\t\treturn sam.PORT.PMUX0_12.Get()\n\tcase 13:\n\t\treturn sam.PORT.PMUX0_13.Get()\n\tcase 14:\n\t\treturn sam.PORT.PMUX0_14.Get()\n\tcase 15:\n\t\treturn sam.PORT.PMUX0_15.Get()\n\tdefault:\n\t\treturn 0\n\t}\n}\n\n// setPMux sets the value for the correct PMUX register for this pin.\nfunc (p Pin) setPMux(val uint8) {\n\tswitch p >> 1 {\n\tcase 0:\n\t\tsam.PORT.PMUX0_0.Set(val)\n\tcase 1:\n\t\tsam.PORT.PMUX0_1.Set(val)\n\tcase 2:\n\t\tsam.PORT.PMUX0_2.Set(val)\n\tcase 3:\n\t\tsam.PORT.PMUX0_3.Set(val)\n\tcase 4:\n\t\tsam.PORT.PMUX0_4.Set(val)\n\tcase 5:\n\t\tsam.PORT.PMUX0_5.Set(val)\n\tcase 6:\n\t\tsam.PORT.PMUX0_6.Set(val)\n\tcase 7:\n\t\tsam.PORT.PMUX0_7.Set(val)\n\tcase 8:\n\t\tsam.PORT.PMUX0_8.Set(val)\n\tcase 9:\n\t\tsam.PORT.PMUX0_9.Set(val)\n\tcase 10:\n\t\tsam.PORT.PMUX0_10.Set(val)\n\tcase 11:\n\t\tsam.PORT.PMUX0_11.Set(val)\n\tcase 12:\n\t\tsam.PORT.PMUX0_12.Set(val)\n\tcase 13:\n\t\tsam.PORT.PMUX0_13.Set(val)\n\tcase 14:\n\t\tsam.PORT.PMUX0_14.Set(val)\n\tcase 15:\n\t\tsam.PORT.PMUX0_15.Set(val)\n\t}\n}\n\n// getPinCfg returns the value for the correct PINCFG register for this pin.\nfunc (p Pin) getPinCfg() uint8 {\n\tswitch p {\n\tcase 0:\n\t\treturn sam.PORT.PINCFG0_0.Get()\n\tcase 1:\n\t\treturn sam.PORT.PINCFG0_1.Get()\n\tcase 2:\n\t\treturn sam.PORT.PINCFG0_2.Get()\n\tcase 3:\n\t\treturn sam.PORT.PINCFG0_3.Get()\n\tcase 4:\n\t\treturn sam.PORT.PINCFG0_4.Get()\n\tcase 5:\n\t\treturn sam.PORT.PINCFG0_5.Get()\n\tcase 6:\n\t\treturn sam.PORT.PINCFG0_6.Get()\n\tcase 7:\n\t\treturn sam.PORT.PINCFG0_7.Get()\n\tcase 8:\n\t\treturn sam.PORT.PINCFG0_8.Get()\n\tcase 9:\n\t\treturn sam.PORT.PINCFG0_9.Get()\n\tcase 10:\n\t\treturn sam.PORT.PINCFG0_10.Get()\n\tcase 11:\n\t\treturn sam.PORT.PINCFG0_11.Get()\n\tcase 12:\n\t\treturn sam.PORT.PINCFG0_12.Get()\n\tcase 13:\n\t\treturn sam.PORT.PINCFG0_13.Get()\n\tcase 14:\n\t\treturn sam.PORT.PINCFG0_14.Get()\n\tcase 15:\n\t\treturn sam.PORT.PINCFG0_15.Get()\n\tcase 16:\n\t\treturn sam.PORT.PINCFG0_16.Get()\n\tcase 17:\n\t\treturn sam.PORT.PINCFG0_17.Get()\n\tcase 18:\n\t\treturn sam.PORT.PINCFG0_18.Get()\n\tcase 19:\n\t\treturn sam.PORT.PINCFG0_19.Get()\n\tcase 20:\n\t\treturn sam.PORT.PINCFG0_20.Get()\n\tcase 21:\n\t\treturn sam.PORT.PINCFG0_21.Get()\n\tcase 22:\n\t\treturn sam.PORT.PINCFG0_22.Get()\n\tcase 23:\n\t\treturn sam.PORT.PINCFG0_23.Get()\n\tcase 24:\n\t\treturn sam.PORT.PINCFG0_24.Get()\n\tcase 25:\n\t\treturn sam.PORT.PINCFG0_25.Get()\n\tcase 26:\n\t\treturn sam.PORT.PINCFG0_26.Get()\n\tcase 27:\n\t\treturn sam.PORT.PINCFG0_27.Get()\n\tcase 28:\n\t\treturn sam.PORT.PINCFG0_28.Get()\n\tcase 29:\n\t\treturn sam.PORT.PINCFG0_29.Get()\n\tcase 30:\n\t\treturn sam.PORT.PINCFG0_30.Get()\n\tcase 31:\n\t\treturn sam.PORT.PINCFG0_31.Get()\n\tdefault:\n\t\treturn 0\n\t}\n}\n\n// setPinCfg sets the value for the correct PINCFG register for this pin.\nfunc (p Pin) setPinCfg(val uint8) {\n\tswitch p {\n\tcase 0:\n\t\tsam.PORT.PINCFG0_0.Set(val)\n\tcase 1:\n\t\tsam.PORT.PINCFG0_1.Set(val)\n\tcase 2:\n\t\tsam.PORT.PINCFG0_2.Set(val)\n\tcase 3:\n\t\tsam.PORT.PINCFG0_3.Set(val)\n\tcase 4:\n\t\tsam.PORT.PINCFG0_4.Set(val)\n\tcase 5:\n\t\tsam.PORT.PINCFG0_5.Set(val)\n\tcase 6:\n\t\tsam.PORT.PINCFG0_6.Set(val)\n\tcase 7:\n\t\tsam.PORT.PINCFG0_7.Set(val)\n\tcase 8:\n\t\tsam.PORT.PINCFG0_8.Set(val)\n\tcase 9:\n\t\tsam.PORT.PINCFG0_9.Set(val)\n\tcase 10:\n\t\tsam.PORT.PINCFG0_10.Set(val)\n\tcase 11:\n\t\tsam.PORT.PINCFG0_11.Set(val)\n\tcase 12:\n\t\tsam.PORT.PINCFG0_12.Set(val)\n\tcase 13:\n\t\tsam.PORT.PINCFG0_13.Set(val)\n\tcase 14:\n\t\tsam.PORT.PINCFG0_14.Set(val)\n\tcase 15:\n\t\tsam.PORT.PINCFG0_15.Set(val)\n\tcase 16:\n\t\tsam.PORT.PINCFG0_16.Set(val)\n\tcase 17:\n\t\tsam.PORT.PINCFG0_17.Set(val)\n\tcase 18:\n\t\tsam.PORT.PINCFG0_18.Set(val)\n\tcase 19:\n\t\tsam.PORT.PINCFG0_19.Set(val)\n\tcase 20:\n\t\tsam.PORT.PINCFG0_20.Set(val)\n\tcase 21:\n\t\tsam.PORT.PINCFG0_21.Set(val)\n\tcase 22:\n\t\tsam.PORT.PINCFG0_22.Set(val)\n\tcase 23:\n\t\tsam.PORT.PINCFG0_23.Set(val)\n\tcase 24:\n\t\tsam.PORT.PINCFG0_24.Set(val)\n\tcase 25:\n\t\tsam.PORT.PINCFG0_25.Set(val)\n\tcase 26:\n\t\tsam.PORT.PINCFG0_26.Set(val)\n\tcase 27:\n\t\tsam.PORT.PINCFG0_27.Set(val)\n\tcase 28:\n\t\tsam.PORT.PINCFG0_28.Set(val)\n\tcase 29:\n\t\tsam.PORT.PINCFG0_29.Set(val)\n\tcase 30:\n\t\tsam.PORT.PINCFG0_30.Set(val)\n\tcase 31:\n\t\tsam.PORT.PINCFG0_31.Set(val)\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_atsamd21g18.go",
    "content": "//go:build sam && atsamd21 && atsamd21g18\n\n// Peripheral abstraction layer for the atsamd21.\n//\n// Datasheet:\n// http://ww1.microchip.com/downloads/en/DeviceDoc/SAMD21-Family-DataSheet-DS40001882D.pdf\npackage machine\n\nimport (\n\t\"device/sam\"\n\t\"runtime/interrupt\"\n)\n\nvar (\n\tsercomUSART0 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM0_USART, SERCOM: 0}\n\tsercomUSART1 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM1_USART, SERCOM: 1}\n\tsercomUSART2 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM2_USART, SERCOM: 2}\n\tsercomUSART3 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM3_USART, SERCOM: 3}\n\tsercomUSART4 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM4_USART, SERCOM: 4}\n\tsercomUSART5 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM5_USART, SERCOM: 5}\n\n\tsercomI2CM0 = &I2C{Bus: sam.SERCOM0_I2CM, SERCOM: 0}\n\tsercomI2CM1 = &I2C{Bus: sam.SERCOM1_I2CM, SERCOM: 1}\n\tsercomI2CM2 = &I2C{Bus: sam.SERCOM2_I2CM, SERCOM: 2}\n\tsercomI2CM3 = &I2C{Bus: sam.SERCOM3_I2CM, SERCOM: 3}\n\tsercomI2CM4 = &I2C{Bus: sam.SERCOM4_I2CM, SERCOM: 4}\n\tsercomI2CM5 = &I2C{Bus: sam.SERCOM5_I2CM, SERCOM: 5}\n\n\tsercomSPIM0 = &SPI{Bus: sam.SERCOM0_SPI, SERCOM: 0}\n\tsercomSPIM1 = &SPI{Bus: sam.SERCOM1_SPI, SERCOM: 1}\n\tsercomSPIM2 = &SPI{Bus: sam.SERCOM2_SPI, SERCOM: 2}\n\tsercomSPIM3 = &SPI{Bus: sam.SERCOM3_SPI, SERCOM: 3}\n\tsercomSPIM4 = &SPI{Bus: sam.SERCOM4_SPI, SERCOM: 4}\n\tsercomSPIM5 = &SPI{Bus: sam.SERCOM5_SPI, SERCOM: 5}\n)\n\nfunc init() {\n\tsercomUSART0.Interrupt = interrupt.New(sam.IRQ_SERCOM0, sercomUSART0.handleInterrupt)\n\tsercomUSART1.Interrupt = interrupt.New(sam.IRQ_SERCOM1, sercomUSART1.handleInterrupt)\n\tsercomUSART2.Interrupt = interrupt.New(sam.IRQ_SERCOM2, sercomUSART2.handleInterrupt)\n\tsercomUSART3.Interrupt = interrupt.New(sam.IRQ_SERCOM3, sercomUSART3.handleInterrupt)\n\tsercomUSART4.Interrupt = interrupt.New(sam.IRQ_SERCOM4, sercomUSART4.handleInterrupt)\n\tsercomUSART5.Interrupt = interrupt.New(sam.IRQ_SERCOM5, sercomUSART5.handleInterrupt)\n}\n\n// Return the register and mask to enable a given GPIO pin. This can be used to\n// implement bit-banged drivers.\nfunc (p Pin) PortMaskSet() (*uint32, uint32) {\n\t// Note: using PORT_IOBUS for faster pin accesses.\n\t// The regular PORT registers appear to take around 4 clock cycles to store,\n\t// which is longer than the ws2812 driver expects. The IOBUS is is fast\n\t// enough to avoid this issue.\n\tif p < 32 {\n\t\treturn &sam.PORT_IOBUS.OUTSET0.Reg, 1 << uint8(p)\n\t} else {\n\t\treturn &sam.PORT_IOBUS.OUTSET1.Reg, 1 << uint8(p-32)\n\t}\n}\n\n// Return the register and mask to disable a given port. This can be used to\n// implement bit-banged drivers.\nfunc (p Pin) PortMaskClear() (*uint32, uint32) {\n\tif p < 32 {\n\t\treturn &sam.PORT_IOBUS.OUTCLR0.Reg, 1 << uint8(p)\n\t} else {\n\t\treturn &sam.PORT_IOBUS.OUTCLR1.Reg, 1 << uint8(p-32)\n\t}\n}\n\n// Set the pin to high or low.\n// Warning: only use this on an output pin!\nfunc (p Pin) Set(high bool) {\n\tif p < 32 {\n\t\tif high {\n\t\t\tsam.PORT.OUTSET0.Set(1 << uint8(p))\n\t\t} else {\n\t\t\tsam.PORT.OUTCLR0.Set(1 << uint8(p))\n\t\t}\n\t} else {\n\t\tif high {\n\t\t\tsam.PORT.OUTSET1.Set(1 << uint8(p-32))\n\t\t} else {\n\t\t\tsam.PORT.OUTCLR1.Set(1 << uint8(p-32))\n\t\t}\n\t}\n}\n\n// Get returns the current value of a GPIO pin when configured as an input or as\n// an output.\nfunc (p Pin) Get() bool {\n\tif p < 32 {\n\t\treturn (sam.PORT.IN0.Get()>>uint8(p))&1 > 0\n\t} else {\n\t\treturn (sam.PORT.IN1.Get()>>uint8(p-32))&1 > 0\n\t}\n}\n\n// Configure this pin with the given configuration.\nfunc (p Pin) Configure(config PinConfig) {\n\tswitch config.Mode {\n\tcase PinOutput:\n\t\tif p < 32 {\n\t\t\tsam.PORT.DIRSET0.Set(1 << uint8(p))\n\t\t\t// output is also set to input enable so pin can read back its own value\n\t\t\tp.setPinCfg(sam.PORT_PINCFG0_INEN)\n\t\t} else {\n\t\t\tsam.PORT.DIRSET1.Set(1 << uint8(p-32))\n\t\t\t// output is also set to input enable so pin can read back its own value\n\t\t\tp.setPinCfg(sam.PORT_PINCFG0_INEN)\n\t\t}\n\n\tcase PinInput:\n\t\tif p < 32 {\n\t\t\tsam.PORT.DIRCLR0.Set(1 << uint8(p))\n\t\t\tp.setPinCfg(sam.PORT_PINCFG0_INEN)\n\t\t} else {\n\t\t\tsam.PORT.DIRCLR1.Set(1 << uint8(p-32))\n\t\t\tp.setPinCfg(sam.PORT_PINCFG0_INEN)\n\t\t}\n\n\tcase PinInputPulldown:\n\t\tif p < 32 {\n\t\t\tsam.PORT.DIRCLR0.Set(1 << uint8(p))\n\t\t\tsam.PORT.OUTCLR0.Set(1 << uint8(p))\n\t\t\tp.setPinCfg(sam.PORT_PINCFG0_INEN | sam.PORT_PINCFG0_PULLEN)\n\t\t} else {\n\t\t\tsam.PORT.DIRCLR1.Set(1 << uint8(p-32))\n\t\t\tsam.PORT.OUTCLR1.Set(1 << uint8(p-32))\n\t\t\tp.setPinCfg(sam.PORT_PINCFG0_INEN | sam.PORT_PINCFG0_PULLEN)\n\t\t}\n\n\tcase PinInputPullup:\n\t\tif p < 32 {\n\t\t\tsam.PORT.DIRCLR0.Set(1 << uint8(p))\n\t\t\tsam.PORT.OUTSET0.Set(1 << uint8(p))\n\t\t\tp.setPinCfg(sam.PORT_PINCFG0_INEN | sam.PORT_PINCFG0_PULLEN)\n\t\t} else {\n\t\t\tsam.PORT.DIRCLR1.Set(1 << uint8(p-32))\n\t\t\tsam.PORT.OUTSET1.Set(1 << uint8(p-32))\n\t\t\tp.setPinCfg(sam.PORT_PINCFG0_INEN | sam.PORT_PINCFG0_PULLEN)\n\t\t}\n\n\tcase PinSERCOM:\n\t\tif p&1 > 0 {\n\t\t\t// odd pin, so save the even pins\n\t\t\tval := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk\n\t\t\tp.setPMux(val | (uint8(PinSERCOM) << sam.PORT_PMUX0_PMUXO_Pos))\n\t\t} else {\n\t\t\t// even pin, so save the odd pins\n\t\t\tval := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk\n\t\t\tp.setPMux(val | (uint8(PinSERCOM) << sam.PORT_PMUX0_PMUXE_Pos))\n\t\t}\n\t\t// enable port config\n\t\tp.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR | sam.PORT_PINCFG0_INEN)\n\n\tcase PinSERCOMAlt:\n\t\tif p&1 > 0 {\n\t\t\t// odd pin, so save the even pins\n\t\t\tval := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk\n\t\t\tp.setPMux(val | (uint8(PinSERCOMAlt) << sam.PORT_PMUX0_PMUXO_Pos))\n\t\t} else {\n\t\t\t// even pin, so save the odd pins\n\t\t\tval := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk\n\t\t\tp.setPMux(val | (uint8(PinSERCOMAlt) << sam.PORT_PMUX0_PMUXE_Pos))\n\t\t}\n\t\t// enable port config\n\t\tp.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR)\n\n\tcase PinCom:\n\t\tif p&1 > 0 {\n\t\t\t// odd pin, so save the even pins\n\t\t\tval := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk\n\t\t\tp.setPMux(val | (uint8(PinCom) << sam.PORT_PMUX0_PMUXO_Pos))\n\t\t} else {\n\t\t\t// even pin, so save the odd pins\n\t\t\tval := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk\n\t\t\tp.setPMux(val | (uint8(PinCom) << sam.PORT_PMUX0_PMUXE_Pos))\n\t\t}\n\t\t// enable port config\n\t\tp.setPinCfg(sam.PORT_PINCFG0_PMUXEN)\n\tcase PinAnalog:\n\t\tif p&1 > 0 {\n\t\t\t// odd pin, so save the even pins\n\t\t\tval := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk\n\t\t\tp.setPMux(val | (uint8(PinAnalog) << sam.PORT_PMUX0_PMUXO_Pos))\n\t\t} else {\n\t\t\t// even pin, so save the odd pins\n\t\t\tval := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk\n\t\t\tp.setPMux(val | (uint8(PinAnalog) << sam.PORT_PMUX0_PMUXE_Pos))\n\t\t}\n\t\t// enable port config\n\t\tp.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR)\n\t}\n}\n\n// getPMux returns the value for the correct PMUX register for this pin.\nfunc (p Pin) getPMux() uint8 {\n\tswitch uint8(p) >> 1 {\n\tcase 0:\n\t\treturn sam.PORT.PMUX0_0.Get()\n\tcase 1:\n\t\treturn sam.PORT.PMUX0_1.Get()\n\tcase 2:\n\t\treturn sam.PORT.PMUX0_2.Get()\n\tcase 3:\n\t\treturn sam.PORT.PMUX0_3.Get()\n\tcase 4:\n\t\treturn sam.PORT.PMUX0_4.Get()\n\tcase 5:\n\t\treturn sam.PORT.PMUX0_5.Get()\n\tcase 6:\n\t\treturn sam.PORT.PMUX0_6.Get()\n\tcase 7:\n\t\treturn sam.PORT.PMUX0_7.Get()\n\tcase 8:\n\t\treturn sam.PORT.PMUX0_8.Get()\n\tcase 9:\n\t\treturn sam.PORT.PMUX0_9.Get()\n\tcase 10:\n\t\treturn sam.PORT.PMUX0_10.Get()\n\tcase 11:\n\t\treturn sam.PORT.PMUX0_11.Get()\n\tcase 12:\n\t\treturn sam.PORT.PMUX0_12.Get()\n\tcase 13:\n\t\treturn sam.PORT.PMUX0_13.Get()\n\tcase 14:\n\t\treturn sam.PORT.PMUX0_14.Get()\n\tcase 15:\n\t\treturn sam.PORT.PMUX0_15.Get()\n\tcase 16:\n\t\treturn uint8(sam.PORT.PMUX1_0.Get()>>0) & 0xff\n\tcase 17:\n\t\treturn uint8(sam.PORT.PMUX1_0.Get()>>8) & 0xff\n\tcase 18:\n\t\treturn uint8(sam.PORT.PMUX1_0.Get()>>16) & 0xff\n\tcase 19:\n\t\treturn uint8(sam.PORT.PMUX1_0.Get()>>24) & 0xff\n\tcase 20:\n\t\treturn uint8(sam.PORT.PMUX1_4.Get()>>0) & 0xff\n\tcase 21:\n\t\treturn uint8(sam.PORT.PMUX1_4.Get()>>8) & 0xff\n\tcase 22:\n\t\treturn uint8(sam.PORT.PMUX1_4.Get()>>16) & 0xff\n\tcase 23:\n\t\treturn uint8(sam.PORT.PMUX1_4.Get()>>24) & 0xff\n\tcase 24:\n\t\treturn uint8(sam.PORT.PMUX1_8.Get()>>0) & 0xff\n\tcase 25:\n\t\treturn uint8(sam.PORT.PMUX1_8.Get()>>8) & 0xff\n\tcase 26:\n\t\treturn uint8(sam.PORT.PMUX1_8.Get()>>16) & 0xff\n\tcase 27:\n\t\treturn uint8(sam.PORT.PMUX1_8.Get()>>24) & 0xff\n\tcase 28:\n\t\treturn uint8(sam.PORT.PMUX1_12.Get()>>0) & 0xff\n\tcase 29:\n\t\treturn uint8(sam.PORT.PMUX1_12.Get()>>8) & 0xff\n\tcase 30:\n\t\treturn uint8(sam.PORT.PMUX1_12.Get()>>16) & 0xff\n\tcase 31:\n\t\treturn uint8(sam.PORT.PMUX1_12.Get()>>24) & 0xff\n\tdefault:\n\t\treturn 0\n\t}\n}\n\n// setPMux sets the value for the correct PMUX register for this pin.\nfunc (p Pin) setPMux(val uint8) {\n\tswitch uint8(p) >> 1 {\n\tcase 0:\n\t\tsam.PORT.PMUX0_0.Set(val)\n\tcase 1:\n\t\tsam.PORT.PMUX0_1.Set(val)\n\tcase 2:\n\t\tsam.PORT.PMUX0_2.Set(val)\n\tcase 3:\n\t\tsam.PORT.PMUX0_3.Set(val)\n\tcase 4:\n\t\tsam.PORT.PMUX0_4.Set(val)\n\tcase 5:\n\t\tsam.PORT.PMUX0_5.Set(val)\n\tcase 6:\n\t\tsam.PORT.PMUX0_6.Set(val)\n\tcase 7:\n\t\tsam.PORT.PMUX0_7.Set(val)\n\tcase 8:\n\t\tsam.PORT.PMUX0_8.Set(val)\n\tcase 9:\n\t\tsam.PORT.PMUX0_9.Set(val)\n\tcase 10:\n\t\tsam.PORT.PMUX0_10.Set(val)\n\tcase 11:\n\t\tsam.PORT.PMUX0_11.Set(val)\n\tcase 12:\n\t\tsam.PORT.PMUX0_12.Set(val)\n\tcase 13:\n\t\tsam.PORT.PMUX0_13.Set(val)\n\tcase 14:\n\t\tsam.PORT.PMUX0_14.Set(val)\n\tcase 15:\n\t\tsam.PORT.PMUX0_15.Set(val)\n\tcase 16:\n\t\tsam.PORT.PMUX1_0.ReplaceBits(uint32(val), 0xff, 0)\n\tcase 17:\n\t\tsam.PORT.PMUX1_0.ReplaceBits(uint32(val), 0xff, 8)\n\tcase 18:\n\t\tsam.PORT.PMUX1_0.ReplaceBits(uint32(val), 0xff, 16)\n\tcase 19:\n\t\tsam.PORT.PMUX1_0.ReplaceBits(uint32(val), 0xff, 24)\n\tcase 20:\n\t\tsam.PORT.PMUX1_4.ReplaceBits(uint32(val), 0xff, 0)\n\tcase 21:\n\t\tsam.PORT.PMUX1_4.ReplaceBits(uint32(val), 0xff, 8)\n\tcase 22:\n\t\tsam.PORT.PMUX1_4.ReplaceBits(uint32(val), 0xff, 16)\n\tcase 23:\n\t\tsam.PORT.PMUX1_4.ReplaceBits(uint32(val), 0xff, 24)\n\tcase 24:\n\t\tsam.PORT.PMUX1_8.ReplaceBits(uint32(val), 0xff, 0)\n\tcase 25:\n\t\tsam.PORT.PMUX1_8.ReplaceBits(uint32(val), 0xff, 8)\n\tcase 26:\n\t\tsam.PORT.PMUX1_8.ReplaceBits(uint32(val), 0xff, 16)\n\tcase 27:\n\t\tsam.PORT.PMUX1_8.ReplaceBits(uint32(val), 0xff, 24)\n\tcase 28:\n\t\tsam.PORT.PMUX1_12.ReplaceBits(uint32(val), 0xff, 0)\n\tcase 29:\n\t\tsam.PORT.PMUX1_12.ReplaceBits(uint32(val), 0xff, 8)\n\tcase 30:\n\t\tsam.PORT.PMUX1_12.ReplaceBits(uint32(val), 0xff, 16)\n\tcase 31:\n\t\tsam.PORT.PMUX1_12.ReplaceBits(uint32(val), 0xff, 24)\n\t}\n}\n\n// getPinCfg returns the value for the correct PINCFG register for this pin.\nfunc (p Pin) getPinCfg() uint8 {\n\tswitch p {\n\tcase 0:\n\t\treturn sam.PORT.PINCFG0_0.Get()\n\tcase 1:\n\t\treturn sam.PORT.PINCFG0_1.Get()\n\tcase 2:\n\t\treturn sam.PORT.PINCFG0_2.Get()\n\tcase 3:\n\t\treturn sam.PORT.PINCFG0_3.Get()\n\tcase 4:\n\t\treturn sam.PORT.PINCFG0_4.Get()\n\tcase 5:\n\t\treturn sam.PORT.PINCFG0_5.Get()\n\tcase 6:\n\t\treturn sam.PORT.PINCFG0_6.Get()\n\tcase 7:\n\t\treturn sam.PORT.PINCFG0_7.Get()\n\tcase 8:\n\t\treturn sam.PORT.PINCFG0_8.Get()\n\tcase 9:\n\t\treturn sam.PORT.PINCFG0_9.Get()\n\tcase 10:\n\t\treturn sam.PORT.PINCFG0_10.Get()\n\tcase 11:\n\t\treturn sam.PORT.PINCFG0_11.Get()\n\tcase 12:\n\t\treturn sam.PORT.PINCFG0_12.Get()\n\tcase 13:\n\t\treturn sam.PORT.PINCFG0_13.Get()\n\tcase 14:\n\t\treturn sam.PORT.PINCFG0_14.Get()\n\tcase 15:\n\t\treturn sam.PORT.PINCFG0_15.Get()\n\tcase 16:\n\t\treturn sam.PORT.PINCFG0_16.Get()\n\tcase 17:\n\t\treturn sam.PORT.PINCFG0_17.Get()\n\tcase 18:\n\t\treturn sam.PORT.PINCFG0_18.Get()\n\tcase 19:\n\t\treturn sam.PORT.PINCFG0_19.Get()\n\tcase 20:\n\t\treturn sam.PORT.PINCFG0_20.Get()\n\tcase 21:\n\t\treturn sam.PORT.PINCFG0_21.Get()\n\tcase 22:\n\t\treturn sam.PORT.PINCFG0_22.Get()\n\tcase 23:\n\t\treturn sam.PORT.PINCFG0_23.Get()\n\tcase 24:\n\t\treturn sam.PORT.PINCFG0_24.Get()\n\tcase 25:\n\t\treturn sam.PORT.PINCFG0_25.Get()\n\tcase 26:\n\t\treturn sam.PORT.PINCFG0_26.Get()\n\tcase 27:\n\t\treturn sam.PORT.PINCFG0_27.Get()\n\tcase 28:\n\t\treturn sam.PORT.PINCFG0_28.Get()\n\tcase 29:\n\t\treturn sam.PORT.PINCFG0_29.Get()\n\tcase 30:\n\t\treturn sam.PORT.PINCFG0_30.Get()\n\tcase 31:\n\t\treturn sam.PORT.PINCFG0_31.Get()\n\tcase 32: // PB00\n\t\treturn uint8(sam.PORT.PINCFG1_0.Get()>>0) & 0xff\n\tcase 33: // PB01\n\t\treturn uint8(sam.PORT.PINCFG1_0.Get()>>8) & 0xff\n\tcase 34: // PB02\n\t\treturn uint8(sam.PORT.PINCFG1_0.Get()>>16) & 0xff\n\tcase 35: // PB03\n\t\treturn uint8(sam.PORT.PINCFG1_0.Get()>>24) & 0xff\n\tcase 36: // PB04\n\t\treturn uint8(sam.PORT.PINCFG1_4.Get()>>0) & 0xff\n\tcase 37: // PB05\n\t\treturn uint8(sam.PORT.PINCFG1_4.Get()>>8) & 0xff\n\tcase 38: // PB06\n\t\treturn uint8(sam.PORT.PINCFG1_4.Get()>>16) & 0xff\n\tcase 39: // PB07\n\t\treturn uint8(sam.PORT.PINCFG1_4.Get()>>24) & 0xff\n\tcase 40: // PB08\n\t\treturn uint8(sam.PORT.PINCFG1_8.Get()>>0) & 0xff\n\tcase 41: // PB09\n\t\treturn uint8(sam.PORT.PINCFG1_8.Get()>>8) & 0xff\n\tcase 42: // PB10\n\t\treturn uint8(sam.PORT.PINCFG1_8.Get()>>16) & 0xff\n\tcase 43: // PB11\n\t\treturn uint8(sam.PORT.PINCFG1_8.Get()>>24) & 0xff\n\tcase 44: // PB12\n\t\treturn uint8(sam.PORT.PINCFG1_12.Get()>>0) & 0xff\n\tcase 45: // PB13\n\t\treturn uint8(sam.PORT.PINCFG1_12.Get()>>8) & 0xff\n\tcase 46: // PB14\n\t\treturn uint8(sam.PORT.PINCFG1_12.Get()>>16) & 0xff\n\tcase 47: // PB15\n\t\treturn uint8(sam.PORT.PINCFG1_12.Get()>>24) & 0xff\n\tcase 48: // PB16\n\t\treturn uint8(sam.PORT.PINCFG1_16.Get()>>0) & 0xff\n\tcase 49: // PB17\n\t\treturn uint8(sam.PORT.PINCFG1_16.Get()>>8) & 0xff\n\tcase 50: // PB18\n\t\treturn uint8(sam.PORT.PINCFG1_16.Get()>>16) & 0xff\n\tcase 51: // PB19\n\t\treturn uint8(sam.PORT.PINCFG1_16.Get()>>24) & 0xff\n\tcase 52: // PB20\n\t\treturn uint8(sam.PORT.PINCFG1_20.Get()>>0) & 0xff\n\tcase 53: // PB21\n\t\treturn uint8(sam.PORT.PINCFG1_20.Get()>>8) & 0xff\n\tcase 54: // PB22\n\t\treturn uint8(sam.PORT.PINCFG1_20.Get()>>16) & 0xff\n\tcase 55: // PB23\n\t\treturn uint8(sam.PORT.PINCFG1_20.Get()>>24) & 0xff\n\tcase 56: // PB24\n\t\treturn uint8(sam.PORT.PINCFG1_24.Get()>>0) & 0xff\n\tcase 57: // PB25\n\t\treturn uint8(sam.PORT.PINCFG1_24.Get()>>8) & 0xff\n\tcase 58: // PB26\n\t\treturn uint8(sam.PORT.PINCFG1_24.Get()>>16) & 0xff\n\tcase 59: // PB27\n\t\treturn uint8(sam.PORT.PINCFG1_24.Get()>>24) & 0xff\n\tcase 60: // PB28\n\t\treturn uint8(sam.PORT.PINCFG1_28.Get()>>0) & 0xff\n\tcase 61: // PB29\n\t\treturn uint8(sam.PORT.PINCFG1_28.Get()>>8) & 0xff\n\tcase 62: // PB30\n\t\treturn uint8(sam.PORT.PINCFG1_28.Get()>>16) & 0xff\n\tcase 63: // PB31\n\t\treturn uint8(sam.PORT.PINCFG1_28.Get()>>24) & 0xff\n\tdefault:\n\t\treturn 0\n\t}\n}\n\n// setPinCfg sets the value for the correct PINCFG register for this pin.\nfunc (p Pin) setPinCfg(val uint8) {\n\tswitch p {\n\tcase 0:\n\t\tsam.PORT.PINCFG0_0.Set(val)\n\tcase 1:\n\t\tsam.PORT.PINCFG0_1.Set(val)\n\tcase 2:\n\t\tsam.PORT.PINCFG0_2.Set(val)\n\tcase 3:\n\t\tsam.PORT.PINCFG0_3.Set(val)\n\tcase 4:\n\t\tsam.PORT.PINCFG0_4.Set(val)\n\tcase 5:\n\t\tsam.PORT.PINCFG0_5.Set(val)\n\tcase 6:\n\t\tsam.PORT.PINCFG0_6.Set(val)\n\tcase 7:\n\t\tsam.PORT.PINCFG0_7.Set(val)\n\tcase 8:\n\t\tsam.PORT.PINCFG0_8.Set(val)\n\tcase 9:\n\t\tsam.PORT.PINCFG0_9.Set(val)\n\tcase 10:\n\t\tsam.PORT.PINCFG0_10.Set(val)\n\tcase 11:\n\t\tsam.PORT.PINCFG0_11.Set(val)\n\tcase 12:\n\t\tsam.PORT.PINCFG0_12.Set(val)\n\tcase 13:\n\t\tsam.PORT.PINCFG0_13.Set(val)\n\tcase 14:\n\t\tsam.PORT.PINCFG0_14.Set(val)\n\tcase 15:\n\t\tsam.PORT.PINCFG0_15.Set(val)\n\tcase 16:\n\t\tsam.PORT.PINCFG0_16.Set(val)\n\tcase 17:\n\t\tsam.PORT.PINCFG0_17.Set(val)\n\tcase 18:\n\t\tsam.PORT.PINCFG0_18.Set(val)\n\tcase 19:\n\t\tsam.PORT.PINCFG0_19.Set(val)\n\tcase 20:\n\t\tsam.PORT.PINCFG0_20.Set(val)\n\tcase 21:\n\t\tsam.PORT.PINCFG0_21.Set(val)\n\tcase 22:\n\t\tsam.PORT.PINCFG0_22.Set(val)\n\tcase 23:\n\t\tsam.PORT.PINCFG0_23.Set(val)\n\tcase 24:\n\t\tsam.PORT.PINCFG0_24.Set(val)\n\tcase 25:\n\t\tsam.PORT.PINCFG0_25.Set(val)\n\tcase 26:\n\t\tsam.PORT.PINCFG0_26.Set(val)\n\tcase 27:\n\t\tsam.PORT.PINCFG0_27.Set(val)\n\tcase 28:\n\t\tsam.PORT.PINCFG0_28.Set(val)\n\tcase 29:\n\t\tsam.PORT.PINCFG0_29.Set(val)\n\tcase 30:\n\t\tsam.PORT.PINCFG0_30.Set(val)\n\tcase 31:\n\t\tsam.PORT.PINCFG0_31.Set(val)\n\tcase 32: // PB00\n\t\tsam.PORT.PINCFG1_0.ReplaceBits(uint32(val), 0xff, 0)\n\tcase 33: // PB01\n\t\tsam.PORT.PINCFG1_0.ReplaceBits(uint32(val), 0xff, 8)\n\tcase 34: // PB02\n\t\tsam.PORT.PINCFG1_0.ReplaceBits(uint32(val), 0xff, 16)\n\tcase 35: // PB03\n\t\tsam.PORT.PINCFG1_0.ReplaceBits(uint32(val), 0xff, 24)\n\tcase 36: // PB04\n\t\tsam.PORT.PINCFG1_4.ReplaceBits(uint32(val), 0xff, 0)\n\tcase 37: // PB05\n\t\tsam.PORT.PINCFG1_4.ReplaceBits(uint32(val), 0xff, 8)\n\tcase 38: // PB06\n\t\tsam.PORT.PINCFG1_4.ReplaceBits(uint32(val), 0xff, 16)\n\tcase 39: // PB07\n\t\tsam.PORT.PINCFG1_4.ReplaceBits(uint32(val), 0xff, 24)\n\tcase 40: // PB08\n\t\tsam.PORT.PINCFG1_8.ReplaceBits(uint32(val), 0xff, 0)\n\tcase 41: // PB09\n\t\tsam.PORT.PINCFG1_8.ReplaceBits(uint32(val), 0xff, 8)\n\tcase 42: // PB10\n\t\tsam.PORT.PINCFG1_8.ReplaceBits(uint32(val), 0xff, 16)\n\tcase 43: // PB11\n\t\tsam.PORT.PINCFG1_8.ReplaceBits(uint32(val), 0xff, 24)\n\tcase 44: // PB12\n\t\tsam.PORT.PINCFG1_12.ReplaceBits(uint32(val), 0xff, 0)\n\tcase 45: // PB13\n\t\tsam.PORT.PINCFG1_12.ReplaceBits(uint32(val), 0xff, 8)\n\tcase 46: // PB14\n\t\tsam.PORT.PINCFG1_12.ReplaceBits(uint32(val), 0xff, 16)\n\tcase 47: // PB15\n\t\tsam.PORT.PINCFG1_12.ReplaceBits(uint32(val), 0xff, 24)\n\tcase 48: // PB16\n\t\tsam.PORT.PINCFG1_16.ReplaceBits(uint32(val), 0xff, 0)\n\tcase 49: // PB17\n\t\tsam.PORT.PINCFG1_16.ReplaceBits(uint32(val), 0xff, 8)\n\tcase 50: // PB18\n\t\tsam.PORT.PINCFG1_16.ReplaceBits(uint32(val), 0xff, 16)\n\tcase 51: // PB19\n\t\tsam.PORT.PINCFG1_16.ReplaceBits(uint32(val), 0xff, 24)\n\tcase 52: // PB20\n\t\tsam.PORT.PINCFG1_20.ReplaceBits(uint32(val), 0xff, 0)\n\tcase 53: // PB21\n\t\tsam.PORT.PINCFG1_20.ReplaceBits(uint32(val), 0xff, 8)\n\tcase 54: // PB22\n\t\tsam.PORT.PINCFG1_20.ReplaceBits(uint32(val), 0xff, 16)\n\tcase 55: // PB23\n\t\tsam.PORT.PINCFG1_20.ReplaceBits(uint32(val), 0xff, 24)\n\tcase 56: // PB24\n\t\tsam.PORT.PINCFG1_24.ReplaceBits(uint32(val), 0xff, 0)\n\tcase 57: // PB25\n\t\tsam.PORT.PINCFG1_24.ReplaceBits(uint32(val), 0xff, 8)\n\tcase 58: // PB26\n\t\tsam.PORT.PINCFG1_24.ReplaceBits(uint32(val), 0xff, 16)\n\tcase 59: // PB27\n\t\tsam.PORT.PINCFG1_24.ReplaceBits(uint32(val), 0xff, 24)\n\tcase 60: // PB28\n\t\tsam.PORT.PINCFG1_28.ReplaceBits(uint32(val), 0xff, 0)\n\tcase 61: // PB29\n\t\tsam.PORT.PINCFG1_28.ReplaceBits(uint32(val), 0xff, 8)\n\tcase 62: // PB30\n\t\tsam.PORT.PINCFG1_28.ReplaceBits(uint32(val), 0xff, 16)\n\tcase 63: // PB31\n\t\tsam.PORT.PINCFG1_28.ReplaceBits(uint32(val), 0xff, 24)\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_atsamd51.go",
    "content": "//go:build (sam && atsamd51) || (sam && atsame5x)\n\n// Peripheral abstraction layer for the atsamd51.\n//\n// Datasheet:\n// http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf\npackage machine\n\nimport (\n\t\"device/arm\"\n\t\"device/sam\"\n\t\"errors\"\n\t\"internal/binary\"\n\t\"runtime/interrupt\"\n\t\"unsafe\"\n)\n\nconst deviceName = sam.Device\n\n// DS60001507, Section 9.6: Serial Number\nvar deviceIDAddr = []uintptr{0x008061FC, 0x00806010, 0x00806014, 0x00806018}\n\nfunc CPUFrequency() uint32 {\n\treturn 120000000\n}\n\nconst (\n\tPinAnalog        PinMode = 1\n\tPinSERCOM        PinMode = 2\n\tPinSERCOMAlt     PinMode = 3\n\tPinTimer         PinMode = 4\n\tPinTimerAlt      PinMode = 5\n\tPinTCCPDEC       PinMode = 6\n\tPinCom           PinMode = 7\n\tPinSDHC          PinMode = 8\n\tPinI2S           PinMode = 9\n\tPinPCC           PinMode = 10\n\tPinGMAC          PinMode = 11\n\tPinACCLK         PinMode = 12\n\tPinCCL           PinMode = 13\n\tPinDigital       PinMode = 14\n\tPinInput         PinMode = 15\n\tPinInputPullup   PinMode = 16\n\tPinOutput        PinMode = 17\n\tPinTCCE          PinMode = PinTimer\n\tPinTCCF          PinMode = PinTimerAlt\n\tPinTCCG          PinMode = PinTCCPDEC\n\tPinInputPulldown PinMode = 18\n\tPinCAN           PinMode = 19\n\tPinCAN0          PinMode = PinSDHC\n\tPinCAN1          PinMode = PinCom\n)\n\ntype PinChange uint8\n\n// Pin change interrupt constants for SetInterrupt.\nconst (\n\tPinRising  PinChange = sam.EIC_CONFIG_SENSE0_RISE\n\tPinFalling PinChange = sam.EIC_CONFIG_SENSE0_FALL\n\tPinToggle  PinChange = sam.EIC_CONFIG_SENSE0_BOTH\n)\n\n// Callbacks to be called for pins configured with SetInterrupt. Unfortunately,\n// we also need to keep track of which interrupt channel is used by which pin,\n// as the only alternative would be iterating through all pins.\n//\n// We're using the magic constant 16 here because the SAM D21 has 16 interrupt\n// channels configurable for pins.\nvar (\n\tinterruptPins [16]Pin // warning: the value is invalid when pinCallbacks[i] is not set!\n\tpinCallbacks  [16]func(Pin)\n)\n\n// Hardware pins\nconst (\n\tPA00 Pin = 0\n\tPA01 Pin = 1\n\tPA02 Pin = 2\n\tPA03 Pin = 3\n\tPA04 Pin = 4\n\tPA05 Pin = 5\n\tPA06 Pin = 6\n\tPA07 Pin = 7\n\tPA08 Pin = 8  // peripherals: TCC0 channel 0, TCC1 channel 4, sercomI2CM0 SDA, sercomI2CM2 SDA\n\tPA09 Pin = 9  // peripherals: TCC0 channel 1, TCC1 channel 5, sercomI2CM0 SCL, sercomI2CM2 SCL\n\tPA10 Pin = 10 // peripherals: TCC0 channel 2, TCC1 channel 6\n\tPA11 Pin = 11 // peripherals: TCC0 channel 3, TCC1 channel 7\n\tPA12 Pin = 12 // peripherals: TCC0 channel 6, TCC1 channel 2, sercomI2CM2 SDA, sercomI2CM4 SDA\n\tPA13 Pin = 13 // peripherals: TCC0 channel 7, TCC1 channel 3, sercomI2CM2 SCL, sercomI2CM4 SCL\n\tPA14 Pin = 14 // peripherals: TCC2 channel 0, TCC1 channel 2\n\tPA15 Pin = 15 // peripherals: TCC2 channel 1, TCC1 channel 3\n\tPA16 Pin = 16 // peripherals: TCC1 channel 0, TCC0 channel 4, sercomI2CM1 SDA, sercomI2CM3 SDA\n\tPA17 Pin = 17 // peripherals: TCC1 channel 1, TCC0 channel 5, sercomI2CM1 SCL, sercomI2CM3 SCL\n\tPA18 Pin = 18 // peripherals: TCC1 channel 2, TCC0 channel 6\n\tPA19 Pin = 19 // peripherals: TCC1 channel 3, TCC0 channel 7\n\tPA20 Pin = 20 // peripherals: TCC1 channel 4, TCC0 channel 0\n\tPA21 Pin = 21 // peripherals: TCC1 channel 5, TCC0 channel 1\n\tPA22 Pin = 22 // peripherals: TCC1 channel 6, TCC0 channel 2, sercomI2CM3 SDA, sercomI2CM5 SDA\n\tPA23 Pin = 23 // peripherals: TCC1 channel 7, TCC0 channel 3, sercomI2CM3 SCL, sercomI2CM5 SCL\n\tPA24 Pin = 24 // peripherals: TCC2 channel 2\n\tPA25 Pin = 25 // peripherals: TCC2 channel 3\n\tPA26 Pin = 26\n\tPA27 Pin = 27\n\tPA28 Pin = 28\n\tPA29 Pin = 29\n\tPA30 Pin = 30 // peripherals: TCC2 channel 0\n\tPA31 Pin = 31 // peripherals: TCC2 channel 1\n\tPB00 Pin = 32\n\tPB01 Pin = 33\n\tPB02 Pin = 34 // peripherals: TCC2 channel 2\n\tPB03 Pin = 35 // peripherals: TCC2 channel 3\n\tPB04 Pin = 36\n\tPB05 Pin = 37\n\tPB06 Pin = 38\n\tPB07 Pin = 39\n\tPB08 Pin = 40\n\tPB09 Pin = 41\n\tPB10 Pin = 42 // peripherals: TCC0 channel 4, TCC1 channel 0\n\tPB11 Pin = 43 // peripherals: TCC0 channel 5, TCC1 channel 1\n\tPB12 Pin = 44 // peripherals: TCC3 channel 0, TCC0 channel 0\n\tPB13 Pin = 45 // peripherals: TCC3 channel 1, TCC0 channel 1\n\tPB14 Pin = 46 // peripherals: TCC4 channel 0, TCC0 channel 2\n\tPB15 Pin = 47 // peripherals: TCC4 channel 1, TCC0 channel 3\n\tPB16 Pin = 48 // peripherals: TCC3 channel 0, TCC0 channel 4\n\tPB17 Pin = 49 // peripherals: TCC3 channel 1, TCC0 channel 5\n\tPB18 Pin = 50 // peripherals: TCC1 channel 0\n\tPB19 Pin = 51 // peripherals: TCC1 channel 1\n\tPB20 Pin = 52 // peripherals: TCC1 channel 2\n\tPB21 Pin = 53 // peripherals: TCC1 channel 3\n\tPB22 Pin = 54\n\tPB23 Pin = 55\n\tPB24 Pin = 56\n\tPB25 Pin = 57\n\tPB26 Pin = 58 // peripherals: TCC1 channel 2\n\tPB27 Pin = 59 // peripherals: TCC1 channel 3\n\tPB28 Pin = 60 // peripherals: TCC1 channel 4\n\tPB29 Pin = 61 // peripherals: TCC1 channel 5\n\tPB30 Pin = 62 // peripherals: TCC4 channel 0, TCC0 channel 6\n\tPB31 Pin = 63 // peripherals: TCC4 channel 1, TCC0 channel 7\n\tPC00 Pin = 64\n\tPC01 Pin = 65\n\tPC02 Pin = 66\n\tPC03 Pin = 67\n\tPC04 Pin = 68 // peripherals: TCC0 channel 0\n\tPC05 Pin = 69 // peripherals: TCC0 channel 1\n\tPC06 Pin = 70\n\tPC07 Pin = 71\n\tPC08 Pin = 72\n\tPC09 Pin = 73\n\tPC10 Pin = 74 // peripherals: TCC0 channel 0, TCC1 channel 4\n\tPC11 Pin = 75 // peripherals: TCC0 channel 1, TCC1 channel 5\n\tPC12 Pin = 76 // peripherals: TCC0 channel 2, TCC1 channel 6\n\tPC13 Pin = 77 // peripherals: TCC0 channel 3, TCC1 channel 7\n\tPC14 Pin = 78 // peripherals: TCC0 channel 4, TCC1 channel 0\n\tPC15 Pin = 79 // peripherals: TCC0 channel 5, TCC1 channel 1\n\tPC16 Pin = 80 // peripherals: TCC0 channel 0\n\tPC17 Pin = 81 // peripherals: TCC0 channel 1\n\tPC18 Pin = 82 // peripherals: TCC0 channel 2\n\tPC19 Pin = 83 // peripherals: TCC0 channel 3\n\tPC20 Pin = 84 // peripherals: TCC0 channel 4\n\tPC21 Pin = 85 // peripherals: TCC0 channel 5\n\tPC22 Pin = 86 // peripherals: TCC0 channel 6\n\tPC23 Pin = 87 // peripherals: TCC0 channel 7\n\tPC24 Pin = 88\n\tPC25 Pin = 89\n\tPC26 Pin = 90\n\tPC27 Pin = 91\n\tPC28 Pin = 92\n\tPC29 Pin = 93\n\tPC30 Pin = 94\n\tPC31 Pin = 95\n\tPD00 Pin = 96\n\tPD01 Pin = 97\n\tPD02 Pin = 98\n\tPD03 Pin = 99\n\tPD04 Pin = 100\n\tPD05 Pin = 101\n\tPD06 Pin = 102\n\tPD07 Pin = 103\n\tPD08 Pin = 104 // peripherals: TCC0 channel 1, sercomI2CM6 SDA, sercomI2CM7 SDA\n\tPD09 Pin = 105 // peripherals: TCC0 channel 2, sercomI2CM6 SCL, sercomI2CM7 SCL\n\tPD10 Pin = 106 // peripherals: TCC0 channel 3\n\tPD11 Pin = 107 // peripherals: TCC0 channel 4\n\tPD12 Pin = 108 // peripherals: TCC0 channel 5\n\tPD13 Pin = 109 // peripherals: TCC0 channel 6\n\tPD14 Pin = 110\n\tPD15 Pin = 111\n\tPD16 Pin = 112\n\tPD17 Pin = 113\n\tPD18 Pin = 114\n\tPD19 Pin = 115\n\tPD20 Pin = 116 // peripherals: TCC1 channel 0\n\tPD21 Pin = 117 // peripherals: TCC1 channel 1\n\tPD22 Pin = 118\n\tPD23 Pin = 119\n\tPD24 Pin = 120\n\tPD25 Pin = 121\n\tPD26 Pin = 122\n\tPD27 Pin = 123\n\tPD28 Pin = 124\n\tPD29 Pin = 125\n\tPD30 Pin = 126\n\tPD31 Pin = 127\n)\n\nconst (\n\tpinPadMapSERCOM0Pad0 uint16 = 0x1000\n\tpinPadMapSERCOM1Pad0 uint16 = 0x2000\n\tpinPadMapSERCOM2Pad0 uint16 = 0x3000\n\tpinPadMapSERCOM3Pad0 uint16 = 0x4000\n\tpinPadMapSERCOM4Pad0 uint16 = 0x5000\n\tpinPadMapSERCOM5Pad0 uint16 = 0x6000\n\tpinPadMapSERCOM6Pad0 uint16 = 0x7000\n\tpinPadMapSERCOM7Pad0 uint16 = 0x8000\n\tpinPadMapSERCOM0Pad2 uint16 = 0x1200\n\tpinPadMapSERCOM1Pad2 uint16 = 0x2200\n\tpinPadMapSERCOM2Pad2 uint16 = 0x3200\n\tpinPadMapSERCOM3Pad2 uint16 = 0x4200\n\tpinPadMapSERCOM4Pad2 uint16 = 0x5200\n\tpinPadMapSERCOM5Pad2 uint16 = 0x6200\n\tpinPadMapSERCOM6Pad2 uint16 = 0x7200\n\tpinPadMapSERCOM7Pad2 uint16 = 0x8200\n\n\tpinPadMapSERCOM0AltPad0 uint16 = 0x0010\n\tpinPadMapSERCOM1AltPad0 uint16 = 0x0020\n\tpinPadMapSERCOM2AltPad0 uint16 = 0x0030\n\tpinPadMapSERCOM3AltPad0 uint16 = 0x0040\n\tpinPadMapSERCOM4AltPad0 uint16 = 0x0050\n\tpinPadMapSERCOM5AltPad0 uint16 = 0x0060\n\tpinPadMapSERCOM6AltPad0 uint16 = 0x0070\n\tpinPadMapSERCOM7AltPad0 uint16 = 0x0080\n\tpinPadMapSERCOM0AltPad1 uint16 = 0x0011\n\tpinPadMapSERCOM1AltPad1 uint16 = 0x0021\n\tpinPadMapSERCOM2AltPad1 uint16 = 0x0031\n\tpinPadMapSERCOM3AltPad1 uint16 = 0x0041\n\tpinPadMapSERCOM4AltPad1 uint16 = 0x0051\n\tpinPadMapSERCOM5AltPad1 uint16 = 0x0061\n\tpinPadMapSERCOM6AltPad1 uint16 = 0x0071\n\tpinPadMapSERCOM7AltPad1 uint16 = 0x0081\n\tpinPadMapSERCOM0AltPad2 uint16 = 0x0012\n\tpinPadMapSERCOM1AltPad2 uint16 = 0x0022\n\tpinPadMapSERCOM2AltPad2 uint16 = 0x0032\n\tpinPadMapSERCOM3AltPad2 uint16 = 0x0042\n\tpinPadMapSERCOM4AltPad2 uint16 = 0x0052\n\tpinPadMapSERCOM5AltPad2 uint16 = 0x0062\n\tpinPadMapSERCOM6AltPad2 uint16 = 0x0072\n\tpinPadMapSERCOM7AltPad2 uint16 = 0x0082\n)\n\n// pinPadMapping lists which pins have which SERCOMs attached to them.\n// The encoding is rather dense, with each uint16 encoding two pins and both\n// SERCOM and SERCOM-ALT.\n//\n// Observations:\n//   - There are eight SERCOMs. Those SERCOM numbers can be encoded in 4 bits.\n//   - Even pad numbers are usually on even pins, and odd pad numbers are usually\n//     on odd pins. The exception is SERCOM-ALT, which sometimes swaps pad 0 and 1.\n//     With that, there is still an invariant that the pad number for an odd pin is\n//     the pad number for the corresponding even pin with the low bit toggled.\n//   - Pin pads come in pairs. If PA00 has pad 0, then PA01 has pad 1.\n//\n// With this information, we can encode SERCOM pin/pad numbers much more\n// efficiently. Due to pads coming in pairs, we can ignore half the pins: the\n// information for an odd pin can be calculated easily from the preceding even\n// pin.\n//\n// Each word below is split in two bytes. The 8 high bytes are for SERCOM and\n// the 8 low bits are for SERCOM-ALT. Of each byte, the 4 high bits encode the\n// SERCOM + 1 while the two low bits encodes the pad number (the pad number for\n// the odd pin can be trivially calculated by toggling the low bit of the pad\n// number). It encodes SERCOM + 1 instead of just the SERCOM number, to make it\n// easy to check whether a nibble is set at all.\n//\n// Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/60001507E.pdf\nvar pinPadMapping = [64]uint16{\n\t// page 32\n\tPA00 / 2: 0 | pinPadMapSERCOM1AltPad0,\n\n\t// page 33\n\tPB08 / 2: 0 | pinPadMapSERCOM4AltPad0,\n\tPA04 / 2: 0 | pinPadMapSERCOM0AltPad0,\n\tPA06 / 2: 0 | pinPadMapSERCOM0AltPad2,\n\tPC04 / 2: pinPadMapSERCOM6Pad0 | 0,\n\tPC06 / 2: pinPadMapSERCOM6Pad2 | 0,\n\tPA08 / 2: pinPadMapSERCOM0Pad0 | pinPadMapSERCOM2AltPad1,\n\tPA10 / 2: pinPadMapSERCOM0Pad2 | pinPadMapSERCOM2AltPad2,\n\tPB10 / 2: 0 | pinPadMapSERCOM4AltPad2,\n\tPB12 / 2: pinPadMapSERCOM4Pad0 | 0,\n\tPB14 / 2: pinPadMapSERCOM4Pad2 | 0,\n\tPD08 / 2: pinPadMapSERCOM7Pad0 | pinPadMapSERCOM6AltPad1,\n\tPD10 / 2: pinPadMapSERCOM7Pad2 | pinPadMapSERCOM6AltPad2,\n\tPC10 / 2: pinPadMapSERCOM6Pad2 | pinPadMapSERCOM7AltPad2,\n\n\t// page 34\n\tPC12 / 2: pinPadMapSERCOM7Pad0 | pinPadMapSERCOM6AltPad1,\n\tPC14 / 2: pinPadMapSERCOM7Pad2 | pinPadMapSERCOM6AltPad2,\n\tPA12 / 2: pinPadMapSERCOM2Pad0 | pinPadMapSERCOM4AltPad1,\n\tPA14 / 2: pinPadMapSERCOM2Pad2 | pinPadMapSERCOM4AltPad2,\n\tPA16 / 2: pinPadMapSERCOM1Pad0 | pinPadMapSERCOM3AltPad1,\n\tPA18 / 2: pinPadMapSERCOM1Pad2 | pinPadMapSERCOM3AltPad2,\n\tPC16 / 2: pinPadMapSERCOM6Pad0 | pinPadMapSERCOM0AltPad1,\n\tPC18 / 2: pinPadMapSERCOM6Pad2 | pinPadMapSERCOM0AltPad2,\n\tPC22 / 2: pinPadMapSERCOM1Pad0 | pinPadMapSERCOM3AltPad1,\n\tPD20 / 2: pinPadMapSERCOM1Pad2 | pinPadMapSERCOM3AltPad2,\n\tPB16 / 2: pinPadMapSERCOM5Pad0 | 0,\n\tPB18 / 2: pinPadMapSERCOM5Pad2 | pinPadMapSERCOM7AltPad2,\n\n\t// page 35\n\tPB20 / 2: pinPadMapSERCOM3Pad0 | pinPadMapSERCOM7AltPad1,\n\tPA20 / 2: pinPadMapSERCOM5Pad2 | pinPadMapSERCOM3AltPad2,\n\tPA22 / 2: pinPadMapSERCOM3Pad0 | pinPadMapSERCOM5AltPad1,\n\tPA24 / 2: pinPadMapSERCOM3Pad2 | pinPadMapSERCOM5AltPad2,\n\tPB22 / 2: pinPadMapSERCOM1Pad2 | pinPadMapSERCOM5AltPad2,\n\tPB24 / 2: pinPadMapSERCOM0Pad0 | pinPadMapSERCOM2AltPad1,\n\tPB26 / 2: pinPadMapSERCOM2Pad0 | pinPadMapSERCOM4AltPad1,\n\tPB28 / 2: pinPadMapSERCOM2Pad2 | pinPadMapSERCOM4AltPad2,\n\tPC24 / 2: pinPadMapSERCOM0Pad2 | pinPadMapSERCOM2AltPad2,\n\t//PC26 / 2: pinPadMapSERCOM1Pad1 | 0, // note: PC26 doesn't support SERCOM, but PC27 does\n\t//PC28 / 2: pinPadMapSERCOM1Pad1 | 0, // note: PC29 doesn't exist in the datasheet?\n\tPA30 / 2: 0 | pinPadMapSERCOM1AltPad2,\n\n\t// page 36\n\tPB30 / 2: 0 | pinPadMapSERCOM5AltPad1,\n\tPB00 / 2: 0 | pinPadMapSERCOM5AltPad2,\n\tPB02 / 2: 0 | pinPadMapSERCOM5AltPad0,\n}\n\n// findPinPadMapping looks up the pad number and the pinmode for a given pin and\n// SERCOM number. The result can either be SERCOM, SERCOM-ALT, or \"not found\"\n// (indicated by returning ok=false). The pad number is returned to calculate\n// the DOPO/DIPO bitfields of the various serial peripherals.\nfunc findPinPadMapping(sercom uint8, pin Pin) (pinMode PinMode, pad uint32, ok bool) {\n\tif int(pin)/2 >= len(pinPadMapping) {\n\t\t// This is probably NoPin, for which no mapping is available.\n\t\treturn\n\t}\n\n\tbytes := pinPadMapping[pin/2]\n\tupper := byte(bytes >> 8)\n\tlower := byte(bytes & 0xff)\n\n\tif upper != 0 {\n\t\t// SERCOM\n\t\tif (upper>>4)-1 == sercom {\n\t\t\tpinMode = PinSERCOM\n\t\t\tpad |= uint32(upper % 4)\n\t\t\tok = true\n\t\t}\n\t}\n\tif lower != 0 {\n\t\t// SERCOM-ALT\n\t\tif (lower>>4)-1 == sercom {\n\t\t\tpinMode = PinSERCOMAlt\n\t\t\tpad |= uint32(lower % 4)\n\t\t\tok = true\n\t\t}\n\t}\n\n\tif ok {\n\t\t// If the pin is uneven, toggle the lowest bit of the pad number.\n\t\tif pin&1 != 0 {\n\t\t\tpad ^= 1\n\t\t}\n\t}\n\treturn\n}\n\n// SetInterrupt sets an interrupt to be executed when a particular pin changes\n// state. The pin should already be configured as an input, including a pull up\n// or down if no external pull is provided.\n//\n// This call will replace a previously set callback on this pin. You can pass a\n// nil func to unset the pin change interrupt. If you do so, the change\n// parameter is ignored and can be set to any value (such as 0).\nfunc (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error {\n\t// Most pins follow a common pattern where the EXTINT value is the pin\n\t// number modulo 16. However, there are a few exceptions, as you can see\n\t// below.\n\textint := uint8(0)\n\n\tswitch p {\n\tcase PA08:\n\t\t// Connected to NMI. This is not currently supported.\n\t\treturn ErrInvalidInputPin\n\tcase PB26:\n\t\textint = 12\n\tcase PB27:\n\t\textint = 13\n\tcase PB28:\n\t\textint = 14\n\tcase PB29:\n\t\textint = 15\n\tcase PC07:\n\t\textint = 9\n\tcase PD08:\n\t\textint = 3\n\tcase PD09:\n\t\textint = 4\n\tcase PD10:\n\t\textint = 5\n\tcase PD11:\n\t\textint = 6\n\tcase PD12:\n\t\textint = 7\n\tcase PD20:\n\t\textint = 10\n\tcase PD21:\n\t\textint = 11\n\tdefault:\n\t\t// All other pins follow a normal pattern.\n\t\textint = uint8(p) % 16\n\t}\n\n\tif callback == nil {\n\t\t// Disable this pin interrupt (if it was enabled).\n\t\tsam.EIC.INTENCLR.Set(1 << extint)\n\t\tif pinCallbacks[extint] != nil {\n\t\t\tpinCallbacks[extint] = nil\n\t\t}\n\t\treturn nil\n\t}\n\n\tif pinCallbacks[extint] != nil {\n\t\t// The pin was already configured.\n\t\t// To properly re-configure a pin, unset it first and set a new\n\t\t// configuration.\n\t\treturn ErrNoPinChangeChannel\n\t}\n\tpinCallbacks[extint] = callback\n\tinterruptPins[extint] = p\n\n\tif !sam.EIC.CTRLA.HasBits(sam.EIC_CTRLA_ENABLE) {\n\t\t// EIC peripheral has not yet been initialized. Initialize it now.\n\n\t\t// The EIC needs two clocks: CLK_EIC_APB and GCLK_EIC. CLK_EIC_APB is\n\t\t// enabled by default, so doesn't have to be re-enabled. The other is\n\t\t// required for detecting edges and must be enabled manually.\n\t\tsam.GCLK.PCHCTRL[4].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\n\t\t// should not be necessary (CLKCTRL is not synchronized)\n\t\tfor sam.GCLK.SYNCBUSY.HasBits(sam.GCLK_SYNCBUSY_GENCTRL_GCLK0 << sam.GCLK_SYNCBUSY_GENCTRL_Pos) {\n\t\t}\n\t}\n\n\t// CONFIG register is enable-protected, so disable EIC.\n\tsam.EIC.CTRLA.ClearBits(sam.EIC_CTRLA_ENABLE)\n\n\t// Configure this pin. Set the 4 bits of the EIC.CONFIGx register to the\n\t// sense value (filter bit set to 0, sense bits set to the change value).\n\taddr := &sam.EIC.CONFIG[0]\n\tif extint >= 8 {\n\t\taddr = &sam.EIC.CONFIG[1]\n\t}\n\tpos := (extint % 8) * 4 // bit position in register\n\taddr.ReplaceBits(uint32(change), 0xf, pos)\n\n\t// Enable external interrupt for this pin.\n\tsam.EIC.INTENSET.Set(1 << extint)\n\n\tsam.EIC.CTRLA.Set(sam.EIC_CTRLA_ENABLE)\n\tfor sam.EIC.SYNCBUSY.HasBits(sam.EIC_SYNCBUSY_ENABLE) {\n\t}\n\n\t// Set the PMUXEN flag, while keeping the INEN and PULLEN flags (if they\n\t// were set before). This avoids clearing the pin pull mode while\n\t// configuring the pin interrupt.\n\tp.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN | (p.getPinCfg() & (sam.PORT_GROUP_PINCFG_INEN | sam.PORT_GROUP_PINCFG_PULLEN)))\n\tif p&1 > 0 {\n\t\t// odd pin, so save the even pins\n\t\tval := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk\n\t\tp.setPMux(val | (0 << sam.PORT_GROUP_PMUX_PMUXO_Pos))\n\t} else {\n\t\t// even pin, so save the odd pins\n\t\tval := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk\n\t\tp.setPMux(val | (0 << sam.PORT_GROUP_PMUX_PMUXE_Pos))\n\t}\n\n\thandleEICInterrupt := func(interrupt.Interrupt) {\n\t\tflags := sam.EIC.INTFLAG.Get()\n\t\tsam.EIC.INTFLAG.Set(flags)      // clear interrupt\n\t\tfor i := uint(0); i < 16; i++ { // there are 16 channels\n\t\t\tif flags&(1<<i) != 0 {\n\t\t\t\tpinCallbacks[i](interruptPins[i])\n\t\t\t}\n\t\t}\n\t}\n\tswitch extint {\n\tcase 0:\n\t\tinterrupt.New(sam.IRQ_EIC_EXTINT_0, handleEICInterrupt).Enable()\n\tcase 1:\n\t\tinterrupt.New(sam.IRQ_EIC_EXTINT_1, handleEICInterrupt).Enable()\n\tcase 2:\n\t\tinterrupt.New(sam.IRQ_EIC_EXTINT_2, handleEICInterrupt).Enable()\n\tcase 3:\n\t\tinterrupt.New(sam.IRQ_EIC_EXTINT_3, handleEICInterrupt).Enable()\n\tcase 4:\n\t\tinterrupt.New(sam.IRQ_EIC_EXTINT_4, handleEICInterrupt).Enable()\n\tcase 5:\n\t\tinterrupt.New(sam.IRQ_EIC_EXTINT_5, handleEICInterrupt).Enable()\n\tcase 6:\n\t\tinterrupt.New(sam.IRQ_EIC_EXTINT_6, handleEICInterrupt).Enable()\n\tcase 7:\n\t\tinterrupt.New(sam.IRQ_EIC_EXTINT_7, handleEICInterrupt).Enable()\n\tcase 8:\n\t\tinterrupt.New(sam.IRQ_EIC_EXTINT_8, handleEICInterrupt).Enable()\n\tcase 9:\n\t\tinterrupt.New(sam.IRQ_EIC_EXTINT_9, handleEICInterrupt).Enable()\n\tcase 10:\n\t\tinterrupt.New(sam.IRQ_EIC_EXTINT_10, handleEICInterrupt).Enable()\n\tcase 11:\n\t\tinterrupt.New(sam.IRQ_EIC_EXTINT_11, handleEICInterrupt).Enable()\n\tcase 12:\n\t\tinterrupt.New(sam.IRQ_EIC_EXTINT_12, handleEICInterrupt).Enable()\n\tcase 13:\n\t\tinterrupt.New(sam.IRQ_EIC_EXTINT_13, handleEICInterrupt).Enable()\n\tcase 14:\n\t\tinterrupt.New(sam.IRQ_EIC_EXTINT_14, handleEICInterrupt).Enable()\n\tcase 15:\n\t\tinterrupt.New(sam.IRQ_EIC_EXTINT_15, handleEICInterrupt).Enable()\n\t}\n\n\treturn nil\n}\n\n// Return the register and mask to enable a given GPIO pin. This can be used to\n// implement bit-banged drivers.\nfunc (p Pin) PortMaskSet() (*uint32, uint32) {\n\tgroup, pin_in_group := p.getPinGrouping()\n\treturn &sam.PORT.GROUP[group].OUTSET.Reg, 1 << pin_in_group\n}\n\n// Return the register and mask to disable a given port. This can be used to\n// implement bit-banged drivers.\nfunc (p Pin) PortMaskClear() (*uint32, uint32) {\n\tgroup, pin_in_group := p.getPinGrouping()\n\treturn &sam.PORT.GROUP[group].OUTCLR.Reg, 1 << pin_in_group\n}\n\n// Set the pin to high or low.\n// Warning: only use this on an output pin!\nfunc (p Pin) Set(high bool) {\n\tgroup, pin_in_group := p.getPinGrouping()\n\tif high {\n\t\tsam.PORT.GROUP[group].OUTSET.Set(1 << pin_in_group)\n\t} else {\n\t\tsam.PORT.GROUP[group].OUTCLR.Set(1 << pin_in_group)\n\t}\n}\n\n// Get returns the current value of a GPIO pin when configured as an input or as\n// an output.\nfunc (p Pin) Get() bool {\n\tgroup, pin_in_group := p.getPinGrouping()\n\treturn (sam.PORT.GROUP[group].IN.Get()>>pin_in_group)&1 > 0\n}\n\n// Toggle switches an output pin from low to high or from high to low.\n// Warning: only use this on an output pin!\nfunc (p Pin) Toggle() {\n\tgroup, pin_in_group := p.getPinGrouping()\n\tsam.PORT.GROUP[group].OUTTGL.Set(1 << pin_in_group)\n}\n\n// Configure this pin with the given configuration.\nfunc (p Pin) Configure(config PinConfig) {\n\tgroup, pin_in_group := p.getPinGrouping()\n\tswitch config.Mode {\n\tcase PinOutput:\n\t\tsam.PORT.GROUP[group].DIRSET.Set(1 << pin_in_group)\n\t\t// output is also set to input enable so pin can read back its own value\n\t\tp.setPinCfg(sam.PORT_GROUP_PINCFG_INEN)\n\n\tcase PinInput:\n\t\tsam.PORT.GROUP[group].DIRCLR.Set(1 << pin_in_group)\n\t\tp.setPinCfg(sam.PORT_GROUP_PINCFG_INEN)\n\n\tcase PinInputPulldown:\n\t\tsam.PORT.GROUP[group].DIRCLR.Set(1 << pin_in_group)\n\t\tsam.PORT.GROUP[group].OUTCLR.Set(1 << pin_in_group)\n\t\tp.setPinCfg(sam.PORT_GROUP_PINCFG_INEN | sam.PORT_GROUP_PINCFG_PULLEN)\n\n\tcase PinInputPullup:\n\t\tsam.PORT.GROUP[group].DIRCLR.Set(1 << pin_in_group)\n\t\tsam.PORT.GROUP[group].OUTSET.Set(1 << pin_in_group)\n\t\tp.setPinCfg(sam.PORT_GROUP_PINCFG_INEN | sam.PORT_GROUP_PINCFG_PULLEN)\n\n\tcase PinSERCOM:\n\t\tif p&1 > 0 {\n\t\t\t// odd pin, so save the even pins\n\t\t\tval := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk\n\t\t\tp.setPMux(val | (uint8(PinSERCOM) << sam.PORT_GROUP_PMUX_PMUXO_Pos))\n\t\t} else {\n\t\t\t// even pin, so save the odd pins\n\t\t\tval := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk\n\t\t\tp.setPMux(val | (uint8(PinSERCOM) << sam.PORT_GROUP_PMUX_PMUXE_Pos))\n\t\t}\n\t\t// enable port config\n\t\tp.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN | sam.PORT_GROUP_PINCFG_DRVSTR | sam.PORT_GROUP_PINCFG_INEN)\n\n\tcase PinSERCOMAlt:\n\t\tif p&1 > 0 {\n\t\t\t// odd pin, so save the even pins\n\t\t\tval := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk\n\t\t\tp.setPMux(val | (uint8(PinSERCOMAlt) << sam.PORT_GROUP_PMUX_PMUXO_Pos))\n\t\t} else {\n\t\t\t// even pin, so save the odd pins\n\t\t\tval := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk\n\t\t\tp.setPMux(val | (uint8(PinSERCOMAlt) << sam.PORT_GROUP_PMUX_PMUXE_Pos))\n\t\t}\n\t\t// enable port config\n\t\tp.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN | sam.PORT_GROUP_PINCFG_DRVSTR)\n\n\tcase PinCom:\n\t\tif p&1 > 0 {\n\t\t\t// odd pin, so save the even pins\n\t\t\tval := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk\n\t\t\tp.setPMux(val | (uint8(PinCom) << sam.PORT_GROUP_PMUX_PMUXO_Pos))\n\t\t} else {\n\t\t\t// even pin, so save the odd pins\n\t\t\tval := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk\n\t\t\tp.setPMux(val | (uint8(PinCom) << sam.PORT_GROUP_PMUX_PMUXE_Pos))\n\t\t}\n\t\t// enable port config\n\t\tp.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN)\n\tcase PinAnalog:\n\t\tif p&1 > 0 {\n\t\t\t// odd pin, so save the even pins\n\t\t\tval := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk\n\t\t\tp.setPMux(val | (uint8(PinAnalog) << sam.PORT_GROUP_PMUX_PMUXO_Pos))\n\t\t} else {\n\t\t\t// even pin, so save the odd pins\n\t\t\tval := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk\n\t\t\tp.setPMux(val | (uint8(PinAnalog) << sam.PORT_GROUP_PMUX_PMUXE_Pos))\n\t\t}\n\t\t// enable port config\n\t\tp.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN | sam.PORT_GROUP_PINCFG_DRVSTR)\n\tcase PinSDHC:\n\t\tif p&1 > 0 {\n\t\t\t// odd pin, so save the even pins\n\t\t\tval := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk\n\t\t\tp.setPMux(val | (uint8(PinSDHC) << sam.PORT_GROUP_PMUX_PMUXO_Pos))\n\t\t} else {\n\t\t\t// even pin, so save the odd pins\n\t\t\tval := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk\n\t\t\tp.setPMux(val | (uint8(PinSDHC) << sam.PORT_GROUP_PMUX_PMUXE_Pos))\n\t\t}\n\t\t// enable port config\n\t\tp.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN)\n\t}\n}\n\n// getPMux returns the value for the correct PMUX register for this pin.\nfunc (p Pin) getPMux() uint8 {\n\tgroup, pin_in_group := p.getPinGrouping()\n\treturn sam.PORT.GROUP[group].PMUX[pin_in_group>>1].Get()\n}\n\n// setPMux sets the value for the correct PMUX register for this pin.\nfunc (p Pin) setPMux(val uint8) {\n\tgroup, pin_in_group := p.getPinGrouping()\n\tsam.PORT.GROUP[group].PMUX[pin_in_group>>1].Set(val)\n}\n\n// getPinCfg returns the value for the correct PINCFG register for this pin.\nfunc (p Pin) getPinCfg() uint8 {\n\tgroup, pin_in_group := p.getPinGrouping()\n\treturn sam.PORT.GROUP[group].PINCFG[pin_in_group].Get()\n}\n\n// setPinCfg sets the value for the correct PINCFG register for this pin.\nfunc (p Pin) setPinCfg(val uint8) {\n\tgroup, pin_in_group := p.getPinGrouping()\n\tsam.PORT.GROUP[group].PINCFG[pin_in_group].Set(val)\n}\n\n// getPinGrouping calculates the gpio group and pin id from the pin number.\n// Pins are split into groups of 32, and each group has its own set of\n// control registers.\nfunc (p Pin) getPinGrouping() (uint8, uint8) {\n\tgroup := uint8(p) >> 5\n\tpin_in_group := uint8(p) & 0x1f\n\treturn group, pin_in_group\n}\n\n// InitADC initializes the ADC.\nfunc InitADC() {\n\t// ADC Bias Calibration\n\t// NVMCTRL_SW0 0x00800080\n\t// #define ADC0_FUSES_BIASCOMP_ADDR    NVMCTRL_SW0\n\t// #define ADC0_FUSES_BIASCOMP_Pos     2            /**< \\brief (NVMCTRL_SW0) ADC Comparator Scaling */\n\t// #define ADC0_FUSES_BIASCOMP_Msk     (_Ul(0x7) << ADC0_FUSES_BIASCOMP_Pos)\n\t// #define ADC0_FUSES_BIASCOMP(value)  (ADC0_FUSES_BIASCOMP_Msk & ((value) << ADC0_FUSES_BIASCOMP_Pos))\n\n\t// #define ADC0_FUSES_BIASR2R_ADDR     NVMCTRL_SW0\n\t// #define ADC0_FUSES_BIASR2R_Pos      8            /**< \\brief (NVMCTRL_SW0) ADC Bias R2R ampli scaling */\n\t// #define ADC0_FUSES_BIASR2R_Msk      (_Ul(0x7) << ADC0_FUSES_BIASR2R_Pos)\n\t// #define ADC0_FUSES_BIASR2R(value)   (ADC0_FUSES_BIASR2R_Msk & ((value) << ADC0_FUSES_BIASR2R_Pos))\n\n\t// #define ADC0_FUSES_BIASREFBUF_ADDR  NVMCTRL_SW0\n\t// #define ADC0_FUSES_BIASREFBUF_Pos   5            /**< \\brief (NVMCTRL_SW0) ADC Bias Reference Buffer Scaling */\n\t// #define ADC0_FUSES_BIASREFBUF_Msk   (_Ul(0x7) << ADC0_FUSES_BIASREFBUF_Pos)\n\t// #define ADC0_FUSES_BIASREFBUF(value) (ADC0_FUSES_BIASREFBUF_Msk & ((value) << ADC0_FUSES_BIASREFBUF_Pos))\n\n\t// #define ADC1_FUSES_BIASCOMP_ADDR    NVMCTRL_SW0\n\t// #define ADC1_FUSES_BIASCOMP_Pos     16           /**< \\brief (NVMCTRL_SW0) ADC Comparator Scaling */\n\t// #define ADC1_FUSES_BIASCOMP_Msk     (_Ul(0x7) << ADC1_FUSES_BIASCOMP_Pos)\n\t// #define ADC1_FUSES_BIASCOMP(value)  (ADC1_FUSES_BIASCOMP_Msk & ((value) << ADC1_FUSES_BIASCOMP_Pos))\n\n\t// #define ADC1_FUSES_BIASR2R_ADDR     NVMCTRL_SW0\n\t// #define ADC1_FUSES_BIASR2R_Pos      22           /**< \\brief (NVMCTRL_SW0) ADC Bias R2R ampli scaling */\n\t// #define ADC1_FUSES_BIASR2R_Msk      (_Ul(0x7) << ADC1_FUSES_BIASR2R_Pos)\n\t// #define ADC1_FUSES_BIASR2R(value)   (ADC1_FUSES_BIASR2R_Msk & ((value) << ADC1_FUSES_BIASR2R_Pos))\n\n\t// #define ADC1_FUSES_BIASREFBUF_ADDR  NVMCTRL_SW0\n\t// #define ADC1_FUSES_BIASREFBUF_Pos   19           /**< \\brief (NVMCTRL_SW0) ADC Bias Reference Buffer Scaling */\n\t// #define ADC1_FUSES_BIASREFBUF_Msk   (_Ul(0x7) << ADC1_FUSES_BIASREFBUF_Pos)\n\t// #define ADC1_FUSES_BIASREFBUF(value) (ADC1_FUSES_BIASREFBUF_Msk & ((value) << ADC1_FUSES_BIASREFBUF_Pos))\n\n\tadcFuse := *(*uint32)(unsafe.Pointer(uintptr(0x00800080)))\n\n\t// uint32_t biascomp = (*((uint32_t *)ADC0_FUSES_BIASCOMP_ADDR) & ADC0_FUSES_BIASCOMP_Msk) >> ADC0_FUSES_BIASCOMP_Pos;\n\tbiascomp := (adcFuse & uint32(0x7<<2)) //>> 2\n\n\t// uint32_t biasr2r = (*((uint32_t *)ADC0_FUSES_BIASR2R_ADDR) & ADC0_FUSES_BIASR2R_Msk) >> ADC0_FUSES_BIASR2R_Pos;\n\tbiasr2r := (adcFuse & uint32(0x7<<8)) //>> 8\n\n\t// uint32_t biasref = (*((uint32_t *)ADC0_FUSES_BIASREFBUF_ADDR) & ADC0_FUSES_BIASREFBUF_Msk) >> ADC0_FUSES_BIASREFBUF_Pos;\n\tbiasref := (adcFuse & uint32(0x7<<5)) //>> 5\n\n\t// calibrate ADC0\n\tsam.ADC0.CALIB.Set(uint16(biascomp | biasr2r | biasref))\n\n\t// biascomp = (*((uint32_t *)ADC1_FUSES_BIASCOMP_ADDR) & ADC1_FUSES_BIASCOMP_Msk) >> ADC1_FUSES_BIASCOMP_Pos;\n\tbiascomp = (adcFuse & uint32(0x7<<16)) //>> 16\n\n\t// biasr2r = (*((uint32_t *)ADC1_FUSES_BIASR2R_ADDR) & ADC1_FUSES_BIASR2R_Msk) >> ADC1_FUSES_BIASR2R_Pos;\n\tbiasr2r = (adcFuse & uint32(0x7<<22)) //>> 22\n\n\t// biasref = (*((uint32_t *)ADC1_FUSES_BIASREFBUF_ADDR) & ADC1_FUSES_BIASREFBUF_Msk) >> ADC1_FUSES_BIASREFBUF_Pos;\n\tbiasref = (adcFuse & uint32(0x7<<19)) //>> 19\n\n\t// calibrate ADC1\n\tsam.ADC1.CALIB.Set(uint16((biascomp | biasr2r | biasref) >> 16))\n}\n\n// Configure configures a ADCPin to be able to be used to read data.\nfunc (a ADC) Configure(config ADCConfig) {\n\n\tfor _, adc := range []*sam.ADC_Type{sam.ADC0, sam.ADC1} {\n\n\t\tfor adc.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_CTRLB) {\n\t\t} // wait for sync\n\n\t\t// Averaging (see datasheet table in AVGCTRL register description)\n\t\tvar resolution uint32 = sam.ADC_CTRLB_RESSEL_16BIT\n\t\tvar samples uint32\n\t\tswitch config.Samples {\n\t\tcase 2:\n\t\t\tsamples = sam.ADC_AVGCTRL_SAMPLENUM_2\n\t\tcase 4:\n\t\t\tsamples = sam.ADC_AVGCTRL_SAMPLENUM_4\n\t\tcase 8:\n\t\t\tsamples = sam.ADC_AVGCTRL_SAMPLENUM_8\n\t\tcase 16:\n\t\t\tsamples = sam.ADC_AVGCTRL_SAMPLENUM_16\n\t\tcase 32:\n\t\t\tsamples = sam.ADC_AVGCTRL_SAMPLENUM_32\n\t\tcase 64:\n\t\t\tsamples = sam.ADC_AVGCTRL_SAMPLENUM_64\n\t\tcase 128:\n\t\t\tsamples = sam.ADC_AVGCTRL_SAMPLENUM_128\n\t\tcase 256:\n\t\t\tsamples = sam.ADC_AVGCTRL_SAMPLENUM_256\n\t\tcase 512:\n\t\t\tsamples = sam.ADC_AVGCTRL_SAMPLENUM_512\n\t\tcase 1024:\n\t\t\tsamples = sam.ADC_AVGCTRL_SAMPLENUM_1024\n\t\tdefault: // 1 sample only (no oversampling nor averaging), adjusting result by 0\n\t\t\t// Resolutions less than 16 bits only make sense when sampling only\n\t\t\t// once. Resulting ADC values become erratic when using both\n\t\t\t// multi-sampling and less than 16 bits of resolution.\n\t\t\tsamples = sam.ADC_AVGCTRL_SAMPLENUM_1\n\t\t\tswitch config.Resolution {\n\t\t\tcase 8:\n\t\t\t\tresolution = sam.ADC_CTRLB_RESSEL_8BIT\n\t\t\tcase 10:\n\t\t\t\tresolution = sam.ADC_CTRLB_RESSEL_10BIT\n\t\t\tcase 12:\n\t\t\t\tresolution = sam.ADC_CTRLB_RESSEL_12BIT\n\t\t\tcase 16:\n\t\t\t\tresolution = sam.ADC_CTRLB_RESSEL_16BIT\n\t\t\tdefault:\n\t\t\t\tresolution = sam.ADC_CTRLB_RESSEL_12BIT\n\t\t\t}\n\t\t}\n\n\t\tadc.AVGCTRL.Set(uint8(samples<<sam.ADC_AVGCTRL_SAMPLENUM_Pos) |\n\t\t\t(0 << sam.ADC_AVGCTRL_ADJRES_Pos))\n\n\t\tadc.CTRLA.SetBits(sam.ADC_CTRLA_PRESCALER_DIV32 << sam.ADC_CTRLA_PRESCALER_Pos)\n\t\tadc.CTRLB.SetBits(uint16(resolution << sam.ADC_CTRLB_RESSEL_Pos))\n\t\tadc.SAMPCTRL.Set(5) // sampling Time Length\n\n\t\tfor adc.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_SAMPCTRL) {\n\t\t} // wait for sync\n\n\t\t// No Negative input (Internal Ground)\n\t\tadc.INPUTCTRL.Set(sam.ADC_INPUTCTRL_MUXNEG_GND << sam.ADC_INPUTCTRL_MUXNEG_Pos)\n\t\tfor adc.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_INPUTCTRL) {\n\t\t} // wait for sync\n\n\t\tfor adc.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_AVGCTRL) {\n\t\t} // wait for sync\n\t\tfor adc.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_REFCTRL) {\n\t\t} // wait for sync\n\n\t\t// TODO: use config.Reference to set AREF level\n\n\t\t// default is 3V3 reference voltage\n\t\tadc.REFCTRL.SetBits(sam.ADC_REFCTRL_REFSEL_INTVCC1)\n\t}\n\n\ta.Pin.Configure(PinConfig{Mode: PinAnalog})\n}\n\n// Get returns the current value of a ADC pin, in the range 0..0xffff.\nfunc (a ADC) Get() uint16 {\n\tbus := a.getADCBus()\n\tch := a.getADCChannel()\n\n\tfor bus.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_INPUTCTRL) {\n\t}\n\n\t// Selection for the positive ADC input channel\n\tbus.INPUTCTRL.ClearBits(sam.ADC_INPUTCTRL_MUXPOS_Msk)\n\tfor bus.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_ENABLE) {\n\t}\n\tbus.INPUTCTRL.SetBits((uint16(ch) & sam.ADC_INPUTCTRL_MUXPOS_Msk) << sam.ADC_INPUTCTRL_MUXPOS_Pos)\n\tfor bus.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_ENABLE) {\n\t}\n\n\t// Enable ADC\n\tbus.CTRLA.SetBits(sam.ADC_CTRLA_ENABLE)\n\tfor bus.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_ENABLE) {\n\t}\n\n\t// Start conversion\n\tbus.SWTRIG.SetBits(sam.ADC_SWTRIG_START)\n\tfor !bus.INTFLAG.HasBits(sam.ADC_INTFLAG_RESRDY) {\n\t}\n\n\t// Clear the Data Ready flag\n\tbus.INTFLAG.ClearBits(sam.ADC_INTFLAG_RESRDY)\n\tfor bus.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_ENABLE) {\n\t}\n\n\t// Start conversion again, since first conversion after reference voltage changed is invalid.\n\tbus.SWTRIG.SetBits(sam.ADC_SWTRIG_START)\n\n\t// Waiting for conversion to complete\n\tfor !bus.INTFLAG.HasBits(sam.ADC_INTFLAG_RESRDY) {\n\t}\n\tval := bus.RESULT.Get()\n\n\t// Disable ADC\n\tfor bus.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_ENABLE) {\n\t}\n\tbus.CTRLA.ClearBits(sam.ADC_CTRLA_ENABLE)\n\tfor bus.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_ENABLE) {\n\t}\n\n\t// scales to 16-bit result\n\tswitch (bus.CTRLB.Get() & sam.ADC_CTRLB_RESSEL_Msk) >> sam.ADC_CTRLB_RESSEL_Pos {\n\tcase sam.ADC_CTRLB_RESSEL_8BIT:\n\t\tval = val << 8\n\tcase sam.ADC_CTRLB_RESSEL_10BIT:\n\t\tval = val << 6\n\tcase sam.ADC_CTRLB_RESSEL_12BIT:\n\t\tval = val << 4\n\tcase sam.ADC_CTRLB_RESSEL_16BIT:\n\t\t// Adjust for multiple samples. This is only configured when the\n\t\t// resolution is 16 bits.\n\t\tswitch (bus.AVGCTRL.Get() & sam.ADC_AVGCTRL_SAMPLENUM_Msk) >> sam.ADC_AVGCTRL_SAMPLENUM_Pos {\n\t\tcase sam.ADC_AVGCTRL_SAMPLENUM_1:\n\t\t\tval <<= 4\n\t\tcase sam.ADC_AVGCTRL_SAMPLENUM_2:\n\t\t\tval <<= 3\n\t\tcase sam.ADC_AVGCTRL_SAMPLENUM_4:\n\t\t\tval <<= 2\n\t\tcase sam.ADC_AVGCTRL_SAMPLENUM_8:\n\t\t\tval <<= 1\n\t\tdefault:\n\t\t\t// These values are all shifted by the hardware so they fit exactly\n\t\t\t// in a 16-bit integer, so they don't need to be shifted here.\n\t\t}\n\t}\n\treturn val\n}\n\nfunc (a ADC) getADCBus() *sam.ADC_Type {\n\tif (a.Pin >= PB04 && a.Pin <= PB07) || (a.Pin >= PC00) {\n\t\treturn sam.ADC1\n\t}\n\treturn sam.ADC0\n}\n\nfunc (a ADC) getADCChannel() uint8 {\n\tswitch a.Pin {\n\tcase PA02:\n\t\treturn 0\n\tcase PB08:\n\t\treturn 2\n\tcase PB09:\n\t\treturn 3\n\tcase PA04:\n\t\treturn 4\n\tcase PA05:\n\t\treturn 5\n\tcase PA06:\n\t\treturn 6\n\tcase PA07:\n\t\treturn 7\n\tcase PB00:\n\t\treturn 12\n\tcase PB01:\n\t\treturn 13\n\tcase PB02:\n\t\treturn 14\n\tcase PB03:\n\t\treturn 15\n\tcase PA09:\n\t\treturn 17\n\tcase PA11:\n\t\treturn 19\n\n\tcase PB04:\n\t\treturn 6\n\tcase PB05:\n\t\treturn 7\n\tcase PB06:\n\t\treturn 8\n\tcase PB07:\n\t\treturn 9\n\n\tcase PC00:\n\t\treturn 10\n\tcase PC01:\n\t\treturn 11\n\tcase PC02:\n\t\treturn 4\n\tcase PC03:\n\t\treturn 5\n\tcase PC30:\n\t\treturn 12\n\tcase PC31:\n\t\treturn 13\n\n\tcase PD00:\n\t\treturn 14\n\tcase PD01:\n\t\treturn 15\n\tdefault:\n\t\tpanic(\"Invalid ADC pin\")\n\t}\n}\n\n// UART on the SAMD51.\ntype UART struct {\n\tBuffer    *RingBuffer\n\tBus       *sam.SERCOM_USART_INT_Type\n\tSERCOM    uint8\n\tInterrupt interrupt.Interrupt // RXC interrupt\n}\n\nvar (\n\tsercomUSART0 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM0_USART_INT, SERCOM: 0}\n\tsercomUSART1 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM1_USART_INT, SERCOM: 1}\n\tsercomUSART2 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM2_USART_INT, SERCOM: 2}\n\tsercomUSART3 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM3_USART_INT, SERCOM: 3}\n\tsercomUSART4 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM4_USART_INT, SERCOM: 4}\n\tsercomUSART5 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM5_USART_INT, SERCOM: 5}\n)\n\nfunc init() {\n\tsercomUSART0.Interrupt = interrupt.New(sam.IRQ_SERCOM0_2, sercomUSART0.handleInterrupt)\n\tsercomUSART1.Interrupt = interrupt.New(sam.IRQ_SERCOM1_2, sercomUSART1.handleInterrupt)\n\tsercomUSART2.Interrupt = interrupt.New(sam.IRQ_SERCOM2_2, sercomUSART2.handleInterrupt)\n\tsercomUSART3.Interrupt = interrupt.New(sam.IRQ_SERCOM3_2, sercomUSART3.handleInterrupt)\n\tsercomUSART4.Interrupt = interrupt.New(sam.IRQ_SERCOM4_2, sercomUSART4.handleInterrupt)\n\tsercomUSART5.Interrupt = interrupt.New(sam.IRQ_SERCOM5_2, sercomUSART5.handleInterrupt)\n}\n\nconst (\n\tsampleRate16X = 16\n\tlsbFirst      = 1\n)\n\n// Configure the UART.\nfunc (uart *UART) Configure(config UARTConfig) error {\n\t// Default baud rate to 115200.\n\tif config.BaudRate == 0 {\n\t\tconfig.BaudRate = 115200\n\t}\n\n\t// determine pins\n\tif config.TX == 0 && config.RX == 0 {\n\t\t// use default pins\n\t\tconfig.TX = UART_TX_PIN\n\t\tconfig.RX = UART_RX_PIN\n\t}\n\n\t// Determine transmit pinout.\n\ttxPinMode, txPad, ok := findPinPadMapping(uart.SERCOM, config.TX)\n\tif !ok {\n\t\treturn ErrInvalidOutputPin\n\t}\n\tvar txPadOut uint32\n\t// See CTRLA.RXPO bits of the SERCOM USART peripheral (page 945-946) for how\n\t// pads are mapped to pinout values.\n\tswitch txPad {\n\tcase 0:\n\t\ttxPadOut = 0\n\tdefault:\n\t\t// should be flow control (RTS/CTS) pin\n\t\treturn ErrInvalidOutputPin\n\t}\n\n\t// Determine receive pinout.\n\trxPinMode, rxPad, ok := findPinPadMapping(uart.SERCOM, config.RX)\n\tif !ok {\n\t\treturn ErrInvalidInputPin\n\t}\n\t// As you can see in the CTRLA.RXPO bits of the SERCOM USART peripheral\n\t// (page 945), input pins are mapped directly.\n\trxPadOut := rxPad\n\n\t// configure pins\n\tconfig.TX.Configure(PinConfig{Mode: txPinMode})\n\tconfig.RX.Configure(PinConfig{Mode: rxPinMode})\n\n\t// configure RTS/CTS pins if provided\n\tif config.RTS != 0 && config.CTS != 0 {\n\t\trtsPinMode, _, ok := findPinPadMapping(uart.SERCOM, config.RTS)\n\t\tif !ok {\n\t\t\treturn ErrInvalidOutputPin\n\t\t}\n\n\t\tctsPinMode, _, ok := findPinPadMapping(uart.SERCOM, config.CTS)\n\t\tif !ok {\n\t\t\treturn ErrInvalidInputPin\n\t\t}\n\n\t\t// See CTRLA.RXPO bits of the SERCOM USART peripheral (page 945-946) for how\n\t\t// pads are mapped to pinout values.\n\t\ttxPadOut = 2\n\n\t\tconfig.RTS.Configure(PinConfig{Mode: rtsPinMode})\n\t\tconfig.CTS.Configure(PinConfig{Mode: ctsPinMode})\n\t}\n\n\t// reset SERCOM\n\tuart.Bus.CTRLA.SetBits(sam.SERCOM_USART_INT_CTRLA_SWRST)\n\tfor uart.Bus.CTRLA.HasBits(sam.SERCOM_USART_INT_CTRLA_SWRST) ||\n\t\tuart.Bus.SYNCBUSY.HasBits(sam.SERCOM_USART_INT_SYNCBUSY_SWRST) {\n\t}\n\n\t// set UART mode/sample rate\n\t// SERCOM_USART_CTRLA_MODE(mode) |\n\t// SERCOM_USART_CTRLA_SAMPR(sampleRate);\n\t// sam.SERCOM_USART_CTRLA_MODE_USART_INT_CLK = 1?\n\tuart.Bus.CTRLA.Set((1 << sam.SERCOM_USART_INT_CTRLA_MODE_Pos) |\n\t\t(1 << sam.SERCOM_USART_INT_CTRLA_SAMPR_Pos)) // sample rate of 16x\n\n\t// set clock\n\tsetSERCOMClockGenerator(uart.SERCOM, sam.GCLK_PCHCTRL_GEN_GCLK1)\n\n\t// Set baud rate\n\tuart.SetBaudRate(config.BaudRate)\n\n\t// setup UART frame\n\t// SERCOM_USART_CTRLA_FORM( (parityMode == SERCOM_NO_PARITY ? 0 : 1) ) |\n\t// dataOrder << SERCOM_USART_CTRLA_DORD_Pos;\n\tuart.Bus.CTRLA.SetBits((0 << sam.SERCOM_USART_INT_CTRLA_FORM_Pos) | // no parity\n\t\t(lsbFirst << sam.SERCOM_USART_INT_CTRLA_DORD_Pos)) // data order\n\n\t// set UART stop bits/parity\n\t// SERCOM_USART_CTRLB_CHSIZE(charSize) |\n\t// \tnbStopBits << SERCOM_USART_CTRLB_SBMODE_Pos |\n\t// \t(parityMode == SERCOM_NO_PARITY ? 0 : parityMode) << SERCOM_USART_CTRLB_PMODE_Pos; //If no parity use default value\n\tuart.Bus.CTRLB.SetBits((0 << sam.SERCOM_USART_INT_CTRLB_CHSIZE_Pos) | // 8 bits is 0\n\t\t(0 << sam.SERCOM_USART_INT_CTRLB_SBMODE_Pos) | // 1 stop bit is zero\n\t\t(0 << sam.SERCOM_USART_INT_CTRLB_PMODE_Pos)) // no parity\n\n\t// set UART pads. This is not same as pins...\n\t//  SERCOM_USART_CTRLA_TXPO(txPad) |\n\t//   SERCOM_USART_CTRLA_RXPO(rxPad);\n\tuart.Bus.CTRLA.SetBits((txPadOut << sam.SERCOM_USART_INT_CTRLA_TXPO_Pos) |\n\t\t(rxPadOut << sam.SERCOM_USART_INT_CTRLA_RXPO_Pos))\n\n\t// Enable Transceiver and Receiver\n\t//sercom->USART.CTRLB.reg |= SERCOM_USART_CTRLB_TXEN | SERCOM_USART_CTRLB_RXEN ;\n\tuart.Bus.CTRLB.SetBits(sam.SERCOM_USART_INT_CTRLB_TXEN | sam.SERCOM_USART_INT_CTRLB_RXEN)\n\n\t// Enable USART1 port.\n\t// sercom->USART.CTRLA.bit.ENABLE = 0x1u;\n\tuart.Bus.CTRLA.SetBits(sam.SERCOM_USART_INT_CTRLA_ENABLE)\n\tfor uart.Bus.SYNCBUSY.HasBits(sam.SERCOM_USART_INT_SYNCBUSY_ENABLE) {\n\t}\n\n\t// setup interrupt on receive\n\tuart.Bus.INTENSET.Set(sam.SERCOM_USART_INT_INTENSET_RXC)\n\n\t// Enable RX IRQ.\n\t// This is a small note at the bottom of the NVIC section of the datasheet:\n\t// > The integer number specified in the source refers to the respective bit\n\t// > position in the INTFLAG register of respective peripheral.\n\t// Therefore, if we only need to listen to the RXC interrupt source (in bit\n\t// position 2), we only need interrupt source 2 for this SERCOM device.\n\tuart.Interrupt.Enable()\n\n\treturn nil\n}\n\n// SetBaudRate sets the communication speed for the UART.\nfunc (uart *UART) SetBaudRate(br uint32) {\n\t// Asynchronous fractional mode (Table 24-2 in datasheet)\n\t//   BAUD = fref / (sampleRateValue * fbaud)\n\t// (multiply by 8, to calculate fractional piece)\n\t// uint32_t baudTimes8 = (SystemCoreClock * 8) / (16 * baudrate);\n\tbaud := (SERCOM_FREQ_REF * 8) / (sampleRate16X * br)\n\n\t// sercom->USART.BAUD.FRAC.FP   = (baudTimes8 % 8);\n\t// sercom->USART.BAUD.FRAC.BAUD = (baudTimes8 / 8);\n\tuart.Bus.BAUD.Set(uint16(((baud % 8) << sam.SERCOM_USART_INT_BAUD_FRAC_MODE_FP_Pos) |\n\t\t((baud / 8) << sam.SERCOM_USART_INT_BAUD_FRAC_MODE_BAUD_Pos)))\n}\n\n// WriteByte writes a byte of data to the UART.\nfunc (uart *UART) writeByte(c byte) error {\n\t// wait until ready to receive\n\tfor !uart.Bus.INTFLAG.HasBits(sam.SERCOM_USART_INT_INTFLAG_DRE) {\n\t}\n\tuart.Bus.DATA.Set(uint32(c))\n\treturn nil\n}\n\nfunc (uart *UART) flush() {}\n\nfunc (uart *UART) handleInterrupt(interrupt.Interrupt) {\n\t// should reset IRQ\n\tuart.Receive(byte((uart.Bus.DATA.Get() & 0xFF)))\n\tuart.Bus.INTFLAG.SetBits(sam.SERCOM_USART_INT_INTFLAG_RXC)\n}\n\n// I2C on the SAMD51.\ntype I2C struct {\n\tBus    *sam.SERCOM_I2CM_Type\n\tSERCOM uint8\n}\n\n// I2CConfig is used to store config info for I2C.\ntype I2CConfig struct {\n\tFrequency uint32\n\tSCL       Pin\n\tSDA       Pin\n}\n\nconst (\n\t// SERCOM_FREQ_REF is always reference frequency on SAMD51 regardless of CPU speed.\n\tSERCOM_FREQ_REF       = 48000000\n\tSERCOM_FREQ_REF_GCLK0 = 120000000\n\n\t// Default rise time in nanoseconds, based on 4.7K ohm pull up resistors\n\triseTimeNanoseconds = 125\n\n\t// wire bus states\n\twireUnknownState = 0\n\twireIdleState    = 1\n\twireOwnerState   = 2\n\twireBusyState    = 3\n\n\t// wire commands\n\twireCmdNoAction    = 0\n\twireCmdRepeatStart = 1\n\twireCmdRead        = 2\n\twireCmdStop        = 3\n)\n\nconst i2cTimeout = 28000 // about 210us\n\n// Configure is intended to setup the I2C interface.\nfunc (i2c *I2C) Configure(config I2CConfig) error {\n\t// Default I2C bus speed is 100 kHz.\n\tif config.Frequency == 0 {\n\t\tconfig.Frequency = 100 * KHz\n\t}\n\n\t// Use default I2C pins if not set.\n\tif config.SDA == 0 && config.SCL == 0 {\n\t\tconfig.SDA = SDA_PIN\n\t\tconfig.SCL = SCL_PIN\n\t}\n\n\tsclPinMode, sclPad, ok := findPinPadMapping(i2c.SERCOM, config.SCL)\n\tif !ok || sclPad != 1 {\n\t\t// SCL must be on pad 1, according to section 36.4 of the datasheet.\n\t\t// Note: this is not an exhaustive test for I2C support on the pin: not\n\t\t// all pins support I2C.\n\t\treturn ErrInvalidClockPin\n\t}\n\tsdaPinMode, sdaPad, ok := findPinPadMapping(i2c.SERCOM, config.SDA)\n\tif !ok || sdaPad != 0 {\n\t\t// SDA must be on pad 0, according to section 36.4 of the datasheet.\n\t\t// Note: this is not an exhaustive test for I2C support on the pin: not\n\t\t// all pins support I2C.\n\t\treturn ErrInvalidDataPin\n\t}\n\n\t// reset SERCOM\n\ti2c.Bus.CTRLA.SetBits(sam.SERCOM_I2CM_CTRLA_SWRST)\n\tfor i2c.Bus.CTRLA.HasBits(sam.SERCOM_I2CM_CTRLA_SWRST) ||\n\t\ti2c.Bus.SYNCBUSY.HasBits(sam.SERCOM_I2CM_SYNCBUSY_SWRST) {\n\t}\n\n\t// set clock\n\tsetSERCOMClockGenerator(i2c.SERCOM, sam.GCLK_PCHCTRL_GEN_GCLK1)\n\n\t// Set i2c controller mode\n\t//SERCOM_I2CM_CTRLA_MODE( I2C_MASTER_OPERATION )\n\t// sam.SERCOM_I2CM_CTRLA_MODE_I2C_MASTER = 5?\n\ti2c.Bus.CTRLA.Set(5 << sam.SERCOM_I2CM_CTRLA_MODE_Pos) // |\n\n\ti2c.SetBaudRate(config.Frequency)\n\n\t// Enable I2CM port.\n\t// sercom->USART.CTRLA.bit.ENABLE = 0x1u;\n\ti2c.Bus.CTRLA.SetBits(sam.SERCOM_I2CM_CTRLA_ENABLE)\n\tfor i2c.Bus.SYNCBUSY.HasBits(sam.SERCOM_I2CM_SYNCBUSY_ENABLE) {\n\t}\n\n\t// set bus idle mode\n\ti2c.Bus.STATUS.SetBits(wireIdleState << sam.SERCOM_I2CM_STATUS_BUSSTATE_Pos)\n\tfor i2c.Bus.SYNCBUSY.HasBits(sam.SERCOM_I2CM_SYNCBUSY_SYSOP) {\n\t}\n\n\t// enable pins\n\tconfig.SDA.Configure(PinConfig{Mode: sdaPinMode})\n\tconfig.SCL.Configure(PinConfig{Mode: sclPinMode})\n\n\treturn nil\n}\n\n// SetBaudRate sets the communication speed for I2C.\nfunc (i2c *I2C) SetBaudRate(br uint32) error {\n\t// Synchronous arithmetic baudrate, via Adafruit SAMD51 implementation:\n\t// sercom->I2CM.BAUD.bit.BAUD = SERCOM_FREQ_REF / ( 2 * baudrate) - 1 ;\n\tbaud := SERCOM_FREQ_REF/(2*br) - 1\n\ti2c.Bus.BAUD.Set(baud)\n\treturn nil\n}\n\n// Tx does a single I2C transaction at the specified address.\n// It clocks out the given address, writes the bytes in w, reads back len(r)\n// bytes and stores them in r, and generates a stop condition on the bus.\nfunc (i2c *I2C) Tx(addr uint16, w, r []byte) error {\n\tvar err error\n\tif len(w) != 0 {\n\t\t// send start/address for write\n\t\ti2c.sendAddress(addr, true)\n\n\t\t// wait until transmission complete\n\t\ttimeout := i2cTimeout\n\t\tfor !i2c.Bus.INTFLAG.HasBits(sam.SERCOM_I2CM_INTFLAG_MB) {\n\t\t\ttimeout--\n\t\t\tif timeout == 0 {\n\t\t\t\treturn errI2CWriteTimeout\n\t\t\t}\n\t\t}\n\n\t\t// ACK received (0: ACK, 1: NACK)\n\t\tif i2c.Bus.STATUS.HasBits(sam.SERCOM_I2CM_STATUS_RXNACK) {\n\t\t\treturn errI2CAckExpected\n\t\t}\n\n\t\t// write data\n\t\tfor _, b := range w {\n\t\t\terr = i2c.WriteByte(b)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\n\t\terr = i2c.signalStop()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tif len(r) != 0 {\n\t\t// send start/address for read\n\t\ti2c.sendAddress(addr, false)\n\n\t\t// wait transmission complete\n\t\tfor !i2c.Bus.INTFLAG.HasBits(sam.SERCOM_I2CM_INTFLAG_SB) {\n\t\t\t// If the peripheral NACKS the address, the MB bit will be set.\n\t\t\t// In that case, send a stop condition and return error.\n\t\t\tif i2c.Bus.INTFLAG.HasBits(sam.SERCOM_I2CM_INTFLAG_MB) {\n\t\t\t\ti2c.Bus.CTRLB.SetBits(wireCmdStop << sam.SERCOM_I2CM_CTRLB_CMD_Pos) // Stop condition\n\t\t\t\treturn errI2CAckExpected\n\t\t\t}\n\t\t}\n\n\t\t// ACK received (0: ACK, 1: NACK)\n\t\tif i2c.Bus.STATUS.HasBits(sam.SERCOM_I2CM_STATUS_RXNACK) {\n\t\t\treturn errI2CAckExpected\n\t\t}\n\n\t\t// read first byte\n\t\tr[0] = i2c.readByte()\n\t\tfor i := 1; i < len(r); i++ {\n\t\t\t// Send an ACK\n\t\t\ti2c.Bus.CTRLB.ClearBits(sam.SERCOM_I2CM_CTRLB_ACKACT)\n\n\t\t\ti2c.signalRead()\n\n\t\t\t// Read data and send the ACK\n\t\t\tr[i] = i2c.readByte()\n\t\t}\n\n\t\t// Send NACK to end transmission\n\t\ti2c.Bus.CTRLB.SetBits(sam.SERCOM_I2CM_CTRLB_ACKACT)\n\n\t\terr = i2c.signalStop()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// WriteByte writes a single byte to the I2C bus.\nfunc (i2c *I2C) WriteByte(data byte) error {\n\t// Send data byte\n\ti2c.Bus.DATA.Set(data)\n\n\t// wait until transmission successful\n\ttimeout := i2cTimeout\n\tfor !i2c.Bus.INTFLAG.HasBits(sam.SERCOM_I2CM_INTFLAG_MB) {\n\t\t// check for bus error\n\t\tif i2c.Bus.STATUS.HasBits(sam.SERCOM_I2CM_STATUS_BUSERR) {\n\t\t\treturn errI2CBusError\n\t\t}\n\t\ttimeout--\n\t\tif timeout == 0 {\n\t\t\treturn errI2CWriteTimeout\n\t\t}\n\t}\n\n\tif i2c.Bus.STATUS.HasBits(sam.SERCOM_I2CM_STATUS_RXNACK) {\n\t\treturn errI2CAckExpected\n\t}\n\n\treturn nil\n}\n\n// sendAddress sends the address and start signal\nfunc (i2c *I2C) sendAddress(address uint16, write bool) error {\n\tdata := (address << 1)\n\tif !write {\n\t\tdata |= 1 // set read flag\n\t}\n\n\t// wait until bus ready\n\ttimeout := i2cTimeout\n\tfor !i2c.Bus.STATUS.HasBits(wireIdleState<<sam.SERCOM_I2CM_STATUS_BUSSTATE_Pos) &&\n\t\t!i2c.Bus.STATUS.HasBits(wireOwnerState<<sam.SERCOM_I2CM_STATUS_BUSSTATE_Pos) {\n\t\ttimeout--\n\t\tif timeout == 0 {\n\t\t\treturn errI2CBusReadyTimeout\n\t\t}\n\t}\n\ti2c.Bus.ADDR.Set(uint32(data))\n\n\treturn nil\n}\n\nfunc (i2c *I2C) signalStop() error {\n\ti2c.Bus.CTRLB.SetBits(wireCmdStop << sam.SERCOM_I2CM_CTRLB_CMD_Pos) // Stop command\n\ttimeout := i2cTimeout\n\tfor i2c.Bus.SYNCBUSY.HasBits(sam.SERCOM_I2CM_SYNCBUSY_SYSOP) {\n\t\ttimeout--\n\t\tif timeout == 0 {\n\t\t\treturn errI2CSignalStopTimeout\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (i2c *I2C) signalRead() error {\n\ti2c.Bus.CTRLB.SetBits(wireCmdRead << sam.SERCOM_I2CM_CTRLB_CMD_Pos) // Read command\n\ttimeout := i2cTimeout\n\tfor i2c.Bus.SYNCBUSY.HasBits(sam.SERCOM_I2CM_SYNCBUSY_SYSOP) {\n\t\ttimeout--\n\t\tif timeout == 0 {\n\t\t\treturn errI2CSignalReadTimeout\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (i2c *I2C) readByte() byte {\n\tfor !i2c.Bus.INTFLAG.HasBits(sam.SERCOM_I2CM_INTFLAG_SB) {\n\t}\n\treturn byte(i2c.Bus.DATA.Get())\n}\n\n// SPI\ntype SPI struct {\n\tBus    *sam.SERCOM_SPIM_Type\n\tSERCOM uint8\n}\n\n// SPIConfig is used to store config info for SPI.\ntype SPIConfig struct {\n\tFrequency uint32\n\tSCK       Pin\n\tSDO       Pin\n\tSDI       Pin\n\tLSBFirst  bool\n\tMode      uint8\n}\n\n// Configure is intended to setup the SPI interface.\nfunc (spi *SPI) Configure(config SPIConfig) error {\n\t// Use default pins if not set.\n\tif config.SCK == 0 && config.SDO == 0 && config.SDI == 0 {\n\t\tconfig.SCK = SPI0_SCK_PIN\n\t\tconfig.SDO = SPI0_SDO_PIN\n\t\tconfig.SDI = SPI0_SDI_PIN\n\t}\n\n\t// set default frequency\n\tif config.Frequency == 0 {\n\t\tconfig.Frequency = 4000000\n\t}\n\n\t// Determine the input pinout (for SDI).\n\tvar dataInPinout uint32\n\tvar SDIPinMode PinMode\n\tif config.SDI != NoPin {\n\t\tvar ok bool\n\t\tSDIPinMode, dataInPinout, ok = findPinPadMapping(spi.SERCOM, config.SDI)\n\t\tif !ok {\n\t\t\treturn ErrInvalidInputPin\n\t\t}\n\t}\n\n\t// Determine the output pinout (for SDO/SCK).\n\t// See DOPO field in the CTRLA register on page 986 of the datasheet.\n\tvar dataOutPinout uint32\n\tsckPinMode, sckPad, ok := findPinPadMapping(spi.SERCOM, config.SCK)\n\tif !ok || sckPad != 1 {\n\t\t// SCK pad must always be 1\n\t\treturn ErrInvalidOutputPin\n\t}\n\tSDOPinMode, SDOPad, ok := findPinPadMapping(spi.SERCOM, config.SDO)\n\tif !ok {\n\t\treturn ErrInvalidOutputPin\n\t}\n\tswitch SDOPad {\n\tcase 0:\n\t\tdataOutPinout = 0x0\n\tcase 3:\n\t\tdataOutPinout = 0x2\n\tdefault:\n\t\treturn ErrInvalidOutputPin\n\t}\n\n\t// Disable SPI port.\n\tspi.Bus.CTRLA.ClearBits(sam.SERCOM_SPIM_CTRLA_ENABLE)\n\tfor spi.Bus.SYNCBUSY.HasBits(sam.SERCOM_SPIM_SYNCBUSY_ENABLE) {\n\t}\n\n\t// enable pins\n\tconfig.SCK.Configure(PinConfig{Mode: sckPinMode})\n\tconfig.SDO.Configure(PinConfig{Mode: SDOPinMode})\n\tif config.SDI != NoPin {\n\t\tconfig.SDI.Configure(PinConfig{Mode: SDIPinMode})\n\t}\n\n\t// reset SERCOM\n\tspi.Bus.CTRLA.SetBits(sam.SERCOM_SPIM_CTRLA_SWRST)\n\tfor spi.Bus.CTRLA.HasBits(sam.SERCOM_SPIM_CTRLA_SWRST) ||\n\t\tspi.Bus.SYNCBUSY.HasBits(sam.SERCOM_SPIM_SYNCBUSY_SWRST) {\n\t}\n\n\t// set bit transfer order\n\tdataOrder := uint32(0)\n\tif config.LSBFirst {\n\t\tdataOrder = 1\n\t}\n\n\t// Set SPI controller\n\t// SERCOM_SPIM_CTRLA_MODE_SPI_MASTER = 3\n\tspi.Bus.CTRLA.Set((3 << sam.SERCOM_SPIM_CTRLA_MODE_Pos) |\n\t\t(dataOutPinout << sam.SERCOM_SPIM_CTRLA_DOPO_Pos) |\n\t\t(dataInPinout << sam.SERCOM_SPIM_CTRLA_DIPO_Pos) |\n\t\t(dataOrder << sam.SERCOM_SPIM_CTRLA_DORD_Pos))\n\n\tspi.Bus.CTRLB.SetBits((0 << sam.SERCOM_SPIM_CTRLB_CHSIZE_Pos) | // 8bit char size\n\t\tsam.SERCOM_SPIM_CTRLB_RXEN) // receive enable\n\n\tfor spi.Bus.SYNCBUSY.HasBits(sam.SERCOM_SPIM_SYNCBUSY_CTRLB) {\n\t}\n\n\t// set mode\n\tswitch config.Mode {\n\tcase 0:\n\t\tspi.Bus.CTRLA.ClearBits(sam.SERCOM_SPIM_CTRLA_CPHA)\n\t\tspi.Bus.CTRLA.ClearBits(sam.SERCOM_SPIM_CTRLA_CPOL)\n\tcase 1:\n\t\tspi.Bus.CTRLA.SetBits(sam.SERCOM_SPIM_CTRLA_CPHA)\n\t\tspi.Bus.CTRLA.ClearBits(sam.SERCOM_SPIM_CTRLA_CPOL)\n\tcase 2:\n\t\tspi.Bus.CTRLA.ClearBits(sam.SERCOM_SPIM_CTRLA_CPHA)\n\t\tspi.Bus.CTRLA.SetBits(sam.SERCOM_SPIM_CTRLA_CPOL)\n\tcase 3:\n\t\tspi.Bus.CTRLA.SetBits(sam.SERCOM_SPIM_CTRLA_CPHA | sam.SERCOM_SPIM_CTRLA_CPOL)\n\tdefault: // to mode 0\n\t\tspi.Bus.CTRLA.ClearBits(sam.SERCOM_SPIM_CTRLA_CPHA)\n\t\tspi.Bus.CTRLA.ClearBits(sam.SERCOM_SPIM_CTRLA_CPOL)\n\t}\n\n\t// Set the clock frequency.\n\t// There are two clocks we can use GCLK0 (120MHz) and GCLK1 (48MHz).\n\t// We can use any even divisor for these clock, which means:\n\t//   - for GCLK0 we can make 60MHz, 30MHz, 20MHz, 15MHz, 12MHz, 10MHz, etc\n\t//   - for GCLK1 we can make 24MHz, 12MHz, 8MHz, 6MHz, 4.8MHz, 4MHz, etc\n\t// This means that by trying both clocks, we can have a wider selection of\n\t// available SPI clock frequencies.\n\n\t// Calculate the baudrate if we would use GCLK1 (48MHz), and the resulting\n\t// frequency. The baud rate is rounded up, so that the resulting frequency\n\t// is rounded down from the maximum value (meaning it will always be smaller\n\t// than or equal to config.Frequency).\n\tbaudRateGCLK1 := (SERCOM_FREQ_REF/2 + config.Frequency - 1) / config.Frequency\n\tfreqGCLK1 := SERCOM_FREQ_REF / 2 / baudRateGCLK1\n\n\t// Same for GCLK0 (120MHz).\n\tbaudRateGCLK0 := (SERCOM_FREQ_REF_GCLK0/2 + config.Frequency - 1) / config.Frequency\n\tfreqGCLK0 := SERCOM_FREQ_REF_GCLK0 / 2 / baudRateGCLK0\n\n\t// Pick the clock source that is the closest to the maximum baud rate.\n\t// Note: there may be reasons to prefer the lower frequency clock (like\n\t// power consumption). If that's the case, we might want to always use the\n\t// 48MHz clock at low frequencies (below 4MHz or so).\n\tif freqGCLK0 > freqGCLK1 && uint32(uint8(baudRateGCLK0-1))+1 == baudRateGCLK0 {\n\t\t// Pick this 120MHz clock if it results in a better frequency after\n\t\t// division, and the baudRate value fits in the BAUD register.\n\t\tsetSERCOMClockGenerator(spi.SERCOM, sam.GCLK_PCHCTRL_GEN_GCLK0)\n\t\tspi.Bus.BAUD.Set(uint8(baudRateGCLK0 - 1))\n\t} else {\n\t\t// Use the 48MHz clock in other cases.\n\t\tsetSERCOMClockGenerator(spi.SERCOM, sam.GCLK_PCHCTRL_GEN_GCLK1)\n\t\tspi.Bus.BAUD.Set(uint8(baudRateGCLK1 - 1))\n\t}\n\n\t// Enable SPI port.\n\tspi.Bus.CTRLA.SetBits(sam.SERCOM_SPIM_CTRLA_ENABLE)\n\tfor spi.Bus.SYNCBUSY.HasBits(sam.SERCOM_SPIM_SYNCBUSY_ENABLE) {\n\t}\n\n\treturn nil\n}\n\n// Transfer writes/reads a single byte using the SPI interface.\nfunc (spi *SPI) Transfer(w byte) (byte, error) {\n\t// write data\n\tspi.Bus.DATA.Set(uint32(w))\n\n\t// wait for receive\n\tfor !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_RXC) {\n\t}\n\n\t// return data\n\treturn byte(spi.Bus.DATA.Get()), nil\n}\n\n// Tx handles read/write operation for SPI interface. Since SPI is a synchronous write/read\n// interface, there must always be the same number of bytes written as bytes read.\n// The Tx method knows about this, and offers a few different ways of calling it.\n//\n// This form sends the bytes in tx buffer, putting the resulting bytes read into the rx buffer.\n// Note that the tx and rx buffers must be the same size:\n//\n//\tspi.Tx(tx, rx)\n//\n// This form sends the tx buffer, ignoring the result. Useful for sending \"commands\" that return zeros\n// until all the bytes in the command packet have been received:\n//\n//\tspi.Tx(tx, nil)\n//\n// This form sends zeros, putting the result into the rx buffer. Good for reading a \"result packet\":\n//\n//\tspi.Tx(nil, rx)\nfunc (spi *SPI) Tx(w, r []byte) error {\n\tswitch {\n\tcase w == nil:\n\t\t// read only, so write zero and read a result.\n\t\tspi.rx(r)\n\tcase r == nil:\n\t\t// write only\n\t\tspi.tx(w)\n\n\tdefault:\n\t\t// write/read\n\t\tif len(w) != len(r) {\n\t\t\treturn ErrTxInvalidSliceSize\n\t\t}\n\n\t\tspi.txrx(w, r)\n\t}\n\n\treturn nil\n}\n\nfunc (spi *SPI) tx(tx []byte) {\n\tfor i := 0; i < len(tx); i++ {\n\t\tfor !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_DRE) {\n\t\t}\n\t\tspi.Bus.DATA.Set(uint32(tx[i]))\n\t}\n\tfor !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_TXC) {\n\t}\n\n\t// read to clear RXC register\n\tfor spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_RXC) {\n\t\tspi.Bus.DATA.Get()\n\t}\n}\n\nfunc (spi *SPI) rx(rx []byte) {\n\tspi.Bus.DATA.Set(0)\n\tfor !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_DRE) {\n\t}\n\n\tfor i := 1; i < len(rx); i++ {\n\t\tspi.Bus.DATA.Set(0)\n\t\tfor !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_RXC) {\n\t\t}\n\t\trx[i-1] = byte(spi.Bus.DATA.Get())\n\t}\n\tfor !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_RXC) {\n\t}\n\trx[len(rx)-1] = byte(spi.Bus.DATA.Get())\n}\n\nfunc (spi *SPI) txrx(tx, rx []byte) {\n\tspi.Bus.DATA.Set(uint32(tx[0]))\n\tfor !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_DRE) {\n\t}\n\n\tfor i := 1; i < len(rx); i++ {\n\t\tspi.Bus.DATA.Set(uint32(tx[i]))\n\t\tfor !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_RXC) {\n\t\t}\n\t\trx[i-1] = byte(spi.Bus.DATA.Get())\n\t}\n\tfor !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_RXC) {\n\t}\n\trx[len(rx)-1] = byte(spi.Bus.DATA.Get())\n}\n\n// The QSPI peripheral on ATSAMD51 is only available on the following pins\nconst (\n\tQSPI_SCK   = PB10\n\tQSPI_CS    = PB11\n\tQSPI_DATA0 = PA08\n\tQSPI_DATA1 = PA09\n\tQSPI_DATA2 = PA10\n\tQSPI_DATA3 = PA11\n)\n\n// TCC is one timer peripheral, which consists of a counter and multiple output\n// channels (that can be connected to actual pins). You can set the frequency\n// using SetPeriod, but only for all the channels in this timer peripheral at\n// once.\ntype TCC sam.TCC_Type\n\n//go:inline\nfunc (tcc *TCC) timer() *sam.TCC_Type {\n\treturn (*sam.TCC_Type)(tcc)\n}\n\n// Configure enables and configures this TCC.\nfunc (tcc *TCC) Configure(config PWMConfig) error {\n\t// Enable the TCC clock to be able to use the TCC.\n\ttcc.configureClock()\n\n\t// Disable timer (if it was enabled). This is necessary because\n\t// tcc.setPeriod may want to change the prescaler bits in CTRLA, which is\n\t// only allowed when the TCC is disabled.\n\ttcc.timer().CTRLA.ClearBits(sam.TCC_CTRLA_ENABLE)\n\n\t// Use \"Normal PWM\" (single-slope PWM)\n\ttcc.timer().WAVE.Set(sam.TCC_WAVE_WAVEGEN_NPWM)\n\n\t// Wait for synchronization of all changed registers.\n\tfor tcc.timer().SYNCBUSY.Get() != 0 {\n\t}\n\n\t// Set the period and prescaler.\n\terr := tcc.setPeriod(config.Period, true)\n\n\t// Enable the timer.\n\ttcc.timer().CTRLA.SetBits(sam.TCC_CTRLA_ENABLE)\n\n\t// Wait for synchronization of all changed registers.\n\tfor tcc.timer().SYNCBUSY.Get() != 0 {\n\t}\n\n\t// Return any error that might have occurred in the tcc.setPeriod call.\n\treturn err\n}\n\n// SetPeriod updates the period of this TCC peripheral.\n// To set a particular frequency, use the following formula:\n//\n//\tperiod = 1e9 / frequency\n//\n// If you use a period of 0, a period that works well for LEDs will be picked.\n//\n// SetPeriod will not change the prescaler, but also won't change the current\n// value in any of the channels. This means that you may need to update the\n// value for the particular channel.\n//\n// Note that you cannot pick any arbitrary period after the TCC peripheral has\n// been configured. If you want to switch between frequencies, pick the lowest\n// frequency (longest period) once when calling Configure and adjust the\n// frequency here as needed.\nfunc (tcc *TCC) SetPeriod(period uint64) error {\n\treturn tcc.setPeriod(period, false)\n}\n\n// setPeriod sets the period of this TCC, possibly updating the prescaler as\n// well. The prescaler can only modified when the TCC is disabled, that is, in\n// the Configure function.\nfunc (tcc *TCC) setPeriod(period uint64, updatePrescaler bool) error {\n\tvar top uint64\n\tif period == 0 {\n\t\t// Make sure the TOP value is at 0xffff (enough for a 16-bit timer).\n\t\ttop = 0xffff\n\t} else {\n\t\t// The formula below calculates the following formula, optimized:\n\t\t//     period * (120e6 / 1e9)\n\t\t// This assumes that the chip is running from generic clock generator 0\n\t\t// at 120MHz.\n\t\ttop = period * 3 / 25\n\t}\n\n\tmaxTop := uint64(0xffff)\n\tif tcc.timer() == sam.TCC0 || tcc.timer() == sam.TCC1 {\n\t\t// Only TCC0 and TCC1 are 24-bit timers, the rest are 16-bit.\n\t\tmaxTop = 0xffffff\n\t}\n\n\tif updatePrescaler {\n\t\t// This function was called during Configure(), with the timer disabled.\n\t\t// Note that updating the prescaler can only happen while the peripheral\n\t\t// is disabled.\n\t\tvar prescaler uint32\n\t\tswitch {\n\t\tcase top <= maxTop:\n\t\t\tprescaler = sam.TCC_CTRLA_PRESCALER_DIV1\n\t\tcase top/2 <= maxTop:\n\t\t\tprescaler = sam.TCC_CTRLA_PRESCALER_DIV2\n\t\t\ttop = top / 2\n\t\tcase top/4 <= maxTop:\n\t\t\tprescaler = sam.TCC_CTRLA_PRESCALER_DIV4\n\t\t\ttop = top / 4\n\t\tcase top/8 <= maxTop:\n\t\t\tprescaler = sam.TCC_CTRLA_PRESCALER_DIV8\n\t\t\ttop = top / 8\n\t\tcase top/16 <= maxTop:\n\t\t\tprescaler = sam.TCC_CTRLA_PRESCALER_DIV16\n\t\t\ttop = top / 16\n\t\tcase top/64 <= maxTop:\n\t\t\tprescaler = sam.TCC_CTRLA_PRESCALER_DIV64\n\t\t\ttop = top / 64\n\t\tcase top/256 <= maxTop:\n\t\t\tprescaler = sam.TCC_CTRLA_PRESCALER_DIV256\n\t\t\ttop = top / 256\n\t\tcase top/1024 <= maxTop:\n\t\t\tprescaler = sam.TCC_CTRLA_PRESCALER_DIV1024\n\t\t\ttop = top / 1024\n\t\tdefault:\n\t\t\treturn ErrPWMPeriodTooLong\n\t\t}\n\t\ttcc.timer().CTRLA.Set((tcc.timer().CTRLA.Get() &^ sam.TCC_CTRLA_PRESCALER_Msk) | (prescaler << sam.TCC_CTRLA_PRESCALER_Pos))\n\t} else {\n\t\t// Do not update the prescaler, but use the already-configured\n\t\t// prescaler. This is the normal SetPeriod case, where the prescaler\n\t\t// must not be changed.\n\t\tprescaler := (tcc.timer().CTRLA.Get() & sam.TCC_CTRLA_PRESCALER_Msk) >> sam.TCC_CTRLA_PRESCALER_Pos\n\t\tswitch prescaler {\n\t\tcase sam.TCC_CTRLA_PRESCALER_DIV1:\n\t\t\ttop /= 1 // no-op\n\t\tcase sam.TCC_CTRLA_PRESCALER_DIV2:\n\t\t\ttop /= 2\n\t\tcase sam.TCC_CTRLA_PRESCALER_DIV4:\n\t\t\ttop /= 4\n\t\tcase sam.TCC_CTRLA_PRESCALER_DIV8:\n\t\t\ttop /= 8\n\t\tcase sam.TCC_CTRLA_PRESCALER_DIV16:\n\t\t\ttop /= 16\n\t\tcase sam.TCC_CTRLA_PRESCALER_DIV64:\n\t\t\ttop /= 64\n\t\tcase sam.TCC_CTRLA_PRESCALER_DIV256:\n\t\t\ttop /= 256\n\t\tcase sam.TCC_CTRLA_PRESCALER_DIV1024:\n\t\t\ttop /= 1024\n\t\tdefault:\n\t\t\t// unreachable\n\t\t}\n\t\tif top > maxTop {\n\t\t\treturn ErrPWMPeriodTooLong\n\t\t}\n\t}\n\n\t// Set the period (the counter top).\n\ttcc.timer().PER.Set(uint32(top) - 1)\n\n\t// Wait for synchronization of CTRLA.PRESCALER and PER registers.\n\tfor tcc.timer().SYNCBUSY.Get() != 0 {\n\t}\n\n\treturn nil\n}\n\n// Top returns the current counter top, for use in duty cycle calculation. It\n// will only change with a call to Configure or SetPeriod, otherwise it is\n// constant.\n//\n// The value returned here is hardware dependent. In general, it's best to treat\n// it as an opaque value that can be divided by some number and passed to\n// tcc.Set (see tcc.Set for more information).\nfunc (tcc *TCC) Top() uint32 {\n\treturn tcc.timer().PER.Get() + 1\n}\n\n// Counter returns the current counter value of the timer in this TCC\n// peripheral. It may be useful for debugging.\nfunc (tcc *TCC) Counter() uint32 {\n\ttcc.timer().CTRLBSET.Set(sam.TCC_CTRLBSET_CMD_READSYNC << sam.TCC_CTRLBSET_CMD_Pos)\n\tfor tcc.timer().SYNCBUSY.Get() != 0 {\n\t}\n\treturn tcc.timer().COUNT.Get()\n}\n\n// Constants that encode a TCC number and WO number together in a single byte.\nconst (\n\tpinTCC0   = 1 << 4 // keep the value 0 usable as \"no value\"\n\tpinTCC1   = 2 << 4\n\tpinTCC2   = 3 << 4\n\tpinTCC3   = 4 << 4\n\tpinTCC4   = 5 << 4\n\tpinTCC0_0 = pinTCC0 | 0\n\tpinTCC0_1 = pinTCC0 | 1\n\tpinTCC0_2 = pinTCC0 | 2\n\tpinTCC0_3 = pinTCC0 | 3\n\tpinTCC0_4 = pinTCC0 | 4\n\tpinTCC0_5 = pinTCC0 | 5\n\tpinTCC0_6 = pinTCC0 | 6\n\tpinTCC1_0 = pinTCC1 | 0\n\tpinTCC1_2 = pinTCC1 | 2\n\tpinTCC1_4 = pinTCC1 | 4\n\tpinTCC1_6 = pinTCC1 | 6\n\tpinTCC2_0 = pinTCC2 | 0\n\tpinTCC2_2 = pinTCC2 | 2\n\tpinTCC3_0 = pinTCC3 | 0\n\tpinTCC4_0 = pinTCC4 | 0\n)\n\n// This is a copy of columns F and G (the TCC columns) of table 6-1 in the\n// datasheet:\n// http://ww1.microchip.com/downloads/en/DeviceDoc/60001507E.pdf\n// For example, \"TCC0/WO[2]\" is converted to pinTCC0_2.\n// Only the even pin numbers are stored here. The odd pin numbers are left out,\n// because their PWM output can be determined from the even number: just add one\n// to the wave output (WO) number.\nvar pinTimerMapping = [...]struct{ F, G uint8 }{\n\t// page 33\n\tPC04 / 2: {pinTCC0_0, 0},\n\tPA08 / 2: {pinTCC0_0, pinTCC1_4},\n\tPA10 / 2: {pinTCC0_2, pinTCC1_6},\n\tPB10 / 2: {pinTCC0_4, pinTCC1_0},\n\tPB12 / 2: {pinTCC3_0, pinTCC0_0},\n\tPB14 / 2: {pinTCC4_0, pinTCC0_2},\n\tPD08 / 2: {pinTCC0_1, 0},\n\tPD10 / 2: {pinTCC0_3, 0},\n\tPD12 / 2: {pinTCC0_5, 0},\n\tPC10 / 2: {pinTCC0_0, pinTCC1_4},\n\t// page 34\n\tPC12 / 2: {pinTCC0_2, pinTCC1_6},\n\tPC14 / 2: {pinTCC0_4, pinTCC1_0},\n\tPA12 / 2: {pinTCC0_6, pinTCC1_2},\n\tPA14 / 2: {pinTCC2_0, pinTCC1_2},\n\tPA16 / 2: {pinTCC1_0, pinTCC0_4},\n\tPA18 / 2: {pinTCC1_2, pinTCC0_6},\n\tPC16 / 2: {pinTCC0_0, 0},\n\tPC18 / 2: {pinTCC0_2, 0},\n\tPC20 / 2: {pinTCC0_4, 0},\n\tPC22 / 2: {pinTCC0_6, 0},\n\tPD20 / 2: {pinTCC1_0, 0},\n\tPB16 / 2: {pinTCC3_0, pinTCC0_4},\n\tPB18 / 2: {pinTCC1_0, 0},\n\t// page 35\n\tPB20 / 2: {pinTCC1_2, 0},\n\tPA20 / 2: {pinTCC1_4, pinTCC0_0},\n\tPA22 / 2: {pinTCC1_6, pinTCC0_2},\n\tPA24 / 2: {pinTCC2_2, 0},\n\tPB26 / 2: {pinTCC1_2, 0},\n\tPB28 / 2: {pinTCC1_4, 0},\n\tPA30 / 2: {pinTCC2_0, 0},\n\t// page 36\n\tPB30 / 2: {pinTCC4_0, pinTCC0_6},\n\tPB02 / 2: {pinTCC2_2, 0},\n}\n\n// findPinTimerMapping returns the pin mode (PinTCCF or PinTCCG) and the channel\n// number for a given timer and pin. A zero PinMode is returned if no mapping\n// could be found.\nfunc findPinTimerMapping(timer uint8, pin Pin) (PinMode, uint8) {\n\tif int(pin/2) >= len(pinTimerMapping) {\n\t\treturn 0, 0 // invalid pin number\n\t}\n\n\tmapping := pinTimerMapping[pin/2]\n\n\t// Check for column F in the datasheet.\n\tif mapping.F>>4-1 == timer {\n\t\treturn PinTCCF, mapping.F&0x0f + uint8(pin)&1\n\t}\n\n\t// Check for column G in the datasheet.\n\tif mapping.G>>4-1 == timer {\n\t\treturn PinTCCG, mapping.G&0x0f + uint8(pin)&1\n\t}\n\n\t// Nothing found.\n\treturn 0, 0\n}\n\n// Channel returns a PWM channel for the given pin. Note that one channel may be\n// shared between multiple pins, and so will have the same duty cycle. If this\n// is not desirable, look for a different TCC or consider using a different pin.\nfunc (tcc *TCC) Channel(pin Pin) (uint8, error) {\n\tpinMode, woOutput := findPinTimerMapping(tcc.timerNum(), pin)\n\n\tif pinMode == 0 {\n\t\t// No pin could be found.\n\t\treturn 0, ErrInvalidOutputPin\n\t}\n\n\t// Convert from waveform output to channel, assuming WEXCTRL.OTMX equals 0.\n\t// See table 49-4 \"Output Matrix Channel Pin Routing Configuration\" on page\n\t// 1829 of the datasheet.\n\t// The number of channels varies by TCC instance, hence the need to switch\n\t// over them. For TCC2-4 the number of channels is equal to the number of\n\t// waveform outputs, so the WO number maps directly to the channel number.\n\t// For TCC0 and TCC1 this is not the case so they will need some special\n\t// handling.\n\tchannel := woOutput\n\tswitch tcc.timer() {\n\tcase sam.TCC0:\n\t\tchannel = woOutput % 6\n\tcase sam.TCC1:\n\t\tchannel = woOutput % 4\n\t}\n\n\t// Enable the port multiplexer for pin\n\tpin.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN)\n\n\t// Connect timer/mux to pin.\n\tif pin&1 > 0 {\n\t\t// odd pin, so save the even pins\n\t\tval := pin.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk\n\t\tpin.setPMux(val | uint8(pinMode<<sam.PORT_GROUP_PMUX_PMUXO_Pos))\n\t} else {\n\t\t// even pin, so save the odd pins\n\t\tval := pin.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk\n\t\tpin.setPMux(val | uint8(pinMode<<sam.PORT_GROUP_PMUX_PMUXE_Pos))\n\t}\n\n\treturn channel, nil\n}\n\n// SetInverting sets whether to invert the output of this channel.\n// Without inverting, a 25% duty cycle would mean the output is high for 25% of\n// the time and low for the rest. Inverting flips the output as if a NOT gate\n// was placed at the output, meaning that the output would be 25% low and 75%\n// high with a duty cycle of 25%.\nfunc (tcc *TCC) SetInverting(channel uint8, inverting bool) {\n\tif inverting {\n\t\ttcc.timer().WAVE.SetBits(1 << (sam.TCC_WAVE_POL0_Pos + channel))\n\t} else {\n\t\ttcc.timer().WAVE.ClearBits(1 << (sam.TCC_WAVE_POL0_Pos + channel))\n\t}\n\n\t// Wait for synchronization of the WAVE register.\n\tfor tcc.timer().SYNCBUSY.Get() != 0 {\n\t}\n}\n\n// Set updates the channel value. This is used to control the channel duty\n// cycle, in other words the fraction of time the channel output is high (or low\n// when inverted). For example, to set it to a 25% duty cycle, use:\n//\n//\ttcc.Set(channel, tcc.Top() / 4)\n//\n// tcc.Set(channel, 0) will set the output to low and tcc.Set(channel,\n// tcc.Top()) will set the output to high, assuming the output isn't inverted.\nfunc (tcc *TCC) Set(channel uint8, value uint32) {\n\t// Update CCBUF, which provides double buffering. The update is applied on\n\t// the next cycle.\n\ttcc.timer().CCBUF[channel].Set(value)\n\tfor tcc.timer().SYNCBUSY.Get() != 0 {\n\t}\n}\n\n// EnterBootloader should perform a system reset in preparation\n// to switch to the bootloader to flash new firmware.\nfunc EnterBootloader() {\n\tarm.DisableInterrupts()\n\n\t// Perform magic reset into bootloader, as mentioned in\n\t// https://github.com/arduino/ArduinoCore-samd/issues/197\n\t*(*uint32)(unsafe.Pointer(uintptr(0x20000000 + HSRAM_SIZE - 4))) = resetMagicValue\n\n\tarm.SystemReset()\n}\n\n// DAC on the SAMD51.\ntype DAC struct {\n\tChannel uint8\n}\n\nvar (\n\tDAC0 = DAC{Channel: 0}\n\tDAC1 = DAC{Channel: 1}\n)\n\n// DACConfig placeholder for future expansion.\ntype DACConfig struct {\n}\n\n// Configure the DAC.\n// output pin must already be configured.\nfunc (dac DAC) Configure(config DACConfig) {\n\t// Turn on clock for DAC\n\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_DAC_)\n\n\tif !sam.GCLK.PCHCTRL[42].HasBits(sam.GCLK_PCHCTRL_CHEN) {\n\t\t// Use Generic Clock Generator 4 as source for DAC.\n\t\tsam.GCLK.PCHCTRL[42].Set((sam.GCLK_PCHCTRL_GEN_GCLK4 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\t\tfor sam.GCLK.SYNCBUSY.HasBits(sam.GCLK_SYNCBUSY_GENCTRL_GCLK4 << sam.GCLK_SYNCBUSY_GENCTRL_Pos) {\n\t\t}\n\n\t\t// reset DAC\n\t\tsam.DAC.CTRLA.Set(sam.DAC_CTRLA_SWRST)\n\n\t\t// wait for reset complete\n\t\tfor sam.DAC.CTRLA.HasBits(sam.DAC_CTRLA_SWRST) {\n\t\t}\n\t\tfor sam.DAC.SYNCBUSY.HasBits(sam.DAC_SYNCBUSY_SWRST) {\n\t\t}\n\t}\n\n\tsam.DAC.CTRLA.ClearBits(sam.DAC_CTRLA_ENABLE)\n\tfor sam.DAC.SYNCBUSY.HasBits(sam.DAC_SYNCBUSY_ENABLE) {\n\t}\n\n\t// enable\n\tsam.DAC.CTRLB.Set(sam.DAC_CTRLB_REFSEL_VREFPU << sam.DAC_CTRLB_REFSEL_Pos)\n\tsam.DAC.DACCTRL[dac.Channel].SetBits((sam.DAC_DACCTRL_CCTRL_CC12M << sam.DAC_DACCTRL_CCTRL_Pos) | sam.DAC_DACCTRL_ENABLE)\n\tsam.DAC.CTRLA.Set(sam.DAC_CTRLA_ENABLE)\n\n\tfor sam.DAC.SYNCBUSY.HasBits(sam.DAC_SYNCBUSY_ENABLE) {\n\t}\n\n\tswitch dac.Channel {\n\tcase 0:\n\t\tfor !sam.DAC.STATUS.HasBits(sam.DAC_STATUS_READY0) {\n\t\t}\n\tdefault:\n\t\tfor !sam.DAC.STATUS.HasBits(sam.DAC_STATUS_READY1) {\n\t\t}\n\t}\n}\n\n// Set writes a single 16-bit value to the DAC.\n// Since the ATSAMD51 only has a 12-bit DAC, the passed-in value will be scaled down.\nfunc (dac DAC) Set(value uint16) error {\n\tsam.DAC.DATA[dac.Channel].Set(value >> 4)\n\tdac.syncDAC()\n\treturn nil\n}\n\nfunc (dac DAC) syncDAC() {\n\tswitch dac.Channel {\n\tcase 0:\n\t\tfor !sam.DAC.STATUS.HasBits(sam.DAC_STATUS_EOC0) {\n\t\t}\n\t\tfor sam.DAC.SYNCBUSY.HasBits(sam.DAC_SYNCBUSY_DATA0) {\n\t\t}\n\tdefault:\n\t\tfor !sam.DAC.STATUS.HasBits(sam.DAC_STATUS_EOC1) {\n\t\t}\n\t\tfor sam.DAC.SYNCBUSY.HasBits(sam.DAC_SYNCBUSY_DATA1) {\n\t\t}\n\t}\n}\n\n// GetRNG returns 32 bits of cryptographically secure random data\nfunc GetRNG() (uint32, error) {\n\tif !sam.MCLK.APBCMASK.HasBits(sam.MCLK_APBCMASK_TRNG_) {\n\t\t// Turn on clock for TRNG\n\t\tsam.MCLK.APBCMASK.SetBits(sam.MCLK_APBCMASK_TRNG_)\n\n\t\t// enable\n\t\tsam.TRNG.CTRLA.Set(sam.TRNG_CTRLA_ENABLE)\n\t}\n\tfor !sam.TRNG.INTFLAG.HasBits(sam.TRNG_INTFLAG_DATARDY) {\n\t}\n\tret := sam.TRNG.DATA.Get()\n\treturn ret, nil\n}\n\n// Flash related code\nconst memoryStart = 0x0\n\n// compile-time check for ensuring we fulfill BlockDevice interface\nvar _ BlockDevice = flashBlockDevice{}\n\nvar Flash flashBlockDevice\n\ntype flashBlockDevice struct {\n\tinitComplete bool\n}\n\n// ReadAt reads the given number of bytes from the block device.\nfunc (f flashBlockDevice) ReadAt(p []byte, off int64) (n int, err error) {\n\tif FlashDataStart()+uintptr(off)+uintptr(len(p)) > FlashDataEnd() {\n\t\treturn 0, errFlashCannotReadPastEOF\n\t}\n\n\twaitWhileFlashBusy()\n\n\tdata := unsafe.Slice((*byte)(unsafe.Add(unsafe.Pointer(FlashDataStart()), uintptr(off))), len(p))\n\tcopy(p, data)\n\n\treturn len(p), nil\n}\n\n// WriteAt writes the given number of bytes to the block device.\n// Data is written to the page buffer in 4-byte chunks, then saved to flash memory.\n// See SAM-D5x-E5x-Family-Data-Sheet-DS60001507.pdf page 591-592.\n// If the length of p is not long enough it will be padded with 0xFF bytes.\n// This method assumes that the destination is already erased.\nfunc (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) {\n\tif FlashDataStart()+uintptr(off)+uintptr(len(p)) > FlashDataEnd() {\n\t\treturn 0, errFlashCannotWritePastEOF\n\t}\n\n\taddress := FlashDataStart() + uintptr(off)\n\tpadded := flashPad(p, int(f.WriteBlockSize()))\n\n\tsettings := disableFlashCache()\n\tdefer restoreFlashCache(settings)\n\n\twaitWhileFlashBusy()\n\n\tsam.NVMCTRL.CTRLB.Set(sam.NVMCTRL_CTRLB_CMD_PBC | (sam.NVMCTRL_CTRLB_CMDEX_KEY << sam.NVMCTRL_CTRLB_CMDEX_Pos))\n\n\twaitWhileFlashBusy()\n\n\tfor j := 0; j < len(padded); j += int(f.WriteBlockSize()) {\n\t\t// page buffer is 512 bytes long, but only 4 bytes can be written at once\n\t\tfor k := 0; k < int(f.WriteBlockSize()); k += 4 {\n\t\t\t*(*uint32)(unsafe.Pointer(address + uintptr(k))) = binary.LittleEndian.Uint32(padded[j+k : j+k+4])\n\t\t}\n\n\t\tsam.NVMCTRL.SetADDR(uint32(address))\n\t\tsam.NVMCTRL.CTRLB.Set(sam.NVMCTRL_CTRLB_CMD_WP | (sam.NVMCTRL_CTRLB_CMDEX_KEY << sam.NVMCTRL_CTRLB_CMDEX_Pos))\n\n\t\twaitWhileFlashBusy()\n\n\t\tif err := checkFlashError(); err != nil {\n\t\t\treturn j, err\n\t\t}\n\n\t\taddress += uintptr(f.WriteBlockSize())\n\t}\n\n\treturn len(padded), nil\n}\n\n// Size returns the number of bytes in this block device.\nfunc (f flashBlockDevice) Size() int64 {\n\treturn int64(FlashDataEnd() - FlashDataStart())\n}\n\nconst writeBlockSize = 512\n\n// WriteBlockSize returns the block size in which data can be written to\n// memory. It can be used by a client to optimize writes, non-aligned writes\n// should always work correctly.\nfunc (f flashBlockDevice) WriteBlockSize() int64 {\n\treturn writeBlockSize\n}\n\nconst eraseBlockSizeValue = 8192\n\nfunc eraseBlockSize() int64 {\n\treturn eraseBlockSizeValue\n}\n\n// EraseBlockSize returns the smallest erasable area on this particular chip\n// in bytes. This is used for the block size in EraseBlocks.\nfunc (f flashBlockDevice) EraseBlockSize() int64 {\n\treturn eraseBlockSize()\n}\n\n// EraseBlocks erases the given number of blocks. An implementation may\n// transparently coalesce ranges of blocks into larger bundles if the chip\n// supports this. The start and len parameters are in block numbers, use\n// EraseBlockSize to map addresses to blocks.\nfunc (f flashBlockDevice) EraseBlocks(start, len int64) error {\n\taddress := FlashDataStart() + uintptr(start*f.EraseBlockSize())\n\n\tsettings := disableFlashCache()\n\tdefer restoreFlashCache(settings)\n\n\twaitWhileFlashBusy()\n\n\tfor i := start; i < start+len; i++ {\n\t\tsam.NVMCTRL.SetADDR(uint32(address))\n\t\tsam.NVMCTRL.CTRLB.Set(sam.NVMCTRL_CTRLB_CMD_EB | (sam.NVMCTRL_CTRLB_CMDEX_KEY << sam.NVMCTRL_CTRLB_CMDEX_Pos))\n\n\t\twaitWhileFlashBusy()\n\n\t\tif err := checkFlashError(); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\taddress += uintptr(f.EraseBlockSize())\n\t}\n\n\treturn nil\n}\n\nfunc disableFlashCache() uint16 {\n\tsettings := sam.NVMCTRL.CTRLA.Get()\n\n\t// disable caches\n\tsam.NVMCTRL.SetCTRLA_CACHEDIS0(1)\n\tsam.NVMCTRL.SetCTRLA_CACHEDIS1(1)\n\n\twaitWhileFlashBusy()\n\n\treturn settings\n}\n\nfunc restoreFlashCache(settings uint16) {\n\tsam.NVMCTRL.CTRLA.Set(settings)\n\twaitWhileFlashBusy()\n}\n\nfunc waitWhileFlashBusy() {\n\tfor sam.NVMCTRL.GetSTATUS_READY() != sam.NVMCTRL_STATUS_READY {\n\t}\n}\n\nvar (\n\terrFlashADDRE   = errors.New(\"errFlashADDRE\")\n\terrFlashPROGE   = errors.New(\"errFlashPROGE\")\n\terrFlashLOCKE   = errors.New(\"errFlashLOCKE\")\n\terrFlashECCSE   = errors.New(\"errFlashECCSE\")\n\terrFlashNVME    = errors.New(\"errFlashNVME\")\n\terrFlashSEESOVF = errors.New(\"errFlashSEESOVF\")\n)\n\nfunc checkFlashError() error {\n\tswitch {\n\tcase sam.NVMCTRL.GetINTENSET_ADDRE() != 0:\n\t\treturn errFlashADDRE\n\tcase sam.NVMCTRL.GetINTENSET_PROGE() != 0:\n\t\treturn errFlashPROGE\n\tcase sam.NVMCTRL.GetINTENSET_LOCKE() != 0:\n\t\treturn errFlashLOCKE\n\tcase sam.NVMCTRL.GetINTENSET_ECCSE() != 0:\n\t\treturn errFlashECCSE\n\tcase sam.NVMCTRL.GetINTENSET_NVME() != 0:\n\t\treturn errFlashNVME\n\tcase sam.NVMCTRL.GetINTENSET_SEESOVF() != 0:\n\t\treturn errFlashSEESOVF\n\t}\n\n\treturn nil\n}\n\n// Watchdog provides access to the hardware watchdog available\n// in the SAMD51.\nvar Watchdog = &watchdogImpl{}\n\nconst (\n\t// WatchdogMaxTimeout in milliseconds (16s)\n\tWatchdogMaxTimeout = (16384 * 1000) / 1024 // CYC16384/1024kHz\n)\n\ntype watchdogImpl struct{}\n\n// Configure the watchdog.\n//\n// This method should not be called after the watchdog is started and on\n// some platforms attempting to reconfigure after starting the watchdog\n// is explicitly forbidden / will not work.\nfunc (wd *watchdogImpl) Configure(config WatchdogConfig) error {\n\t// 1.024kHz clock\n\tcycles := int((int64(config.TimeoutMillis) * 1024) / 1000)\n\n\t// period is expressed as a power-of-two, starting at 8 / 1024ths of a second\n\tperiod := uint8(0)\n\tcfgCycles := 8\n\tfor cfgCycles < cycles {\n\t\tperiod++\n\t\tcfgCycles <<= 1\n\n\t\tif period >= 0xB {\n\t\t\tbreak\n\t\t}\n\t}\n\n\tsam.WDT.CONFIG.Set(period << sam.WDT_CONFIG_PER_Pos)\n\n\treturn nil\n}\n\n// Starts the watchdog.\nfunc (wd *watchdogImpl) Start() error {\n\tsam.WDT.CTRLA.SetBits(sam.WDT_CTRLA_ENABLE)\n\treturn nil\n}\n\n// Update the watchdog, indicating that `source` is healthy.\nfunc (wd *watchdogImpl) Update() {\n\tsam.WDT.CLEAR.Set(sam.WDT_CLEAR_CLEAR_KEY)\n}\n"
  },
  {
    "path": "src/machine/machine_atsamd51_usb.go",
    "content": "//go:build (sam && atsamd51) || (sam && atsame5x)\n\npackage machine\n\nimport (\n\t\"device/sam\"\n\t\"machine/usb\"\n\t\"runtime/interrupt\"\n\t\"unsafe\"\n)\n\nconst (\n\t// these are SAMD51 specific.\n\tusb_DEVICE_PCKSIZE_BYTE_COUNT_Pos  = 0\n\tusb_DEVICE_PCKSIZE_BYTE_COUNT_Mask = 0x3FFF\n\n\tusb_DEVICE_PCKSIZE_SIZE_Pos  = 28\n\tusb_DEVICE_PCKSIZE_SIZE_Mask = 0x7\n\n\tusb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Pos  = 14\n\tusb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Mask = 0x3FFF\n\n\tNumberOfUSBEndpoints = 8\n)\n\nvar (\n\tendPoints = []uint32{\n\t\tusb.CONTROL_ENDPOINT:  usb.ENDPOINT_TYPE_CONTROL,\n\t\tusb.CDC_ENDPOINT_ACM:  (usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn),\n\t\tusb.CDC_ENDPOINT_OUT:  (usb.ENDPOINT_TYPE_BULK | usb.EndpointOut),\n\t\tusb.CDC_ENDPOINT_IN:   (usb.ENDPOINT_TYPE_BULK | usb.EndpointIn),\n\t\tusb.HID_ENDPOINT_IN:   (usb.ENDPOINT_TYPE_DISABLE), // Interrupt In\n\t\tusb.HID_ENDPOINT_OUT:  (usb.ENDPOINT_TYPE_DISABLE), // Interrupt Out\n\t\tusb.MIDI_ENDPOINT_IN:  (usb.ENDPOINT_TYPE_DISABLE), // Bulk In\n\t\tusb.MIDI_ENDPOINT_OUT: (usb.ENDPOINT_TYPE_DISABLE), // Bulk Out\n\t}\n)\n\n// Configure the USB peripheral. The config is here for compatibility with the UART interface.\nfunc (dev *USBDevice) Configure(config UARTConfig) {\n\tif dev.initcomplete {\n\t\treturn\n\t}\n\n\t// reset USB interface\n\tsam.USB_DEVICE.CTRLA.SetBits(sam.USB_DEVICE_CTRLA_SWRST)\n\tfor sam.USB_DEVICE.SYNCBUSY.HasBits(sam.USB_DEVICE_SYNCBUSY_SWRST) ||\n\t\tsam.USB_DEVICE.SYNCBUSY.HasBits(sam.USB_DEVICE_SYNCBUSY_ENABLE) {\n\t}\n\n\tsam.USB_DEVICE.DESCADD.Set(uint32(uintptr(unsafe.Pointer(&usbEndpointDescriptors))))\n\n\t// configure pins\n\tUSBCDC_DM_PIN.Configure(PinConfig{Mode: PinCom})\n\tUSBCDC_DP_PIN.Configure(PinConfig{Mode: PinCom})\n\n\t// performs pad calibration from store fuses\n\thandlePadCalibration()\n\n\t// run in standby\n\tsam.USB_DEVICE.CTRLA.SetBits(sam.USB_DEVICE_CTRLA_RUNSTDBY)\n\n\t// set full speed\n\tsam.USB_DEVICE.CTRLB.SetBits(sam.USB_DEVICE_CTRLB_SPDCONF_FS << sam.USB_DEVICE_CTRLB_SPDCONF_Pos)\n\n\t// attach\n\tsam.USB_DEVICE.CTRLB.ClearBits(sam.USB_DEVICE_CTRLB_DETACH)\n\n\t// enable interrupt for end of reset\n\tsam.USB_DEVICE.INTENSET.SetBits(sam.USB_DEVICE_INTENSET_EORST)\n\n\t// enable interrupt for start of frame\n\tsam.USB_DEVICE.INTENSET.SetBits(sam.USB_DEVICE_INTENSET_SOF)\n\n\t// enable USB\n\tsam.USB_DEVICE.CTRLA.SetBits(sam.USB_DEVICE_CTRLA_ENABLE)\n\n\t// enable IRQ\n\tinterrupt.New(sam.IRQ_USB_OTHER, handleUSBIRQ).Enable()\n\tinterrupt.New(sam.IRQ_USB_SOF_HSOF, handleUSBIRQ).Enable()\n\tinterrupt.New(sam.IRQ_USB_TRCPT0, handleUSBIRQ).Enable()\n\tinterrupt.New(sam.IRQ_USB_TRCPT1, handleUSBIRQ).Enable()\n\n\tdev.initcomplete = true\n}\n\nfunc handlePadCalibration() {\n\t// Load Pad Calibration data from non-volatile memory\n\t// This requires registers that are not included in the SVD file.\n\t// Modeled after defines from samd21g18a.h and nvmctrl.h:\n\t//\n\t// #define NVMCTRL_OTP4 0x00806020\n\t//\n\t// #define USB_FUSES_TRANSN_ADDR       (NVMCTRL_OTP4 + 4)\n\t// #define USB_FUSES_TRANSN_Pos        13           /**< \\brief (NVMCTRL_OTP4) USB pad Transn calibration */\n\t// #define USB_FUSES_TRANSN_Msk        (0x1Fu << USB_FUSES_TRANSN_Pos)\n\t// #define USB_FUSES_TRANSN(value)     ((USB_FUSES_TRANSN_Msk & ((value) << USB_FUSES_TRANSN_Pos)))\n\n\t// #define USB_FUSES_TRANSP_ADDR       (NVMCTRL_OTP4 + 4)\n\t// #define USB_FUSES_TRANSP_Pos        18           /**< \\brief (NVMCTRL_OTP4) USB pad Transp calibration */\n\t// #define USB_FUSES_TRANSP_Msk        (0x1Fu << USB_FUSES_TRANSP_Pos)\n\t// #define USB_FUSES_TRANSP(value)     ((USB_FUSES_TRANSP_Msk & ((value) << USB_FUSES_TRANSP_Pos)))\n\n\t// #define USB_FUSES_TRIM_ADDR         (NVMCTRL_OTP4 + 4)\n\t// #define USB_FUSES_TRIM_Pos          23           /**< \\brief (NVMCTRL_OTP4) USB pad Trim calibration */\n\t// #define USB_FUSES_TRIM_Msk          (0x7u << USB_FUSES_TRIM_Pos)\n\t// #define USB_FUSES_TRIM(value)       ((USB_FUSES_TRIM_Msk & ((value) << USB_FUSES_TRIM_Pos)))\n\t//\n\tfuse := *(*uint32)(unsafe.Pointer(uintptr(0x00806020) + 4))\n\tcalibTransN := uint16(fuse>>13) & uint16(0x1f)\n\tcalibTransP := uint16(fuse>>18) & uint16(0x1f)\n\tcalibTrim := uint16(fuse>>23) & uint16(0x7)\n\n\tif calibTransN == 0x1f {\n\t\tcalibTransN = 5\n\t}\n\tsam.USB_DEVICE.PADCAL.SetBits(calibTransN << sam.USB_DEVICE_PADCAL_TRANSN_Pos)\n\n\tif calibTransP == 0x1f {\n\t\tcalibTransP = 29\n\t}\n\tsam.USB_DEVICE.PADCAL.SetBits(calibTransP << sam.USB_DEVICE_PADCAL_TRANSP_Pos)\n\n\tif calibTrim == 0x7 {\n\t\tcalibTrim = 3\n\t}\n\tsam.USB_DEVICE.PADCAL.SetBits(calibTrim << sam.USB_DEVICE_PADCAL_TRIM_Pos)\n}\n\nfunc handleUSBIRQ(intr interrupt.Interrupt) {\n\t// reset all interrupt flags\n\tflags := sam.USB_DEVICE.INTFLAG.Get()\n\tsam.USB_DEVICE.INTFLAG.Set(flags)\n\n\t// End of reset\n\tif (flags & sam.USB_DEVICE_INTFLAG_EORST) > 0 {\n\t\t// Configure control endpoint\n\t\tinitEndpoint(0, usb.ENDPOINT_TYPE_CONTROL)\n\n\t\tusbConfiguration = 0\n\n\t\t// ack the End-Of-Reset interrupt\n\t\tsam.USB_DEVICE.INTFLAG.Set(sam.USB_DEVICE_INTFLAG_EORST)\n\t}\n\n\t// Start of frame\n\tif (flags & sam.USB_DEVICE_INTFLAG_SOF) > 0 {\n\t\t// if you want to blink LED showing traffic, this would be the place...\n\t}\n\n\t// Endpoint 0 Setup interrupt\n\tif getEPINTFLAG(0)&sam.USB_DEVICE_ENDPOINT_EPINTFLAG_RXSTP > 0 {\n\t\t// ack setup received\n\t\tsetEPINTFLAG(0, sam.USB_DEVICE_ENDPOINT_EPINTFLAG_RXSTP)\n\n\t\t// parse setup\n\t\tsetup := usb.NewSetup(udd_ep_out_cache_buffer[0][:])\n\n\t\t// Clear the Bank 0 ready flag on Control OUT\n\t\tusbEndpointDescriptors[0].DeviceDescBank[0].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[0]))))\n\t\tusbEndpointDescriptors[0].DeviceDescBank[0].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)\n\t\tsetEPSTATUSCLR(0, sam.USB_DEVICE_ENDPOINT_EPSTATUSCLR_BK0RDY)\n\n\t\tok := false\n\t\tif (setup.BmRequestType & usb.REQUEST_TYPE) == usb.REQUEST_STANDARD {\n\t\t\t// Standard Requests\n\t\t\tok = handleStandardSetup(setup)\n\t\t} else {\n\t\t\t// Class Interface Requests\n\t\t\tif setup.WIndex < uint16(len(usbSetupHandler)) && usbSetupHandler[setup.WIndex] != nil {\n\t\t\t\tok = usbSetupHandler[setup.WIndex](setup)\n\t\t\t}\n\t\t}\n\n\t\tif ok {\n\t\t\t// set Bank1 ready\n\t\t\tsetEPSTATUSSET(0, sam.USB_DEVICE_ENDPOINT_EPSTATUSSET_BK1RDY)\n\t\t} else {\n\t\t\t// Stall endpoint\n\t\t\tsetEPSTATUSSET(0, sam.USB_DEVICE_ENDPOINT_EPINTFLAG_STALL1)\n\t\t}\n\n\t\tif getEPINTFLAG(0)&sam.USB_DEVICE_ENDPOINT_EPINTFLAG_STALL1 > 0 {\n\t\t\t// ack the stall\n\t\t\tsetEPINTFLAG(0, sam.USB_DEVICE_ENDPOINT_EPINTFLAG_STALL1)\n\n\t\t\t// clear stall request\n\t\t\tsetEPINTENCLR(0, sam.USB_DEVICE_ENDPOINT_EPINTENCLR_STALL1)\n\t\t}\n\t}\n\n\t// Now the actual transfer handlers, ignore endpoint number 0 (setup)\n\tvar i uint32\n\tfor i = 1; i < uint32(len(endPoints)); i++ {\n\t\t// Check if endpoint has a pending interrupt\n\t\tepFlags := getEPINTFLAG(i)\n\t\tsetEPINTFLAG(i, epFlags)\n\t\tif (epFlags & sam.USB_DEVICE_ENDPOINT_EPINTFLAG_TRCPT0) > 0 {\n\t\t\tbuf := handleEndpointRx(i)\n\t\t\tif usbRxHandler[i] == nil || usbRxHandler[i](buf) {\n\t\t\t\tAckUsbOutTransfer(i)\n\t\t\t}\n\t\t} else if (epFlags & sam.USB_DEVICE_ENDPOINT_EPINTFLAG_TRCPT1) > 0 {\n\t\t\tif usbTxHandler[i] != nil {\n\t\t\t\tusbTxHandler[i]()\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc initEndpoint(ep, config uint32) {\n\tswitch config {\n\tcase usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn:\n\t\t// set packet size\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.SetBits(epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos)\n\n\t\t// set data buffer address\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[1].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_in_cache_buffer[ep]))))\n\n\t\t// set endpoint type\n\t\tsetEPCFG(ep, ((usb.ENDPOINT_TYPE_INTERRUPT + 1) << sam.USB_DEVICE_ENDPOINT_EPCFG_EPTYPE1_Pos))\n\n\t\tsetEPINTENSET(ep, sam.USB_DEVICE_ENDPOINT_EPINTENSET_TRCPT1)\n\n\tcase usb.ENDPOINT_TYPE_BULK | usb.EndpointOut:\n\t\t// set packet size\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.SetBits(epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos)\n\n\t\t// set data buffer address\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[0].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[ep]))))\n\n\t\t// set endpoint type\n\t\tsetEPCFG(ep, ((usb.ENDPOINT_TYPE_BULK + 1) << sam.USB_DEVICE_ENDPOINT_EPCFG_EPTYPE0_Pos))\n\n\t\t// receive interrupts when current transfer complete\n\t\tsetEPINTENSET(ep, sam.USB_DEVICE_ENDPOINT_EPINTENSET_TRCPT0)\n\n\t\t// set byte count to zero, we have not received anything yet\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)\n\n\t\t// ready for next transfer\n\t\tsetEPSTATUSCLR(ep, sam.USB_DEVICE_ENDPOINT_EPSTATUSCLR_BK0RDY)\n\n\tcase usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointOut:\n\t\t// set packet size\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.SetBits(epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos)\n\n\t\t// set data buffer address\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[0].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[ep]))))\n\n\t\t// set endpoint type\n\t\tsetEPCFG(ep, ((usb.ENDPOINT_TYPE_INTERRUPT + 1) << sam.USB_DEVICE_ENDPOINT_EPCFG_EPTYPE0_Pos))\n\n\t\t// receive interrupts when current transfer complete\n\t\tsetEPINTENSET(ep, sam.USB_DEVICE_ENDPOINT_EPINTENSET_TRCPT0)\n\n\t\t// set byte count to zero, we have not received anything yet\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)\n\n\t\t// ready for next transfer\n\t\tsetEPSTATUSCLR(ep, sam.USB_DEVICE_ENDPOINT_EPSTATUSCLR_BK0RDY)\n\n\tcase usb.ENDPOINT_TYPE_BULK | usb.EndpointIn:\n\t\t// set packet size\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.SetBits(epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos)\n\n\t\t// set data buffer address\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[1].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_in_cache_buffer[ep]))))\n\n\t\t// set endpoint type\n\t\tsetEPCFG(ep, ((usb.ENDPOINT_TYPE_BULK + 1) << sam.USB_DEVICE_ENDPOINT_EPCFG_EPTYPE1_Pos))\n\n\t\t// NAK on endpoint IN, the bank is not yet filled in.\n\t\tsetEPSTATUSCLR(ep, sam.USB_DEVICE_ENDPOINT_EPSTATUSCLR_BK1RDY)\n\n\t\tsetEPINTENSET(ep, sam.USB_DEVICE_ENDPOINT_EPINTENSET_TRCPT1)\n\n\tcase usb.ENDPOINT_TYPE_CONTROL:\n\t\t// Control OUT\n\t\t// set packet size\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.SetBits(epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos)\n\n\t\t// set data buffer address\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[0].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[ep]))))\n\n\t\t// set endpoint type\n\t\tsetEPCFG(ep, getEPCFG(ep)|((usb.ENDPOINT_TYPE_CONTROL+1)<<sam.USB_DEVICE_ENDPOINT_EPCFG_EPTYPE0_Pos))\n\n\t\t// Control IN\n\t\t// set packet size\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.SetBits(epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos)\n\n\t\t// set data buffer address\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[1].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_in_cache_buffer[ep]))))\n\n\t\t// set endpoint type\n\t\tsetEPCFG(ep, getEPCFG(ep)|((usb.ENDPOINT_TYPE_CONTROL+1)<<sam.USB_DEVICE_ENDPOINT_EPCFG_EPTYPE1_Pos))\n\n\t\t// Prepare OUT endpoint for receive\n\t\t// set multi packet size for expected number of receive bytes on control OUT\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.SetBits(64 << usb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Pos)\n\n\t\t// set byte count to zero, we have not received anything yet\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)\n\n\t\t// NAK on endpoint OUT to show we are ready to receive control data\n\t\tsetEPSTATUSSET(ep, sam.USB_DEVICE_ENDPOINT_EPSTATUSSET_BK0RDY)\n\n\t\t// Enable Setup-Received interrupt\n\t\tsetEPINTENSET(0, sam.USB_DEVICE_ENDPOINT_EPINTENSET_RXSTP)\n\t}\n}\n\nfunc handleUSBSetAddress(setup usb.Setup) bool {\n\t// set packet size 64 with auto Zlp after transfer\n\tusbEndpointDescriptors[0].DeviceDescBank[1].PCKSIZE.Set((epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos) |\n\t\tuint32(1<<31)) // autozlp\n\n\t// ack the transfer is complete from the request\n\tsetEPINTFLAG(0, sam.USB_DEVICE_ENDPOINT_EPINTFLAG_TRCPT1)\n\n\t// set bank ready for data\n\tsetEPSTATUSSET(0, sam.USB_DEVICE_ENDPOINT_EPSTATUSSET_BK1RDY)\n\n\t// wait for transfer to complete\n\ttimeout := 3000\n\tfor (getEPINTFLAG(0) & sam.USB_DEVICE_ENDPOINT_EPINTFLAG_TRCPT1) == 0 {\n\t\ttimeout--\n\t\tif timeout == 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\t// last, set the device address to that requested by host\n\tsam.USB_DEVICE.DADD.SetBits(setup.WValueL)\n\tsam.USB_DEVICE.DADD.SetBits(sam.USB_DEVICE_DADD_ADDEN)\n\n\treturn true\n}\n\n// SendUSBInPacket sends a packet for USB (interrupt in / bulk in).\nfunc SendUSBInPacket(ep uint32, data []byte) bool {\n\tsendUSBPacket(ep, data, 0)\n\n\t// clear transfer complete flag\n\tsetEPINTFLAG(ep, sam.USB_DEVICE_ENDPOINT_EPINTFLAG_TRCPT1)\n\n\t// send data by setting bank ready\n\tsetEPSTATUSSET(ep, sam.USB_DEVICE_ENDPOINT_EPSTATUSSET_BK1RDY)\n\n\treturn true\n}\n\n// Prevent file size increases: https://github.com/tinygo-org/tinygo/pull/998\n//\n//go:noinline\nfunc sendUSBPacket(ep uint32, data []byte, maxsize uint16) {\n\tl := uint16(len(data))\n\tif 0 < maxsize && maxsize < l {\n\t\tl = maxsize\n\t}\n\n\t// Set endpoint address for sending data\n\tif ep == 0 {\n\t\tcopy(udd_ep_control_cache_buffer[:], data[:l])\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[1].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_control_cache_buffer))))\n\t} else {\n\t\tcopy(udd_ep_in_cache_buffer[ep][:], data[:l])\n\t\tusbEndpointDescriptors[ep].DeviceDescBank[1].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_in_cache_buffer[ep]))))\n\t}\n\n\t// clear multi-packet size which is total bytes already sent\n\tusbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Mask << usb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Pos)\n\n\t// set byte count, which is total number of bytes to be sent\n\tusbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)\n\tusbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.SetBits((uint32(l) & usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask) << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)\n}\n\nfunc ReceiveUSBControlPacket() ([cdcLineInfoSize]byte, error) {\n\tvar b [cdcLineInfoSize]byte\n\n\t// Wait until OUT transfer is ready.\n\ttimeout := 300000\n\tfor (getEPSTATUS(0) & sam.USB_DEVICE_ENDPOINT_EPSTATUS_BK0RDY) == 0 {\n\t\ttimeout--\n\t\tif timeout == 0 {\n\t\t\treturn b, ErrUSBReadTimeout\n\t\t}\n\t}\n\n\t// Wait until OUT transfer is completed.\n\ttimeout = 300000\n\tfor (getEPINTFLAG(0) & sam.USB_DEVICE_ENDPOINT_EPINTFLAG_TRCPT0) == 0 {\n\t\ttimeout--\n\t\tif timeout == 0 {\n\t\t\treturn b, ErrUSBReadTimeout\n\t\t}\n\t}\n\n\t// get data\n\tbytesread := uint32((usbEndpointDescriptors[0].DeviceDescBank[0].PCKSIZE.Get() >>\n\t\tusb_DEVICE_PCKSIZE_BYTE_COUNT_Pos) & usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask)\n\n\tif bytesread != cdcLineInfoSize {\n\t\treturn b, ErrUSBBytesRead\n\t}\n\n\tcopy(b[:7], udd_ep_out_cache_buffer[0][:7])\n\n\treturn b, nil\n}\n\nfunc handleEndpointRx(ep uint32) []byte {\n\t// get data\n\tcount := int((usbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.Get() >>\n\t\tusb_DEVICE_PCKSIZE_BYTE_COUNT_Pos) & usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask)\n\n\treturn udd_ep_out_cache_buffer[ep][:count]\n}\n\n// AckUsbOutTransfer is called to acknowledge the completion of a USB OUT transfer.\nfunc AckUsbOutTransfer(ep uint32) {\n\t// set byte count to zero\n\tusbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)\n\n\t// set multi packet size to 64\n\tusbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.SetBits(64 << usb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Pos)\n\n\t// set ready for next data\n\tsetEPSTATUSCLR(ep, sam.USB_DEVICE_ENDPOINT_EPSTATUSCLR_BK0RDY)\n}\n\nfunc SendZlp() {\n\tusbEndpointDescriptors[0].DeviceDescBank[1].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)\n}\n\nfunc epPacketSize(size uint16) uint32 {\n\tswitch size {\n\tcase 8:\n\t\treturn 0\n\tcase 16:\n\t\treturn 1\n\tcase 32:\n\t\treturn 2\n\tcase 64:\n\t\treturn 3\n\tcase 128:\n\t\treturn 4\n\tcase 256:\n\t\treturn 5\n\tcase 512:\n\t\treturn 6\n\tcase 1023:\n\t\treturn 7\n\tdefault:\n\t\treturn 0\n\t}\n}\n\nfunc getEPCFG(ep uint32) uint8 {\n\treturn sam.USB_DEVICE.DEVICE_ENDPOINT[ep].EPCFG.Get()\n}\n\nfunc setEPCFG(ep uint32, val uint8) {\n\tsam.USB_DEVICE.DEVICE_ENDPOINT[ep].EPCFG.Set(val)\n}\n\nfunc setEPSTATUSCLR(ep uint32, val uint8) {\n\tsam.USB_DEVICE.DEVICE_ENDPOINT[ep].EPSTATUSCLR.Set(val)\n}\n\nfunc setEPSTATUSSET(ep uint32, val uint8) {\n\tsam.USB_DEVICE.DEVICE_ENDPOINT[ep].EPSTATUSSET.Set(val)\n}\n\nfunc getEPSTATUS(ep uint32) uint8 {\n\treturn sam.USB_DEVICE.DEVICE_ENDPOINT[ep].EPSTATUS.Get()\n}\n\nfunc getEPINTFLAG(ep uint32) uint8 {\n\treturn sam.USB_DEVICE.DEVICE_ENDPOINT[ep].EPINTFLAG.Get()\n}\n\nfunc setEPINTFLAG(ep uint32, val uint8) {\n\tsam.USB_DEVICE.DEVICE_ENDPOINT[ep].EPINTFLAG.Set(val)\n}\n\nfunc setEPINTENCLR(ep uint32, val uint8) {\n\tsam.USB_DEVICE.DEVICE_ENDPOINT[ep].EPINTENCLR.Set(val)\n}\n\nfunc setEPINTENSET(ep uint32, val uint8) {\n\tsam.USB_DEVICE.DEVICE_ENDPOINT[ep].EPINTENSET.Set(val)\n}\n"
  },
  {
    "path": "src/machine/machine_atsamd51g19.go",
    "content": "//go:build sam && atsamd51 && atsamd51g19\n\n// Peripheral abstraction layer for the atsamd51.\n//\n// Datasheet:\n// http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf\npackage machine\n\nimport \"device/sam\"\n\nconst HSRAM_SIZE = 0x00030000\n\nvar (\n\tsercomI2CM0 = &I2C{Bus: sam.SERCOM0_I2CM, SERCOM: 0}\n\tsercomI2CM1 = &I2C{Bus: sam.SERCOM1_I2CM, SERCOM: 1}\n\tsercomI2CM2 = &I2C{Bus: sam.SERCOM2_I2CM, SERCOM: 2}\n\tsercomI2CM3 = &I2C{Bus: sam.SERCOM3_I2CM, SERCOM: 3}\n\tsercomI2CM4 = &I2C{Bus: sam.SERCOM4_I2CM, SERCOM: 4}\n\tsercomI2CM5 = &I2C{Bus: sam.SERCOM5_I2CM, SERCOM: 5}\n\n\tsercomSPIM0 = &SPI{Bus: sam.SERCOM0_SPIM, SERCOM: 0}\n\tsercomSPIM1 = &SPI{Bus: sam.SERCOM1_SPIM, SERCOM: 1}\n\tsercomSPIM2 = &SPI{Bus: sam.SERCOM2_SPIM, SERCOM: 2}\n\tsercomSPIM3 = &SPI{Bus: sam.SERCOM3_SPIM, SERCOM: 3}\n\tsercomSPIM4 = &SPI{Bus: sam.SERCOM4_SPIM, SERCOM: 4}\n\tsercomSPIM5 = &SPI{Bus: sam.SERCOM5_SPIM, SERCOM: 5}\n)\n\n// setSERCOMClockGenerator sets the GCLK for sercom\nfunc setSERCOMClockGenerator(sercom uint8, gclk uint32) {\n\tswitch sercom {\n\tcase 0:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM0_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM0_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM0_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 1:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM1_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM1_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM1_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 2:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM2_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM2_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM2_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 3:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM3_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM3_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM3_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 4:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM4_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM4_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM4_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 5:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM5_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM5_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM5_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\t}\n}\n\n// This chip has three TCC peripherals, which have PWM as one feature.\nvar (\n\tTCC0 = (*TCC)(sam.TCC0)\n\tTCC1 = (*TCC)(sam.TCC1)\n\tTCC2 = (*TCC)(sam.TCC2)\n)\n\nfunc (tcc *TCC) configureClock() {\n\t// Turn on timer clocks used for TCC and use generic clock generator 0.\n\tswitch tcc.timer() {\n\tcase sam.TCC0:\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_TCC0_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC0].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\tcase sam.TCC1:\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_TCC1_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC1].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\tcase sam.TCC2:\n\t\tsam.MCLK.APBCMASK.SetBits(sam.MCLK_APBCMASK_TCC2_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC2].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\t}\n}\n\nfunc (tcc *TCC) timerNum() uint8 {\n\tswitch tcc.timer() {\n\tcase sam.TCC0:\n\t\treturn 0\n\tcase sam.TCC1:\n\t\treturn 1\n\tcase sam.TCC2:\n\t\treturn 2\n\tdefault:\n\t\treturn 0x0f // should not happen\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_atsamd51j19.go",
    "content": "//go:build sam && atsamd51 && atsamd51j19\n\n// Peripheral abstraction layer for the atsamd51.\n//\n// Datasheet:\n// http://ww1.microchip.com/downloads/en/DeviceDoc/SAM_D5xE5x_Family_Data_Sheet_DS60001507F.pdf\npackage machine\n\nimport \"device/sam\"\n\nconst HSRAM_SIZE = 0x00030000\n\nvar (\n\tsercomI2CM0 = &I2C{Bus: sam.SERCOM0_I2CM, SERCOM: 0}\n\tsercomI2CM1 = &I2C{Bus: sam.SERCOM1_I2CM, SERCOM: 1}\n\tsercomI2CM2 = &I2C{Bus: sam.SERCOM2_I2CM, SERCOM: 2}\n\tsercomI2CM3 = &I2C{Bus: sam.SERCOM3_I2CM, SERCOM: 3}\n\tsercomI2CM4 = &I2C{Bus: sam.SERCOM4_I2CM, SERCOM: 4}\n\tsercomI2CM5 = &I2C{Bus: sam.SERCOM5_I2CM, SERCOM: 5}\n\n\tsercomSPIM0 = &SPI{Bus: sam.SERCOM0_SPIM, SERCOM: 0}\n\tsercomSPIM1 = &SPI{Bus: sam.SERCOM1_SPIM, SERCOM: 1}\n\tsercomSPIM2 = &SPI{Bus: sam.SERCOM2_SPIM, SERCOM: 2}\n\tsercomSPIM3 = &SPI{Bus: sam.SERCOM3_SPIM, SERCOM: 3}\n\tsercomSPIM4 = &SPI{Bus: sam.SERCOM4_SPIM, SERCOM: 4}\n\tsercomSPIM5 = &SPI{Bus: sam.SERCOM5_SPIM, SERCOM: 5}\n)\n\n// setSERCOMClockGenerator sets the GCLK for sercom\nfunc setSERCOMClockGenerator(sercom uint8, gclk uint32) {\n\tswitch sercom {\n\tcase 0:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM0_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM0_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM0_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 1:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM1_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM1_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM1_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 2:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM2_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM2_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM2_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 3:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM3_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM3_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM3_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 4:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM4_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM4_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM4_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 5:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM5_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM5_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM5_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\t}\n}\n\n// This chip has five TCC peripherals, which have PWM as one feature.\nvar (\n\tTCC0 = (*TCC)(sam.TCC0)\n\tTCC1 = (*TCC)(sam.TCC1)\n\tTCC2 = (*TCC)(sam.TCC2)\n\tTCC3 = (*TCC)(sam.TCC3)\n\tTCC4 = (*TCC)(sam.TCC4)\n)\n\nfunc (tcc *TCC) configureClock() {\n\t// Turn on timer clocks used for the TCC and use generic clock generator 0.\n\tswitch tcc.timer() {\n\tcase sam.TCC0:\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_TCC0_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC0].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\tcase sam.TCC1:\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_TCC1_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC1].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\tcase sam.TCC2:\n\t\tsam.MCLK.APBCMASK.SetBits(sam.MCLK_APBCMASK_TCC2_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC2].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\tcase sam.TCC3:\n\t\tsam.MCLK.APBCMASK.SetBits(sam.MCLK_APBCMASK_TCC3_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC3].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\tcase sam.TCC4:\n\t\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_TCC4_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC4].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\t}\n}\n\nfunc (tcc *TCC) timerNum() uint8 {\n\tswitch tcc.timer() {\n\tcase sam.TCC0:\n\t\treturn 0\n\tcase sam.TCC1:\n\t\treturn 1\n\tcase sam.TCC2:\n\t\treturn 2\n\tcase sam.TCC3:\n\t\treturn 3\n\tcase sam.TCC4:\n\t\treturn 4\n\tdefault:\n\t\treturn 0x0f // should not happen\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_atsamd51j20.go",
    "content": "//go:build sam && atsamd51 && atsamd51j20\n\n// Peripheral abstraction layer for the atsamd51.\n//\n// Datasheet:\n// http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf\npackage machine\n\nimport \"device/sam\"\n\nconst HSRAM_SIZE = 0x00040000\n\nvar (\n\tsercomI2CM0 = &I2C{Bus: sam.SERCOM0_I2CM, SERCOM: 0}\n\tsercomI2CM1 = &I2C{Bus: sam.SERCOM1_I2CM, SERCOM: 1}\n\tsercomI2CM2 = &I2C{Bus: sam.SERCOM2_I2CM, SERCOM: 2}\n\tsercomI2CM3 = &I2C{Bus: sam.SERCOM3_I2CM, SERCOM: 3}\n\tsercomI2CM4 = &I2C{Bus: sam.SERCOM4_I2CM, SERCOM: 4}\n\tsercomI2CM5 = &I2C{Bus: sam.SERCOM5_I2CM, SERCOM: 5}\n\n\tsercomSPIM0 = &SPI{Bus: sam.SERCOM0_SPIM, SERCOM: 0}\n\tsercomSPIM1 = &SPI{Bus: sam.SERCOM1_SPIM, SERCOM: 1}\n\tsercomSPIM2 = &SPI{Bus: sam.SERCOM2_SPIM, SERCOM: 2}\n\tsercomSPIM3 = &SPI{Bus: sam.SERCOM3_SPIM, SERCOM: 3}\n\tsercomSPIM4 = &SPI{Bus: sam.SERCOM4_SPIM, SERCOM: 4}\n\tsercomSPIM5 = &SPI{Bus: sam.SERCOM5_SPIM, SERCOM: 5}\n)\n\n// setSERCOMClockGenerator sets the GCLK for sercom\nfunc setSERCOMClockGenerator(sercom uint8, gclk uint32) {\n\tswitch sercom {\n\tcase 0:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM0_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM0_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM0_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 1:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM1_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM1_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM1_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 2:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM2_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM2_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM2_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 3:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM3_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM3_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM3_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 4:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM4_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM4_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM4_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 5:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM5_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM5_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM5_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\t}\n}\n\n// This chip has five TCC peripherals, which have PWM as one feature.\nvar (\n\tTCC0 = (*TCC)(sam.TCC0)\n\tTCC1 = (*TCC)(sam.TCC1)\n\tTCC2 = (*TCC)(sam.TCC2)\n\tTCC3 = (*TCC)(sam.TCC3)\n\tTCC4 = (*TCC)(sam.TCC4)\n)\n\nfunc (tcc *TCC) configureClock() {\n\t// Turn on timer clocks used for TCC and use generic clock generator 0.\n\tswitch tcc.timer() {\n\tcase sam.TCC0:\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_TCC0_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC0].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\tcase sam.TCC1:\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_TCC1_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC1].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\tcase sam.TCC2:\n\t\tsam.MCLK.APBCMASK.SetBits(sam.MCLK_APBCMASK_TCC2_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC2].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\tcase sam.TCC3:\n\t\tsam.MCLK.APBCMASK.SetBits(sam.MCLK_APBCMASK_TCC3_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC3].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\tcase sam.TCC4:\n\t\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_TCC4_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC4].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\t}\n}\n\nfunc (tcc *TCC) timerNum() uint8 {\n\tswitch tcc.timer() {\n\tcase sam.TCC0:\n\t\treturn 0\n\tcase sam.TCC1:\n\t\treturn 1\n\tcase sam.TCC2:\n\t\treturn 2\n\tcase sam.TCC3:\n\t\treturn 3\n\tcase sam.TCC4:\n\t\treturn 4\n\tdefault:\n\t\treturn 0x0f // should not happen\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_atsamd51p19.go",
    "content": "//go:build sam && atsamd51 && atsamd51p19\n\n// Peripheral abstraction layer for the atsamd51.\n//\n// Datasheet:\n// http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf\npackage machine\n\nimport \"device/sam\"\n\nconst HSRAM_SIZE = 0x00030000\n\nvar (\n\tsercomI2CM0 = &I2C{Bus: sam.SERCOM0_I2CM, SERCOM: 0}\n\tsercomI2CM1 = &I2C{Bus: sam.SERCOM1_I2CM, SERCOM: 1}\n\tsercomI2CM2 = &I2C{Bus: sam.SERCOM2_I2CM, SERCOM: 2}\n\tsercomI2CM3 = &I2C{Bus: sam.SERCOM3_I2CM, SERCOM: 3}\n\tsercomI2CM4 = &I2C{Bus: sam.SERCOM4_I2CM, SERCOM: 4}\n\tsercomI2CM5 = &I2C{Bus: sam.SERCOM5_I2CM, SERCOM: 5}\n\tsercomI2CM6 = &I2C{Bus: sam.SERCOM6_I2CM, SERCOM: 6}\n\tsercomI2CM7 = &I2C{Bus: sam.SERCOM7_I2CM, SERCOM: 7}\n\n\tsercomSPIM0 = &SPI{Bus: sam.SERCOM0_SPIM, SERCOM: 0}\n\tsercomSPIM1 = &SPI{Bus: sam.SERCOM1_SPIM, SERCOM: 1}\n\tsercomSPIM2 = &SPI{Bus: sam.SERCOM2_SPIM, SERCOM: 2}\n\tsercomSPIM3 = &SPI{Bus: sam.SERCOM3_SPIM, SERCOM: 3}\n\tsercomSPIM4 = &SPI{Bus: sam.SERCOM4_SPIM, SERCOM: 4}\n\tsercomSPIM5 = &SPI{Bus: sam.SERCOM5_SPIM, SERCOM: 5}\n\tsercomSPIM6 = &SPI{Bus: sam.SERCOM6_SPIM, SERCOM: 6}\n\tsercomSPIM7 = &SPI{Bus: sam.SERCOM7_SPIM, SERCOM: 7}\n)\n\n// setSERCOMClockGenerator sets the GCLK for sercom\nfunc setSERCOMClockGenerator(sercom uint8, gclk uint32) {\n\tswitch sercom {\n\tcase 0:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM0_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM0_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM0_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 1:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM1_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM1_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM1_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 2:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM2_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM2_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM2_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 3:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM3_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM3_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM3_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 4:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM4_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM4_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM4_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 5:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM5_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM5_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM5_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 6:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM6_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM6_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM6_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 7:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM7_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM7_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM7_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\t}\n}\n\n// This chip has five TCC peripherals, which have PWM as one feature.\nvar (\n\tTCC0 = (*TCC)(sam.TCC0)\n\tTCC1 = (*TCC)(sam.TCC1)\n\tTCC2 = (*TCC)(sam.TCC2)\n\tTCC3 = (*TCC)(sam.TCC3)\n\tTCC4 = (*TCC)(sam.TCC4)\n)\n\nfunc (tcc *TCC) configureClock() {\n\t// Turn on timer clocks used for TCC and use generic clock generator 0.\n\tswitch tcc.timer() {\n\tcase sam.TCC0:\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_TCC0_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC0].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\tcase sam.TCC1:\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_TCC1_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC1].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\tcase sam.TCC2:\n\t\tsam.MCLK.APBCMASK.SetBits(sam.MCLK_APBCMASK_TCC2_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC2].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\tcase sam.TCC3:\n\t\tsam.MCLK.APBCMASK.SetBits(sam.MCLK_APBCMASK_TCC3_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC3].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\tcase sam.TCC4:\n\t\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_TCC4_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC4].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\t}\n}\n\nfunc (tcc *TCC) timerNum() uint8 {\n\tswitch tcc.timer() {\n\tcase sam.TCC0:\n\t\treturn 0\n\tcase sam.TCC1:\n\t\treturn 1\n\tcase sam.TCC2:\n\t\treturn 2\n\tcase sam.TCC3:\n\t\treturn 3\n\tcase sam.TCC4:\n\t\treturn 4\n\tdefault:\n\t\treturn 0x0f // should not happen\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_atsamd51p20.go",
    "content": "//go:build sam && atsamd51 && atsamd51p20\n\n// Peripheral abstraction layer for the atsamd51.\n//\n// Datasheet:\n// http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf\npackage machine\n\nimport \"device/sam\"\n\nconst HSRAM_SIZE = 0x00040000\n\nvar (\n\tsercomI2CM0 = &I2C{Bus: sam.SERCOM0_I2CM, SERCOM: 0}\n\tsercomI2CM1 = &I2C{Bus: sam.SERCOM1_I2CM, SERCOM: 1}\n\tsercomI2CM2 = &I2C{Bus: sam.SERCOM2_I2CM, SERCOM: 2}\n\tsercomI2CM3 = &I2C{Bus: sam.SERCOM3_I2CM, SERCOM: 3}\n\tsercomI2CM4 = &I2C{Bus: sam.SERCOM4_I2CM, SERCOM: 4}\n\tsercomI2CM5 = &I2C{Bus: sam.SERCOM5_I2CM, SERCOM: 5}\n\tsercomI2CM6 = &I2C{Bus: sam.SERCOM6_I2CM, SERCOM: 6}\n\tsercomI2CM7 = &I2C{Bus: sam.SERCOM7_I2CM, SERCOM: 7}\n\n\tsercomSPIM0 = &SPI{Bus: sam.SERCOM0_SPIM, SERCOM: 0}\n\tsercomSPIM1 = &SPI{Bus: sam.SERCOM1_SPIM, SERCOM: 1}\n\tsercomSPIM2 = &SPI{Bus: sam.SERCOM2_SPIM, SERCOM: 2}\n\tsercomSPIM3 = &SPI{Bus: sam.SERCOM3_SPIM, SERCOM: 3}\n\tsercomSPIM4 = &SPI{Bus: sam.SERCOM4_SPIM, SERCOM: 4}\n\tsercomSPIM5 = &SPI{Bus: sam.SERCOM5_SPIM, SERCOM: 5}\n\tsercomSPIM6 = &SPI{Bus: sam.SERCOM6_SPIM, SERCOM: 6}\n\tsercomSPIM7 = &SPI{Bus: sam.SERCOM7_SPIM, SERCOM: 7}\n)\n\n// setSERCOMClockGenerator sets the GCLK for sercom\nfunc setSERCOMClockGenerator(sercom uint8, gclk uint32) {\n\tswitch sercom {\n\tcase 0:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM0_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM0_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM0_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 1:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM1_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM1_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM1_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 2:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM2_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM2_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM2_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 3:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM3_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM3_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM3_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 4:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM4_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM4_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM4_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 5:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM5_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM5_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM5_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 6:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM6_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM6_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM6_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 7:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM7_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM7_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM7_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\t}\n}\n\n// This chip has five TCC peripherals, which have PWM as one feature.\nvar (\n\tTCC0 = (*TCC)(sam.TCC0)\n\tTCC1 = (*TCC)(sam.TCC1)\n\tTCC2 = (*TCC)(sam.TCC2)\n\tTCC3 = (*TCC)(sam.TCC3)\n\tTCC4 = (*TCC)(sam.TCC4)\n)\n\nfunc (tcc *TCC) configureClock() {\n\t// Turn on timer clocks used for TCC and use generic clock generator 0.\n\tswitch tcc.timer() {\n\tcase sam.TCC0:\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_TCC0_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC0].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\tcase sam.TCC1:\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_TCC1_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC1].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\tcase sam.TCC2:\n\t\tsam.MCLK.APBCMASK.SetBits(sam.MCLK_APBCMASK_TCC2_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC2].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\tcase sam.TCC3:\n\t\tsam.MCLK.APBCMASK.SetBits(sam.MCLK_APBCMASK_TCC3_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC3].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\tcase sam.TCC4:\n\t\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_TCC4_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC4].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\t}\n}\n\nfunc (tcc *TCC) timerNum() uint8 {\n\tswitch tcc.timer() {\n\tcase sam.TCC0:\n\t\treturn 0\n\tcase sam.TCC1:\n\t\treturn 1\n\tcase sam.TCC2:\n\t\treturn 2\n\tcase sam.TCC3:\n\t\treturn 3\n\tcase sam.TCC4:\n\t\treturn 4\n\tdefault:\n\t\treturn 0x0f // should not happen\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_atsame51j19.go",
    "content": "//go:build sam && atsame51 && atsame51j19\n\n// Peripheral abstraction layer for the atsame51.\n//\n// Datasheet:\n// http://ww1.microchip.com/downloads/en/DeviceDoc/SAM_D5xE5x_Family_Data_Sheet_DS60001507F.pdf\npackage machine\n\nimport \"device/sam\"\n\nconst HSRAM_SIZE = 0x00030000\n\nvar (\n\tsercomI2CM0 = &I2C{Bus: sam.SERCOM0_I2CM, SERCOM: 0}\n\tsercomI2CM1 = &I2C{Bus: sam.SERCOM1_I2CM, SERCOM: 1}\n\tsercomI2CM2 = &I2C{Bus: sam.SERCOM2_I2CM, SERCOM: 2}\n\tsercomI2CM3 = &I2C{Bus: sam.SERCOM3_I2CM, SERCOM: 3}\n\tsercomI2CM4 = &I2C{Bus: sam.SERCOM4_I2CM, SERCOM: 4}\n\tsercomI2CM5 = &I2C{Bus: sam.SERCOM5_I2CM, SERCOM: 5}\n\n\tsercomSPIM0 = &SPI{Bus: sam.SERCOM0_SPIM, SERCOM: 0}\n\tsercomSPIM1 = &SPI{Bus: sam.SERCOM1_SPIM, SERCOM: 1}\n\tsercomSPIM2 = &SPI{Bus: sam.SERCOM2_SPIM, SERCOM: 2}\n\tsercomSPIM3 = &SPI{Bus: sam.SERCOM3_SPIM, SERCOM: 3}\n\tsercomSPIM4 = &SPI{Bus: sam.SERCOM4_SPIM, SERCOM: 4}\n\tsercomSPIM5 = &SPI{Bus: sam.SERCOM5_SPIM, SERCOM: 5}\n)\n\n// setSERCOMClockGenerator sets the GCLK for sercom\nfunc setSERCOMClockGenerator(sercom uint8, gclk uint32) {\n\tswitch sercom {\n\tcase 0:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM0_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM0_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM0_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 1:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM1_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM1_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM1_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 2:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM2_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM2_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM2_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 3:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM3_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM3_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM3_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 4:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM4_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM4_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM4_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 5:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM5_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM5_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM5_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\t}\n}\n\n// This chip has five TCC peripherals, which have PWM as one feature.\nvar (\n\tTCC0 = (*TCC)(sam.TCC0)\n\tTCC1 = (*TCC)(sam.TCC1)\n\tTCC2 = (*TCC)(sam.TCC2)\n\tTCC3 = (*TCC)(sam.TCC3)\n\tTCC4 = (*TCC)(sam.TCC4)\n)\n\nfunc (tcc *TCC) configureClock() {\n\t// Turn on timer clocks used for the TCC and use generic clock generator 0.\n\tswitch tcc.timer() {\n\tcase sam.TCC0:\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_TCC0_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC0].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\tcase sam.TCC1:\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_TCC1_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC1].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\tcase sam.TCC2:\n\t\tsam.MCLK.APBCMASK.SetBits(sam.MCLK_APBCMASK_TCC2_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC2].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\tcase sam.TCC3:\n\t\tsam.MCLK.APBCMASK.SetBits(sam.MCLK_APBCMASK_TCC3_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC3].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\tcase sam.TCC4:\n\t\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_TCC4_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC4].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\t}\n}\n\nfunc (tcc *TCC) timerNum() uint8 {\n\tswitch tcc.timer() {\n\tcase sam.TCC0:\n\t\treturn 0\n\tcase sam.TCC1:\n\t\treturn 1\n\tcase sam.TCC2:\n\t\treturn 2\n\tcase sam.TCC3:\n\t\treturn 3\n\tcase sam.TCC4:\n\t\treturn 4\n\tdefault:\n\t\treturn 0x0f // should not happen\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_atsame54p20.go",
    "content": "//go:build sam && atsame5x && atsame54p20\n\n// Peripheral abstraction layer for the atsame54.\n//\n// Datasheet:\n// http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf\npackage machine\n\nimport \"device/sam\"\n\nconst HSRAM_SIZE = 0x00040000\n\nvar (\n\tsercomI2CM0 = &I2C{Bus: sam.SERCOM0_I2CM, SERCOM: 0}\n\tsercomI2CM1 = &I2C{Bus: sam.SERCOM1_I2CM, SERCOM: 1}\n\tsercomI2CM2 = &I2C{Bus: sam.SERCOM2_I2CM, SERCOM: 2}\n\tsercomI2CM3 = &I2C{Bus: sam.SERCOM3_I2CM, SERCOM: 3}\n\tsercomI2CM4 = &I2C{Bus: sam.SERCOM4_I2CM, SERCOM: 4}\n\tsercomI2CM5 = &I2C{Bus: sam.SERCOM5_I2CM, SERCOM: 5}\n\tsercomI2CM6 = &I2C{Bus: sam.SERCOM6_I2CM, SERCOM: 6}\n\tsercomI2CM7 = &I2C{Bus: sam.SERCOM7_I2CM, SERCOM: 7}\n\n\tsercomSPIM0 = &SPI{Bus: sam.SERCOM0_SPIM, SERCOM: 0}\n\tsercomSPIM1 = &SPI{Bus: sam.SERCOM1_SPIM, SERCOM: 1}\n\tsercomSPIM2 = &SPI{Bus: sam.SERCOM2_SPIM, SERCOM: 2}\n\tsercomSPIM3 = &SPI{Bus: sam.SERCOM3_SPIM, SERCOM: 3}\n\tsercomSPIM4 = &SPI{Bus: sam.SERCOM4_SPIM, SERCOM: 4}\n\tsercomSPIM5 = &SPI{Bus: sam.SERCOM5_SPIM, SERCOM: 5}\n\tsercomSPIM6 = &SPI{Bus: sam.SERCOM6_SPIM, SERCOM: 6}\n\tsercomSPIM7 = &SPI{Bus: sam.SERCOM7_SPIM, SERCOM: 7}\n)\n\n// setSERCOMClockGenerator sets the GCLK for sercom\nfunc setSERCOMClockGenerator(sercom uint8, gclk uint32) {\n\tswitch sercom {\n\tcase 0:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM0_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM0_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM0_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 1:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM1_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM1_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM1_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 2:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM2_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM2_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM2_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 3:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM3_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM3_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM3_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 4:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM4_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM4_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM4_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 5:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM5_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM5_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM5_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 6:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM6_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM6_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM6_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\tcase 7:\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM7_CORE].ClearBits(sam.GCLK_PCHCTRL_CHEN)\n\t\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM7_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM7_CORE].Set((gclk << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\t\tsam.GCLK_PCHCTRL_CHEN)\n\t}\n}\n\n// This chip has five TCC peripherals, which have PWM as one feature.\nvar (\n\tTCC0 = (*TCC)(sam.TCC0)\n\tTCC1 = (*TCC)(sam.TCC1)\n\tTCC2 = (*TCC)(sam.TCC2)\n\tTCC3 = (*TCC)(sam.TCC3)\n\tTCC4 = (*TCC)(sam.TCC4)\n)\n\nfunc (tcc *TCC) configureClock() {\n\t// Turn on timer clocks used for TCC and use generic clock generator 0.\n\tswitch tcc.timer() {\n\tcase sam.TCC0:\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_TCC0_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC0].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\tcase sam.TCC1:\n\t\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_TCC1_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC1].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\tcase sam.TCC2:\n\t\tsam.MCLK.APBCMASK.SetBits(sam.MCLK_APBCMASK_TCC2_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC2].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\tcase sam.TCC3:\n\t\tsam.MCLK.APBCMASK.SetBits(sam.MCLK_APBCMASK_TCC3_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC3].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\tcase sam.TCC4:\n\t\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_TCC4_)\n\t\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC4].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)\n\t}\n}\n\nfunc (tcc *TCC) timerNum() uint8 {\n\tswitch tcc.timer() {\n\tcase sam.TCC0:\n\t\treturn 0\n\tcase sam.TCC1:\n\t\treturn 1\n\tcase sam.TCC2:\n\t\treturn 2\n\tcase sam.TCC3:\n\t\treturn 3\n\tcase sam.TCC4:\n\t\treturn 4\n\tdefault:\n\t\treturn 0x0f // should not happen\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_atsame5x_can.go",
    "content": "//go:build (sam && atsame51) || (sam && atsame54)\n\npackage machine\n\nimport (\n\t\"device/sam\"\n\t\"errors\"\n\t\"runtime/interrupt\"\n\t\"unsafe\"\n)\n\nconst (\n\tCANRxFifoSize = 16\n\tCANTxFifoSize = 16\n\tCANEvFifoSize = 16\n)\n\n// Message RAM can only be located in the first 64 KB area of the system RAM.\n// TODO: when the go:section pragma is merged, add the section configuration\n\n//go:align 4\nvar CANRxFifo [2][(8 + 64) * CANRxFifoSize]byte\n\n//go:align 4\nvar CANTxFifo [2][(8 + 64) * CANTxFifoSize]byte\n\n//go:align 4\nvar CANEvFifo [2][(8) * CANEvFifoSize]byte\n\ntype CAN struct {\n\tBus *sam.CAN_Type\n}\n\ntype CANTransferRate uint32\n\n// CAN transfer rates for CANConfig\nconst (\n\tCANTransferRate125kbps  CANTransferRate = 125000\n\tCANTransferRate250kbps  CANTransferRate = 250000\n\tCANTransferRate500kbps  CANTransferRate = 500000\n\tCANTransferRate1000kbps CANTransferRate = 1000000\n\tCANTransferRate2000kbps CANTransferRate = 2000000\n\tCANTransferRate4000kbps CANTransferRate = 4000000\n)\n\n// CANConfig holds CAN configuration parameters. Tx and Rx need to be\n// specified with some pins. When the Standby Pin is specified, configure it\n// as an output pin and output Low in Configure(). If this operation is not\n// necessary, specify NoPin.\ntype CANConfig struct {\n\tTransferRate   CANTransferRate\n\tTransferRateFD CANTransferRate\n\tTx             Pin\n\tRx             Pin\n\tStandby        Pin\n}\n\nvar (\n\terrCANInvalidTransferRate   = errors.New(\"CAN: invalid TransferRate\")\n\terrCANInvalidTransferRateFD = errors.New(\"CAN: invalid TransferRateFD\")\n)\n\n// Configure this CAN peripheral with the given configuration.\nfunc (can *CAN) Configure(config CANConfig) error {\n\tif config.Standby != NoPin {\n\t\tconfig.Standby.Configure(PinConfig{Mode: PinOutput})\n\t\tconfig.Standby.Low()\n\t}\n\n\tmode := PinCAN0\n\tif can.instance() == 1 {\n\t\tmode = PinCAN1\n\t}\n\n\tconfig.Rx.Configure(PinConfig{Mode: mode})\n\tconfig.Tx.Configure(PinConfig{Mode: mode})\n\n\tcan.Bus.CCCR.SetBits(sam.CAN_CCCR_INIT)\n\tfor !can.Bus.CCCR.HasBits(sam.CAN_CCCR_INIT) {\n\t}\n\n\tcan.Bus.CCCR.SetBits(sam.CAN_CCCR_CCE)\n\n\tcan.Bus.CCCR.SetBits(sam.CAN_CCCR_BRSE | sam.CAN_CCCR_FDOE)\n\tcan.Bus.MRCFG.Set(sam.CAN_MRCFG_QOS_MEDIUM)\n\t// base clock == 48 MHz\n\tif config.TransferRate == 0 {\n\t\tconfig.TransferRate = CANTransferRate500kbps\n\t}\n\tbrp := uint32(6)\n\tswitch config.TransferRate {\n\tcase CANTransferRate125kbps:\n\t\tbrp = 32\n\tcase CANTransferRate250kbps:\n\t\tbrp = 16\n\tcase CANTransferRate500kbps:\n\t\tbrp = 8\n\tcase CANTransferRate1000kbps:\n\t\tbrp = 4\n\tdefault:\n\t\treturn errCANInvalidTransferRate\n\t}\n\tcan.Bus.NBTP.Set(8<<sam.CAN_NBTP_NTSEG1_Pos | (brp-1)<<sam.CAN_NBTP_NBRP_Pos |\n\t\t1<<sam.CAN_NBTP_NTSEG2_Pos | 3<<sam.CAN_NBTP_NSJW_Pos)\n\n\tif config.TransferRateFD == 0 {\n\t\tconfig.TransferRateFD = CANTransferRate1000kbps\n\t}\n\tif config.TransferRateFD < config.TransferRate {\n\t\treturn errCANInvalidTransferRateFD\n\t}\n\tbrp = uint32(2)\n\tswitch config.TransferRateFD {\n\tcase CANTransferRate125kbps:\n\t\tbrp = 32\n\tcase CANTransferRate250kbps:\n\t\tbrp = 16\n\tcase CANTransferRate500kbps:\n\t\tbrp = 8\n\tcase CANTransferRate1000kbps:\n\t\tbrp = 4\n\tcase CANTransferRate2000kbps:\n\t\tbrp = 2\n\tcase CANTransferRate4000kbps:\n\t\tbrp = 1\n\tdefault:\n\t\treturn errCANInvalidTransferRateFD\n\t}\n\tcan.Bus.DBTP.Set((brp-1)<<sam.CAN_DBTP_DBRP_Pos | 8<<sam.CAN_DBTP_DTSEG1_Pos |\n\t\t1<<sam.CAN_DBTP_DTSEG2_Pos | 3<<sam.CAN_DBTP_DSJW_Pos)\n\n\tcan.Bus.RXF0C.Set(sam.CAN_RXF0C_F0OM | CANRxFifoSize<<sam.CAN_RXF0C_F0S_Pos | uint32(uintptr(unsafe.Pointer(&CANRxFifo[can.instance()][0])))&0xFFFF)\n\tcan.Bus.RXESC.Set(sam.CAN_RXESC_F0DS_DATA64)\n\tcan.Bus.TXESC.Set(sam.CAN_TXESC_TBDS_DATA64)\n\tcan.Bus.TXBC.Set(CANTxFifoSize<<sam.CAN_TXBC_TFQS_Pos | 0<<sam.CAN_TXBC_NDTB_Pos | uint32(uintptr(unsafe.Pointer(&CANTxFifo[can.instance()][0])))&0xFFFF)\n\tcan.Bus.TXEFC.Set(CANEvFifoSize<<sam.CAN_TXEFC_EFS_Pos | uint32(uintptr(unsafe.Pointer(&CANEvFifo[can.instance()][0])))&0xFFFF)\n\n\tcan.Bus.TSCC.Set(sam.CAN_TSCC_TSS_INC)\n\n\tcan.Bus.GFC.Set(0<<sam.CAN_GFC_ANFS_Pos | 0<<sam.CAN_GFC_ANFE_Pos)\n\n\tcan.Bus.SIDFC.Set(0 << sam.CAN_SIDFC_LSS_Pos)\n\tcan.Bus.XIDFC.Set(0 << sam.CAN_SIDFC_LSS_Pos)\n\n\tcan.Bus.XIDAM.Set(0x1FFFFFFF << sam.CAN_XIDAM_EIDM_Pos)\n\n\tcan.Bus.ILE.SetBits(sam.CAN_ILE_EINT0)\n\n\tcan.Bus.CCCR.ClearBits(sam.CAN_CCCR_CCE)\n\tcan.Bus.CCCR.ClearBits(sam.CAN_CCCR_INIT)\n\tfor can.Bus.CCCR.HasBits(sam.CAN_CCCR_INIT) {\n\t}\n\n\treturn nil\n}\n\n// Callbacks to be called for CAN.SetInterrupt(). Wre're using the magic\n// constant 2 and 32 here because the SAM E51/E54 has 2 CAN and 32 interrupt\n// sources.\nvar (\n\tcanInstances [2]*CAN\n\tcanCallbacks [2][32]func(*CAN)\n)\n\n// SetInterrupt sets an interrupt to be executed when a particular CAN state.\n//\n// This call will replace a previously set callback. You can pass a nil func\n// to unset the CAN interrupt. If you do so, the change parameter is ignored\n// and can be set to any value (such as 0).\nfunc (can *CAN) SetInterrupt(ie uint32, callback func(*CAN)) error {\n\tif callback == nil {\n\t\t// Disable this CAN interrupt\n\t\tcan.Bus.IE.ClearBits(ie)\n\t\treturn nil\n\t}\n\tcan.Bus.IE.SetBits(ie)\n\n\tidx := 0\n\tswitch can.Bus {\n\tcase sam.CAN0:\n\t\tcanInstances[0] = can\n\tcase sam.CAN1:\n\t\tcanInstances[1] = can\n\t\tidx = 1\n\t}\n\n\tfor i := uint(0); i < 32; i++ {\n\t\tif ie&(1<<i) != 0 {\n\t\t\tcanCallbacks[idx][i] = callback\n\t\t}\n\t}\n\n\tswitch can.Bus {\n\tcase sam.CAN0:\n\t\tinterrupt.New(sam.IRQ_CAN0, func(interrupt.Interrupt) {\n\t\t\tir := sam.CAN0.IR.Get()\n\t\t\tsam.CAN0.IR.Set(ir) // clear interrupt\n\t\t\tfor i := uint(0); i < 32; i++ {\n\t\t\t\tif ir&(1<<i) != 0 && canCallbacks[0][i] != nil {\n\t\t\t\t\tcanCallbacks[0][i](canInstances[0])\n\t\t\t\t}\n\t\t\t}\n\t\t}).Enable()\n\tcase sam.CAN1:\n\t\tinterrupt.New(sam.IRQ_CAN1, func(interrupt.Interrupt) {\n\t\t\tir := sam.CAN1.IR.Get()\n\t\t\tsam.CAN1.IR.Set(ir) // clear interrupt\n\t\t\tfor i := uint(0); i < 32; i++ {\n\t\t\t\tif ir&(1<<i) != 0 && canCallbacks[1][i] != nil {\n\t\t\t\t\tcanCallbacks[1][i](canInstances[1])\n\t\t\t\t}\n\t\t\t}\n\t\t}).Enable()\n\t}\n\n\treturn nil\n}\n\n// TxFifoIsFull returns whether TxFifo is full or not.\nfunc (can *CAN) TxFifoIsFull() bool {\n\treturn (can.Bus.TXFQS.Get() & sam.CAN_TXFQS_TFQF_Msk) == sam.CAN_TXFQS_TFQF_Msk\n}\n\n// TxFifoFreeLevel returns how many messages can still be set in the TxFifo.\nfunc (can *CAN) TxFifoFreeLevel() int {\n\treturn int(can.Bus.GetTXFQS_TFFL())\n}\n\n// TxRaw sends a CAN Frame according to CANTxBufferElement.\nfunc (can *CAN) TxRaw(e *CANTxBufferElement) {\n\tputIndex := (can.Bus.TXFQS.Get() & sam.CAN_TXFQS_TFQPI_Msk) >> sam.CAN_TXFQS_TFQPI_Pos\n\n\tf := CANTxFifo[can.instance()][putIndex*(8+64) : (putIndex+1)*(8+64)]\n\tid := e.ID\n\tif !e.XTD {\n\t\t// standard identifier is stored into ID[28:18]\n\t\tid <<= 18\n\t}\n\n\tf[3] = byte(id>>24) & 0x1F\n\tif e.ESI {\n\t\tf[3] |= 0x80\n\t}\n\tif e.XTD {\n\t\tf[3] |= 0x40\n\t}\n\tif e.RTR {\n\t\tf[3] |= 0x20\n\t}\n\tf[2] = byte(id >> 16)\n\tf[1] = byte(id >> 8)\n\tf[0] = byte(id)\n\tf[7] = e.MM\n\tf[6] = e.DLC\n\tif e.EFC {\n\t\tf[6] |= 0x80\n\t}\n\tif e.FDF {\n\t\tf[6] |= 0x20\n\t}\n\tif e.BRS {\n\t\tf[6] |= 0x10\n\t}\n\tf[5] = 0x00 // reserved\n\tf[4] = 0x00 // reserved\n\n\tlength := CANDlcToLength(e.DLC, e.FDF)\n\tfor i := byte(0); i < length; i++ {\n\t\tf[8+i] = e.DB[i]\n\t}\n\n\tcan.Bus.TXBAR.SetBits(1 << putIndex)\n}\n\n// The Tx transmits CAN frames. It is easier to use than TxRaw, but not as\n// flexible.\nfunc (can *CAN) Tx(id uint32, data []byte, isFD, isExtendedID bool) {\n\tlength := byte(len(data))\n\tdlc := CANLengthToDlc(length, true)\n\n\te := CANTxBufferElement{\n\t\tESI: false,\n\t\tXTD: isExtendedID,\n\t\tRTR: false,\n\t\tID:  id,\n\t\tMM:  0x00,\n\t\tEFC: true,\n\t\tFDF: isFD,\n\t\tBRS: isFD,\n\t\tDLC: dlc,\n\t}\n\n\tif !isFD {\n\t\tif length > 8 {\n\t\t\tlength = 8\n\t\t}\n\t}\n\tfor i := byte(0); i < length; i++ {\n\t\te.DB[i] = data[i]\n\t}\n\n\tcan.TxRaw(&e)\n}\n\n// RxFifoSize returns the number of CAN Frames currently stored in the RXFifo.\nfunc (can *CAN) RxFifoSize() int {\n\tsz := (can.Bus.RXF0S.Get() & sam.CAN_RXF0S_F0FL_Msk) >> sam.CAN_RXF0S_F0FL_Pos\n\treturn int(sz)\n}\n\n// RxFifoIsFull returns whether RxFifo is full or not.\nfunc (can *CAN) RxFifoIsFull() bool {\n\tsz := (can.Bus.RXF0S.Get() & sam.CAN_RXF0S_F0FL_Msk) >> sam.CAN_RXF0S_F0FL_Pos\n\treturn sz == CANRxFifoSize\n}\n\n// RxFifoIsEmpty returns whether RxFifo is empty or not.\nfunc (can *CAN) RxFifoIsEmpty() bool {\n\tsz := (can.Bus.RXF0S.Get() & sam.CAN_RXF0S_F0FL_Msk) >> sam.CAN_RXF0S_F0FL_Pos\n\treturn sz == 0\n}\n\n// RxRaw copies the received CAN frame to CANRxBufferElement.\nfunc (can *CAN) RxRaw(e *CANRxBufferElement) {\n\tidx := (can.Bus.RXF0S.Get() & sam.CAN_RXF0S_F0GI_Msk) >> sam.CAN_RXF0S_F0GI_Pos\n\tf := CANRxFifo[can.instance()][idx*(8+64):]\n\n\te.ESI = false\n\tif (f[3] & 0x80) != 0x00 {\n\t\te.ESI = true\n\t}\n\n\te.XTD = false\n\tif (f[3] & 0x40) != 0x00 {\n\t\te.XTD = true\n\t}\n\n\te.RTR = false\n\tif (f[3] & 0x20) != 0x00 {\n\t\te.RTR = true\n\t}\n\n\tid := ((uint32(f[3]) << 24) + (uint32(f[2]) << 16) + (uint32(f[1]) << 8) + uint32(f[0])) & 0x1FFFFFFF\n\tif !e.XTD {\n\t\tid >>= 18\n\t\tid &= 0x000007FF\n\t}\n\te.ID = id\n\n\te.ANMF = false\n\tif (f[7] & 0x80) != 0x00 {\n\t\te.ANMF = true\n\t}\n\n\te.FIDX = f[7] & 0x7F\n\n\te.FDF = false\n\tif (f[6] & 0x20) != 0x00 {\n\t\te.FDF = true\n\t}\n\n\te.BRS = false\n\tif (f[6] & 0x10) != 0x00 {\n\t\te.BRS = true\n\t}\n\n\te.DLC = f[6] & 0x0F\n\n\te.RXTS = (uint16(f[5]) << 8) + uint16(f[4])\n\n\tfor i := byte(0); i < CANDlcToLength(e.DLC, e.FDF); i++ {\n\t\te.DB[i] = f[i+8]\n\t}\n\n\tcan.Bus.RXF0A.ReplaceBits(idx, sam.CAN_RXF0A_F0AI_Msk, sam.CAN_RXF0A_F0AI_Pos)\n}\n\n// Rx receives a CAN frame. It is easier to use than RxRaw, but not as\n// flexible.\nfunc (can *CAN) Rx() (id uint32, dlc byte, data []byte, isFd, isExtendedID bool) {\n\te := CANRxBufferElement{}\n\tcan.RxRaw(&e)\n\tlength := CANDlcToLength(e.DLC, e.FDF)\n\treturn e.ID, length, e.DB[:length], e.FDF, e.XTD\n}\n\nfunc (can *CAN) instance() byte {\n\tif can.Bus == sam.CAN0 {\n\t\treturn 0\n\t} else {\n\t\treturn 1\n\t}\n}\n\n// CANTxBufferElement is a struct that corresponds to the same5x' Tx Buffer\n// Element.\ntype CANTxBufferElement struct {\n\tESI bool\n\tXTD bool\n\tRTR bool\n\tID  uint32\n\tMM  uint8\n\tEFC bool\n\tFDF bool\n\tBRS bool\n\tDLC uint8\n\tDB  [64]uint8\n}\n\n// CANRxBufferElement is a struct that corresponds to the same5x Rx Buffer and\n// FIFO Element.\ntype CANRxBufferElement struct {\n\tESI  bool\n\tXTD  bool\n\tRTR  bool\n\tID   uint32\n\tANMF bool\n\tFIDX uint8\n\tFDF  bool\n\tBRS  bool\n\tDLC  uint8\n\tRXTS uint16\n\tDB   [64]uint8\n}\n\n// Data returns the received data as a slice of the size according to dlc.\nfunc (e CANRxBufferElement) Data() []byte {\n\treturn e.DB[:CANDlcToLength(e.DLC, e.FDF)]\n}\n\n// Length returns its actual length.\nfunc (e CANRxBufferElement) Length() byte {\n\treturn CANDlcToLength(e.DLC, e.FDF)\n}\n\n// CANDlcToLength() converts a DLC value to its actual length.\nfunc CANDlcToLength(dlc byte, isFD bool) byte {\n\tlength := dlc\n\tif dlc == 0x09 {\n\t\tlength = 12\n\t} else if dlc == 0x0A {\n\t\tlength = 16\n\t} else if dlc == 0x0B {\n\t\tlength = 20\n\t} else if dlc == 0x0C {\n\t\tlength = 24\n\t} else if dlc == 0x0D {\n\t\tlength = 32\n\t} else if dlc == 0x0E {\n\t\tlength = 48\n\t} else if dlc == 0x0F {\n\t\tlength = 64\n\t}\n\treturn length\n\n}\n\n// CANLengthToDlc() converts its actual length to a DLC value.\nfunc CANLengthToDlc(length byte, isFD bool) byte {\n\tdlc := length\n\tif length <= 0x08 {\n\t} else if length <= 12 {\n\t\tdlc = 0x09\n\t} else if length <= 16 {\n\t\tdlc = 0x0A\n\t} else if length <= 20 {\n\t\tdlc = 0x0B\n\t} else if length <= 24 {\n\t\tdlc = 0x0C\n\t} else if length <= 32 {\n\t\tdlc = 0x0D\n\t} else if length <= 48 {\n\t\tdlc = 0x0E\n\t} else if length <= 64 {\n\t\tdlc = 0x0F\n\t}\n\treturn dlc\n}\n"
  },
  {
    "path": "src/machine/machine_attiny1616.go",
    "content": "//go:build attiny1616\n\npackage machine\n\nimport (\n\t\"device/avr\"\n)\n\nconst (\n\tportA Pin = iota * 8\n\tportB\n\tportC\n)\n\nconst (\n\tPA0 = portA + 0\n\tPA1 = portA + 1\n\tPA2 = portA + 2\n\tPA3 = portA + 3\n\tPA4 = portA + 4\n\tPA5 = portA + 5\n\tPA6 = portA + 6\n\tPA7 = portA + 7\n\tPB0 = portB + 0\n\tPB1 = portB + 1\n\tPB2 = portB + 2\n\tPB3 = portB + 3\n\tPB4 = portB + 4\n\tPB5 = portB + 5\n\tPB6 = portB + 6\n\tPB7 = portB + 7\n\tPC0 = portC + 0\n\tPC1 = portC + 1\n\tPC2 = portC + 2\n\tPC3 = portC + 3\n\tPC4 = portC + 4\n\tPC5 = portC + 5\n\tPC6 = portC + 6\n\tPC7 = portC + 7\n)\n\n// getPortMask returns the PORT peripheral and mask for the pin.\nfunc (p Pin) getPortMask() (*avr.PORT_Type, uint8) {\n\tswitch {\n\tcase p >= PA0 && p <= PA7: // port A\n\t\treturn avr.PORTA, 1 << uint8(p-portA)\n\tcase p >= PB0 && p <= PB7: // port B\n\t\treturn avr.PORTB, 1 << uint8(p-portB)\n\tdefault: // port C\n\t\treturn avr.PORTC, 1 << uint8(p-portC)\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_attiny85.go",
    "content": "//go:build attiny85\n\npackage machine\n\nimport (\n\t\"device/avr\"\n\t\"runtime/volatile\"\n)\n\nconst (\n\tPB0 Pin = iota\n\tPB1\n\tPB2\n\tPB3\n\tPB4\n\tPB5\n)\n\n// getPortMask returns the PORTx register and mask for the pin.\nfunc (p Pin) getPortMask() (*volatile.Register8, uint8) {\n\t// Very simple for the attiny85, which only has a single port.\n\treturn avr.PORTB, 1 << uint8(p)\n}\n"
  },
  {
    "path": "src/machine/machine_avr.go",
    "content": "//go:build avr && !avrtiny\n\npackage machine\n\nimport (\n\t\"device/avr\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nconst deviceName = avr.DEVICE\n\nconst (\n\tPinInput PinMode = iota\n\tPinInputPullup\n\tPinOutput\n)\n\n// In all the AVRs I've looked at, the PIN/DDR/PORT registers followed a regular\n// pattern: PINx, DDRx, PORTx in this order without registers in between.\n// Therefore, if you know any of them, you can calculate the other two.\n//\n// For now, I've chosen to let the PORTx register be the one that is returned\n// for each specific chip and to calculate the others from that one. Setting an\n// output port (done using PORTx) is likely the most common operation and the\n// one that is the most time critical. For others, the PINx and DDRx register\n// can trivially be calculated using a subtraction.\n\n// Configure sets the pin to input or output.\nfunc (p Pin) Configure(config PinConfig) {\n\tport, mask := p.getPortMask()\n\t// The DDRx register can be found by subtracting one from the PORTx\n\t// register, as this appears to be the case for many (most? all?) AVR chips.\n\tddr := (*volatile.Register8)(unsafe.Pointer(uintptr(unsafe.Pointer(port)) - 1))\n\tif config.Mode == PinOutput {\n\t\t// set output bit\n\t\tddr.SetBits(mask)\n\n\t\t// Note: if the pin was PinInputPullup before, it'll now be high.\n\t\t// Otherwise it will be low.\n\t} else {\n\t\t// configure input: clear output bit\n\t\tddr.ClearBits(mask)\n\n\t\tif config.Mode == PinInput {\n\t\t\t// No pullup (floating).\n\t\t\t// The transition may be one of the following:\n\t\t\t//   output high -> input pullup -> input (safe: output high and input pullup are similar)\n\t\t\t//   output low  -> input        -> input (safe: no extra transition)\n\t\t\tport.ClearBits(mask)\n\t\t} else {\n\t\t\t// Pullup.\n\t\t\t// The transition may be one of the following:\n\t\t\t//   output high -> input pullup -> input pullup (safe: no extra transition)\n\t\t\t//   output low  -> input        -> input pullup (possibly problematic)\n\t\t\t// For the last transition (output low -> input -> input pullup),\n\t\t\t// the transition may be problematic in some cases because there is\n\t\t\t// an intermediate floating state (which may cause irratic\n\t\t\t// interrupts, for example). If this is a problem, the application\n\t\t\t// should set the pin high before configuring it as PinInputPullup.\n\t\t\t// We can't do that here because setting it to high as an\n\t\t\t// intermediate state may have other problems.\n\t\t\tport.SetBits(mask)\n\t\t}\n\t}\n}\n\n// Get returns the current value of a GPIO pin when the pin is configured as an\n// input or as an output.\nfunc (p Pin) Get() bool {\n\tport, mask := p.getPortMask()\n\t// As noted above, the PINx register is always two registers below the PORTx\n\t// register, so we can find it simply by subtracting two from the PORTx\n\t// register address.\n\tpin := (*volatile.Register8)(unsafe.Pointer(uintptr(unsafe.Pointer(port)) - 2)) // PINA, PINB, etc\n\treturn (pin.Get() & mask) > 0\n}\n\n// Set changes the value of the GPIO pin. The pin must be configured as output.\nfunc (p Pin) Set(value bool) {\n\tif value { // set bits\n\t\tport, mask := p.PortMaskSet()\n\t\tport.Set(mask)\n\t} else { // clear bits\n\t\tport, mask := p.PortMaskClear()\n\t\tport.Set(mask)\n\t}\n}\n\n// Return the register and mask to enable a given GPIO pin. This can be used to\n// implement bit-banged drivers.\n//\n// Warning: there are no separate pin set/clear registers on the AVR. The\n// returned mask is only valid as long as no other pin in the same port has been\n// changed.\nfunc (p Pin) PortMaskSet() (*volatile.Register8, uint8) {\n\tport, mask := p.getPortMask()\n\treturn port, port.Get() | mask\n}\n\n// Return the register and mask to disable a given port. This can be used to\n// implement bit-banged drivers.\n//\n// Warning: there are no separate pin set/clear registers on the AVR. The\n// returned mask is only valid as long as no other pin in the same port has been\n// changed.\nfunc (p Pin) PortMaskClear() (*volatile.Register8, uint8) {\n\tport, mask := p.getPortMask()\n\treturn port, port.Get() &^ mask\n}\n\n// InitADC initializes the registers needed for ADC.\nfunc InitADC() {\n\t// set a2d prescaler so we are inside the desired 50-200 KHz range at 16MHz.\n\tavr.ADCSRA.SetBits(avr.ADCSRA_ADPS2 | avr.ADCSRA_ADPS1 | avr.ADCSRA_ADPS0)\n\n\t// enable a2d conversions\n\tavr.ADCSRA.SetBits(avr.ADCSRA_ADEN)\n}\n\n// Configure configures a ADCPin to be able to be used to read data.\nfunc (a ADC) Configure(ADCConfig) {\n\treturn // no pin specific setup on AVR machine.\n}\n\n// Get returns the current value of a ADC pin, in the range 0..0xffff. The AVR\n// has an ADC of 10 bits precision so the lower 6 bits will be zero.\nfunc (a ADC) Get() uint16 {\n\t// set the analog reference (high two bits of ADMUX) and select the\n\t// channel (low 4 bits), masked to only turn on one ADC at a time.\n\t// set the ADLAR bit (left-adjusted result) to get a value scaled to 16\n\t// bits. This has the same effect as shifting the return value left by 6\n\t// bits.\n\tavr.ADMUX.Set(avr.ADMUX_REFS0 | avr.ADMUX_ADLAR | (uint8(a.Pin) & 0x07))\n\n\t// start the conversion\n\tavr.ADCSRA.SetBits(avr.ADCSRA_ADSC)\n\n\t// ADSC is cleared when the conversion finishes\n\tfor ok := true; ok; ok = avr.ADCSRA.HasBits(avr.ADCSRA_ADSC) {\n\t}\n\n\treturn uint16(avr.ADCL.Get()) | uint16(avr.ADCH.Get())<<8\n}\n\n// linked from runtime.adjustMonotonicTimer\nfunc adjustMonotonicTimer()\n\n// linked from runtime.initMonotonicTimer\nfunc initMonotonicTimer()\n"
  },
  {
    "path": "src/machine/machine_avrtiny.go",
    "content": "//go:build avrtiny\n\npackage machine\n\nimport (\n\t\"device/avr\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nconst deviceName = avr.DEVICE\n\nconst (\n\tPinInput PinMode = iota\n\tPinInputPullup\n\tPinOutput\n)\n\n// Configure sets the pin to input or output.\nfunc (p Pin) Configure(config PinConfig) {\n\tport, mask := p.getPortMask()\n\n\tif config.Mode == PinOutput {\n\t\t// set output bit\n\t\tport.DIRSET.Set(mask)\n\n\t\t// Note: the output state (high or low) is as it was before.\n\t} else {\n\t\t// Configure the pin as an input.\n\t\t// First set up the configuration that will be used when it is an input.\n\t\tpinctrl := uint8(0)\n\t\tif config.Mode == PinInputPullup {\n\t\t\tpinctrl |= avr.PORT_PIN0CTRL_PULLUPEN\n\t\t}\n\t\t// Find the PINxCTRL register for this pin.\n\t\tctrlAddress := (*volatile.Register8)(unsafe.Add(unsafe.Pointer(&port.PIN0CTRL), p%8))\n\t\tctrlAddress.Set(pinctrl)\n\n\t\t// Configure the pin as input (if it wasn't an input pin before).\n\t\tport.DIRCLR.Set(mask)\n\t}\n}\n\n// Get returns the current value of a GPIO pin when the pin is configured as an\n// input or as an output.\nfunc (p Pin) Get() bool {\n\tport, mask := p.getPortMask()\n\t// As noted above, the PINx register is always two registers below the PORTx\n\t// register, so we can find it simply by subtracting two from the PORTx\n\t// register address.\n\treturn (port.IN.Get() & mask) > 0\n}\n\n// Set changes the value of the GPIO pin. The pin must be configured as output.\nfunc (p Pin) Set(high bool) {\n\tport, mask := p.getPortMask()\n\tif high {\n\t\tport.OUTSET.Set(mask)\n\t} else {\n\t\tport.OUTCLR.Set(mask)\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_cortexm.go",
    "content": "//go:build cortexm\n\npackage machine\n\nimport \"device/arm\"\n\n// CPUReset performs a hard system reset.\nfunc CPUReset() {\n\tarm.SystemReset()\n}\n"
  },
  {
    "path": "src/machine/machine_esp32.go",
    "content": "//go:build esp32\n\npackage machine\n\nimport (\n\t\"device/esp\"\n\t\"errors\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nconst deviceName = esp.Device\n\nconst peripheralClock = 80000000 // 80MHz\n\n// CPUFrequency returns the current CPU frequency of the chip.\n// Currently it is a fixed frequency but it may allow changing in the future.\nfunc CPUFrequency() uint32 {\n\treturn 160e6 // 160MHz\n}\n\nvar (\n\tErrInvalidSPIBus = errors.New(\"machine: invalid SPI bus\")\n)\n\nconst (\n\tPinOutput PinMode = iota\n\tPinInput\n\tPinInputPullup\n\tPinInputPulldown\n)\n\n// Hardware pin numbers\nconst (\n\tGPIO0  Pin = 0\n\tGPIO1  Pin = 1\n\tGPIO2  Pin = 2\n\tGPIO3  Pin = 3\n\tGPIO4  Pin = 4\n\tGPIO5  Pin = 5\n\tGPIO6  Pin = 6\n\tGPIO7  Pin = 7\n\tGPIO8  Pin = 8\n\tGPIO9  Pin = 9\n\tGPIO10 Pin = 10\n\tGPIO11 Pin = 11\n\tGPIO12 Pin = 12\n\tGPIO13 Pin = 13\n\tGPIO14 Pin = 14\n\tGPIO15 Pin = 15\n\tGPIO16 Pin = 16\n\tGPIO17 Pin = 17\n\tGPIO18 Pin = 18\n\tGPIO19 Pin = 19\n\tGPIO21 Pin = 21\n\tGPIO22 Pin = 22\n\tGPIO23 Pin = 23\n\tGPIO25 Pin = 25\n\tGPIO26 Pin = 26\n\tGPIO27 Pin = 27\n\tGPIO32 Pin = 32\n\tGPIO33 Pin = 33\n\tGPIO34 Pin = 34\n\tGPIO35 Pin = 35\n\tGPIO36 Pin = 36\n\tGPIO37 Pin = 37\n\tGPIO38 Pin = 38\n\tGPIO39 Pin = 39\n)\n\n// Configure this pin with the given configuration.\nfunc (p Pin) Configure(config PinConfig) {\n\t// Output function 256 is a special value reserved for use as a regular GPIO\n\t// pin. Peripherals (SPI etc) can set a custom output function by calling\n\t// lowercase configure() instead with a signal name.\n\tp.configure(config, 256)\n}\n\n// configure is the same as Configure, but allows for setting a specific input\n// or output signal.\n// Signals are always routed through the GPIO matrix for simplicity. Output\n// signals are configured in FUNCx_OUT_SEL_CFG which selects a particular signal\n// to output on a given pin. Input signals are configured in FUNCy_IN_SEL_CFG,\n// which sets the pin to use for a particular input signal.\nfunc (p Pin) configure(config PinConfig, signal uint32) {\n\tif p == NoPin {\n\t\t// This simplifies pin configuration in peripherals such as SPI.\n\t\treturn\n\t}\n\n\tvar muxConfig uint32 // The mux configuration.\n\n\t// Configure this pin as a GPIO pin.\n\tconst function = 3 // function 3 is GPIO for every pin\n\tmuxConfig |= (function - 1) << esp.IO_MUX_GPIO0_MCU_SEL_Pos\n\n\t// Make this pin an input pin (always).\n\tmuxConfig |= esp.IO_MUX_GPIO0_FUN_IE\n\n\t// Set drive strength: 0 is lowest, 3 is highest.\n\tmuxConfig |= 2 << esp.IO_MUX_GPIO0_FUN_DRV_Pos\n\n\t// Select pull mode.\n\tif config.Mode == PinInputPullup {\n\t\tmuxConfig |= esp.IO_MUX_GPIO0_FUN_WPU\n\t} else if config.Mode == PinInputPulldown {\n\t\tmuxConfig |= esp.IO_MUX_GPIO0_FUN_WPD\n\t}\n\n\t// Configure the pad with the given IO mux configuration.\n\tp.mux().Set(muxConfig)\n\n\tswitch config.Mode {\n\tcase PinOutput:\n\t\t// Set the 'output enable' bit.\n\t\tif p < 32 {\n\t\t\tesp.GPIO.ENABLE_W1TS.Set(1 << p)\n\t\t} else {\n\t\t\tesp.GPIO.ENABLE1_W1TS.Set(1 << (p - 32))\n\t\t}\n\t\t// Set the signal to read the output value from. It can be a peripheral\n\t\t// output signal, or the special value 256 which indicates regular GPIO\n\t\t// usage.\n\t\tp.outFunc().Set(signal)\n\tcase PinInput, PinInputPullup, PinInputPulldown:\n\t\t// Clear the 'output enable' bit.\n\t\tif p < 32 {\n\t\t\tesp.GPIO.ENABLE_W1TC.Set(1 << p)\n\t\t} else {\n\t\t\tesp.GPIO.ENABLE1_W1TC.Set(1 << (p - 32))\n\t\t}\n\t\tif signal != 256 {\n\t\t\t// Signal is a peripheral function (not a simple GPIO). Connect this\n\t\t\t// signal to the pin.\n\t\t\t// Note that outFunc and inFunc work in the opposite direction.\n\t\t\t// outFunc configures a pin to use a given output signal, while\n\t\t\t// inFunc specifies a pin to use to read the signal from.\n\t\t\tinFunc(signal).Set(esp.GPIO_FUNC_IN_SEL_CFG_SEL | uint32(p)<<esp.GPIO_FUNC_IN_SEL_CFG_IN_SEL_Pos)\n\t\t}\n\t}\n}\n\n// outFunc returns the FUNCx_OUT_SEL_CFG register used for configuring the\n// output function selection.\nfunc (p Pin) outFunc() *volatile.Register32 {\n\treturn (*volatile.Register32)(unsafe.Add(unsafe.Pointer(&esp.GPIO.FUNC0_OUT_SEL_CFG), uintptr(p)*4))\n}\n\n// inFunc returns the FUNCy_IN_SEL_CFG register used for configuring the input\n// function selection.\nfunc inFunc(signal uint32) *volatile.Register32 {\n\treturn (*volatile.Register32)(unsafe.Add(unsafe.Pointer(&esp.GPIO.FUNC0_IN_SEL_CFG), uintptr(signal)*4))\n}\n\n// Set the pin to high or low.\n// Warning: only use this on an output pin!\nfunc (p Pin) Set(value bool) {\n\tif value {\n\t\treg, mask := p.portMaskSet()\n\t\treg.Set(mask)\n\t} else {\n\t\treg, mask := p.portMaskClear()\n\t\treg.Set(mask)\n\t}\n}\n\n// Return the register and mask to enable a given GPIO pin. This can be used to\n// implement bit-banged drivers.\n//\n// Warning: only use this on an output pin!\nfunc (p Pin) PortMaskSet() (*uint32, uint32) {\n\treg, mask := p.portMaskSet()\n\treturn &reg.Reg, mask\n}\n\n// Return the register and mask to disable a given GPIO pin. This can be used to\n// implement bit-banged drivers.\n//\n// Warning: only use this on an output pin!\nfunc (p Pin) PortMaskClear() (*uint32, uint32) {\n\treg, mask := p.portMaskClear()\n\treturn &reg.Reg, mask\n}\n\nfunc (p Pin) portMaskSet() (*volatile.Register32, uint32) {\n\tif p < 32 {\n\t\treturn &esp.GPIO.OUT_W1TS, 1 << p\n\t} else {\n\t\treturn &esp.GPIO.OUT1_W1TS, 1 << (p - 32)\n\t}\n}\n\nfunc (p Pin) portMaskClear() (*volatile.Register32, uint32) {\n\tif p < 32 {\n\t\treturn &esp.GPIO.OUT_W1TC, 1 << p\n\t} else {\n\t\treturn &esp.GPIO.OUT1_W1TC, 1 << (p - 32)\n\t}\n}\n\n// Get returns the current value of a GPIO pin when the pin is configured as an\n// input or as an output.\nfunc (p Pin) Get() bool {\n\tif p < 32 {\n\t\treturn esp.GPIO.IN.Get()&(1<<p) != 0\n\t} else {\n\t\treturn esp.GPIO.IN1.Get()&(1<<(p-32)) != 0\n\t}\n}\n\n// mux returns the I/O mux configuration register corresponding to the given\n// GPIO pin.\nfunc (p Pin) mux() *volatile.Register32 {\n\t// I have no idea whether there is any pattern in the GPIO <-> pad mapping.\n\t// I couldn't find it.\n\tswitch p {\n\tcase 36:\n\t\treturn &esp.IO_MUX.GPIO36\n\tcase 37:\n\t\treturn &esp.IO_MUX.GPIO37\n\tcase 38:\n\t\treturn &esp.IO_MUX.GPIO38\n\tcase 39:\n\t\treturn &esp.IO_MUX.GPIO39\n\tcase 34:\n\t\treturn &esp.IO_MUX.GPIO34\n\tcase 35:\n\t\treturn &esp.IO_MUX.GPIO35\n\tcase 32:\n\t\treturn &esp.IO_MUX.GPIO32\n\tcase 33:\n\t\treturn &esp.IO_MUX.GPIO33\n\tcase 25:\n\t\treturn &esp.IO_MUX.GPIO25\n\tcase 26:\n\t\treturn &esp.IO_MUX.GPIO26\n\tcase 27:\n\t\treturn &esp.IO_MUX.GPIO27\n\tcase 14:\n\t\treturn &esp.IO_MUX.GPIO14\n\tcase 12:\n\t\treturn &esp.IO_MUX.GPIO12\n\tcase 13:\n\t\treturn &esp.IO_MUX.GPIO13\n\tcase 15:\n\t\treturn &esp.IO_MUX.GPIO15\n\tcase 2:\n\t\treturn &esp.IO_MUX.GPIO2\n\tcase 0:\n\t\treturn &esp.IO_MUX.GPIO0\n\tcase 4:\n\t\treturn &esp.IO_MUX.GPIO4\n\tcase 16:\n\t\treturn &esp.IO_MUX.GPIO16\n\tcase 17:\n\t\treturn &esp.IO_MUX.GPIO17\n\tcase 9:\n\t\treturn &esp.IO_MUX.GPIO9\n\tcase 10:\n\t\treturn &esp.IO_MUX.GPIO10\n\tcase 11:\n\t\treturn &esp.IO_MUX.GPIO11\n\tcase 6:\n\t\treturn &esp.IO_MUX.GPIO6\n\tcase 7:\n\t\treturn &esp.IO_MUX.GPIO7\n\tcase 8:\n\t\treturn &esp.IO_MUX.GPIO8\n\tcase 5:\n\t\treturn &esp.IO_MUX.GPIO5\n\tcase 18:\n\t\treturn &esp.IO_MUX.GPIO18\n\tcase 19:\n\t\treturn &esp.IO_MUX.GPIO19\n\tcase 20:\n\t\treturn &esp.IO_MUX.GPIO20\n\tcase 21:\n\t\treturn &esp.IO_MUX.GPIO21\n\tcase 22:\n\t\treturn &esp.IO_MUX.GPIO22\n\tcase 3:\n\t\treturn &esp.IO_MUX.GPIO3\n\tcase 1:\n\t\treturn &esp.IO_MUX.GPIO1\n\tcase 23:\n\t\treturn &esp.IO_MUX.GPIO23\n\tcase 24:\n\t\treturn &esp.IO_MUX.GPIO24\n\tdefault:\n\t\treturn nil\n\t}\n}\n\nvar DefaultUART = UART0\n\nvar (\n\tUART0  = &_UART0\n\t_UART0 = UART{Bus: esp.UART0, Buffer: NewRingBuffer()}\n\tUART1  = &_UART1\n\t_UART1 = UART{Bus: esp.UART1, Buffer: NewRingBuffer()}\n\tUART2  = &_UART2\n\t_UART2 = UART{Bus: esp.UART2, Buffer: NewRingBuffer()}\n)\n\ntype UART struct {\n\tBus    *esp.UART_Type\n\tBuffer *RingBuffer\n}\n\nfunc (uart *UART) Configure(config UARTConfig) {\n\tif config.BaudRate == 0 {\n\t\tconfig.BaudRate = 115200\n\t}\n\tuart.Bus.CLKDIV.Set(peripheralClock / config.BaudRate)\n}\n\nfunc (uart *UART) writeByte(b byte) error {\n\tfor (uart.Bus.STATUS.Get()>>16)&0xff >= 128 {\n\t\t// Read UART_TXFIFO_CNT from the status register, which indicates how\n\t\t// many bytes there are in the transmit buffer. Wait until there are\n\t\t// less than 128 bytes in this buffer (the default buffer size).\n\t}\n\t// Write to the TX_FIFO register.\n\t(*volatile.Register8)(unsafe.Add(unsafe.Pointer(uart.Bus), 0x200C0000)).Set(b)\n\treturn nil\n}\n\nfunc (uart *UART) flush() {}\n\n// Serial Peripheral Interface on the ESP32.\ntype SPI struct {\n\tBus *esp.SPI_Type\n}\n\nvar (\n\t// SPI0 and SPI1 are reserved for use by the caching system etc.\n\tSPI2 = &SPI{esp.SPI2}\n\tSPI3 = &SPI{esp.SPI3}\n)\n\n// SPIConfig configures a SPI peripheral on the ESP32. Make sure to set at least\n// SCK, SDO and SDI (possibly to NoPin if not in use). The default for LSBFirst\n// (false) and Mode (0) are good for most applications. The frequency defaults\n// to 1MHz if not set but can be configured up to 40MHz. Possible values are\n// 40MHz and integer divisions from 40MHz such as 20MHz, 13.3MHz, 10MHz, 8MHz,\n// etc.\ntype SPIConfig struct {\n\tFrequency uint32\n\tSCK       Pin\n\tSDO       Pin\n\tSDI       Pin\n\tLSBFirst  bool\n\tMode      uint8\n}\n\n// Configure and make the SPI peripheral ready to use.\nfunc (spi *SPI) Configure(config SPIConfig) error {\n\tif config.Frequency == 0 {\n\t\tconfig.Frequency = 4e6 // default to 4MHz\n\t}\n\n\t// Configure the SPI clock. This assumes a peripheral clock of 80MHz.\n\tvar clockReg uint32\n\tif config.Frequency > 40e6 {\n\t\t// Don't use a prescaler, but directly connect to the APB clock. This\n\t\t// results in a SPI clock frequency of 40MHz.\n\t\tclockReg |= esp.SPI_CLOCK_CLK_EQU_SYSCLK\n\t} else {\n\t\t// Use a prescaler for frequencies below 40MHz. They will get rounded\n\t\t// down to the next possible frequency (20MHz, 13.3MHz, 10MHz, 8MHz,\n\t\t// 6.7MHz, 5.7MHz, 5MHz, etc).\n\t\t// This code is much simpler than how ESP-IDF configures the frequency,\n\t\t// but should be just as accurate. The only exception is for frequencies\n\t\t// below 4883Hz, which will need special support.\n\t\tif config.Frequency < 4883 {\n\t\t\t// The current lower limit is 4883Hz.\n\t\t\t// The hardware supports lower frequencies by setting the h and n\n\t\t\t// variables, but that's not yet implemented.\n\t\t\tconfig.Frequency = 4883\n\t\t}\n\t\t// The prescaler value is 40e6 / config.Frequency, but rounded up so\n\t\t// that the actual frequency is never higher than the frequency\n\t\t// requested in config.Frequency.\n\t\tvar (\n\t\t\tpre uint32 = (40e6 + config.Frequency - 1) / config.Frequency\n\t\t\tn   uint32 = 2 // this value seems to equal the number of ticks per SPI clock tick\n\t\t\th   uint32 = 1 // must be half of n according to the formula in the reference manual\n\t\t\tl   uint32 = n // must equal n according to the reference manual\n\t\t)\n\t\tclockReg |= (pre - 1) << esp.SPI_CLOCK_CLKDIV_PRE_Pos\n\t\tclockReg |= (n - 1) << esp.SPI_CLOCK_CLKCNT_N_Pos\n\t\tclockReg |= (h - 1) << esp.SPI_CLOCK_CLKCNT_H_Pos\n\t\tclockReg |= (l - 1) << esp.SPI_CLOCK_CLKCNT_L_Pos\n\t}\n\tspi.Bus.CLOCK.Set(clockReg)\n\n\t// SPI_CTRL_REG controls bit order.\n\tvar ctrlReg uint32\n\tif config.LSBFirst {\n\t\tctrlReg |= esp.SPI_CTRL_WR_BIT_ORDER\n\t\tctrlReg |= esp.SPI_CTRL_RD_BIT_ORDER\n\t}\n\tspi.Bus.CTRL.Set(ctrlReg)\n\n\t// SPI_CTRL2_REG, SPI_USER_REG and SPI_PIN_REG control SPI clock polarity\n\t// (mode), among others.\n\tvar ctrl2Reg, userReg, pinReg uint32\n\t// For mode configuration, see table 29 in the reference manual (page 128).\n\tswitch config.Mode {\n\tcase 0:\n\tcase 1:\n\t\tuserReg |= esp.SPI_USER_CK_OUT_EDGE\n\tcase 2:\n\t\tuserReg |= esp.SPI_USER_CK_OUT_EDGE\n\t\tpinReg |= esp.SPI_PIN_CK_IDLE_EDGE\n\tcase 3:\n\t\tpinReg |= esp.SPI_PIN_CK_IDLE_EDGE\n\t}\n\t// Enable full-duplex communication.\n\tuserReg |= esp.SPI_USER_DOUTDIN\n\tuserReg |= esp.SPI_USER_USR_MOSI\n\t// Write values to registers.\n\tspi.Bus.CTRL2.Set(ctrl2Reg)\n\tspi.Bus.USER.Set(userReg)\n\tspi.Bus.PIN.Set(pinReg)\n\n\t// Configure pins.\n\t// TODO: use direct output if possible, if the configured pins match the\n\t// possible direct configurations (e.g. for SPI2, when SCK is pin 14 etc).\n\tif spi.Bus == esp.SPI2 {\n\t\tconfig.SCK.configure(PinConfig{Mode: PinOutput}, 8)  // HSPICLK\n\t\tconfig.SDI.configure(PinConfig{Mode: PinInput}, 9)   // HSPIQ\n\t\tconfig.SDO.configure(PinConfig{Mode: PinOutput}, 10) // HSPID\n\t} else if spi.Bus == esp.SPI3 {\n\t\tconfig.SCK.configure(PinConfig{Mode: PinOutput}, 63) // VSPICLK\n\t\tconfig.SDI.configure(PinConfig{Mode: PinInput}, 64)  // VSPIQ\n\t\tconfig.SDO.configure(PinConfig{Mode: PinOutput}, 65) // VSPID\n\t} else {\n\t\t// Don't know how to configure this bus.\n\t\treturn ErrInvalidSPIBus\n\t}\n\n\treturn nil\n}\n\n// Transfer writes/reads a single byte using the SPI interface. If you need to\n// transfer larger amounts of data, Tx will be faster.\nfunc (spi *SPI) Transfer(w byte) (byte, error) {\n\tspi.Bus.MISO_DLEN.Set(7 << esp.SPI_MISO_DLEN_USR_MISO_DBITLEN_Pos)\n\tspi.Bus.MOSI_DLEN.Set(7 << esp.SPI_MOSI_DLEN_USR_MOSI_DBITLEN_Pos)\n\n\tspi.Bus.W0.Set(uint32(w))\n\n\t// Send/receive byte.\n\tspi.Bus.CMD.Set(esp.SPI_CMD_USR)\n\tfor spi.Bus.CMD.Get() != 0 {\n\t}\n\n\t// The received byte is stored in W0.\n\treturn byte(spi.Bus.W0.Get()), nil\n}\n\n// Tx handles read/write operation for SPI interface. Since SPI is a synchronous write/read\n// interface, there must always be the same number of bytes written as bytes read.\n// This is accomplished by sending zero bits if r is bigger than w or discarding\n// the incoming data if w is bigger than r.\nfunc (spi *SPI) Tx(w, r []byte) error {\n\ttoTransfer := len(w)\n\tif len(r) > toTransfer {\n\t\ttoTransfer = len(r)\n\t}\n\n\tfor toTransfer != 0 {\n\t\t// Do only 64 bytes at a time.\n\t\tchunkSize := toTransfer\n\t\tif chunkSize > 64 {\n\t\t\tchunkSize = 64\n\t\t}\n\n\t\t// Fill tx buffer.\n\t\ttransferWords := (*[16]volatile.Register32)(unsafe.Pointer(uintptr(unsafe.Pointer(&spi.Bus.W0))))\n\t\tif len(w) >= 64 {\n\t\t\t// We can fill the entire 64-byte transfer buffer with data.\n\t\t\t// This loop is slightly faster than the loop below.\n\t\t\tfor i := 0; i < 16; i++ {\n\t\t\t\tword := uint32(w[i*4])<<0 | uint32(w[i*4+1])<<8 | uint32(w[i*4+2])<<16 | uint32(w[i*4+3])<<24\n\t\t\t\ttransferWords[i].Set(word)\n\t\t\t}\n\t\t} else {\n\t\t\t// We can't fill the entire transfer buffer, so we need to be a bit\n\t\t\t// more careful.\n\t\t\t// Note that parts of the transfer buffer that aren't used still\n\t\t\t// need to be set to zero, otherwise we might be transferring\n\t\t\t// garbage from a previous transmission if w is smaller than r.\n\t\t\tfor i := 0; i < 16; i++ {\n\t\t\t\tvar word uint32\n\t\t\t\tif i*4+3 < len(w) {\n\t\t\t\t\tword |= uint32(w[i*4+3]) << 24\n\t\t\t\t}\n\t\t\t\tif i*4+2 < len(w) {\n\t\t\t\t\tword |= uint32(w[i*4+2]) << 16\n\t\t\t\t}\n\t\t\t\tif i*4+1 < len(w) {\n\t\t\t\t\tword |= uint32(w[i*4+1]) << 8\n\t\t\t\t}\n\t\t\t\tif i*4+0 < len(w) {\n\t\t\t\t\tword |= uint32(w[i*4+0]) << 0\n\t\t\t\t}\n\t\t\t\ttransferWords[i].Set(word)\n\t\t\t}\n\t\t}\n\n\t\t// Do the transfer.\n\t\tspi.Bus.MISO_DLEN.Set((uint32(chunkSize)*8 - 1) << esp.SPI_MISO_DLEN_USR_MISO_DBITLEN_Pos)\n\t\tspi.Bus.MOSI_DLEN.Set((uint32(chunkSize)*8 - 1) << esp.SPI_MOSI_DLEN_USR_MOSI_DBITLEN_Pos)\n\t\tspi.Bus.CMD.Set(esp.SPI_CMD_USR)\n\t\tfor spi.Bus.CMD.Get() != 0 {\n\t\t}\n\n\t\t// Read rx buffer.\n\t\trxSize := 64\n\t\tif rxSize > len(r) {\n\t\t\trxSize = len(r)\n\t\t}\n\t\tfor i := 0; i < rxSize; i++ {\n\t\t\tr[i] = byte(transferWords[i/4].Get() >> ((i % 4) * 8))\n\t\t}\n\n\t\t// Cut off some part of the output buffer so the next iteration we will\n\t\t// only send the remaining bytes.\n\t\tif len(w) < chunkSize {\n\t\t\tw = nil\n\t\t} else {\n\t\t\tw = w[chunkSize:]\n\t\t}\n\t\tif len(r) < chunkSize {\n\t\t\tr = nil\n\t\t} else {\n\t\t\tr = r[chunkSize:]\n\t\t}\n\t\ttoTransfer -= chunkSize\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "src/machine/machine_esp32_i2c.go",
    "content": "//go:build esp32\n\npackage machine\n\nimport (\n\t\"device/esp\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nvar (\n\tI2C0 = &I2C{Bus: esp.I2C0, funcSCL: 29, funcSDA: 30}\n\tI2C1 = &I2C{Bus: esp.I2C1, funcSCL: 95, funcSDA: 96}\n)\n\ntype I2C struct {\n\tBus              *esp.I2C_Type\n\tfuncSCL, funcSDA uint32\n\tconfig           I2CConfig\n}\n\n// I2CConfig is used to store config info for I2C.\ntype I2CConfig struct {\n\tFrequency uint32 // in Hz\n\tSCL       Pin\n\tSDA       Pin\n}\n\nconst (\n\ti2cClkSourceFrequency = uint32(80 * MHz)\n)\n\nfunc (i2c *I2C) Configure(config I2CConfig) error {\n\tif config.Frequency == 0 {\n\t\tconfig.Frequency = 400 * KHz\n\t}\n\tif config.SCL == 0 {\n\t\tconfig.SCL = SCL_PIN\n\t}\n\tif config.SDA == 0 {\n\t\tconfig.SDA = SDA_PIN\n\t}\n\ti2c.config = config\n\n\ti2c.initAll()\n\treturn nil\n}\n\nfunc (i2c *I2C) initAll() {\n\ti2c.initClock()\n\ti2c.initNoiseFilter()\n\ti2c.initPins()\n\ti2c.initFrequency()\n\ti2c.startMaster()\n}\n\n//go:inline\nfunc (i2c *I2C) initClock() {\n\t// reset I2C clock\n\tif i2c.Bus == esp.I2C0 {\n\t\tesp.DPORT.SetPERIP_RST_EN_I2C0_EXT0_RST(1)\n\t\tesp.DPORT.SetPERIP_CLK_EN_I2C0_EXT0_CLK_EN(1)\n\t\tesp.DPORT.SetPERIP_RST_EN_I2C0_EXT0_RST(0)\n\t} else {\n\t\tesp.DPORT.SetPERIP_RST_EN_I2C_EXT1_RST(1)\n\t\tesp.DPORT.SetPERIP_CLK_EN_I2C_EXT1_CLK_EN(1)\n\t\tesp.DPORT.SetPERIP_RST_EN_I2C_EXT1_RST(0)\n\t}\n\t// disable interrupts\n\ti2c.Bus.INT_ENA.Set(0)\n\ti2c.Bus.INT_CLR.Set(0x3fff)\n\n\ti2c.Bus.SetCTR_CLK_EN(1)\n}\n\n//go:inline\nfunc (i2c *I2C) initNoiseFilter() {\n\ti2c.Bus.SCL_FILTER_CFG.Set(0xF)\n\ti2c.Bus.SDA_FILTER_CFG.Set(0xF)\n}\n\n//go:inline\nfunc (i2c *I2C) initPins() {\n\tvar muxConfig uint32\n\tconst function = 2 // function 2 is just GPIO\n\n\t// SDA\n\tmuxConfig = function << esp.IO_MUX_GPIO0_MCU_SEL_Pos\n\t// Make this pin an input pin (always).\n\tmuxConfig |= esp.IO_MUX_GPIO0_FUN_IE\n\t// Set drive strength: 0 is lowest, 3 is highest.\n\tmuxConfig |= 1 << esp.IO_MUX_GPIO0_FUN_DRV_Pos\n\ti2c.config.SDA.mux().Set(muxConfig)\n\ti2c.config.SDA.outFunc().Set(i2c.funcSDA)\n\tinFunc(i2c.funcSDA).Set(uint32(esp.GPIO_FUNC_IN_SEL_CFG_SEL | i2c.config.SDA))\n\ti2c.config.SDA.Set(true)\n\t// Configure the pad with the given IO mux configuration.\n\ti2c.config.SDA.pinReg().SetBits(esp.GPIO_PIN_PAD_DRIVER)\n\n\tesp.GPIO.ENABLE_W1TS.Set(1 << int(i2c.config.SDA))\n\ti2c.Bus.SetCTR_SDA_FORCE_OUT(1)\n\n\t// SCL\n\tmuxConfig = function << esp.IO_MUX_GPIO0_MCU_SEL_Pos\n\t// Make this pin an input pin (always).\n\tmuxConfig |= esp.IO_MUX_GPIO0_FUN_IE\n\t// Set drive strength: 0 is lowest, 3 is highest.\n\tmuxConfig |= 1 << esp.IO_MUX_GPIO0_FUN_DRV_Pos\n\ti2c.config.SCL.mux().Set(muxConfig)\n\ti2c.config.SCL.outFunc().Set(i2c.funcSCL)\n\tinFunc(i2c.funcSCL).Set(uint32(esp.GPIO_FUNC_IN_SEL_CFG_SEL | i2c.config.SCL))\n\ti2c.config.SCL.Set(true)\n\t// Configure the pad with the given IO mux configuration.\n\ti2c.config.SCL.pinReg().SetBits(esp.GPIO_PIN_PAD_DRIVER)\n\n\tesp.GPIO.ENABLE_W1TS.Set(1 << int(i2c.config.SCL))\n\ti2c.Bus.SetCTR_SCL_FORCE_OUT(1)\n}\n\n//go:inline\nfunc (i2c *I2C) initFrequency() {\n\tclkmDiv := i2cClkSourceFrequency/(i2c.config.Frequency*1024) + 1\n\tsclkFreq := i2cClkSourceFrequency / clkmDiv\n\thalfCycle := sclkFreq / i2c.config.Frequency / 2\n\t//SCL\n\tsclLow := halfCycle\n\tsclWaitHigh := uint32(0)\n\tif i2c.config.Frequency > 50000 {\n\t\tsclWaitHigh = halfCycle / 8 // compensate the time when freq > 50K\n\t}\n\tsclHigh := halfCycle - sclWaitHigh\n\t// SDA\n\tsdaHold := halfCycle / 4\n\tsda_sample := halfCycle / 2\n\tsetup := halfCycle\n\thold := halfCycle\n\n\ti2c.Bus.SetSCL_LOW_PERIOD(sclLow - 1)\n\ti2c.Bus.SetSCL_HIGH_PERIOD(sclHigh)\n\ti2c.Bus.SetSCL_RSTART_SETUP_TIME(setup)\n\ti2c.Bus.SetSCL_STOP_SETUP_TIME(setup)\n\ti2c.Bus.SetSCL_START_HOLD_TIME(hold - 1)\n\ti2c.Bus.SetSCL_STOP_HOLD_TIME(hold - 1)\n\ti2c.Bus.SetSDA_SAMPLE_TIME(sda_sample)\n\ti2c.Bus.SetSDA_HOLD_TIME(sdaHold)\n\t// set timeout value\n\ti2c.Bus.SetTO_TIME_OUT(20 * halfCycle)\n}\n\n//go:inline\nfunc (i2c *I2C) startMaster() {\n\t// FIFO mode for data\n\ti2c.Bus.SetFIFO_CONF_NONFIFO_EN(0)\n\t// Reset TX & RX buffers\n\ti2c.Bus.SetFIFO_CONF_RX_FIFO_RST(1)\n\ti2c.Bus.SetFIFO_CONF_RX_FIFO_RST(0)\n\ti2c.Bus.SetFIFO_CONF_TX_FIFO_RST(1)\n\ti2c.Bus.SetFIFO_CONF_TX_FIFO_RST(0)\n\t// enable master mode\n\ti2c.Bus.SetCTR_MS_MODE(1)\n}\n\nfunc (i2c *I2C) resetBus() {\n\t// unlike esp32c3, the esp32 i2c modules do not have a reset fsm register,\n\t// so we need to:\n\t//   1. disconnect the pins\n\t//   2. generate a stop condition manually\n\t//   3. do a full reset\n\t//   4. redo all configuration\n\n\ti2c.config.SDA.mux().Set(2<<esp.IO_MUX_GPIO0_MCU_SEL_Pos | esp.IO_MUX_GPIO0_FUN_IE | 1<<esp.IO_MUX_GPIO0_FUN_DRV_Pos)\n\ti2c.config.SDA.outFunc().Set(0x500)\n\ti2c.config.SDA.pinReg().SetBits(esp.GPIO_PIN_PAD_DRIVER)\n\ti2c.config.SCL.mux().Set(2<<esp.IO_MUX_GPIO0_MCU_SEL_Pos | esp.IO_MUX_GPIO0_FUN_IE | 1<<esp.IO_MUX_GPIO0_FUN_DRV_Pos)\n\ti2c.config.SCL.outFunc().Set(0x500)\n\ti2c.config.SCL.pinReg().SetBits(esp.GPIO_PIN_PAD_DRIVER)\n\n\t// bit-bang a read-NACK in case any device on the bus is in the middle of a write\n\ti2c.config.SCL.Low()\n\ti2c.config.SDA.High()\n\twait()\n\tfor i := 0; i < 9; i++ {\n\t\tif i2c.config.SDA.Get() {\n\t\t\tbreak\n\t\t}\n\t\ti2c.config.SCL.High()\n\t\twait()\n\t\ti2c.config.SCL.Low()\n\t\twait()\n\t}\n\ti2c.config.SDA.Low()\n\ti2c.config.SCL.High()\n\twait()\n\ti2c.config.SDA.High()\n\n\t// initAll contains initClock which contains a reset\n\ti2c.initAll()\n}\n\nfunc wait() {\n\tend := nanotime() + 5_000\n\tfor nanotime() < end {\n\t\t//spin\n\t}\n}\n\ntype i2cCommandType = uint32\ntype i2cAck = uint32\n\nconst (\n\ti2cCMD_RSTART   i2cCommandType = 0 << 11\n\ti2cCMD_WRITE    i2cCommandType = 1<<11 | 1<<8 // WRITE + ack_check_en\n\ti2cCMD_READ     i2cCommandType = 2 << 11\n\ti2cCMD_READLAST i2cCommandType = 2<<11 | 1<<10 // READ + NACK\n\ti2cCMD_STOP     i2cCommandType = 3 << 11\n\ti2cCMD_END      i2cCommandType = 4 << 11\n)\n\ntype i2cCommand struct {\n\tcmd  i2cCommandType\n\tdata []byte\n\thead int\n}\n\n//go:linkname nanotime runtime.nanotime\nfunc nanotime() int64\n\nfunc (i2c *I2C) transmit(addr uint16, cmd []i2cCommand, timeoutMS int) error {\n\tif i2c.Bus.GetSR_BUS_BUSY() == 1 {\n\t\ti2c.resetBus()\n\t}\n\n\tconst intMask = esp.I2C_INT_STATUS_END_DETECT_INT_ST_Msk | esp.I2C_INT_STATUS_TRANS_COMPLETE_INT_ST_Msk | esp.I2C_INT_STATUS_TIME_OUT_INT_ST_Msk | esp.I2C_INT_STATUS_ACK_ERR_INT_ST_Msk | esp.I2C_INT_STATUS_ARBITRATION_LOST_INT_ST_Msk\n\ti2c.Bus.INT_CLR.Set(intMask)\n\ti2c.Bus.INT_ENA.Set(intMask)\n\n\tdefer func() {\n\t\ti2c.Bus.INT_CLR.Set(intMask)\n\t\ti2c.Bus.INT_ENA.Set(0)\n\t}()\n\n\ttimeoutNS := int64(timeoutMS) * 1000000\n\tneedAddress := true\n\tneedRestart := false\n\treadLast := false\n\tvar readTo []byte\n\tfor cmdIdx, reg := 0, &i2c.Bus.COMD0; cmdIdx < len(cmd); {\n\t\tc := &cmd[cmdIdx]\n\n\t\tswitch c.cmd {\n\t\tcase i2cCMD_RSTART:\n\t\t\treg.Set(i2cCMD_RSTART)\n\t\t\treg = nextAddress(reg)\n\t\t\tcmdIdx++\n\n\t\tcase i2cCMD_WRITE:\n\t\t\tcount := 32\n\t\t\tif needAddress {\n\t\t\t\tneedAddress = false\n\t\t\t\ti2c.Bus.SetDATA_FIFO_RDATA((uint32(addr) & 0x7f) << 1)\n\t\t\t\tcount--\n\t\t\t\ti2c.Bus.SLAVE_ADDR.Set(uint32(addr))\n\t\t\t}\n\t\t\tfor ; count > 0 && c.head < len(c.data); count, c.head = count-1, c.head+1 {\n\t\t\t\ti2c.Bus.SetDATA_FIFO_RDATA(uint32(c.data[c.head]))\n\t\t\t}\n\t\t\treg.Set(i2cCMD_WRITE | uint32(32-count))\n\t\t\treg = nextAddress(reg)\n\n\t\t\tif c.head < len(c.data) {\n\t\t\t\treg.Set(i2cCMD_END)\n\t\t\t\treg = nil\n\t\t\t} else {\n\t\t\t\tcmdIdx++\n\t\t\t}\n\t\t\tneedRestart = true\n\n\t\tcase i2cCMD_READ:\n\t\t\tif needAddress {\n\t\t\t\tneedAddress = false\n\t\t\t\ti2c.Bus.SetDATA_FIFO_RDATA((uint32(addr)&0x7f)<<1 | 1)\n\t\t\t\ti2c.Bus.SLAVE_ADDR.Set(uint32(addr))\n\t\t\t\treg.Set(i2cCMD_WRITE | 1)\n\t\t\t\treg = nextAddress(reg)\n\t\t\t}\n\t\t\tif needRestart {\n\t\t\t\t// We need to send RESTART again after i2cCMD_WRITE.\n\t\t\t\treg.Set(i2cCMD_RSTART)\n\n\t\t\t\treg = nextAddress(reg)\n\t\t\t\treg.Set(i2cCMD_WRITE | 1)\n\n\t\t\t\treg = nextAddress(reg)\n\t\t\t\ti2c.Bus.SetDATA_FIFO_RDATA((uint32(addr)&0x7f)<<1 | 1)\n\t\t\t\tneedRestart = false\n\t\t\t}\n\t\t\tcount := 32\n\t\t\tbytes := len(c.data) - c.head\n\t\t\t// Only last byte in sequence must be sent with ACK set to 1 to indicate end of data.\n\t\t\tsplit := bytes <= count\n\t\t\tif split {\n\t\t\t\tbytes--\n\t\t\t}\n\t\t\tif bytes > 32 {\n\t\t\t\tbytes = 32\n\t\t\t}\n\t\t\tif bytes > 0 {\n\t\t\t\treg.Set(i2cCMD_READ | uint32(bytes))\n\t\t\t\treg = nextAddress(reg)\n\t\t\t}\n\n\t\t\tif split {\n\t\t\t\treadLast = true\n\t\t\t\treg.Set(i2cCMD_READLAST | 1)\n\t\t\t\treg = nextAddress(reg)\n\t\t\t\treadTo = c.data[c.head : c.head+bytes+1] // read bytes + 1 last byte\n\t\t\t\tcmdIdx++\n\t\t\t} else {\n\t\t\t\treg.Set(i2cCMD_END)\n\t\t\t\treadTo = c.data[c.head : c.head+bytes]\n\t\t\t\treg = nil\n\t\t\t}\n\n\t\tcase i2cCMD_STOP:\n\t\t\treg.Set(i2cCMD_STOP)\n\t\t\treg = nil\n\t\t\tcmdIdx++\n\t\t}\n\t\tif reg == nil {\n\t\t\t// transmit now\n\t\t\ti2c.Bus.SetCTR_TRANS_START(1)\n\t\t\tend := nanotime() + timeoutNS\n\t\t\tvar mask uint32\n\t\t\tfor mask = i2c.Bus.INT_STATUS.Get(); mask&intMask == 0; mask = i2c.Bus.INT_STATUS.Get() {\n\t\t\t\tif nanotime() > end {\n\t\t\t\t\t// timeout leaves the bus in an undefined state, reset\n\t\t\t\t\ti2c.resetBus()\n\t\t\t\t\tif readTo != nil {\n\t\t\t\t\t\treturn errI2CReadTimeout\n\t\t\t\t\t}\n\t\t\t\t\treturn errI2CWriteTimeout\n\t\t\t\t}\n\t\t\t}\n\t\t\tswitch {\n\t\t\tcase mask&esp.I2C_INT_STATUS_ACK_ERR_INT_ST_Msk != 0 && !readLast:\n\t\t\t\treturn errI2CAckExpected\n\t\t\tcase mask&esp.I2C_INT_STATUS_TIME_OUT_INT_ST_Msk != 0:\n\t\t\t\t// timeout leaves the bus in an undefined state, reset\n\t\t\t\ti2c.resetBus()\n\t\t\t\tif readTo != nil {\n\t\t\t\t\treturn errI2CReadTimeout\n\t\t\t\t}\n\t\t\t\treturn errI2CWriteTimeout\n\t\t\t}\n\t\t\ti2c.Bus.INT_CLR.SetBits(intMask)\n\t\t\tfor i := 0; i < len(readTo); i++ {\n\t\t\t\treadTo[i] = byte(i2c.Bus.GetDATA_FIFO_RDATA() & 0xff)\n\t\t\t\tc.head++\n\t\t\t}\n\t\t\treadTo = nil\n\t\t\treg = &i2c.Bus.COMD0\n\t\t}\n\t}\n\treturn nil\n}\n\n// Tx does a single I2C transaction at the specified address.\n// It clocks out the given address, writes the bytes in w, reads back len(r)\n// bytes and stores them in r, and generates a stop condition on the bus.\nfunc (i2c *I2C) Tx(addr uint16, w, r []byte) (err error) {\n\t// timeout in microseconds.\n\tconst timeout = 40 // 40ms is a reasonable time for a real-time system.\n\n\tcmd := make([]i2cCommand, 0, 8)\n\tcmd = append(cmd, i2cCommand{cmd: i2cCMD_RSTART})\n\tif len(w) > 0 {\n\t\tcmd = append(cmd, i2cCommand{cmd: i2cCMD_WRITE, data: w})\n\t}\n\tif len(r) > 0 {\n\t\tcmd = append(cmd, i2cCommand{cmd: i2cCMD_READ, data: r})\n\t}\n\tcmd = append(cmd, i2cCommand{cmd: i2cCMD_STOP})\n\n\treturn i2c.transmit(addr, cmd, timeout)\n}\n\nfunc (i2c *I2C) SetBaudRate(br uint32) error {\n\treturn errI2CNotImplemented\n}\n\nfunc (p Pin) pinReg() *volatile.Register32 {\n\treturn (*volatile.Register32)(unsafe.Pointer((uintptr(unsafe.Pointer(&esp.GPIO.PIN0)) + uintptr(p)*4)))\n}\n\nfunc nextAddress(reg *volatile.Register32) *volatile.Register32 {\n\treturn (*volatile.Register32)(unsafe.Add(unsafe.Pointer(reg), 4))\n}\n\n// CheckDevice does an empty I2C transaction at the specified address.\n// This can be used to find out if any device with that address is\n// connected, e.g. for enumerating all devices on the bus.\nfunc (i2c *I2C) CheckDevice(addr uint16) bool {\n\t// timeout in microseconds.\n\tconst timeout = 40 // 40ms is a reasonable time for a real-time system.\n\n\tcmd := []i2cCommand{\n\t\t{cmd: i2cCMD_RSTART},\n\t\t{cmd: i2cCMD_WRITE},\n\t\t{cmd: i2cCMD_STOP},\n\t}\n\treturn i2c.transmit(addr, cmd, timeout) == nil\n}\n"
  },
  {
    "path": "src/machine/machine_esp32c3.go",
    "content": "//go:build esp32c3\n\npackage machine\n\nimport (\n\t\"device/esp\"\n\t\"device/riscv\"\n\t\"errors\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n\t\"sync\"\n\t\"unsafe\"\n)\n\nconst deviceName = esp.Device\nconst maxPin = 22\nconst cpuInterruptFromPin = 6\n\n// CPUFrequency returns the current CPU frequency of the chip.\n// Currently it is a fixed frequency but it may allow changing in the future.\nfunc CPUFrequency() uint32 {\n\treturn 160e6 // 160MHz\n}\n\nconst (\n\tPinOutput PinMode = iota\n\tPinInput\n\tPinInputPullup\n\tPinInputPulldown\n)\n\nconst (\n\tGPIO0  Pin = 0\n\tGPIO1  Pin = 1\n\tGPIO2  Pin = 2\n\tGPIO3  Pin = 3\n\tGPIO4  Pin = 4\n\tGPIO5  Pin = 5\n\tGPIO6  Pin = 6\n\tGPIO7  Pin = 7\n\tGPIO8  Pin = 8\n\tGPIO9  Pin = 9\n\tGPIO10 Pin = 10\n\tGPIO11 Pin = 11\n\tGPIO12 Pin = 12\n\tGPIO13 Pin = 13\n\tGPIO14 Pin = 14\n\tGPIO15 Pin = 15\n\tGPIO16 Pin = 16\n\tGPIO17 Pin = 17\n\tGPIO18 Pin = 18\n\tGPIO19 Pin = 19\n\tGPIO20 Pin = 20\n\tGPIO21 Pin = 21\n)\n\ntype PinChange uint8\n\n// Pin change interrupt constants for SetInterrupt.\nconst (\n\tPinRising PinChange = iota + 1\n\tPinFalling\n\tPinToggle\n)\n\n// Configure this pin with the given configuration.\nfunc (p Pin) Configure(config PinConfig) {\n\tif p == NoPin {\n\t\t// This simplifies pin configuration in peripherals such as SPI.\n\t\treturn\n\t}\n\n\tvar muxConfig uint32\n\n\t// Configure this pin as a GPIO pin.\n\tconst function = 1 // function 1 is GPIO for every pin\n\tmuxConfig |= function << esp.IO_MUX_GPIO_MCU_SEL_Pos\n\n\t// Make this pin an input pin (always).\n\tmuxConfig |= esp.IO_MUX_GPIO_FUN_IE\n\n\t// Set drive strength: 0 is lowest, 3 is highest.\n\tmuxConfig |= 2 << esp.IO_MUX_GPIO_FUN_DRV_Pos\n\n\t// Select pull mode.\n\tif config.Mode == PinInputPullup {\n\t\tmuxConfig |= esp.IO_MUX_GPIO_FUN_WPU\n\t} else if config.Mode == PinInputPulldown {\n\t\tmuxConfig |= esp.IO_MUX_GPIO_FUN_WPD\n\t}\n\n\t// Configure the pad with the given IO mux configuration.\n\tp.mux().Set(muxConfig)\n\n\t// Set the output signal to the simple GPIO output.\n\tp.outFunc().Set(0x80)\n\n\tswitch config.Mode {\n\tcase PinOutput:\n\t\t// Set the 'output enable' bit.\n\t\tesp.GPIO.ENABLE_W1TS.Set(1 << p)\n\tcase PinInput, PinInputPullup, PinInputPulldown:\n\t\t// Clear the 'output enable' bit.\n\t\tesp.GPIO.ENABLE_W1TC.Set(1 << p)\n\t}\n}\n\n// outFunc returns the FUNCx_OUT_SEL_CFG register used for configuring the\n// output function selection.\nfunc (p Pin) outFunc() *volatile.Register32 {\n\treturn (*volatile.Register32)(unsafe.Add(unsafe.Pointer(&esp.GPIO.FUNC0_OUT_SEL_CFG), uintptr(p)*4))\n}\n\nfunc (p Pin) pinReg() *volatile.Register32 {\n\treturn (*volatile.Register32)(unsafe.Pointer((uintptr(unsafe.Pointer(&esp.GPIO.PIN0)) + uintptr(p)*4)))\n}\n\n// inFunc returns the FUNCy_IN_SEL_CFG register used for configuring the input\n// function selection.\nfunc inFunc(signal uint32) *volatile.Register32 {\n\treturn (*volatile.Register32)(unsafe.Add(unsafe.Pointer(&esp.GPIO.FUNC0_IN_SEL_CFG), uintptr(signal)*4))\n}\n\n// mux returns the I/O mux configuration register corresponding to the given\n// GPIO pin.\nfunc (p Pin) mux() *volatile.Register32 {\n\treturn (*volatile.Register32)(unsafe.Add(unsafe.Pointer(&esp.IO_MUX.GPIO0), uintptr(p)*4))\n}\n\n// pin returns the PIN register corresponding to the given GPIO pin.\nfunc (p Pin) pin() *volatile.Register32 {\n\treturn (*volatile.Register32)(unsafe.Add(unsafe.Pointer(&esp.GPIO.PIN0), uintptr(p)*4))\n}\n\n// Set the pin to high or low.\n// Warning: only use this on an output pin!\nfunc (p Pin) Set(value bool) {\n\tif value {\n\t\treg, mask := p.portMaskSet()\n\t\treg.Set(mask)\n\t} else {\n\t\treg, mask := p.portMaskClear()\n\t\treg.Set(mask)\n\t}\n}\n\n// Get returns the current value of a GPIO pin when configured as an input or as\n// an output.\nfunc (p Pin) Get() bool {\n\treg := &esp.GPIO.IN\n\treturn (reg.Get()>>p)&1 > 0\n}\n\n// Return the register and mask to enable a given GPIO pin. This can be used to\n// implement bit-banged drivers.\n//\n// Warning: only use this on an output pin!\nfunc (p Pin) PortMaskSet() (*uint32, uint32) {\n\treg, mask := p.portMaskSet()\n\treturn &reg.Reg, mask\n}\n\n// Return the register and mask to disable a given GPIO pin. This can be used to\n// implement bit-banged drivers.\n//\n// Warning: only use this on an output pin!\nfunc (p Pin) PortMaskClear() (*uint32, uint32) {\n\treg, mask := p.portMaskClear()\n\treturn &reg.Reg, mask\n}\n\nfunc (p Pin) portMaskSet() (*volatile.Register32, uint32) {\n\treturn &esp.GPIO.OUT_W1TS, 1 << p\n}\n\nfunc (p Pin) portMaskClear() (*volatile.Register32, uint32) {\n\treturn &esp.GPIO.OUT_W1TC, 1 << p\n}\n\n// SetInterrupt sets an interrupt to be executed when a particular pin changes\n// state. The pin should already be configured as an input, including a pull up\n// or down if no external pull is provided.\n//\n// You can pass a nil func to unset the pin change interrupt. If you do so,\n// the change parameter is ignored and can be set to any value (such as 0).\n// If the pin is already configured with a callback, you must first unset\n// this pins interrupt before you can set a new callback.\nfunc (p Pin) SetInterrupt(change PinChange, callback func(Pin)) (err error) {\n\tif p >= maxPin {\n\t\treturn ErrInvalidInputPin\n\t}\n\n\tif callback == nil {\n\t\t// Disable this pin interrupt\n\t\tp.pin().ClearBits(esp.GPIO_PIN_INT_TYPE_Msk | esp.GPIO_PIN_INT_ENA_Msk)\n\n\t\tif pinCallbacks[p] != nil {\n\t\t\tpinCallbacks[p] = nil\n\t\t}\n\t\treturn nil\n\t}\n\n\tif pinCallbacks[p] != nil {\n\t\t// The pin was already configured.\n\t\t// To properly re-configure a pin, unset it first and set a new\n\t\t// configuration.\n\t\treturn ErrNoPinChangeChannel\n\t}\n\tpinCallbacks[p] = callback\n\n\tonceSetupPinInterrupt.Do(func() {\n\t\terr = setupPinInterrupt()\n\t})\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tp.pin().Set(\n\t\t(p.pin().Get() & ^uint32(esp.GPIO_PIN_INT_TYPE_Msk|esp.GPIO_PIN_INT_ENA_Msk)) |\n\t\t\tuint32(change)<<esp.GPIO_PIN_INT_TYPE_Pos | uint32(1)<<esp.GPIO_PIN_INT_ENA_Pos)\n\n\treturn nil\n}\n\nvar (\n\tpinCallbacks          [maxPin]func(Pin)\n\tonceSetupPinInterrupt sync.Once\n)\n\nfunc setupPinInterrupt() error {\n\tesp.INTERRUPT_CORE0.GPIO_INTERRUPT_PRO_MAP.Set(cpuInterruptFromPin)\n\treturn interrupt.New(cpuInterruptFromPin, func(interrupt.Interrupt) {\n\t\tstatus := esp.GPIO.STATUS.Get()\n\t\tfor i, mask := 0, uint32(1); i < maxPin; i, mask = i+1, mask<<1 {\n\t\t\tif (status&mask) != 0 && pinCallbacks[i] != nil {\n\t\t\t\tpinCallbacks[i](Pin(i))\n\t\t\t}\n\t\t}\n\t\t// clear interrupt bit\n\t\tesp.GPIO.STATUS_W1TC.SetBits(status)\n\t}).Enable()\n}\n\nvar (\n\tDefaultUART = UART0\n\n\tUART0  = &_UART0\n\t_UART0 = UART{Bus: esp.UART0, Buffer: NewRingBuffer()}\n\tUART1  = &_UART1\n\t_UART1 = UART{Bus: esp.UART1, Buffer: NewRingBuffer()}\n\n\tonceUart            = sync.Once{}\n\terrSamePins         = errors.New(\"UART: invalid pin combination\")\n\terrWrongUART        = errors.New(\"UART: unsupported UARTn\")\n\terrWrongBitSize     = errors.New(\"UART: invalid data size\")\n\terrWrongStopBitSize = errors.New(\"UART: invalid bit size\")\n)\n\ntype UART struct {\n\tBus                  *esp.UART_Type\n\tBuffer               *RingBuffer\n\tParityErrorDetected  bool // set when parity error detected\n\tDataErrorDetected    bool // set when data corruption detected\n\tDataOverflowDetected bool // set when data overflow detected in UART FIFO buffer or RingBuffer\n}\n\nconst (\n\tdefaultDataBits = 8\n\tdefaultStopBit  = 1\n\tdefaultParity   = ParityNone\n\n\tuartInterrupts = esp.UART_INT_ENA_RXFIFO_FULL_INT_ENA |\n\t\tesp.UART_INT_ENA_PARITY_ERR_INT_ENA |\n\t\tesp.UART_INT_ENA_FRM_ERR_INT_ENA |\n\t\tesp.UART_INT_ENA_RXFIFO_OVF_INT_ENA |\n\t\tesp.UART_INT_ENA_GLITCH_DET_INT_ENA\n\n\tpplClockFreq = 80e6\n)\n\ntype registerSet struct {\n\tinterruptMapReg  *volatile.Register32\n\tuartClockBitMask uint32\n\tgpioMatrixSignal uint32\n}\n\nfunc (uart *UART) Configure(config UARTConfig) error {\n\tif config.BaudRate == 0 {\n\t\tconfig.BaudRate = 115200\n\t}\n\tif config.TX == config.RX {\n\t\treturn errSamePins\n\t}\n\tswitch {\n\tcase uart.Bus == esp.UART0:\n\t\treturn uart.configure(config, registerSet{\n\t\t\tinterruptMapReg:  &esp.INTERRUPT_CORE0.UART_INTR_MAP,\n\t\t\tuartClockBitMask: esp.SYSTEM_PERIP_CLK_EN0_UART_CLK_EN,\n\t\t\tgpioMatrixSignal: 6,\n\t\t})\n\tcase uart.Bus == esp.UART1:\n\t\treturn uart.configure(config, registerSet{\n\t\t\tinterruptMapReg:  &esp.INTERRUPT_CORE0.UART1_INTR_MAP,\n\t\t\tuartClockBitMask: esp.SYSTEM_PERIP_CLK_EN0_UART1_CLK_EN,\n\t\t\tgpioMatrixSignal: 9,\n\t\t})\n\t}\n\treturn errWrongUART\n}\n\nfunc (uart *UART) configure(config UARTConfig, regs registerSet) error {\n\n\tinitUARTClock(uart.Bus, regs)\n\n\t// - disable TX/RX clock to make sure the UART transmitter or receiver is not at work during configuration\n\tuart.Bus.SetCLK_CONF_TX_SCLK_EN(0)\n\tuart.Bus.SetCLK_CONF_RX_SCLK_EN(0)\n\n\t// Configure static registers (Ref: Configuring URATn Communication)\n\n\t// - default clock source: 1=APB_CLK, 2=FOSC_CLK, 3=XTAL_CLK\n\tuart.Bus.SetCLK_CONF_SCLK_SEL(1)\n\t// reset divisor of the divider via UART_SCLK_DIV_NUM, UART_SCLK_DIV_A, and UART_SCLK_DIV_B\n\tuart.Bus.SetCLK_CONF_SCLK_DIV_NUM(0)\n\tuart.Bus.SetCLK_CONF_SCLK_DIV_A(0)\n\tuart.Bus.SetCLK_CONF_SCLK_DIV_B(0)\n\n\t// - the baud rate\n\tuart.SetBaudRate(config.BaudRate)\n\t// - the data format\n\tuart.SetFormat(defaultDataBits, defaultStopBit, defaultParity)\n\t// - set UART mode\n\tuart.Bus.SetRS485_CONF_RS485_EN(0)\n\tuart.Bus.SetRS485_CONF_RS485TX_RX_EN(0)\n\tuart.Bus.SetRS485_CONF_RS485RXBY_TX_EN(0)\n\tuart.Bus.SetCONF0_IRDA_EN(0)\n\t// - disable hw-flow control\n\tuart.Bus.SetCONF0_TX_FLOW_EN(0)\n\tuart.Bus.SetCONF1_RX_FLOW_EN(0)\n\n\t// synchronize values into Core Clock\n\tuart.Bus.SetID_REG_UPDATE(1)\n\n\tuart.setupPins(config, regs)\n\tuart.configureInterrupt(regs.interruptMapReg)\n\tuart.enableTransmitter()\n\tuart.enableReceiver()\n\n\t// Start TX/RX\n\tuart.Bus.SetCLK_CONF_TX_SCLK_EN(1)\n\tuart.Bus.SetCLK_CONF_RX_SCLK_EN(1)\n\treturn nil\n}\n\nfunc (uart *UART) SetFormat(dataBits, stopBits int, parity UARTParity) error {\n\tif dataBits < 5 {\n\t\treturn errWrongBitSize\n\t}\n\tif stopBits > 1 {\n\t\treturn errWrongStopBitSize\n\t}\n\t// - data length\n\tuart.Bus.SetCONF0_BIT_NUM(uint32(dataBits - 5))\n\t// - stop bit\n\tuart.Bus.SetCONF0_STOP_BIT_NUM(uint32(stopBits))\n\t// - parity check\n\tswitch parity {\n\tcase ParityNone:\n\t\tuart.Bus.SetCONF0_PARITY_EN(0)\n\tcase ParityEven:\n\t\tuart.Bus.SetCONF0_PARITY_EN(1)\n\t\tuart.Bus.SetCONF0_PARITY(0)\n\tcase ParityOdd:\n\t\tuart.Bus.SetCONF0_PARITY_EN(1)\n\t\tuart.Bus.SetCONF0_PARITY(1)\n\t}\n\treturn nil\n}\n\nfunc initUARTClock(bus *esp.UART_Type, regs registerSet) {\n\tuartClock := &esp.SYSTEM.PERIP_CLK_EN0\n\tuartClockReset := &esp.SYSTEM.PERIP_RST_EN0\n\n\t// Initialize/reset URATn (Ref: Initializing URATn)\n\t// - enable the clock for UART RAM\n\tuartClock.SetBits(esp.SYSTEM_PERIP_CLK_EN0_UART_MEM_CLK_EN)\n\t// - enable APB_CLK for UARTn\n\tuartClock.SetBits(regs.uartClockBitMask)\n\t// - reset sequence\n\tuartClockReset.ClearBits(regs.uartClockBitMask)\n\tbus.SetCLK_CONF_RST_CORE(1)\n\tuartClockReset.SetBits(regs.uartClockBitMask)\n\tuartClockReset.ClearBits(regs.uartClockBitMask)\n\tbus.SetCLK_CONF_RST_CORE(0)\n\t// synchronize core register\n\tbus.SetID_REG_UPDATE(0)\n\t// enable RTC clock\n\tesp.RTC_CNTL.SetCLK_CONF_DIG_CLK8M_EN(1)\n\t// wait for Core Clock to ready for configuration\n\tfor bus.GetID_REG_UPDATE() > 0 {\n\t\triscv.Asm(\"nop\")\n\t}\n}\n\nfunc (uart *UART) SetBaudRate(baudRate uint32) {\n\t// based on esp-idf\n\tmax_div := uint32((1 << 12) - 1)\n\tsclk_div := (pplClockFreq + (max_div * baudRate) - 1) / (max_div * baudRate)\n\tclk_div := (pplClockFreq << 4) / (baudRate * sclk_div)\n\tuart.Bus.SetCLKDIV(clk_div >> 4)\n\tuart.Bus.SetCLKDIV_FRAG(clk_div & 0xf)\n\tuart.Bus.SetCLK_CONF_SCLK_DIV_NUM(sclk_div - 1)\n}\n\nfunc (uart *UART) setupPins(config UARTConfig, regs registerSet) {\n\tconfig.RX.Configure(PinConfig{Mode: PinInputPullup})\n\tconfig.TX.Configure(PinConfig{Mode: PinInputPullup})\n\n\t// link TX with GPIO signal X (technical reference manual 5.10) (this is not interrupt signal!)\n\tconfig.TX.outFunc().Set(regs.gpioMatrixSignal)\n\t// link RX with GPIO signal X and route signals via GPIO matrix (GPIO_SIGn_IN_SEL 0x40)\n\tinFunc(regs.gpioMatrixSignal).Set(esp.GPIO_FUNC_IN_SEL_CFG_SEL | uint32(config.RX))\n}\n\nfunc (uart *UART) configureInterrupt(intrMapReg *volatile.Register32) { // Disable all UART interrupts\n\t// Disable all UART interrupts\n\tuart.Bus.INT_ENA.ClearBits(0x0ffff)\n\n\tintrMapReg.Set(7)\n\tonceUart.Do(func() {\n\t\t_ = interrupt.New(7, func(i interrupt.Interrupt) {\n\t\t\tUART0.serveInterrupt(0)\n\t\t\tUART1.serveInterrupt(1)\n\t\t}).Enable()\n\t})\n}\n\nfunc (uart *UART) serveInterrupt(num int) {\n\t// get interrupt status\n\tinterrutFlag := uart.Bus.INT_ST.Get()\n\tif (interrutFlag & uartInterrupts) == 0 {\n\t\treturn\n\t}\n\n\t// block UART interrupts while processing\n\tuart.Bus.INT_ENA.ClearBits(uartInterrupts)\n\n\tif interrutFlag&esp.UART_INT_ENA_RXFIFO_FULL_INT_ENA > 0 {\n\t\tfor uart.Bus.GetSTATUS_RXFIFO_CNT() > 0 {\n\t\t\tb := uart.Bus.GetFIFO_RXFIFO_RD_BYTE()\n\t\t\tif !uart.Buffer.Put(byte(b & 0xff)) {\n\t\t\t\tuart.DataOverflowDetected = true\n\t\t\t}\n\t\t}\n\t}\n\tif interrutFlag&esp.UART_INT_ENA_PARITY_ERR_INT_ENA > 0 {\n\t\tuart.ParityErrorDetected = true\n\t}\n\tif 0 != interrutFlag&esp.UART_INT_ENA_FRM_ERR_INT_ENA {\n\t\tuart.DataErrorDetected = true\n\t}\n\tif 0 != interrutFlag&esp.UART_INT_ENA_RXFIFO_OVF_INT_ENA {\n\t\tuart.DataOverflowDetected = true\n\t}\n\tif 0 != interrutFlag&esp.UART_INT_ENA_GLITCH_DET_INT_ENA {\n\t\tuart.DataErrorDetected = true\n\t}\n\n\t// Clear the UART interrupt status\n\tuart.Bus.INT_CLR.SetBits(interrutFlag)\n\tuart.Bus.INT_CLR.ClearBits(interrutFlag)\n\t// Enable interrupts\n\tuart.Bus.INT_ENA.Set(uartInterrupts)\n}\n\nconst uart_empty_thresh_default = 10\n\nfunc (uart *UART) enableTransmitter() {\n\tuart.Bus.SetCONF0_TXFIFO_RST(1)\n\tuart.Bus.SetCONF0_TXFIFO_RST(0)\n\t// TXINFO empty threshold is when txfifo_empty_int interrupt produced after the amount of data in Tx-FIFO is less than this register value.\n\tuart.Bus.SetCONF1_TXFIFO_EMPTY_THRHD(uart_empty_thresh_default)\n\t// we are not using interrupt on TX since write we are waiting for FIFO to have space.\n\t// uart.Bus.INT_ENA.SetBits(esp.UART_INT_ENA_TXFIFO_EMPTY_INT_ENA)\n}\n\nfunc (uart *UART) enableReceiver() {\n\tuart.Bus.SetCONF0_RXFIFO_RST(1)\n\tuart.Bus.SetCONF0_RXFIFO_RST(0)\n\t// using value 1 so that we can start populate ring buffer with data as we get it\n\tuart.Bus.SetCONF1_RXFIFO_FULL_THRHD(1)\n\t// enable interrupts for:\n\tuart.Bus.SetINT_ENA_RXFIFO_FULL_INT_ENA(1)\n\tuart.Bus.SetINT_ENA_FRM_ERR_INT_ENA(1)\n\tuart.Bus.SetINT_ENA_PARITY_ERR_INT_ENA(1)\n\tuart.Bus.SetINT_ENA_GLITCH_DET_INT_ENA(1)\n\tuart.Bus.SetINT_ENA_RXFIFO_OVF_INT_ENA(1)\n}\n\nfunc (uart *UART) writeByte(b byte) error {\n\tfor (uart.Bus.STATUS.Get()&esp.UART_STATUS_TXFIFO_CNT_Msk)>>esp.UART_STATUS_TXFIFO_CNT_Pos >= 128 {\n\t\t// Read UART_TXFIFO_CNT from the status register, which indicates how\n\t\t// many bytes there are in the transmit buffer. Wait until there are\n\t\t// less than 128 bytes in this buffer (the default buffer size).\n\t}\n\tuart.Bus.FIFO.Set(uint32(b))\n\treturn nil\n}\n\nfunc (uart *UART) flush() {}\n\ntype Serialer interface {\n\tWriteByte(c byte) error\n\tWrite(data []byte) (n int, err error)\n\tConfigure(config UARTConfig) error\n\tBuffered() int\n\tReadByte() (byte, error)\n\tDTR() bool\n\tRTS() bool\n}\n\nfunc initUSB() {\n\t// nothing to do here\n}\n\n// USB Serial/JTAG Controller\n// See esp32-c3_technical_reference_manual_en.pdf\n// pg. 736\ntype USB_DEVICE struct {\n\tBus *esp.USB_DEVICE_Type\n}\n\nvar (\n\t_USBCDC = &USB_DEVICE{\n\t\tBus: esp.USB_DEVICE,\n\t}\n\n\tUSBCDC Serialer = _USBCDC\n)\n\nvar (\n\terrUSBWrongSize            = errors.New(\"USB: invalid write size\")\n\terrUSBCouldNotWriteAllData = errors.New(\"USB: could not write all data\")\n\terrUSBBufferEmpty          = errors.New(\"USB: read buffer empty\")\n)\n\nfunc (usbdev *USB_DEVICE) Configure(config UARTConfig) error {\n\treturn nil\n}\n\nfunc (usbdev *USB_DEVICE) WriteByte(c byte) error {\n\tif usbdev.Bus.GetEP1_CONF_SERIAL_IN_EP_DATA_FREE() == 0 {\n\t\treturn errUSBCouldNotWriteAllData\n\t}\n\n\tusbdev.Bus.SetEP1_RDWR_BYTE(uint32(c))\n\tusbdev.flush()\n\n\treturn nil\n}\n\nfunc (usbdev *USB_DEVICE) Write(data []byte) (n int, err error) {\n\tif len(data) == 0 || len(data) > 64 {\n\t\treturn 0, errUSBWrongSize\n\t}\n\n\tfor i, c := range data {\n\t\tif usbdev.Bus.GetEP1_CONF_SERIAL_IN_EP_DATA_FREE() == 0 {\n\t\t\tif i > 0 {\n\t\t\t\tusbdev.flush()\n\t\t\t}\n\n\t\t\treturn i, errUSBCouldNotWriteAllData\n\t\t}\n\t\tusbdev.Bus.SetEP1_RDWR_BYTE(uint32(c))\n\t}\n\n\tusbdev.flush()\n\treturn len(data), nil\n}\n\nfunc (usbdev *USB_DEVICE) Buffered() int {\n\treturn int(usbdev.Bus.GetEP1_CONF_SERIAL_OUT_EP_DATA_AVAIL())\n}\n\nfunc (usbdev *USB_DEVICE) ReadByte() (byte, error) {\n\tif usbdev.Bus.GetEP1_CONF_SERIAL_OUT_EP_DATA_AVAIL() != 0 {\n\t\treturn byte(usbdev.Bus.GetEP1_RDWR_BYTE()), nil\n\t}\n\n\treturn 0, nil\n}\n\nfunc (usbdev *USB_DEVICE) DTR() bool {\n\treturn false\n}\n\nfunc (usbdev *USB_DEVICE) RTS() bool {\n\treturn false\n}\n\nfunc (usbdev *USB_DEVICE) flush() {\n\tusbdev.Bus.SetEP1_CONF_WR_DONE(1)\n\tfor usbdev.Bus.GetEP1_CONF_SERIAL_IN_EP_DATA_FREE() == 0 {\n\t}\n}\n\n// GetRNG returns 32-bit random numbers using the ESP32-C3 true random number generator,\n// Random numbers are generated based on the thermal noise in the system and the\n// asynchronous clock mismatch.\n// For maximum entropy also make sure that the SAR_ADC is enabled.\n// See esp32-c3_technical_reference_manual_en.pdf p.524\nfunc GetRNG() (ret uint32, err error) {\n\t// ensure ADC clock is initialized\n\tinitADCClock()\n\n\t// ensure fast RTC clock is enabled\n\tif esp.RTC_CNTL.GetCLK_CONF_DIG_CLK8M_EN() == 0 {\n\t\tesp.RTC_CNTL.SetCLK_CONF_DIG_CLK8M_EN(1)\n\t}\n\n\treturn esp.APB_CTRL.GetRND_DATA(), nil\n}\n\nfunc initADCClock() {\n\tif esp.APB_SARADC.GetCLKM_CONF_CLK_EN() == 1 {\n\t\treturn\n\t}\n\n\t// only support ADC_CTRL_CLK set to 1\n\tesp.APB_SARADC.SetCLKM_CONF_CLK_SEL(1)\n\n\tesp.APB_SARADC.SetCTRL_SARADC_SAR_CLK_GATED(1)\n\n\tesp.APB_SARADC.SetCLKM_CONF_CLKM_DIV_NUM(15)\n\tesp.APB_SARADC.SetCLKM_CONF_CLKM_DIV_B(1)\n\tesp.APB_SARADC.SetCLKM_CONF_CLKM_DIV_A(0)\n\n\tesp.APB_SARADC.SetCTRL_SARADC_SAR_CLK_DIV(1)\n\tesp.APB_SARADC.SetCLKM_CONF_CLK_EN(1)\n}\n"
  },
  {
    "path": "src/machine/machine_esp32c3_i2c.go",
    "content": "//go:build esp32c3 && !m5stamp_c3\n\npackage machine\n\nimport (\n\t\"device/esp\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nvar (\n\tI2C0 = &I2C{}\n)\n\ntype I2C struct{}\n\n// I2CConfig is used to store config info for I2C.\ntype I2CConfig struct {\n\tFrequency uint32 // in Hz\n\tSCL       Pin\n\tSDA       Pin\n}\n\nconst (\n\tclkXTAL               = 0\n\tclkFOSC               = 1\n\tclkXTALFrequency      = uint32(40e6)\n\tclkFOSCFrequency      = uint32(17.5e6)\n\ti2cClkSourceFrequency = clkXTALFrequency\n\ti2cClkSource          = clkXTAL\n)\n\nfunc (i2c *I2C) Configure(config I2CConfig) error {\n\tif config.Frequency == 0 {\n\t\tconfig.Frequency = 400 * KHz\n\t}\n\tif config.SCL == 0 {\n\t\tconfig.SCL = SCL_PIN\n\t}\n\tif config.SDA == 0 {\n\t\tconfig.SDA = SDA_PIN\n\t}\n\n\ti2c.initClock(config)\n\ti2c.initNoiseFilter()\n\ti2c.initPins(config)\n\ti2c.initFrequency(config)\n\ti2c.startMaster()\n\treturn nil\n}\n\n//go:inline\nfunc (i2c *I2C) initClock(config I2CConfig) {\n\t// reset I2C clock\n\tesp.SYSTEM.SetPERIP_RST_EN0_I2C_EXT0_RST(1)\n\tesp.SYSTEM.SetPERIP_CLK_EN0_I2C_EXT0_CLK_EN(1)\n\tesp.SYSTEM.SetPERIP_RST_EN0_I2C_EXT0_RST(0)\n\t// disable interrupts\n\tesp.I2C0.INT_ENA.ClearBits(0x3fff)\n\tesp.I2C0.INT_CLR.ClearBits(0x3fff)\n\n\tesp.I2C0.SetCLK_CONF_SCLK_SEL(i2cClkSource)\n\tesp.I2C0.SetCLK_CONF_SCLK_ACTIVE(1)\n\tesp.I2C0.SetCLK_CONF_SCLK_DIV_NUM(i2cClkSourceFrequency / (config.Frequency * 1024))\n\tesp.I2C0.SetCTR_CLK_EN(1)\n}\n\n//go:inline\nfunc (i2c *I2C) initNoiseFilter() {\n\tesp.I2C0.FILTER_CFG.Set(0x377)\n}\n\n//go:inline\nfunc (i2c *I2C) initPins(config I2CConfig) {\n\tvar muxConfig uint32\n\tconst function = 1 // function 1 is just GPIO\n\n\t// SDA\n\tmuxConfig = function << esp.IO_MUX_GPIO_MCU_SEL_Pos\n\t// Make this pin an input pin (always).\n\tmuxConfig |= esp.IO_MUX_GPIO_FUN_IE\n\t// Set drive strength: 0 is lowest, 3 is highest.\n\tmuxConfig |= 1 << esp.IO_MUX_GPIO_FUN_DRV_Pos\n\tconfig.SDA.mux().Set(muxConfig)\n\tconfig.SDA.outFunc().Set(54)\n\tinFunc(54).Set(uint32(esp.GPIO_FUNC_IN_SEL_CFG_SEL | config.SDA))\n\tconfig.SDA.Set(true)\n\t// Configure the pad with the given IO mux configuration.\n\tconfig.SDA.pinReg().SetBits(esp.GPIO_PIN_PAD_DRIVER)\n\n\tesp.GPIO.ENABLE.SetBits(1 << int(config.SDA))\n\tesp.I2C0.SetCTR_SDA_FORCE_OUT(1)\n\n\t// SCL\n\tmuxConfig = function << esp.IO_MUX_GPIO_MCU_SEL_Pos\n\t// Make this pin an input pin (always).\n\tmuxConfig |= esp.IO_MUX_GPIO_FUN_IE\n\t// Set drive strength: 0 is lowest, 3 is highest.\n\tmuxConfig |= 1 << esp.IO_MUX_GPIO_FUN_DRV_Pos\n\tconfig.SCL.mux().Set(muxConfig)\n\tconfig.SCL.outFunc().Set(53)\n\tinFunc(53).Set(uint32(config.SCL))\n\tconfig.SCL.Set(true)\n\t// Configure the pad with the given IO mux configuration.\n\tconfig.SCL.pinReg().SetBits(esp.GPIO_PIN_PAD_DRIVER)\n\n\tesp.GPIO.ENABLE.SetBits(1 << int(config.SCL))\n\tesp.I2C0.SetCTR_SCL_FORCE_OUT(1)\n}\n\n//go:inline\nfunc (i2c *I2C) initFrequency(config I2CConfig) {\n\n\tclkmDiv := i2cClkSourceFrequency/(config.Frequency*1024) + 1\n\tsclkFreq := i2cClkSourceFrequency / clkmDiv\n\thalfCycle := sclkFreq / config.Frequency / 2\n\t//SCL\n\tsclLow := halfCycle\n\tsclWaitHigh := uint32(0)\n\tif config.Frequency > 50000 {\n\t\tsclWaitHigh = halfCycle / 8 // compensate the time when freq > 50K\n\t}\n\tsclHigh := halfCycle - sclWaitHigh\n\t// SDA\n\tsdaHold := halfCycle / 4\n\tsda_sample := halfCycle / 2\n\tsetup := halfCycle\n\thold := halfCycle\n\n\tesp.I2C0.SetSCL_LOW_PERIOD(sclLow - 1)\n\tesp.I2C0.SetSCL_HIGH_PERIOD(sclHigh)\n\tesp.I2C0.SetSCL_HIGH_PERIOD_SCL_WAIT_HIGH_PERIOD(25)\n\tesp.I2C0.SetSCL_RSTART_SETUP_TIME(setup)\n\tesp.I2C0.SetSCL_STOP_SETUP_TIME(setup)\n\tesp.I2C0.SetSCL_START_HOLD_TIME(hold - 1)\n\tesp.I2C0.SetSCL_STOP_HOLD_TIME(hold - 1)\n\tesp.I2C0.SetSDA_SAMPLE_TIME(sda_sample)\n\tesp.I2C0.SetSDA_HOLD_TIME(sdaHold)\n}\n\n//go:inline\nfunc (i2c *I2C) startMaster() {\n\t// FIFO mode for data\n\tesp.I2C0.SetFIFO_CONF_NONFIFO_EN(0)\n\t// Reset TX & RX buffers\n\tesp.I2C0.SetFIFO_CONF_RX_FIFO_RST(1)\n\tesp.I2C0.SetFIFO_CONF_RX_FIFO_RST(0)\n\tesp.I2C0.SetFIFO_CONF_TX_FIFO_RST(1)\n\tesp.I2C0.SetFIFO_CONF_TX_FIFO_RST(0)\n\t// set timeout value\n\tesp.I2C0.TO.Set(0x10)\n\t// enable master mode\n\tesp.I2C0.CTR.Set(0x113)\n\tesp.I2C0.SetCTR_CONF_UPGATE(1)\n\tresetMaster()\n}\n\n//go:inline\nfunc resetMaster() {\n\t// reset FSM\n\tesp.I2C0.SetCTR_FSM_RST(1)\n\t// clear the bus\n\tesp.I2C0.SetSCL_SP_CONF_SCL_RST_SLV_NUM(9)\n\tesp.I2C0.SetSCL_SP_CONF_SCL_RST_SLV_EN(1)\n\tesp.I2C0.SetSCL_STRETCH_CONF_SLAVE_SCL_STRETCH_EN(1)\n\tesp.I2C0.SetCTR_CONF_UPGATE(1)\n\tesp.I2C0.FILTER_CFG.Set(0x377)\n\t// wait for SCL_RST_SLV_EN\n\tfor esp.I2C0.GetSCL_SP_CONF_SCL_RST_SLV_EN() != 0 {\n\t}\n\tesp.I2C0.SetSCL_SP_CONF_SCL_RST_SLV_NUM(0)\n}\n\ntype i2cCommandType = uint32\ntype i2cAck = uint32\n\nconst (\n\ti2cCMD_RSTART   i2cCommandType = 6 << 11\n\ti2cCMD_WRITE    i2cCommandType = 1<<11 | 1<<8 // WRITE + ack_check_en\n\ti2cCMD_READ     i2cCommandType = 3<<11 | 1<<8 // READ + ack_check_en\n\ti2cCMD_READLAST i2cCommandType = 3<<11 | 5<<8 // READ + ack_check_en + NACK\n\ti2cCMD_STOP     i2cCommandType = 2 << 11\n\ti2cCMD_END      i2cCommandType = 4 << 11\n)\n\ntype i2cCommand struct {\n\tcmd  i2cCommandType\n\tdata []byte\n\thead int\n}\n\n//go:linkname nanotime runtime.nanotime\nfunc nanotime() int64\n\nfunc (i2c *I2C) transmit(addr uint16, cmd []i2cCommand, timeoutMS int) error {\n\tconst intMask = esp.I2C_INT_STATUS_END_DETECT_INT_ST_Msk | esp.I2C_INT_STATUS_TRANS_COMPLETE_INT_ST_Msk | esp.I2C_INT_STATUS_TIME_OUT_INT_ST_Msk | esp.I2C_INT_STATUS_NACK_INT_ST_Msk\n\tesp.I2C0.INT_CLR.SetBits(intMask)\n\tesp.I2C0.INT_ENA.SetBits(intMask)\n\tesp.I2C0.SetCTR_CONF_UPGATE(1)\n\n\tdefer func() {\n\t\tesp.I2C0.INT_CLR.SetBits(intMask)\n\t\tesp.I2C0.INT_ENA.ClearBits(intMask)\n\t}()\n\n\ttimeoutNS := int64(timeoutMS) * 1000000\n\tneedAddress := true\n\tneedRestart := false\n\treadLast := false\n\tvar readTo []byte\n\tfor cmdIdx, reg := 0, &esp.I2C0.COMD0; cmdIdx < len(cmd); {\n\t\tc := &cmd[cmdIdx]\n\n\t\tswitch c.cmd {\n\t\tcase i2cCMD_RSTART:\n\t\t\treg.Set(i2cCMD_RSTART)\n\t\t\treg = nextAddress(reg)\n\t\t\tcmdIdx++\n\n\t\tcase i2cCMD_WRITE:\n\t\t\tcount := 32\n\t\t\tif needAddress {\n\t\t\t\tneedAddress = false\n\t\t\t\tesp.I2C0.SetDATA_FIFO_RDATA((uint32(addr) & 0x7f) << 1)\n\t\t\t\tcount--\n\t\t\t\tesp.I2C0.SLAVE_ADDR.Set(uint32(addr))\n\t\t\t\tesp.I2C0.SetCTR_CONF_UPGATE(1)\n\t\t\t}\n\t\t\tfor ; count > 0 && c.head < len(c.data); count, c.head = count-1, c.head+1 {\n\t\t\t\tesp.I2C0.SetDATA_FIFO_RDATA(uint32(c.data[c.head]))\n\t\t\t}\n\t\t\treg.Set(i2cCMD_WRITE | uint32(32-count))\n\t\t\treg = nextAddress(reg)\n\n\t\t\tif c.head < len(c.data) {\n\t\t\t\treg.Set(i2cCMD_END)\n\t\t\t\treg = nil\n\t\t\t} else {\n\t\t\t\tcmdIdx++\n\t\t\t}\n\t\t\tneedRestart = true\n\n\t\tcase i2cCMD_READ:\n\t\t\tif needAddress {\n\t\t\t\tneedAddress = false\n\t\t\t\tesp.I2C0.SetDATA_FIFO_RDATA((uint32(addr)&0x7f)<<1 | 1)\n\t\t\t\tesp.I2C0.SLAVE_ADDR.Set(uint32(addr))\n\t\t\t\treg.Set(i2cCMD_WRITE | 1)\n\t\t\t\treg = nextAddress(reg)\n\t\t\t}\n\t\t\tif needRestart {\n\t\t\t\t// We need to send RESTART again after i2cCMD_WRITE.\n\t\t\t\treg.Set(i2cCMD_RSTART)\n\n\t\t\t\treg = nextAddress(reg)\n\t\t\t\treg.Set(i2cCMD_WRITE | 1)\n\n\t\t\t\treg = nextAddress(reg)\n\t\t\t\tesp.I2C0.SetDATA_FIFO_RDATA((uint32(addr)&0x7f)<<1 | 1)\n\t\t\t\tneedRestart = false\n\t\t\t}\n\t\t\tcount := 32\n\t\t\tbytes := len(c.data) - c.head\n\t\t\t// Only last byte in sequence must be sent with ACK set to 1 to indicate end of data.\n\t\t\tsplit := bytes <= count\n\t\t\tif split {\n\t\t\t\tbytes--\n\t\t\t}\n\t\t\tif bytes > 32 {\n\t\t\t\tbytes = 32\n\t\t\t}\n\t\t\treg.Set(i2cCMD_READ | uint32(bytes))\n\t\t\treg = nextAddress(reg)\n\n\t\t\tif split {\n\t\t\t\treadLast = true\n\t\t\t\treg.Set(i2cCMD_READLAST | 1)\n\t\t\t\treg = nextAddress(reg)\n\t\t\t\treadTo = c.data[c.head : c.head+bytes+1] // read bytes + 1 last byte\n\t\t\t\tcmdIdx++\n\t\t\t} else {\n\t\t\t\treg.Set(i2cCMD_END)\n\t\t\t\treadTo = c.data[c.head : c.head+bytes]\n\t\t\t\treg = nil\n\t\t\t}\n\n\t\tcase i2cCMD_STOP:\n\t\t\treg.Set(i2cCMD_STOP)\n\t\t\treg = nil\n\t\t\tcmdIdx++\n\t\t}\n\t\tif reg == nil {\n\t\t\t// transmit now\n\t\t\tesp.I2C0.SetCTR_CONF_UPGATE(1)\n\t\t\tesp.I2C0.SetCTR_TRANS_START(1)\n\t\t\tend := nanotime() + timeoutNS\n\t\t\tvar mask uint32\n\t\t\tfor mask = esp.I2C0.INT_STATUS.Get(); mask&intMask == 0; mask = esp.I2C0.INT_STATUS.Get() {\n\t\t\t\tif nanotime() > end {\n\t\t\t\t\tif readTo != nil {\n\t\t\t\t\t\treturn errI2CReadTimeout\n\t\t\t\t\t}\n\t\t\t\t\treturn errI2CWriteTimeout\n\t\t\t\t}\n\t\t\t}\n\t\t\tswitch {\n\t\t\tcase mask&esp.I2C_INT_STATUS_NACK_INT_ST_Msk != 0 && !readLast:\n\t\t\t\treturn errI2CAckExpected\n\t\t\tcase mask&esp.I2C_INT_STATUS_TIME_OUT_INT_ST_Msk != 0:\n\t\t\t\tif readTo != nil {\n\t\t\t\t\treturn errI2CReadTimeout\n\t\t\t\t}\n\t\t\t\treturn errI2CWriteTimeout\n\t\t\t}\n\t\t\tesp.I2C0.INT_CLR.SetBits(intMask)\n\t\t\tfor i := 0; i < len(readTo); i++ {\n\t\t\t\treadTo[i] = byte(esp.I2C0.GetDATA_FIFO_RDATA() & 0xff)\n\t\t\t\tc.head++\n\t\t\t}\n\t\t\treadTo = nil\n\t\t\treg = &esp.I2C0.COMD0\n\t\t}\n\t}\n\treturn nil\n}\n\n// Tx does a single I2C transaction at the specified address.\n// It clocks out the given address, writes the bytes in w, reads back len(r)\n// bytes and stores them in r, and generates a stop condition on the bus.\nfunc (i2c *I2C) Tx(addr uint16, w, r []byte) (err error) {\n\t// timeout in microseconds.\n\tconst timeout = 40 // 40ms is a reasonable time for a real-time system.\n\n\tcmd := make([]i2cCommand, 0, 8)\n\tcmd = append(cmd, i2cCommand{cmd: i2cCMD_RSTART})\n\tif len(w) > 0 {\n\t\tcmd = append(cmd, i2cCommand{cmd: i2cCMD_WRITE, data: w})\n\t}\n\tif len(r) > 0 {\n\t\tcmd = append(cmd, i2cCommand{cmd: i2cCMD_READ, data: r})\n\t}\n\tcmd = append(cmd, i2cCommand{cmd: i2cCMD_STOP})\n\n\treturn i2c.transmit(addr, cmd, timeout)\n}\n\nfunc (i2c *I2C) SetBaudRate(br uint32) error {\n\treturn nil\n}\n\nfunc nextAddress(reg *volatile.Register32) *volatile.Register32 {\n\treturn (*volatile.Register32)(unsafe.Add(unsafe.Pointer(reg), 4))\n}\n"
  },
  {
    "path": "src/machine/machine_esp32c3_spi.go",
    "content": "//go:build esp32c3\n\npackage machine\n\n// On the C3 variant, SPI2 is a general purpose SPI controller. SPI0 and SPI1\n// are used internally to access the ESP32-C3’s attached flash memory. Due to\n// different registers between SPI2 and the other SPI ports, this driver\n// currently supports only the the general purpose FSPI SPI2 controller.\n// https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-reference/peripherals/spi_master.html\n\nimport (\n\t\"device/esp\"\n\t\"errors\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nconst (\n\tSPI_MODE0 = uint8(0)\n\tSPI_MODE1 = uint8(1)\n\tSPI_MODE2 = uint8(2)\n\tSPI_MODE3 = uint8(3)\n\n\tFSPICLK_IN_IDX  = uint32(63)\n\tFSPICLK_OUT_IDX = uint32(63)\n\tFSPIQ_IN_IDX    = uint32(64)\n\tFSPIQ_OUT_IDX   = uint32(64)\n\tFSPID_IN_IDX    = uint32(65)\n\tFSPID_OUT_IDX   = uint32(65)\n\tFSPIHD_IN_IDX   = uint32(66)\n\tFSPIHD_OUT_IDX  = uint32(66)\n\tFSPIWP_IN_IDX   = uint32(67)\n\tFSPIWP_OUT_IDX  = uint32(67)\n\tFSPICS0_IN_IDX  = uint32(68)\n\tFSPICS0_OUT_IDX = uint32(68)\n\tFSPICS1_OUT_IDX = uint32(69)\n\tFSPICS2_OUT_IDX = uint32(70)\n\tFSPICS3_OUT_IDX = uint32(71)\n\tFSPICS4_OUT_IDX = uint32(72)\n\tFSPICS5_OUT_IDX = uint32(73)\n)\n\nvar (\n\tErrInvalidSPIBus  = errors.New(\"machine: SPI bus is invalid\")\n\tErrInvalidSPIMode = errors.New(\"machine: SPI mode is invalid\")\n)\n\n// Serial Peripheral Interface on the ESP32-C3.\ntype SPI struct {\n\tBus *esp.SPI2_Type\n}\n\nvar (\n\t// SPI0 and SPI1 are reserved for use by the caching system etc.\n\tSPI2 = &SPI{esp.SPI2}\n)\n\n// SPIConfig is used to store config info for SPI.\ntype SPIConfig struct {\n\tFrequency uint32\n\tSCK       Pin   // Serial Clock\n\tSDO       Pin   // Serial Data Out (MOSI)\n\tSDI       Pin   // Serial Data In  (MISO)\n\tCS        Pin   // Chip Select (optional)\n\tLSBFirst  bool  // MSB is default\n\tMode      uint8 // SPI_MODE0 is default\n}\n\n// Compute the SPI bus frequency from the CPU frequency.\nfunc freqToClockDiv(hz uint32) uint32 {\n\tfcpu := CPUFrequency()\n\tif hz >= fcpu { // maximum frequency\n\t\treturn 1 << 31\n\t}\n\tif hz < (fcpu / (16 * 64)) { // minimum frequency\n\t\treturn 15<<18 | 63<<12 | 31<<6 | 63 // pre=15, n=63\n\t}\n\n\t// iterate looking for an exact match\n\t// or iterate all 16 prescaler options\n\t// looking for the smallest error\n\tvar bestPre, bestN, bestErr uint32\n\tbestN = 1\n\tbestErr = 0xffffffff\n\tq := uint32(float32(pplClockFreq)/float32(hz) + float32(0.5))\n\tfor p := uint32(0); p < 16; p++ {\n\t\tn := q/(p+1) - 1\n\t\tif n < 1 { // prescaler became too large, stop enum\n\t\t\tbreak\n\t\t}\n\t\tif n > 63 { // prescaler too small, skip to next\n\t\t\tcontinue\n\t\t}\n\n\t\tfreq := fcpu / ((p + 1) * (n + 1))\n\t\tif freq == hz { // exact match\n\t\t\treturn p<<18 | n<<12 | (n/2)<<6 | n\n\t\t}\n\n\t\tvar err uint32\n\t\tif freq < hz {\n\t\t\terr = hz - freq\n\t\t} else {\n\t\t\terr = freq - hz\n\t\t}\n\t\tif err < bestErr {\n\t\t\tbestErr = err\n\t\t\tbestPre = p\n\t\t\tbestN = n\n\t\t}\n\t}\n\n\treturn bestPre<<18 | bestN<<12 | (bestN/2)<<6 | bestN\n}\n\n// Configure and make the SPI peripheral ready to use.\nfunc (spi *SPI) Configure(config SPIConfig) error {\n\t// right now this is only setup to work for the esp32c3 spi2 bus\n\tif spi.Bus != esp.SPI2 {\n\t\treturn ErrInvalidSPIBus\n\t}\n\n\t// periph module reset\n\tesp.SYSTEM.SetPERIP_RST_EN0_SPI2_RST(1)\n\tesp.SYSTEM.SetPERIP_RST_EN0_SPI2_RST(0)\n\n\t// periph module enable\n\tesp.SYSTEM.SetPERIP_CLK_EN0_SPI2_CLK_EN(1)\n\tesp.SYSTEM.SetPERIP_RST_EN0_SPI2_RST(0)\n\n\t// init the spi2 bus\n\tspi.Bus.SLAVE.Set(0)\n\tspi.Bus.MISC.Set(0)\n\tspi.Bus.USER.Set(0)\n\tspi.Bus.USER1.Set(0)\n\tspi.Bus.CTRL.Set(0)\n\tspi.Bus.CLK_GATE.Set(0)\n\tspi.Bus.DMA_CONF.Set(0)\n\tspi.Bus.SetDMA_CONF_RX_AFIFO_RST(1)\n\tspi.Bus.SetDMA_CONF_BUF_AFIFO_RST(1)\n\tspi.Bus.CLOCK.Set(0)\n\n\t// clear data buf\n\tspi.Bus.SetW0(0)\n\tspi.Bus.SetW1(0)\n\tspi.Bus.SetW2(0)\n\tspi.Bus.SetW3(0)\n\tspi.Bus.SetW4(0)\n\tspi.Bus.SetW5(0)\n\tspi.Bus.SetW6(0)\n\tspi.Bus.SetW7(0)\n\tspi.Bus.SetW8(0)\n\tspi.Bus.SetW9(0)\n\tspi.Bus.SetW10(0)\n\tspi.Bus.SetW11(0)\n\tspi.Bus.SetW12(0)\n\tspi.Bus.SetW13(0)\n\tspi.Bus.SetW14(0)\n\tspi.Bus.SetW15(0)\n\n\t// start the spi2 bus\n\tspi.Bus.SetCLK_GATE_CLK_EN(1)\n\tspi.Bus.SetCLK_GATE_MST_CLK_SEL(1)\n\tspi.Bus.SetCLK_GATE_MST_CLK_ACTIVE(1)\n\tspi.Bus.SetDMA_CONF_SLV_TX_SEG_TRANS_CLR_EN(1)\n\tspi.Bus.SetDMA_CONF_SLV_RX_SEG_TRANS_CLR_EN(1)\n\tspi.Bus.SetDMA_CONF_DMA_SLV_SEG_TRANS_EN(0)\n\tspi.Bus.SetUSER_USR_MOSI(1)\n\tspi.Bus.SetUSER_USR_MISO(1)\n\tspi.Bus.SetUSER_DOUTDIN(1)\n\n\t// set spi2 data mode\n\tswitch config.Mode {\n\tcase SPI_MODE0:\n\t\tspi.Bus.SetMISC_CK_IDLE_EDGE(0)\n\t\tspi.Bus.SetUSER_CK_OUT_EDGE(0)\n\tcase SPI_MODE1:\n\t\tspi.Bus.SetMISC_CK_IDLE_EDGE(0)\n\t\tspi.Bus.SetUSER_CK_OUT_EDGE(1)\n\tcase SPI_MODE2:\n\t\tspi.Bus.SetMISC_CK_IDLE_EDGE(1)\n\t\tspi.Bus.SetUSER_CK_OUT_EDGE(1)\n\tcase SPI_MODE3:\n\t\tspi.Bus.SetMISC_CK_IDLE_EDGE(1)\n\t\tspi.Bus.SetUSER_CK_OUT_EDGE(0)\n\tdefault:\n\t\treturn ErrInvalidSPIMode\n\t}\n\n\t// set spi2 bit order\n\tif config.LSBFirst {\n\t\tspi.Bus.SetCTRL_WR_BIT_ORDER(1) // LSB first\n\t\tspi.Bus.SetCTRL_RD_BIT_ORDER(1)\n\t} else {\n\t\tspi.Bus.SetCTRL_WR_BIT_ORDER(0) // MSB first\n\t\tspi.Bus.SetCTRL_RD_BIT_ORDER(0)\n\t}\n\n\t// configure SPI bus clock\n\tspi.Bus.CLOCK.Set(freqToClockDiv(config.Frequency))\n\n\t// configure esp32c3 gpio pin matrix\n\tconfig.SDI.Configure(PinConfig{Mode: PinInput})\n\tinFunc(FSPIQ_IN_IDX).Set(esp.GPIO_FUNC_IN_SEL_CFG_SEL | uint32(config.SDI))\n\tconfig.SDO.Configure(PinConfig{Mode: PinOutput})\n\tconfig.SDO.outFunc().Set(FSPID_OUT_IDX)\n\tconfig.SCK.Configure(PinConfig{Mode: PinOutput})\n\tconfig.SCK.outFunc().Set(FSPICLK_OUT_IDX)\n\tif config.CS != NoPin {\n\t\tconfig.CS.Configure(PinConfig{Mode: PinOutput})\n\t\tconfig.CS.outFunc().Set(FSPICS0_OUT_IDX)\n\t}\n\n\treturn nil\n}\n\n// Transfer writes/reads a single byte using the SPI interface. If you need to\n// transfer larger amounts of data, Tx will be faster.\nfunc (spi *SPI) Transfer(w byte) (byte, error) {\n\tspi.Bus.SetMS_DLEN_MS_DATA_BITLEN(7)\n\n\tspi.Bus.SetW0(uint32(w))\n\n\t// Send/receive byte.\n\tspi.Bus.SetCMD_UPDATE(1)\n\tfor spi.Bus.GetCMD_UPDATE() != 0 {\n\t}\n\n\tspi.Bus.SetCMD_USR(1)\n\tfor spi.Bus.GetCMD_USR() != 0 {\n\t}\n\n\t// The received byte is stored in W0.\n\treturn byte(spi.Bus.GetW0()), nil\n}\n\n// Tx handles read/write operation for SPI interface. Since SPI is a synchronous write/read\n// interface, there must always be the same number of bytes written as bytes read.\n// This is accomplished by sending zero bits if r is bigger than w or discarding\n// the incoming data if w is bigger than r.\nfunc (spi *SPI) Tx(w, r []byte) error {\n\ttoTransfer := len(w)\n\tif len(r) > toTransfer {\n\t\ttoTransfer = len(r)\n\t}\n\n\tfor toTransfer > 0 {\n\t\t// Chunk 64 bytes at a time.\n\t\tchunkSize := toTransfer\n\t\tif chunkSize > 64 {\n\t\t\tchunkSize = 64\n\t\t}\n\n\t\t// Fill tx buffer.\n\t\ttransferWords := (*[16]volatile.Register32)(unsafe.Pointer(uintptr(unsafe.Pointer(&spi.Bus.W0))))\n\t\tif len(w) >= 64 {\n\t\t\t// We can fill the entire 64-byte transfer buffer with data.\n\t\t\t// This loop is slightly faster than the loop below.\n\t\t\tfor i := 0; i < 16; i++ {\n\t\t\t\tword := uint32(w[i*4]) | uint32(w[i*4+1])<<8 | uint32(w[i*4+2])<<16 | uint32(w[i*4+3])<<24\n\t\t\t\ttransferWords[i].Set(word)\n\t\t\t}\n\t\t} else {\n\t\t\t// We can't fill the entire transfer buffer, so we need to be a bit\n\t\t\t// more careful.\n\t\t\t// Note that parts of the transfer buffer that aren't used still\n\t\t\t// need to be set to zero, otherwise we might be transferring\n\t\t\t// garbage from a previous transmission if w is smaller than r.\n\t\t\tfor i := 0; i < 16; i++ {\n\t\t\t\tvar word uint32\n\t\t\t\tif i*4+3 < len(w) {\n\t\t\t\t\tword |= uint32(w[i*4+3]) << 24\n\t\t\t\t}\n\t\t\t\tif i*4+2 < len(w) {\n\t\t\t\t\tword |= uint32(w[i*4+2]) << 16\n\t\t\t\t}\n\t\t\t\tif i*4+1 < len(w) {\n\t\t\t\t\tword |= uint32(w[i*4+1]) << 8\n\t\t\t\t}\n\t\t\t\tif i*4+0 < len(w) {\n\t\t\t\t\tword |= uint32(w[i*4+0]) << 0\n\t\t\t\t}\n\t\t\t\ttransferWords[i].Set(word)\n\t\t\t}\n\t\t}\n\n\t\t// Do the transfer.\n\t\tspi.Bus.SetMS_DLEN_MS_DATA_BITLEN(uint32(chunkSize)*8 - 1)\n\n\t\tspi.Bus.SetCMD_UPDATE(1)\n\t\tfor spi.Bus.GetCMD_UPDATE() != 0 {\n\t\t}\n\n\t\tspi.Bus.SetCMD_USR(1)\n\t\tfor spi.Bus.GetCMD_USR() != 0 {\n\t\t}\n\n\t\t// Read rx buffer.\n\t\trxSize := 64\n\t\tif rxSize > len(r) {\n\t\t\trxSize = len(r)\n\t\t}\n\t\tfor i := 0; i < rxSize; i++ {\n\t\t\tr[i] = byte(transferWords[i/4].Get() >> ((i % 4) * 8))\n\t\t}\n\n\t\t// Cut off some part of the output buffer so the next iteration we will\n\t\t// only send the remaining bytes.\n\t\tif len(w) < chunkSize {\n\t\t\tw = nil\n\t\t} else {\n\t\t\tw = w[chunkSize:]\n\t\t}\n\t\tif len(r) < chunkSize {\n\t\t\tr = nil\n\t\t} else {\n\t\t\tr = r[chunkSize:]\n\t\t}\n\t\ttoTransfer -= chunkSize\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "src/machine/machine_esp32s3.go",
    "content": "//go:build esp32s3\n\npackage machine\n\nimport (\n\t\"device/esp\"\n\t\"errors\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nconst deviceName = esp.Device\n\nconst xtalClock = 40_000000       // 40MHz\nconst apbClock = 80_000000        // 80MHz\nconst cryptoPWMClock = 160_000000 // 160MHz\n\n// GetCPUFrequency returns the current CPU frequency of the chip.\nfunc GetCPUFrequency() (uint32, error) {\n\tswitch esp.SYSTEM.GetSYSCLK_CONF_SOC_CLK_SEL() {\n\tcase 0:\n\t\treturn xtalClock / (esp.SYSTEM.GetSYSCLK_CONF_PRE_DIV_CNT() + 1), nil\n\tcase 1:\n\t\tswitch esp.SYSTEM.GetCPU_PER_CONF_CPUPERIOD_SEL() {\n\t\tcase 0:\n\t\t\treturn 80e6, nil\n\t\tcase 1:\n\t\t\treturn 160e6, nil\n\t\tcase 2:\n\t\t\t// If esp.SYSTEM.GetCPU_PER_CONF_PLL_FREQ_SEL() == 1, this is undefined\n\t\t\treturn 240e6, nil\n\t\t}\n\tcase 2:\n\t\t//RC Fast Clock\n\t\treturn (175e5) / (esp.SYSTEM.GetSYSCLK_CONF_PRE_DIV_CNT() + 1), nil\n\t}\n\treturn 0, errors.New(\"machine: Unable to determine current cpu frequency\")\n}\n\n// SetCPUFrequency sets the frequency of the CPU to one of several targets\nfunc SetCPUFrequency(frequency uint32) error {\n\t// Always assume we are on PLL. Lower frequencies can be set with a different\n\t// clock source, but this will change the behavior of APB clock and Crypto PWM\n\t// clock\n\t//esp.SYSTEM.SetSYSCLK_CONF_SOC_CLK_SEL(1)\n\n\tswitch frequency {\n\tcase 80_000000:\n\t\tesp.SYSTEM.SetCPU_PER_CONF_CPUPERIOD_SEL(0)\n\t\tesp.SYSTEM.SetCPU_PER_CONF_PLL_FREQ_SEL(0) // Reduce PLL freq when possible\n\t\treturn nil\n\tcase 160_000000:\n\t\tesp.SYSTEM.SetCPU_PER_CONF_CPUPERIOD_SEL(1)\n\t\tesp.SYSTEM.SetCPU_PER_CONF_PLL_FREQ_SEL(0)\n\t\treturn nil\n\tcase 240_000000:\n\t\tesp.SYSTEM.SetCPU_PER_CONF_PLL_FREQ_SEL(1) // Increase PLL freq when needed\n\t\tesp.SYSTEM.SetCPU_PER_CONF_CPUPERIOD_SEL(2)\n\t\treturn nil\n\t}\n\treturn errors.New(\"machine: Unsupported CPU frequency selected. Supported: 80, 160, 240 MHz\")\n}\n\nvar (\n\tErrInvalidSPIBus = errors.New(\"machine: invalid SPI bus\")\n)\n\nconst (\n\tPinOutput PinMode = iota\n\tPinInput\n\tPinInputPullup\n\tPinInputPulldown\n)\n\n// Hardware pin numbers\nconst (\n\tGPIO0  Pin = 0\n\tGPIO1  Pin = 1\n\tGPIO2  Pin = 2\n\tGPIO3  Pin = 3\n\tGPIO4  Pin = 4\n\tGPIO5  Pin = 5\n\tGPIO6  Pin = 6\n\tGPIO7  Pin = 7\n\tGPIO8  Pin = 8\n\tGPIO9  Pin = 9\n\tGPIO10 Pin = 10\n\tGPIO11 Pin = 11\n\tGPIO12 Pin = 12\n\tGPIO13 Pin = 13\n\tGPIO14 Pin = 14\n\tGPIO15 Pin = 15\n\tGPIO16 Pin = 16\n\tGPIO17 Pin = 17\n\tGPIO18 Pin = 18\n\tGPIO19 Pin = 19\n\tGPIO20 Pin = 20\n\tGPIO21 Pin = 21\n\tGPIO26 Pin = 26\n\tGPIO27 Pin = 27\n\tGPIO28 Pin = 28\n\tGPIO29 Pin = 29\n\tGPIO30 Pin = 30\n\tGPIO31 Pin = 31\n\tGPIO32 Pin = 32\n\tGPIO33 Pin = 33\n\tGPIO34 Pin = 34\n\tGPIO35 Pin = 35\n\tGPIO36 Pin = 36\n\tGPIO37 Pin = 37\n\tGPIO38 Pin = 38\n\tGPIO39 Pin = 39\n\tGPIO40 Pin = 40\n\tGPIO41 Pin = 41\n\tGPIO42 Pin = 42\n\tGPIO43 Pin = 43\n\tGPIO44 Pin = 44\n\tGPIO45 Pin = 45\n\tGPIO46 Pin = 46\n\tGPIO47 Pin = 47\n\tGPIO48 Pin = 48\n)\n\n// Configure this pin with the given configuration.\nfunc (p Pin) Configure(config PinConfig) {\n\t// Output function 256 is a special value reserved for use as a regular GPIO\n\t// pin. Peripherals (SPI etc) can set a custom output function by calling\n\t// lowercase configure() instead with a signal name.\n\tp.configure(config, 256)\n}\n\n// configure is the same as Configure, but allows for setting a specific input\n// or output signal.\n// Signals are always routed through the GPIO matrix for simplicity. Output\n// signals are configured in FUNCx_OUT_SEL_CFG which selects a particular signal\n// to output on a given pin. Input signals are configured in FUNCy_IN_SEL_CFG,\n// which sets the pin to use for a particular input signal.\nfunc (p Pin) configure(config PinConfig, signal uint32) {\n\tif p == NoPin {\n\t\t// This simplifies pin configuration in peripherals such as SPI.\n\t\treturn\n\t}\n\n\tioConfig := uint32(0)\n\n\t// MCU_SEL: Function 1 is always GPIO\n\tioConfig |= (1 << esp.IO_MUX_GPIO_MCU_SEL_Pos)\n\n\t// FUN_IE: Make this pin an input pin (always set for GPIO operation)\n\tioConfig |= esp.IO_MUX_GPIO_FUN_IE\n\n\t// DRV: Set drive strength to 20 mA as a default. Pins 17 and 18 are special\n\tvar drive uint32\n\tif p == GPIO17 || p == GPIO18 {\n\t\tdrive = 1 // 20 mA\n\t} else {\n\t\tdrive = 2 // 20 mA\n\t}\n\tioConfig |= (drive << esp.IO_MUX_GPIO_FUN_DRV_Pos)\n\n\t// WPU/WPD: Select pull mode.\n\tif config.Mode == PinInputPullup {\n\t\tioConfig |= esp.IO_MUX_GPIO_FUN_WPU\n\t} else if config.Mode == PinInputPulldown {\n\t\tioConfig |= esp.IO_MUX_GPIO_FUN_WPD\n\t}\n\n\t// Set configuration\n\tioRegister := p.ioMuxReg()\n\tioRegister.Set(ioConfig)\n\n\tswitch config.Mode {\n\tcase PinOutput:\n\t\t// Set the 'output enable' bit.\n\t\tif p < 32 {\n\t\t\tesp.GPIO.ENABLE_W1TS.Set(1 << p)\n\t\t} else {\n\t\t\tesp.GPIO.ENABLE1_W1TS.Set(1 << (p - 32))\n\t\t}\n\t\t// Set the signal to read the output value from. It can be a peripheral\n\t\t// output signal, or the special value 256 which indicates regular GPIO\n\t\t// usage.\n\t\tp.outFunc().Set(signal)\n\tcase PinInput, PinInputPullup, PinInputPulldown:\n\t\t// Clear the 'output enable' bit.\n\t\tif p < 32 {\n\t\t\tesp.GPIO.ENABLE_W1TC.Set(1 << p)\n\t\t} else {\n\t\t\tesp.GPIO.ENABLE1_W1TC.Set(1 << (p - 32))\n\t\t}\n\t\tif signal != 256 {\n\t\t\t// Signal is a peripheral function (not a simple GPIO). Connect this\n\t\t\t// signal to the pin.\n\t\t\t// Note that outFunc and inFunc work in the opposite direction.\n\t\t\t// outFunc configures a pin to use a given output signal, while\n\t\t\t// inFunc specifies a pin to use to read the signal from.\n\t\t\tinFunc(signal).Set(esp.GPIO_FUNC_IN_SEL_CFG_SEL | uint32(p)<<esp.GPIO_FUNC_IN_SEL_CFG_IN_SEL_Pos)\n\t\t}\n\t}\n}\n\n// ioMuxReg returns the IO_MUX_n_REG register used for configuring the io mux for\n// this pin\nfunc (p Pin) ioMuxReg() *volatile.Register32 {\n\treturn (*volatile.Register32)(unsafe.Add(unsafe.Pointer(&esp.IO_MUX.GPIO0), uintptr(p)*4))\n}\n\n// outFunc returns the FUNCx_OUT_SEL_CFG register used for configuring the\n// output function selection.\nfunc (p Pin) outFunc() *volatile.Register32 {\n\treturn (*volatile.Register32)(unsafe.Add(unsafe.Pointer(&esp.GPIO.FUNC0_OUT_SEL_CFG), uintptr(p)*4))\n}\n\n// inFunc returns the FUNCy_IN_SEL_CFG register used for configuring the input\n// function selection.\nfunc inFunc(signal uint32) *volatile.Register32 {\n\treturn (*volatile.Register32)(unsafe.Add(unsafe.Pointer(&esp.GPIO.FUNC0_IN_SEL_CFG), uintptr(signal)*4))\n}\n\n// Set the pin to high or low.\n// Warning: only use this on an output pin!\nfunc (p Pin) Set(value bool) {\n\tif value {\n\t\treg, mask := p.portMaskSet()\n\t\treg.Set(mask)\n\t} else {\n\t\treg, mask := p.portMaskClear()\n\t\treg.Set(mask)\n\t}\n}\n\n// Return the register and mask to enable a given GPIO pin. This can be used to\n// implement bit-banged drivers.\n//\n// Warning: only use this on an output pin!\nfunc (p Pin) PortMaskSet() (*uint32, uint32) {\n\treg, mask := p.portMaskSet()\n\treturn &reg.Reg, mask\n}\n\n// Return the register and mask to disable a given GPIO pin. This can be used to\n// implement bit-banged drivers.\n//\n// Warning: only use this on an output pin!\nfunc (p Pin) PortMaskClear() (*uint32, uint32) {\n\treg, mask := p.portMaskClear()\n\treturn &reg.Reg, mask\n}\n\nfunc (p Pin) portMaskSet() (*volatile.Register32, uint32) {\n\tif p < 32 {\n\t\treturn &esp.GPIO.OUT_W1TS, 1 << p\n\t} else {\n\t\treturn &esp.GPIO.OUT1_W1TS, 1 << (p - 32)\n\t}\n}\n\nfunc (p Pin) portMaskClear() (*volatile.Register32, uint32) {\n\tif p < 32 {\n\t\treturn &esp.GPIO.OUT_W1TC, 1 << p\n\t} else {\n\t\treturn &esp.GPIO.OUT1_W1TC, 1 << (p - 32)\n\t}\n}\n\n// Get returns the current value of a GPIO pin when the pin is configured as an\n// input or as an output.\nfunc (p Pin) Get() bool {\n\tif p < 32 {\n\t\treturn esp.GPIO.IN.Get()&(1<<p) != 0\n\t} else {\n\t\treturn esp.GPIO.IN1.Get()&(1<<(p-32)) != 0\n\t}\n}\n\nvar DefaultUART = UART0\n\nvar (\n\tUART0  = &_UART0\n\t_UART0 = UART{Bus: esp.UART0, Buffer: NewRingBuffer()}\n\tUART1  = &_UART1\n\t_UART1 = UART{Bus: esp.UART1, Buffer: NewRingBuffer()}\n\tUART2  = &_UART2\n\t_UART2 = UART{Bus: esp.UART2, Buffer: NewRingBuffer()}\n)\n\ntype UART struct {\n\tBus    *esp.UART_Type\n\tBuffer *RingBuffer\n}\n\nfunc (uart *UART) Configure(config UARTConfig) {\n\tif config.BaudRate == 0 {\n\t\tconfig.BaudRate = 115200\n\t}\n\t// Crystal clock source is selected by default\n\tuart.Bus.CLKDIV.Set(xtalClock / config.BaudRate)\n}\n\nfunc (uart *UART) writeByte(b byte) error {\n\tfor (uart.Bus.STATUS.Get()>>16)&0xff >= 128 {\n\t\t// Read UART_TXFIFO_CNT from the status register, which indicates how\n\t\t// many bytes there are in the transmit buffer. Wait until there are\n\t\t// less than 128 bytes in this buffer (the default buffer size).\n\t}\n\tuart.Bus.FIFO.Set(uint32(b))\n\treturn nil\n}\n\nfunc (uart *UART) flush() {}\n\n// TODO: SPI\n"
  },
  {
    "path": "src/machine/machine_esp8266.go",
    "content": "//go:build esp8266\n\npackage machine\n\nimport (\n\t\"device/esp\"\n\t\"runtime/volatile\"\n)\n\nconst deviceName = esp.Device\n\nfunc CPUFrequency() uint32 {\n\treturn 80000000 // 80MHz\n}\n\nconst (\n\tPinOutput PinMode = iota\n\tPinInput\n)\n\n// Hardware pin numbers\nconst (\n\tGPIO0 Pin = iota\n\tGPIO1\n\tGPIO2\n\tGPIO3\n\tGPIO4\n\tGPIO5\n\tGPIO6\n\tGPIO7\n\tGPIO8\n\tGPIO9\n\tGPIO10\n\tGPIO11\n\tGPIO12\n\tGPIO13\n\tGPIO14\n\tGPIO15\n\tGPIO16\n)\n\n// Pins that are fixed by the chip.\nconst (\n\tUART_TX_PIN Pin = 1\n\tUART_RX_PIN Pin = 3\n)\n\n// Pin functions are not trivial. The below array maps a pin number (GPIO\n// number) to the pad as used in the IO mux.\n// Tables with the mapping:\n// https://www.esp8266.com/wiki/doku.php?id=esp8266_gpio_pin_allocations#pin_functions\n// https://www.espressif.com/sites/default/files/documentation/ESP8266_Pin_List_0.xls\nvar pinPadMapping = [...]uint8{\n\t12: 0,\n\t13: 1,\n\t14: 2,\n\t15: 3,\n\t3:  4,\n\t1:  5,\n\t6:  6,\n\t7:  7,\n\t8:  8,\n\t9:  9,\n\t10: 10,\n\t11: 11,\n\t0:  12,\n\t2:  13,\n\t4:  14,\n\t5:  15,\n}\n\n// getPad returns the pad number and the register to configure this pad.\nfunc (p Pin) getPad() (uint8, *volatile.Register32) {\n\tpad := pinPadMapping[p]\n\tvar reg *volatile.Register32\n\tswitch pad {\n\tcase 0:\n\t\treg = &esp.IO_MUX.IO_MUX_MTDI\n\tcase 1:\n\t\treg = &esp.IO_MUX.IO_MUX_MTCK\n\tcase 2:\n\t\treg = &esp.IO_MUX.IO_MUX_MTMS\n\tcase 3:\n\t\treg = &esp.IO_MUX.IO_MUX_MTDO\n\tcase 4:\n\t\treg = &esp.IO_MUX.IO_MUX_U0RXD\n\tcase 5:\n\t\treg = &esp.IO_MUX.IO_MUX_U0TXD\n\tcase 6:\n\t\treg = &esp.IO_MUX.IO_MUX_SD_CLK\n\tcase 7:\n\t\treg = &esp.IO_MUX.IO_MUX_SD_DATA0\n\tcase 8:\n\t\treg = &esp.IO_MUX.IO_MUX_SD_DATA1\n\tcase 9:\n\t\treg = &esp.IO_MUX.IO_MUX_SD_DATA2\n\tcase 10:\n\t\treg = &esp.IO_MUX.IO_MUX_SD_DATA3\n\tcase 11:\n\t\treg = &esp.IO_MUX.IO_MUX_SD_CMD\n\tcase 12:\n\t\treg = &esp.IO_MUX.IO_MUX_GPIO0\n\tcase 13:\n\t\treg = &esp.IO_MUX.IO_MUX_GPIO2\n\tcase 14:\n\t\treg = &esp.IO_MUX.IO_MUX_GPIO4\n\tcase 15:\n\t\treg = &esp.IO_MUX.IO_MUX_GPIO5\n\t}\n\treturn pad, reg\n}\n\n// Configure sets the given pin as output or input pin.\nfunc (p Pin) Configure(config PinConfig) {\n\tswitch config.Mode {\n\tcase PinInput, PinOutput:\n\t\tpad, reg := p.getPad()\n\t\tif pad >= 12 { // pin 0, 2, 4, 5\n\t\t\treg.Set(0 << 4) // function 0 at bit position 4\n\t\t} else {\n\t\t\treg.Set(3 << 4) // function 3 at bit position 4\n\t\t}\n\t\tif config.Mode == PinOutput {\n\t\t\tesp.GPIO.GPIO_ENABLE_W1TS.Set(1 << p)\n\t\t} else {\n\t\t\tesp.GPIO.GPIO_ENABLE_W1TC.Set(1 << p)\n\t\t}\n\t}\n}\n\n// Get returns the current value of a GPIO pin when the pin is configured as an\n// input or as an output.\nfunc (p Pin) Get() bool {\n\t// See this document for details\n\t// https://www.espressif.com/sites/default/files/documentation/esp8266-technical_reference_en.pdf\n\n\treturn esp.GPIO.GPIO_IN.Get()&(1<<p) != 0\n}\n\n// Set sets the output value of this pin to high (true) or low (false).\nfunc (p Pin) Set(value bool) {\n\tif value {\n\t\tesp.GPIO.GPIO_OUT_W1TS.Set(1 << p)\n\t} else {\n\t\tesp.GPIO.GPIO_OUT_W1TC.Set(1 << p)\n\t}\n}\n\n// Return the register and mask to enable a given GPIO pin. This can be used to\n// implement bit-banged drivers.\n//\n// Warning: only use this on an output pin!\nfunc (p Pin) PortMaskSet() (*uint32, uint32) {\n\treturn &esp.GPIO.GPIO_OUT_W1TS.Reg, 1 << p\n}\n\n// Return the register and mask to disable a given GPIO pin. This can be used to\n// implement bit-banged drivers.\n//\n// Warning: only use this on an output pin!\nfunc (p Pin) PortMaskClear() (*uint32, uint32) {\n\treturn &esp.GPIO.GPIO_OUT_W1TC.Reg, 1 << p\n}\n\nvar DefaultUART = UART0\n\n// UART0 is a hardware UART that supports both TX and RX.\nvar UART0 = &_UART0\nvar _UART0 = UART{Buffer: NewRingBuffer()}\n\ntype UART struct {\n\tBuffer *RingBuffer\n}\n\n// Configure the UART baud rate. TX and RX pins are fixed by the hardware so\n// cannot be modified and will be ignored.\nfunc (uart *UART) Configure(config UARTConfig) {\n\tif config.BaudRate == 0 {\n\t\tconfig.BaudRate = 115200\n\t}\n\tesp.UART0.UART_CLKDIV.Set(CPUFrequency() / config.BaudRate)\n}\n\n// writeByte writes a single byte to the output buffer. Note that the hardware\n// includes a buffer of 128 bytes which will be used first.\nfunc (uart *UART) writeByte(c byte) error {\n\tfor (esp.UART0.UART_STATUS.Get()>>16)&0xff >= 128 {\n\t\t// Wait until the TX buffer has room.\n\t}\n\tesp.UART0.UART_FIFO.Set(uint32(c))\n\treturn nil\n}\n\nfunc (uart *UART) flush() {}\n"
  },
  {
    "path": "src/machine/machine_fe310.go",
    "content": "//go:build fe310\n\npackage machine\n\nimport (\n\t\"device/sifive\"\n\t\"runtime/interrupt\"\n\t\"unsafe\"\n)\n\nconst deviceName = sifive.Device\n\nfunc CPUFrequency() uint32 {\n\treturn 320000000 // 320MHz\n}\n\nconst (\n\tPinInput PinMode = iota\n\tPinOutput\n\tPinPWM\n\tPinSPI\n\tPinI2C = PinSPI\n)\n\n// Configure this pin with the given configuration.\nfunc (p Pin) Configure(config PinConfig) {\n\tsifive.GPIO0.INPUT_EN.SetBits(1 << uint8(p))\n\tswitch config.Mode {\n\tcase PinInput:\n\t\tsifive.GPIO0.OUTPUT_EN.ClearBits(1 << uint8(p))\n\tcase PinOutput:\n\t\tsifive.GPIO0.OUTPUT_EN.SetBits(1 << uint8(p))\n\tcase PinPWM:\n\t\tsifive.GPIO0.IOF_EN.SetBits(1 << uint8(p))\n\t\tsifive.GPIO0.IOF_SEL.SetBits(1 << uint8(p))\n\tcase PinSPI:\n\t\tsifive.GPIO0.IOF_EN.SetBits(1 << uint8(p))\n\t\tsifive.GPIO0.IOF_SEL.ClearBits(1 << uint8(p))\n\t}\n}\n\n// Set the pin to high or low.\nfunc (p Pin) Set(high bool) {\n\tif high {\n\t\tsifive.GPIO0.PORT.SetBits(1 << uint8(p))\n\t} else {\n\t\tsifive.GPIO0.PORT.ClearBits(1 << uint8(p))\n\t}\n}\n\n// Get returns the current value of a GPIO pin when the pin is configured as an\n// input or as an output.\nfunc (p Pin) Get() bool {\n\tval := sifive.GPIO0.VALUE.Get() & (1 << uint8(p))\n\treturn (val > 0)\n}\n\n// Return the register and mask to enable a given GPIO pin. This can be used to\n// implement bit-banged drivers.\n//\n// Warning: only use this on an output pin!\nfunc (p Pin) PortMaskSet() (*uint32, uint32) {\n\treturn (*uint32)(unsafe.Pointer(&sifive.GPIO0.PORT)), sifive.GPIO0.PORT.Get() | (1 << uint8(p))\n}\n\n// Return the register and mask to disable a given GPIO pin. This can be used to\n// implement bit-banged drivers.\n//\n// Warning: only use this on an output pin!\nfunc (p Pin) PortMaskClear() (*uint32, uint32) {\n\treturn (*uint32)(unsafe.Pointer(&sifive.GPIO0.PORT)), sifive.GPIO0.PORT.Get() &^ (1 << uint8(p))\n}\n\ntype UART struct {\n\tBus    *sifive.UART_Type\n\tBuffer *RingBuffer\n}\n\nvar (\n\tUART0  = &_UART0\n\t_UART0 = UART{Bus: sifive.UART0, Buffer: NewRingBuffer()}\n)\n\nfunc (uart *UART) Configure(config UARTConfig) {\n\tif config.BaudRate == 0 {\n\t\tconfig.BaudRate = 115200\n\t}\n\t// The divisor is:\n\t//   fbaud = fin / (div + 1)\n\t// Restating to get the divisor:\n\t//   div = fin / fbaud - 1\n\t// But we're using integers, so we should take care of rounding:\n\t//   div = (fin + fbaud/2) / fbaud - 1\n\tdivisor := (CPUFrequency()+config.BaudRate/2)/config.BaudRate - 1\n\tsifive.UART0.DIV.Set(divisor)\n\tsifive.UART0.TXCTRL.Set(sifive.UART_TXCTRL_ENABLE)\n\tsifive.UART0.RXCTRL.Set(sifive.UART_RXCTRL_ENABLE)\n\tsifive.UART0.IE.Set(sifive.UART_IE_RXWM) // enable the receive interrupt (only)\n\tintr := interrupt.New(sifive.IRQ_UART0, _UART0.handleInterrupt)\n\tintr.SetPriority(5)\n\tintr.Enable()\n}\n\nfunc (uart *UART) handleInterrupt(interrupt.Interrupt) {\n\trxdata := uart.Bus.RXDATA.Get()\n\tc := byte(rxdata)\n\tif uint32(c) != rxdata {\n\t\t// The rxdata has other bits set than just the low 8 bits. This probably\n\t\t// means that the 'empty' flag is set, which indicates there is no data\n\t\t// to be read and the byte is garbage. Ignore this byte.\n\t\treturn\n\t}\n\tuart.Receive(c)\n}\n\nfunc (uart *UART) writeByte(c byte) error {\n\tfor sifive.UART0.TXDATA.Get()&sifive.UART_TXDATA_FULL != 0 {\n\t}\n\n\tsifive.UART0.TXDATA.Set(uint32(c))\n\treturn nil\n}\n\nfunc (uart *UART) flush() {}\n\n// SPI on the FE310. The normal SPI0 is actually a quad-SPI meant for flash, so it is best\n// to use SPI1 or SPI2 port for most applications.\ntype SPI struct {\n\tBus *sifive.QSPI_Type\n}\n\n// SPIConfig is used to store config info for SPI.\ntype SPIConfig struct {\n\tFrequency uint32\n\tSCK       Pin\n\tSDO       Pin\n\tSDI       Pin\n\tLSBFirst  bool\n\tMode      uint8\n}\n\n// Configure is intended to setup the SPI interface.\nfunc (spi *SPI) Configure(config SPIConfig) error {\n\t// Use default pins if not set.\n\tif config.SCK == 0 && config.SDO == 0 && config.SDI == 0 {\n\t\tconfig.SCK = SPI0_SCK_PIN\n\t\tconfig.SDO = SPI0_SDO_PIN\n\t\tconfig.SDI = SPI0_SDI_PIN\n\t}\n\n\t// enable pins for SPI\n\tconfig.SCK.Configure(PinConfig{Mode: PinSPI})\n\tconfig.SDO.Configure(PinConfig{Mode: PinSPI})\n\tconfig.SDI.Configure(PinConfig{Mode: PinSPI})\n\n\t// set default frequency\n\tif config.Frequency == 0 {\n\t\tconfig.Frequency = 4000000 // 4MHz\n\t}\n\n\t// div = (SPI_CFG(dev)->f_sys / (2 * frequency)) - 1;\n\tdiv := CPUFrequency()/(2*config.Frequency) - 1\n\tspi.Bus.DIV.Set(div)\n\n\t// set mode\n\tswitch config.Mode {\n\tcase 0:\n\t\tspi.Bus.MODE.ClearBits(sifive.QSPI_MODE_PHASE)\n\t\tspi.Bus.MODE.ClearBits(sifive.QSPI_MODE_POLARITY)\n\tcase 1:\n\t\tspi.Bus.MODE.SetBits(sifive.QSPI_MODE_PHASE)\n\t\tspi.Bus.MODE.ClearBits(sifive.QSPI_MODE_POLARITY)\n\tcase 2:\n\t\tspi.Bus.MODE.ClearBits(sifive.QSPI_MODE_PHASE)\n\t\tspi.Bus.MODE.SetBits(sifive.QSPI_MODE_POLARITY)\n\tcase 3:\n\t\tspi.Bus.MODE.SetBits(sifive.QSPI_MODE_PHASE | sifive.QSPI_MODE_POLARITY)\n\tdefault: // to mode 0\n\t\tspi.Bus.MODE.ClearBits(sifive.QSPI_MODE_PHASE)\n\t\tspi.Bus.MODE.ClearBits(sifive.QSPI_MODE_POLARITY)\n\t}\n\n\t// frame length\n\tspi.Bus.FMT.SetBits(8 << sifive.QSPI_FMT_LENGTH_Pos)\n\n\t// Set single line operation, by clearing all bits\n\tspi.Bus.FMT.ClearBits(sifive.QSPI_FMT_PROTOCOL_Msk)\n\n\t// set bit transfer order\n\tif config.LSBFirst {\n\t\tspi.Bus.FMT.SetBits(sifive.QSPI_FMT_ENDIAN)\n\t} else {\n\t\tspi.Bus.FMT.ClearBits(sifive.QSPI_FMT_ENDIAN)\n\t}\n\n\treturn nil\n}\n\n// Transfer writes/reads a single byte using the SPI interface.\nfunc (spi *SPI) Transfer(w byte) (byte, error) {\n\t// wait for tx ready\n\tfor spi.Bus.TXDATA.HasBits(sifive.QSPI_TXDATA_FULL) {\n\t}\n\n\t// write data\n\tspi.Bus.TXDATA.Set(uint32(w))\n\n\t// wait until receive has data\n\tdata := spi.Bus.RXDATA.Get()\n\tfor data&sifive.QSPI_RXDATA_EMPTY > 0 {\n\t\tdata = spi.Bus.RXDATA.Get()\n\t}\n\n\t// return data\n\treturn byte(data), nil\n}\n\n// I2C on the FE310-G002.\ntype I2C struct {\n\tBus sifive.I2C_Type\n}\n\nvar (\n\tI2C0 = (*I2C)(unsafe.Pointer(sifive.I2C0))\n)\n\n// I2CConfig is used to store config info for I2C.\ntype I2CConfig struct {\n\tFrequency uint32\n\tSCL       Pin\n\tSDA       Pin\n}\n\nvar i2cClockFrequency uint32 = 32000000\n\n// Configure is intended to setup the I2C interface.\nfunc (i2c *I2C) Configure(config I2CConfig) error {\n\tif config.Frequency == 0 {\n\t\tconfig.Frequency = 100 * KHz\n\t}\n\n\tif config.SDA == 0 && config.SCL == 0 {\n\t\tconfig.SDA = I2C0_SDA_PIN\n\t\tconfig.SCL = I2C0_SCL_PIN\n\t}\n\n\ti2c.SetBaudRate(config.Frequency)\n\n\tconfig.SDA.Configure(PinConfig{Mode: PinI2C})\n\tconfig.SCL.Configure(PinConfig{Mode: PinI2C})\n\n\treturn nil\n}\n\n// SetBaudRate sets the communication speed for I2C.\nfunc (i2c *I2C) SetBaudRate(br uint32) error {\n\tvar prescaler = i2cClockFrequency/(5*br) - 1\n\n\t// disable controller before setting the prescale registers\n\ti2c.Bus.CTR.ClearBits(sifive.I2C_CTR_EN)\n\n\t// set prescaler registers\n\ti2c.Bus.PRER_LO.Set(uint32(prescaler & 0xff))\n\ti2c.Bus.PRER_HI.Set(uint32((prescaler >> 8) & 0xff))\n\n\t// enable controller\n\ti2c.Bus.CTR.SetBits(sifive.I2C_CTR_EN)\n\n\treturn nil\n}\n\n// Tx does a single I2C transaction at the specified address.\n// It clocks out the given address, writes the bytes in w, reads back len(r)\n// bytes and stores them in r, and generates a stop condition on the bus.\nfunc (i2c *I2C) Tx(addr uint16, w, r []byte) error {\n\tvar err error\n\tif len(w) != 0 {\n\t\t// send start/address for write\n\t\ti2c.sendAddress(addr, true)\n\n\t\t// ACK received (0: ACK, 1: NACK)\n\t\tif i2c.Bus.CR_SR.HasBits(sifive.I2C_SR_RX_ACK) {\n\t\t\treturn errI2CAckExpected\n\t\t}\n\n\t\t// write data\n\t\tfor _, b := range w {\n\t\t\terr = i2c.writeByte(b)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\tif len(r) != 0 {\n\t\t// send start/address for read\n\t\ti2c.sendAddress(addr, false)\n\n\t\t// ACK received (0: ACK, 1: NACK)\n\t\tif i2c.Bus.CR_SR.HasBits(sifive.I2C_SR_RX_ACK) {\n\t\t\treturn errI2CAckExpected\n\t\t}\n\n\t\t// read first byte\n\t\tr[0] = i2c.readByte()\n\t\tfor i := 1; i < len(r); i++ {\n\t\t\t// send an ACK\n\t\t\ti2c.Bus.CR_SR.Set(^uint32(sifive.I2C_CR_ACK))\n\n\t\t\t// read data and send the ACK\n\t\t\tr[i] = i2c.readByte()\n\t\t}\n\n\t\t// send NACK to end transmission\n\t\ti2c.Bus.CR_SR.Set(sifive.I2C_CR_ACK)\n\t}\n\n\t// generate stop condition\n\ti2c.Bus.CR_SR.Set(sifive.I2C_CR_STO)\n\treturn nil\n}\n\n// Writes a single byte to the I2C bus.\nfunc (i2c *I2C) writeByte(data byte) error {\n\t// Send data byte\n\ti2c.Bus.TXR_RXR.Set(uint32(data))\n\n\ti2c.Bus.CR_SR.Set(sifive.I2C_CR_WR)\n\n\t// wait until transmission complete\n\tfor i2c.Bus.CR_SR.HasBits(sifive.I2C_SR_TIP) {\n\t}\n\n\t// ACK received (0: ACK, 1: NACK)\n\tif i2c.Bus.CR_SR.HasBits(sifive.I2C_SR_RX_ACK) {\n\t\treturn errI2CAckExpected\n\t}\n\n\treturn nil\n}\n\n// Reads a single byte from the I2C bus.\nfunc (i2c *I2C) readByte() byte {\n\ti2c.Bus.CR_SR.Set(sifive.I2C_CR_RD)\n\n\t// wait until transmission complete\n\tfor i2c.Bus.CR_SR.HasBits(sifive.I2C_SR_TIP) {\n\t}\n\n\treturn byte(i2c.Bus.TXR_RXR.Get())\n}\n\n// Sends the address and start signal.\nfunc (i2c *I2C) sendAddress(address uint16, write bool) error {\n\tdata := (address << 1)\n\tif !write {\n\t\tdata |= 1 // set read flag in transmit register\n\t}\n\n\t// write address to transmit register\n\ti2c.Bus.TXR_RXR.Set(uint32(data))\n\n\t// generate start condition\n\ti2c.Bus.CR_SR.Set((sifive.I2C_CR_STA | sifive.I2C_CR_WR))\n\n\t// wait until transmission complete\n\tfor i2c.Bus.CR_SR.HasBits(sifive.I2C_SR_TIP) {\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "src/machine/machine_fe310_simulator.go",
    "content": "//go:build !baremetal && hifive1b\n\npackage machine\n\nvar I2C0 = &I2C{Bus: 0, PinsSDA: []Pin{P12}, PinsSCL: []Pin{P13}}\n"
  },
  {
    "path": "src/machine/machine_gameboyadvance.go",
    "content": "//go:build gameboyadvance\n\npackage machine\n\nimport (\n\t\"device/gba\"\n\n\t\"image/color\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\n// Not sure what name to pick here. Not using ARM7TDMI because that's the CPU\n// name, not the device name.\nconst deviceName = \"GBA\"\n\n// Interrupt numbers as used on the GameBoy Advance. Register them with\n// runtime/interrupt.New.\nconst (\n\tIRQ_VBLANK  = gba.IRQ_VBLANK\n\tIRQ_HBLANK  = gba.IRQ_HBLANK\n\tIRQ_VCOUNT  = gba.IRQ_VCOUNT\n\tIRQ_TIMER0  = gba.IRQ_TIMER0\n\tIRQ_TIMER1  = gba.IRQ_TIMER1\n\tIRQ_TIMER2  = gba.IRQ_TIMER2\n\tIRQ_TIMER3  = gba.IRQ_TIMER3\n\tIRQ_COM     = gba.IRQ_COM\n\tIRQ_DMA0    = gba.IRQ_DMA0\n\tIRQ_DMA1    = gba.IRQ_DMA1\n\tIRQ_DMA2    = gba.IRQ_DMA2\n\tIRQ_DMA3    = gba.IRQ_DMA3\n\tIRQ_KEYPAD  = gba.IRQ_KEYPAD\n\tIRQ_GAMEPAK = gba.IRQ_GAMEPAK\n)\n\n// Set has not been implemented.\nfunc (p Pin) Set(value bool) {\n\t// do nothing\n}\n\nvar Display = DisplayMode3{(*[160][240]volatile.Register16)(unsafe.Pointer(uintptr(gba.MEM_VRAM)))}\n\ntype DisplayMode3 struct {\n\tport *[160][240]volatile.Register16\n}\n\nfunc (d *DisplayMode3) Configure() {\n\t// Use video mode 3 (in BG2, a 16bpp bitmap in VRAM) and Enable BG2\n\tgba.DISP.DISPCNT.Set(gba.DISPCNT_BGMODE_3<<gba.DISPCNT_BGMODE_Pos |\n\t\tgba.DISPCNT_SCREENDISPLAY_BG2_ENABLE<<gba.DISPCNT_SCREENDISPLAY_BG2_Pos)\n}\n\nfunc (d *DisplayMode3) Size() (x, y int16) {\n\treturn 240, 160\n}\n\nfunc (d *DisplayMode3) SetPixel(x, y int16, c color.RGBA) {\n\td.port[y][x].Set((uint16(c.R) >> 3) | ((uint16(c.G) >> 3) << 5) | ((uint16(c.B) >> 3) << 10))\n}\n\nfunc (d *DisplayMode3) Display() error {\n\t// Nothing to do here.\n\treturn nil\n}\n"
  },
  {
    "path": "src/machine/machine_generic.go",
    "content": "//go:build !baremetal\n\npackage machine\n\nimport (\n\t\"crypto/rand\"\n\t\"errors\"\n\t\"slices\"\n)\n\n// Dummy machine package that calls out to external functions.\n\nconst deviceName = \"generic\"\n\nvar (\n\tUSB = &UART{100}\n)\n\n// The Serial port always points to the default UART in a simulated environment.\n//\n// TODO: perhaps this should be a special serial object that outputs via WASI\n// stdout calls.\nvar Serial = hardwareUART0\n\nconst (\n\tPinInput PinMode = iota\n\tPinOutput\n\tPinInputPullup\n\tPinInputPulldown\n)\n\nfunc (p Pin) Configure(config PinConfig) {\n\tgpioConfigure(p, config)\n}\n\nfunc (p Pin) Set(value bool) {\n\tgpioSet(p, value)\n}\n\nfunc (p Pin) Get() bool {\n\treturn gpioGet(p)\n}\n\n//export __tinygo_gpio_configure\nfunc gpioConfigure(pin Pin, config PinConfig)\n\n//export __tinygo_gpio_set\nfunc gpioSet(pin Pin, value bool)\n\n//export __tinygo_gpio_get\nfunc gpioGet(pin Pin) bool\n\n// Generic PWM/timer peripheral. Properties can be configured depending on the\n// hardware.\ntype timerType struct {\n\t// Static properties.\n\tinstance    int32\n\tfrequency   uint64\n\tbits        int\n\tprescalers  []int\n\tchannelPins [][]Pin\n\n\t// Configured 'top' value.\n\ttop uint32\n}\n\n// Configure the PWM/timer peripheral.\nfunc (t *timerType) Configure(config PWMConfig) error {\n\t// Note: for very large period values, this multiplication will overflow.\n\ttop := config.Period * t.frequency / 1e9\n\tif config.Period == 0 {\n\t\ttop = 0xffff // default for LEDs\n\t}\n\n\t// The maximum value that can be stored with the given number of bits in\n\t// this timer.\n\tmaxTop := uint64(1)<<uint64(t.bits) - 1\n\n\t// Look for an appropriate prescaler value.\n\tvar prescaler int\n\tfor _, div := range t.prescalers {\n\t\tif top/uint64(div) <= maxTop {\n\t\t\tprescaler = div\n\t\t\ttop = top / uint64(div)\n\t\t\tbreak\n\t\t}\n\t}\n\tif prescaler == 0 {\n\t\treturn ErrPWMPeriodTooLong\n\t}\n\n\t// Set these values as the configuration.\n\tt.top = uint32(top)\n\tpwmConfigure(t.instance, float64(t.frequency)/float64(prescaler), uint32(top))\n\n\treturn nil\n}\n\n// Channel returns a PWM channel for the given pin. Note that one channel may be\n// shared between multiple pins, and so will have the same duty cycle. If this\n// is not desirable, look for a different PWM/timer peripheral or consider using\n// a different pin.\nfunc (t *timerType) Channel(pin Pin) (uint8, error) {\n\tfor ch, pins := range t.channelPins {\n\t\t// For nrf52xxx chips specifically we can assign any channel to any pin.\n\t\t// We use a similar (identical?) logic to the hardware implementation,\n\t\t// and pick the first empty channel.\n\t\tif pins == nil {\n\t\t\tt.channelPins[ch] = []Pin{pin}\n\t\t\tpwmChannelConfigure(t.instance, int32(ch), pin)\n\t\t\treturn uint8(ch), nil\n\t\t}\n\n\t\t// Check whether the pin can be used on this channel.\n\t\tfor _, p := range pins {\n\t\t\tif p == pin {\n\t\t\t\tpwmChannelConfigure(t.instance, int32(ch), pin)\n\t\t\t\treturn uint8(ch), nil\n\t\t\t}\n\t\t}\n\t}\n\n\treturn 0, ErrInvalidOutputPin\n}\n\nfunc (t *timerType) Set(channel uint8, value uint32) {\n\tpwmChannelSet(t.instance, channel, value)\n}\n\n// Top returns the current counter top, for use in duty cycle calculation. It\n// will only change with a call to Configure or SetPeriod, otherwise it is\n// constant.\n//\n// The value returned here is hardware dependent. In general, it's best to treat\n// it as an opaque value that can be divided by some number and passed to Set\n// (see Set documentation for more information).\nfunc (t *timerType) Top() uint32 {\n\treturn t.top\n}\n\n//export __tinygo_pwm_configure\nfunc pwmConfigure(instance int32, frequency float64, top uint32)\n\n//export __tinygo_pwm_channel_configure\nfunc pwmChannelConfigure(instance, channel int32, pin Pin)\n\n//export __tinygo_pwm_channel_set\nfunc pwmChannelSet(instance int32, channel uint8, value uint32)\n\ntype SPI struct {\n\tBus uint8\n}\n\ntype SPIConfig struct {\n\tFrequency uint32\n\tSCK       Pin\n\tSDO       Pin\n\tSDI       Pin\n\tMode      uint8\n}\n\nfunc (spi *SPI) Configure(config SPIConfig) error {\n\tspiConfigure(spi.Bus, config.SCK, config.SDO, config.SDI)\n\treturn nil\n}\n\n// Transfer writes/reads a single byte using the SPI interface.\nfunc (spi *SPI) Transfer(w byte) (byte, error) {\n\treturn spiTransfer(spi.Bus, w), nil\n}\n\n// Tx handles read/write operation for SPI interface. Since SPI is a synchronous write/read\n// interface, there must always be the same number of bytes written as bytes read.\n// The Tx method knows about this, and offers a few different ways of calling it.\n//\n// This form sends the bytes in tx buffer, putting the resulting bytes read into the rx buffer.\n// Note that the tx and rx buffers must be the same size:\n//\n//\tspi.Tx(tx, rx)\n//\n// This form sends the tx buffer, ignoring the result. Useful for sending \"commands\" that return zeros\n// until all the bytes in the command packet have been received:\n//\n//\tspi.Tx(tx, nil)\n//\n// This form sends zeros, putting the result into the rx buffer. Good for reading a \"result packet\":\n//\n//\tspi.Tx(nil, rx)\nfunc (spi *SPI) Tx(w, r []byte) error {\n\tvar wptr, rptr *byte\n\tvar wlen, rlen int\n\tif len(w) != 0 {\n\t\twptr = &w[0]\n\t\twlen = len(w)\n\t}\n\tif len(r) != 0 {\n\t\trptr = &r[0]\n\t\trlen = len(r)\n\t}\n\tspiTX(spi.Bus, wptr, wlen, rptr, rlen)\n\treturn nil\n}\n\n//export __tinygo_spi_configure\nfunc spiConfigure(bus uint8, sck Pin, SDO Pin, SDI Pin)\n\n//export __tinygo_spi_transfer\nfunc spiTransfer(bus uint8, w uint8) uint8\n\n//export __tinygo_spi_tx\nfunc spiTX(bus uint8, wptr *byte, wlen int, rptr *byte, rlen int) uint8\n\n// InitADC enables support for ADC peripherals.\nfunc InitADC() {\n\t// Nothing to do here.\n}\n\n// Configure configures an ADC pin to be able to be used to read data.\nfunc (adc ADC) Configure(ADCConfig) {\n}\n\n// Get reads the current analog value from this ADC peripheral.\nfunc (adc ADC) Get() uint16 {\n\treturn adcRead(adc.Pin)\n}\n\n//export __tinygo_adc_read\nfunc adcRead(pin Pin) uint16\n\n// I2C is a generic implementation of the Inter-IC communication protocol.\ntype I2C struct {\n\tBus     uint8\n\tPinsSCL []Pin\n\tPinsSDA []Pin\n}\n\n// I2CConfig is used to store config info for I2C.\ntype I2CConfig struct {\n\tFrequency uint32\n\tSCL       Pin\n\tSDA       Pin\n}\n\n// Configure is intended to setup the I2C interface.\nfunc (i2c *I2C) Configure(config I2CConfig) error {\n\tif i2c.PinsSCL != nil {\n\t\tmatchSCL := slices.Index(i2c.PinsSCL, config.SCL) >= 0\n\t\tmatchSDA := slices.Index(i2c.PinsSDA, config.SDA) >= 0\n\t\tif !matchSCL && !matchSDA {\n\t\t\treturn errors.New(\"i2c: SCL and SDA pins are incorrect for this I2C instance\")\n\t\t} else if !matchSCL {\n\t\t\treturn errors.New(\"i2c: SCL pin is incorrect for this I2C instance\")\n\t\t} else if !matchSDA {\n\t\t\treturn errors.New(\"i2c: SDA pin is incorrect for this I2C instance\")\n\t\t}\n\t}\n\tif config.Frequency == 0 {\n\t\tconfig.Frequency = 100 * KHz\n\t}\n\ti2cConfigure(i2c.Bus, config.SCL, config.SDA, config.Frequency)\n\treturn nil\n}\n\n// SetBaudRate sets the I2C frequency.\nfunc (i2c *I2C) SetBaudRate(br uint32) error {\n\ti2cSetBaudRate(i2c.Bus, br)\n\treturn nil\n}\n\n// Tx does a single I2C transaction at the specified address.\nfunc (i2c *I2C) Tx(addr uint16, w, r []byte) error {\n\tvar wptr, rptr *byte\n\tvar wlen, rlen int\n\tif len(w) != 0 {\n\t\twptr = &w[0]\n\t\twlen = len(w)\n\t}\n\tif len(r) != 0 {\n\t\trptr = &r[0]\n\t\trlen = len(r)\n\t}\n\terrCode := i2cTransfer(i2c.Bus, addr, wptr, wlen, rptr, rlen)\n\tswitch errCode {\n\tcase 0:\n\t\treturn nil\n\tcase 1:\n\t\treturn errI2CNoDevices\n\tcase 2:\n\t\treturn errI2CMultipleDevices\n\tcase 3:\n\t\treturn errI2CWrongAddress\n\tdefault:\n\t\treturn errI2CBusError // unknown error code\n\t}\n}\n\n//export __tinygo_i2c_configure\nfunc i2cConfigure(bus uint8, scl Pin, sda Pin, frequency uint32)\n\n//export __tinygo_i2c_set_baud_rate\nfunc i2cSetBaudRate(bus uint8, br uint32)\n\n//export __tinygo_i2c_transfer\nfunc i2cTransfer(bus uint8, addr uint16, w *byte, wlen int, r *byte, rlen int) int\n\ntype UART struct {\n\tBus uint8\n}\n\n// Configure the UART.\nfunc (uart *UART) Configure(config UARTConfig) {\n\tuartConfigure(uart.Bus, config.TX, config.RX)\n}\n\n// Read from the UART.\nfunc (uart *UART) Read(data []byte) (n int, err error) {\n\treturn uartRead(uart.Bus, &data[0], len(data)), nil\n}\n\n// Write to the UART.\nfunc (uart *UART) Write(data []byte) (n int, err error) {\n\treturn uartWrite(uart.Bus, &data[0], len(data)), nil\n}\n\n// Buffered returns the number of bytes currently stored in the RX buffer.\nfunc (uart *UART) Buffered() int {\n\treturn 0\n}\n\n// ReadByte reads a single byte from the UART.\nfunc (uart *UART) ReadByte() (byte, error) {\n\tvar b byte\n\tuartRead(uart.Bus, &b, 1)\n\treturn b, nil\n}\n\n// WriteByte writes a single byte to the UART.\nfunc (uart *UART) WriteByte(b byte) error {\n\tuartWrite(uart.Bus, &b, 1)\n\treturn nil\n}\n\n//export __tinygo_uart_configure\nfunc uartConfigure(bus uint8, tx Pin, rx Pin)\n\n//export __tinygo_uart_read\nfunc uartRead(bus uint8, buf *byte, bufLen int) int\n\n//export __tinygo_uart_write\nfunc uartWrite(bus uint8, buf *byte, bufLen int) int\n\nvar (\n\thardwareUART0 = &UART{0}\n\thardwareUART1 = &UART{1}\n)\n\n// Some objects used by Atmel SAM D chips (samd21, samd51).\n// Defined here (without build tag) for convenience.\nvar (\n\tsercomUSART0 = UART{0}\n\tsercomUSART1 = UART{1}\n\tsercomUSART2 = UART{2}\n\tsercomUSART3 = UART{3}\n\tsercomUSART4 = UART{4}\n\tsercomUSART5 = UART{5}\n\n\tsercomSPIM0 = &SPI{0}\n\tsercomSPIM1 = &SPI{1}\n\tsercomSPIM2 = &SPI{2}\n\tsercomSPIM3 = &SPI{3}\n\tsercomSPIM4 = &SPI{4}\n\tsercomSPIM5 = &SPI{5}\n\tsercomSPIM6 = &SPI{6}\n\tsercomSPIM7 = &SPI{7}\n)\n\n// GetRNG returns 32 bits of random data from the WASI random source.\nfunc GetRNG() (uint32, error) {\n\tvar buf [4]byte\n\t_, err := rand.Read(buf[:])\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn uint32(buf[0])<<0 | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24, nil\n}\n"
  },
  {
    "path": "src/machine/machine_generic_peripherals.go",
    "content": "//go:build !baremetal && !arduino_mkr1000 && !arduino_mkrwifi1010 && !arduino_nano33 && !arduino_zero && !circuitplay_express && !feather_m0 && !feather_m4 && !grandcentral_m4 && !itsybitsy_m0 && !itsybitsy_m4 && !matrixportal_m4 && !metro_m4_airlift && !p1am_100 && !pybadge && !pygamer && !pyportal && !qtpy && !trinket_m0 && !wioterminal && !xiao\n\npackage machine\n\n// These peripherals are defined separately so that they can be excluded on\n// boards that define their peripherals in the board file (e.g. board_qtpy.go).\n\nvar (\n\tUART0 = hardwareUART0\n\tUART1 = hardwareUART1\n\tSPI0  = &SPI{0}\n\tSPI1  = &SPI{1}\n)\n"
  },
  {
    "path": "src/machine/machine_k210.go",
    "content": "//go:build k210\n\npackage machine\n\nimport (\n\t\"device/kendryte\"\n\t\"device/riscv\"\n\t\"errors\"\n\t\"runtime/interrupt\"\n\t\"unsafe\"\n)\n\nconst deviceName = kendryte.Device\n\nfunc CPUFrequency() uint32 {\n\treturn 390000000\n}\n\ntype fpioaPullMode uint8\ntype PinChange uint8\n\n// Pin modes.\nconst (\n\tPinInput PinMode = iota\n\tPinInputPullup\n\tPinInputPulldown\n\tPinOutput\n)\n\n// Deprecated: use PinInputPullup and PinInputPulldown instead.\nconst (\n\tPinInputPullUp   = PinInputPullup\n\tPinInputPullDown = PinInputPulldown\n)\n\n// FPIOA internal pull resistors.\nconst (\n\tfpioaPullNone fpioaPullMode = iota\n\tfpioaPullDown\n\tfpioaPullUp\n)\n\n// GPIOHS pin interrupt events.\nconst (\n\tPinRising PinChange = 1 << iota\n\tPinFalling\n\tPinToggle = PinRising | PinFalling\n)\n\nvar (\n\terrUnsupportedSPIController = errors.New(\"SPI controller not supported. Use SPI0 or SPI1.\")\n\terrI2CTxAbort               = errors.New(\"I2C transmission has been aborted.\")\n)\n\nfunc (p Pin) setFPIOAIOPull(pull fpioaPullMode) {\n\tswitch pull {\n\tcase fpioaPullNone:\n\t\tkendryte.FPIOA.IO[uint8(p)].ClearBits(kendryte.FPIOA_IO_PU & kendryte.FPIOA_IO_PD)\n\tcase fpioaPullUp:\n\t\tkendryte.FPIOA.IO[uint8(p)].SetBits(kendryte.FPIOA_IO_PU)\n\t\tkendryte.FPIOA.IO[uint8(p)].ClearBits(kendryte.FPIOA_IO_PD)\n\tcase fpioaPullDown:\n\t\tkendryte.FPIOA.IO[uint8(p)].ClearBits(kendryte.FPIOA_IO_PU)\n\t\tkendryte.FPIOA.IO[uint8(p)].SetBits(kendryte.FPIOA_IO_PD)\n\t}\n}\n\n// SetFPIOAFunction is used to configure the pin for one of the FPIOA functions.\n// Each pin on the Kendryte K210 can be configured with any of the available FPIOA functions.\nfunc (p Pin) SetFPIOAFunction(f FPIOAFunction) {\n\tkendryte.FPIOA.IO[uint8(p)].Set(fpioaFuncDefaults[uint8(f)])\n}\n\n// FPIOAFunction returns the current FPIOA function of the pin.\nfunc (p Pin) FPIOAFunction() FPIOAFunction {\n\treturn FPIOAFunction((kendryte.FPIOA.IO[uint8(p)].Get() & kendryte.FPIOA_IO_CH_SEL_Msk))\n}\n\n// Configure this pin with the given configuration.\n// The pin must already be set as GPIO or GPIOHS pin.\nfunc (p Pin) Configure(config PinConfig) {\n\tvar input bool\n\n\t// Check if the current pin's FPIOA function is either GPIO or GPIOHS.\n\tf := p.FPIOAFunction()\n\tif f < FUNC_GPIOHS0 || f > FUNC_GPIO7 {\n\t\treturn // The pin is not configured as GPIO or GPIOHS.\n\t}\n\n\t// Configure pin.\n\tkendryte.FPIOA.IO[uint8(p)].SetBits(kendryte.FPIOA_IO_OE_EN | kendryte.FPIOA_IO_IE_EN | kendryte.FPIOA_IO_ST | kendryte.FPIOA_IO_DS_Msk)\n\n\tswitch config.Mode {\n\tcase PinInput:\n\t\tp.setFPIOAIOPull(fpioaPullNone)\n\t\tinput = true\n\tcase PinInputPullup:\n\t\tp.setFPIOAIOPull(fpioaPullUp)\n\t\tinput = true\n\tcase PinInputPulldown:\n\t\tp.setFPIOAIOPull(fpioaPullDown)\n\t\tinput = true\n\tcase PinOutput:\n\t\tp.setFPIOAIOPull(fpioaPullNone)\n\t\tinput = false\n\t}\n\n\tif f >= FUNC_GPIO0 && f <= FUNC_GPIO7 {\n\t\t// Converts the IO pin number in the effective GPIO number (based on the FPIOA function).\n\t\tgpioPin := uint8(f - FUNC_GPIO0)\n\n\t\tif input {\n\t\t\tkendryte.GPIO.DIRECTION.ClearBits(1 << gpioPin)\n\t\t} else {\n\t\t\tkendryte.GPIO.DIRECTION.SetBits(1 << gpioPin)\n\t\t}\n\t} else if f >= FUNC_GPIOHS0 && f <= FUNC_GPIOHS31 {\n\t\t// Converts the IO pin number in the effective GPIOHS number (based on the FPIOA function).\n\t\tgpioPin := uint8(f - FUNC_GPIOHS0)\n\n\t\tif input {\n\t\t\tkendryte.GPIOHS.INPUT_EN.SetBits(1 << gpioPin)\n\t\t\tkendryte.GPIOHS.OUTPUT_EN.ClearBits(1 << gpioPin)\n\t\t} else {\n\t\t\tkendryte.GPIOHS.OUTPUT_EN.SetBits(1 << gpioPin)\n\t\t\tkendryte.GPIOHS.INPUT_EN.ClearBits(1 << gpioPin)\n\t\t}\n\t}\n}\n\n// Set the pin to high or low.\nfunc (p Pin) Set(high bool) {\n\n\t// Check if the current pin's FPIOA function is either GPIO or GPIOHS.\n\tf := p.FPIOAFunction()\n\tif f < FUNC_GPIOHS0 || f > FUNC_GPIO7 {\n\t\treturn // The pin is not configured as GPIO or GPIOHS.\n\t}\n\n\tif f >= FUNC_GPIO0 && f <= FUNC_GPIO7 {\n\t\tgpioPin := uint8(f - FUNC_GPIO0)\n\n\t\tif high {\n\t\t\tkendryte.GPIO.DATA_OUTPUT.SetBits(1 << gpioPin)\n\t\t} else {\n\t\t\tkendryte.GPIO.DATA_OUTPUT.ClearBits(1 << gpioPin)\n\t\t}\n\t} else if f >= FUNC_GPIOHS0 && f <= FUNC_GPIOHS31 {\n\t\tgpioPin := uint8(f - FUNC_GPIOHS0)\n\n\t\tif high {\n\t\t\tkendryte.GPIOHS.OUTPUT_VAL.SetBits(1 << gpioPin)\n\t\t} else {\n\t\t\tkendryte.GPIOHS.OUTPUT_VAL.ClearBits(1 << gpioPin)\n\t\t}\n\t}\n}\n\n// Get returns the current value of a GPIO pin.\nfunc (p Pin) Get() bool {\n\n\t// Check if the current pin's FPIOA function is either GPIO or GPIOHS.\n\tf := p.FPIOAFunction()\n\tif f < FUNC_GPIOHS0 || f > FUNC_GPIO7 {\n\t\treturn false // The pin is not configured as GPIO or GPIOHS.\n\t}\n\n\tvar val uint32\n\tif f >= FUNC_GPIO0 && f <= FUNC_GPIO7 {\n\t\tgpioPin := uint8(f - FUNC_GPIO0)\n\t\tval = kendryte.GPIO.DATA_INPUT.Get() & (1 << gpioPin)\n\t} else if f >= FUNC_GPIOHS0 && f <= FUNC_GPIOHS31 {\n\t\tgpioPin := uint8(f - FUNC_GPIOHS0)\n\t\tval = kendryte.GPIOHS.INPUT_VAL.Get() & (1 << gpioPin)\n\t}\n\treturn (val > 0)\n}\n\n// Callbacks to be called for GPIOHS pins configured with SetInterrupt.\nvar pinCallbacks [32]func(Pin)\n\n// SetInterrupt sets an interrupt to be executed when a particular pin changes\n// state. The pin should already be configured as an input, including a pull up\n// or down if no external pull is provided.\n//\n// You can pass a nil func to unset the pin change interrupt. If you do so,\n// the change parameter is ignored and can be set to any value (such as 0).\n// If the pin is already configured with a callback, you must first unset\n// this pins interrupt before you can set a new callback.\nfunc (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error {\n\n\t// Check if the pin is a GPIOHS pin.\n\tf := p.FPIOAFunction()\n\tif f < FUNC_GPIOHS0 || f > FUNC_GPIOHS31 {\n\t\treturn ErrInvalidDataPin\n\t}\n\n\tgpioPin := uint8(f - FUNC_GPIOHS0)\n\n\t// Clear all interrupts.\n\tkendryte.GPIOHS.RISE_IE.ClearBits(1 << gpioPin)\n\tkendryte.GPIOHS.FALL_IE.ClearBits(1 << gpioPin)\n\tkendryte.GPIOHS.HIGH_IE.ClearBits(1 << gpioPin)\n\tkendryte.GPIOHS.LOW_IE.ClearBits(1 << gpioPin)\n\n\t// Clear all the pending bits for this pin.\n\tkendryte.GPIOHS.RISE_IP.SetBits(1 << gpioPin)\n\tkendryte.GPIOHS.FALL_IP.SetBits(1 << gpioPin)\n\tkendryte.GPIOHS.HIGH_IP.SetBits(1 << gpioPin)\n\tkendryte.GPIOHS.LOW_IP.SetBits(1 << gpioPin)\n\n\tif callback == nil {\n\t\tif pinCallbacks[gpioPin] != nil {\n\t\t\tpinCallbacks[gpioPin] = nil\n\t\t}\n\t\treturn nil\n\t}\n\n\tif pinCallbacks[gpioPin] != nil {\n\t\t// The pin was already configured.\n\t\t// To properly re-configure a pin, unset it first and set a new\n\t\t// configuration.\n\t\treturn ErrNoPinChangeChannel\n\t}\n\n\tpinCallbacks[gpioPin] = callback\n\n\t// Enable interrupts.\n\tif change&PinRising != 0 {\n\t\tkendryte.GPIOHS.RISE_IE.SetBits(1 << gpioPin)\n\t}\n\tif change&PinFalling != 0 {\n\t\tkendryte.GPIOHS.FALL_IE.SetBits(1 << gpioPin)\n\t}\n\n\thandleInterrupt := func(inter interrupt.Interrupt) {\n\n\t\tpin := uint8(inter.GetNumber() - kendryte.IRQ_GPIOHS0)\n\n\t\tif kendryte.GPIOHS.RISE_IE.HasBits(1 << pin) {\n\t\t\tkendryte.GPIOHS.RISE_IE.ClearBits(1 << pin)\n\t\t\t// Acknowledge interrupt atomically.\n\t\t\triscv.AsmFull(\n\t\t\t\t\"amoor.w {}, {mask}, ({reg})\",\n\t\t\t\tmap[string]interface{}{\n\t\t\t\t\t\"mask\": uint32(1 << pin),\n\t\t\t\t\t\"reg\":  uintptr(unsafe.Pointer(&kendryte.GPIOHS.RISE_IP.Reg)),\n\t\t\t\t})\n\t\t\tkendryte.GPIOHS.RISE_IE.SetBits(1 << pin)\n\t\t}\n\n\t\tif kendryte.GPIOHS.FALL_IE.HasBits(1 << pin) {\n\t\t\tkendryte.GPIOHS.FALL_IE.ClearBits(1 << pin)\n\t\t\t// Acknowledge interrupt atomically.\n\t\t\triscv.AsmFull(\n\t\t\t\t\"amoor.w {}, {mask}, ({reg})\",\n\t\t\t\tmap[string]interface{}{\n\t\t\t\t\t\"mask\": uint32(1 << pin),\n\t\t\t\t\t\"reg\":  uintptr(unsafe.Pointer(&kendryte.GPIOHS.FALL_IP.Reg)),\n\t\t\t\t})\n\t\t\tkendryte.GPIOHS.FALL_IE.SetBits(1 << pin)\n\t\t}\n\n\t\tpinCallbacks[pin](Pin(pin))\n\t}\n\n\tvar ir interrupt.Interrupt\n\n\tswitch f {\n\tcase FUNC_GPIOHS0:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS0, handleInterrupt)\n\tcase FUNC_GPIOHS1:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS1, handleInterrupt)\n\tcase FUNC_GPIOHS2:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS2, handleInterrupt)\n\tcase FUNC_GPIOHS3:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS3, handleInterrupt)\n\tcase FUNC_GPIOHS4:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS4, handleInterrupt)\n\tcase FUNC_GPIOHS5:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS5, handleInterrupt)\n\tcase FUNC_GPIOHS6:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS6, handleInterrupt)\n\tcase FUNC_GPIOHS7:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS7, handleInterrupt)\n\tcase FUNC_GPIOHS8:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS8, handleInterrupt)\n\tcase FUNC_GPIOHS9:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS9, handleInterrupt)\n\tcase FUNC_GPIOHS10:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS10, handleInterrupt)\n\tcase FUNC_GPIOHS11:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS11, handleInterrupt)\n\tcase FUNC_GPIOHS12:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS12, handleInterrupt)\n\tcase FUNC_GPIOHS13:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS13, handleInterrupt)\n\tcase FUNC_GPIOHS14:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS14, handleInterrupt)\n\tcase FUNC_GPIOHS15:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS15, handleInterrupt)\n\tcase FUNC_GPIOHS16:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS16, handleInterrupt)\n\tcase FUNC_GPIOHS17:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS17, handleInterrupt)\n\tcase FUNC_GPIOHS18:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS18, handleInterrupt)\n\tcase FUNC_GPIOHS19:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS19, handleInterrupt)\n\tcase FUNC_GPIOHS20:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS20, handleInterrupt)\n\tcase FUNC_GPIOHS21:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS21, handleInterrupt)\n\tcase FUNC_GPIOHS22:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS22, handleInterrupt)\n\tcase FUNC_GPIOHS23:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS23, handleInterrupt)\n\tcase FUNC_GPIOHS24:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS24, handleInterrupt)\n\tcase FUNC_GPIOHS25:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS25, handleInterrupt)\n\tcase FUNC_GPIOHS26:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS26, handleInterrupt)\n\tcase FUNC_GPIOHS27:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS27, handleInterrupt)\n\tcase FUNC_GPIOHS28:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS28, handleInterrupt)\n\tcase FUNC_GPIOHS29:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS29, handleInterrupt)\n\tcase FUNC_GPIOHS30:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS30, handleInterrupt)\n\tcase FUNC_GPIOHS31:\n\t\tir = interrupt.New(kendryte.IRQ_GPIOHS31, handleInterrupt)\n\t}\n\n\tir.SetPriority(5)\n\tir.Enable()\n\n\treturn nil\n\n}\n\ntype UART struct {\n\tBus    *kendryte.UARTHS_Type\n\tBuffer *RingBuffer\n}\n\nvar (\n\tUART0  = &_UART0\n\t_UART0 = UART{Bus: kendryte.UARTHS, Buffer: NewRingBuffer()}\n)\n\nfunc (uart *UART) Configure(config UARTConfig) {\n\n\t// Use default baudrate  if not set.\n\tif config.BaudRate == 0 {\n\t\tconfig.BaudRate = 115200\n\t}\n\n\t// Use default pins if not set.\n\tif config.TX == 0 && config.RX == 0 {\n\t\tconfig.TX = UART_TX_PIN\n\t\tconfig.RX = UART_RX_PIN\n\t}\n\n\tconfig.TX.SetFPIOAFunction(FUNC_UARTHS_TX)\n\tconfig.RX.SetFPIOAFunction(FUNC_UARTHS_RX)\n\n\tdiv := CPUFrequency()/config.BaudRate - 1\n\n\tuart.Bus.DIV.Set(div)\n\tuart.Bus.TXCTRL.Set(kendryte.UARTHS_TXCTRL_TXEN)\n\tuart.Bus.RXCTRL.Set(kendryte.UARTHS_RXCTRL_RXEN)\n\n\t// Enable interrupts on receive.\n\tuart.Bus.IE.Set(kendryte.UARTHS_IE_RXWM)\n\n\tintr := interrupt.New(kendryte.IRQ_UARTHS, _UART0.handleInterrupt)\n\tintr.SetPriority(5)\n\tintr.Enable()\n}\n\nfunc (uart *UART) handleInterrupt(interrupt.Interrupt) {\n\trxdata := uart.Bus.RXDATA.Get()\n\tc := byte(rxdata)\n\tif uint32(c) != rxdata {\n\t\t// The rxdata has other bits set than just the low 8 bits. This probably\n\t\t// means that the 'empty' flag is set, which indicates there is no data\n\t\t// to be read and the byte is garbage. Ignore this byte.\n\t\treturn\n\t}\n\tuart.Receive(c)\n}\n\nfunc (uart *UART) writeByte(c byte) error {\n\tfor uart.Bus.TXDATA.Get()&kendryte.UARTHS_TXDATA_FULL != 0 {\n\t}\n\n\tuart.Bus.TXDATA.Set(uint32(c))\n\treturn nil\n}\n\nfunc (uart *UART) flush() {}\n\ntype SPI struct {\n\tBus *kendryte.SPI_Type\n}\n\n// SPIConfig is used to store config info for SPI.\ntype SPIConfig struct {\n\tFrequency uint32\n\tSCK       Pin\n\tSDO       Pin\n\tSDI       Pin\n\tLSBFirst  bool\n\tMode      uint8\n}\n\n// Configure is intended to setup the SPI interface.\n// Only SPI controller 0 and 1 can be used because SPI2 is a special\n// peripheral-mode controller and SPI3 is used for flashing.\nfunc (spi *SPI) Configure(config SPIConfig) error {\n\t// Use default pins if not set.\n\tif config.SCK == 0 && config.SDO == 0 && config.SDI == 0 {\n\t\tconfig.SCK = SPI0_SCK_PIN\n\t\tconfig.SDO = SPI0_SDO_PIN\n\t\tconfig.SDI = SPI0_SDI_PIN\n\t}\n\n\t// Enable APB2 clock.\n\tkendryte.SYSCTL.CLK_EN_CENT.SetBits(kendryte.SYSCTL_CLK_EN_CENT_APB2_CLK_EN)\n\n\tswitch spi.Bus {\n\tcase kendryte.SPI0:\n\t\t// Initialize SPI clock.\n\t\tkendryte.SYSCTL.CLK_EN_PERI.SetBits(kendryte.SYSCTL_CLK_EN_PERI_SPI0_CLK_EN)\n\t\tkendryte.SYSCTL.CLK_TH1.ClearBits(kendryte.SYSCTL_CLK_TH1_SPI0_CLK_Msk)\n\n\t\t// Initialize pins.\n\t\tconfig.SCK.SetFPIOAFunction(FUNC_SPI0_SCLK)\n\t\tconfig.SDO.SetFPIOAFunction(FUNC_SPI0_D0)\n\t\tconfig.SDI.SetFPIOAFunction(FUNC_SPI0_D1)\n\tcase kendryte.SPI1:\n\t\t// Initialize SPI clock.\n\t\tkendryte.SYSCTL.CLK_EN_PERI.SetBits(kendryte.SYSCTL_CLK_EN_PERI_SPI1_CLK_EN)\n\t\tkendryte.SYSCTL.CLK_TH1.ClearBits(kendryte.SYSCTL_CLK_TH1_SPI1_CLK_Msk)\n\n\t\t// Initialize pins.\n\t\tconfig.SCK.SetFPIOAFunction(FUNC_SPI1_SCLK)\n\t\tconfig.SDO.SetFPIOAFunction(FUNC_SPI1_D0)\n\t\tconfig.SDI.SetFPIOAFunction(FUNC_SPI1_D1)\n\tdefault:\n\t\treturn errUnsupportedSPIController\n\t}\n\n\t// Set default frequency.\n\tif config.Frequency == 0 {\n\t\tconfig.Frequency = 4000000 // 4MHz\n\t}\n\n\tbaudr := CPUFrequency() / config.Frequency\n\tspi.Bus.BAUDR.Set(baudr)\n\n\t// Configure SPI mode 0, standard frame format, 8-bit data, little-endian.\n\tspi.Bus.IMR.Set(0)\n\tspi.Bus.DMACR.Set(0)\n\tspi.Bus.DMATDLR.Set(0x10)\n\tspi.Bus.DMARDLR.Set(0)\n\tspi.Bus.SER.Set(0)\n\tspi.Bus.SSIENR.Set(0)\n\tspi.Bus.CTRLR0.Set((7 << 16))\n\tspi.Bus.SPI_CTRLR0.Set(0)\n\tspi.Bus.ENDIAN.Set(0)\n\n\treturn nil\n}\n\n// Transfer writes/reads a single byte using the SPI interface.\nfunc (spi *SPI) Transfer(w byte) (byte, error) {\n\tspi.Bus.SSIENR.Set(0)\n\n\t// Set transfer-receive mode.\n\tspi.Bus.CTRLR0.ClearBits(0x3 << 8)\n\n\t// Enable/disable SPI.\n\tspi.Bus.SSIENR.Set(1)\n\tdefer spi.Bus.SSIENR.Set(0)\n\n\t// Enable/disable device.\n\tspi.Bus.SER.Set(0x1)\n\tdefer spi.Bus.SER.Set(0)\n\n\tspi.Bus.DR0.Set(uint32(w))\n\n\t// Wait for transfer.\n\tfor spi.Bus.SR.Get()&0x05 != 0x04 {\n\t}\n\n\t// Wait for data.\n\tfor spi.Bus.RXFLR.Get() == 0 {\n\t}\n\n\treturn byte(spi.Bus.DR0.Get()), nil\n}\n\n// I2C on the K210.\ntype I2C struct {\n\tBus kendryte.I2C_Type\n}\n\nvar (\n\tI2C0 = (*I2C)(unsafe.Pointer(kendryte.I2C0))\n\tI2C1 = (*I2C)(unsafe.Pointer(kendryte.I2C1))\n\tI2C2 = (*I2C)(unsafe.Pointer(kendryte.I2C2))\n)\n\n// I2CConfig is used to store config info for I2C.\ntype I2CConfig struct {\n\tFrequency uint32\n\tSCL       Pin\n\tSDA       Pin\n}\n\n// Configure is intended to setup the I2C interface.\nfunc (i2c *I2C) Configure(config I2CConfig) error {\n\n\tif config.Frequency == 0 {\n\t\tconfig.Frequency = 100 * KHz\n\t}\n\n\tif config.SDA == 0 && config.SCL == 0 {\n\t\tconfig.SDA = I2C0_SDA_PIN\n\t\tconfig.SCL = I2C0_SCL_PIN\n\t}\n\n\t// Enable APB0 clock.\n\tkendryte.SYSCTL.CLK_EN_CENT.SetBits(kendryte.SYSCTL_CLK_EN_CENT_APB0_CLK_EN)\n\n\tswitch &i2c.Bus {\n\tcase kendryte.I2C0:\n\t\t// Initialize I2C0 clock.\n\t\tkendryte.SYSCTL.CLK_EN_PERI.SetBits(kendryte.SYSCTL_CLK_EN_PERI_I2C0_CLK_EN)\n\t\tkendryte.SYSCTL.CLK_TH5.ReplaceBits(0x03, kendryte.SYSCTL_CLK_TH5_I2C0_CLK_Msk, kendryte.SYSCTL_CLK_TH5_I2C0_CLK_Pos)\n\n\t\t// Initialize pins.\n\t\tconfig.SDA.SetFPIOAFunction(FUNC_I2C0_SDA)\n\t\tconfig.SCL.SetFPIOAFunction(FUNC_I2C0_SCLK)\n\tcase kendryte.I2C1:\n\t\t// Initialize I2C1 clock.\n\t\tkendryte.SYSCTL.CLK_EN_PERI.SetBits(kendryte.SYSCTL_CLK_EN_PERI_I2C1_CLK_EN)\n\t\tkendryte.SYSCTL.CLK_TH5.ReplaceBits(0x03, kendryte.SYSCTL_CLK_TH5_I2C1_CLK_Msk, kendryte.SYSCTL_CLK_TH5_I2C1_CLK_Pos)\n\n\t\t// Initialize pins.\n\t\tconfig.SDA.SetFPIOAFunction(FUNC_I2C1_SDA)\n\t\tconfig.SCL.SetFPIOAFunction(FUNC_I2C1_SCLK)\n\tcase kendryte.I2C2:\n\t\t// Initialize I2C2 clock.\n\t\tkendryte.SYSCTL.CLK_EN_PERI.SetBits(kendryte.SYSCTL_CLK_EN_PERI_I2C2_CLK_EN)\n\t\tkendryte.SYSCTL.CLK_TH5.ReplaceBits(0x03, kendryte.SYSCTL_CLK_TH5_I2C2_CLK_Msk, kendryte.SYSCTL_CLK_TH5_I2C2_CLK_Pos)\n\n\t\t// Initialize pins.\n\t\tconfig.SDA.SetFPIOAFunction(FUNC_I2C2_SDA)\n\t\tconfig.SCL.SetFPIOAFunction(FUNC_I2C2_SCLK)\n\t}\n\n\ti2c.SetBaudRate(config.Frequency)\n\n\ti2c.Bus.INTR_MASK.Set(0)\n\ti2c.Bus.DMA_CR.Set(0x03)\n\ti2c.Bus.DMA_RDLR.Set(0)\n\ti2c.Bus.DMA_TDLR.Set(0x4)\n\n\treturn nil\n}\n\n// SetBaudRate sets the communication speed for I2C.\nfunc (i2c *I2C) SetBaudRate(br uint32) error {\n\tdiv := CPUFrequency() / br / 16\n\n\t// Disable controller before setting the prescale register.\n\ti2c.Bus.ENABLE.Set(0)\n\n\ti2c.Bus.CON.Set(0x63)\n\n\t// Set prescaler registers.\n\ti2c.Bus.SS_SCL_HCNT.Set(uint32(div))\n\ti2c.Bus.SS_SCL_LCNT.Set(uint32(div))\n\n\treturn nil\n}\n\n// Tx does a single I2C transaction at the specified address.\n// It clocks out the given address, writes the bytes in w, reads back len(r)\n// bytes and stores them in r, and generates a stop condition on the bus.\nfunc (i2c *I2C) Tx(addr uint16, w, r []byte) error {\n\t// Set peripheral address.\n\ti2c.Bus.TAR.Set(uint32(addr))\n\t// Enable controller.\n\ti2c.Bus.ENABLE.Set(1)\n\n\tif len(w) != 0 {\n\t\ti2c.Bus.CLR_TX_ABRT.Set(i2c.Bus.CLR_TX_ABRT.Get())\n\t\tdataLen := uint32(len(w))\n\t\tdi := 0\n\n\t\tfor dataLen != 0 {\n\t\t\tfifoLen := 8 - i2c.Bus.TXFLR.Get()\n\t\t\tif dataLen < fifoLen {\n\t\t\t\tfifoLen = dataLen\n\t\t\t}\n\n\t\t\tfor i := uint32(0); i < fifoLen; i++ {\n\t\t\t\ti2c.Bus.DATA_CMD.Set(uint32(w[di]))\n\t\t\t\tdi += 1\n\t\t\t}\n\t\t\tif i2c.Bus.TX_ABRT_SOURCE.Get() != 0 {\n\t\t\t\treturn errI2CTxAbort\n\t\t\t}\n\t\t\tdataLen -= fifoLen\n\t\t}\n\n\t\t// Wait for transmission to complete.\n\t\tfor i2c.Bus.STATUS.HasBits(kendryte.I2C_STATUS_ACTIVITY) || !i2c.Bus.STATUS.HasBits(kendryte.I2C_STATUS_TFE) {\n\t\t}\n\n\t\tif i2c.Bus.TX_ABRT_SOURCE.Get() != 0 {\n\t\t\treturn errI2CTxAbort\n\t\t}\n\t}\n\tif len(r) != 0 {\n\t\tdataLen := uint32(len(r))\n\t\tcmdLen := uint32(len(r))\n\t\tdi := 0\n\n\t\tfor dataLen != 0 || cmdLen != 0 {\n\t\t\tfifoLen := i2c.Bus.RXFLR.Get()\n\t\t\tif dataLen < fifoLen {\n\t\t\t\tfifoLen = dataLen\n\t\t\t}\n\t\t\tfor i := uint32(0); i < fifoLen; i++ {\n\t\t\t\tr[di] = byte(i2c.Bus.DATA_CMD.Get())\n\t\t\t\tdi += 1\n\t\t\t}\n\t\t\tdataLen -= fifoLen\n\n\t\t\tfifoLen = 8 - i2c.Bus.TXFLR.Get()\n\t\t\tif cmdLen < fifoLen {\n\t\t\t\tfifoLen = cmdLen\n\t\t\t}\n\t\t\tfor i := uint32(0); i < fifoLen; i++ {\n\t\t\t\ti2c.Bus.DATA_CMD.Set(0x100)\n\t\t\t}\n\t\t\tif i2c.Bus.TX_ABRT_SOURCE.Get() != 0 {\n\t\t\t\treturn errI2CTxAbort\n\t\t\t}\n\t\t\tcmdLen -= fifoLen\n\t\t}\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "src/machine/machine_mimxrt1062.go",
    "content": "//go:build mimxrt1062\n\npackage machine\n\nimport (\n\t\"device/nxp\"\n\t\"math/bits\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n)\n\n// Peripheral abstraction layer for the MIMXRT1062\n\nconst deviceName = nxp.Device\n\nfunc CPUFrequency() uint32 {\n\treturn 600000000\n}\n\nconst (\n\t// GPIO\n\tPinInput PinMode = iota\n\tPinInputPullup\n\tPinInputPulldown\n\tPinOutput\n\tPinOutputOpenDrain\n\tPinDisable\n\n\t// ADC\n\tPinInputAnalog\n\n\t// UART\n\tPinModeUARTTX\n\tPinModeUARTRX\n\n\t// SPI\n\tPinModeSPISDI\n\tPinModeSPISDO\n\tPinModeSPICLK\n\tPinModeSPICS\n\n\t// I2C\n\tPinModeI2CSDA\n\tPinModeI2CSCL\n)\n\n// Deprecated: use PinInputPullup and PinInputPulldown instead.\nconst (\n\tPinInputPullUp   = PinInputPullup\n\tPinInputPullDown = PinInputPulldown\n)\n\ntype PinChange uint8\n\nconst (\n\tPinRising PinChange = iota + 2\n\tPinFalling\n\tPinToggle\n)\n\n// pinJumpTable represents a function lookup table for all 128 GPIO pins.\n//\n// There are 4 GPIO ports (A-D) and 32 pins (0-31) on each port. The uint8 value\n// of a Pin is used as table index. The number of pins with a defined (non-nil)\n// function is recorded in the uint8 field numDefined.\ntype pinJumpTable struct {\n\tlut        [4 * 32]func(Pin)\n\tnumDefined uint8\n}\n\n// pinISR stores the interrupt callbacks for GPIO pins, and pinInterrupt holds\n// an interrupt service routine that dispatches the interrupt callbacks.\nvar (\n\tpinISR       pinJumpTable\n\tpinInterrupt *interrupt.Interrupt\n)\n\n// From the i.MXRT1062 Processor Reference Manual (Chapter 12 - GPIO):\n//\n// |  High-speed GPIOs exist in this device:\n// |    - GPIO1-5 are standard-speed GPIOs that run off the IPG_CLK_ROOT, while\n// |      GPIO6-9 are high-speed GPIOs that run at the AHB_CLK_ROOT frequency.\n// |      See the table \"System Clocks, Gating, and Override\" in CCM chapter.\n// |    - Regular GPIO and high speed GPIO are paired (GPIO1 and GPIO6 share the\n// |      same pins, GPIO2 and GPIO7 share, etc). The IOMUXC_GPR_GPR26-29\n// |      registers are used to determine if the regular or high-speed GPIO\n// |      module is used for the GPIO pins on a given port.\n//\n// Therefore, we do not even use GPIO1-5 and instead use their high-speed\n// partner for all pins. This is configured at startup in the runtime package\n// (func initPins() in `runtime_mimxrt1062.go`).\n// We cannot declare 32 pins for all available ports (GPIO1-9) anyway, since Pin\n// is only uint8, and 9*32=288 > 256, so something has to be sacrificed.\n\nconst (\n\tportA Pin = iota * 32 // GPIO1(6)\n\tportB                 // GPIO2(7)\n\tportC                 // GPIO3(8)\n\tportD                 // GPIO4(9)\n)\n\nconst (\n\t//                   [Pad]:      Alt Func 0       Alt Func 1       Alt Func 2           Alt Func 3            Alt Func 4            Alt Func 5   Alt Func 6            Alt Func 7            Alt Func 8             Alt Func 9\n\t//                   ----------  ---------------  ---------------  -------------------  --------------------  --------------------  -----------  --------------------  --------------------  ---------------------  ----------------\n\tPA0  = portA + 0  // [AD_B0_00]: FLEXPWM2_PWMA03  XBAR1_INOUT14    REF_CLK_32K          USB_OTG2_ID           LPI2C1_SCLS           GPIO1_IO00   USDHC1_RESET_B        LPSPI3_SCK             ~                      ~\n\tPA1  = portA + 1  // [AD_B0_01]: FLEXPWM2_PWMB03  XBAR1_INOUT15    REF_CLK_24M          USB_OTG1_ID           LPI2C1_SDAS           GPIO1_IO01   EWM_OUT_B             LPSPI3_SDO             ~                      ~\n\tPA2  = portA + 2  // [AD_B0_02]: FLEXCAN2_TX      XBAR1_INOUT16    LPUART6_TX           USB_OTG1_PWR          FLEXPWM1_PWMX00       GPIO1_IO02   LPI2C1_HREQ           LPSPI3_SDI             ~                      ~\n\tPA3  = portA + 3  // [AD_B0_03]: FLEXCAN2_RX      XBAR1_INOUT17    LPUART6_RX           USB_OTG1_OC           FLEXPWM1_PWMX01       GPIO1_IO03   REF_CLK_24M           LPSPI3_PCS0            ~                      ~\n\tPA4  = portA + 4  // [AD_B0_04]: SRC_BOOT_MODE00  MQS_RIGHT        ENET_TX_DATA03       SAI2_TX_SYNC          CSI_DATA09            GPIO1_IO04   PIT_TRIGGER00         LPSPI3_PCS1            ~                      ~\n\tPA5  = portA + 5  // [AD_B0_05]: SRC_BOOT_MODE01  MQS_LEFT         ENET_TX_DATA02       SAI2_TX_BCLK          CSI_DATA08            GPIO1_IO05   XBAR1_INOUT17         LPSPI3_PCS2            ~                      ~\n\tPA6  = portA + 6  // [AD_B0_06]: JTAG_TMS         GPT2_COMPARE1    ENET_RX_CLK          SAI2_RX_BCLK          CSI_DATA07            GPIO1_IO06   XBAR1_INOUT18         LPSPI3_PCS3            ~                      ~\n\tPA7  = portA + 7  // [AD_B0_07]: JTAG_TCK         GPT2_COMPARE2    ENET_TX_ER           SAI2_RX_SYNC          CSI_DATA06            GPIO1_IO07   XBAR1_INOUT19         ENET_1588_EVENT3_OUT   ~                      ~\n\tPA8  = portA + 8  // [AD_B0_08]: JTAG_MOD         GPT2_COMPARE3    ENET_RX_DATA03       SAI2_RX_DATA          CSI_DATA05            GPIO1_IO08   XBAR1_IN20            ENET_1588_EVENT3_IN    ~                      ~\n\tPA9  = portA + 9  // [AD_B0_09]: JTAG_TDI         FLEXPWM2_PWMA03  ENET_RX_DATA02       SAI2_TX_DATA          CSI_DATA04            GPIO1_IO09   XBAR1_IN21            GPT2_CLK              SEMC_DQS4               ~\n\tPA10 = portA + 10 // [AD_B0_10]: JTAG_TDO         FLEXPWM1_PWMA03  ENET_CRS             SAI2_MCLK             CSI_DATA03            GPIO1_IO10   XBAR1_IN22            ENET_1588_EVENT0_OUT  FLEXCAN3_TX            ARM_TRACE_SWO\n\tPA11 = portA + 11 // [AD_B0_11]: JTAG_TRSTB       FLEXPWM1_PWMB03  ENET_COL             WDOG1_WDOG_B          CSI_DATA02            GPIO1_IO11   XBAR1_IN23            ENET_1588_EVENT0_IN   FLEXCAN3_RX            SEMC_CLK6\n\tPA12 = portA + 12 // [AD_B0_12]: LPI2C4_SCL       CCM_PMIC_READY   LPUART1_TX           WDOG2_WDOG_B          FLEXPWM1_PWMX02       GPIO1_IO12   ENET_1588_EVENT1_OUT  NMI_GLUE_NMI           ~                      ~\n\tPA13 = portA + 13 // [AD_B0_13]: LPI2C4_SDA       GPT1_CLK         LPUART1_RX           EWM_OUT_B             FLEXPWM1_PWMX03       GPIO1_IO13   ENET_1588_EVENT1_IN   REF_CLK_24M            ~                      ~\n\tPA14 = portA + 14 // [AD_B0_14]: USB_OTG2_OC      XBAR1_IN24       LPUART1_CTS_B        ENET_1588_EVENT0_OUT  CSI_VSYNC             GPIO1_IO14   FLEXCAN2_TX           FLEXCAN3_TX            ~                      ~\n\tPA15 = portA + 15 // [AD_B0_15]: USB_OTG2_PWR     XBAR1_IN25       LPUART1_RTS_B        ENET_1588_EVENT0_IN   CSI_HSYNC             GPIO1_IO15   FLEXCAN2_RX           WDOG1_WDOG_RST_B_DEB  FLEXCAN3_RX             ~\n\tPA16 = portA + 16 // [AD_B1_00]: USB_OTG2_ID      QTIMER3_TIMER0   LPUART2_CTS_B        LPI2C1_SCL            WDOG1_B               GPIO1_IO16   USDHC1_WP             KPP_ROW07             ENET2_1588_EVENT0_OUT  FLEXIO3_FLEXIO00\n\tPA17 = portA + 17 // [AD_B1_01]: USB_OTG1_PWR     QTIMER3_TIMER1   LPUART2_RTS_B        LPI2C1_SDA            CCM_PMIC_READY        GPIO1_IO17   USDHC1_VSELECT        KPP_COL07             ENET2_1588_EVENT0_IN   FLEXIO3_FLEXIO01\n\tPA18 = portA + 18 // [AD_B1_02]: USB_OTG1_ID      QTIMER3_TIMER2   LPUART2_TX           SPDIF_OUT             ENET_1588_EVENT2_OUT  GPIO1_IO18   USDHC1_CD_B           KPP_ROW06             GPT2_CLK               FLEXIO3_FLEXIO02\n\tPA19 = portA + 19 // [AD_B1_03]: USB_OTG1_OC      QTIMER3_TIMER3   LPUART2_RX           SPDIF_IN              ENET_1588_EVENT2_IN   GPIO1_IO19   USDHC2_CD_B           KPP_COL06             GPT2_CAPTURE1          FLEXIO3_FLEXIO03\n\tPA20 = portA + 20 // [AD_B1_04]: FLEXSPIB_DATA03  ENET_MDC         LPUART3_CTS_B        SPDIF_SR_CLK          CSI_PIXCLK            GPIO1_IO20   USDHC2_DATA0          KPP_ROW05             GPT2_CAPTURE2          FLEXIO3_FLEXIO04\n\tPA21 = portA + 21 // [AD_B1_05]: FLEXSPIB_DATA02  ENET_MDIO        LPUART3_RTS_B        SPDIF_OUT             CSI_MCLK              GPIO1_IO21   USDHC2_DATA1          KPP_COL05             GPT2_COMPARE1          FLEXIO3_FLEXIO05\n\tPA22 = portA + 22 // [AD_B1_06]: FLEXSPIB_DATA01  LPI2C3_SDA       LPUART3_TX           SPDIF_LOCK            CSI_VSYNC             GPIO1_IO22   USDHC2_DATA2          KPP_ROW04             GPT2_COMPARE2          FLEXIO3_FLEXIO06\n\tPA23 = portA + 23 // [AD_B1_07]: FLEXSPIB_DATA00  LPI2C3_SCL       LPUART3_RX           SPDIF_EXT_CLK         CSI_HSYNC             GPIO1_IO23   USDHC2_DATA3          KPP_COL04             GPT2_COMPARE3          FLEXIO3_FLEXIO07\n\tPA24 = portA + 24 // [AD_B1_08]: FLEXSPIA_SS1_B   FLEXPWM4_PWMA00  FLEXCAN1_TX          CCM_PMIC_READY        CSI_DATA09            GPIO1_IO24   USDHC2_CMD            KPP_ROW03             FLEXIO3_FLEXIO08        ~\n\tPA25 = portA + 25 // [AD_B1_09]: FLEXSPIA_DQS     FLEXPWM4_PWMA01  FLEXCAN1_RX          SAI1_MCLK             CSI_DATA08            GPIO1_IO25   USDHC2_CLK            KPP_COL03             FLEXIO3_FLEXIO09        ~\n\tPA26 = portA + 26 // [AD_B1_10]: FLEXSPIA_DATA03  WDOG1_B          LPUART8_TX           SAI1_RX_SYNC          CSI_DATA07            GPIO1_IO26   USDHC2_WP             KPP_ROW02             ENET2_1588_EVENT1_OUT  FLEXIO3_FLEXIO10\n\tPA27 = portA + 27 // [AD_B1_11]: FLEXSPIA_DATA02  EWM_OUT_B        LPUART8_RX           SAI1_RX_BCLK          CSI_DATA06            GPIO1_IO27   USDHC2_RESET_B        KPP_COL02             ENET2_1588_EVENT1_IN   FLEXIO3_FLEXIO11\n\tPA28 = portA + 28 // [AD_B1_12]: FLEXSPIA_DATA01  ACMP_OUT00       LPSPI3_PCS0          SAI1_RX_DATA00        CSI_DATA05            GPIO1_IO28   USDHC2_DATA4          KPP_ROW01             ENET2_1588_EVENT2_OUT  FLEXIO3_FLEXIO12\n\tPA29 = portA + 29 // [AD_B1_13]: FLEXSPIA_DATA00  ACMP_OUT01       LPSPI3_SDI           SAI1_TX_DATA00        CSI_DATA04            GPIO1_IO29   USDHC2_DATA5          KPP_COL01             ENET2_1588_EVENT2_IN   FLEXIO3_FLEXIO13\n\tPA30 = portA + 30 // [AD_B1_14]: FLEXSPIA_SCLK    ACMP_OUT02       LPSPI3_SDO           SAI1_TX_BCLK          CSI_DATA03            GPIO1_IO30   USDHC2_DATA6          KPP_ROW00             ENET2_1588_EVENT3_OUT  FLEXIO3_FLEXIO14\n\tPA31 = portA + 31 // [AD_B1_15]: FLEXSPIA_SS0_B   ACMP_OUT03       LPSPI3_SCK           SAI1_TX_SYNC          CSI_DATA02            GPIO1_IO31   USDHC2_DATA7          KPP_COL00             ENET2_1588_EVENT3_IN   FLEXIO3_FLEXIO15\n\n\tPB0  = portB + 0  // [B0_00]:    LCD_CLK          QTIMER1_TIMER0   MQS_RIGHT            LPSPI4_PCS0           FLEXIO2_FLEXIO00      GPIO2_IO00   SEMC_CSX01            ENET2_MDC              ~                      ~\n\tPB1  = portB + 1  // [B0_01]:    LCD_ENABLE       QTIMER1_TIMER1   MQS_LEFT             LPSPI4_SDI            FLEXIO2_FLEXIO01      GPIO2_IO01   SEMC_CSX02            ENET2_MDIO             ~                      ~\n\tPB2  = portB + 2  // [B0_02]:    LCD_HSYNC        QTIMER1_TIMER2   FLEXCAN1_TX          LPSPI4_SDO            FLEXIO2_FLEXIO02      GPIO2_IO02   SEMC_CSX03            ENET2_1588_EVENT0_OUT  ~                      ~\n\tPB3  = portB + 3  // [B0_03]:    LCD_VSYNC        QTIMER2_TIMER0   FLEXCAN1_RX          LPSPI4_SCK            FLEXIO2_FLEXIO03      GPIO2_IO03   WDOG2_RESET_B_DEB     ENET2_1588_EVENT0_IN   ~                      ~\n\tPB4  = portB + 4  // [B0_04]:    LCD_DATA00       QTIMER2_TIMER1   LPI2C2_SCL           ARM_TRACE0            FLEXIO2_FLEXIO04      GPIO2_IO04   SRC_BOOT_CFG00        ENET2_TDATA03          ~                      ~\n\tPB5  = portB + 5  // [B0_05]:    LCD_DATA01       QTIMER2_TIMER2   LPI2C2_SDA           ARM_TRACE1            FLEXIO2_FLEXIO05      GPIO2_IO05   SRC_BOOT_CFG01        ENET2_TDATA02          ~                      ~\n\tPB6  = portB + 6  // [B0_06]:    LCD_DATA02       QTIMER3_TIMER0   FLEXPWM2_PWMA00      ARM_TRACE2            FLEXIO2_FLEXIO06      GPIO2_IO06   SRC_BOOT_CFG02        ENET2_RX_CLK           ~                      ~\n\tPB7  = portB + 7  // [B0_07]:    LCD_DATA03       QTIMER3_TIMER1   FLEXPWM2_PWMB00      ARM_TRACE3            FLEXIO2_FLEXIO07      GPIO2_IO07   SRC_BOOT_CFG03        ENET2_TX_ER            ~                      ~\n\tPB8  = portB + 8  // [B0_08]:    LCD_DATA04       QTIMER3_TIMER2   FLEXPWM2_PWMA01      LPUART3_TX            FLEXIO2_FLEXIO08      GPIO2_IO08   SRC_BOOT_CFG04        ENET2_RDATA03          ~                      ~\n\tPB9  = portB + 9  // [B0_09]:    LCD_DATA05       QTIMER4_TIMER0   FLEXPWM2_PWMB01      LPUART3_RX            FLEXIO2_FLEXIO09      GPIO2_IO09   SRC_BOOT_CFG05        ENET2_RDATA02          ~                      ~\n\tPB10 = portB + 10 // [B0_10]:    LCD_DATA06       QTIMER4_TIMER1   FLEXPWM2_PWMA02      SAI1_TX_DATA03        FLEXIO2_FLEXIO10      GPIO2_IO10   SRC_BOOT_CFG06        ENET2_CRS              ~                      ~\n\tPB11 = portB + 11 // [B0_11]:    LCD_DATA07       QTIMER4_TIMER2   FLEXPWM2_PWMB02      SAI1_TX_DATA02        FLEXIO2_FLEXIO11      GPIO2_IO11   SRC_BOOT_CFG07        ENET2_COL              ~                      ~\n\tPB12 = portB + 12 // [B0_12]:    LCD_DATA08       XBAR1_INOUT10    ARM_TRACE_CLK        SAI1_TX_DATA01        FLEXIO2_FLEXIO12      GPIO2_IO12   SRC_BOOT_CFG08        ENET2_TDATA00          ~                      ~\n\tPB13 = portB + 13 // [B0_13]:    LCD_DATA09       XBAR1_INOUT11    ARM_TRACE_SWO        SAI1_MCLK             FLEXIO2_FLEXIO13      GPIO2_IO13   SRC_BOOT_CFG09        ENET2_TDATA01          ~                      ~\n\tPB14 = portB + 14 // [B0_14]:    LCD_DATA10       XBAR1_INOUT12    ARM_TXEV             SAI1_RX_SYNC          FLEXIO2_FLEXIO14      GPIO2_IO14   SRC_BOOT_CFG10        ENET2_TX_EN            ~                      ~\n\tPB15 = portB + 15 // [B0_15]:    LCD_DATA11       XBAR1_INOUT13    ARM_RXEV             SAI1_RX_BCLK          FLEXIO2_FLEXIO15      GPIO2_IO15   SRC_BOOT_CFG11        ENET2_TX_CLK          ENET2_REF_CLK2          ~\n\tPB16 = portB + 16 // [B1_00]:    LCD_DATA12       XBAR1_INOUT14    LPUART4_TX           SAI1_RX_DATA00        FLEXIO2_FLEXIO16      GPIO2_IO16   FLEXPWM1_PWMA03       ENET2_RX_ER           FLEXIO3_FLEXIO16        ~\n\tPB17 = portB + 17 // [B1_01]:    LCD_DATA13       XBAR1_INOUT15    LPUART4_RX           SAI1_TX_DATA00        FLEXIO2_FLEXIO17      GPIO2_IO17   FLEXPWM1_PWMB03       ENET2_RDATA00         FLEXIO3_FLEXIO17        ~\n\tPB18 = portB + 18 // [B1_02]:    LCD_DATA14       XBAR1_INOUT16    LPSPI4_PCS2          SAI1_TX_BCLK          FLEXIO2_FLEXIO18      GPIO2_IO18   FLEXPWM2_PWMA03       ENET2_RDATA01         FLEXIO3_FLEXIO18        ~\n\tPB19 = portB + 19 // [B1_03]:    LCD_DATA15       XBAR1_INOUT17    LPSPI4_PCS1          SAI1_TX_SYNC          FLEXIO2_FLEXIO19      GPIO2_IO19   FLEXPWM2_PWMB03       ENET2_RX_EN           FLEXIO3_FLEXIO19        ~\n\tPB20 = portB + 20 // [B1_04]:    LCD_DATA16       LPSPI4_PCS0      CSI_DATA15           ENET_RX_DATA00        FLEXIO2_FLEXIO20      GPIO2_IO20   GPT1_CLK              FLEXIO3_FLEXIO20       ~                      ~\n\tPB21 = portB + 21 // [B1_05]:    LCD_DATA17       LPSPI4_SDI       CSI_DATA14           ENET_RX_DATA01        FLEXIO2_FLEXIO21      GPIO2_IO21   GPT1_CAPTURE1         FLEXIO3_FLEXIO21       ~                      ~\n\tPB22 = portB + 22 // [B1_06]:    LCD_DATA18       LPSPI4_SDO       CSI_DATA13           ENET_RX_EN            FLEXIO2_FLEXIO22      GPIO2_IO22   GPT1_CAPTURE2         FLEXIO3_FLEXIO22       ~                      ~\n\tPB23 = portB + 23 // [B1_07]:    LCD_DATA19       LPSPI4_SCK       CSI_DATA12           ENET_TX_DATA00        FLEXIO2_FLEXIO23      GPIO2_IO23   GPT1_COMPARE1         FLEXIO3_FLEXIO23       ~                      ~\n\tPB24 = portB + 24 // [B1_08]:    LCD_DATA20       QTIMER1_TIMER3   CSI_DATA11           ENET_TX_DATA01        FLEXIO2_FLEXIO24      GPIO2_IO24   FLEXCAN2_TX           GPT1_COMPARE2         FLEXIO3_FLEXIO24        ~\n\tPB25 = portB + 25 // [B1_09]:    LCD_DATA21       QTIMER2_TIMER3   CSI_DATA10           ENET_TX_EN            FLEXIO2_FLEXIO25      GPIO2_IO25   FLEXCAN2_RX           GPT1_COMPARE3         FLEXIO3_FLEXIO25        ~\n\tPB26 = portB + 26 // [B1_10]:    LCD_DATA22       QTIMER3_TIMER3   CSI_DATA00           ENET_TX_CLK           FLEXIO2_FLEXIO26      GPIO2_IO26   ENET_REF_CLK          FLEXIO3_FLEXIO26       ~                      ~\n\tPB27 = portB + 27 // [B1_11]:    LCD_DATA23       QTIMER4_TIMER3   CSI_DATA01           ENET_RX_ER            FLEXIO2_FLEXIO27      GPIO2_IO27   LPSPI4_PCS3           FLEXIO3_FLEXIO27       ~                      ~\n\tPB28 = portB + 28 // [B1_12]:    LPUART5_TX       CSI_PIXCLK       ENET_1588_EVENT0_IN  FLEXIO2_FLEXIO28      GPIO2_IO28            USDHC1_CD_B  FLEXIO3_FLEXIO28       ~                     ~                      ~\n\tPB29 = portB + 29 // [B1_13]:    WDOG1_B          LPUART5_RX       CSI_VSYNC            ENET_1588_EVENT0_OUT  FLEXIO2_FLEXIO29      GPIO2_IO29   USDHC1_WP             SEMC_DQS4             FLEXIO3_FLEXIO29        ~\n\tPB30 = portB + 30 // [B1_14]:    ENET_MDC         FLEXPWM4_PWMA02  CSI_HSYNC            XBAR1_IN02            FLEXIO2_FLEXIO30      GPIO2_IO30   USDHC1_VSELECT        ENET2_TDATA00         FLEXIO3_FLEXIO30        ~\n\tPB31 = portB + 31 // [B1_15]:    ENET_MDIO        FLEXPWM4_PWMA03  CSI_MCLK             XBAR1_IN03            FLEXIO2_FLEXIO31      GPIO2_IO31   USDHC1_RESET_B        ENET2_TDATA01         FLEXIO3_FLEXIO31        ~\n\n\tPC0  = portC + 0  // [SD_B1_00]: USDHC2_DATA3     FLEXSPIB_DATA03  FLEXPWM1_PWMA03      SAI1_TX_DATA03        LPUART4_TX            GPIO3_IO00   SAI3_RX_DATA           ~                     ~                      ~\n\tPC1  = portC + 1  // [SD_B1_01]: USDHC2_DATA2     FLEXSPIB_DATA02  FLEXPWM1_PWMB03      SAI1_TX_DATA02        LPUART4_RX            GPIO3_IO01   SAI3_TX_DATA           ~                     ~                      ~\n\tPC2  = portC + 2  // [SD_B1_02]: USDHC2_DATA1     FLEXSPIB_DATA01  FLEXPWM2_PWMA03      SAI1_TX_DATA01        FLEXCAN1_TX           GPIO3_IO02   CCM_WAIT              SAI3_TX_SYNC           ~                      ~\n\tPC3  = portC + 3  // [SD_B1_03]: USDHC2_DATA0     FLEXSPIB_DATA00  FLEXPWM2_PWMB03      SAI1_MCLK             FLEXCAN1_RX           GPIO3_IO03   CCM_PMIC_READY        SAI3_TX_BCLK           ~                      ~\n\tPC4  = portC + 4  // [SD_B1_04]: USDHC2_CLK       FLEXSPIB_SCLK    LPI2C1_SCL           SAI1_RX_SYNC          FLEXSPIA_SS1_B        GPIO3_IO04   CCM_STOP              SAI3_MCLK              ~                      ~\n\tPC5  = portC + 5  // [SD_B1_05]: USDHC2_CMD       FLEXSPIA_DQS     LPI2C1_SDA           SAI1_RX_BCLK          FLEXSPIB_SS0_B        GPIO3_IO05   SAI3_RX_SYNC           ~                     ~                      ~\n\tPC6  = portC + 6  // [SD_B1_06]: USDHC2_RESET_B   FLEXSPIA_SS0_B   LPUART7_CTS_B        SAI1_RX_DATA00        LPSPI2_PCS0           GPIO3_IO06   SAI3_RX_BCLK           ~                     ~                      ~\n\tPC7  = portC + 7  // [SD_B1_07]: SEMC_CSX01       FLEXSPIA_SCLK    LPUART7_RTS_B        SAI1_TX_DATA00        LPSPI2_SCK            GPIO3_IO07    ~                     ~                     ~                      ~\n\tPC8  = portC + 8  // [SD_B1_08]: USDHC2_DATA4     FLEXSPIA_DATA00  LPUART7_TX           SAI1_TX_BCLK          LPSPI2_SD0            GPIO3_IO08   SEMC_CSX02             ~                     ~                      ~\n\tPC9  = portC + 9  // [SD_B1_09]: USDHC2_DATA5     FLEXSPIA_DATA01  LPUART7_RX           SAI1_TX_SYNC          LPSPI2_SDI            GPIO3_IO09    ~                     ~                     ~                      ~\n\tPC10 = portC + 10 // [SD_B1_10]: USDHC2_DATA6     FLEXSPIA_DATA02  LPUART2_RX           LPI2C2_SDA            LPSPI2_PCS2           GPIO3_IO10    ~                     ~                     ~                      ~\n\tPC11 = portC + 11 // [SD_B1_11]: USDHC2_DATA7     FLEXSPIA_DATA03  LPUART2_TX           LPI2C2_SCL            LPSPI2_PCS3           GPIO3_IO11    ~                     ~                     ~                      ~\n\tPC12 = portC + 12 // [SD_B0_00]: USDHC1_CMD       FLEXPWM1_PWMA00  LPI2C3_SCL           XBAR1_INOUT04         LPSPI1_SCK            GPIO3_IO12   FLEXSPIA_SS1_B        ENET2_TX_EN           SEMC_DQS4               ~\n\tPC13 = portC + 13 // [SD_B0_01]: USDHC1_CLK       FLEXPWM1_PWMB00  LPI2C3_SDA           XBAR1_INOUT05         LPSPI1_PCS0           GPIO3_IO13   FLEXSPIB_SS1_B        ENET2_TX_CLK          ENET2_REF_CLK2          ~\n\tPC14 = portC + 14 // [SD_B0_02]: USDHC1_DATA0     FLEXPWM1_PWMA01  LPUART8_CTS_B        XBAR1_INOUT06         LPSPI1_SDO            GPIO3_IO14   ENET2_RX_ER           SEMC_CLK5              ~                      ~\n\tPC15 = portC + 15 // [SD_B0_03]: USDHC1_DATA1     FLEXPWM1_PWMB01  LPUART8_RTS_B        XBAR1_INOUT07         LPSPI1_SDI            GPIO3_IO15   ENET2_RDATA00         SEMC_CLK6              ~                      ~\n\tPC16 = portC + 16 // [SD_B0_04]: USDHC1_DATA2     FLEXPWM1_PWMA02  LPUART8_TX           XBAR1_INOUT08         FLEXSPIB_SS0_B        GPIO3_IO16   CCM_CLKO1             ENET2_RDATA01          ~                      ~\n\tPC17 = portC + 17 // [SD_B0_05]: USDHC1_DATA3     FLEXPWM1_PWMB02  LPUART8_RX           XBAR1_INOUT09         FLEXSPIB_DQS          GPIO3_IO17   CCM_CLKO2             ENET2_RX_EN            ~                      ~\n\tPC18 = portC + 18 // [EMC_32]:   SEMC_DATA10      FLEXPWM3_PWMB01  LPUART7_RX           CCM_PMIC_RDY          CSI_DATA21            GPIO3_IO18   ENET2_TX_EN            ~                     ~                      ~\n\tPC19 = portC + 19 // [EMC_33]:   SEMC_DATA11      FLEXPWM3_PWMA02  USDHC1_RESET_B       SAI3_RX_DATA          CSI_DATA20            GPIO3_IO19   ENET2_TX_CLK          ENET2_REF_CLK2         ~                      ~\n\tPC20 = portC + 20 // [EMC_34]:   SEMC_DATA12      FLEXPWM3_PWMB02  USDHC1_VSELECT       SAI3_RX_SYNC          CSI_DATA19            GPIO3_IO20   ENET2_RX_ER            ~                     ~                      ~\n\tPC21 = portC + 21 // [EMC_35]:   SEMC_DATA13      XBAR1_INOUT18    GPT1_COMPARE1        SAI3_RX_BCLK          CSI_DATA18            GPIO3_IO21   USDHC1_CD_B           ENET2_RDATA00          ~                      ~\n\tPC22 = portC + 22 // [EMC_36]:   SEMC_DATA14      XBAR1_IN22       GPT1_COMPARE2        SAI3_TX_DATA          CSI_DATA17            GPIO3_IO22   USDHC1_WP             ENET2_RDATA01         FLEXCAN3_TX             ~\n\tPC23 = portC + 23 // [EMC_37]:   SEMC_DATA15      XBAR1_IN23       GPT1_COMPARE3        SAI3_MCLK             CSI_DATA16            GPIO3_IO23   USDHC2_WP             ENET2_RX_EN           FLEXCAN3_RX             ~\n\tPC24 = portC + 24 // [EMC_38]:   SEMC_DM01        FLEXPWM1_PWMA03  LPUART8_TX           SAI3_TX_BCLK          CSI_FIELD             GPIO3_IO24   USDHC2_VSELECT        ENET2_MDC              ~                      ~\n\tPC25 = portC + 25 // [EMC_39]:   SEMC_DQS         FLEXPWM1_PWMB03  LPUART8_RX           SAI3_TX_SYNC          WDOG1_WDOG_B          GPIO3_IO25   USDHC2_CD_B           ENET2_MDIO            SEMC_DQS4               ~\n\tPC26 = portC + 26 // [EMC_40]:   SEMC_RDY         GPT2_CAPTURE2    LPSPI1_PCS2          USB_OTG2_OC           ENET_MDC              GPIO3_IO26   USDHC2_RESET_B        SEMC_CLK5              ~                      ~\n\tPC27 = portC + 27 // [EMC_41]:   SEMC_CSX00       GPT2_CAPTURE1    LPSPI1_PCS3          USB_OTG2_PWR          ENET_MDIO             GPIO3_IO27   USDHC1_VSELECT         ~                     ~                      ~\n\t_    = portC + 28 //\n\t_    = portC + 29 //\n\t_    = portC + 30 //\n\t_    = portC + 31 //\n\n\tPD0  = portD + 0  // [EMC_00]:   SEMC_DATA00      FLEXPWM4_PWMA00  LPSPI2_SCK           XBAR1_XBAR_IN02       FLEXIO1_FLEXIO00      GPIO4_IO00    ~                     ~                     ~                      ~\n\tPD1  = portD + 1  // [EMC_01]:   SEMC_DATA01      FLEXPWM4_PWMB00  LPSPI2_PCS0          XBAR1_IN03            FLEXIO1_FLEXIO01      GPIO4_IO01    ~                     ~                     ~                      ~\n\tPD2  = portD + 2  // [EMC_02]:   SEMC_DATA02      FLEXPWM4_PWMA01  LPSPI2_SDO           XBAR1_INOUT04         FLEXIO1_FLEXIO02      GPIO4_IO02    ~                     ~                     ~                      ~\n\tPD3  = portD + 3  // [EMC_03]:   SEMC_DATA03      FLEXPWM4_PWMB01  LPSPI2_SDI           XBAR1_INOUT05         FLEXIO1_FLEXIO03      GPIO4_IO03    ~                     ~                     ~                      ~\n\tPD4  = portD + 4  // [EMC_04]:   SEMC_DATA04      FLEXPWM4_PWMA02  SAI2_TX_DATA         XBAR1_INOUT06         FLEXIO1_FLEXIO04      GPIO4_IO04    ~                     ~                     ~                      ~\n\tPD5  = portD + 5  // [EMC_05]:   SEMC_DATA05      FLEXPWM4_PWMB02  SAI2_TX_SYNC         XBAR1_INOUT07         FLEXIO1_FLEXIO05      GPIO4_IO05    ~                     ~                     ~                      ~\n\tPD6  = portD + 6  // [EMC_06]:   SEMC_DATA06      FLEXPWM2_PWMA00  SAI2_TX_BCLK         XBAR1_INOUT08         FLEXIO1_FLEXIO06      GPIO4_IO06    ~                     ~                     ~                      ~\n\tPD7  = portD + 7  // [EMC_07]:   SEMC_DATA07      FLEXPWM2_PWMB00  SAI2_MCLK            XBAR1_INOUT09         FLEXIO1_FLEXIO07      GPIO4_IO07    ~                     ~                     ~                      ~\n\tPD8  = portD + 8  // [EMC_08]:   SEMC_DM00        FLEXPWM2_PWMA01  SAI2_RX_DATA         XBAR1_INOUT17         FLEXIO1_FLEXIO08      GPIO4_IO08    ~                     ~                     ~                      ~\n\tPD9  = portD + 9  // [EMC_09]:   SEMC_ADDR00      FLEXPWM2_PWMB01  SAI2_RX_SYNC         FLEXCAN2_TX           FLEXIO1_FLEXIO09      GPIO4_IO09   FLEXSPI2_B_SS1_B       ~                     ~                      ~\n\tPD10 = portD + 10 // [EMC_10]:   SEMC_ADDR01      FLEXPWM2_PWMA02  SAI2_RX_BCLK         FLEXCAN2_RX           FLEXIO1_FLEXIO10      GPIO4_IO10   FLEXSPI2_B_SS0_B       ~                     ~                      ~\n\tPD11 = portD + 11 // [EMC_11]:   SEMC_ADDR02      FLEXPWM2_PWMB02  LPI2C4_SDA           USDHC2_RESET_B        FLEXIO1_FLEXIO11      GPIO4_IO11   FLEXSPI2_B_DQS         ~                     ~                      ~\n\tPD12 = portD + 12 // [EMC_12]:   SEMC_ADDR03      XBAR1_IN24       LPI2C4_SCL           USDHC1_WP             FLEXPWM1_PWMA03       GPIO4_IO12   FLEXSPI2_B_SCLK        ~                     ~                      ~\n\tPD13 = portD + 13 // [EMC_13]:   SEMC_ADDR04      XBAR1_IN25       LPUART3_TX           MQS_RIGHT             FLEXPWM1_PWMB03       GPIO4_IO13   FLEXSPI2_B_DATA00      ~                     ~                      ~\n\tPD14 = portD + 14 // [EMC_14]:   SEMC_ADDR05      XBAR1_INOUT19    LPUART3_RX           MQS_LEFT              LPSPI2_PCS1           GPIO4_IO14   FLEXSPI2_B_DATA01      ~                     ~                      ~\n\tPD15 = portD + 15 // [EMC_15]:   SEMC_ADDR06      XBAR1_IN20       LPUART3_CTS_B        SPDIF_OUT             QTIMER3_TIMER0        GPIO4_IO15   FLEXSPI2_B_DATA02      ~                     ~                      ~\n\tPD16 = portD + 16 // [EMC_16]:   SEMC_ADDR07      XBAR1_IN21       LPUART3_RTS_B        SPDIF_IN              QTIMER3_TIMER1        GPIO4_IO16   FLEXSPI2_B_DATA03      ~                     ~                      ~\n\tPD17 = portD + 17 // [EMC_17]:   SEMC_ADDR08      FLEXPWM4_PWMA03  LPUART4_CTS_B        FLEXCAN1_TX           QTIMER3_TIMER2        GPIO4_IO17    ~                     ~                     ~                      ~\n\tPD18 = portD + 18 // [EMC_18]:   SEMC_ADDR09      FLEXPWM4_PWMB03  LPUART4_RTS_B        FLEXCAN1_RX           QTIMER3_TIMER3        GPIO4_IO18   SNVS_VIO_5_CTL         ~                     ~                      ~\n\tPD19 = portD + 19 // [EMC_19]:   SEMC_ADDR11      FLEXPWM2_PWMA03  LPUART4_TX           ENET_RDATA01          QTIMER2_TIMER0        GPIO4_IO19   SNVS_VIO_5             ~                     ~                      ~\n\tPD20 = portD + 20 // [EMC_20]:   SEMC_ADDR12      FLEXPWM2_PWMB03  LPUART4_RX           ENET_RDATA00          QTIMER2_TIMER1        GPIO4_IO20    ~                     ~                     ~                      ~\n\tPD21 = portD + 21 // [EMC_21]:   SEMC_BA0         FLEXPWM3_PWMA03  LPI2C3_SDA           ENET_TDATA01          QTIMER2_TIMER2        GPIO4_IO21    ~                     ~                     ~                      ~\n\tPD22 = portD + 22 // [EMC_22]:   SEMC_BA1         FLEXPWM3_PWMB03  LPI2C3_SCL           ENET_TDATA00          QTIMER2_TIMER3        GPIO4_IO22   FLEXSPI2_A_SS1_B       ~                     ~                      ~\n\tPD23 = portD + 23 // [EMC_23]:   SEMC_ADDR10      FLEXPWM1_PWMA00  LPUART5_TX           ENET_RX_EN            GPT1_CAPTURE2         GPIO4_IO23   FLEXSPI2_A_DQS         ~                     ~                      ~\n\tPD24 = portD + 24 // [EMC_24]:   SEMC_CAS         FLEXPWM1_PWMB00  LPUART5_RX           ENET_TX_EN            GPT1_CAPTURE1         GPIO4_IO24   FLEXSPI2_A_SS0_B       ~                     ~                      ~\n\tPD25 = portD + 25 // [EMC_25]:   SEMC_RAS         FLEXPWM1_PWMA01  LPUART6_TX           ENET_TX_CLK           ENET_REF_CLK          GPIO4_IO25   FLEXSPI2_A_SCLK        ~                     ~                      ~\n\tPD26 = portD + 26 // [EMC_26]:   SEMC_CLK         FLEXPWM1_PWMB01  LPUART6_RX           ENET_RX_ER            FLEXIO1_FLEXIO12      GPIO4_IO26   FLEXSPI2_A_DATA00      ~                     ~                      ~\n\tPD27 = portD + 27 // [EMC_27]:   SEMC_CKE         FLEXPWM1_PWMA02  LPUART5_RTS_B        LPSPI1_SCK            FLEXIO1_FLEXIO13      GPIO4_IO27   FLEXSPI2_A_DATA01      ~                     ~                      ~\n\tPD28 = portD + 28 // [EMC_28]:   SEMC_WE          FLEXPWM1_PWMB02  LPUART5_CTS_B        LPSPI1_SDO            FLEXIO1_FLEXIO14      GPIO4_IO28   FLEXSPI2_A_DATA02      ~                     ~                      ~\n\tPD29 = portD + 29 // [EMC_29]:   SEMC_CS0         FLEXPWM3_PWMA00  LPUART6_RTS_B        LPSPI1_SDI            FLEXIO1_FLEXIO15      GPIO4_IO29   FLEXSPI2_A_DATA03      ~                     ~                      ~\n\tPD30 = portD + 30 // [EMC_30]:   SEMC_DATA08      FLEXPWM3_PWMB00  LPUART6_CTS_B        LPSPI1_PCS0           CSI_DATA23            GPIO4_IO30   ENET2_TDATA00          ~                     ~                      ~\n\tPD31 = portD + 31 // [EMC_31]:   SEMC_DATA09      FLEXPWM3_PWMA01  LPUART7_TX           LPSPI1_PCS1           CSI_DATA22            GPIO4_IO31   ENET2_TDATA01          ~                     ~                      ~\n)\n\nfunc (p Pin) getPos() uint8   { return uint8(p % 32) }\nfunc (p Pin) getMask() uint32 { return uint32(1) << p.getPos() }\nfunc (p Pin) getPort() Pin    { return Pin(p/32) * 32 }\n\n// Configure sets the GPIO pad and pin properties, and selects the appropriate\n// alternate function, for a given Pin and PinConfig.\nfunc (p Pin) Configure(config PinConfig) {\n\tvar (\n\t\tsre = uint32(0x01 << 0)\n\t\tdse = func(n uint32) uint32 { return (n & 0x07) << 3 }\n\t\tspd = func(n uint32) uint32 { return (n & 0x03) << 6 }\n\t\tode = uint32(0x01 << 11)\n\t\tpke = uint32(0x01 << 12)\n\t\tpue = uint32(0x01 << 13)\n\t\tpup = func(n uint32) uint32 { return (n & 0x03) << 14 }\n\t\thys = uint32(0x01 << 16)\n\t)\n\n\t_, gpio := p.getGPIO() // use fast GPIO for all pins\n\tpad, mux := p.getPad()\n\n\t// first configure the pad characteristics\n\tswitch config.Mode {\n\tcase PinInput:\n\t\tgpio.GDIR.ClearBits(p.getMask())\n\t\tpad.Set(dse(7))\n\n\tcase PinInputPullup:\n\t\tgpio.GDIR.ClearBits(p.getMask())\n\t\tpad.Set(dse(7) | pke | pue | pup(3) | hys)\n\n\tcase PinInputPulldown:\n\t\tgpio.GDIR.ClearBits(p.getMask())\n\t\tpad.Set(dse(7) | pke | pue | hys)\n\n\tcase PinOutput:\n\t\tgpio.GDIR.SetBits(p.getMask())\n\t\tpad.Set(dse(7))\n\n\tcase PinOutputOpenDrain:\n\t\tgpio.GDIR.SetBits(p.getMask())\n\t\tpad.Set(dse(7) | ode)\n\n\tcase PinDisable:\n\t\tgpio.GDIR.ClearBits(p.getMask())\n\t\tpad.Set(dse(7) | hys)\n\n\tcase PinInputAnalog:\n\t\tgpio.GDIR.ClearBits(p.getMask())\n\t\tpad.Set(dse(7))\n\n\tcase PinModeUARTTX:\n\t\tpad.Set(sre | dse(3) | spd(3))\n\n\tcase PinModeUARTRX:\n\t\tpad.Set(dse(7) | pke | pue | pup(3) | hys)\n\n\tcase PinModeSPISDI:\n\t\tpad.Set(dse(7) | spd(2))\n\n\tcase PinModeSPISDO:\n\t\tpad.Set(dse(7) | spd(2))\n\n\tcase PinModeSPICLK:\n\t\tpad.Set(dse(7) | spd(2))\n\n\tcase PinModeSPICS:\n\t\tpad.Set(dse(7))\n\n\tcase PinModeI2CSDA, PinModeI2CSCL:\n\t\tpad.Set(ode | sre | dse(4) | spd(1) | pke | pue | pup(3))\n\t}\n\n\t// then configure the alternate function mux\n\tmux.Set(p.getMuxMode(config))\n}\n\n// Get returns the current value of a GPIO pin.\nfunc (p Pin) Get() bool {\n\t_, gpio := p.getGPIO() // use fast GPIO for all pins\n\treturn gpio.PSR.HasBits(p.getMask())\n}\n\n// Set changes the value of the GPIO pin. The pin must be configured as output.\nfunc (p Pin) Set(value bool) {\n\t_, gpio := p.getGPIO() // use fast GPIO for all pins\n\tif value {\n\t\tgpio.DR_SET.Set(p.getMask())\n\t} else {\n\t\tgpio.DR_CLEAR.Set(p.getMask())\n\t}\n}\n\n// Toggle switches an output pin from low to high or from high to low.\nfunc (p Pin) Toggle() {\n\t_, gpio := p.getGPIO() // use fast GPIO for all pins\n\tgpio.DR_TOGGLE.Set(p.getMask())\n}\n\n// dispatchInterrupt invokes the user-provided callback functions for external\n// interrupts generated on the high-speed GPIO pins.\n//\n// Unfortunately, all four high-speed GPIO ports (A-D) are connected to just a\n// single interrupt control line. Therefore, the interrupt status register (ISR)\n// must be checked in all four GPIO ports on every interrupt.\nfunc (jt *pinJumpTable) dispatchInterrupt(interrupt.Interrupt) {\n\thandle := func(gpio *nxp.GPIO_Type, port Pin) {\n\t\tif status := gpio.ISR.Get() & gpio.IMR.Get(); status != 0 {\n\t\t\tgpio.ISR.Set(status) // clear interrupt\n\t\t\tfor status != 0 {\n\t\t\t\toff := Pin(bits.TrailingZeros32(status)) // ctz\n\t\t\t\tpin := Pin(port + off)\n\t\t\t\tjt.lut[pin](pin)\n\t\t\t\tstatus &^= 1 << off\n\t\t\t}\n\t\t}\n\t}\n\tif jt.numDefined > 0 {\n\t\thandle(nxp.GPIO6, portA)\n\t\thandle(nxp.GPIO7, portB)\n\t\thandle(nxp.GPIO8, portC)\n\t\thandle(nxp.GPIO9, portD)\n\t}\n}\n\n// set associates a function with a given Pin in the receiver lookup table. If\n// the function is nil, the given Pin's associated function is removed.\nfunc (jt *pinJumpTable) set(pin Pin, fn func(Pin)) {\n\tif int(pin) < len(jt.lut) {\n\t\tif nil != fn {\n\t\t\tif nil == jt.lut[pin] {\n\t\t\t\tjt.numDefined++\n\t\t\t}\n\t\t\tjt.lut[pin] = fn\n\t\t} else {\n\t\t\tif nil != jt.lut[pin] {\n\t\t\t\tjt.numDefined--\n\t\t\t}\n\t\t\tjt.lut[pin] = nil\n\t\t}\n\t}\n}\n\n// SetInterrupt sets an interrupt to be executed when a particular pin changes\n// state. The pin should already be configured as an input, including a pull up\n// or down if no external pull is provided.\n//\n// This call will replace a previously set callback on this pin. You can pass a\n// nil func to unset the pin change interrupt. If you do so, the change\n// parameter is ignored and can be set to any value (such as 0).\nfunc (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error {\n\t_, gpio := p.getGPIO() // use fast GPIO for all pins\n\tmask := p.getMask()\n\tif nil != callback {\n\t\tswitch change {\n\t\tcase PinRising, PinFalling:\n\t\t\tgpio.EDGE_SEL.ClearBits(mask)\n\t\t\tvar reg *volatile.Register32\n\t\t\tvar pos uint8\n\t\t\tif pos = p.getPos(); pos < 16 {\n\t\t\t\treg = &gpio.ICR1 // ICR1 = pins 0-15\n\t\t\t} else {\n\t\t\t\treg = &gpio.ICR2 // ICR2 = pins 16-31\n\t\t\t\tpos -= 16\n\t\t\t}\n\t\t\treg.ReplaceBits(uint32(change), 0x3, pos*2)\n\t\tcase PinToggle:\n\t\t\tgpio.EDGE_SEL.SetBits(mask)\n\t\t}\n\t\tpinISR.set(p, callback) // associate the callback with the pin\n\t\tgpio.ISR.Set(mask)      // clear any pending interrupt (W1C)\n\t\tgpio.IMR.SetBits(mask)  // enable external interrupt\n\t} else {\n\t\tpinISR.set(p, nil)       // remove any associated callback from the pin\n\t\tgpio.ISR.Set(mask)       // clear any pending interrupt (W1C)\n\t\tgpio.IMR.ClearBits(mask) // disable external interrupt\n\t}\n\t// enable or disable the interrupt based on number of defined callbacks\n\tif pinISR.numDefined > 0 {\n\t\tif nil == pinInterrupt {\n\t\t\t// create the Interrupt if it is not yet defined\n\t\t\tirq := interrupt.New(nxp.IRQ_GPIO6_7_8_9, pinISR.dispatchInterrupt)\n\t\t\tpinInterrupt = &irq\n\t\t\tpinInterrupt.Enable()\n\t\t}\n\t} else {\n\t\tif nil != pinInterrupt {\n\t\t\t// disable the interrupt if it is defined\n\t\t\tpinInterrupt.Disable()\n\t\t}\n\t}\n\treturn nil\n}\n\n// getGPIO returns both the normal (IPG_CLK_ROOT) and high-speed (AHB_CLK_ROOT)\n// GPIO peripherals to which a given Pin is connected.\n//\n// Note that, currently, the device is configured to use high-speed GPIO for all\n// pins (GPIO6-9), so the first return value should not be used (GPIO1-4).\n// See the remarks and documentation reference in the comments preceding the\n// const Pin definitions above.\nfunc (p Pin) getGPIO() (norm *nxp.GPIO_Type, fast *nxp.GPIO_Type) {\n\tswitch p.getPort() {\n\tcase portA:\n\t\treturn nxp.GPIO1, nxp.GPIO6\n\tcase portB:\n\t\treturn nxp.GPIO2, nxp.GPIO7\n\tcase portC:\n\t\treturn nxp.GPIO3, nxp.GPIO8\n\tcase portD:\n\t\treturn nxp.GPIO4, nxp.GPIO9\n\tdefault:\n\t\tpanic(\"machine: unknown port\")\n\t}\n}\n\n// getPad returns both the pad and mux configuration registers for a given Pin.\nfunc (p Pin) getPad() (pad *volatile.Register32, mux *volatile.Register32) {\n\tswitch p.getPort() {\n\tcase portA:\n\t\tswitch p.getPos() {\n\t\tcase 0:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_00\n\t\tcase 1:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_01\n\t\tcase 2:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_02\n\t\tcase 3:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_03\n\t\tcase 4:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_04\n\t\tcase 5:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_05\n\t\tcase 6:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_06, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_06\n\t\tcase 7:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_07, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_07\n\t\tcase 8:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_08, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_08\n\t\tcase 9:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_09, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_09\n\t\tcase 10:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_10, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_10\n\t\tcase 11:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_11, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_11\n\t\tcase 12:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_12, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_12\n\t\tcase 13:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_13, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_13\n\t\tcase 14:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_14, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_14\n\t\tcase 15:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_15, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_15\n\t\tcase 16:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_00\n\t\tcase 17:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_01\n\t\tcase 18:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_02\n\t\tcase 19:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_03\n\t\tcase 20:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_04\n\t\tcase 21:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_05\n\t\tcase 22:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_06, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_06\n\t\tcase 23:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_07, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_07\n\t\tcase 24:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_08, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_08\n\t\tcase 25:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_09, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_09\n\t\tcase 26:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_10, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_10\n\t\tcase 27:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_11, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_11\n\t\tcase 28:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_12, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_12\n\t\tcase 29:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_13, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_13\n\t\tcase 30:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_14, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_14\n\t\tcase 31:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_15, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_15\n\t\t}\n\tcase portB:\n\t\tswitch p.getPos() {\n\t\tcase 0:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_00\n\t\tcase 1:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_01\n\t\tcase 2:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_02\n\t\tcase 3:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_03\n\t\tcase 4:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_04\n\t\tcase 5:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_05\n\t\tcase 6:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_06, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_06\n\t\tcase 7:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_07, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_07\n\t\tcase 8:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_08, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_08\n\t\tcase 9:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_09, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_09\n\t\tcase 10:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_10, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_10\n\t\tcase 11:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_11, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_11\n\t\tcase 12:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_12, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_12\n\t\tcase 13:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_13, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_13\n\t\tcase 14:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_14, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_14\n\t\tcase 15:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_15, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_15\n\t\tcase 16:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_00\n\t\tcase 17:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_01\n\t\tcase 18:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_02\n\t\tcase 19:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_03\n\t\tcase 20:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_04\n\t\tcase 21:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_05\n\t\tcase 22:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_06, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_06\n\t\tcase 23:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_07, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_07\n\t\tcase 24:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_08, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_08\n\t\tcase 25:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_09, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_09\n\t\tcase 26:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_10, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_10\n\t\tcase 27:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_11, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_11\n\t\tcase 28:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_12, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_12\n\t\tcase 29:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_13, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_13\n\t\tcase 30:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_14, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_14\n\t\tcase 31:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_15, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_15\n\t\t}\n\tcase portC:\n\t\tswitch p.getPos() {\n\t\tcase 0:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_00\n\t\tcase 1:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_01\n\t\tcase 2:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_02\n\t\tcase 3:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_03\n\t\tcase 4:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_04\n\t\tcase 5:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_05\n\t\tcase 6:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_06, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_06\n\t\tcase 7:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_07, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_07\n\t\tcase 8:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_08, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_08\n\t\tcase 9:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_09, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_09\n\t\tcase 10:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_10, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_10\n\t\tcase 11:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_11, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_11\n\t\tcase 12:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B0_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B0_00\n\t\tcase 13:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B0_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B0_01\n\t\tcase 14:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B0_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B0_02\n\t\tcase 15:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B0_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B0_03\n\t\tcase 16:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B0_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B0_04\n\t\tcase 17:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B0_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B0_05\n\t\tcase 18:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_32, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_32\n\t\tcase 19:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_33, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_33\n\t\tcase 20:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_34, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_34\n\t\tcase 21:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_35, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_35\n\t\tcase 22:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_36, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_36\n\t\tcase 23:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_37, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_37\n\t\tcase 24:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_38, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_38\n\t\tcase 25:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_39, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_39\n\t\tcase 26:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_40, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_40\n\t\tcase 27:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_41, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_41\n\t\tcase 28, 29, 30, 31:\n\t\t}\n\tcase portD:\n\t\tswitch p.getPos() {\n\t\tcase 0:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_00\n\t\tcase 1:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_01\n\t\tcase 2:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_02\n\t\tcase 3:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_03\n\t\tcase 4:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_04\n\t\tcase 5:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_05\n\t\tcase 6:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_06, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_06\n\t\tcase 7:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_07, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_07\n\t\tcase 8:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_08, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_08\n\t\tcase 9:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_09, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_09\n\t\tcase 10:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_10, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_10\n\t\tcase 11:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_11, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_11\n\t\tcase 12:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_12, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_12\n\t\tcase 13:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_13, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_13\n\t\tcase 14:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_14, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_14\n\t\tcase 15:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_15, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_15\n\t\tcase 16:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_16, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_16\n\t\tcase 17:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_17, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_17\n\t\tcase 18:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_18, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_18\n\t\tcase 19:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_19, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_19\n\t\tcase 20:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_20, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_20\n\t\tcase 21:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_21, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_21\n\t\tcase 22:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_22, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_22\n\t\tcase 23:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_23, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_23\n\t\tcase 24:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_24, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_24\n\t\tcase 25:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_25, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_25\n\t\tcase 26:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_26, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_26\n\t\tcase 27:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_27, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_27\n\t\tcase 28:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_28, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_28\n\t\tcase 29:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_29, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_29\n\t\tcase 30:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_30, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_30\n\t\tcase 31:\n\t\t\treturn &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_31, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_31\n\t\t}\n\t}\n\tpanic(\"machine: invalid pin\")\n}\n\n// muxSelect is yet another level of indirection required to connect pins in an\n// alternate function state to a desired peripheral (since more than one pin can\n// provide a given alternate function).\n//\n// Once a pin is configured with a given alternate function mode, the IOMUXC\n// device must then be configured to select which alternate function pin to\n// route to the desired peripheral.\n//\n// The reference manual refers to this functionality as a \"Daisy Chain\". The\n// associated docs are found in the i.MX RT1060 Processor Reference Manual:\n// \"Chapter 11.3.3 Daisy chain - multi pads driving same module input pin\"\ntype muxSelect struct {\n\tmux uint8                // AF mux selection (NOT a Pin type)\n\tsel *volatile.Register32 // AF selection register\n}\n\n// connect configures the IOMUXC controller to route a given pin with alternate\n// function to a desired peripheral (see godoc comments on type muxSelect).\nfunc (s muxSelect) connect() {\n\ts.sel.Set(uint32(s.mux))\n}\n\n// getMuxMode acts as a callback from the `(Pin).Configure(PinMode)` routine to\n// determine the alternate function setting for a given Pin and PinConfig.\n// This value is used in the IOMUXC device's SW_MUX_CTL_PAD_GPIO_* registers.\nfunc (p Pin) getMuxMode(config PinConfig) uint32 {\n\tconst forcePath = true // TODO: should be input parameter?\n\tswitch config.Mode {\n\n\t// GPIO\n\tcase PinInput, PinInputPullup, PinInputPulldown,\n\t\tPinOutput, PinOutputOpenDrain, PinDisable:\n\t\tmode := uint32(0x5) // GPIO is always alternate function 5\n\t\tif forcePath {\n\t\t\tmode |= 0x10 // SION bit\n\t\t}\n\t\treturn mode\n\n\t// ADC\n\tcase PinInputAnalog:\n\t\tmode := uint32(0x5) // use alternate function 5 (GPIO)\n\t\tif forcePath {\n\t\t\tmode |= 0x10 // SION bit\n\t\t}\n\t\treturn mode\n\n\t// UART RX/TX\n\tcase PinModeUARTRX, PinModeUARTTX:\n\t\tmode := uint32(0x2) // UART is usually alternate function 2 on Teensy 4.x\n\t\t// Teensy 4.1 has a UART (LPUART5) with alternate function 1\n\t\tif p == PB28 || p == PB29 {\n\t\t\tmode = 0x1\n\t\t}\n\t\treturn mode\n\n\t// SPI SDI\n\tcase PinModeSPISDI:\n\t\tvar mode uint32\n\t\tswitch p {\n\t\tcase PC15: // LPSPI1 SDI on PC15 alternate function 4\n\t\t\tmode = uint32(0x4)\n\t\tcase PA2: // LPSPI3 SDI on PA2 alternate function 7\n\t\t\tmode = uint32(0x7)\n\t\tcase PB1: // LPSPI4 SDI on PB1 alternate function 3\n\t\t\tmode = uint32(0x3)\n\t\tdefault:\n\t\t\tpanic(\"machine: invalid SPI SDI pin\")\n\t\t}\n\t\tif forcePath {\n\t\t\tmode |= 0x10 // SION bit\n\t\t}\n\t\treturn mode\n\n\t// SPI SDO\n\tcase PinModeSPISDO:\n\t\tvar mode uint32\n\t\tswitch p {\n\t\tcase PC14: // LPSPI1 SDO on PC14 alternate function 4\n\t\t\tmode = uint32(0x4)\n\t\tcase PA30: // LPSPI3 SDO on PA30 alternate function 2\n\t\t\tmode = uint32(0x2)\n\t\tcase PB2: // LPSPI4 SDO on PB2 alternate function 3\n\t\t\tmode = uint32(0x3)\n\t\tdefault:\n\t\t\tpanic(\"machine: invalid SPI SDO pin\")\n\t\t}\n\t\tif forcePath {\n\t\t\tmode |= 0x10 // SION bit\n\t\t}\n\t\treturn mode\n\n\t// SPI SCK\n\tcase PinModeSPICLK:\n\t\tvar mode uint32\n\t\tswitch p {\n\t\tcase PC12: // LPSPI1 SCK on PC12 alternate function 4\n\t\t\tmode = uint32(0x4)\n\t\tcase PA31: // LPSPI3 SCK on PA31 alternate function 2\n\t\t\tmode = uint32(0x2)\n\t\tcase PB3: // LPSPI4 SCK on PB3 alternate function 3\n\t\t\tmode = uint32(0x3)\n\t\tdefault:\n\t\t\tpanic(\"machine: invalid SPI CLK pin\")\n\t\t}\n\t\tif forcePath {\n\t\t\tmode |= 0x10 // SION bit\n\t\t}\n\t\treturn mode\n\n\t// SPI CS\n\tcase PinModeSPICS:\n\t\tvar mode uint32\n\t\tswitch p {\n\t\tcase PC13: // LPSPI1 CS on PC13 alternate function 4\n\t\t\tmode = uint32(0x4)\n\t\tcase PA3: // LPSPI3 CS on PA3 alternate function 7\n\t\t\tmode = uint32(0x7)\n\t\tcase PB0: // LPSPI4 CS on PB0 alternate function 3\n\t\t\tmode = uint32(0x3)\n\t\tdefault: // use alternate function 5 (GPIO) if non-CS pin selected\n\t\t\tmode = uint32(0x5)\n\t\t}\n\t\tif forcePath {\n\t\t\tmode |= 0x10 // SION bit\n\t\t}\n\t\treturn mode\n\n\t// I2C SDA\n\tcase PinModeI2CSDA:\n\t\tvar mode uint32\n\t\tswitch p {\n\t\tcase PA13: // LPI2C4 SDA on PA13 alternate function 0\n\t\t\tmode = uint32(0)\n\t\tcase PA17: // LPI2C1 SDA on PA17 alternate function 3\n\t\t\tmode = uint32(3)\n\t\tcase PA22: // LPI2C3 SDA on PA22 alternate function 1\n\t\t\tmode = uint32(1)\n\t\tdefault:\n\t\t\tpanic(\"machine: invalid I2C SDA pin\")\n\t\t}\n\t\tif forcePath {\n\t\t\tmode |= 0x10 // SION bit\n\t\t}\n\t\treturn mode\n\n\t// I2C SCL\n\tcase PinModeI2CSCL:\n\t\tvar mode uint32\n\t\tswitch p {\n\t\tcase PA12: // LPI2C4 SCL on PA12 alternate function 0\n\t\t\tmode = uint32(0)\n\t\tcase PA16: // LPI2C1 SCL on PA16 alternate function 3\n\t\t\tmode = uint32(3)\n\t\tcase PA23: // LPI2C3 SCL on PA23 alternate function 1\n\t\t\tmode = uint32(1)\n\t\tdefault:\n\t\t\tpanic(\"machine: invalid I2C SCL pin\")\n\t\t}\n\t\tif forcePath {\n\t\t\tmode |= 0x10 // SION bit\n\t\t}\n\t\treturn mode\n\n\tdefault:\n\t\tpanic(\"machine: invalid pin mode\")\n\t}\n}\n\n// maximum ADC value for the currently configured resolution (used for scaling)\nvar adcMaximum uint32\n\n// InitADC is not used by this machine. Use `(ADC).Configure()`.\nfunc InitADC() {}\n\n// Configure initializes the receiver's ADC peripheral and pin for analog input.\nfunc (a ADC) Configure(config ADCConfig) {\n\t// if not specified, use defaults: 10-bit resolution, 4 samples/conversion\n\tconst (\n\t\tdefaultResolution = uint32(10)\n\t\tdefaultSamples    = uint32(4)\n\t)\n\n\ta.Pin.Configure(PinConfig{Mode: PinInputAnalog})\n\n\tresolution, samples := config.Resolution, config.Samples\n\tif 0 == resolution {\n\t\tresolution = defaultResolution\n\t}\n\tif 0 == samples {\n\t\tsamples = defaultSamples\n\t}\n\tif resolution > 12 {\n\t\tresolution = 12 // maximum resolution of 12 bits\n\t}\n\tadcMaximum = (uint32(1) << resolution) - 1\n\n\tmode, average := a.mode(resolution, samples)\n\n\tnxp.ADC1.CFG.Set(mode | nxp.ADC_CFG_ADHSC) // configure ADC1\n\tnxp.ADC2.CFG.Set(mode | nxp.ADC_CFG_ADHSC) // configure ADC2\n\n\t// begin calibration\n\tnxp.ADC1.GC.Set(average | nxp.ADC_GC_CAL)\n\tnxp.ADC2.GC.Set(average | nxp.ADC_GC_CAL)\n\n\tfor a.isCalibrating() {\n\t} // wait for calibration\n}\n\n// Get performs a single ADC conversion, returning a 16-bit unsigned integer.\n// The value returned will be scaled (uniformly distributed) if necessary so\n// that it is always in the range [0..65535], regardless of the ADC's configured\n// bit size (resolution).\nfunc (a ADC) Get() uint16 {\n\tif ch1, ch2, ok := a.Pin.getADCChannel(); ok {\n\t\tfor a.isCalibrating() {\n\t\t} // wait for calibration\n\t\tvar val uint32\n\t\tif noADCChannel != ch1 {\n\t\t\tnxp.ADC1.HC0.Set(uint32(ch1))\n\t\t\tfor !nxp.ADC1.HS.HasBits(nxp.ADC_HS_COCO0) {\n\t\t\t}\n\t\t\tval = nxp.ADC1.R0.Get() & 0xFFFF\n\t\t} else {\n\t\t\tnxp.ADC2.HC0.Set(uint32(ch2))\n\t\t\tfor !nxp.ADC2.HS.HasBits(nxp.ADC_HS_COCO0) {\n\t\t\t}\n\t\t\tval = nxp.ADC2.R0.Get() & 0xFFFF\n\t\t}\n\t\t// should never be zero, but just in case, use UINT16_MAX so that the scalar\n\t\t// gets factored out of the conversion result, leaving the original reading\n\t\t// to be returned unaltered/unscaled.\n\t\tif adcMaximum == 0 {\n\t\t\tadcMaximum = 0xFFFF\n\t\t}\n\t\t// scale up to a 16-bit value\n\t\treturn uint16((val * 0xFFFF) / adcMaximum)\n\t}\n\treturn 0\n}\n\n// mode constructs bit masks for mode and average - used in ADC configuration\n// registers - from a given ADC bit size (resolution) and sample count.\nfunc (a ADC) mode(resolution, samples uint32) (mode, average uint32) {\n\n\t// use asynchronous clock (ADACK) (0 = IPG, 1 = IPG/2, or 3 = ADACK)\n\tmode = (nxp.ADC_CFG_ADICLK_ADICLK_3 << nxp.ADC_CFG_ADICLK_Pos) & nxp.ADC_CFG_ADICLK_Msk\n\n\t// input clock DIV2 (0 = DIV1, 1 = DIV2, 2 = DIV4, or 3 = DIV8)\n\tmode |= (nxp.ADC_CFG_ADIV_ADIV_1 << nxp.ADC_CFG_ADIV_Pos) & nxp.ADC_CFG_ADIV_Msk\n\n\tswitch resolution {\n\tcase 8: // 8-bit conversion, sample period (ADC clocks) = 8\n\t\tmode |= (nxp.ADC_CFG_MODE_MODE_0 << nxp.ADC_CFG_MODE_Pos) & nxp.ADC_CFG_MODE_Msk\n\t\tmode |= (nxp.ADC_CFG_ADSTS_ADSTS_3 << nxp.ADC_CFG_ADSTS_Pos) & nxp.ADC_CFG_ADSTS_Msk\n\n\tcase 12: // 12-bit conversion, sample period (ADC clocks) = 24\n\t\tmode |= (nxp.ADC_CFG_MODE_MODE_2 << nxp.ADC_CFG_MODE_Pos) & nxp.ADC_CFG_MODE_Msk\n\t\tmode |= (nxp.ADC_CFG_ADSTS_ADSTS_3 << nxp.ADC_CFG_ADSTS_Pos) & nxp.ADC_CFG_ADSTS_Msk\n\t\tmode |= nxp.ADC_CFG_ADLSMP\n\n\tdefault: // 10-bit conversion, sample period (ADC clocks) = 20\n\t\tmode |= (nxp.ADC_CFG_MODE_MODE_1 << nxp.ADC_CFG_MODE_Pos) & nxp.ADC_CFG_MODE_Msk\n\t\tmode |= (nxp.ADC_CFG_ADSTS_ADSTS_2 << nxp.ADC_CFG_ADSTS_Pos) & nxp.ADC_CFG_ADSTS_Msk\n\t\tmode |= nxp.ADC_CFG_ADLSMP\n\t}\n\n\tif samples >= 4 {\n\t\tif samples >= 32 {\n\t\t\t// 32 samples averaged\n\t\t\tmode |= (nxp.ADC_CFG_AVGS_AVGS_3 << nxp.ADC_CFG_AVGS_Pos) & nxp.ADC_CFG_AVGS_Msk\n\t\t} else if samples >= 16 {\n\t\t\t// 16 samples averaged\n\t\t\tmode |= (nxp.ADC_CFG_AVGS_AVGS_2 << nxp.ADC_CFG_AVGS_Pos) & nxp.ADC_CFG_AVGS_Msk\n\t\t} else if samples >= 8 {\n\t\t\t// 8 samples averaged\n\t\t\tmode |= (nxp.ADC_CFG_AVGS_AVGS_1 << nxp.ADC_CFG_AVGS_Pos) & nxp.ADC_CFG_AVGS_Msk\n\t\t} else {\n\t\t\t// 4 samples averaged\n\t\t\tmode |= (nxp.ADC_CFG_AVGS_AVGS_0 << nxp.ADC_CFG_AVGS_Pos) & nxp.ADC_CFG_AVGS_Msk\n\t\t}\n\t\taverage = nxp.ADC_GC_AVGE\n\t}\n\n\treturn mode, average\n}\n\n// isCalibrating returns true if and only if either one (or both) of ADC1 and\n// ADC2 have their calibrating flags set. ADC reads must wait until these flags\n// are clear before attempting a conversion.\nfunc (a ADC) isCalibrating() bool {\n\treturn nxp.ADC1.GC.HasBits(nxp.ADC_GC_CAL) || nxp.ADC2.GC.HasBits(nxp.ADC_GC_CAL)\n}\n\nconst noADCChannel = uint8(0xFF)\n\n// getADCChannel returns the input channel for ADC1/ADC2 of the receiver Pin p.\nfunc (p Pin) getADCChannel() (adc1, adc2 uint8, ok bool) {\n\tswitch p {\n\tcase PA12: // [AD_B0_12]:       ADC1_IN1        ~\n\t\treturn 1, noADCChannel, true\n\tcase PA13: // [AD_B0_13]:       ADC1_IN2        ~\n\t\treturn 2, noADCChannel, true\n\tcase PA14: // [AD_B0_14]:       ADC1_IN3        ~\n\t\treturn 3, noADCChannel, true\n\tcase PA15: // [AD_B0_15]:       ADC1_IN4        ~\n\t\treturn 4, noADCChannel, true\n\tcase PA16: // [AD_B1_00]:       ADC1_IN5     ADC2_IN5\n\t\treturn 5, 5, true\n\tcase PA17: // [AD_B1_01]:       ADC1_IN6     ADC2_IN6\n\t\treturn 6, 6, true\n\tcase PA18: // [AD_B1_02]:       ADC1_IN7     ADC2_IN7\n\t\treturn 7, 7, true\n\tcase PA19: // [AD_B1_03]:       ADC1_IN8     ADC2_IN8\n\t\treturn 8, 8, true\n\tcase PA20: // [AD_B1_04]:       ADC1_IN9     ADC2_IN9\n\t\treturn 9, 9, true\n\tcase PA21: // [AD_B1_05]:       ADC1_IN10    ADC2_IN10\n\t\treturn 10, 10, true\n\tcase PA22: // [AD_B1_06]:       ADC1_IN11    ADC2_IN11\n\t\treturn 11, 11, true\n\tcase PA23: // [AD_B1_07]:       ADC1_IN12    ADC2_IN12\n\t\treturn 12, 12, true\n\tcase PA24: // [AD_B1_08]:       ADC1_IN13    ADC2_IN13\n\t\treturn 13, 13, true\n\tcase PA25: // [AD_B1_09]:       ADC1_IN14    ADC2_IN14\n\t\treturn 14, 14, true\n\tcase PA26: // [AD_B1_10]:       ADC1_IN15    ADC2_IN15\n\t\treturn 15, 15, true\n\tcase PA27: // [AD_B1_11]:       ADC1_IN0     ADC2_IN0\n\t\treturn 16, 16, true\n\tcase PA28: // [AD_B1_12]:          ~         ADC2_IN1\n\t\treturn noADCChannel, 1, true\n\tcase PA29: // [AD_B1_13]:          ~         ADC2_IN2\n\t\treturn noADCChannel, 2, true\n\tcase PA30: // [AD_B1_14]:          ~         ADC2_IN3\n\t\treturn noADCChannel, 3, true\n\tcase PA31: // [AD_B1_15]:          ~         ADC2_IN4\n\t\treturn noADCChannel, 4, true\n\tdefault:\n\t\treturn noADCChannel, noADCChannel, false\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_mimxrt1062_i2c.go",
    "content": "//go:build mimxrt1062\n\npackage machine\n\n// I2C peripheral abstraction layer for the MIMXRT1062\n\nimport (\n\t\"device/nxp\"\n)\n\n// I2CConfig is used to store config info for I2C.\ntype I2CConfig struct {\n\tFrequency uint32\n\tSDA       Pin\n\tSCL       Pin\n}\n\ntype I2C struct {\n\tBus *nxp.LPI2C_Type\n\n\t// these pins are initialized by each global I2C variable declared in the\n\t// board_teensy4x.go file according to the board manufacturer's default pin\n\t// mapping. they can be overridden with the I2CConfig argument given to\n\t// (*I2C) Configure(I2CConfig).\n\tsda, scl Pin\n\n\t// these hold the input selector (\"daisy chain\") values that select which pins\n\t// are connected to the LPI2C device, and should be defined where the I2C\n\t// instance is declared (e.g., in the board definition). see the godoc\n\t// comments on type muxSelect for more details.\n\tmuxSDA, muxSCL muxSelect\n}\n\ntype i2cDirection bool\n\nconst (\n\tdirectionWrite i2cDirection = false\n\tdirectionRead  i2cDirection = true\n)\n\nfunc (dir i2cDirection) shift(addr uint16) uint32 {\n\tif addr <<= 1; dir == directionRead {\n\t\taddr |= 1\n\t}\n\treturn uint32(addr) & 0xFF\n}\n\n// I2C enumerated types\ntype (\n\tresultFlag   uint32\n\tstatusFlag   uint32\n\ttransferFlag uint32\n\tcommandFlag  uint32\n\tstateFlag    uint32\n)\n\nconst (\n\t// general purpose results\n\tresultSuccess         resultFlag = 0x0 // success\n\tresultFail            resultFlag = 0x1 // fail\n\tresultReadOnly        resultFlag = 0x2 // read only failure\n\tresultOutOfRange      resultFlag = 0x3 // out of range access\n\tresultInvalidArgument resultFlag = 0x4 // invalid argument check\n\t// I2C-specific results\n\tresultBusy                 resultFlag = 0x0384 + 0x0 // the controller is already performing a transfer\n\tresultIdle                 resultFlag = 0x0384 + 0x1 // the peripheral driver is idle\n\tresultNak                  resultFlag = 0x0384 + 0x2 // the peripheral device sent a NAK in response to a byte\n\tresultFifoError            resultFlag = 0x0384 + 0x3 // FIFO under run or overrun\n\tresultBitError             resultFlag = 0x0384 + 0x4 // transferred bit was not seen on the bus\n\tresultArbitrationLost      resultFlag = 0x0384 + 0x5 // arbitration lost error\n\tresultPinLowTimeout        resultFlag = 0x0384 + 0x6 // SCL or SDA were held low longer than the timeout\n\tresultNoTransferInProgress resultFlag = 0x0384 + 0x7 // attempt to abort a transfer when one is not in progress\n\tresultDmaRequestFail       resultFlag = 0x0384 + 0x8 // DMA request failed\n\tresultTimeout              resultFlag = 0x0384 + 0x9 // timeout polling status flags\n)\n\nconst (\n\tstatusTxReady         statusFlag = nxp.LPI2C_MSR_TDF  // transmit data flag\n\tstatusRxReady         statusFlag = nxp.LPI2C_MSR_RDF  // receive data flag\n\tstatusEndOfPacket     statusFlag = nxp.LPI2C_MSR_EPF  // end Packet flag\n\tstatusStopDetect      statusFlag = nxp.LPI2C_MSR_SDF  // stop detect flag\n\tstatusNackDetect      statusFlag = nxp.LPI2C_MSR_NDF  // NACK detect flag\n\tstatusArbitrationLost statusFlag = nxp.LPI2C_MSR_ALF  // arbitration lost flag\n\tstatusFifoErr         statusFlag = nxp.LPI2C_MSR_FEF  // FIFO error flag\n\tstatusPinLowTimeout   statusFlag = nxp.LPI2C_MSR_PLTF // pin low timeout flag\n\tstatusI2CDataMatch    statusFlag = nxp.LPI2C_MSR_DMF  // data match flag\n\tstatusBusy            statusFlag = nxp.LPI2C_MSR_MBF  // busy flag\n\tstatusBusBusy         statusFlag = nxp.LPI2C_MSR_BBF  // bus busy flag\n\n\t// all flags which are cleared by the driver upon starting a transfer\n\tstatusClear statusFlag = statusEndOfPacket | statusStopDetect | statusNackDetect |\n\t\tstatusArbitrationLost | statusFifoErr | statusPinLowTimeout | statusI2CDataMatch\n\n\t// IRQ sources enabled by the non-blocking transactional API\n\tstatusIrq statusFlag = statusArbitrationLost | statusTxReady | statusRxReady |\n\t\tstatusStopDetect | statusNackDetect | statusPinLowTimeout | statusFifoErr\n\n\t// errors to check for\n\tstatusError statusFlag = statusNackDetect | statusArbitrationLost | statusFifoErr |\n\t\tstatusPinLowTimeout\n)\n\n// LPI2C transfer modes\nconst (\n\ttransferDefault       transferFlag = 0x0 // transfer starts with a start signal, stops with a stop signal\n\ttransferNoStart       transferFlag = 0x1 // don't send a start condition, address, and sub address\n\ttransferRepeatedStart transferFlag = 0x2 // send a repeated start condition\n\ttransferNoStop        transferFlag = 0x4 // don't send a stop condition\n)\n\n// LPI2C FIFO commands\nconst (\n\tcommandTxData commandFlag = (0x0 << nxp.LPI2C_MTDR_CMD_Pos) & nxp.LPI2C_MTDR_CMD_Msk // transmit\n\tcommandRxData commandFlag = (0x1 << nxp.LPI2C_MTDR_CMD_Pos) & nxp.LPI2C_MTDR_CMD_Msk // receive\n\tcommandStop   commandFlag = (0x2 << nxp.LPI2C_MTDR_CMD_Pos) & nxp.LPI2C_MTDR_CMD_Msk // generate STOP condition\n\tcommandStart  commandFlag = (0x4 << nxp.LPI2C_MTDR_CMD_Pos) & nxp.LPI2C_MTDR_CMD_Msk // generate (REPEATED)START and transmit\n)\n\n// LPI2C transactional states\nconst (\n\tstateIdle              stateFlag = 0x0\n\tstateSendCommand       stateFlag = 0x1\n\tstateIssueReadCommand  stateFlag = 0x2\n\tstateTransferData      stateFlag = 0x3\n\tstateStop              stateFlag = 0x4\n\tstateWaitForCompletion stateFlag = 0x5\n)\n\nfunc (i2c *I2C) setPins(c I2CConfig) (sda, scl Pin) {\n\t// if both given pins are defined, or either receiver pin is undefined.\n\tif 0 != c.SDA && 0 != c.SCL || 0 == i2c.sda || 0 == i2c.scl {\n\t\t// override the receiver's pins.\n\t\ti2c.sda, i2c.scl = c.SDA, c.SCL\n\t}\n\t// return the selected pins.\n\treturn i2c.sda, i2c.scl\n}\n\n// Configure is intended to setup an I2C interface for transmit/receive.\nfunc (i2c *I2C) Configure(config I2CConfig) error {\n\t// init pins\n\tsda, scl := i2c.setPins(config)\n\n\t// configure the mux and pad control registers\n\tsda.Configure(PinConfig{Mode: PinModeI2CSDA})\n\tscl.Configure(PinConfig{Mode: PinModeI2CSCL})\n\n\t// configure the mux input selector\n\ti2c.muxSDA.connect()\n\ti2c.muxSCL.connect()\n\n\tfreq := config.Frequency\n\tif 0 == freq {\n\t\tfreq = 100 * KHz\n\t}\n\n\t// reset clock and registers, and enable LPI2C module interface\n\ti2c.reset(freq)\n\n\treturn nil\n}\n\n// SetBaudRate sets the communication speed for I2C.\nfunc (i2c I2C) SetBaudRate(br uint32) error {\n\t// TODO: implement\n\treturn errI2CNotImplemented\n}\n\nfunc (i2c I2C) Tx(addr uint16, w, r []byte) error {\n\t// perform transmit transfer\n\tif nil != w {\n\t\t// generate start condition on bus\n\t\tif result := i2c.start(addr, directionWrite); resultSuccess != result {\n\t\t\treturn errI2CSignalStartTimeout\n\t\t}\n\t\t// ensure TX FIFO is empty\n\t\tif result := i2c.waitForTxEmpty(); resultSuccess != result {\n\t\t\treturn errI2CBusReadyTimeout\n\t\t}\n\t\t// check if communication was successful\n\t\tif status := statusFlag(i2c.Bus.MSR.Get()); 0 != (status & statusNackDetect) {\n\t\t\treturn errI2CAckExpected\n\t\t}\n\t\t// send transmit data\n\t\tif result := i2c.controllerTransmit(w); resultSuccess != result {\n\t\t\treturn errI2CWriteTimeout\n\t\t}\n\t}\n\n\t// perform receive transfer\n\tif nil != r {\n\t\t// generate (repeated-)start condition on bus\n\t\tif result := i2c.start(addr, directionRead); resultSuccess != result {\n\t\t\treturn errI2CSignalStartTimeout\n\t\t}\n\t\t// read received data\n\t\tif result := i2c.controllerReceive(r); resultSuccess != result {\n\t\t\treturn errI2CReadTimeout\n\t\t}\n\t}\n\n\t// generate stop condition on bus\n\tif result := i2c.stop(); resultSuccess != result {\n\t\treturn errI2CSignalStopTimeout\n\t}\n\n\treturn nil\n}\n\n// WriteRegisterEx transmits first the register and then the data to the\n// peripheral device.\n//\n// Many I2C-compatible devices are organized in terms of registers. This method\n// is a shortcut to easily write to such registers. Also, it only works for\n// devices with 7-bit addresses, which is the vast majority.\nfunc (i2c I2C) WriteRegisterEx(address uint8, register uint8, data []byte) error {\n\toption := transferOption{\n\t\tflags:          transferDefault,  // transfer options bit mask (0 = normal transfer)\n\t\tperipheral:     uint16(address),  // 7-bit peripheral address\n\t\tdirection:      directionWrite,   // directionRead or directionWrite\n\t\tsubaddress:     uint16(register), // peripheral sub-address (transferred MSB first)\n\t\tsubaddressSize: 1,                // byte length of sub-address (maximum = 4 bytes)\n\t}\n\tif result := i2c.controllerTransferPoll(option, data); resultSuccess != result {\n\t\treturn errI2CWriteTimeout\n\t}\n\treturn nil\n}\n\n// ReadRegisterEx transmits the register, restarts the connection as a read\n// operation, and reads the response.\n//\n// Many I2C-compatible devices are organized in terms of registers. This method\n// is a shortcut to easily read such registers. Also, it only works for devices\n// with 7-bit addresses, which is the vast majority.\nfunc (i2c I2C) ReadRegisterEx(address uint8, register uint8, data []byte) error {\n\toption := transferOption{\n\t\tflags:          transferDefault,  // transfer options bit mask (0 = normal transfer)\n\t\tperipheral:     uint16(address),  // 7-bit peripheral address\n\t\tdirection:      directionRead,    // directionRead or directionWrite\n\t\tsubaddress:     uint16(register), // peripheral sub-address (transferred MSB first)\n\t\tsubaddressSize: 1,                // byte length of sub-address (maximum = 4 bytes)\n\t}\n\tif result := i2c.controllerTransferPoll(option, data); resultSuccess != result {\n\t\treturn errI2CWriteTimeout\n\t}\n\treturn nil\n}\n\nfunc (i2c *I2C) reset(freq uint32) {\n\t// disable interface\n\ti2c.Bus.MCR.ClearBits(nxp.LPI2C_MCR_MEN)\n\n\t// software reset all interface registers\n\ti2c.Bus.MCR.Set(nxp.LPI2C_MCR_RST)\n\n\t// RST remains set until manually cleared!\n\ti2c.Bus.MCR.ClearBits(nxp.LPI2C_MCR_RST)\n\n\t// disable host request\n\ti2c.Bus.MCFGR0.Set(0)\n\n\t// enable ACK, use I2C 2-pin open drain mode\n\ti2c.Bus.MCFGR1.Set(0)\n\n\t// set FIFO watermarks (RX=1, TX=1)\n\tmfcr := (uint32(0x1) << nxp.LPI2C_MFCR_RXWATER_Pos) & nxp.LPI2C_MFCR_RXWATER_Msk\n\tmfcr |= (uint32(0x1) << nxp.LPI2C_MFCR_TXWATER_Pos) & nxp.LPI2C_MFCR_TXWATER_Msk\n\ti2c.Bus.MFCR.Set(mfcr)\n\n\t// configure clock using receiver frequency\n\ti2c.setFrequency(freq)\n\n\t// clear reset, and enable the interface\n\ti2c.Bus.MCR.Set(nxp.LPI2C_MCR_MEN)\n\n\t// wait for the I2C bus to idle\n\tfor i2c.Bus.MSR.Get()&nxp.LPI2C_MSR_BBF != 0 {\n\t}\n}\n\nfunc (i2c *I2C) setFrequency(freq uint32) {\n\tvar (\n\t\tbestPre   uint32 = 0\n\t\tbestClkHi uint32 = 0\n\t\tbestError uint32 = 0xFFFFFFFF\n\t)\n\n\t// disable interface\n\twasEnabled := i2c.Bus.MCR.HasBits(nxp.LPI2C_MCR_MEN)\n\ti2c.Bus.MCR.ClearBits(nxp.LPI2C_MCR_MEN)\n\n\t// baud rate = (24MHz/(2^pre))/(CLKLO+1 + CLKHI+1 + FLOOR((2+FILTSCL)/(2^pre)))\n\t// assume: CLKLO=2*CLKHI, SETHOLD=CLKHI, DATAVD=CLKHI/2\n\tfor pre := uint32(1); pre <= 128; pre *= 2 {\n\t\tif bestError == 0 {\n\t\t\tbreak\n\t\t}\n\t\tfor clkHi := uint32(1); clkHi < 32; clkHi++ {\n\t\t\tvar absError, rate uint32\n\t\t\tif clkHi == 1 {\n\t\t\t\trate = (24 * MHz / pre) / (1 + 3 + 2 + 2/pre)\n\t\t\t} else {\n\t\t\t\trate = (24 * MHz / pre) / (3*clkHi + 2 + 2/pre)\n\t\t\t}\n\t\t\tif freq > rate {\n\t\t\t\tabsError = freq - rate\n\t\t\t} else {\n\t\t\t\tabsError = rate - freq\n\t\t\t}\n\t\t\tif absError < bestError {\n\t\t\t\tbestPre = pre\n\t\t\t\tbestClkHi = clkHi\n\t\t\t\tbestError = absError\n\t\t\t\t// if the error is 0, then we can stop searching because we won't find a\n\t\t\t\t// better match\n\t\t\t\tif absError == 0 {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tvar (\n\t\tclklo   = func(n uint32) uint32 { return (n << nxp.LPI2C_MCCR0_CLKLO_Pos) & nxp.LPI2C_MCCR0_CLKLO_Msk }\n\t\tclkhi   = func(n uint32) uint32 { return (n << nxp.LPI2C_MCCR0_CLKHI_Pos) & nxp.LPI2C_MCCR0_CLKHI_Msk }\n\t\tdatavd  = func(n uint32) uint32 { return (n << nxp.LPI2C_MCCR0_DATAVD_Pos) & nxp.LPI2C_MCCR0_DATAVD_Msk }\n\t\tsethold = func(n uint32) uint32 { return (n << nxp.LPI2C_MCCR0_SETHOLD_Pos) & nxp.LPI2C_MCCR0_SETHOLD_Msk }\n\t)\n\t// StandardMode, FastMode, FastModePlus, and UltraFastMode\n\tmccr0 := clkhi(bestClkHi)\n\tif bestClkHi < 2 {\n\t\tmccr0 |= (clklo(3) | sethold(2) | datavd(1))\n\t} else {\n\t\tmccr0 |= clklo(2*bestClkHi) | sethold(bestClkHi) | datavd(bestClkHi/2)\n\t}\n\ti2c.Bus.MCCR0.Set(mccr0)\n\ti2c.Bus.MCCR1.Set(i2c.Bus.MCCR0.Get())\n\n\tfor i := uint32(0); i < 8; i++ {\n\t\tif bestPre == (1 << i) {\n\t\t\tbestPre = i\n\t\t\tbreak\n\t\t}\n\t}\n\tpreMask := (bestPre << nxp.LPI2C_MCFGR1_PRESCALE_Pos) & nxp.LPI2C_MCFGR1_PRESCALE_Msk\n\ti2c.Bus.MCFGR1.Set((i2c.Bus.MCFGR1.Get() & ^uint32(nxp.LPI2C_MCFGR1_PRESCALE_Msk)) | preMask)\n\n\tvar (\n\t\tfiltsda = func(n uint32) uint32 { return (n << nxp.LPI2C_MCFGR2_FILTSDA_Pos) & nxp.LPI2C_MCFGR2_FILTSDA_Msk }\n\t\tfiltscl = func(n uint32) uint32 { return (n << nxp.LPI2C_MCFGR2_FILTSCL_Pos) & nxp.LPI2C_MCFGR2_FILTSCL_Msk }\n\t\tbusidle = func(n uint32) uint32 { return (n << nxp.LPI2C_MCFGR2_BUSIDLE_Pos) & nxp.LPI2C_MCFGR2_BUSIDLE_Msk }\n\t\tpinlow  = func(n uint32) uint32 { return (n << nxp.LPI2C_MCFGR3_PINLOW_Pos) & nxp.LPI2C_MCFGR3_PINLOW_Msk }\n\n\t\tmcfgr2, mcfgr3 uint32\n\t)\n\tconst i2cClockStretchTimeout = 15000 // microseconds\n\tif freq >= 5*MHz {\n\t\t// I2C UltraFastMode 5 MHz\n\t\tmcfgr2 = 0 // disable glitch filters and timeout for UltraFastMode\n\t\tmcfgr3 = 0 //\n\t} else if freq >= 1*MHz {\n\t\t// I2C FastModePlus 1 MHz\n\t\tmcfgr2 = filtsda(1) | filtscl(1) | busidle(2400) // 100us timeout\n\t\tmcfgr3 = pinlow(i2cClockStretchTimeout*24/256 + 1)\n\t} else if freq >= 400*KHz {\n\t\t// I2C FastMode 400 kHz\n\t\tmcfgr2 = filtsda(2) | filtscl(2) | busidle(3600) // 150us timeout\n\t\tmcfgr3 = pinlow(i2cClockStretchTimeout*24/256 + 1)\n\t} else {\n\t\t// I2C StandardMode 100 kHz\n\t\tmcfgr2 = filtsda(5) | filtscl(5) | busidle(3000) // 250us timeout\n\t\tmcfgr3 = pinlow(i2cClockStretchTimeout*12/256 + 1)\n\t}\n\ti2c.Bus.MCFGR2.Set(mcfgr2)\n\ti2c.Bus.MCFGR3.Set(mcfgr3)\n\n\t// restore controller mode if it was enabled when called\n\tif wasEnabled {\n\t\ti2c.Bus.MCR.SetBits(nxp.LPI2C_MCR_MEN)\n\t}\n}\n\n// checkStatus converts the status register to a resultFlag for return, and\n// clears any errors if present.\nfunc (i2c *I2C) checkStatus(status statusFlag) resultFlag {\n\tresult := resultSuccess\n\t// check for error. these errors cause a stop to be sent automatically.\n\t// we must clear the errors before a new transfer can start.\n\tif status &= statusError; 0 != status {\n\t\t// select the correct error code ordered by severity, bus issues first.\n\t\tif 0 != (status & statusPinLowTimeout) {\n\t\t\tresult = resultPinLowTimeout\n\t\t} else if 0 != (status & statusArbitrationLost) {\n\t\t\tresult = resultArbitrationLost\n\t\t} else if 0 != (status & statusNackDetect) {\n\t\t\tresult = resultNak\n\t\t} else if 0 != (status & statusFifoErr) {\n\t\t\tresult = resultFifoError\n\t\t}\n\t\t// clear the flags\n\t\ti2c.Bus.MSR.Set(uint32(status))\n\t\t// reset fifos. these flags clear automatically.\n\t\ti2c.Bus.MCR.SetBits(nxp.LPI2C_MCR_RRF | nxp.LPI2C_MCR_RTF)\n\t}\n\treturn result\n}\n\nfunc (i2c *I2C) getFIFOSize() (rx, tx uint32) { return 4, 4 }\nfunc (i2c *I2C) getFIFOCount() (rx, tx uint32) {\n\tmfsr := i2c.Bus.MFSR.Get()\n\treturn (mfsr & nxp.LPI2C_MFSR_RXCOUNT_Msk) >> nxp.LPI2C_MFSR_RXCOUNT_Pos,\n\t\t(mfsr & nxp.LPI2C_MFSR_TXCOUNT_Msk) >> nxp.LPI2C_MFSR_TXCOUNT_Pos\n}\n\nfunc (i2c *I2C) waitForTxReady() resultFlag {\n\tresult := resultSuccess\n\t_, txSize := i2c.getFIFOSize()\n\tfor {\n\t\t_, txCount := i2c.getFIFOCount()\n\t\tstatus := statusFlag(i2c.Bus.MSR.Get())\n\t\tif result = i2c.checkStatus(status); resultSuccess != result {\n\t\t\tbreak\n\t\t}\n\t\tif txSize-txCount > 0 {\n\t\t\tbreak\n\t\t}\n\t}\n\treturn result\n}\n\nfunc (i2c *I2C) waitForTxEmpty() resultFlag {\n\tresult := resultSuccess\n\tfor {\n\t\t_, txCount := i2c.getFIFOCount()\n\t\tstatus := statusFlag(i2c.Bus.MSR.Get())\n\t\tif result = i2c.checkStatus(status); resultSuccess != result {\n\t\t\tbreak\n\t\t}\n\t\tif 0 == txCount {\n\t\t\tbreak\n\t\t}\n\t}\n\treturn result\n}\n\n// isBusBusy checks if the I2C bus is busy, returning true if it is busy and we\n// are not the ones driving it, otherwise false.\nfunc (i2c *I2C) isBusBusy() bool {\n\tstatus := statusFlag(i2c.Bus.MSR.Get())\n\treturn (0 != (status & statusBusBusy)) && (0 == (status & statusBusy))\n}\n\n// start sends a START signal and peripheral address on the I2C bus.\n//\n// This function is used to initiate a new controller mode transfer. First, the\n// bus state is checked to ensure that another controller is not occupying the\n// bus. Then a START signal is transmitted, followed by the 7-bit peripheral\n// address. Note that this function does not actually wait until the START and\n// address are successfully sent on the bus before returning.\nfunc (i2c *I2C) start(address uint16, dir i2cDirection) resultFlag {\n\t// return an error if the bus is already in use by another controller\n\tif i2c.isBusBusy() {\n\t\treturn resultBusy\n\t}\n\t// clear all flags\n\ti2c.Bus.MSR.Set(uint32(statusClear))\n\t// turn off auto-stop\n\ti2c.Bus.MCFGR1.ClearBits(nxp.LPI2C_MCFGR1_AUTOSTOP)\n\t// wait until there is room in the FIFO\n\tif result := i2c.waitForTxReady(); resultSuccess != result {\n\t\treturn result\n\t}\n\n\t// issue start command\n\ti2c.Bus.MTDR.Set(uint32(commandStart) | dir.shift(address))\n\treturn resultSuccess\n}\n\n// stop sends a STOP signal on the I2C bus.\n//\n// This function does not return until the STOP signal is seen on the bus, or\n// an error occurs.\nfunc (i2c *I2C) stop() resultFlag {\n\tconst tryMax = 0 // keep waiting forever\n\t// wait until there is room in the FIFO\n\tresult := i2c.waitForTxReady()\n\tif resultSuccess != result {\n\t\treturn result\n\t}\n\t// send the STOP signal\n\ti2c.Bus.MTDR.Set(uint32(commandStop))\n\t// wait for the stop detected flag to set, indicating the transfer has\n\t// completed on the bus. also check for errors while waiting.\n\ttry := 0\n\tfor resultSuccess == result && (0 == tryMax || try < tryMax) {\n\t\tstatus := statusFlag(i2c.Bus.MSR.Get())\n\t\tresult = i2c.checkStatus(status)\n\t\tif (0 != (status & statusStopDetect)) && (0 != (status & statusTxReady)) {\n\t\t\ti2c.Bus.MSR.Set(uint32(statusStopDetect))\n\t\t\tbreak\n\t\t}\n\t\ttry++\n\t}\n\tif 0 != tryMax && try >= tryMax {\n\t\treturn resultTimeout\n\t}\n\treturn result\n}\n\n// controllerReceive performs a polling receive transfer on the I2C bus.\nfunc (i2c *I2C) controllerReceive(rxBuffer []byte) resultFlag {\n\tconst tryMax = 0 // keep trying forever\n\trxSize := len(rxBuffer)\n\tif rxSize == 0 {\n\t\treturn resultSuccess\n\t}\n\t// wait until there is room in the FIFO\n\tresult := i2c.waitForTxReady()\n\tif resultSuccess != result {\n\t\treturn result\n\t}\n\tsizeMask := (uint32(rxSize-1) << nxp.LPI2C_MTDR_DATA_Pos) & nxp.LPI2C_MTDR_DATA_Msk\n\ti2c.Bus.MTDR.Set(uint32(commandRxData) | sizeMask)\n\n\t// receive data\n\tfor rxSize > 0 {\n\t\t// read LPI2C receive FIFO register. the register includes a flag to\n\t\t// indicate whether the FIFO is empty, so we can both get the data and check\n\t\t// if we need to keep reading using a single register read.\n\t\tvar data uint32\n\t\ttry := 0\n\t\tfor 0 == tryMax || try < tryMax {\n\t\t\t// check for errors on the bus\n\t\t\tstatus := statusFlag(i2c.Bus.MSR.Get())\n\t\t\tresult = i2c.checkStatus(status)\n\t\t\tif resultSuccess != result {\n\t\t\t\treturn result\n\t\t\t}\n\t\t\t// read received data, break if FIFO was non-empty\n\t\t\tdata = i2c.Bus.MRDR.Get()\n\t\t\tif 0 == (data & nxp.LPI2C_MRDR_RXEMPTY_Msk) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\ttry++\n\t\t}\n\t\t// ensure we didn't timeout waiting for data\n\t\tif 0 != tryMax && try >= tryMax {\n\t\t\treturn resultTimeout\n\t\t}\n\t\t// copy data to RX buffer\n\t\trxBuffer[len(rxBuffer)-rxSize] = byte(data & nxp.LPI2C_MRDR_DATA_Msk)\n\t\trxSize--\n\t}\n\treturn result\n}\n\n// controllerTransmit performs a polling transmit transfer on the I2C bus.\nfunc (i2c *I2C) controllerTransmit(txBuffer []byte) resultFlag {\n\ttxSize := len(txBuffer)\n\tfor txSize > 0 {\n\t\t// wait until there is room in the FIFO\n\t\tresult := i2c.waitForTxReady()\n\t\tif resultSuccess != result {\n\t\t\treturn result\n\t\t}\n\t\t// write byte into LPI2C data register\n\t\ti2c.Bus.MTDR.Set(uint32(txBuffer[len(txBuffer)-txSize] & nxp.LPI2C_MTDR_DATA_Msk))\n\t\ttxSize--\n\t}\n\treturn resultSuccess\n}\n\ntype transferOption struct {\n\tflags          transferFlag // transfer options bit mask (0 = normal transfer)\n\tperipheral     uint16       // 7-bit peripheral address\n\tdirection      i2cDirection // directionRead or directionWrite\n\tsubaddress     uint16       // peripheral sub-address (transferred MSB first)\n\tsubaddressSize uint16       // byte length of sub-address (maximum = 4 bytes)\n}\n\nfunc (i2c *I2C) controllerTransferPoll(option transferOption, data []byte) resultFlag {\n\t// return an error if the bus is already in use by another controller\n\tif i2c.isBusBusy() {\n\t\treturn resultBusy\n\t}\n\t// clear all flags\n\ti2c.Bus.MSR.Set(uint32(statusClear))\n\t// turn off auto-stop\n\ti2c.Bus.MCFGR1.ClearBits(nxp.LPI2C_MCFGR1_AUTOSTOP)\n\n\tcmd := make([]uint16, 0, 7)\n\tsize := len(data)\n\n\tdirection := option.direction\n\tif option.subaddressSize > 0 {\n\t\tdirection = directionWrite\n\t}\n\t// peripheral address\n\tif 0 == (option.flags & transferNoStart) {\n\t\taddr := direction.shift(option.peripheral)\n\t\tcmd = append(cmd, uint16(uint32(commandStart)|addr))\n\t}\n\t// sub-address (MSB-first)\n\trem := option.subaddressSize\n\tfor rem > 0 {\n\t\trem--\n\t\tcmd = append(cmd, (option.subaddress>>(8*rem))&0xFF)\n\t}\n\t// need to send repeated start if switching directions to read\n\tif (0 != size) && (directionRead == option.direction) {\n\t\tif directionWrite == direction {\n\t\t\taddr := directionRead.shift(option.peripheral)\n\t\t\tcmd = append(cmd, uint16(uint32(commandStart)|addr))\n\t\t}\n\t}\n\t// send command buffer\n\tresult := resultSuccess\n\tfor _, c := range cmd {\n\t\t// wait until there is room in the FIFO\n\t\tif result = i2c.waitForTxReady(); resultSuccess != result {\n\t\t\treturn result\n\t\t}\n\t\t// write byte into LPI2C controller data register\n\t\ti2c.Bus.MTDR.Set(uint32(c))\n\t}\n\t// send data\n\tif option.direction == directionWrite && size > 0 {\n\t\tresult = i2c.controllerTransmit(data)\n\t}\n\t// receive data\n\tif option.direction == directionRead && size > 0 {\n\t\tresult = i2c.controllerReceive(data)\n\t}\n\tif resultSuccess != result {\n\t\treturn result\n\t}\n\tif 0 == (option.flags & transferNoStop) {\n\t\tresult = i2c.stop()\n\t}\n\treturn result\n}\n"
  },
  {
    "path": "src/machine/machine_mimxrt1062_spi.go",
    "content": "//go:build mimxrt1062\n\npackage machine\n\n// SPI peripheral abstraction layer for the MIMXRT1062\n\nimport (\n\t\"device/nxp\"\n\t\"errors\"\n\t\"unsafe\"\n)\n\n// SPIConfig is used to store config info for SPI.\ntype SPIConfig struct {\n\tFrequency uint32\n\tSDI       Pin\n\tSDO       Pin\n\tSCK       Pin\n\tCS        Pin\n\tLSBFirst  bool\n\tMode      uint8\n}\n\nfunc (c SPIConfig) getPins() (di, do, ck, cs Pin) {\n\tif 0 == c.SDI && 0 == c.SDO && 0 == c.SCK && 0 == c.CS {\n\t\t// default pins if none specified\n\t\treturn SPI_SDI_PIN, SPI_SDO_PIN, SPI_SCK_PIN, SPI_CS_PIN\n\t}\n\treturn c.SDI, c.SDO, c.SCK, c.CS\n}\n\ntype SPI struct {\n\tBus *nxp.LPSPI_Type\n\n\t// these hold the input selector (\"daisy chain\") values that select which pins\n\t// are connected to the LPSPI device, and should be defined where the SPI\n\t// instance is declared (e.g., in the board definition). see the godoc\n\t// comments on type muxSelect for more details.\n\tmuxSDI, muxSDO, muxSCK, muxCS muxSelect\n\n\t// these are copied from SPIConfig, during (*SPI).Configure(SPIConfig), and\n\t// should be considered read-only for internal reference (i.e., modifying them\n\t// will have no desirable effect).\n\tsdi, sdo, sck, cs Pin\n\tfrequency         uint32\n\n\t// auxiliary state data used internally\n\tconfigured bool\n}\n\nconst (\n\tstatusTxDataRequest    = nxp.LPSPI_SR_TDF // Transmit data flag\n\tstatusRxDataReady      = nxp.LPSPI_SR_RDF // Receive data flag\n\tstatusWordComplete     = nxp.LPSPI_SR_WCF // Word Complete flag\n\tstatusFrameComplete    = nxp.LPSPI_SR_FCF // Frame Complete flag\n\tstatusTransferComplete = nxp.LPSPI_SR_TCF // Transfer Complete flag\n\tstatusTransmitError    = nxp.LPSPI_SR_TEF // Transmit Error flag (FIFO underrun)\n\tstatusReceiveError     = nxp.LPSPI_SR_REF // Receive Error flag (FIFO overrun)\n\tstatusDataMatch        = nxp.LPSPI_SR_DMF // Data Match flag\n\tstatusModuleBusy       = nxp.LPSPI_SR_MBF // Module Busy flag\n\tstatusAll              = nxp.LPSPI_SR_TDF | nxp.LPSPI_SR_RDF |\n\t\tnxp.LPSPI_SR_WCF | nxp.LPSPI_SR_FCF | nxp.LPSPI_SR_TCF | nxp.LPSPI_SR_TEF |\n\t\tnxp.LPSPI_SR_REF | nxp.LPSPI_SR_DMF | nxp.LPSPI_SR_MBF\n)\n\nvar (\n\terrSPINotConfigured = errors.New(\"SPI interface is not yet configured\")\n)\n\n// Configure is intended to setup an SPI interface for transmit/receive.\nfunc (spi *SPI) Configure(config SPIConfig) error {\n\n\tconst defaultSpiFreq = 4000000 // 4 MHz\n\n\t// init pins\n\tspi.sdi, spi.sdo, spi.sck, spi.cs = config.getPins()\n\n\t// configure the mux and pad control registers\n\tspi.sdi.Configure(PinConfig{Mode: PinModeSPISDI})\n\tspi.sdo.Configure(PinConfig{Mode: PinModeSPISDO})\n\tspi.sck.Configure(PinConfig{Mode: PinModeSPICLK})\n\tspi.cs.Configure(PinConfig{Mode: PinModeSPICS})\n\n\t// configure the mux input selector\n\tspi.muxSDI.connect()\n\tspi.muxSDO.connect()\n\tspi.muxSCK.connect()\n\tspi.muxCS.connect()\n\n\t// software reset of LPSPI state registers\n\tspi.Bus.CR.SetBits(nxp.LPSPI_CR_RST)\n\t// also reset FIFOs (not performed by software reset above)\n\tspi.Bus.CR.SetBits(nxp.LPSPI_CR_RRF | nxp.LPSPI_CR_RTF)\n\tspi.Bus.CR.Set(0)\n\n\t// set controller mode, and input data is sampled on delayed SCK edge\n\tspi.Bus.CFGR1.Set(nxp.LPSPI_CFGR1_MASTER | nxp.LPSPI_CFGR1_SAMPLE)\n\n\tspi.frequency = config.Frequency\n\tif 0 == spi.frequency {\n\t\tspi.frequency = defaultSpiFreq\n\t}\n\n\t// configure LPSPI clock divisor and CS assertion delays\n\tdiv := spi.getClockDivisor(config.Frequency)\n\tccr := (div << nxp.LPSPI_CCR_SCKDIV_Pos) & nxp.LPSPI_CCR_SCKDIV_Msk\n\tccr |= ((div / 2) << nxp.LPSPI_CCR_DBT_Pos) & nxp.LPSPI_CCR_DBT_Msk\n\tccr |= ((div / 2) << nxp.LPSPI_CCR_PCSSCK_Pos) & nxp.LPSPI_CCR_PCSSCK_Msk\n\tspi.Bus.CCR.Set(ccr)\n\n\t// 8-bit frame size (words)\n\ttcr := uint32(7)\n\tif config.LSBFirst {\n\t\ttcr |= nxp.LPSPI_TCR_LSBF\n\t}\n\t// set polarity and phase\n\tswitch config.Mode {\n\tcase Mode1:\n\t\ttcr |= nxp.LPSPI_TCR_CPHA\n\tcase Mode2:\n\t\ttcr |= nxp.LPSPI_TCR_CPOL\n\tcase Mode3:\n\t\ttcr |= nxp.LPSPI_TCR_CPOL\n\t\ttcr |= nxp.LPSPI_TCR_CPHA\n\t}\n\tspi.Bus.TCR.Set(tcr)\n\n\t// clear FIFO water marks\n\tspi.setWatermark(0, 0)\n\n\t// enable LPSPI module\n\tspi.Bus.CR.Set(nxp.LPSPI_CR_MEN)\n\n\tspi.configured = true\n\n\treturn nil\n}\n\n// Transfer writes/reads a single byte using the SPI interface.\nfunc (spi *SPI) Transfer(w byte) (byte, error) {\n\tif !spi.configured {\n\t\treturn 0, errSPINotConfigured\n\t}\n\n\tconst readTryMax = 10000\n\n\tfor spi.Bus.SR.HasBits(statusModuleBusy) {\n\t} // wait for SPI busy bit to clear\n\n\t_, txFIFOSize := spi.getFIFOSize()\n\n\tspi.flushFIFO(true, true)\n\tspi.Bus.SR.Set(statusAll) // clear all status flags (W1C)\n\n\t// enable LPSPI module\n\tspi.Bus.CR.Set(nxp.LPSPI_CR_MEN)\n\n\t// TODO: unnecessary since we just flushed the FIFO?\n\tfor { // wait for TX FIFO to not be full\n\t\tif _, txFIFO := spi.getFIFOCount(); txFIFO < txFIFOSize {\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// write out byte to TX FIFO\n\tspi.Bus.TDR.Set(uint32(w))\n\n\t// try to read from RX FIFO if anything exists\n\tdidRead := false\n\tdata := byte(0)\n\tfor i := 0; !didRead && (i < readTryMax); i++ {\n\t\trxFIFO, _ := spi.getFIFOCount()\n\t\tdidRead = rxFIFO > 0\n\t\tif didRead {\n\t\t\tdata = byte(spi.Bus.RDR.Get())\n\t\t}\n\t}\n\n\t// if nothing was read, then wait for transfer complete flag to decide when\n\t// we are finished\n\tif !didRead {\n\t\tfor !spi.Bus.SR.HasBits(nxp.LPSPI_SR_TCF) {\n\t\t} // wait for all transfers complete flag to set\n\t}\n\n\treturn data, nil\n}\n\nfunc (spi *SPI) isHardwareCSPin(pin Pin) bool {\n\tswitch unsafe.Pointer(spi.Bus) {\n\tcase unsafe.Pointer(nxp.LPSPI1):\n\t\treturn SPI1_CS_PIN == pin\n\tcase unsafe.Pointer(nxp.LPSPI2):\n\t\treturn SPI2_CS_PIN == pin\n\tcase unsafe.Pointer(nxp.LPSPI3):\n\t\treturn SPI3_CS_PIN == pin\n\t}\n\treturn false\n}\n\nfunc (spi *SPI) hasHardwareCSPin() bool {\n\treturn spi.isHardwareCSPin(spi.cs)\n}\n\n// getClockDivisor finds the SPI prescalar that minimizes the error between\n// requested frequency and possible frequencies available with the LPSPI clock.\n// this routine is based on Teensyduino (libraries/SPI/SPI.cpp):\n//\n//\tvoid SPIClass::setClockDivider_noInline(uint32_t clk)\nfunc (spi *SPI) getClockDivisor(freq uint32) uint32 {\n\tconst clock = 132000000 // LPSPI root clock frequency (PLL2)\n\td := uint32(clock)\n\tif freq > 0 {\n\t\td /= freq\n\t}\n\tif d > 0 && clock/d > freq {\n\t\td++\n\t}\n\tif d > 257 {\n\t\treturn 255\n\t}\n\tif d > 2 {\n\t\treturn d - 2\n\t}\n\treturn 0\n}\n\nfunc (spi *SPI) getFIFOSize() (rx, tx uint32) {\n\tparam := spi.Bus.PARAM.Get()\n\treturn uint32(1) << ((param & nxp.LPSPI_PARAM_RXFIFO_Msk) >> nxp.LPSPI_PARAM_RXFIFO_Pos),\n\t\tuint32(1) << ((param & nxp.LPSPI_PARAM_TXFIFO_Msk) >> nxp.LPSPI_PARAM_TXFIFO_Pos)\n}\n\nfunc (spi *SPI) getFIFOCount() (rx, tx uint32) {\n\tfsr := spi.Bus.FSR.Get()\n\treturn (fsr & nxp.LPSPI_FSR_RXCOUNT_Msk) >> nxp.LPSPI_FSR_RXCOUNT_Pos,\n\t\t(fsr & nxp.LPSPI_FSR_TXCOUNT_Msk) >> nxp.LPSPI_FSR_TXCOUNT_Pos\n}\n\nfunc (spi *SPI) flushFIFO(rx, tx bool) {\n\tvar flush uint32\n\tif rx {\n\t\tflush |= nxp.LPSPI_CR_RRF\n\t}\n\tif tx {\n\t\tflush |= nxp.LPSPI_CR_RTF\n\t}\n\tspi.Bus.CR.SetBits(flush)\n}\n\nfunc (spi *SPI) setWatermark(rx, tx uint32) {\n\tspi.Bus.FCR.Set(((rx << nxp.LPSPI_FCR_RXWATER_Pos) & nxp.LPSPI_FCR_RXWATER_Msk) |\n\t\t((tx << nxp.LPSPI_FCR_TXWATER_Pos) & nxp.LPSPI_FCR_TXWATER_Msk))\n}\n"
  },
  {
    "path": "src/machine/machine_mimxrt1062_uart.go",
    "content": "//go:build mimxrt1062\n\npackage machine\n\nimport (\n\t\"device/nxp\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n)\n\n// UART peripheral abstraction layer for the MIMXRT1062\n\ntype UART struct {\n\tBus       *nxp.LPUART_Type\n\tBuffer    *RingBuffer\n\tInterrupt interrupt.Interrupt\n\n\t// txBuffer should be allocated globally (such as when UART is created) to\n\t// prevent it being reclaimed or cleaned up prematurely.\n\ttxBuffer *RingBuffer\n\n\t// these hold the input selector (\"daisy chain\") values that select which pins\n\t// are connected to the LPUART device, and should be defined where the UART\n\t// instance is declared. see the godoc comments on type muxSelect for more\n\t// details.\n\tmuxRX, muxTX muxSelect\n\n\t// these are copied from UARTConfig, during (*UART).Configure(UARTConfig), and\n\t// should be considered read-only for internal reference (i.e., modifying them\n\t// will have no desirable effect).\n\trx, tx Pin\n\tbaud   uint32\n\n\t// auxiliary state data used internally\n\tconfigured   bool\n\ttransmitting volatile.Register32\n}\n\nfunc (uart *UART) isTransmitting() bool { return uart.transmitting.Get() != 0 }\nfunc (uart *UART) startTransmitting()   { uart.transmitting.Set(1) }\nfunc (uart *UART) stopTransmitting()    { uart.transmitting.Set(0) }\nfunc (uart *UART) resetTransmitting() {\n\tuart.stopTransmitting()\n\tuart.Bus.GLOBAL.SetBits(nxp.LPUART_GLOBAL_RST)\n\tuart.Bus.GLOBAL.ClearBits(nxp.LPUART_GLOBAL_RST)\n}\n\n// Configure initializes a UART with the given UARTConfig and other default\n// settings.\nfunc (uart *UART) Configure(config UARTConfig) {\n\n\tconst defaultUartFreq = 115200\n\n\t// use default baud rate if not specified\n\tif config.BaudRate == 0 {\n\t\tconfig.BaudRate = defaultUartFreq\n\t}\n\n\t// use default UART pins if not specified\n\tif config.RX == 0 && config.TX == 0 {\n\t\tconfig.RX = UART_RX_PIN\n\t\tconfig.TX = UART_TX_PIN\n\t}\n\n\tuart.baud = config.BaudRate\n\tuart.rx = config.RX\n\tuart.tx = config.TX\n\n\t// configure the mux and pad control registers\n\tuart.rx.Configure(PinConfig{Mode: PinModeUARTRX})\n\tuart.tx.Configure(PinConfig{Mode: PinModeUARTTX})\n\n\t// configure the mux input selector\n\tuart.muxRX.connect()\n\tuart.muxTX.connect()\n\n\t// reset all internal logic and registers\n\tuart.resetTransmitting()\n\n\t// disable until we have finished configuring registers\n\tuart.Bus.CTRL.Set(0)\n\n\t// determine the baud rate and over-sample divisors\n\tsbr, osr := uart.getBaudRateDivisor(uart.baud)\n\n\t// set the baud rate, over-sample configuration, stop bits\n\tbaudBits := (((osr - 1) << nxp.LPUART_BAUD_OSR_Pos) & nxp.LPUART_BAUD_OSR_Msk) |\n\t\t((sbr << nxp.LPUART_BAUD_SBR_Pos) & nxp.LPUART_BAUD_SBR_Msk)\n\tif osr <= 8 {\n\t\t// if OSR less than or equal to 8, we must enable sampling on both edges\n\t\tbaudBits |= nxp.LPUART_BAUD_BOTHEDGE\n\t}\n\tuart.Bus.BAUD.Set(baudBits)\n\tuart.Bus.PINCFG.Set(0) // disable triggers\n\n\t// configure watermarks, flush and enable TX/RX FIFOs\n\trxSize, txSize := uart.getFIFOSize()\n\trxWater := rxSize >> 1\n\tif rxWater > uint32(nxp.LPUART_FIFO_RXFIFOSIZE_Msk>>nxp.LPUART_FIFO_RXFIFOSIZE_Pos) {\n\t\trxWater = uint32(nxp.LPUART_FIFO_RXFIFOSIZE_Msk >> nxp.LPUART_FIFO_RXFIFOSIZE_Pos)\n\t}\n\ttxWater := txSize >> 1\n\tif txWater > uint32(nxp.LPUART_FIFO_TXFIFOSIZE_Msk>>nxp.LPUART_FIFO_TXFIFOSIZE_Pos) {\n\t\ttxWater = uint32(nxp.LPUART_FIFO_TXFIFOSIZE_Msk >> nxp.LPUART_FIFO_TXFIFOSIZE_Pos)\n\t}\n\tuart.Bus.WATER.Set(\n\t\t((rxWater << nxp.LPUART_WATER_RXWATER_Pos) & nxp.LPUART_WATER_RXWATER_Msk) |\n\t\t\t((txWater << nxp.LPUART_WATER_TXWATER_Pos) & nxp.LPUART_WATER_TXWATER_Msk))\n\tuart.Bus.FIFO.SetBits(nxp.LPUART_FIFO_RXFE | nxp.LPUART_FIFO_TXFE |\n\t\tnxp.LPUART_FIFO_RXFLUSH | nxp.LPUART_FIFO_TXFLUSH)\n\n\t// for now we assume some configuration. in particular:\n\t//  Data bits         -> 8-bit\n\t//  Parity bit        -> None (parity bit generation disabled)\n\t//  Stop bits         -> 1 stop bit\n\t//  MSB first         -> false\n\t//  RX idle type      -> idle count starts after start bit\n\t//  RX idle config    -> 1 idle character\n\t//  RX RTS enabled    -> false\n\t//  TX CTS enabled    -> false\n\n\t// enable transmitter, receiver functions\n\tuart.Bus.CTRL.Set(nxp.LPUART_CTRL_TE | nxp.LPUART_CTRL_RE |\n\t\t// enable receiver, idle line interrupts\n\t\tnxp.LPUART_CTRL_RIE | nxp.LPUART_CTRL_ILIE)\n\n\t// clear all status flags\n\tuart.Bus.STAT.Set(uart.Bus.STAT.Get())\n\n\t// enable RX interrupt\n\tuart.Interrupt.SetPriority(0xC0)\n\tuart.Interrupt.Enable()\n\n\tuart.configured = true\n}\n\n// Disable disables the UART interface.\n//\n// If any buffered data has not yet been transmitted, Disable waits until\n// transmission completes before disabling the interface. The receiver UART's\n// interrupt is also disabled, and the RX/TX pins are reconfigured for GPIO\n// input (pull-up).\nfunc (uart *UART) Disable() {\n\n\t// first ensure the device is enabled\n\tif uart.configured {\n\n\t\t// wait for any buffered data to send\n\t\tuart.Sync()\n\n\t\t// stop trapping RX interrupts\n\t\tuart.Interrupt.Disable()\n\n\t\t// reset all internal registers\n\t\tuart.resetTransmitting()\n\n\t\t// disable RX/TX functions\n\t\tuart.Bus.CTRL.ClearBits(nxp.LPUART_CTRL_TE | nxp.LPUART_CTRL_RE)\n\n\t\t// put pins back into GPIO mode\n\t\tuart.rx.Configure(PinConfig{Mode: PinInputPullup})\n\t\tuart.tx.Configure(PinConfig{Mode: PinInputPullup})\n\t}\n\tuart.configured = false\n}\n\n// Sync blocks the calling goroutine until all data in the output buffer has\n// been transmitted.\nfunc (uart *UART) Sync() error {\n\tfor uart.isTransmitting() {\n\t}\n\treturn nil\n}\n\n// WriteByte writes a single byte of data to the UART interface.\nfunc (uart *UART) writeByte(c byte) error {\n\tuart.startTransmitting()\n\tfor !uart.txBuffer.Put(c) {\n\t}\n\tuart.Bus.CTRL.SetBits(nxp.LPUART_CTRL_TIE)\n\treturn nil\n}\n\nfunc (uart *UART) flush() {}\n\n// getBaudRateDivisor finds the greatest over-sampling factor (4..32) and\n// corresponding baud rate divisor (1..8191) that best partition a given baud\n// rate into equal intervals.\n//\n// This is an integral (non-floating point) translation of the logic at the\n// beginning of:\n//\n//\tvoid HardwareSerial::begin(uint32_t baud, uint16_t format)\n//\n// (from Teensyduino: cores/teensy4/HardwareSerial.cpp)\n//\n// We don't want to use floating point here in case it gets called from an ISR\n// or very early during system init.\nfunc (uart *UART) getBaudRateDivisor(baudRate uint32) (sbr uint32, osr uint32) {\n\tconst clock = 24000000 // UART is muxed to 24 MHz OSC\n\terr := uint32(0xFFFFFFFF)\n\tsbr, osr = 0, 0\n\tfor o := uint32(4); o <= 32; o++ {\n\t\ts := ((clock*10)/(baudRate*o) + 5) / 10\n\t\tif s == 0 {\n\t\t\ts = 1\n\t\t}\n\t\tb := clock / (s * o)\n\t\tvar e uint32\n\t\tif b > baudRate {\n\t\t\te = b - baudRate\n\t\t} else {\n\t\t\te = baudRate - b\n\t\t}\n\t\tif e <= err {\n\t\t\terr = e\n\t\t\tosr = o\n\t\t\tsbr = s\n\t\t}\n\t}\n\treturn sbr, osr\n}\n\nfunc (uart *UART) getFIFOSize() (rx, tx uint32) {\n\tfifo := uart.Bus.FIFO.Get()\n\trx = uint32(1) << ((fifo & nxp.LPUART_FIFO_RXFIFOSIZE_Msk) >> nxp.LPUART_FIFO_RXFIFOSIZE_Pos)\n\tif rx > 1 {\n\t\trx <<= 1\n\t}\n\ttx = uint32(1) << ((fifo & nxp.LPUART_FIFO_TXFIFOSIZE_Msk) >> nxp.LPUART_FIFO_TXFIFOSIZE_Pos)\n\tif tx > 1 {\n\t\ttx <<= 1\n\t}\n\treturn rx, tx\n}\n\nfunc (uart *UART) getStatus() uint32 {\n\treturn uart.Bus.STAT.Get() |\n\t\t((uart.Bus.FIFO.Get() & uint32(nxp.LPUART_FIFO_TXEMPT_Msk|nxp.LPUART_FIFO_RXEMPT_Msk|\n\t\t\tnxp.LPUART_FIFO_TXOF_Msk|nxp.LPUART_FIFO_RXUF_Msk)) >> 16)\n}\n\nfunc (uart *UART) getEnabledInterrupts() uint32 {\n\treturn ((uart.Bus.BAUD.Get() & uint32(nxp.LPUART_BAUD_LBKDIE_Msk|nxp.LPUART_BAUD_RXEDGIE_Msk)) >> 8) |\n\t\t((uart.Bus.FIFO.Get() & uint32(nxp.LPUART_FIFO_TXOFE_Msk|nxp.LPUART_FIFO_RXUFE_Msk)) >> 8) |\n\t\t(uart.Bus.CTRL.Get() & uint32(0xFF0C000))\n}\n\nfunc (uart *UART) disableInterrupts(mask uint32) {\n\tuart.Bus.BAUD.ClearBits((mask << 8) & uint32(nxp.LPUART_BAUD_LBKDIE_Msk|nxp.LPUART_BAUD_RXEDGIE_Msk))\n\tuart.Bus.FIFO.Set((uart.Bus.FIFO.Get() & ^uint32(nxp.LPUART_FIFO_TXOF_Msk|nxp.LPUART_FIFO_RXUF_Msk)) &\n\t\t^uint32((mask<<8)&(nxp.LPUART_FIFO_TXOFE_Msk|nxp.LPUART_FIFO_RXUFE_Msk)))\n\tmask &= uint32(0xFFFFFF00)\n\tuart.Bus.CTRL.ClearBits(mask)\n}\n\nfunc (uart *UART) handleInterrupt(interrupt.Interrupt) {\n\n\tstat := uart.getStatus()\n\tinte := uart.getEnabledInterrupts()\n\n\t_, txSize := uart.getFIFOSize()\n\n\t// check for and clear overrun, otherwise RX will not work\n\tif (stat & uint32(nxp.LPUART_STAT_OR)) != 0 {\n\t\tuart.Bus.STAT.Set((uart.Bus.STAT.Get() & uint32(0x3FE00000)) | nxp.LPUART_STAT_OR)\n\t}\n\n\t// idle or receive data register is full\n\tif (stat & uint32(nxp.LPUART_STAT_RDRF|nxp.LPUART_STAT_IDLE)) != 0 {\n\t\tcount := (uart.Bus.WATER.Get() & uint32(nxp.LPUART_WATER_RXCOUNT_Msk)) >> nxp.LPUART_WATER_RXCOUNT_Pos\n\t\tfor ; count > 0; count-- {\n\t\t\t// read up to 8 bits of data at a time\n\t\t\t// TODO: 7, 9, and 10-bit support?\n\t\t\tuart.Buffer.Put(uint8(uart.Bus.DATA.Get() & uint32(0xFF)))\n\t\t}\n\t\t// if it was an IDLE status, clear the flag\n\t\tif (stat & uint32(nxp.LPUART_STAT_IDLE)) != 0 {\n\t\t\tuart.Bus.STAT.SetBits(nxp.LPUART_STAT_IDLE)\n\t\t}\n\t\t// disable idle line interrupts\n\t\tuart.disableInterrupts(nxp.LPUART_CTRL_RIE | nxp.LPUART_CTRL_ORIE)\n\t}\n\n\t// check if we have data to write\n\tif ((inte & nxp.LPUART_CTRL_TIE) != 0) && ((stat & nxp.LPUART_STAT_TDRE) != 0) {\n\t\tfor ((uart.Bus.WATER.Get() & uint32(nxp.LPUART_WATER_TXCOUNT_Msk)) >> nxp.LPUART_WATER_TXCOUNT_Pos) < txSize {\n\t\t\tif b, ok := uart.txBuffer.Get(); ok {\n\t\t\t\tuart.Bus.DATA.Set(uint32(b))\n\t\t\t} else {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif uart.Bus.STAT.HasBits(nxp.LPUART_STAT_TDRE) {\n\t\t\tuart.Bus.CTRL.Set((uart.Bus.CTRL.Get() & ^uint32(nxp.LPUART_CTRL_TIE)) | nxp.LPUART_CTRL_TCIE)\n\t\t}\n\t}\n\n\tif ((inte & nxp.LPUART_CTRL_TCIE) != 0) && ((stat & nxp.LPUART_STAT_TC) != 0) {\n\t\tuart.stopTransmitting()\n\t\tuart.Bus.CTRL.ClearBits(nxp.LPUART_CTRL_TCIE)\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_nrf.go",
    "content": "//go:build nrf\n\npackage machine\n\nimport (\n\t\"device/arm\"\n\t\"device/nrf\"\n\t\"errors\"\n\t\"internal/binary\"\n\t\"runtime/interrupt\"\n\t\"unsafe\"\n)\n\nconst deviceName = nrf.Device\n\nvar deviceID [8]byte\n\n// DeviceID returns an identifier that is unique within\n// a particular chipset.\n//\n// The identity is one burnt into the MCU itself, or the\n// flash chip at time of manufacture.\n//\n// It's possible that two different vendors may allocate\n// the same DeviceID, so callers should take this into\n// account if needing to generate a globally unique id.\n//\n// The length of the hardware ID is vendor-specific, but\n// 8 bytes (64 bits) is common.\nfunc DeviceID() []byte {\n\twords := make([]uint32, 2)\n\twords[0] = nrf.FICR.DEVICEID[0].Get()\n\twords[1] = nrf.FICR.DEVICEID[1].Get()\n\n\tfor i := 0; i < 8; i++ {\n\t\tshift := (i % 4) * 8\n\t\tw := i / 4\n\t\tdeviceID[i] = byte(words[w] >> shift)\n\t}\n\n\treturn deviceID[:]\n}\n\nconst (\n\tPinInput         PinMode = (nrf.GPIO_PIN_CNF_DIR_Input << nrf.GPIO_PIN_CNF_DIR_Pos) | (nrf.GPIO_PIN_CNF_INPUT_Connect << nrf.GPIO_PIN_CNF_INPUT_Pos)\n\tPinInputPullup   PinMode = PinInput | (nrf.GPIO_PIN_CNF_PULL_Pullup << nrf.GPIO_PIN_CNF_PULL_Pos)\n\tPinInputPulldown PinMode = PinInput | (nrf.GPIO_PIN_CNF_PULL_Pulldown << nrf.GPIO_PIN_CNF_PULL_Pos)\n\tPinOutput        PinMode = (nrf.GPIO_PIN_CNF_DIR_Output << nrf.GPIO_PIN_CNF_DIR_Pos) | (nrf.GPIO_PIN_CNF_INPUT_Connect << nrf.GPIO_PIN_CNF_INPUT_Pos)\n)\n\ntype PinChange uint8\n\n// Pin change interrupt constants for SetInterrupt.\nconst (\n\tPinRising  PinChange = nrf.GPIOTE_CONFIG_POLARITY_LoToHi\n\tPinFalling PinChange = nrf.GPIOTE_CONFIG_POLARITY_HiToLo\n\tPinToggle  PinChange = nrf.GPIOTE_CONFIG_POLARITY_Toggle\n)\n\n// Callbacks to be called for pins configured with SetInterrupt.\nvar pinCallbacks [len(nrf.GPIOTE.CONFIG)]func(Pin)\n\n// Configure this pin with the given configuration.\nfunc (p Pin) Configure(config PinConfig) {\n\tcfg := config.Mode | nrf.GPIO_PIN_CNF_DRIVE_S0S1 | nrf.GPIO_PIN_CNF_SENSE_Disabled\n\tport, pin := p.getPortPin()\n\tport.PIN_CNF[pin].Set(uint32(cfg))\n}\n\n// Set the pin to high or low.\n// Warning: only use this on an output pin!\nfunc (p Pin) Set(high bool) {\n\tport, pin := p.getPortPin()\n\tif high {\n\t\tport.OUTSET.Set(1 << pin)\n\t} else {\n\t\tport.OUTCLR.Set(1 << pin)\n\t}\n}\n\n// Return the register and mask to enable a given GPIO pin. This can be used to\n// implement bit-banged drivers.\nfunc (p Pin) PortMaskSet() (*uint32, uint32) {\n\tport, pin := p.getPortPin()\n\treturn &port.OUTSET.Reg, 1 << pin\n}\n\n// Return the register and mask to disable a given port. This can be used to\n// implement bit-banged drivers.\nfunc (p Pin) PortMaskClear() (*uint32, uint32) {\n\tport, pin := p.getPortPin()\n\treturn &port.OUTCLR.Reg, 1 << pin\n}\n\n// Get returns the current value of a GPIO pin when the pin is configured as an\n// input or as an output.\nfunc (p Pin) Get() bool {\n\tport, pin := p.getPortPin()\n\treturn (port.IN.Get()>>pin)&1 != 0\n}\n\n// SetInterrupt sets an interrupt to be executed when a particular pin changes\n// state. The pin should already be configured as an input, including a pull up\n// or down if no external pull is provided.\n//\n// This call will replace a previously set callback on this pin. You can pass a\n// nil func to unset the pin change interrupt. If you do so, the change\n// parameter is ignored and can be set to any value (such as 0).\nfunc (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error {\n\t// Some variables to easily check whether a channel was already configured\n\t// as an event channel for the given pin.\n\t// This is not just an optimization, this is required: the datasheet says\n\t// that configuring more than one channel for a given pin results in\n\t// unpredictable behavior.\n\texpectedConfigMask := uint32(nrf.GPIOTE_CONFIG_MODE_Msk | nrf.GPIOTE_CONFIG_PSEL_Msk)\n\texpectedConfig := nrf.GPIOTE_CONFIG_MODE_Event<<nrf.GPIOTE_CONFIG_MODE_Pos | uint32(p)<<nrf.GPIOTE_CONFIG_PSEL_Pos\n\n\tfoundChannel := false\n\tfor i := range nrf.GPIOTE.CONFIG {\n\t\tconfig := nrf.GPIOTE.CONFIG[i].Get()\n\t\tif config == 0 || config&expectedConfigMask == expectedConfig {\n\t\t\t// Found an empty GPIOTE channel or one that was already configured\n\t\t\t// for this pin.\n\t\t\tif callback == nil {\n\t\t\t\t// Disable this channel.\n\t\t\t\tnrf.GPIOTE.INTENCLR.Set(uint32(1 << uint(i)))\n\t\t\t\tpinCallbacks[i] = nil\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\t// Enable this channel with the given callback.\n\t\t\tnrf.GPIOTE.INTENCLR.Set(uint32(1 << uint(i)))\n\t\t\tnrf.GPIOTE.CONFIG[i].Set(nrf.GPIOTE_CONFIG_MODE_Event<<nrf.GPIOTE_CONFIG_MODE_Pos |\n\t\t\t\tuint32(p)<<nrf.GPIOTE_CONFIG_PSEL_Pos |\n\t\t\t\tuint32(change)<<nrf.GPIOTE_CONFIG_POLARITY_Pos)\n\t\t\tpinCallbacks[i] = callback\n\t\t\tnrf.GPIOTE.INTENSET.Set(uint32(1 << uint(i)))\n\t\t\tfoundChannel = true\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif !foundChannel {\n\t\treturn ErrNoPinChangeChannel\n\t}\n\n\t// Set and enable the GPIOTE interrupt. It's not a problem if this happens\n\t// more than once.\n\tinterrupt.New(nrf.IRQ_GPIOTE, func(interrupt.Interrupt) {\n\t\tfor i := range nrf.GPIOTE.EVENTS_IN {\n\t\t\tif nrf.GPIOTE.EVENTS_IN[i].Get() != 0 {\n\t\t\t\tnrf.GPIOTE.EVENTS_IN[i].Set(0)\n\t\t\t\tpin := Pin((nrf.GPIOTE.CONFIG[i].Get() & nrf.GPIOTE_CONFIG_PSEL_Msk) >> nrf.GPIOTE_CONFIG_PSEL_Pos)\n\t\t\t\tpinCallbacks[i](pin)\n\t\t\t}\n\t\t}\n\t}).Enable()\n\n\t// Everything was configured correctly.\n\treturn nil\n}\n\n// UART on the NRF.\ntype UART struct {\n\tBuffer *RingBuffer\n}\n\n// UART\nvar (\n\t// UART0 is the hardware UART on the NRF SoC.\n\t_UART0 = UART{Buffer: NewRingBuffer()}\n\tUART0  = &_UART0\n)\n\n// Configure the UART.\nfunc (uart *UART) Configure(config UARTConfig) {\n\t// Default baud rate to 115200.\n\tif config.BaudRate == 0 {\n\t\tconfig.BaudRate = 115200\n\t}\n\n\tuart.SetBaudRate(config.BaudRate)\n\n\t// Set TX and RX pins\n\tif config.TX == 0 && config.RX == 0 {\n\t\t// Use default pins\n\t\tuart.setPins(UART_TX_PIN, UART_RX_PIN)\n\t} else {\n\t\tuart.setPins(config.TX, config.RX)\n\t}\n\n\tnrf.UART0.ENABLE.Set(nrf.UART_ENABLE_ENABLE_Enabled)\n\tnrf.UART0.TASKS_STARTTX.Set(1)\n\tnrf.UART0.TASKS_STARTRX.Set(1)\n\tnrf.UART0.INTENSET.Set(nrf.UART_INTENSET_RXDRDY_Msk)\n\n\t// Enable RX IRQ.\n\tintr := interrupt.New(nrf.IRQ_UART0, _UART0.handleInterrupt)\n\tintr.SetPriority(0xc0) // low priority\n\tintr.Enable()\n}\n\n// SetBaudRate sets the communication speed for the UART.\nfunc (uart *UART) SetBaudRate(br uint32) {\n\t// Magic: calculate 'baudrate' register from the input number.\n\t// Every value listed in the datasheet will be converted to the\n\t// correct register value, except for 192600. I suspect the value\n\t// listed in the nrf52 datasheet (0x0EBED000) is incorrectly rounded\n\t// and should be 0x0EBEE000, as the nrf51 datasheet lists the\n\t// nonrounded value 0x0EBEDFA4.\n\t// Some background:\n\t// https://devzone.nordicsemi.com/f/nordic-q-a/391/uart-baudrate-register-values/2046#2046\n\trate := uint32((uint64(br/400)*uint64(400*0xffffffff/16000000) + 0x800) & 0xffffff000)\n\n\tnrf.UART0.BAUDRATE.Set(rate)\n}\n\n// WriteByte writes a byte of data to the UART.\nfunc (uart *UART) writeByte(c byte) error {\n\tnrf.UART0.EVENTS_TXDRDY.Set(0)\n\tnrf.UART0.TXD.Set(uint32(c))\n\tfor nrf.UART0.EVENTS_TXDRDY.Get() == 0 {\n\t}\n\treturn nil\n}\n\nfunc (uart *UART) flush() {}\n\nfunc (uart *UART) handleInterrupt(interrupt.Interrupt) {\n\tif nrf.UART0.EVENTS_RXDRDY.Get() != 0 {\n\t\tuart.Receive(byte(nrf.UART0.RXD.Get()))\n\t\tnrf.UART0.EVENTS_RXDRDY.Set(0x0)\n\t}\n}\n\nconst i2cTimeout = 0xffff // this is around 29ms on a nrf52\n\n// I2CConfig is used to store config info for I2C.\ntype I2CConfig struct {\n\tFrequency uint32\n\tSCL       Pin\n\tSDA       Pin\n\tMode      I2CMode\n}\n\n// Configure is intended to setup the I2C interface.\nfunc (i2c *I2C) Configure(config I2CConfig) error {\n\n\ti2c.disable()\n\n\t// Default I2C bus speed is 100 kHz.\n\tif config.Frequency == 0 {\n\t\tconfig.Frequency = 100 * KHz\n\t}\n\t// Default I2C pins if not set.\n\tif config.SDA == 0 && config.SCL == 0 {\n\t\tconfig.SDA = SDA_PIN\n\t\tconfig.SCL = SCL_PIN\n\t}\n\n\t// do config\n\tsclPort, sclPin := config.SCL.getPortPin()\n\tsclPort.PIN_CNF[sclPin].Set((nrf.GPIO_PIN_CNF_DIR_Input << nrf.GPIO_PIN_CNF_DIR_Pos) |\n\t\t(nrf.GPIO_PIN_CNF_INPUT_Connect << nrf.GPIO_PIN_CNF_INPUT_Pos) |\n\t\t(nrf.GPIO_PIN_CNF_PULL_Pullup << nrf.GPIO_PIN_CNF_PULL_Pos) |\n\t\t(nrf.GPIO_PIN_CNF_DRIVE_S0D1 << nrf.GPIO_PIN_CNF_DRIVE_Pos) |\n\t\t(nrf.GPIO_PIN_CNF_SENSE_Disabled << nrf.GPIO_PIN_CNF_SENSE_Pos))\n\n\tsdaPort, sdaPin := config.SDA.getPortPin()\n\tsdaPort.PIN_CNF[sdaPin].Set((nrf.GPIO_PIN_CNF_DIR_Input << nrf.GPIO_PIN_CNF_DIR_Pos) |\n\t\t(nrf.GPIO_PIN_CNF_INPUT_Connect << nrf.GPIO_PIN_CNF_INPUT_Pos) |\n\t\t(nrf.GPIO_PIN_CNF_PULL_Pullup << nrf.GPIO_PIN_CNF_PULL_Pos) |\n\t\t(nrf.GPIO_PIN_CNF_DRIVE_S0D1 << nrf.GPIO_PIN_CNF_DRIVE_Pos) |\n\t\t(nrf.GPIO_PIN_CNF_SENSE_Disabled << nrf.GPIO_PIN_CNF_SENSE_Pos))\n\n\ti2c.setPins(config.SCL, config.SDA)\n\n\ti2c.mode = config.Mode\n\tif i2c.mode == I2CModeController {\n\t\ti2c.SetBaudRate(config.Frequency)\n\n\t\ti2c.enableAsController()\n\t} else {\n\t\ti2c.enableAsTarget()\n\t}\n\n\treturn nil\n}\n\n// SetBaudRate sets the I2C frequency. It has the side effect of also\n// enabling the I2C hardware if disabled beforehand.\n//\n//go:inline\nfunc (i2c *I2C) SetBaudRate(br uint32) error {\n\tswitch {\n\tcase br >= 400*KHz:\n\t\ti2c.Bus.SetFREQUENCY(nrf.TWI_FREQUENCY_FREQUENCY_K400)\n\tcase br >= 250*KHz:\n\t\ti2c.Bus.SetFREQUENCY(nrf.TWI_FREQUENCY_FREQUENCY_K250)\n\tdefault:\n\t\ti2c.Bus.SetFREQUENCY(nrf.TWI_FREQUENCY_FREQUENCY_K100)\n\t}\n\n\treturn nil\n}\n\n// signalStop sends a stop signal to the I2C peripheral and waits for confirmation.\nfunc (i2c *I2C) signalStop() error {\n\ttries := 0\n\ti2c.Bus.TASKS_STOP.Set(1)\n\tfor i2c.Bus.EVENTS_STOPPED.Get() == 0 {\n\t\ttries++\n\t\tif tries >= i2cTimeout {\n\t\t\treturn errI2CSignalStopTimeout\n\t\t}\n\t}\n\ti2c.Bus.EVENTS_STOPPED.Set(0)\n\treturn nil\n}\n\nvar rngStarted = false\n\n// getRNG returns 32 bits of non-deterministic random data based on internal thermal noise.\n// According to Nordic's documentation, the random output is suitable for cryptographic purposes.\nfunc getRNG() (ret uint32, err error) {\n\t// There's no apparent way to check the status of the RNG peripheral's task, so simply start it\n\t// to avoid deadlocking while waiting for output.\n\tif !rngStarted {\n\t\tnrf.RNG.TASKS_START.Set(1)\n\t\tnrf.RNG.SetCONFIG_DERCEN(nrf.RNG_CONFIG_DERCEN_Enabled)\n\t\trngStarted = true\n\t}\n\n\t// The RNG returns one byte at a time, so stack up four bytes into a single uint32 for return.\n\tfor i := 0; i < 4; i++ {\n\t\t// Wait for data to be ready.\n\t\tfor nrf.RNG.EVENTS_VALRDY.Get() == 0 {\n\t\t}\n\t\t// Append random byte to output.\n\t\tret = (ret << 8) ^ nrf.RNG.GetVALUE()\n\t\t// Unset the EVENTS_VALRDY register to avoid reading the same random output twice.\n\t\tnrf.RNG.EVENTS_VALRDY.Set(0)\n\t}\n\n\treturn ret, nil\n}\n\n// ReadTemperature reads the silicon die temperature of the chip. The return\n// value is in milli-celsius.\nfunc ReadTemperature() int32 {\n\tnrf.TEMP.TASKS_START.Set(1)\n\tfor nrf.TEMP.EVENTS_DATARDY.Get() == 0 {\n\t}\n\ttemp := int32(nrf.TEMP.TEMP.Get()) * 250 // the returned value is in units of 0.25°C\n\tnrf.TEMP.EVENTS_DATARDY.Set(0)\n\treturn temp\n}\n\nconst memoryStart = 0x0\n\n// compile-time check for ensuring we fulfill BlockDevice interface\nvar _ BlockDevice = flashBlockDevice{}\n\nvar Flash flashBlockDevice\n\ntype flashBlockDevice struct {\n}\n\n// ReadAt reads the given number of bytes from the block device.\nfunc (f flashBlockDevice) ReadAt(p []byte, off int64) (n int, err error) {\n\tif FlashDataStart()+uintptr(off)+uintptr(len(p)) > FlashDataEnd() {\n\t\treturn 0, errFlashCannotReadPastEOF\n\t}\n\n\tdata := unsafe.Slice((*byte)(unsafe.Pointer(FlashDataStart()+uintptr(off))), len(p))\n\tcopy(p, data)\n\n\treturn len(p), nil\n}\n\n// WriteAt writes the given number of bytes to the block device.\n// Only double-word (64 bits) length data can be programmed. See rm0461 page 78.\n// If the length of p is not long enough it will be padded with 0xFF bytes.\n// This method assumes that the destination is already erased.\nfunc (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) {\n\tif len(p) == 0 {\n\t\treturn 0, nil // nothing to do (and it would fail in sd_flash_write)\n\t}\n\n\tif FlashDataStart()+uintptr(off)+uintptr(len(p)) > FlashDataEnd() {\n\t\treturn 0, errFlashCannotWritePastEOF\n\t}\n\n\taddress := FlashDataStart() + uintptr(off)\n\tpadded := flashPad(p, int(f.WriteBlockSize()))\n\n\t// When the SoftDevice is enabled, access to the flash is restricted and\n\t// must go through the SoftDevice API.\n\tif isSoftDeviceEnabled() {\n\t\t// Call sd_flash_write, which is SVC_SOC_BASE + 9 in all the\n\t\t// SoftDevices I've checked.\n\t\t// Documentation:\n\t\t// https://docs.nordicsemi.com/bundle/s140_v6.0.0_api/page/group_n_r_f_s_o_c_f_u_n_c_t_i_o_n_s.html\n\t\tnumberOfWords := len(padded) / 4 // flash access goes in 32-bit words\n\t\tresult := arm.SVCall3(0x20+9, address, &padded[0], uint32(numberOfWords))\n\t\tif result != 0 {\n\t\t\t// Could not queue flash operation? Not sure when this can\n\t\t\t// happen.\n\t\t\treturn 0, flashError\n\t\t}\n\n\t\t// Wait until the SoftDevice is finished.\n\t\tflashStatus = flashStatusBusy\n\t\tfor flashStatus == flashStatusBusy {\n\t\t\thandleSoftDeviceEvents()\n\t\t}\n\n\t\t// Check whether the operation was successful.\n\t\tif flashStatus != flashStatusOk {\n\t\t\tflashStatus = flashStatusOk\n\t\t\treturn 0, flashError\n\t\t}\n\t\treturn len(p), nil\n\t}\n\n\twaitWhileFlashBusy()\n\n\tnrf.NVMC.SetCONFIG_WEN(nrf.NVMC_CONFIG_WEN_Wen)\n\tdefer nrf.NVMC.SetCONFIG_WEN(nrf.NVMC_CONFIG_WEN_Ren)\n\n\tfor j := 0; j < len(padded); j += int(f.WriteBlockSize()) {\n\t\t// write word\n\t\t*(*uint32)(unsafe.Pointer(address)) = binary.LittleEndian.Uint32(padded[j : j+int(f.WriteBlockSize())])\n\t\taddress += uintptr(f.WriteBlockSize())\n\t\twaitWhileFlashBusy()\n\t}\n\n\treturn len(padded), nil\n}\n\n// Size returns the number of bytes in this block device.\nfunc (f flashBlockDevice) Size() int64 {\n\treturn int64(FlashDataEnd() - FlashDataStart())\n}\n\nconst writeBlockSize = 4\n\n// WriteBlockSize returns the block size in which data can be written to\n// memory. It can be used by a client to optimize writes, non-aligned writes\n// should always work correctly.\nfunc (f flashBlockDevice) WriteBlockSize() int64 {\n\treturn writeBlockSize\n}\n\n// EraseBlockSize returns the smallest erasable area on this particular chip\n// in bytes. This is used for the block size in EraseBlocks.\n// It must be a power of two, and may be as small as 1. A typical size is 4096.\nfunc (f flashBlockDevice) EraseBlockSize() int64 {\n\treturn eraseBlockSize()\n}\n\n// EraseBlocks erases the given number of blocks. An implementation may\n// transparently coalesce ranges of blocks into larger bundles if the chip\n// supports this. The start and len parameters are in block numbers, use\n// EraseBlockSize to map addresses to blocks.\nfunc (f flashBlockDevice) EraseBlocks(start, len int64) error {\n\t// When the SoftDevice is enabled, access to the flash is restricted and\n\t// must go through the SoftDevice API.\n\tif isSoftDeviceEnabled() {\n\t\tfor i := range uint32(len) {\n\t\t\tflashPage := uint32(FlashDataStart())/eraseBlockSizeValue + uint32(start) + i\n\n\t\t\t// Call sd_flash_page_erase, which is SVC_SOC_BASE + 8 in all the\n\t\t\t// SoftDevices I've checked.\n\t\t\t// Documentation:\n\t\t\t// https://docs.nordicsemi.com/bundle/s140_v6.0.0_api/page/group_n_r_f_s_o_c_f_u_n_c_t_i_o_n_s.html#ga9c93dd94a138ad8b5ed3693ea38ffb3e\n\t\t\tresult := arm.SVCall1(0x20+8, flashPage)\n\t\t\tif result != 0 {\n\t\t\t\t// Could not queue flash operation? Not sure when this can\n\t\t\t\t// happen.\n\t\t\t\treturn flashError\n\t\t\t}\n\n\t\t\t// Wait until the SoftDevice is finished.\n\t\t\tflashStatus = flashStatusBusy\n\t\t\tfor flashStatus == flashStatusBusy {\n\t\t\t\thandleSoftDeviceEvents()\n\t\t\t}\n\n\t\t\t// Check whether the operation was successful.\n\t\t\tif flashStatus != flashStatusOk {\n\t\t\t\tflashStatus = flashStatusOk\n\t\t\t\treturn flashError\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\n\t// SoftDevice is not used or enabled. Use NVIC directly.\n\n\taddress := FlashDataStart() + uintptr(start*f.EraseBlockSize())\n\twaitWhileFlashBusy()\n\n\tnrf.NVMC.SetCONFIG_WEN(nrf.NVMC_CONFIG_WEN_Een)\n\tdefer nrf.NVMC.SetCONFIG_WEN(nrf.NVMC_CONFIG_WEN_Ren)\n\n\tfor i := start; i < start+len; i++ {\n\t\tnrf.NVMC.ERASEPAGE.Set(uint32(address))\n\t\twaitWhileFlashBusy()\n\t\taddress += uintptr(f.EraseBlockSize())\n\t}\n\n\treturn nil\n}\n\nfunc waitWhileFlashBusy() {\n\tfor nrf.NVMC.GetREADY() != nrf.NVMC_READY_READY_Ready {\n\t}\n}\n\nvar flashError = errors.New(\"machine: flash operation failed\")\n\nconst (\n\tflashStatusOk = iota\n\tflashStatusError\n\tflashStatusBusy\n)\n\nvar flashStatus uint8 = flashStatusOk\n\nvar sdEvent uint32\n\n// Process all queued SoftDevice events. May only be called when the SoftDevice is enabled.\n//\n// Normally these are handled in the same interrupt where Bluetooth events are\n// handled. But in TinyGo, that's complicated. One option would be to put it in\n// the tinygo.org/x/bluetooth package, but that would cause a circular\n// dependency between the machine and the bluetooth package. Another would be to\n// put it here, but let the bluetooth package call handleSoftDeviceEvents, but\n// that relies on updating the bluetooth package at the same time. As a\n// compromise, these events are handled directly where they are expected (here\n// in the machine package). This works in practice since there are only very few\n// of such events (at the moment, only flash-related ones which is in the\n// machine package anyway).\nfunc handleSoftDeviceEvents() {\n\tfor {\n\t\tvar result uintptr\n\t\tif nrf.Device == \"nrf52\" || nrf.Device == \"nrf52840\" || nrf.Device == \"nrf52833\" {\n\t\t\t// sd_evt_get: SOC_SVC_BASE_NOT_AVAILABLE + 31\n\t\t\tresult = arm.SVCall1(0x2C+31, &sdEvent)\n\t\t} else {\n\t\t\treturn // TODO: nrf51 etc\n\t\t}\n\t\tif result != 0 {\n\t\t\t// Some error occured. The only possible error is\n\t\t\t// NRF_ERROR_NOT_FOUND, which means there are no more events.\n\t\t\treturn\n\t\t}\n\n\t\t// The following events are the same numbers in all SoftDevices I've checked.\n\t\tswitch sdEvent {\n\t\tcase 2: // NRF_EVT_FLASH_OPERATION_SUCCESS\n\t\t\tflashStatus = flashStatusOk\n\t\tcase 3: // NRF_EVT_FLASH_OPERATION_ERROR\n\t\t\tflashStatus = flashStatusError\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_nrf51.go",
    "content": "//go:build nrf51\n\npackage machine\n\nimport (\n\t\"device/nrf\"\n)\n\nconst eraseBlockSizeValue = 1024\n\nfunc eraseBlockSize() int64 {\n\treturn eraseBlockSizeValue\n}\n\n// Get peripheral and pin number for this GPIO pin.\nfunc (p Pin) getPortPin() (*nrf.GPIO_Type, uint32) {\n\treturn nrf.GPIO, uint32(p)\n}\n\nfunc (uart *UART) setPins(tx, rx Pin) {\n\tnrf.UART0.PSELTXD.Set(uint32(tx))\n\tnrf.UART0.PSELRXD.Set(uint32(rx))\n}\n\nfunc (i2c *I2C) setPins(scl, sda Pin) {\n\ti2c.Bus.PSELSCL.Set(uint32(scl))\n\ti2c.Bus.PSELSDA.Set(uint32(sda))\n}\n\n// SPI on the NRF.\ntype SPI struct {\n\tBus *nrf.SPI_Type\n}\n\n// There are 2 SPI interfaces on the NRF51.\nvar (\n\tSPI0 = &SPI{Bus: nrf.SPI0}\n\tSPI1 = &SPI{Bus: nrf.SPI1}\n)\n\n// SPIConfig is used to store config info for SPI.\ntype SPIConfig struct {\n\tFrequency uint32\n\tSCK       Pin\n\tSDO       Pin\n\tSDI       Pin\n\tLSBFirst  bool\n\tMode      uint8\n}\n\n// Configure is intended to setup the SPI interface.\nfunc (spi *SPI) Configure(config SPIConfig) error {\n\t// Disable bus to configure it\n\tspi.Bus.ENABLE.Set(nrf.SPI_ENABLE_ENABLE_Disabled)\n\n\t// set frequency\n\tvar freq uint32\n\n\tif config.Frequency == 0 {\n\t\tconfig.Frequency = 4000000 // 4MHz\n\t}\n\n\tswitch {\n\tcase config.Frequency >= 8000000:\n\t\tfreq = nrf.SPI_FREQUENCY_FREQUENCY_M8\n\tcase config.Frequency >= 4000000:\n\t\tfreq = nrf.SPI_FREQUENCY_FREQUENCY_M4\n\tcase config.Frequency >= 2000000:\n\t\tfreq = nrf.SPI_FREQUENCY_FREQUENCY_M2\n\tcase config.Frequency >= 1000000:\n\t\tfreq = nrf.SPI_FREQUENCY_FREQUENCY_M1\n\tcase config.Frequency >= 500000:\n\t\tfreq = nrf.SPI_FREQUENCY_FREQUENCY_K500\n\tcase config.Frequency >= 250000:\n\t\tfreq = nrf.SPI_FREQUENCY_FREQUENCY_K250\n\tdefault: // below 250kHz, default to the lowest speed available\n\t\tfreq = nrf.SPI_FREQUENCY_FREQUENCY_K125\n\t}\n\tspi.Bus.FREQUENCY.Set(freq)\n\n\tvar conf uint32\n\n\t// set bit transfer order\n\tif config.LSBFirst {\n\t\tconf = (nrf.SPI_CONFIG_ORDER_LsbFirst << nrf.SPI_CONFIG_ORDER_Pos)\n\t}\n\n\t// set mode\n\tswitch config.Mode {\n\tcase 0:\n\t\tconf &^= (nrf.SPI_CONFIG_CPOL_ActiveHigh << nrf.SPI_CONFIG_CPOL_Pos)\n\t\tconf &^= (nrf.SPI_CONFIG_CPHA_Leading << nrf.SPI_CONFIG_CPHA_Pos)\n\tcase 1:\n\t\tconf &^= (nrf.SPI_CONFIG_CPOL_ActiveHigh << nrf.SPI_CONFIG_CPOL_Pos)\n\t\tconf |= (nrf.SPI_CONFIG_CPHA_Trailing << nrf.SPI_CONFIG_CPHA_Pos)\n\tcase 2:\n\t\tconf |= (nrf.SPI_CONFIG_CPOL_ActiveLow << nrf.SPI_CONFIG_CPOL_Pos)\n\t\tconf &^= (nrf.SPI_CONFIG_CPHA_Leading << nrf.SPI_CONFIG_CPHA_Pos)\n\tcase 3:\n\t\tconf |= (nrf.SPI_CONFIG_CPOL_ActiveLow << nrf.SPI_CONFIG_CPOL_Pos)\n\t\tconf |= (nrf.SPI_CONFIG_CPHA_Trailing << nrf.SPI_CONFIG_CPHA_Pos)\n\tdefault: // to mode\n\t\tconf &^= (nrf.SPI_CONFIG_CPOL_ActiveHigh << nrf.SPI_CONFIG_CPOL_Pos)\n\t\tconf &^= (nrf.SPI_CONFIG_CPHA_Leading << nrf.SPI_CONFIG_CPHA_Pos)\n\t}\n\tspi.Bus.CONFIG.Set(conf)\n\n\t// set pins\n\tif config.SCK == 0 && config.SDO == 0 && config.SDI == 0 {\n\t\tconfig.SCK = SPI0_SCK_PIN\n\t\tconfig.SDO = SPI0_SDO_PIN\n\t\tconfig.SDI = SPI0_SDI_PIN\n\t}\n\tspi.Bus.PSELSCK.Set(uint32(config.SCK))\n\tspi.Bus.PSELMOSI.Set(uint32(config.SDO))\n\tspi.Bus.PSELMISO.Set(uint32(config.SDI))\n\n\t// Re-enable bus now that it is configured.\n\tspi.Bus.ENABLE.Set(nrf.SPI_ENABLE_ENABLE_Enabled)\n\n\treturn nil\n}\n\n// Transfer writes/reads a single byte using the SPI interface.\nfunc (spi *SPI) Transfer(w byte) (byte, error) {\n\tspi.Bus.TXD.Set(uint32(w))\n\tfor spi.Bus.EVENTS_READY.Get() == 0 {\n\t}\n\tr := spi.Bus.RXD.Get()\n\tspi.Bus.EVENTS_READY.Set(0)\n\n\t// TODO: handle SPI errors\n\treturn byte(r), nil\n}\n\n// Tx handles read/write operation for SPI interface. Since SPI is a synchronous write/read\n// interface, there must always be the same number of bytes written as bytes read.\n// The Tx method knows about this, and offers a few different ways of calling it.\n//\n// This form sends the bytes in tx buffer, putting the resulting bytes read into the rx buffer.\n// Note that the tx and rx buffers must be the same size:\n//\n//\tspi.Tx(tx, rx)\n//\n// This form sends the tx buffer, ignoring the result. Useful for sending \"commands\" that return zeros\n// until all the bytes in the command packet have been received:\n//\n//\tspi.Tx(tx, nil)\n//\n// This form sends zeros, putting the result into the rx buffer. Good for reading a \"result packet\":\n//\n//\tspi.Tx(nil, rx)\nfunc (spi *SPI) Tx(w, r []byte) error {\n\tvar err error\n\n\tswitch {\n\tcase len(w) == 0:\n\t\t// read only, so write zero and read a result.\n\t\tfor i := range r {\n\t\t\tr[i], err = spi.Transfer(0)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\tcase len(r) == 0:\n\t\t// write only\n\t\tspi.Bus.TXD.Set(uint32(w[0]))\n\t\tw = w[1:]\n\t\tfor _, b := range w {\n\t\t\tspi.Bus.TXD.Set(uint32(b))\n\t\t\tfor spi.Bus.EVENTS_READY.Get() == 0 {\n\t\t\t}\n\t\t\tspi.Bus.EVENTS_READY.Set(0)\n\t\t\t_ = spi.Bus.RXD.Get()\n\t\t}\n\t\tfor spi.Bus.EVENTS_READY.Get() == 0 {\n\t\t}\n\t\tspi.Bus.EVENTS_READY.Set(0)\n\t\t_ = spi.Bus.RXD.Get()\n\n\tdefault:\n\t\t// write/read\n\t\tif len(w) != len(r) {\n\t\t\treturn ErrTxInvalidSliceSize\n\t\t}\n\n\t\tfor i, b := range w {\n\t\t\tr[i], err = spi.Transfer(b)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// InitADC initializes the registers needed for ADC.\nfunc InitADC() {\n\treturn // no specific setup on nrf51 machine.\n}\n\n// Configure configures an ADC pin to be able to read analog data.\nfunc (a ADC) Configure(ADCConfig) {\n\treturn // no pin specific setup on nrf51 machine.\n}\n\n// Get returns the current value of a ADC pin in the range 0..0xffff.\nfunc (a ADC) Get() uint16 {\n\tvar value uint32\n\n\tadcPin := a.getADCPin()\n\n\t// Enable ADC.\n\tnrf.ADC.SetENABLE(nrf.ADC_ENABLE_ENABLE_Enabled)\n\n\t// Set pin to read.\n\tnrf.ADC.SetCONFIG_PSEL(adcPin)\n\n\t// config ADC\n\tnrf.ADC.SetCONFIG_RES(nrf.ADC_CONFIG_RES_10bit)\n\tnrf.ADC.SetCONFIG_INPSEL(nrf.ADC_CONFIG_INPSEL_AnalogInputOneThirdPrescaling)\n\tnrf.ADC.SetCONFIG_REFSEL(nrf.ADC_CONFIG_REFSEL_SupplyOneThirdPrescaling)\n\n\t// Start tasks.\n\tnrf.ADC.TASKS_START.Set(1)\n\n\t// Wait until the sample task is done.\n\tfor nrf.ADC.EVENTS_END.Get() == 0 {\n\t}\n\tnrf.ADC.EVENTS_END.Set(0x00)\n\n\tvalue = nrf.ADC.GetRESULT()\n\n\t// Stop the ADC\n\tnrf.ADC.TASKS_STOP.Set(1)\n\n\t// Disable ADC.\n\tnrf.ADC.SetENABLE(nrf.ADC_ENABLE_ENABLE_Disabled)\n\n\tif value < 0 {\n\t\tvalue = 0\n\t}\n\n\t// Return 16-bit result from 10-bit value.\n\treturn uint16(value << 6)\n}\n\nfunc (a ADC) getADCPin() uint32 {\n\tswitch a.Pin {\n\tcase 1:\n\t\treturn nrf.ADC_CONFIG_PSEL_AnalogInput2\n\n\tcase 2:\n\t\treturn nrf.ADC_CONFIG_PSEL_AnalogInput3\n\n\tcase 3:\n\t\treturn nrf.ADC_CONFIG_PSEL_AnalogInput4\n\n\tcase 4:\n\t\treturn nrf.ADC_CONFIG_PSEL_AnalogInput5\n\n\tcase 5:\n\t\treturn nrf.ADC_CONFIG_PSEL_AnalogInput6\n\n\tcase 6:\n\t\treturn nrf.ADC_CONFIG_PSEL_AnalogInput7\n\n\tcase 26:\n\t\treturn nrf.ADC_CONFIG_PSEL_AnalogInput0\n\n\tcase 27:\n\t\treturn nrf.ADC_CONFIG_PSEL_AnalogInput1\n\n\tdefault:\n\t\treturn 0\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_nrf51_simulator.go",
    "content": "//go:build !baremetal && (microbit || pca10031 || hw_651)\n\npackage machine\n\nvar I2C0 = &I2C{Bus: 0}\nvar I2C1 = &I2C{Bus: 1}\n"
  },
  {
    "path": "src/machine/machine_nrf52.go",
    "content": "//go:build nrf52\n\npackage machine\n\nimport (\n\t\"device/nrf\"\n)\n\n// Hardware pins\nconst (\n\tP0_00 Pin = 0\n\tP0_01 Pin = 1\n\tP0_02 Pin = 2\n\tP0_03 Pin = 3\n\tP0_04 Pin = 4\n\tP0_05 Pin = 5\n\tP0_06 Pin = 6\n\tP0_07 Pin = 7\n\tP0_08 Pin = 8\n\tP0_09 Pin = 9\n\tP0_10 Pin = 10\n\tP0_11 Pin = 11\n\tP0_12 Pin = 12\n\tP0_13 Pin = 13\n\tP0_14 Pin = 14\n\tP0_15 Pin = 15\n\tP0_16 Pin = 16\n\tP0_17 Pin = 17\n\tP0_18 Pin = 18\n\tP0_19 Pin = 19\n\tP0_20 Pin = 20\n\tP0_21 Pin = 21\n\tP0_22 Pin = 22\n\tP0_23 Pin = 23\n\tP0_24 Pin = 24\n\tP0_25 Pin = 25\n\tP0_26 Pin = 26\n\tP0_27 Pin = 27\n\tP0_28 Pin = 28\n\tP0_29 Pin = 29\n\tP0_30 Pin = 30\n\tP0_31 Pin = 31\n)\n\n// Get peripheral and pin number for this GPIO pin.\nfunc (p Pin) getPortPin() (*nrf.GPIO_Type, uint32) {\n\treturn nrf.P0, uint32(p)\n}\n\nfunc (uart *UART) setPins(tx, rx Pin) {\n\tnrf.UART0.PSELTXD.Set(uint32(tx))\n\tnrf.UART0.PSELRXD.Set(uint32(rx))\n}\n\nfunc (i2c *I2C) setPins(scl, sda Pin) {\n\ti2c.Bus.PSELSCL.Set(uint32(scl))\n\ti2c.Bus.PSELSDA.Set(uint32(sda))\n}\n\n// PWM\nvar (\n\tPWM0 = &PWM{PWM: nrf.PWM0}\n\tPWM1 = &PWM{PWM: nrf.PWM1}\n\tPWM2 = &PWM{PWM: nrf.PWM2}\n)\n\nconst eraseBlockSizeValue = 4096\n\nfunc eraseBlockSize() int64 {\n\treturn eraseBlockSizeValue\n}\n\nconst spiMaxBufferSize = 255 // from the datasheet: TXD.MAXCNT and RXD.MAXCNT\n"
  },
  {
    "path": "src/machine/machine_nrf52833.go",
    "content": "//go:build nrf52833\n\npackage machine\n\nimport (\n\t\"device/nrf\"\n)\n\n// Hardware pins\nconst (\n\tP0_00 Pin = 0\n\tP0_01 Pin = 1\n\tP0_02 Pin = 2\n\tP0_03 Pin = 3\n\tP0_04 Pin = 4\n\tP0_05 Pin = 5\n\tP0_06 Pin = 6\n\tP0_07 Pin = 7\n\tP0_08 Pin = 8\n\tP0_09 Pin = 9\n\tP0_10 Pin = 10\n\tP0_11 Pin = 11\n\tP0_12 Pin = 12\n\tP0_13 Pin = 13\n\tP0_14 Pin = 14\n\tP0_15 Pin = 15\n\tP0_16 Pin = 16\n\tP0_17 Pin = 17\n\tP0_18 Pin = 18\n\tP0_19 Pin = 19\n\tP0_20 Pin = 20\n\tP0_21 Pin = 21\n\tP0_22 Pin = 22\n\tP0_23 Pin = 23\n\tP0_24 Pin = 24\n\tP0_25 Pin = 25\n\tP0_26 Pin = 26\n\tP0_27 Pin = 27\n\tP0_28 Pin = 28\n\tP0_29 Pin = 29\n\tP0_30 Pin = 30\n\tP0_31 Pin = 31\n\tP1_00 Pin = 32\n\tP1_01 Pin = 33\n\tP1_02 Pin = 34\n\tP1_03 Pin = 35\n\tP1_04 Pin = 36\n\tP1_05 Pin = 37\n\tP1_06 Pin = 38\n\tP1_07 Pin = 39\n\tP1_08 Pin = 40\n\tP1_09 Pin = 41\n\tP1_10 Pin = 42\n\tP1_11 Pin = 43\n\tP1_12 Pin = 44\n\tP1_13 Pin = 45\n\tP1_14 Pin = 46\n\tP1_15 Pin = 47\n)\n\n// Get peripheral and pin number for this GPIO pin.\nfunc (p Pin) getPortPin() (*nrf.GPIO_Type, uint32) {\n\tif p >= 32 {\n\t\treturn nrf.P1, uint32(p - 32)\n\t} else {\n\t\treturn nrf.P0, uint32(p)\n\t}\n}\n\nfunc (uart *UART) setPins(tx, rx Pin) {\n\tnrf.UART0.PSEL.TXD.Set(uint32(tx))\n\tnrf.UART0.PSEL.RXD.Set(uint32(rx))\n}\n\nfunc (i2c *I2C) setPins(scl, sda Pin) {\n\ti2c.Bus.PSEL.SCL.Set(uint32(scl))\n\ti2c.Bus.PSEL.SDA.Set(uint32(sda))\n}\n\n// PWM\nvar (\n\tPWM0 = &PWM{PWM: nrf.PWM0}\n\tPWM1 = &PWM{PWM: nrf.PWM1}\n\tPWM2 = &PWM{PWM: nrf.PWM2}\n\tPWM3 = &PWM{PWM: nrf.PWM3}\n)\n\nconst eraseBlockSizeValue = 4096\n\nfunc eraseBlockSize() int64 {\n\treturn eraseBlockSizeValue\n}\n\nconst spiMaxBufferSize = 0xffff // from the datasheet: TXD.MAXCNT and RXD.MAXCNT\n"
  },
  {
    "path": "src/machine/machine_nrf52840.go",
    "content": "//go:build nrf52840\n\npackage machine\n\nimport (\n\t\"device/nrf\"\n\t\"errors\"\n\t\"unsafe\"\n)\n\n// Get peripheral and pin number for this GPIO pin.\nfunc (p Pin) getPortPin() (*nrf.GPIO_Type, uint32) {\n\tif p >= 32 {\n\t\treturn nrf.P1, uint32(p - 32)\n\t} else {\n\t\treturn nrf.P0, uint32(p)\n\t}\n}\n\nfunc (uart *UART) setPins(tx, rx Pin) {\n\tnrf.UART0.PSEL.TXD.Set(uint32(tx))\n\tnrf.UART0.PSEL.RXD.Set(uint32(rx))\n}\n\nfunc (i2c *I2C) setPins(scl, sda Pin) {\n\ti2c.Bus.PSEL.SCL.Set(uint32(scl))\n\ti2c.Bus.PSEL.SDA.Set(uint32(sda))\n}\n\n// PWM\nvar (\n\tPWM0 = &PWM{PWM: nrf.PWM0}\n\tPWM1 = &PWM{PWM: nrf.PWM1}\n\tPWM2 = &PWM{PWM: nrf.PWM2}\n\tPWM3 = &PWM{PWM: nrf.PWM3}\n)\n\n// PDM represents a PDM device\ntype PDM struct {\n\tdevice        *nrf.PDM_Type\n\tdefaultBuffer int16\n}\n\n// Configure is intended to set up the PDM interface prior to use.\nfunc (pdm *PDM) Configure(config PDMConfig) error {\n\tif config.DIN == 0 {\n\t\treturn errors.New(\"No DIN pin provided in configuration\")\n\t}\n\n\tif config.CLK == 0 {\n\t\treturn errors.New(\"No CLK pin provided in configuration\")\n\t}\n\n\tconfig.DIN.Configure(PinConfig{Mode: PinInput})\n\tconfig.CLK.Configure(PinConfig{Mode: PinOutput})\n\tpdm.device = nrf.PDM\n\tpdm.device.PSEL.DIN.Set(uint32(config.DIN))\n\tpdm.device.PSEL.CLK.Set(uint32(config.CLK))\n\tpdm.device.PDMCLKCTRL.Set(nrf.PDM_PDMCLKCTRL_FREQ_Default)\n\tpdm.device.RATIO.Set(nrf.PDM_RATIO_RATIO_Ratio64)\n\tpdm.device.GAINL.Set(nrf.PDM_GAINL_GAINL_DefaultGain)\n\tpdm.device.GAINR.Set(nrf.PDM_GAINR_GAINR_DefaultGain)\n\tpdm.device.ENABLE.Set(nrf.PDM_ENABLE_ENABLE_Enabled)\n\n\tif config.Stereo {\n\t\tpdm.device.MODE.Set(nrf.PDM_MODE_OPERATION_Stereo | nrf.PDM_MODE_EDGE_LeftRising)\n\t} else {\n\t\tpdm.device.MODE.Set(nrf.PDM_MODE_OPERATION_Mono | nrf.PDM_MODE_EDGE_LeftRising)\n\t}\n\n\tpdm.device.SAMPLE.SetPTR(uint32(uintptr(unsafe.Pointer(&pdm.defaultBuffer))))\n\tpdm.device.SAMPLE.SetMAXCNT_BUFFSIZE(1)\n\tpdm.device.SetTASKS_START(1)\n\treturn nil\n}\n\n// Read stores a set of samples in the given target buffer.\nfunc (pdm *PDM) Read(buf []int16) (uint32, error) {\n\tpdm.device.SAMPLE.SetPTR(uint32(uintptr(unsafe.Pointer(&buf[0]))))\n\tpdm.device.SAMPLE.MAXCNT.Set(uint32(len(buf)))\n\tpdm.device.EVENTS_STARTED.Set(0)\n\n\t// Step 1: wait for new sampling to start for target buffer\n\tfor !pdm.device.EVENTS_STARTED.HasBits(nrf.PDM_EVENTS_STARTED_EVENTS_STARTED) {\n\t}\n\tpdm.device.EVENTS_END.Set(0)\n\n\t// Step 2: swap out buffers for next recording so we don't continue to\n\t// write to the target buffer\n\tpdm.device.EVENTS_STARTED.Set(0)\n\tpdm.device.SAMPLE.SetPTR(uint32(uintptr(unsafe.Pointer(&pdm.defaultBuffer))))\n\tpdm.device.SAMPLE.MAXCNT.Set(1)\n\n\t// Step 3: wait for original event to end\n\tfor pdm.device.EVENTS_END.HasBits(nrf.PDM_EVENTS_STOPPED_EVENTS_STOPPED) {\n\t}\n\n\t// Step 4: wait for default buffer to start recording before proceeding\n\t// otherwise we see the contents of target buffer change later\n\tfor !pdm.device.EVENTS_STARTED.HasBits(nrf.PDM_EVENTS_STARTED_EVENTS_STARTED) {\n\t}\n\n\treturn uint32(len(buf)), nil\n}\n\nconst eraseBlockSizeValue = 4096\n\nfunc eraseBlockSize() int64 {\n\treturn eraseBlockSizeValue\n}\n\nconst spiMaxBufferSize = 0xffff // from the datasheet: TXD.MAXCNT and RXD.MAXCNT\n\n// ADC instance for the VDDH input pin. This pin is typically connected to USB\n// input voltage (~5V) or directly to a battery.\nvar ADC_VDDH = ADC{adcVDDHPin}\n"
  },
  {
    "path": "src/machine/machine_nrf52840_enter_bootloader.go",
    "content": "//go:build nrf52840\n\npackage machine\n\nimport (\n\t\"device/arm\"\n\t\"device/nrf\"\n)\n\nconst (\n\tdfuMagicSerialOnlyReset = 0x4e\n\tdfuMagicUF2Reset        = 0x57\n\tdfuMagicOTAReset        = 0xA8\n)\n\n// EnterSerialBootloader resets the chip into the serial bootloader. After\n// reset, it can be flashed using serial/nrfutil.\nfunc EnterSerialBootloader() {\n\tarm.DisableInterrupts()\n\tnrf.POWER.GPREGRET.Set(dfuMagicSerialOnlyReset)\n\tarm.SystemReset()\n}\n\n// EnterUF2Bootloader resets the chip into the UF2 bootloader. After reset, it\n// can be flashed via nrfutil or by copying a UF2 file to the mass storage device\nfunc EnterUF2Bootloader() {\n\tarm.DisableInterrupts()\n\tnrf.POWER.GPREGRET.Set(dfuMagicUF2Reset)\n\tarm.SystemReset()\n}\n\n// EnterOTABootloader resets the chip into the bootloader so that it can be\n// flashed via an OTA update\nfunc EnterOTABootloader() {\n\tarm.DisableInterrupts()\n\tnrf.POWER.GPREGRET.Set(dfuMagicOTAReset)\n\tarm.SystemReset()\n}\n"
  },
  {
    "path": "src/machine/machine_nrf52840_lfxtal_false.go",
    "content": "//go:build nrf52840 && nrf52840_lfxtal_false\n\npackage machine\n\nconst HasLowFrequencyCrystal = false\n"
  },
  {
    "path": "src/machine/machine_nrf52840_lfxtal_true.go",
    "content": "//go:build nrf52840 && ((nrf52840_generic && !nrf52840_lfxtal_false) || nrf52840_lfxtal_true)\n\npackage machine\n\nconst HasLowFrequencyCrystal = true\n"
  },
  {
    "path": "src/machine/machine_nrf52840_simulator.go",
    "content": "//go:build !baremetal && (bluemicro840 || circuitplay_bluefruit || clue_alpha || feather_nrf52840_sense || feather_nrf52840 || itsybitsy_nrf52840 || mdbt50qrx || nano_33_ble || nicenano || nrf52840_mdk || particle_3rd_gen || pca10056 || pca10059 || rak4631 || reelboard || xiao_ble)\n\n// Simulator support for nrf52840 based boards.\n\npackage machine\n\n// Channel values below are nil, so that they get filled in on the first use.\n// This is the same as what happens on baremetal.\n\nvar PWM0 = &timerType{\n\tinstance:   0,\n\tfrequency:  16e6,\n\tbits:       15,\n\tprescalers: []int{1, 2, 4, 8, 16, 32, 64, 128},\n\tchannelPins: [][]Pin{\n\t\tnil, // channel 0\n\t\tnil, // channel 1\n\t\tnil, // channel 2\n\t\tnil, // channel 3\n\t},\n}\n\nvar PWM1 = &timerType{\n\tinstance:   1,\n\tfrequency:  16e6,\n\tbits:       15,\n\tprescalers: []int{1, 2, 4, 8, 16, 32, 64, 128},\n\tchannelPins: [][]Pin{\n\t\tnil, // channel 0\n\t\tnil, // channel 1\n\t\tnil, // channel 2\n\t\tnil, // channel 3\n\t},\n}\n\nvar PWM2 = &timerType{\n\tinstance:   2,\n\tfrequency:  16e6,\n\tbits:       15,\n\tprescalers: []int{1, 2, 4, 8, 16, 32, 64, 128},\n\tchannelPins: [][]Pin{\n\t\tnil, // channel 0\n\t\tnil, // channel 1\n\t\tnil, // channel 2\n\t\tnil, // channel 3\n\t},\n}\n\nvar PWM3 = &timerType{\n\tinstance:   3,\n\tfrequency:  16e6,\n\tbits:       15,\n\tprescalers: []int{1, 2, 4, 8, 16, 32, 64, 128},\n\tchannelPins: [][]Pin{\n\t\tnil, // channel 0\n\t\tnil, // channel 1\n\t\tnil, // channel 2\n\t\tnil, // channel 3\n\t},\n}\n\nvar I2C0 = &I2C{Bus: 0}\nvar I2C1 = &I2C{Bus: 1}\n"
  },
  {
    "path": "src/machine/machine_nrf52840_usb.go",
    "content": "//go:build nrf52840\n\npackage machine\n\nimport (\n\t\"device/arm\"\n\t\"device/nrf\"\n\t\"machine/usb\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nconst NumberOfUSBEndpoints = 8\n\nvar (\n\tsendOnEP0DATADONE struct {\n\t\tptr    *byte\n\t\tcount  int\n\t\toffset int\n\t}\n\tepinen      uint32\n\tepouten     uint32\n\teasyDMABusy volatile.Register8\n\n\tendPoints = []uint32{\n\t\tusb.CONTROL_ENDPOINT:  usb.ENDPOINT_TYPE_CONTROL,\n\t\tusb.CDC_ENDPOINT_ACM:  (usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn),\n\t\tusb.CDC_ENDPOINT_OUT:  (usb.ENDPOINT_TYPE_BULK | usb.EndpointOut),\n\t\tusb.CDC_ENDPOINT_IN:   (usb.ENDPOINT_TYPE_BULK | usb.EndpointIn),\n\t\tusb.HID_ENDPOINT_IN:   (usb.ENDPOINT_TYPE_DISABLE), // Interrupt In\n\t\tusb.HID_ENDPOINT_OUT:  (usb.ENDPOINT_TYPE_DISABLE), // Interrupt Out\n\t\tusb.MIDI_ENDPOINT_IN:  (usb.ENDPOINT_TYPE_DISABLE), // Bulk In\n\t\tusb.MIDI_ENDPOINT_OUT: (usb.ENDPOINT_TYPE_DISABLE), // Bulk Out\n\t}\n)\n\n// enterCriticalSection is used to protect access to easyDMA - only one thing\n// can be done with it at a time\nfunc enterCriticalSection() {\n\twaitForEasyDMA()\n\teasyDMABusy.SetBits(1)\n}\n\nfunc waitForEasyDMA() {\n\tfor easyDMABusy.HasBits(1) {\n\t\tarm.Asm(\"wfi\")\n\t}\n}\n\nfunc exitCriticalSection() {\n\teasyDMABusy.ClearBits(1)\n}\n\n// Configure the USB peripheral. The config is here for compatibility with the UART interface.\nfunc (dev *USBDevice) Configure(config UARTConfig) {\n\tif dev.initcomplete {\n\t\treturn\n\t}\n\n\tstate := interrupt.Disable()\n\tdefer interrupt.Restore(state)\n\n\tnrf.USBD.USBPULLUP.Set(0)\n\n\t// Enable IRQ. Make sure this is higher than the SWI2 interrupt handler so\n\t// that it is possible to print to the console from a BLE interrupt. You\n\t// shouldn't generally do that but it is useful for debugging and panic\n\t// logging.\n\tintr := interrupt.New(nrf.IRQ_USBD, handleUSBIRQ)\n\tintr.SetPriority(0x40) // interrupt priority 2 (lower number means more important)\n\tintr.Enable()\n\n\t// enable interrupt for end of reset and start of frame\n\tnrf.USBD.INTEN.Set(nrf.USBD_INTENSET_USBEVENT)\n\n\t// errata 187\n\t// https://infocenter.nordicsemi.com/topic/errata_nRF52840_EngB/ERR/nRF52840/EngineeringB/latest/anomaly_840_187.html\n\t(*volatile.Register32)(unsafe.Pointer(uintptr(0x4006EC00))).Set(0x00009375)\n\t(*volatile.Register32)(unsafe.Pointer(uintptr(0x4006ED14))).Set(0x00000003)\n\t(*volatile.Register32)(unsafe.Pointer(uintptr(0x4006EC00))).Set(0x00009375)\n\n\t// enable USB\n\tnrf.USBD.ENABLE.Set(1)\n\n\ttimeout := 300000\n\tfor !nrf.USBD.EVENTCAUSE.HasBits(nrf.USBD_EVENTCAUSE_READY) {\n\t\ttimeout--\n\t\tif timeout == 0 {\n\t\t\treturn\n\t\t}\n\t}\n\tnrf.USBD.EVENTCAUSE.ClearBits(nrf.USBD_EVENTCAUSE_READY)\n\n\t// errata 187\n\t(*volatile.Register32)(unsafe.Pointer(uintptr(0x4006EC00))).Set(0x00009375)\n\t(*volatile.Register32)(unsafe.Pointer(uintptr(0x4006ED14))).Set(0x00000000)\n\t(*volatile.Register32)(unsafe.Pointer(uintptr(0x4006EC00))).Set(0x00009375)\n\n\tdev.initcomplete = true\n}\n\nfunc handleUSBIRQ(interrupt.Interrupt) {\n\tif nrf.USBD.EVENTS_SOF.Get() == 1 {\n\t\tnrf.USBD.EVENTS_SOF.Set(0)\n\n\t\t// if you want to blink LED showing traffic, this would be the place...\n\t}\n\n\t// USBD ready event\n\tif nrf.USBD.EVENTS_USBEVENT.Get() == 1 {\n\t\tnrf.USBD.EVENTS_USBEVENT.Set(0)\n\t\tif (nrf.USBD.EVENTCAUSE.Get() & nrf.USBD_EVENTCAUSE_READY) > 0 {\n\n\t\t\t// Configure control endpoint\n\t\t\tinitEndpoint(0, usb.ENDPOINT_TYPE_CONTROL)\n\t\t\tnrf.USBD.USBPULLUP.Set(1)\n\n\t\t\tusbConfiguration = 0\n\t\t}\n\t\tnrf.USBD.EVENTCAUSE.Set(0)\n\t}\n\n\tif nrf.USBD.EVENTS_EP0DATADONE.Get() == 1 {\n\t\t// done sending packet - either need to send another or enter status stage\n\t\tnrf.USBD.EVENTS_EP0DATADONE.Set(0)\n\t\tif sendOnEP0DATADONE.ptr != nil {\n\t\t\t// previous data was too big for one packet, so send a second\n\t\t\tptr := sendOnEP0DATADONE.ptr\n\t\t\tcount := sendOnEP0DATADONE.count\n\t\t\tif count > usb.EndpointPacketSize {\n\t\t\t\tsendOnEP0DATADONE.offset += usb.EndpointPacketSize\n\t\t\t\tsendOnEP0DATADONE.ptr = &udd_ep_control_cache_buffer[sendOnEP0DATADONE.offset]\n\t\t\t\tcount = usb.EndpointPacketSize\n\t\t\t}\n\t\t\tsendOnEP0DATADONE.count -= count\n\t\t\tsendViaEPIn(\n\t\t\t\t0,\n\t\t\t\tptr,\n\t\t\t\tcount,\n\t\t\t)\n\n\t\t\t// clear, so we know we're done\n\t\t\tif sendOnEP0DATADONE.count == 0 {\n\t\t\t\tsendOnEP0DATADONE.ptr = nil\n\t\t\t\tsendOnEP0DATADONE.offset = 0\n\t\t\t}\n\t\t} else {\n\t\t\t// no more data, so set status stage\n\t\t\tSendZlp() // nrf.USBD.TASKS_EP0STATUS.Set(1)\n\t\t}\n\t\treturn\n\t}\n\n\t// Endpoint 0 Setup interrupt\n\tif nrf.USBD.EVENTS_EP0SETUP.Get() == 1 {\n\t\t// ack setup received\n\t\tnrf.USBD.EVENTS_EP0SETUP.Set(0)\n\n\t\t// parse setup\n\t\tsetup := parseUSBSetupRegisters()\n\n\t\tok := false\n\t\tif (setup.BmRequestType & usb.REQUEST_TYPE) == usb.REQUEST_STANDARD {\n\t\t\t// Standard Requests\n\t\t\tok = handleStandardSetup(setup)\n\t\t} else {\n\t\t\t// Class Interface Requests\n\t\t\tif setup.WIndex < uint16(len(usbSetupHandler)) && usbSetupHandler[setup.WIndex] != nil {\n\t\t\t\tok = usbSetupHandler[setup.WIndex](setup)\n\t\t\t}\n\t\t}\n\n\t\tif !ok {\n\t\t\t// Stall endpoint\n\t\t\tnrf.USBD.TASKS_EP0STALL.Set(1)\n\t\t}\n\t}\n\n\t// Now the actual transfer handlers, ignore endpoint number 0 (setup)\n\tif nrf.USBD.EVENTS_EPDATA.Get() > 0 {\n\t\tnrf.USBD.EVENTS_EPDATA.Set(0)\n\t\tepDataStatus := nrf.USBD.EPDATASTATUS.Get()\n\t\tnrf.USBD.EPDATASTATUS.Set(epDataStatus)\n\t\tvar i uint32\n\t\tfor i = 1; i < uint32(len(endPoints)); i++ {\n\t\t\t// Check if endpoint has a pending interrupt\n\t\t\tinDataDone := epDataStatus&(nrf.USBD_EPDATASTATUS_EPIN1<<(i-1)) > 0\n\t\t\toutDataDone := epDataStatus&(nrf.USBD_EPDATASTATUS_EPOUT1<<(i-1)) > 0\n\t\t\tif inDataDone {\n\t\t\t\tif usbTxHandler[i] != nil {\n\t\t\t\t\tusbTxHandler[i]()\n\t\t\t\t}\n\t\t\t} else if outDataDone {\n\t\t\t\tenterCriticalSection()\n\t\t\t\tnrf.USBD.EPOUT[i].PTR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[i]))))\n\t\t\t\tcount := nrf.USBD.SIZE.EPOUT[i].Get()\n\t\t\t\tnrf.USBD.EPOUT[i].MAXCNT.Set(count)\n\t\t\t\tnrf.USBD.TASKS_STARTEPOUT[i].Set(1)\n\t\t\t}\n\t\t}\n\t}\n\n\t// ENDEPOUT[n] events\n\tfor i := 0; i < len(endPoints); i++ {\n\t\tif nrf.USBD.EVENTS_ENDEPOUT[i].Get() > 0 {\n\t\t\tnrf.USBD.EVENTS_ENDEPOUT[i].Set(0)\n\t\t\tbuf := handleEndpointRx(uint32(i))\n\t\t\tif usbRxHandler[i] == nil || usbRxHandler[i](buf) {\n\t\t\t\tAckUsbOutTransfer(uint32(i))\n\t\t\t}\n\t\t\texitCriticalSection()\n\t\t}\n\t}\n}\n\nfunc parseUSBSetupRegisters() usb.Setup {\n\treturn usb.Setup{\n\t\tBmRequestType: uint8(nrf.USBD.BMREQUESTTYPE.Get()),\n\t\tBRequest:      uint8(nrf.USBD.BREQUEST.Get()),\n\t\tWValueL:       uint8(nrf.USBD.WVALUEL.Get()),\n\t\tWValueH:       uint8(nrf.USBD.WVALUEH.Get()),\n\t\tWIndex:        uint16((nrf.USBD.WINDEXH.Get() << 8) | nrf.USBD.WINDEXL.Get()),\n\t\tWLength:       uint16(((nrf.USBD.WLENGTHH.Get() & 0xff) << 8) | (nrf.USBD.WLENGTHL.Get() & 0xff)),\n\t}\n}\n\nfunc initEndpoint(ep, config uint32) {\n\tswitch config {\n\tcase usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn:\n\t\tenableEPIn(ep)\n\n\tcase usb.ENDPOINT_TYPE_BULK | usb.EndpointOut:\n\t\tnrf.USBD.INTENSET.Set(nrf.USBD_INTENSET_ENDEPOUT0 << ep)\n\t\tnrf.USBD.SIZE.EPOUT[ep].Set(0)\n\t\tenableEPOut(ep)\n\n\tcase usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointOut:\n\t\tnrf.USBD.INTENSET.Set(nrf.USBD_INTENSET_ENDEPOUT0 << ep)\n\t\tnrf.USBD.SIZE.EPOUT[ep].Set(0)\n\t\tenableEPOut(ep)\n\n\tcase usb.ENDPOINT_TYPE_BULK | usb.EndpointIn:\n\t\tenableEPIn(ep)\n\n\tcase usb.ENDPOINT_TYPE_CONTROL:\n\t\tenableEPIn(0)\n\t\tenableEPOut(0)\n\t\tnrf.USBD.INTENSET.Set(nrf.USBD_INTENSET_ENDEPOUT0 |\n\t\t\tnrf.USBD_INTENSET_EP0SETUP |\n\t\t\tnrf.USBD_INTENSET_EPDATA |\n\t\t\tnrf.USBD_INTENSET_EP0DATADONE)\n\t\tSendZlp() // nrf.USBD.TASKS_EP0STATUS.Set(1)\n\t}\n}\n\n// SendUSBInPacket sends a packet for USBHID (interrupt in / bulk in).\nfunc SendUSBInPacket(ep uint32, data []byte) bool {\n\tsendUSBPacket(ep, data, 0)\n\n\t// clear transfer complete flag\n\tnrf.USBD.INTENCLR.Set(nrf.USBD_INTENCLR_ENDEPOUT0 << 4)\n\n\treturn true\n}\n\n// Prevent file size increases: https://github.com/tinygo-org/tinygo/pull/998\n//\n//go:noinline\nfunc sendUSBPacket(ep uint32, data []byte, maxsize uint16) {\n\tcount := len(data)\n\tif 0 < int(maxsize) && int(maxsize) < count {\n\t\tcount = int(maxsize)\n\t}\n\n\tif ep == 0 {\n\t\tcopy(udd_ep_control_cache_buffer[:], data[:count])\n\t\tif count > usb.EndpointPacketSize {\n\t\t\tsendOnEP0DATADONE.offset = usb.EndpointPacketSize\n\t\t\tsendOnEP0DATADONE.ptr = &udd_ep_control_cache_buffer[sendOnEP0DATADONE.offset]\n\t\t\tsendOnEP0DATADONE.count = count - usb.EndpointPacketSize\n\t\t\tcount = usb.EndpointPacketSize\n\t\t}\n\t\tsendViaEPIn(\n\t\t\tep,\n\t\t\t&udd_ep_control_cache_buffer[0],\n\t\t\tcount,\n\t\t)\n\t} else {\n\t\tcopy(udd_ep_in_cache_buffer[ep][:], data[:count])\n\t\tsendViaEPIn(\n\t\t\tep,\n\t\t\t&udd_ep_in_cache_buffer[ep][0],\n\t\t\tcount,\n\t\t)\n\t}\n}\n\nfunc handleEndpointRx(ep uint32) []byte {\n\t// get data\n\tcount := int(nrf.USBD.EPOUT[ep].AMOUNT.Get())\n\n\treturn udd_ep_out_cache_buffer[ep][:count]\n}\n\n// AckUsbOutTransfer is called to acknowledge the completion of a USB OUT transfer.\nfunc AckUsbOutTransfer(ep uint32) {\n\t// set ready for next data\n\tnrf.USBD.SIZE.EPOUT[ep].Set(0)\n}\n\nfunc SendZlp() {\n\tnrf.USBD.TASKS_EP0STATUS.Set(1)\n}\n\nfunc sendViaEPIn(ep uint32, ptr *byte, count int) {\n\tnrf.USBD.EPIN[ep].PTR.Set(\n\t\tuint32(uintptr(unsafe.Pointer(ptr))),\n\t)\n\tnrf.USBD.EPIN[ep].MAXCNT.Set(uint32(count))\n\tnrf.USBD.TASKS_STARTEPIN[ep].Set(1)\n}\n\nfunc enableEPOut(ep uint32) {\n\tepouten = epouten | (nrf.USBD_EPOUTEN_OUT0 << ep)\n\tnrf.USBD.EPOUTEN.Set(epouten)\n}\n\nfunc enableEPIn(ep uint32) {\n\tepinen = epinen | (nrf.USBD_EPINEN_IN0 << ep)\n\tnrf.USBD.EPINEN.Set(epinen)\n}\n\nfunc handleUSBSetAddress(setup usb.Setup) bool {\n\t// nrf USBD handles this\n\treturn true\n}\n\nfunc ReceiveUSBControlPacket() ([cdcLineInfoSize]byte, error) {\n\tvar b [cdcLineInfoSize]byte\n\n\tnrf.USBD.TASKS_EP0RCVOUT.Set(1)\n\n\tnrf.USBD.EPOUT[0].PTR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[0]))))\n\tnrf.USBD.EPOUT[0].MAXCNT.Set(64)\n\n\ttimeout := 300000\n\tcount := 0\n\tfor {\n\t\tif nrf.USBD.EVENTS_EP0DATADONE.Get() == 1 {\n\t\t\tnrf.USBD.EVENTS_EP0DATADONE.Set(0)\n\t\t\tcount = int(nrf.USBD.SIZE.EPOUT[0].Get())\n\t\t\tnrf.USBD.TASKS_STARTEPOUT[0].Set(1)\n\t\t\tbreak\n\t\t}\n\t\ttimeout--\n\t\tif timeout == 0 {\n\t\t\treturn b, ErrUSBReadTimeout\n\t\t}\n\t}\n\n\ttimeout = 300000\n\tfor {\n\t\tif nrf.USBD.EVENTS_ENDEPOUT[0].Get() == 1 {\n\t\t\tnrf.USBD.EVENTS_ENDEPOUT[0].Set(0)\n\t\t\tbreak\n\t\t}\n\n\t\ttimeout--\n\t\tif timeout == 0 {\n\t\t\treturn b, ErrUSBReadTimeout\n\t\t}\n\t}\n\n\tnrf.USBD.TASKS_EP0STATUS.Set(1)\n\tnrf.USBD.TASKS_EP0RCVOUT.Set(0)\n\n\tcopy(b[:7], udd_ep_out_cache_buffer[0][:count])\n\n\treturn b, nil\n}\n"
  },
  {
    "path": "src/machine/machine_nrf52840_usb_reset_bossa.go",
    "content": "//go:build nrf52840 && nrf52840_reset_bossa\n\npackage machine\n\n// EnterBootloader resets the chip into the serial bootloader. After\n// reset, it can be flashed using serial/nrfutil.\nfunc EnterBootloader() {\n\tEnterSerialBootloader()\n}\n"
  },
  {
    "path": "src/machine/machine_nrf52840_usb_reset_none.go",
    "content": "//go:build nrf52840 && !nrf52840_reset_uf2 && !nrf52840_reset_bossa\n\npackage machine\n\n// EnterBootloader resets the chip into the serial bootloader.\nfunc EnterBootloader() {\n\t// skip\n}\n"
  },
  {
    "path": "src/machine/machine_nrf52840_usb_reset_uf2.go",
    "content": "//go:build nrf52840 && nrf52840_reset_uf2\n\npackage machine\n\n// EnterBootloader resets the chip into the UF2 bootloader. After reset, it\n// can be flashed via nrfutil or by copying a UF2 file to the mass storage device\nfunc EnterBootloader() {\n\tEnterUF2Bootloader()\n}\n"
  },
  {
    "path": "src/machine/machine_nrf528xx.go",
    "content": "//go:build nrf52840 || nrf52833\n\npackage machine\n\nimport (\n\t\"device/nrf\"\n\t\"unsafe\"\n)\n\n// I2C on the NRF528xx.\ntype I2C struct {\n\tBus  *nrf.TWIM_Type // Called Bus to align with Bus field in nrf51\n\tBusT *nrf.TWIS_Type\n\tmode I2CMode\n}\n\n// There are 2 I2C interfaces on the NRF.\nvar (\n\tI2C0 = &I2C{Bus: nrf.TWIM0, BusT: nrf.TWIS0}\n\tI2C1 = &I2C{Bus: nrf.TWIM1, BusT: nrf.TWIS1}\n)\n\nfunc (i2c *I2C) enableAsController() {\n\ti2c.Bus.ENABLE.Set(nrf.TWIM_ENABLE_ENABLE_Enabled)\n}\n\nfunc (i2c *I2C) enableAsTarget() {\n\ti2c.BusT.ENABLE.Set(nrf.TWIS_ENABLE_ENABLE_Enabled)\n}\n\nfunc (i2c *I2C) disable() {\n\ti2c.Bus.ENABLE.Set(0)\n}\n\n// Tx does a single I2C transaction at the specified address (when in controller mode).\n//\n// It clocks out the given address, writes the bytes in w, reads back len(r)\n// bytes and stores them in r, and generates a stop condition on the bus.\nfunc (i2c *I2C) Tx(addr uint16, w, r []byte) (err error) {\n\ti2c.Bus.ADDRESS.Set(uint32(addr))\n\n\ti2c.Bus.EVENTS_STOPPED.Set(0)\n\ti2c.Bus.EVENTS_ERROR.Set(0)\n\ti2c.Bus.EVENTS_RXSTARTED.Set(0)\n\ti2c.Bus.EVENTS_TXSTARTED.Set(0)\n\ti2c.Bus.EVENTS_LASTRX.Set(0)\n\ti2c.Bus.EVENTS_LASTTX.Set(0)\n\ti2c.Bus.EVENTS_SUSPENDED.Set(0)\n\n\t// Configure for a single shot to perform both write and read (as applicable)\n\tif len(w) != 0 {\n\t\ti2c.Bus.TXD.PTR.Set(uint32(unsafeNoEscape(unsafe.Pointer(unsafe.SliceData(w)))))\n\t\ti2c.Bus.TXD.MAXCNT.Set(uint32(len(w)))\n\n\t\t// If no read, immediately signal stop after TX\n\t\tif len(r) == 0 {\n\t\t\ti2c.Bus.SHORTS.Set(nrf.TWIM_SHORTS_LASTTX_STOP)\n\t\t}\n\t}\n\tif len(r) != 0 {\n\t\ti2c.Bus.RXD.PTR.Set(uint32(unsafeNoEscape(unsafe.Pointer(unsafe.SliceData(r)))))\n\t\ti2c.Bus.RXD.MAXCNT.Set(uint32(len(r)))\n\n\t\t// Auto-start Rx after Tx and Stop after Rx\n\t\ti2c.Bus.SHORTS.Set(nrf.TWIM_SHORTS_LASTTX_STARTRX | nrf.TWIM_SHORTS_LASTRX_STOP)\n\t}\n\n\t// Fire the transaction\n\ti2c.Bus.TASKS_RESUME.Set(1)\n\tif len(w) != 0 {\n\t\ti2c.Bus.TASKS_STARTTX.Set(1)\n\t} else if len(r) != 0 {\n\t\ti2c.Bus.TASKS_STARTRX.Set(1)\n\t}\n\n\t// Wait until transaction stopped to ensure buffers fully processed\n\tfor i2c.Bus.EVENTS_STOPPED.Get() == 0 {\n\t\t// Allow scheduler to run\n\t\tgosched()\n\n\t\t// Handle first occurrence of error by ensuring STOP sent on bus\n\t\tif err == nil && i2c.Bus.EVENTS_ERROR.Get() != 0 {\n\t\t\terr = twiCError(i2c.Bus.ERRORSRC.Get())\n\t\t\tif i2c.Bus.EVENTS_STOPPED.Get() == 0 {\n\t\t\t\t// STOP cannot be sent during SUSPEND\n\t\t\t\ti2c.Bus.TASKS_RESUME.Set(1)\n\t\t\t\ti2c.Bus.TASKS_STOP.Set(1)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Make sure the w and r buffers stay alive until this point, so they won't\n\t// be garbage collected while the buffers are used by the hardware.\n\tkeepAliveNoEscape(unsafe.Pointer(unsafe.SliceData(w)))\n\tkeepAliveNoEscape(unsafe.Pointer(unsafe.SliceData(r)))\n\n\treturn\n}\n\n// Listen starts listening for I2C requests sent to specified address\n//\n// addr is the address to listen to\nfunc (i2c *I2C) Listen(addr uint8) error {\n\ti2c.BusT.ADDRESS[0].Set(uint32(addr))\n\ti2c.BusT.CONFIG.Set(nrf.TWIS_CONFIG_ADDRESS0_Enabled)\n\n\ti2c.BusT.EVENTS_STOPPED.Set(0)\n\ti2c.BusT.EVENTS_ERROR.Set(0)\n\ti2c.BusT.EVENTS_RXSTARTED.Set(0)\n\ti2c.BusT.EVENTS_TXSTARTED.Set(0)\n\ti2c.BusT.EVENTS_WRITE.Set(0)\n\ti2c.BusT.EVENTS_READ.Set(0)\n\n\treturn nil\n}\n\n// WaitForEvent blocks the current go-routine until an I2C event is received (when in Target mode).\n//\n// The passed buffer will be populated for receive events, with the number of bytes\n// received returned in count.  For other event types, buf is not modified and a count\n// of zero is returned.\n//\n// For request events, the caller MUST call `Reply` to avoid hanging the i2c bus indefinitely.\nfunc (i2c *I2C) WaitForEvent(buf []byte) (evt I2CTargetEvent, count int, err error) {\n\ti2c.BusT.RXD.PTR.Set(uint32(unsafeNoEscape(unsafe.Pointer(unsafe.SliceData(buf)))))\n\ti2c.BusT.RXD.MAXCNT.Set(uint32(len(buf)))\n\n\ti2c.BusT.TASKS_PREPARERX.Set(nrf.TWIS_TASKS_PREPARERX_TASKS_PREPARERX_Trigger)\n\n\ti2c.Bus.TASKS_RESUME.Set(1)\n\n\tfor i2c.BusT.EVENTS_STOPPED.Get() == 0 &&\n\t\ti2c.BusT.EVENTS_READ.Get() == 0 {\n\t\tgosched()\n\n\t\tif i2c.BusT.EVENTS_ERROR.Get() != 0 {\n\t\t\ti2c.BusT.EVENTS_ERROR.Set(0)\n\t\t\treturn I2CReceive, 0, twisError(i2c.BusT.ERRORSRC.Get())\n\t\t}\n\t}\n\n\t// Make sure buf stays alive until this point, so it won't be garbage\n\t// collected while it is used by the hardware.\n\tkeepAliveNoEscape(unsafe.Pointer(unsafe.SliceData(buf)))\n\n\tcount = 0\n\tevt = I2CFinish\n\terr = nil\n\n\tif i2c.BusT.EVENTS_WRITE.Get() != 0 {\n\t\ti2c.BusT.EVENTS_WRITE.Set(0)\n\n\t\t// Data was sent to this target.  We've waited for\n\t\t// READ or STOPPED event, so transmission should be\n\t\t// complete.\n\t\tcount = int(i2c.BusT.RXD.AMOUNT.Get())\n\t\tevt = I2CReceive\n\t} else if i2c.BusT.EVENTS_READ.Get() != 0 {\n\t\ti2c.BusT.EVENTS_READ.Set(0)\n\n\t\t// Data is requested from this target, hw will stretch\n\t\t// the controller's clock until there is a reply to\n\t\t// send\n\t\tevt = I2CRequest\n\t} else if i2c.BusT.EVENTS_STOPPED.Get() != 0 {\n\t\ti2c.BusT.EVENTS_STOPPED.Set(0)\n\t\tevt = I2CFinish\n\t}\n\n\treturn\n}\n\n// Reply supplies the response data the controller.\nfunc (i2c *I2C) Reply(buf []byte) error {\n\ti2c.BusT.TXD.PTR.Set(uint32(unsafeNoEscape(unsafe.Pointer(unsafe.SliceData(buf)))))\n\ti2c.BusT.TXD.MAXCNT.Set(uint32(len(buf)))\n\n\ti2c.BusT.EVENTS_STOPPED.Set(0)\n\n\t// Trigger Tx\n\ti2c.BusT.TASKS_PREPARETX.Set(nrf.TWIS_TASKS_PREPARETX_TASKS_PREPARETX_Trigger)\n\n\t// Block, waiting for Tx to complete\n\tfor i2c.BusT.EVENTS_STOPPED.Get() == 0 {\n\t\tgosched()\n\n\t\tif i2c.BusT.EVENTS_ERROR.Get() != 0 {\n\t\t\treturn twisError(i2c.BusT.ERRORSRC.Get())\n\t\t}\n\t}\n\n\t// Make sure the buffer stays alive until this point, so it won't be garbage\n\t// collected while it is used by the hardware.\n\tkeepAliveNoEscape(unsafe.Pointer(unsafe.SliceData(buf)))\n\n\ti2c.BusT.EVENTS_STOPPED.Set(0)\n\n\treturn nil\n}\n\n// twiCError converts an I2C controller error to Go\nfunc twiCError(val uint32) error {\n\tif val == 0 {\n\t\treturn nil\n\t} else if val&nrf.TWIM_ERRORSRC_OVERRUN_Msk == nrf.TWIM_ERRORSRC_OVERRUN {\n\t\treturn errI2CBusError\n\t} else if val&nrf.TWIM_ERRORSRC_ANACK_Msk == nrf.TWIM_ERRORSRC_ANACK {\n\t\treturn errI2CAckExpected\n\t} else if val&nrf.TWIM_ERRORSRC_DNACK_Msk == nrf.TWIM_ERRORSRC_DNACK {\n\t\treturn errI2CAckExpected\n\t}\n\n\treturn errI2CBusError\n}\n\n// twisError converts an I2C target error to Go\nfunc twisError(val uint32) error {\n\tif val == 0 {\n\t\treturn nil\n\t} else if val&nrf.TWIS_ERRORSRC_OVERFLOW_Msk == nrf.TWIS_ERRORSRC_OVERFLOW {\n\t\treturn errI2COverflow\n\t} else if val&nrf.TWIS_ERRORSRC_DNACK_Msk == nrf.TWIS_ERRORSRC_DNACK {\n\t\treturn errI2CAckExpected\n\t} else if val&nrf.TWIS_ERRORSRC_OVERREAD_Msk == nrf.TWIS_ERRORSRC_OVERREAD {\n\t\treturn errI2COverread\n\t}\n\n\treturn errI2CBusError\n}\n\nvar (\n\tWatchdog = &watchdogImpl{}\n)\n\nconst (\n\t// WatchdogMaxTimeout in milliseconds (approx 36h)\n\tWatchdogMaxTimeout = (0xffffffff * 1000) / 32768\n)\n\ntype watchdogImpl struct {\n}\n\n// Configure the watchdog.\n//\n// This method should not be called after the watchdog is started and on\n// some platforms attempting to reconfigure after starting the watchdog\n// is explicitly forbidden / will not work.\nfunc (wd *watchdogImpl) Configure(config WatchdogConfig) error {\n\t// 32.768kHz counter\n\tcrv := int32((int64(config.TimeoutMillis) * 32768) / 1000)\n\tnrf.WDT.CRV.Set(uint32(crv))\n\n\t// One source\n\tnrf.WDT.RREN.Set(0x1)\n\n\t// Run during sleep\n\tnrf.WDT.CONFIG.Set(nrf.WDT_CONFIG_SLEEP_Run)\n\n\treturn nil\n}\n\n// Starts the watchdog.\nfunc (wd *watchdogImpl) Start() error {\n\tnrf.WDT.TASKS_START.Set(nrf.WDT_TASKS_START_TASKS_START)\n\treturn nil\n}\n\n// Update the watchdog, indicating that `source` is healthy.\nfunc (wd *watchdogImpl) Update() {\n\t// 0x6E524635 = magic value from datasheet\n\tnrf.WDT.RR[0].Set(0x6E524635)\n}\n"
  },
  {
    "path": "src/machine/machine_nrf52xxx.go",
    "content": "//go:build nrf52 || nrf52840 || nrf52833\n\npackage machine\n\nimport (\n\t\"device/nrf\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nfunc CPUFrequency() uint32 {\n\treturn 64000000\n}\n\nvar adcVDDHPin = Pin(254) // special pin number for VDDH on the nrf52840\n\n// InitADC initializes the registers needed for ADC.\nfunc InitADC() {\n\t// Enable ADC.\n\t// The ADC does not consume a noticeable amount of current by being enabled.\n\tnrf.SAADC.ENABLE.Set(nrf.SAADC_ENABLE_ENABLE_Enabled << nrf.SAADC_ENABLE_ENABLE_Pos)\n}\n\n// Configure configures an ADC pin to be able to read analog data.\n// Reference voltage can be 150, 300, 600, 1200, 1800, 2400, 3000(default), 3600 mV\n// Resolution can be 8, 10, 12(default), 14 bits\n// SampleTime will be ceiled to 3(default), 5, 10, 15, 20 or 40(max) µS respectively\n// Samples can be 1(default), 2, 4, 8, 16, 32, 64, 128, 256 samples\nfunc (a *ADC) Configure(config ADCConfig) {\n\tvar configVal uint32 = nrf.SAADC_CH_CONFIG_RESP_Bypass<<nrf.SAADC_CH_CONFIG_RESP_Pos |\n\t\tnrf.SAADC_CH_CONFIG_RESN_Bypass<<nrf.SAADC_CH_CONFIG_RESN_Pos |\n\t\tnrf.SAADC_CH_CONFIG_REFSEL_Internal<<nrf.SAADC_CH_CONFIG_REFSEL_Pos |\n\t\tnrf.SAADC_CH_CONFIG_MODE_SE<<nrf.SAADC_CH_CONFIG_MODE_Pos\n\n\tswitch config.Reference {\n\tcase 150: // 0.15V\n\t\tconfigVal |= nrf.SAADC_CH_CONFIG_GAIN_Gain4 << nrf.SAADC_CH_CONFIG_GAIN_Pos\n\tcase 300: // 0.3V\n\t\tconfigVal |= nrf.SAADC_CH_CONFIG_GAIN_Gain2 << nrf.SAADC_CH_CONFIG_GAIN_Pos\n\tcase 600: // 0.6V\n\t\tconfigVal |= nrf.SAADC_CH_CONFIG_GAIN_Gain1 << nrf.SAADC_CH_CONFIG_GAIN_Pos\n\tcase 1200: // 1.2V\n\t\tconfigVal |= nrf.SAADC_CH_CONFIG_GAIN_Gain1_2 << nrf.SAADC_CH_CONFIG_GAIN_Pos\n\tcase 1800: // 1.8V\n\t\tconfigVal |= nrf.SAADC_CH_CONFIG_GAIN_Gain1_3 << nrf.SAADC_CH_CONFIG_GAIN_Pos\n\tcase 2400: // 2.4V\n\t\tconfigVal |= nrf.SAADC_CH_CONFIG_GAIN_Gain1_4 << nrf.SAADC_CH_CONFIG_GAIN_Pos\n\tcase 3000, 0: // 3.0V (default)\n\t\tconfigVal |= nrf.SAADC_CH_CONFIG_GAIN_Gain1_5 << nrf.SAADC_CH_CONFIG_GAIN_Pos\n\tcase 3600: // 3.6V\n\t\tconfigVal |= nrf.SAADC_CH_CONFIG_GAIN_Gain1_6 << nrf.SAADC_CH_CONFIG_GAIN_Pos\n\tdefault:\n\t\t// TODO: return an error, will that interfere with any interfaced if one will be?\n\t}\n\n\tvar resolution uint32\n\tswitch config.Resolution {\n\tcase 8:\n\t\tresolution = nrf.SAADC_RESOLUTION_VAL_8bit\n\tcase 10:\n\t\tresolution = nrf.SAADC_RESOLUTION_VAL_10bit\n\tcase 12:\n\t\tresolution = nrf.SAADC_RESOLUTION_VAL_12bit\n\tcase 14:\n\t\tresolution = nrf.SAADC_RESOLUTION_VAL_14bit\n\tdefault:\n\t\tresolution = nrf.SAADC_RESOLUTION_VAL_12bit\n\t}\n\tnrf.SAADC.RESOLUTION.Set(resolution)\n\n\t// Source resistance, according to table 41 on page 676 of the nrf52832 datasheet.\n\t// https://docs-be.nordicsemi.com/bundle/ps_nrf52840/attach/nRF52840_PS_v1.11.pdf?_LANG=enus\n\tif config.SampleTime <= 3 { // <= 10kΩ\n\t\tconfigVal |= nrf.SAADC_CH_CONFIG_TACQ_3us << nrf.SAADC_CH_CONFIG_TACQ_Pos\n\t} else if config.SampleTime <= 5 { // <= 40kΩ\n\t\tconfigVal |= nrf.SAADC_CH_CONFIG_TACQ_5us << nrf.SAADC_CH_CONFIG_TACQ_Pos\n\t} else if config.SampleTime <= 10 { // <= 100kΩ\n\t\tconfigVal |= nrf.SAADC_CH_CONFIG_TACQ_10us << nrf.SAADC_CH_CONFIG_TACQ_Pos\n\t} else if config.SampleTime <= 15 { // <= 200kΩ\n\t\tconfigVal |= nrf.SAADC_CH_CONFIG_TACQ_15us << nrf.SAADC_CH_CONFIG_TACQ_Pos\n\t} else if config.SampleTime <= 20 { // <= 400kΩ\n\t\tconfigVal |= nrf.SAADC_CH_CONFIG_TACQ_20us << nrf.SAADC_CH_CONFIG_TACQ_Pos\n\t} else { // <= 800kΩ\n\t\tconfigVal |= nrf.SAADC_CH_CONFIG_TACQ_40us << nrf.SAADC_CH_CONFIG_TACQ_Pos\n\t}\n\n\t// Oversampling configuration.\n\tburst := true\n\tswitch config.Samples {\n\tdefault: // no oversampling\n\t\tnrf.SAADC.OVERSAMPLE.Set(nrf.SAADC_OVERSAMPLE_OVERSAMPLE_Bypass)\n\t\tburst = false\n\tcase 2:\n\t\tnrf.SAADC.OVERSAMPLE.Set(nrf.SAADC_OVERSAMPLE_OVERSAMPLE_Over2x)\n\tcase 4:\n\t\tnrf.SAADC.OVERSAMPLE.Set(nrf.SAADC_OVERSAMPLE_OVERSAMPLE_Over4x)\n\tcase 8:\n\t\tnrf.SAADC.OVERSAMPLE.Set(nrf.SAADC_OVERSAMPLE_OVERSAMPLE_Over8x)\n\tcase 16:\n\t\tnrf.SAADC.OVERSAMPLE.Set(nrf.SAADC_OVERSAMPLE_OVERSAMPLE_Over16x)\n\tcase 32:\n\t\tnrf.SAADC.OVERSAMPLE.Set(nrf.SAADC_OVERSAMPLE_OVERSAMPLE_Over32x)\n\tcase 64:\n\t\tnrf.SAADC.OVERSAMPLE.Set(nrf.SAADC_OVERSAMPLE_OVERSAMPLE_Over64x)\n\tcase 128:\n\t\tnrf.SAADC.OVERSAMPLE.Set(nrf.SAADC_OVERSAMPLE_OVERSAMPLE_Over128x)\n\tcase 256:\n\t\tnrf.SAADC.OVERSAMPLE.Set(nrf.SAADC_OVERSAMPLE_OVERSAMPLE_Over256x)\n\t}\n\tif burst {\n\t\t// BURST=1 is needed when oversampling\n\t\tconfigVal |= nrf.SAADC_CH_CONFIG_BURST\n\t}\n\n\t// Configure channel 0, which is the only channel we use.\n\tnrf.SAADC.CH[0].CONFIG.Set(configVal)\n}\n\n// Get returns the current value of an ADC pin in the range 0..0xffff.\nfunc (a *ADC) Get() uint16 {\n\tvar adcPin uint32\n\tvar rawValue volatile.Register16\n\n\tswitch a.Pin {\n\tcase 2:\n\t\tadcPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput0\n\tcase 3:\n\t\tadcPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput1\n\tcase 4:\n\t\tadcPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput2\n\tcase 5:\n\t\tadcPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput3\n\tcase 28:\n\t\tadcPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput4\n\tcase 29:\n\t\tadcPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput5\n\tcase 30:\n\t\tadcPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput6\n\tcase 31:\n\t\tadcPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput7\n\tcase adcVDDHPin:\n\t\tif Device == \"nrf52840\" {\n\t\t\tadcPin = 0x0D // VDDHDIV5 on the nrf52840\n\t\t} else {\n\t\t\treturn 0\n\t\t}\n\tdefault:\n\t\treturn 0\n\t}\n\n\t// Set pin to read.\n\tnrf.SAADC.CH[0].PSELP.Set(adcPin)\n\n\t// Destination for sample result.\n\t// Note: rawValue doesn't need to be kept alive for the GC, since the\n\t// volatile read later will force it to stay alive.\n\tnrf.SAADC.RESULT.PTR.Set(uint32(unsafeNoEscape(unsafe.Pointer(&rawValue))))\n\tnrf.SAADC.RESULT.MAXCNT.Set(1) // One sample\n\n\t// Start tasks.\n\tnrf.SAADC.TASKS_START.Set(1)\n\tfor nrf.SAADC.EVENTS_STARTED.Get() == 0 {\n\t}\n\tnrf.SAADC.EVENTS_STARTED.Set(0x00)\n\n\t// Start the sample task.\n\tnrf.SAADC.TASKS_SAMPLE.Set(1)\n\n\t// Wait until the sample task is done.\n\tfor nrf.SAADC.EVENTS_END.Get() == 0 {\n\t}\n\tnrf.SAADC.EVENTS_END.Set(0x00)\n\n\t// Stop the ADC\n\tnrf.SAADC.TASKS_STOP.Set(1)\n\tfor nrf.SAADC.EVENTS_STOPPED.Get() == 0 {\n\t}\n\tnrf.SAADC.EVENTS_STOPPED.Set(0)\n\n\t// convert to 16 bit resolution/value\n\tvar resolutionAdjustment uint8\n\tswitch nrf.SAADC.RESOLUTION.Get() {\n\tcase nrf.SAADC_RESOLUTION_VAL_8bit:\n\t\tresolutionAdjustment = 8\n\tcase nrf.SAADC_RESOLUTION_VAL_10bit:\n\t\tresolutionAdjustment = 6\n\tcase nrf.SAADC_RESOLUTION_VAL_12bit:\n\t\tresolutionAdjustment = 4\n\tcase nrf.SAADC_RESOLUTION_VAL_14bit:\n\t\tresolutionAdjustment = 2\n\tdefault:\n\t\tresolutionAdjustment = 4 // 12bit\n\t}\n\n\tvalue := int16(rawValue.Get())\n\tif value < 0 {\n\t\tvalue = 0\n\t}\n\n\treturn uint16(value << resolutionAdjustment)\n}\n\n// SPI on the NRF.\ntype SPI struct {\n\tBus *nrf.SPIM_Type\n\tbuf *[1]byte // 1-byte buffer for the Transfer method\n}\n\n// There are 3 SPI interfaces on the NRF528xx.\nvar (\n\tSPI0 = &SPI{Bus: nrf.SPIM0, buf: new([1]byte)}\n\tSPI1 = &SPI{Bus: nrf.SPIM1, buf: new([1]byte)}\n\tSPI2 = &SPI{Bus: nrf.SPIM2, buf: new([1]byte)}\n)\n\n// SPIConfig is used to store config info for SPI.\ntype SPIConfig struct {\n\tFrequency uint32\n\tSCK       Pin\n\tSDO       Pin\n\tSDI       Pin\n\tLSBFirst  bool\n\tMode      uint8\n}\n\n// Configure is intended to set up the SPI interface.\nfunc (spi *SPI) Configure(config SPIConfig) error {\n\t// Disable bus to configure it\n\tspi.Bus.ENABLE.Set(nrf.SPIM_ENABLE_ENABLE_Disabled)\n\n\t// Pick a default frequency.\n\tif config.Frequency == 0 {\n\t\tconfig.Frequency = 4000000 // 4MHz\n\t}\n\n\t// set frequency\n\tvar freq uint32\n\tswitch {\n\tcase config.Frequency >= 8000000:\n\t\tfreq = nrf.SPIM_FREQUENCY_FREQUENCY_M8\n\tcase config.Frequency >= 4000000:\n\t\tfreq = nrf.SPIM_FREQUENCY_FREQUENCY_M4\n\tcase config.Frequency >= 2000000:\n\t\tfreq = nrf.SPIM_FREQUENCY_FREQUENCY_M2\n\tcase config.Frequency >= 1000000:\n\t\tfreq = nrf.SPIM_FREQUENCY_FREQUENCY_M1\n\tcase config.Frequency >= 500000:\n\t\tfreq = nrf.SPIM_FREQUENCY_FREQUENCY_K500\n\tcase config.Frequency >= 250000:\n\t\tfreq = nrf.SPIM_FREQUENCY_FREQUENCY_K250\n\tdefault: // below 250kHz, default to the lowest speed available\n\t\tfreq = nrf.SPIM_FREQUENCY_FREQUENCY_K125\n\t}\n\tspi.Bus.FREQUENCY.Set(freq)\n\n\tvar conf uint32\n\n\t// set bit transfer order\n\tif config.LSBFirst {\n\t\tconf = (nrf.SPIM_CONFIG_ORDER_LsbFirst << nrf.SPIM_CONFIG_ORDER_Pos)\n\t}\n\n\t// set mode\n\tswitch config.Mode {\n\tcase 0:\n\t\tconf &^= (nrf.SPIM_CONFIG_CPOL_ActiveHigh << nrf.SPIM_CONFIG_CPOL_Pos)\n\t\tconf &^= (nrf.SPIM_CONFIG_CPHA_Leading << nrf.SPIM_CONFIG_CPHA_Pos)\n\tcase 1:\n\t\tconf &^= (nrf.SPIM_CONFIG_CPOL_ActiveHigh << nrf.SPIM_CONFIG_CPOL_Pos)\n\t\tconf |= (nrf.SPIM_CONFIG_CPHA_Trailing << nrf.SPIM_CONFIG_CPHA_Pos)\n\tcase 2:\n\t\tconf |= (nrf.SPIM_CONFIG_CPOL_ActiveLow << nrf.SPIM_CONFIG_CPOL_Pos)\n\t\tconf &^= (nrf.SPIM_CONFIG_CPHA_Leading << nrf.SPIM_CONFIG_CPHA_Pos)\n\tcase 3:\n\t\tconf |= (nrf.SPIM_CONFIG_CPOL_ActiveLow << nrf.SPIM_CONFIG_CPOL_Pos)\n\t\tconf |= (nrf.SPIM_CONFIG_CPHA_Trailing << nrf.SPIM_CONFIG_CPHA_Pos)\n\tdefault: // to mode\n\t\tconf &^= (nrf.SPIM_CONFIG_CPOL_ActiveHigh << nrf.SPIM_CONFIG_CPOL_Pos)\n\t\tconf &^= (nrf.SPIM_CONFIG_CPHA_Leading << nrf.SPIM_CONFIG_CPHA_Pos)\n\t}\n\tspi.Bus.CONFIG.Set(conf)\n\n\t// set pins\n\tif config.SCK == 0 && config.SDO == 0 && config.SDI == 0 {\n\t\tconfig.SCK = SPI0_SCK_PIN\n\t\tconfig.SDO = SPI0_SDO_PIN\n\t\tconfig.SDI = SPI0_SDI_PIN\n\t}\n\tspi.Bus.PSEL.SCK.Set(uint32(config.SCK))\n\tspi.Bus.PSEL.MOSI.Set(uint32(config.SDO))\n\tspi.Bus.PSEL.MISO.Set(uint32(config.SDI))\n\n\t// Re-enable bus now that it is configured.\n\tspi.Bus.ENABLE.Set(nrf.SPIM_ENABLE_ENABLE_Enabled)\n\n\treturn nil\n}\n\n// Transfer writes/reads a single byte using the SPI interface.\nfunc (spi *SPI) Transfer(w byte) (byte, error) {\n\tbuf := spi.buf[:]\n\tbuf[0] = w\n\terr := spi.Tx(buf[:], buf[:])\n\treturn buf[0], err\n}\n\n// Tx handles read/write operation for SPI interface. Since SPI is a synchronous\n// write/read interface, there must always be the same number of bytes written\n// as bytes read. Therefore, if the number of bytes don't match it will be\n// padded until they fit: if len(w) > len(r) the extra bytes received will be\n// dropped and if len(w) < len(r) extra 0 bytes will be sent.\nfunc (spi *SPI) Tx(w, r []byte) error {\n\t// Unfortunately the hardware (on the nrf52832) only supports a limited\n\t// amount of bytes in the buffers (depending on the chip), so if either w or\n\t// r is longer than that the transfer needs to be broken up in pieces.\n\tfor len(r) != 0 || len(w) != 0 {\n\t\t// Prepare the SPI transfer: set the DMA pointers and lengths.\n\t\t// read buffer\n\t\tnr := uint32(len(r))\n\t\tif nr > 0 {\n\t\t\tif nr > spiMaxBufferSize {\n\t\t\t\tnr = spiMaxBufferSize\n\t\t\t}\n\t\t\tspi.Bus.RXD.PTR.Set(uint32(unsafeNoEscape(unsafe.Pointer(unsafe.SliceData(r)))))\n\t\t\tr = r[nr:]\n\t\t}\n\t\tspi.Bus.RXD.MAXCNT.Set(nr)\n\n\t\t// write buffer\n\t\tnw := uint32(len(w))\n\t\tif nw > 0 {\n\t\t\tif nw > spiMaxBufferSize {\n\t\t\t\tnw = spiMaxBufferSize\n\t\t\t}\n\t\t\tspi.Bus.TXD.PTR.Set(uint32(unsafeNoEscape(unsafe.Pointer(unsafe.SliceData(w)))))\n\t\t\tw = w[nw:]\n\t\t}\n\t\tspi.Bus.TXD.MAXCNT.Set(nw)\n\n\t\t// Do the transfer.\n\t\t// Note: this can be improved by not waiting until the transfer is\n\t\t// finished if the transfer is send-only (a common case).\n\t\tspi.Bus.TASKS_START.Set(1)\n\t\tfor spi.Bus.EVENTS_END.Get() == 0 {\n\t\t\tgosched()\n\t\t}\n\t\tspi.Bus.EVENTS_END.Set(0)\n\t}\n\n\t// Make sure the w and r buffers stay alive for the GC until this point,\n\t// since they are used by the hardware but not otherwise visible.\n\tkeepAliveNoEscape(unsafe.Pointer(unsafe.SliceData(r)))\n\tkeepAliveNoEscape(unsafe.Pointer(unsafe.SliceData(w)))\n\n\treturn nil\n}\n\n// PWM is one PWM peripheral, which consists of a counter and multiple output\n// channels (that can be connected to actual pins). You can set the frequency\n// using SetPeriod, but only for all the channels in this PWM peripheral at\n// once.\ntype PWM struct {\n\tPWM *nrf.PWM_Type\n\n\tchannelValues [4]volatile.Register16\n}\n\n// Configure enables and configures this PWM.\n// On the nRF52 series, the maximum period is around 0.26s.\nfunc (pwm *PWM) Configure(config PWMConfig) error {\n\t// Enable the peripheral.\n\tpwm.PWM.ENABLE.Set(nrf.PWM_ENABLE_ENABLE_Enabled << nrf.PWM_ENABLE_ENABLE_Pos)\n\n\t// Use up counting only. TODO: allow configuring as up-and-down.\n\tpwm.PWM.MODE.Set(nrf.PWM_MODE_UPDOWN_Up << nrf.PWM_MODE_UPDOWN_Pos)\n\n\t// Indicate there are four channels that each have a different value.\n\tpwm.PWM.DECODER.Set(nrf.PWM_DECODER_LOAD_Individual<<nrf.PWM_DECODER_LOAD_Pos | nrf.PWM_DECODER_MODE_RefreshCount<<nrf.PWM_DECODER_MODE_Pos)\n\n\terr := pwm.setPeriod(config.Period, true)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Set the EasyDMA buffer, which has 4 values (one for each channel).\n\tpwm.PWM.SEQ[0].PTR.Set(uint32(uintptr(unsafe.Pointer(&pwm.channelValues[0]))))\n\tpwm.PWM.SEQ[0].CNT.Set(4)\n\n\t// SEQ[0] is not yet started, it will be started on the first\n\t// PWMChannel.Set() call.\n\n\treturn nil\n}\n\n// SetPeriod updates the period of this PWM peripheral.\n// To set a particular frequency, use the following formula:\n//\n//\tperiod = 1e9 / frequency\n//\n// If you use a period of 0, a period that works well for LEDs will be picked.\n//\n// SetPeriod will not change the prescaler, but also won't change the current\n// value in any of the channels. This means that you may need to update the\n// value for the particular channel.\n//\n// Note that you cannot pick any arbitrary period after the PWM peripheral has\n// been configured. If you want to switch between frequencies, pick the lowest\n// frequency (longest period) once when calling Configure and adjust the\n// frequency here as needed.\nfunc (pwm *PWM) SetPeriod(period uint64) error {\n\treturn pwm.setPeriod(period, false)\n}\n\nfunc (pwm *PWM) setPeriod(period uint64, updatePrescaler bool) error {\n\tconst maxTop = 0x7fff // 15 bits counter\n\n\t// The top value is the number of PWM ticks a PWM period takes. It is\n\t// initially picked assuming an unlimited COUNTERTOP and no PWM prescaler.\n\tvar top uint64\n\tif period == 0 {\n\t\t// The period is 0, which means \"pick something reasonable for LEDs\".\n\t\ttop = maxTop\n\t} else {\n\t\t// The formula below calculates the following formula, optimized:\n\t\t//     period * (16e6 / 1e9)\n\t\t// The max frequency (16e6 or 16MHz) is set by the hardware.\n\t\ttop = period * 2 / 125\n\t}\n\n\t// The ideal PWM period may be larger than would fit in the PWM counter,\n\t// which is only 15 bits (see maxTop). Therefore, try to make the PWM clock\n\t// speed lower with a prescaler to make the top value fit the COUNTERTOP.\n\tif updatePrescaler {\n\t\t// This function was called during Configure().\n\t\tswitch {\n\t\tcase top <= maxTop:\n\t\t\tpwm.PWM.PRESCALER.Set(nrf.PWM_PRESCALER_PRESCALER_DIV_1)\n\t\tcase top/2 <= maxTop:\n\t\t\tpwm.PWM.PRESCALER.Set(nrf.PWM_PRESCALER_PRESCALER_DIV_2)\n\t\t\ttop /= 2\n\t\tcase top/4 <= maxTop:\n\t\t\tpwm.PWM.PRESCALER.Set(nrf.PWM_PRESCALER_PRESCALER_DIV_4)\n\t\t\ttop /= 4\n\t\tcase top/8 <= maxTop:\n\t\t\tpwm.PWM.PRESCALER.Set(nrf.PWM_PRESCALER_PRESCALER_DIV_8)\n\t\t\ttop /= 8\n\t\tcase top/16 <= maxTop:\n\t\t\tpwm.PWM.PRESCALER.Set(nrf.PWM_PRESCALER_PRESCALER_DIV_16)\n\t\t\ttop /= 16\n\t\tcase top/32 <= maxTop:\n\t\t\tpwm.PWM.PRESCALER.Set(nrf.PWM_PRESCALER_PRESCALER_DIV_32)\n\t\t\ttop /= 32\n\t\tcase top/64 <= maxTop:\n\t\t\tpwm.PWM.PRESCALER.Set(nrf.PWM_PRESCALER_PRESCALER_DIV_64)\n\t\t\ttop /= 64\n\t\tcase top/128 <= maxTop:\n\t\t\tpwm.PWM.PRESCALER.Set(nrf.PWM_PRESCALER_PRESCALER_DIV_128)\n\t\t\ttop /= 128\n\t\tdefault:\n\t\t\treturn ErrPWMPeriodTooLong\n\t\t}\n\t} else {\n\t\t// Do not update the prescaler, but use the already-configured\n\t\t// prescaler. This is the normal SetPeriod case, where the prescaler\n\t\t// must not be changed.\n\t\tprescaler := pwm.PWM.PRESCALER.Get()\n\t\tswitch prescaler {\n\t\tcase nrf.PWM_PRESCALER_PRESCALER_DIV_1:\n\t\t\ttop /= 1\n\t\tcase nrf.PWM_PRESCALER_PRESCALER_DIV_2:\n\t\t\ttop /= 2\n\t\tcase nrf.PWM_PRESCALER_PRESCALER_DIV_4:\n\t\t\ttop /= 4\n\t\tcase nrf.PWM_PRESCALER_PRESCALER_DIV_8:\n\t\t\ttop /= 8\n\t\tcase nrf.PWM_PRESCALER_PRESCALER_DIV_16:\n\t\t\ttop /= 16\n\t\tcase nrf.PWM_PRESCALER_PRESCALER_DIV_32:\n\t\t\ttop /= 32\n\t\tcase nrf.PWM_PRESCALER_PRESCALER_DIV_64:\n\t\t\ttop /= 64\n\t\tcase nrf.PWM_PRESCALER_PRESCALER_DIV_128:\n\t\t\ttop /= 128\n\t\t}\n\t\tif top > maxTop {\n\t\t\treturn ErrPWMPeriodTooLong\n\t\t}\n\t}\n\tpwm.PWM.COUNTERTOP.Set(uint32(top))\n\n\t// Apparently this is needed to apply the new COUNTERTOP.\n\tpwm.PWM.TASKS_SEQSTART[0].Set(1)\n\n\treturn nil\n}\n\n// Top returns the current counter top, for use in duty cycle calculation. It\n// will only change with a call to Configure or SetPeriod, otherwise it is\n// constant.\n//\n// The value returned here is hardware dependent. In general, it's best to treat\n// it as an opaque value that can be divided by some number and passed to\n// pwm.Set (see pwm.Set for more information).\nfunc (pwm *PWM) Top() uint32 {\n\treturn pwm.PWM.COUNTERTOP.Get()\n}\n\n// Channel returns a PWM channel for the given pin.\nfunc (pwm *PWM) Channel(pin Pin) (uint8, error) {\n\tconfig := uint32(pin)\n\tfor ch := uint8(0); ch < 4; ch++ {\n\t\tchannelConfig := pwm.PWM.PSEL.OUT[ch].Get()\n\t\tif channelConfig == 0xffffffff {\n\t\t\t// Unused channel. Configure it.\n\t\t\tpwm.PWM.PSEL.OUT[ch].Set(config)\n\t\t\t// Configure the pin (required by the reference manual).\n\t\t\tpin.Configure(PinConfig{Mode: PinOutput})\n\t\t\t// Set channel to zero and non-inverting.\n\t\t\tpwm.channelValues[ch].Set(0x8000)\n\t\t\treturn ch, nil\n\t\t} else if channelConfig == config {\n\t\t\t// This channel is already configured for this pin.\n\t\t\treturn ch, nil\n\t\t}\n\t}\n\n\t// All four pins are already in use with other pins.\n\treturn 0, ErrInvalidOutputPin\n}\n\n// SetInverting sets whether to invert the output of this channel.\n// Without inverting, a 25% duty cycle would mean the output is high for 25% of\n// the time and low for the rest. Inverting flips the output as if a NOT gate\n// was placed at the output, meaning that the output would be 25% low and 75%\n// high with a duty cycle of 25%.\nfunc (pwm *PWM) SetInverting(channel uint8, inverting bool) {\n\tptr := &pwm.channelValues[channel]\n\tif inverting {\n\t\tptr.Set(ptr.Get() &^ 0x8000)\n\t} else {\n\t\tptr.Set(ptr.Get() | 0x8000)\n\t}\n}\n\n// Set updates the channel value. This is used to control the channel duty\n// cycle. For example, to set it to a 25% duty cycle, use:\n//\n//\tch.Set(ch.Top() / 4)\n//\n// ch.Set(0) will set the output to low and ch.Set(ch.Top()) will set the output\n// to high, assuming the output isn't inverted.\nfunc (pwm *PWM) Set(channel uint8, value uint32) {\n\t// Update the channel value while retaining the polarity bit.\n\tptr := &pwm.channelValues[channel]\n\tptr.Set(ptr.Get()&0x8000 | uint16(value)&0x7fff)\n\n\t// Start the PWM, if it isn't already running.\n\tpwm.PWM.TASKS_SEQSTART[0].Set(1)\n}\n"
  },
  {
    "path": "src/machine/machine_nrf5x.go",
    "content": "//go:build nrf51 || nrf52\n\npackage machine\n\nimport \"device/nrf\"\n\n// I2C on the NRF51 and NRF52.\ntype I2C struct {\n\tBus  *nrf.TWI_Type\n\tmode I2CMode\n}\n\n// There are 2 I2C interfaces on the NRF.\nvar (\n\tI2C0 = &I2C{Bus: nrf.TWI0}\n\tI2C1 = &I2C{Bus: nrf.TWI1}\n)\n\nfunc (i2c *I2C) enableAsController() {\n\ti2c.Bus.ENABLE.Set(nrf.TWI_ENABLE_ENABLE_Enabled)\n}\n\nfunc (i2c *I2C) enableAsTarget() {\n\t// Not supported on this hardware\n}\n\nfunc (i2c *I2C) disable() {\n\ti2c.Bus.ENABLE.Set(0)\n}\n\n// Tx does a single I2C transaction at the specified address.\n// It clocks out the given address, writes the bytes in w, reads back len(r)\n// bytes and stores them in r, and generates a stop condition on the bus.\nfunc (i2c *I2C) Tx(addr uint16, w, r []byte) (err error) {\n\n\t// Tricky stop condition.\n\t// After reads, the stop condition is generated implicitly with a shortcut.\n\t// After writes not followed by reads and in the case of errors, stop must be generated explicitly.\n\n\ti2c.Bus.ADDRESS.Set(uint32(addr))\n\n\tif len(w) != 0 {\n\t\ti2c.Bus.TASKS_STARTTX.Set(1) // start transmission for writing\n\t\tfor _, b := range w {\n\t\t\tif err = i2c.writeByte(b); err != nil {\n\t\t\t\ti2c.signalStop()\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\n\tif len(r) != 0 {\n\t\t// To trigger suspend task when a byte is received\n\t\ti2c.Bus.SHORTS.Set(nrf.TWI_SHORTS_BB_SUSPEND)\n\t\ti2c.Bus.TASKS_STARTRX.Set(1) // re-start transmission for reading\n\t\tfor i := range r {           // read each char\n\t\t\tif i+1 == len(r) {\n\t\t\t\t// To trigger stop task when last byte is received, set before resume task.\n\t\t\t\ti2c.Bus.SHORTS.Set(nrf.TWI_SHORTS_BB_STOP)\n\t\t\t}\n\t\t\tif i > 0 {\n\t\t\t\ti2c.Bus.TASKS_RESUME.Set(1) // re-start transmission for reading\n\t\t\t}\n\t\t\tif r[i], err = i2c.readByte(); err != nil {\n\t\t\t\ti2c.Bus.SHORTS.Set(nrf.TWI_SHORTS_BB_SUSPEND_Disabled)\n\t\t\t\ti2c.signalStop()\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t\ti2c.Bus.SHORTS.Set(nrf.TWI_SHORTS_BB_SUSPEND_Disabled)\n\t}\n\n\tif len(r) == 0 {\n\t\t// Stop the I2C transaction after the write.\n\t\terr = i2c.signalStop()\n\t} else {\n\t\t// The last byte read has already stopped the transaction, via\n\t\t// TWI_SHORTS_BB_STOP. But we still need to wait until we receive the\n\t\t// STOPPED event.\n\t\ttries := 0\n\t\tfor i2c.Bus.EVENTS_STOPPED.Get() == 0 {\n\t\t\ttries++\n\t\t\tif tries >= i2cTimeout {\n\t\t\t\treturn errI2CSignalStopTimeout\n\t\t\t}\n\t\t}\n\t\ti2c.Bus.EVENTS_STOPPED.Set(0)\n\t}\n\n\treturn\n}\n\n// writeByte writes a single byte to the I2C bus and waits for confirmation.\nfunc (i2c *I2C) writeByte(data byte) error {\n\ttries := 0\n\ti2c.Bus.TXD.Set(uint32(data))\n\tfor i2c.Bus.EVENTS_TXDSENT.Get() == 0 {\n\t\tif e := i2c.Bus.EVENTS_ERROR.Get(); e != 0 {\n\t\t\ti2c.Bus.EVENTS_ERROR.Set(0)\n\t\t\treturn errI2CBusError\n\t\t}\n\t\ttries++\n\t\tif tries >= i2cTimeout {\n\t\t\treturn errI2CWriteTimeout\n\t\t}\n\t}\n\ti2c.Bus.EVENTS_TXDSENT.Set(0)\n\treturn nil\n}\n\n// readByte reads a single byte from the I2C bus when it is ready.\nfunc (i2c *I2C) readByte() (byte, error) {\n\ttries := 0\n\tfor i2c.Bus.EVENTS_RXDREADY.Get() == 0 {\n\t\tif e := i2c.Bus.EVENTS_ERROR.Get(); e != 0 {\n\t\t\ti2c.Bus.EVENTS_ERROR.Set(0)\n\t\t\treturn 0, errI2CBusError\n\t\t}\n\t\ttries++\n\t\tif tries >= i2cTimeout {\n\t\t\treturn 0, errI2CReadTimeout\n\t\t}\n\t}\n\ti2c.Bus.EVENTS_RXDREADY.Set(0)\n\treturn byte(i2c.Bus.RXD.Get()), nil\n}\n"
  },
  {
    "path": "src/machine/machine_nrf_bare.go",
    "content": "//go:build nrf && !softdevice\n\npackage machine\n\n// GetRNG returns 32 bits of non-deterministic random data based on internal thermal noise.\n// According to Nordic's documentation, the random output is suitable for cryptographic purposes.\nfunc GetRNG() (ret uint32, err error) {\n\treturn getRNG()\n}\n\nfunc isSoftDeviceEnabled() bool {\n\treturn false\n}\n"
  },
  {
    "path": "src/machine/machine_nrf_sd.go",
    "content": "//go:build nrf && softdevice\n\npackage machine\n\nimport (\n\t\"device/arm\"\n\t\"device/nrf\"\n\n\t\"errors\"\n)\n\n// avoid a heap allocation in GetRNG.\nvar (\n\tbytesAvailable uint8\n\tbuf            [4]uint8\n\n\terrNoSoftDeviceSupport = errors.New(\"rng: softdevice not supported on this device\")\n\terrNotEnoughRandomData = errors.New(\"rng: not enough random data available\")\n)\n\n// GetRNG returns 32 bits of non-deterministic random data based on internal thermal noise.\n// According to Nordic's documentation, the random output is suitable for cryptographic purposes.\nfunc GetRNG() (ret uint32, err error) {\n\t// First check whether the SoftDevice is enabled.\n\t// sd_rand_application_bytes_available_get cannot be called when the SoftDevice is not enabled.\n\tif !isSoftDeviceEnabled() {\n\t\treturn getRNG()\n\t}\n\n\t// call into the SoftDevice to get random data bytes available\n\tswitch nrf.Device {\n\tcase \"nrf51\":\n\t\t// sd_rand_application_bytes_available_get: SOC_SVC_BASE_NOT_AVAILABLE + 4\n\t\tarm.SVCall1(0x2B+4, &bytesAvailable)\n\tcase \"nrf52\", \"nrf52840\", \"nrf52833\":\n\t\t// sd_rand_application_bytes_available_get: SOC_SVC_BASE_NOT_AVAILABLE + 4\n\t\tarm.SVCall1(0x2C+4, &bytesAvailable)\n\tdefault:\n\t\treturn 0, errNoSoftDeviceSupport\n\t}\n\n\tif bytesAvailable < 4 {\n\t\treturn 0, errNotEnoughRandomData\n\t}\n\n\tswitch nrf.Device {\n\tcase \"nrf51\":\n\t\t// sd_rand_application_vector_get: SOC_SVC_BASE_NOT_AVAILABLE + 5\n\t\tarm.SVCall2(0x2B+5, &buf, 4)\n\tcase \"nrf52\", \"nrf52840\", \"nrf52833\":\n\t\t// sd_rand_application_vector_get: SOC_SVC_BASE_NOT_AVAILABLE + 5\n\t\tarm.SVCall2(0x2C+5, &buf, 4)\n\t}\n\n\treturn uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24, nil\n}\n\n// This function is defined in the runtime, but we need it too.\n//\n//go:linkname isSoftDeviceEnabled runtime.isSoftDeviceEnabled\nfunc isSoftDeviceEnabled() bool\n"
  },
  {
    "path": "src/machine/machine_nxpmk66f18.go",
    "content": "// Derivative work of Teensyduino Core Library\n// http://www.pjrc.com/teensy/\n// Copyright (c) 2017 PJRC.COM, LLC.\n//\n// Permission is hereby granted, free of charge, to any person obtaining\n// a copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to\n// the following conditions:\n//\n// 1. The above copyright notice and this permission notice shall be\n// included in all copies or substantial portions of the Software.\n//\n// 2. If the Software is incorporated into a build system that allows\n// selection among a list of target devices, then similar target\n// devices manufactured by PJRC.COM must be included in the list of\n// target devices and selectable in the same manner.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n//go:build nxp && mk66f18\n\npackage machine\n\nimport (\n\t\"device/nxp\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nconst deviceName = nxp.Device\n\nconst (\n\tPinInput PinMode = iota\n\tPinInputPullup\n\tPinInputPulldown\n\tPinOutput\n\tPinOutputOpenDrain\n\tPinDisable\n)\n\n// Deprecated: use PinInputPullup and PinInputPulldown instead.\nconst (\n\tPinInputPullUp   = PinInputPullup\n\tPinInputPullDown = PinInputPulldown\n)\n\nconst (\n\tPA00 Pin = iota\n\tPA01\n\tPA02\n\tPA03\n\tPA04\n\tPA05\n\tPA06\n\tPA07\n\tPA08\n\tPA09\n\tPA10\n\tPA11\n\tPA12\n\tPA13\n\tPA14\n\tPA15\n\tPA16\n\tPA17\n\tPA18\n\tPA19\n\tPA20\n\tPA21\n\tPA22\n\tPA23\n\tPA24\n\tPA25\n\tPA26\n\tPA27\n\tPA28\n\tPA29\n)\n\nconst (\n\tPB00 Pin = iota + 32\n\tPB01\n\tPB02\n\tPB03\n\tPB04\n\tPB05\n\tPB06\n\tPB07\n\tPB08\n\tPB09\n\tPB10\n\tPB11\n\t_\n\t_\n\t_\n\t_\n\tPB16\n\tPB17\n\tPB18\n\tPB19\n\tPB20\n\tPB21\n\tPB22\n\tPB23\n)\n\nconst (\n\tPC00 Pin = iota + 64\n\tPC01\n\tPC02\n\tPC03\n\tPC04\n\tPC05\n\tPC06\n\tPC07\n\tPC08\n\tPC09\n\tPC10\n\tPC11\n\tPC12\n\tPC13\n\tPC14\n\tPC15\n\tPC16\n\tPC17\n\tPC18\n\tPC19\n)\n\nconst (\n\tPD00 Pin = iota + 96\n\tPD01\n\tPD02\n\tPD03\n\tPD04\n\tPD05\n\tPD06\n\tPD07\n\tPD08\n\tPD09\n\tPD10\n\tPD11\n\tPD12\n\tPD13\n\tPD14\n\tPD15\n)\n\nconst (\n\tPE00 Pin = iota + 128\n\tPE01\n\tPE02\n\tPE03\n\tPE04\n\tPE05\n\tPE06\n\tPE07\n\tPE08\n\tPE09\n\tPE10\n\tPE11\n\tPE12\n\tPE13\n\tPE14\n\tPE15\n\tPE16\n\tPE17\n\tPE18\n\tPE19\n\tPE20\n\tPE21\n\tPE22\n\tPE23\n\tPE24\n\tPE25\n\tPE26\n\tPE27\n\tPE28\n)\n\n//go:inline\nfunc (p Pin) reg() (*nxp.GPIO_Type, *volatile.Register32, uint8) {\n\tvar gpio *nxp.GPIO_Type\n\tvar pcr *nxp.PORT_Type\n\n\tswitch p / 32 {\n\tcase 0:\n\t\tgpio, pcr = nxp.GPIOA, nxp.PORTA\n\tcase 1:\n\t\tgpio, pcr = nxp.GPIOB, nxp.PORTB\n\tcase 2:\n\t\tgpio, pcr = nxp.GPIOC, nxp.PORTC\n\tcase 3:\n\t\tgpio, pcr = nxp.GPIOD, nxp.PORTD\n\tcase 5:\n\t\tgpio, pcr = nxp.GPIOE, nxp.PORTE\n\tdefault:\n\t\tpanic(\"invalid pin number\")\n\t}\n\n\treturn gpio, &(*[32]volatile.Register32)(unsafe.Pointer(pcr))[p%32], uint8(p % 32)\n}\n\n// Configure this pin with the given configuration.\nfunc (p Pin) Configure(config PinConfig) {\n\tgpio, pcr, pos := p.reg()\n\n\tswitch config.Mode {\n\tcase PinOutput:\n\t\tgpio.PDDR.SetBits(1 << pos)\n\t\tpcr.Set((1 << nxp.PORT_PCR0_MUX_Pos) | nxp.PORT_PCR0_SRE | nxp.PORT_PCR0_DSE)\n\n\tcase PinOutputOpenDrain:\n\t\tgpio.PDDR.SetBits(1 << pos)\n\t\tpcr.Set((1 << nxp.PORT_PCR0_MUX_Pos) | nxp.PORT_PCR0_SRE | nxp.PORT_PCR0_DSE | nxp.PORT_PCR0_ODE)\n\n\tcase PinInput:\n\t\tgpio.PDDR.ClearBits(1 << pos)\n\t\tpcr.Set((1 << nxp.PORT_PCR0_MUX_Pos))\n\n\tcase PinInputPullup:\n\t\tgpio.PDDR.ClearBits(1 << pos)\n\t\tpcr.Set((1 << nxp.PORT_PCR0_MUX_Pos) | nxp.PORT_PCR0_PE | nxp.PORT_PCR0_PS)\n\n\tcase PinInputPulldown:\n\t\tgpio.PDDR.ClearBits(1 << pos)\n\t\tpcr.Set((1 << nxp.PORT_PCR0_MUX_Pos) | nxp.PORT_PCR0_PE)\n\n\tcase PinDisable:\n\t\tgpio.PDDR.ClearBits(1 << pos)\n\t\tpcr.Set((0 << nxp.PORT_PCR0_MUX_Pos))\n\t}\n}\n\n// Set changes the value of the GPIO pin. The pin must be configured as output.\nfunc (p Pin) Set(value bool) {\n\tgpio, _, pos := p.reg()\n\tif value {\n\t\tgpio.PSOR.Set(1 << pos)\n\t} else {\n\t\tgpio.PCOR.Set(1 << pos)\n\t}\n}\n\n// Get returns the current value of a GPIO pin.\nfunc (p Pin) Get() bool {\n\tgpio, _, pos := p.reg()\n\treturn gpio.PDIR.HasBits(1 << pos)\n}\n\nfunc (p Pin) Control() *volatile.Register32 {\n\t_, pcr, _ := p.reg()\n\treturn pcr\n}\n\nfunc (p Pin) Fast() FastPin {\n\tgpio, _, pos := p.reg()\n\treturn FastPin{\n\t\tPDOR: gpio.PDOR.Bit(pos),\n\t\tPSOR: gpio.PSOR.Bit(pos),\n\t\tPCOR: gpio.PCOR.Bit(pos),\n\t\tPTOR: gpio.PTOR.Bit(pos),\n\t\tPDIR: gpio.PDIR.Bit(pos),\n\t\tPDDR: gpio.PDDR.Bit(pos),\n\t}\n}\n\ntype FastPin struct {\n\tPDOR *volatile.BitRegister\n\tPSOR *volatile.BitRegister\n\tPCOR *volatile.BitRegister\n\tPTOR *volatile.BitRegister\n\tPDIR *volatile.BitRegister\n\tPDDR *volatile.BitRegister\n}\n\nfunc (p FastPin) Set()         { p.PSOR.Set(true) }\nfunc (p FastPin) Clear()       { p.PCOR.Set(true) }\nfunc (p FastPin) Toggle()      { p.PTOR.Set(true) }\nfunc (p FastPin) Write(v bool) { p.PDOR.Set(v) }\nfunc (p FastPin) Read() bool   { return p.PDIR.Get() }\n"
  },
  {
    "path": "src/machine/machine_nxpmk66f18_uart.go",
    "content": "// Derivative work of Teensyduino Core Library\n// http://www.pjrc.com/teensy/\n// Copyright (c) 2017 PJRC.COM, LLC.\n//\n// Permission is hereby granted, free of charge, to any person obtaining\n// a copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to\n// the following conditions:\n//\n// 1. The above copyright notice and this permission notice shall be\n// included in all copies or substantial portions of the Software.\n//\n// 2. If the Software is incorporated into a build system that allows\n// selection among a list of target devices, then similar target\n// devices manufactured by PJRC.COM must be included in the list of\n// target devices and selectable in the same manner.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n//go:build nxp && mk66f18\n\npackage machine\n\nimport (\n\t\"device/arm\"\n\t\"device/nxp\"\n\t\"errors\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n\n\t_ \"unsafe\" // for go:linkname\n)\n\nconst (\n\tuartC2Enable       = nxp.UART_C2_TE | nxp.UART_C2_RE | nxp.UART_C2_RIE | nxp.UART_C2_ILIE\n\tuartC2TXActive     = uartC2Enable | nxp.UART_C2_TIE\n\tuartC2TXCompleting = uartC2Enable | nxp.UART_C2_TCIE\n\tuartC2TXInactive   = uartC2Enable\n\n\tuartIRQPriority = 64\n\n\t// determined from UARTx_PFIFO\n\tuartRXFIFODepth = 8\n\tuartTXFIFODepth = 8\n)\n\nvar (\n\tErrNotImplemented = errors.New(\"device has not been implemented\")\n\tErrNotConfigured  = errors.New(\"device has not been configured\")\n)\n\n// PutcharUART writes a byte to the UART synchronously, without using interrupts\n// or calling the scheduler\nfunc PutcharUART(u *UART, c byte) {\n\t// ensure the UART has been configured\n\tif !u.SCGC.HasBits(u.SCGCMask) {\n\t\tu.configure(UARTConfig{}, false)\n\t}\n\n\tfor u.TCFIFO.Get() > 0 {\n\t\t// busy wait\n\t}\n\tu.D.Set(c)\n\tu.C2.Set(uartC2TXActive)\n}\n\n// PollUART manually checks a UART status and calls the ISR. This should only be\n// called by runtime.abort.\nfunc PollUART(u *UART) {\n\tif u.SCGC.HasBits(u.SCGCMask) {\n\t\tu.handleStatusInterrupt(u.Interrupt)\n\t}\n}\n\ntype UART struct {\n\t*nxp.UART_Type\n\tSCGC     *volatile.Register32\n\tSCGCMask uint32\n\n\tDefaultRX Pin\n\tDefaultTX Pin\n\n\t// state\n\tBuffer       RingBuffer // RX Buffer\n\tTXBuffer     RingBuffer\n\tConfigured   bool\n\tTransmitting volatile.Register8\n\tInterrupt    interrupt.Interrupt\n}\n\nvar (\n\tUART0  = &_UART0\n\tUART1  = &_UART1\n\tUART2  = &_UART2\n\tUART3  = &_UART3\n\tUART4  = &_UART4\n\t_UART0 = UART{UART_Type: nxp.UART0, SCGC: &nxp.SIM.SCGC4, SCGCMask: nxp.SIM_SCGC4_UART0, DefaultRX: defaultUART0RX, DefaultTX: defaultUART0TX}\n\t_UART1 = UART{UART_Type: nxp.UART1, SCGC: &nxp.SIM.SCGC4, SCGCMask: nxp.SIM_SCGC4_UART1, DefaultRX: defaultUART1RX, DefaultTX: defaultUART1TX}\n\t_UART2 = UART{UART_Type: nxp.UART2, SCGC: &nxp.SIM.SCGC4, SCGCMask: nxp.SIM_SCGC4_UART2, DefaultRX: defaultUART2RX, DefaultTX: defaultUART2TX}\n\t_UART3 = UART{UART_Type: nxp.UART3, SCGC: &nxp.SIM.SCGC4, SCGCMask: nxp.SIM_SCGC4_UART3, DefaultRX: defaultUART3RX, DefaultTX: defaultUART3TX}\n\t_UART4 = UART{UART_Type: nxp.UART4, SCGC: &nxp.SIM.SCGC1, SCGCMask: nxp.SIM_SCGC1_UART4, DefaultRX: defaultUART4RX, DefaultTX: defaultUART4TX}\n)\n\nfunc init() {\n\tUART0.Interrupt = interrupt.New(nxp.IRQ_UART0_RX_TX, _UART0.handleStatusInterrupt)\n\tUART1.Interrupt = interrupt.New(nxp.IRQ_UART1_RX_TX, _UART1.handleStatusInterrupt)\n\tUART2.Interrupt = interrupt.New(nxp.IRQ_UART2_RX_TX, _UART2.handleStatusInterrupt)\n\tUART3.Interrupt = interrupt.New(nxp.IRQ_UART3_RX_TX, _UART3.handleStatusInterrupt)\n\tUART4.Interrupt = interrupt.New(nxp.IRQ_UART4_RX_TX, _UART4.handleStatusInterrupt)\n}\n\n// Configure the UART.\nfunc (u *UART) Configure(config UARTConfig) {\n\tu.configure(config, true)\n}\n\nfunc (u *UART) configure(config UARTConfig, canSched bool) {\n\t// from: serial_begin\n\n\tif !u.Configured {\n\t\tu.Transmitting.Set(0)\n\n\t\t// turn on the clock\n\t\tu.SCGC.Set(u.SCGCMask)\n\n\t\t// configure pins\n\t\tu.DefaultRX.Control().Set(nxp.PORT_PCR0_PE | nxp.PORT_PCR0_PS | nxp.PORT_PCR0_PFE | (3 << nxp.PORT_PCR0_MUX_Pos))\n\t\tu.DefaultTX.Control().Set(nxp.PORT_PCR0_DSE | nxp.PORT_PCR0_SRE | (3 << nxp.PORT_PCR0_MUX_Pos))\n\t\tu.C1.Set(nxp.UART_C1_ILT)\n\t}\n\n\t// default to 115200 baud\n\tif config.BaudRate == 0 {\n\t\tconfig.BaudRate = 115200\n\t}\n\n\t// copied from teensy core's BAUD2DIV macro\n\tdivisor := ((CPUFrequency() * 2) + (config.BaudRate >> 1)) / config.BaudRate\n\tif divisor < 32 {\n\t\tdivisor = 32\n\t}\n\n\tif u.Configured {\n\t\t// don't change baud rate mid transmit\n\t\tif canSched {\n\t\t\tu.Flush()\n\t\t} else {\n\t\t\tfor u.Transmitting.Get() != 0 {\n\t\t\t\t// busy wait flush\n\t\t\t}\n\t\t}\n\t}\n\n\t// set the divisor\n\tu.BDH.Set(uint8((divisor >> 13) & 0x1F))\n\tu.BDL.Set(uint8((divisor >> 5) & 0xFF))\n\tu.C4.Set(uint8(divisor & 0x1F))\n\n\tif !u.Configured {\n\t\tu.Configured = true\n\n\t\tu.C1.Set(nxp.UART_C1_ILT)\n\n\t\t// configure TX and RX watermark\n\t\tu.TWFIFO.Set(2) // causes bit TDRE of S1 to set\n\t\tu.RWFIFO.Set(4) // causes bit RDRF of S1 to set\n\n\t\t// enable FIFOs\n\t\tu.PFIFO.Set(nxp.UART_PFIFO_TXFE | nxp.UART_PFIFO_RXFE)\n\n\t\t// setup interrupts\n\t\tu.C2.Set(uartC2TXInactive)\n\t\tu.Interrupt.SetPriority(uartIRQPriority)\n\t\tu.Interrupt.Enable()\n\t}\n}\n\nfunc (u *UART) Disable() {\n\t// from: serial_end\n\n\t// check if the device has been enabled already\n\tif !u.SCGC.HasBits(u.SCGCMask) {\n\t\treturn\n\t}\n\n\tu.Flush()\n\n\tu.Interrupt.Disable()\n\tu.C2.Set(0)\n\n\t// reconfigure pin\n\tu.DefaultRX.Configure(PinConfig{Mode: PinInputPullup})\n\tu.DefaultTX.Configure(PinConfig{Mode: PinInputPullup})\n\n\t// clear flags\n\tu.S1.Get()\n\tu.D.Get()\n\tu.Buffer.Clear()\n}\n\nfunc (u *UART) Flush() {\n\tfor u.Transmitting.Get() != 0 {\n\t\tgosched()\n\t}\n}\n\nfunc (u *UART) handleStatusInterrupt(interrupt.Interrupt) {\n\t// from: uart0_status_isr\n\n\t// receive\n\tif u.S1.HasBits(nxp.UART_S1_RDRF | nxp.UART_S1_IDLE) {\n\t\tintrs := arm.DisableInterrupts()\n\t\tavail := u.RCFIFO.Get()\n\t\tif avail == 0 {\n\t\t\t// The only way to clear the IDLE interrupt flag is\n\t\t\t// to read the data register.  But reading with no\n\t\t\t// data causes a FIFO underrun, which causes the\n\t\t\t// FIFO to return corrupted data.  If anyone from\n\t\t\t// Freescale reads this, what a poor design!  There\n\t\t\t// write should be a write-1-to-clear for IDLE.\n\t\t\tu.D.Get()\n\t\t\t// flushing the fifo recovers from the underrun,\n\t\t\t// but there's a possible race condition where a\n\t\t\t// new character could be received between reading\n\t\t\t// RCFIFO == 0 and flushing the FIFO.  To minimize\n\t\t\t// the chance, interrupts are disabled so a higher\n\t\t\t// priority interrupt (hopefully) doesn't delay.\n\t\t\t// TODO: change this to disabling the IDLE interrupt\n\t\t\t// which won't be simple, since we already manage\n\t\t\t// which transmit interrupts are enabled.\n\t\t\tu.CFIFO.Set(nxp.UART_CFIFO_RXFLUSH)\n\t\t\tarm.EnableInterrupts(intrs)\n\n\t\t} else {\n\t\t\tarm.EnableInterrupts(intrs)\n\n\t\t\tfor {\n\t\t\t\tu.Buffer.Put(u.D.Get())\n\t\t\t\tavail--\n\t\t\t\tif avail <= 0 {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// transmit\n\tif u.C2.HasBits(nxp.UART_C2_TIE) && u.S1.HasBits(nxp.UART_S1_TDRE) {\n\t\tdata := make([]byte, 0, uartTXFIFODepth)\n\t\tavail := uartTXFIFODepth - u.TCFIFO.Get()\n\n\t\t// get avail bytes from ring buffer\n\t\tfor len(data) < int(avail) {\n\t\t\tif b, ok := u.TXBuffer.Get(); ok {\n\t\t\t\tdata = append(data, b)\n\t\t\t} else {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\t// write data to FIFO\n\t\tl := len(data)\n\t\tfor i, b := range data {\n\t\t\tif i == l-1 {\n\t\t\t\t// only clear TDRE on last write, per the manual\n\t\t\t\tu.S1.Get()\n\t\t\t}\n\t\t\tu.D.Set(b)\n\t\t}\n\n\t\t// if FIFO still has room, disable TIE, enable TCIE\n\t\tif u.S1.HasBits(nxp.UART_S1_TDRE) {\n\t\t\tu.C2.Set(uartC2TXCompleting)\n\t\t}\n\t}\n\n\t// transmit complete\n\tif u.C2.HasBits(nxp.UART_C2_TCIE) && u.S1.HasBits(nxp.UART_S1_TC) {\n\t\tu.Transmitting.Set(0)\n\t\tu.C2.Set(uartC2TXInactive)\n\t}\n}\n\n// WriteByte writes a byte of data to the UART.\nfunc (u *UART) writeByte(c byte) error {\n\tif !u.Configured {\n\t\treturn ErrNotConfigured\n\t}\n\n\tfor !u.TXBuffer.Put(c) {\n\t\tgosched()\n\t}\n\n\tu.Transmitting.Set(1)\n\tu.C2.Set(uartC2TXActive)\n\treturn nil\n}\n\nfunc (uart *UART) flush() {}\n"
  },
  {
    "path": "src/machine/machine_rp2.go",
    "content": "//go:build rp2040 || rp2350\n\npackage machine\n\nimport (\n\t\"device/rp\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nconst deviceName = rp.Device\n\nconst (\n\t// Number of spin locks available\n\t// Note: On RP2350, most spinlocks are unusable due to Errata 2\n\t_NUMSPINLOCKS         = 32\n\t_PICO_SPINLOCK_ID_IRQ = 9\n\t// is48Pin notes whether the chip is RP2040 with 32 pins or RP2350 with 48 pins.\n\tis48Pin = _NUMBANK0_GPIOS == 48\n)\n\n// UART on the RP2040\nvar (\n\tUART0  = &_UART0\n\t_UART0 = UART{\n\t\tBuffer: NewRingBuffer(),\n\t\tBus:    rp.UART0,\n\t}\n\n\tUART1  = &_UART1\n\t_UART1 = UART{\n\t\tBuffer: NewRingBuffer(),\n\t\tBus:    rp.UART1,\n\t}\n)\n\nfunc init() {\n\tUART0.Interrupt = interrupt.New(rp.IRQ_UART0_IRQ, _UART0.handleInterrupt)\n\tUART1.Interrupt = interrupt.New(rp.IRQ_UART1_IRQ, _UART1.handleInterrupt)\n}\n\n//go:linkname machineInit runtime.machineInit\nfunc machineInit() {\n\t// Reset all peripherals to put system into a known state,\n\t// except for QSPI pads and the XIP IO bank, as this is fatal if running from flash\n\t// and the PLLs, as this is fatal if clock muxing has not been reset on this boot\n\t// and USB, syscfg, as this disturbs USB-to-SWD on core 1\n\tbits := ^uint32(initDontReset)\n\tresetBlock(bits)\n\n\t// Remove reset from peripherals which are clocked only by clkSys and\n\t// clkRef. Other peripherals stay in reset until we've configured clocks.\n\tbits = ^uint32(initUnreset)\n\tunresetBlockWait(bits)\n\n\tclocks.init()\n\n\t// Peripheral clocks should now all be running\n\tunresetBlockWait(RESETS_RESET_Msk)\n\n\t// DBGPAUSE pauses the timer when a debugger is connected. This prevents\n\t// sleep functions from ever returning, so disable it.\n\ttimer.setDbgPause(false)\n}\n\n//go:linkname ticks runtime.machineTicks\nfunc ticks() uint64 {\n\treturn timer.timeElapsed()\n}\n\n//go:linkname lightSleep runtime.machineLightSleep\nfunc lightSleep(ticks uint64) {\n\ttimer.lightSleep(ticks)\n}\n\n// CurrentCore returns the core number the call was made from.\nfunc CurrentCore() int {\n\treturn int(rp.SIO.CPUID.Get())\n}\n\n// NumCores returns number of cores available on the device.\nfunc NumCores() int { return 2 }\n\n// ChipVersion returns the version of the chip. 1 is returned for B0 and B1\n// chip.\nfunc ChipVersion() uint8 {\n\tconst (\n\t\tSYSINFO_BASE                  = 0x40000000\n\t\tSYSINFO_CHIP_ID_OFFSET        = 0x00000000\n\t\tSYSINFO_CHIP_ID_REVISION_BITS = 0xf0000000\n\t\tSYSINFO_CHIP_ID_REVISION_LSB  = 28\n\t)\n\n\t// First register of sysinfo is chip id\n\tchipID := *(*uint32)(unsafe.Pointer(uintptr(SYSINFO_BASE + SYSINFO_CHIP_ID_OFFSET)))\n\t// Version 1 == B0/B1\n\tversion := (chipID & SYSINFO_CHIP_ID_REVISION_BITS) >> SYSINFO_CHIP_ID_REVISION_LSB\n\treturn uint8(version)\n}\n\n// Single DMA channel. See rp.DMA_Type.\ntype dmaChannel struct {\n\tREAD_ADDR   volatile.Register32\n\tWRITE_ADDR  volatile.Register32\n\tTRANS_COUNT volatile.Register32\n\tCTRL_TRIG   volatile.Register32\n\t_           [12]volatile.Register32 // aliases\n}\n\n// Static assignment of DMA channels to peripherals.\n// Allocating them statically is good enough for now. If lots of peripherals use\n// DMA, these might need to be assigned at runtime.\nconst (\n\tspi0DMAChannel = iota\n\tspi1DMAChannel\n)\n\n// DMA channels usable on the RP2040.\nvar dmaChannels = (*[12 + 4*rp2350ExtraReg]dmaChannel)(unsafe.Pointer(rp.DMA))\n\n//go:inline\nfunc boolToBit(a bool) uint32 {\n\tif a {\n\t\treturn 1\n\t}\n\treturn 0\n}\n\n//go:inline\nfunc u32max(a, b uint32) uint32 {\n\tif a > b {\n\t\treturn a\n\t}\n\treturn b\n}\n\n//go:inline\nfunc isReservedI2CAddr(addr uint8) bool {\n\treturn (addr&0x78) == 0 || (addr&0x78) == 0x78\n}\n"
  },
  {
    "path": "src/machine/machine_rp2040_rom.go",
    "content": "//go:build tinygo && rp2040\n\npackage machine\n\nimport (\n\t\"runtime/interrupt\"\n\t\"unsafe\"\n)\n\n/*\n// https://github.com/raspberrypi/pico-sdk\n// src/rp2_common/pico_bootrom/include/pico/bootrom.h\n\n#define ROM_FUNC_POPCOUNT32             ROM_TABLE_CODE('P', '3')\n#define ROM_FUNC_REVERSE32              ROM_TABLE_CODE('R', '3')\n#define ROM_FUNC_CLZ32                  ROM_TABLE_CODE('L', '3')\n#define ROM_FUNC_CTZ32                  ROM_TABLE_CODE('T', '3')\n#define ROM_FUNC_MEMSET                 ROM_TABLE_CODE('M', 'S')\n#define ROM_FUNC_MEMSET4                ROM_TABLE_CODE('S', '4')\n#define ROM_FUNC_MEMCPY                 ROM_TABLE_CODE('M', 'C')\n#define ROM_FUNC_MEMCPY44               ROM_TABLE_CODE('C', '4')\n#define ROM_FUNC_RESET_USB_BOOT         ROM_TABLE_CODE('U', 'B')\n#define ROM_FUNC_CONNECT_INTERNAL_FLASH ROM_TABLE_CODE('I', 'F')\n#define ROM_FUNC_FLASH_EXIT_XIP         ROM_TABLE_CODE('E', 'X')\n#define ROM_FUNC_FLASH_RANGE_ERASE      ROM_TABLE_CODE('R', 'E')\n#define ROM_FUNC_FLASH_RANGE_PROGRAM    ROM_TABLE_CODE('R', 'P')\n#define ROM_FUNC_FLASH_FLUSH_CACHE      ROM_TABLE_CODE('F', 'C')\n#define ROM_FUNC_FLASH_ENTER_CMD_XIP    ROM_TABLE_CODE('C', 'X')\n\n#define ROM_TABLE_CODE(c1, c2) ((c1) | ((c2) << 8))\n\ntypedef unsigned char uint8_t;\ntypedef unsigned short uint16_t;\ntypedef unsigned long uint32_t;\ntypedef unsigned long size_t;\ntypedef unsigned long uintptr_t;\n\n#define false 0\n#define true 1\ntypedef int bool;\n\n#define ram_func __attribute__((section(\".ramfuncs\"),noinline))\n\ntypedef void *(*rom_table_lookup_fn)(uint16_t *table, uint32_t code);\ntypedef void __attribute__((noreturn)) (*rom_reset_usb_boot_fn)(uint32_t, uint32_t);\ntypedef void (*flash_init_boot2_copyout_fn)(void);\ntypedef void (*flash_enable_xip_via_boot2_fn)(void);\ntypedef void (*flash_exit_xip_fn)(void);\ntypedef void (*flash_flush_cache_fn)(void);\ntypedef void (*flash_connect_internal_fn)(void);\ntypedef void (*flash_range_erase_fn)(uint32_t, size_t, uint32_t, uint16_t);\ntypedef void (*flash_range_program_fn)(uint32_t, const uint8_t*, size_t);\n\nstatic inline __attribute__((always_inline)) void __compiler_memory_barrier(void) {\n    __asm__ volatile (\"\" : : : \"memory\");\n}\n\n#define rom_hword_as_ptr(rom_address) (void *)(uintptr_t)(*(uint16_t *)(uintptr_t)(rom_address))\n\nvoid *rom_func_lookup(uint32_t code) {\n\trom_table_lookup_fn rom_table_lookup = (rom_table_lookup_fn) rom_hword_as_ptr(0x18);\n\tuint16_t *func_table = (uint16_t *) rom_hword_as_ptr(0x14);\n\treturn rom_table_lookup(func_table, code);\n}\n\nvoid reset_usb_boot(uint32_t usb_activity_gpio_pin_mask, uint32_t disable_interface_mask) {\n\trom_reset_usb_boot_fn func = (rom_reset_usb_boot_fn) rom_func_lookup(ROM_FUNC_RESET_USB_BOOT);\n\tfunc(usb_activity_gpio_pin_mask, disable_interface_mask);\n}\n\n#define FLASH_BLOCK_ERASE_CMD 0xd8\n\n#define FLASH_PAGE_SIZE (1u << 8)\n#define FLASH_SECTOR_SIZE (1u << 12)\n#define FLASH_BLOCK_SIZE (1u << 16)\n\n#define BOOT2_SIZE_WORDS 64\n#define XIP_BASE 0x10000000\n\nstatic uint32_t boot2_copyout[BOOT2_SIZE_WORDS];\nstatic bool boot2_copyout_valid = false;\n\nstatic ram_func void flash_init_boot2_copyout() {\n\tif (boot2_copyout_valid)\n\t\t\treturn;\n\tfor (int i = 0; i < BOOT2_SIZE_WORDS; ++i)\n\t\t\tboot2_copyout[i] = ((uint32_t *)XIP_BASE)[i];\n\t__compiler_memory_barrier();\n\tboot2_copyout_valid = true;\n}\n\nstatic ram_func void flash_enable_xip_via_boot2() {\n\t((void (*)(void))boot2_copyout+1)();\n}\n\n#define IO_QSPI_BASE 0x40018000\n#define IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_BITS         0x00000300\n#define IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_MSB          9\n#define IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_LSB          8\n#define IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_VALUE_LOW    0x2\n#define IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_VALUE_HIGH   0x3\n\n#define XIP_SSI_BASE 0x18000000\n#define ssi_hw ((ssi_hw_t *)XIP_SSI_BASE)\n#define SSI_SR_OFFSET      0x00000028\n#define SSI_DR0_OFFSET     0x00000060\n#define SSI_SR_TFNF_BITS   0x00000002\n#define SSI_SR_RFNE_BITS   0x00000008\n\nvoid ram_func flash_cs_force(bool high) {\n    uint32_t field_val = high ?\n        IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_VALUE_HIGH :\n        IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_VALUE_LOW;\n\n\t// &ioqspi_hw->io[1].ctrl\n\tuint32_t *addr = (uint32_t*)(IO_QSPI_BASE + (1 * 8) + 4);\n\n\t*addr = ((*addr) & !IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_BITS)\n\t\t| (field_val << IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_LSB);\n\n}\n\n// See https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/hardware_flash/flash.c#L86\nvoid ram_func flash_range_write(uint32_t offset, const uint8_t *data, size_t count)\n{\n\tflash_range_program_fn flash_range_program_func = (flash_range_program_fn) rom_func_lookup(ROM_FUNC_FLASH_RANGE_PROGRAM);\n\tflash_connect_internal_fn flash_connect_internal_func = (flash_connect_internal_fn) rom_func_lookup(ROM_FUNC_CONNECT_INTERNAL_FLASH);\n\tflash_exit_xip_fn flash_exit_xip_func = (flash_exit_xip_fn) rom_func_lookup(ROM_FUNC_FLASH_EXIT_XIP);\n\tflash_flush_cache_fn flash_flush_cache_func = (flash_flush_cache_fn) rom_func_lookup(ROM_FUNC_FLASH_FLUSH_CACHE);\n\n\tflash_init_boot2_copyout();\n\n\t__compiler_memory_barrier();\n\n\tflash_connect_internal_func();\n\tflash_exit_xip_func();\n\n\tflash_range_program_func(offset, data, count);\n\tflash_flush_cache_func();\n\tflash_enable_xip_via_boot2();\n}\n\nvoid ram_func flash_erase_blocks(uint32_t offset, size_t count)\n{\n\tflash_range_erase_fn flash_range_erase_func = (flash_range_erase_fn) rom_func_lookup(ROM_FUNC_FLASH_RANGE_ERASE);\n\tflash_connect_internal_fn flash_connect_internal_func = (flash_connect_internal_fn) rom_func_lookup(ROM_FUNC_CONNECT_INTERNAL_FLASH);\n\tflash_exit_xip_fn flash_exit_xip_func = (flash_exit_xip_fn) rom_func_lookup(ROM_FUNC_FLASH_EXIT_XIP);\n\tflash_flush_cache_fn flash_flush_cache_func = (flash_flush_cache_fn) rom_func_lookup(ROM_FUNC_FLASH_FLUSH_CACHE);\n\n\tflash_init_boot2_copyout();\n\n\t__compiler_memory_barrier();\n\n\tflash_connect_internal_func();\n\tflash_exit_xip_func();\n\n\tflash_range_erase_func(offset, count, FLASH_BLOCK_SIZE, FLASH_BLOCK_ERASE_CMD);\n\tflash_flush_cache_func();\n\tflash_enable_xip_via_boot2();\n}\n\nvoid ram_func flash_do_cmd(const uint8_t *txbuf, uint8_t *rxbuf, size_t count) {\n\tflash_connect_internal_fn flash_connect_internal_func = (flash_connect_internal_fn) rom_func_lookup(ROM_FUNC_CONNECT_INTERNAL_FLASH);\n\tflash_exit_xip_fn flash_exit_xip_func = (flash_exit_xip_fn) rom_func_lookup(ROM_FUNC_FLASH_EXIT_XIP);\n\tflash_flush_cache_fn flash_flush_cache_func = (flash_flush_cache_fn) rom_func_lookup(ROM_FUNC_FLASH_FLUSH_CACHE);\n\n\tflash_init_boot2_copyout();\n\n\t__compiler_memory_barrier();\n\n\tflash_connect_internal_func();\n\tflash_exit_xip_func();\n\n\tflash_cs_force(0);\n\tsize_t tx_remaining = count;\n\tsize_t rx_remaining = count;\n\t// We may be interrupted -- don't want FIFO to overflow if we're distracted.\n\tconst size_t max_in_flight = 16 - 2;\n\twhile (tx_remaining || rx_remaining) {\n\t\tuint32_t flags = *(uint32_t*)(XIP_SSI_BASE + SSI_SR_OFFSET);\n\t\tbool can_put = !!(flags & SSI_SR_TFNF_BITS);\n\t\tbool can_get = !!(flags & SSI_SR_RFNE_BITS);\n\t\tif (can_put && tx_remaining && rx_remaining - tx_remaining < max_in_flight) {\n\t\t\t*(uint32_t*)(XIP_SSI_BASE + SSI_DR0_OFFSET) = *txbuf++;\n\t\t\t--tx_remaining;\n\t\t}\n\t\tif (can_get && rx_remaining) {\n\t\t\t*rxbuf++ = (uint8_t)*(uint32_t*)(XIP_SSI_BASE + SSI_DR0_OFFSET);\n\t\t\t--rx_remaining;\n\t\t}\n\t}\n\tflash_cs_force(1);\n\n\tflash_flush_cache_func();\n\tflash_enable_xip_via_boot2();\n}\n\n*/\nimport \"C\"\n\nfunc enterBootloader() {\n\tC.reset_usb_boot(0, 0)\n}\n\nfunc doFlashCommand(tx []byte, rx []byte) error {\n\tif len(tx) != len(rx) {\n\t\treturn errFlashInvalidWriteLength\n\t}\n\n\tC.flash_do_cmd(\n\t\t(*C.uint8_t)(unsafe.Pointer(&tx[0])),\n\t\t(*C.uint8_t)(unsafe.Pointer(&rx[0])),\n\t\tC.ulong(len(tx)))\n\n\treturn nil\n}\n\n// Flash related code\nconst memoryStart = C.XIP_BASE // memory start for purpose of erase\n\nfunc (f flashBlockDevice) writeAt(p []byte, off int64) (n int, err error) {\n\tif writeAddress(off)+uintptr(C.XIP_BASE) > FlashDataEnd() {\n\t\treturn 0, errFlashCannotWritePastEOF\n\t}\n\n\tstate := interrupt.Disable()\n\tdefer interrupt.Restore(state)\n\n\t// rp2040 writes to offset, not actual address\n\t// e.g. real address 0x10003000 is written to at\n\t// 0x00003000\n\taddress := writeAddress(off)\n\tpadded := flashPad(p, int(f.WriteBlockSize()))\n\n\tC.flash_range_write(C.uint32_t(address),\n\t\t(*C.uint8_t)(unsafe.Pointer(&padded[0])),\n\t\tC.ulong(len(padded)))\n\n\treturn len(padded), nil\n}\n\nfunc (f flashBlockDevice) eraseBlocks(start, length int64) error {\n\taddress := writeAddress(start * f.EraseBlockSize())\n\tif address+uintptr(C.XIP_BASE) > FlashDataEnd() {\n\t\treturn errFlashCannotErasePastEOF\n\t}\n\n\tstate := interrupt.Disable()\n\tdefer interrupt.Restore(state)\n\n\tC.flash_erase_blocks(C.uint32_t(address), C.ulong(length*f.EraseBlockSize()))\n\n\treturn nil\n}\n"
  },
  {
    "path": "src/machine/machine_rp2040_rtc.go",
    "content": "//go:build rp2040\n\n// Implementation based on code located here:\n// https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/hardware_rtc/rtc.c\n\npackage machine\n\nimport (\n\t\"device/rp\"\n\t\"errors\"\n\t\"runtime/interrupt\"\n\t\"unsafe\"\n)\n\ntype rtcType rp.RTC_Type\n\ntype rtcTime struct {\n\tYear  int16\n\tMonth int8\n\tDay   int8\n\tDotw  int8\n\tHour  int8\n\tMin   int8\n\tSec   int8\n}\n\nvar RTC = (*rtcType)(unsafe.Pointer(rp.RTC))\n\nconst (\n\tsecond = 1\n\tminute = 60 * second\n\thour   = 60 * minute\n\tday    = 24 * hour\n)\n\nvar (\n\trtcAlarmRepeats bool\n\trtcCallback     func()\n\trtcEpoch        = rtcTime{\n\t\tYear: 1970, Month: 1, Day: 1, Dotw: 4, Hour: 0, Min: 0, Sec: 0,\n\t}\n)\n\nvar (\n\tErrRtcDelayTooSmall = errors.New(\"RTC interrupt deplay is too small, shall be at least 1 second\")\n\tErrRtcDelayTooLarge = errors.New(\"RTC interrupt deplay is too large, shall be no more than 1 day\")\n)\n\n// SetInterrupt configures delayed and optionally recurring interrupt by real time clock.\n//\n// Delay is specified in whole seconds, allowed range depends on platform.\n// Zero delay disables previously configured interrupt, if any.\n//\n// RP2040 implementation allows delay to be up to 1 day, otherwise a respective error is emitted.\nfunc (rtc *rtcType) SetInterrupt(delay uint32, repeat bool, callback func()) error {\n\n\t// Verify delay range\n\tif delay > day {\n\t\treturn ErrRtcDelayTooLarge\n\t}\n\n\t// De-configure delayed interrupt if delay is zero\n\tif delay == 0 {\n\t\trtc.disableInterruptMatch()\n\t\treturn nil\n\t}\n\n\t// Configure delayed interrupt\n\trtc.setDivider()\n\n\trtcAlarmRepeats = repeat\n\trtcCallback = callback\n\n\terr := rtc.setTime(rtcEpoch)\n\tif err != nil {\n\t\treturn err\n\t}\n\trtc.setAlarm(toAlarmTime(delay), callback)\n\n\treturn nil\n}\n\nfunc toAlarmTime(delay uint32) rtcTime {\n\tresult := rtcEpoch\n\tremainder := delay + 1 // needed \"+1\", otherwise alarm fires one second too early\n\tif remainder >= hour {\n\t\tresult.Hour = int8(remainder / hour)\n\t\tremainder %= hour\n\t}\n\tif remainder >= minute {\n\t\tresult.Min = int8(remainder / minute)\n\t\tremainder %= minute\n\t}\n\tresult.Sec = int8(remainder)\n\treturn result\n}\n\nfunc (rtc *rtcType) setDivider() {\n\t// Get clk_rtc freq and make sure it is running\n\trtcFreq := configuredFreq[clkRTC]\n\tif rtcFreq == 0 {\n\t\tpanic(\"can not set RTC divider, clock is not running\")\n\t}\n\n\t// Take rtc out of reset now that we know clk_rtc is running\n\tresetBlock(rp.RESETS_RESET_RTC)\n\tunresetBlockWait(rp.RESETS_RESET_RTC)\n\n\t// Set up the 1 second divider.\n\t// If rtc_freq is 400 then clkdiv_m1 should be 399\n\trtcFreq -= 1\n\n\t// Check the freq is not too big to divide\n\tif rtcFreq > rp.RTC_CLKDIV_M1_CLKDIV_M1_Msk {\n\t\tpanic(\"can not set RTC divider, clock frequency is too big to divide\")\n\t}\n\n\t// Write divide value\n\trtc.CLKDIV_M1.Set(rtcFreq)\n}\n\n// setTime configures RTC with supplied time, initialises and activates it.\nfunc (rtc *rtcType) setTime(t rtcTime) error {\n\n\t// Disable RTC and wait while it is still running\n\trtc.CTRL.Set(0)\n\tfor rtc.isActive() {\n\t}\n\n\trtc.SETUP_0.Set((uint32(t.Year) << rp.RTC_SETUP_0_YEAR_Pos) |\n\t\t(uint32(t.Month) << rp.RTC_SETUP_0_MONTH_Pos) |\n\t\t(uint32(t.Day) << rp.RTC_SETUP_0_DAY_Pos))\n\n\trtc.SETUP_1.Set((uint32(t.Dotw) << rp.RTC_SETUP_1_DOTW_Pos) |\n\t\t(uint32(t.Hour) << rp.RTC_SETUP_1_HOUR_Pos) |\n\t\t(uint32(t.Min) << rp.RTC_SETUP_1_MIN_Pos) |\n\t\t(uint32(t.Sec) << rp.RTC_SETUP_1_SEC_Pos))\n\n\t// Load setup values into RTC clock domain\n\trtc.CTRL.SetBits(rp.RTC_CTRL_LOAD)\n\n\t// Enable RTC and wait for it to be running\n\trtc.CTRL.SetBits(rp.RTC_CTRL_RTC_ENABLE)\n\tfor !rtc.isActive() {\n\t}\n\n\treturn nil\n}\n\nfunc (rtc *rtcType) isActive() bool {\n\treturn rtc.CTRL.HasBits(rp.RTC_CTRL_RTC_ACTIVE)\n}\n\n// setAlarm configures alarm in RTC and arms it.\n// The callback is executed in the context of an interrupt handler,\n// so regular restructions for this sort of code apply: no blocking, no memory allocation, etc.\nfunc (rtc *rtcType) setAlarm(t rtcTime, callback func()) {\n\n\trtc.disableInterruptMatch()\n\n\t// Clear all match enable bits\n\trtc.IRQ_SETUP_0.ClearBits(rp.RTC_IRQ_SETUP_0_YEAR_ENA | rp.RTC_IRQ_SETUP_0_MONTH_ENA | rp.RTC_IRQ_SETUP_0_DAY_ENA)\n\trtc.IRQ_SETUP_1.ClearBits(rp.RTC_IRQ_SETUP_1_DOTW_ENA | rp.RTC_IRQ_SETUP_1_HOUR_ENA | rp.RTC_IRQ_SETUP_1_MIN_ENA | rp.RTC_IRQ_SETUP_1_SEC_ENA)\n\n\t// Only add to setup if it isn't -1 and set the match enable bits for things we care about\n\tif t.Year >= 0 {\n\t\trtc.IRQ_SETUP_0.SetBits(uint32(t.Year) << rp.RTC_SETUP_0_YEAR_Pos)\n\t\trtc.IRQ_SETUP_0.SetBits(rp.RTC_IRQ_SETUP_0_YEAR_ENA)\n\t}\n\n\tif t.Month >= 0 {\n\t\trtc.IRQ_SETUP_0.SetBits(uint32(t.Month) << rp.RTC_SETUP_0_MONTH_Pos)\n\t\trtc.IRQ_SETUP_0.SetBits(rp.RTC_IRQ_SETUP_0_MONTH_ENA)\n\t}\n\n\tif t.Day >= 0 {\n\t\trtc.IRQ_SETUP_0.SetBits(uint32(t.Day) << rp.RTC_SETUP_0_DAY_Pos)\n\t\trtc.IRQ_SETUP_0.SetBits(rp.RTC_IRQ_SETUP_0_DAY_ENA)\n\t}\n\n\tif t.Dotw >= 0 {\n\t\trtc.IRQ_SETUP_1.SetBits(uint32(t.Dotw) << rp.RTC_SETUP_1_DOTW_Pos)\n\t\trtc.IRQ_SETUP_1.SetBits(rp.RTC_IRQ_SETUP_1_DOTW_ENA)\n\t}\n\n\tif t.Hour >= 0 {\n\t\trtc.IRQ_SETUP_1.SetBits(uint32(t.Hour) << rp.RTC_SETUP_1_HOUR_Pos)\n\t\trtc.IRQ_SETUP_1.SetBits(rp.RTC_IRQ_SETUP_1_HOUR_ENA)\n\t}\n\n\tif t.Min >= 0 {\n\t\trtc.IRQ_SETUP_1.SetBits(uint32(t.Min) << rp.RTC_SETUP_1_MIN_Pos)\n\t\trtc.IRQ_SETUP_1.SetBits(rp.RTC_IRQ_SETUP_1_MIN_ENA)\n\t}\n\n\tif t.Sec >= 0 {\n\t\trtc.IRQ_SETUP_1.SetBits(uint32(t.Sec) << rp.RTC_SETUP_1_SEC_Pos)\n\t\trtc.IRQ_SETUP_1.SetBits(rp.RTC_IRQ_SETUP_1_SEC_ENA)\n\t}\n\n\t// Enable the IRQ at the proc\n\tinterrupt.New(rp.IRQ_RTC_IRQ, rtcHandleInterrupt).Enable()\n\n\t// Enable the IRQ at the peri\n\trtc.INTE.Set(rp.RTC_INTE_RTC)\n\n\trtc.enableInterruptMatch()\n}\n\nfunc (rtc *rtcType) enableInterruptMatch() {\n\t// Set matching and wait for it to be enabled\n\trtc.IRQ_SETUP_0.SetBits(rp.RTC_IRQ_SETUP_0_MATCH_ENA)\n\tfor !rtc.IRQ_SETUP_0.HasBits(rp.RTC_IRQ_SETUP_0_MATCH_ACTIVE) {\n\t}\n}\n\nfunc (rtc *rtcType) disableInterruptMatch() {\n\t// Disable matching and wait for it to stop being active\n\trtc.IRQ_SETUP_0.ClearBits(rp.RTC_IRQ_SETUP_0_MATCH_ENA)\n\tfor rtc.IRQ_SETUP_0.HasBits(rp.RTC_IRQ_SETUP_0_MATCH_ACTIVE) {\n\t}\n}\n\nfunc rtcHandleInterrupt(itr interrupt.Interrupt) {\n\t// Always disable the alarm to clear the current IRQ.\n\t// Even if it is a repeatable alarm, we don't want it to keep firing.\n\t// If it matches on a second it can keep firing for that second.\n\tRTC.disableInterruptMatch()\n\n\t// Call user callback function\n\tif rtcCallback != nil {\n\t\trtcCallback()\n\t}\n\n\tif rtcAlarmRepeats {\n\t\t// If it is a repeatable alarm, reset time and re-enable the alarm.\n\t\tRTC.setTime(rtcEpoch)\n\t\tRTC.enableInterruptMatch()\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_rp2040_simulator.go",
    "content": "//go:build !baremetal && (ae_rp2040 || badger2040_w || badger2040 || challenger_rp2040 || elecrow_rp2040 || feather_rp2040 || gopher_badge || kb2040 || macropad_rp2040 || nano_rp2040 || pico || qtpy_rp2040 || thingplus_rp2040 || thumby || trinkey_qt2040 || tufty2040 || waveshare_rp2040_tiny || waveshare_rp2040_zero || xiao_rp2040)\n\n// Simulator support for the RP2040.\n//\n// This is *only* for the RP2040. RP2350 is a different chip with slightly\n// different characteristics.\n\npackage machine\n\nvar PWM0 = &timerType{\n\tinstance:   0,\n\tfrequency:  200e6,\n\tbits:       16,\n\tprescalers: []int{1, 2, 4, 8, 16, 32, 64, 128, 256}, // actually a continuing range, TODO\n\tchannelPins: [][]Pin{\n\t\t{GPIO0, GPIO16}, // channel A (0)\n\t\t{GPIO1, GPIO17}, // channel B (1)\n\t},\n}\n\nvar PWM1 = &timerType{\n\tinstance:   0,\n\tfrequency:  200e6,\n\tbits:       16,\n\tprescalers: []int{1, 2, 4, 8, 16, 32, 64, 128, 256},\n\tchannelPins: [][]Pin{\n\t\t{GPIO2, GPIO18}, // channel A (0)\n\t\t{GPIO3, GPIO19}, // channel B (1)\n\t},\n}\n\nvar PWM2 = &timerType{\n\tinstance:   0,\n\tfrequency:  200e6,\n\tbits:       16,\n\tprescalers: []int{1, 2, 4, 8, 16, 32, 64, 128, 256},\n\tchannelPins: [][]Pin{\n\t\t{GPIO4, GPIO20}, // channel A (0)\n\t\t{GPIO5, GPIO21}, // channel B (1)\n\t},\n}\n\nvar PWM3 = &timerType{\n\tinstance:   0,\n\tfrequency:  200e6,\n\tbits:       16,\n\tprescalers: []int{1, 2, 4, 8, 16, 32, 64, 128, 256},\n\tchannelPins: [][]Pin{\n\t\t{GPIO6, GPIO22}, // channel A (0)\n\t\t{GPIO7, GPIO23}, // channel B (1)\n\t},\n}\n\nvar PWM4 = &timerType{\n\tinstance:   0,\n\tfrequency:  200e6,\n\tbits:       16,\n\tprescalers: []int{1, 2, 4, 8, 16, 32, 64, 128, 256},\n\tchannelPins: [][]Pin{\n\t\t{GPIO8, GPIO24}, // channel A (0)\n\t\t{GPIO9, GPIO25}, // channel B (1)\n\t},\n}\n\nvar PWM5 = &timerType{\n\tinstance:   0,\n\tfrequency:  200e6,\n\tbits:       16,\n\tprescalers: []int{1, 2, 4, 8, 16, 32, 64, 128, 256},\n\tchannelPins: [][]Pin{\n\t\t{GPIO10, GPIO26}, // channel A (0)\n\t\t{GPIO11, GPIO27}, // channel B (1)\n\t},\n}\n\nvar PWM6 = &timerType{\n\tinstance:   0,\n\tfrequency:  200e6,\n\tbits:       16,\n\tprescalers: []int{1, 2, 4, 8, 16, 32, 64, 128, 256},\n\tchannelPins: [][]Pin{\n\t\t{GPIO12, GPIO28}, // channel A (0)\n\t\t{GPIO13, GPIO29}, // channel B (1)\n\t},\n}\n\nvar PWM7 = &timerType{\n\tinstance:   0,\n\tfrequency:  200e6,\n\tbits:       16,\n\tprescalers: []int{1, 2, 4, 8, 16, 32, 64, 128, 256},\n\tchannelPins: [][]Pin{\n\t\t{GPIO14}, // channel A (0)\n\t\t{GPIO15}, // channel B (1)\n\t},\n}\n\nvar I2C0 = &I2C{\n\tBus:     0,\n\tPinsSCL: []Pin{GPIO1, GPIO5, GPIO9, GPIO13, GPIO17, GPIO21},\n\tPinsSDA: []Pin{GPIO0, GPIO4, GPIO8, GPIO12, GPIO16, GPIO20},\n}\n\nvar I2C1 = &I2C{\n\tBus:     0,\n\tPinsSCL: []Pin{GPIO3, GPIO7, GPIO11, GPIO15, GPIO19, GPIO27},\n\tPinsSDA: []Pin{GPIO2, GPIO6, GPIO10, GPIO14, GPIO18, GPIO26},\n}\n"
  },
  {
    "path": "src/machine/machine_rp2040_usb.go",
    "content": "//go:build rp2040\n\npackage machine\n\nimport (\n\t\"device/rp\"\n\t\"machine/usb\"\n\t\"runtime/interrupt\"\n)\n\n// Configure the USB peripheral. The config is here for compatibility with the UART interface.\nfunc (dev *USBDevice) Configure(config UARTConfig) {\n\t// Reset usb controller\n\tresetBlock(rp.RESETS_RESET_USBCTRL)\n\tunresetBlockWait(rp.RESETS_RESET_USBCTRL)\n\n\t// Clear any previous state in dpram just in case\n\t_usbDPSRAM.clear()\n\n\t// Enable USB interrupt at processor\n\trp.USBCTRL_REGS.INTE.Set(0)\n\tintr := interrupt.New(rp.IRQ_USBCTRL_IRQ, handleUSBIRQ)\n\tintr.SetPriority(0x00)\n\tintr.Enable()\n\tirqSet(rp.IRQ_USBCTRL_IRQ, true)\n\n\t// Mux the controller to the onboard usb phy\n\trp.USBCTRL_REGS.USB_MUXING.Set(rp.USBCTRL_REGS_USB_MUXING_TO_PHY | rp.USBCTRL_REGS_USB_MUXING_SOFTCON)\n\n\t// Force VBUS detect so the device thinks it is plugged into a host\n\trp.USBCTRL_REGS.USB_PWR.Set(rp.USBCTRL_REGS_USB_PWR_VBUS_DETECT | rp.USBCTRL_REGS_USB_PWR_VBUS_DETECT_OVERRIDE_EN)\n\n\t// Enable the USB controller in device mode.\n\trp.USBCTRL_REGS.MAIN_CTRL.Set(rp.USBCTRL_REGS_MAIN_CTRL_CONTROLLER_EN)\n\n\t// Enable an interrupt per EP0 transaction\n\trp.USBCTRL_REGS.SIE_CTRL.Set(rp.USBCTRL_REGS_SIE_CTRL_EP0_INT_1BUF)\n\n\t// Enable interrupts for when a buffer is done, when the bus is reset,\n\t// and when a setup packet is received\n\trp.USBCTRL_REGS.INTE.Set(rp.USBCTRL_REGS_INTE_BUFF_STATUS |\n\t\trp.USBCTRL_REGS_INTE_BUS_RESET |\n\t\trp.USBCTRL_REGS_INTE_SETUP_REQ)\n\n\t// Present full speed device by enabling pull up on DP\n\trp.USBCTRL_REGS.SIE_CTRL.SetBits(rp.USBCTRL_REGS_SIE_CTRL_PULLUP_EN)\n}\n\nfunc handleUSBIRQ(intr interrupt.Interrupt) {\n\tstatus := rp.USBCTRL_REGS.INTS.Get()\n\n\t// Setup packet received\n\tif (status & rp.USBCTRL_REGS_INTS_SETUP_REQ) > 0 {\n\t\trp.USBCTRL_REGS.SIE_STATUS.Set(rp.USBCTRL_REGS_SIE_STATUS_SETUP_REC)\n\t\tsetup := usb.NewSetup(_usbDPSRAM.setupBytes())\n\n\t\tok := false\n\t\tif (setup.BmRequestType & usb.REQUEST_TYPE) == usb.REQUEST_STANDARD {\n\t\t\t// Standard Requests\n\t\t\tok = handleStandardSetup(setup)\n\t\t} else {\n\t\t\t// Class Interface Requests\n\t\t\tif setup.WIndex < uint16(len(usbSetupHandler)) && usbSetupHandler[setup.WIndex] != nil {\n\t\t\t\tok = usbSetupHandler[setup.WIndex](setup)\n\t\t\t}\n\t\t}\n\n\t\tif !ok {\n\t\t\t// Stall endpoint?\n\t\t\tUSBDev.SetStallEPIn(0)\n\t\t}\n\n\t}\n\n\t// Buffer status, one or more buffers have completed\n\tif (status & rp.USBCTRL_REGS_INTS_BUFF_STATUS) > 0 {\n\t\tif sendOnEP0DATADONE.offset > 0 {\n\t\t\tep := uint32(0)\n\t\t\tdata := sendOnEP0DATADONE.data\n\t\t\tcount := len(data) - sendOnEP0DATADONE.offset\n\t\t\tif ep == 0 && count > usb.EndpointPacketSize {\n\t\t\t\tcount = usb.EndpointPacketSize\n\t\t\t}\n\n\t\t\tsendViaEPIn(ep, data[sendOnEP0DATADONE.offset:], count)\n\t\t\tsendOnEP0DATADONE.offset += count\n\t\t\tif sendOnEP0DATADONE.offset == len(data) {\n\t\t\t\tsendOnEP0DATADONE.offset = 0\n\t\t\t}\n\t\t}\n\n\t\ts2 := rp.USBCTRL_REGS.BUFF_STATUS.Get()\n\n\t\t// OUT (PC -> rp2040)\n\t\tfor i := 0; i < 16; i++ {\n\t\t\tif s2&(1<<(i*2+1)) > 0 {\n\t\t\t\tbuf := handleEndpointRx(uint32(i))\n\t\t\t\tif usbRxHandler[i] == nil || usbRxHandler[i](buf) {\n\t\t\t\t\tAckUsbOutTransfer(uint32(i))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// IN (rp2040 -> PC)\n\t\tfor i := 0; i < 16; i++ {\n\t\t\tif s2&(1<<(i*2)) > 0 {\n\t\t\t\tif usbTxHandler[i] != nil {\n\t\t\t\t\tusbTxHandler[i]()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\trp.USBCTRL_REGS.BUFF_STATUS.Set(s2)\n\t}\n\n\t// Bus is reset\n\tif (status & rp.USBCTRL_REGS_INTS_BUS_RESET) > 0 {\n\t\trp.USBCTRL_REGS.SIE_STATUS.Set(rp.USBCTRL_REGS_SIE_STATUS_BUS_RESET)\n\t\tfixRP2040UsbDeviceEnumeration()\n\n\t\trp.USBCTRL_REGS.ADDR_ENDP.Set(0)\n\t\tinitEndpoint(0, usb.ENDPOINT_TYPE_CONTROL)\n\t}\n}\n\nfunc handleUSBSetAddress(setup usb.Setup) bool {\n\t// Using 570μs timeout which is exactly the same as SAMD21.\n\tconst ackTimeout = 570\n\n\trp.USBCTRL_REGS.SIE_STATUS.Set(rp.USBCTRL_REGS_SIE_STATUS_ACK_REC)\n\tsendUSBPacket(0, []byte{}, 0)\n\n\t// Wait for transfer to complete with a timeout.\n\tt := timer.timeElapsed()\n\tfor (rp.USBCTRL_REGS.SIE_STATUS.Get() & rp.USBCTRL_REGS_SIE_STATUS_ACK_REC) == 0 {\n\t\tif dt := timer.timeElapsed() - t; dt >= ackTimeout {\n\t\t\treturn false\n\t\t}\n\t}\n\n\t// Set the device address to that requested by host.\n\trp.USBCTRL_REGS.ADDR_ENDP.Set(uint32(setup.WValueL) & rp.USBCTRL_REGS_ADDR_ENDP_ADDRESS_Msk)\n\treturn true\n}\n\nfunc armEPZeroStall() {\n\trp.USBCTRL_REGS.EP_STALL_ARM.Set(rp.USBCTRL_REGS_EP_STALL_ARM_EP0_IN)\n}\n"
  },
  {
    "path": "src/machine/machine_rp2040_usb_fix_usb_device_enumeration.go",
    "content": "//go:build rp2040\n\npackage machine\n\nimport (\n\t\"device/arm\"\n\t\"device/rp\"\n)\n\n// https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/pico_fix/rp2040_usb_device_enumeration/rp2040_usb_device_enumeration.c\n// According to errata RP2040-E5:\n// \"It is safe (and inexpensive) to enable the software workaround even when using versions of RP2040\n// which include the fix in hardware.\"\n// So let us always use the software fix.\nfunc fixRP2040UsbDeviceEnumeration() {\n\t// After coming out of reset, the hardware expects 800us of LS_J (linestate J) time\n\t// before it will move to the connected state. However on a hub that broadcasts packets\n\t// for other devices this isn't the case. The plan here is to wait for the end of the bus\n\t// reset, force an LS_J for 1ms and then switch control back to the USB phy. Unfortunately\n\t// this requires us to use GPIO15 as there is no other way to force the input path.\n\t// We only need to force DP as DM can be left at zero. It will be gated off by GPIO\n\t// logic if it isn't func selected.\n\n\t// Wait SE0 phase will call force ls_j phase which will call finish phase\n\thw_enumeration_fix_wait_se0()\n}\n\nfunc hw_enumeration_fix_wait_se0() {\n\t// Wait for SE0 to end (i.e. the host to stop resetting). This reset can last quite long.\n\t// 10-15ms so we are going to set a timer callback.\n\n\t// if timer pool disabled, or no timer available, have to busy wait.\n\thw_enumeration_fix_busy_wait_se0()\n}\n\nconst (\n\tLS_SE0 = 0b00\n\tLS_J   = 0b01\n\tLS_K   = 0b10\n\tLS_SE1 = 0b11\n)\n\nconst (\n\tdp = 15\n)\n\nvar (\n\tgpioCtrlPrev uint32\n\tpadCtrlPrev  uint32\n)\n\nfunc hw_enumeration_fix_busy_wait_se0() {\n\tfor ((rp.USBCTRL_REGS.SIE_STATUS.Get() & rp.USBCTRL_REGS_SIE_STATUS_LINE_STATE_Msk) >> rp.USBCTRL_REGS_SIE_STATUS_LINE_STATE_Pos) == LS_SE0 {\n\t}\n\n\t// Now force LS_J (next stage of fix)\n\thw_enumeration_fix_force_ls_j()\n}\n\nfunc hw_enumeration_fix_force_ls_j() {\n\t// DM must be 0 for this to work. This is true if it is selected\n\t// to any other function. fn 8 on this pin is only for debug so shouldn't\n\t// be selected\n\n\t// Before changing any pin state, take a copy of the current gpio control register\n\tgpioCtrlPrev = ioBank0.io[dp].ctrl.Get()\n\t// Also take a copy of the pads register\n\tpadCtrlPrev = padsBank0.io[dp].Get()\n\n\t// Enable bus keep and force pin to tristate, so USB DP muxing doesn't affect\n\t// pin state\n\tpadsBank0.io[dp].SetBits(rp.PADS_BANK0_GPIO0_PUE | rp.PADS_BANK0_GPIO0_PDE)\n\tioBank0.io[dp].ctrl.ReplaceBits(rp.IO_BANK0_GPIO0_CTRL_OEOVER_DISABLE, rp.IO_BANK0_GPIO0_CTRL_OEOVER_Msk>>rp.IO_BANK0_GPIO0_CTRL_OEOVER_Pos, rp.IO_BANK0_GPIO0_CTRL_OEOVER_Pos)\n\n\t// Select function 8 (USB debug muxing) without disturbing other controls\n\tioBank0.io[dp].ctrl.ReplaceBits(8, rp.IO_BANK0_GPIO0_CTRL_FUNCSEL_Msk>>rp.IO_BANK0_GPIO0_CTRL_FUNCSEL_Pos, rp.IO_BANK0_GPIO0_CTRL_FUNCSEL_Pos)\n\n\t// J state is a differential 1 for a full speed device so\n\t// DP = 1 and DM = 0. Don't actually need to set DM low as it\n\t// is already gated assuming it isn't funcseld.\n\tioBank0.io[dp].ctrl.ReplaceBits(rp.IO_BANK0_GPIO1_CTRL_INOVER_HIGH, rp.IO_BANK0_GPIO1_CTRL_INOVER_Msk>>rp.IO_BANK0_GPIO1_CTRL_INOVER_Pos, rp.IO_BANK0_GPIO1_CTRL_INOVER_Pos)\n\n\t// Force PHY pull up to stay before switching away from the phy\n\trp.USBCTRL_REGS.USBPHY_DIRECT.SetBits(rp.USBCTRL_REGS_USBPHY_DIRECT_DP_PULLUP_EN)\n\trp.USBCTRL_REGS.USBPHY_DIRECT_OVERRIDE.SetBits(rp.USBCTRL_REGS_USBPHY_DIRECT_OVERRIDE_DP_PULLUP_EN_OVERRIDE_EN)\n\n\t// Switch to GPIO phy with LS_J forced\n\trp.USBCTRL_REGS.USB_MUXING.Set(rp.USBCTRL_REGS_USB_MUXING_TO_DIGITAL_PAD | rp.USBCTRL_REGS_USB_MUXING_SOFTCON)\n\n\t// LS_J is now forced but while loop to wait ~800us here just to check\n\twaitCycles(25000)\n\n\t// if timer pool disabled, or no timer available, have to busy wait.\n\thw_enumeration_fix_finish()\n\n}\n\nfunc hw_enumeration_fix_finish() {\n\t// Should think we are connected now\n\tfor (rp.USBCTRL_REGS.SIE_STATUS.Get() & rp.USBCTRL_REGS_SIE_STATUS_CONNECTED) != rp.USBCTRL_REGS_SIE_STATUS_CONNECTED {\n\t}\n\n\t// Switch back to USB phy\n\trp.USBCTRL_REGS.USB_MUXING.Set(rp.USBCTRL_REGS_USB_MUXING_TO_PHY | rp.USBCTRL_REGS_USB_MUXING_SOFTCON)\n\n\t// Get rid of DP pullup override\n\trp.USBCTRL_REGS.USBPHY_DIRECT_OVERRIDE.ClearBits(rp.USBCTRL_REGS_USBPHY_DIRECT_OVERRIDE_DP_PULLUP_EN_OVERRIDE_EN)\n\n\t// Finally, restore the gpio ctrl value back to GPIO15\n\tioBank0.io[dp].ctrl.Set(gpioCtrlPrev)\n\t// Restore the pad ctrl value\n\tpadsBank0.io[dp].Set(padCtrlPrev)\n}\n\nfunc waitCycles(n int) {\n\tfor n > 0 {\n\t\tarm.Asm(\"nop\")\n\t\tn--\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_rp2350_rom.go",
    "content": "//go:build tinygo && rp2350\n\npackage machine\n\nimport (\n\t\"runtime/interrupt\"\n\t\"unsafe\"\n)\n\n/*\ntypedef unsigned char uint8_t;\ntypedef unsigned short uint16_t;\ntypedef unsigned long uint32_t;\ntypedef unsigned long size_t;\ntypedef unsigned long uintptr_t;\ntypedef long int intptr_t;\n\ntypedef const volatile uint16_t io_ro_16;\ntypedef const volatile uint32_t io_ro_32;\ntypedef volatile uint16_t io_rw_16;\ntypedef volatile uint32_t io_rw_32;\ntypedef volatile uint32_t io_wo_32;\n\n#define false 0\n#define true 1\ntypedef int bool;\n\n#define ram_func __attribute__((section(\".ramfuncs\"),noinline))\n\ntypedef void (*flash_exit_xip_fn)(void);\ntypedef void (*flash_flush_cache_fn)(void);\ntypedef void (*flash_connect_internal_fn)(void);\ntypedef void (*flash_range_erase_fn)(uint32_t, size_t, uint32_t, uint16_t);\ntypedef void (*flash_range_program_fn)(uint32_t, const uint8_t*, size_t);\nstatic inline __attribute__((always_inline)) void __compiler_memory_barrier(void) {\n    __asm__ volatile (\"\" : : : \"memory\");\n}\n\n// https://datasheets.raspberrypi.com/rp2350/rp2350-datasheet.pdf\n// 13.9. Predefined OTP Data Locations\n// OTP_DATA: FLASH_DEVINFO Register\n\n#define OTP_DATA_FLASH_DEVINFO_CS0_SIZE_BITS 0x0F00\n#define OTP_DATA_FLASH_DEVINFO_CS0_SIZE_LSB  8\n#define OTP_DATA_FLASH_DEVINFO_CS1_SIZE_BITS 0xF000\n#define OTP_DATA_FLASH_DEVINFO_CS1_SIZE_LSB  12\n\n\n// https://github.com/raspberrypi/pico-sdk\n// src/rp2350/hardware_regs/include/hardware/regs/addressmap.h\n\n#define REG_ALIAS_RW_BITS  (0x0 << 12)\n#define REG_ALIAS_XOR_BITS (0x1 << 12)\n#define REG_ALIAS_SET_BITS (0x2 << 12)\n#define REG_ALIAS_CLR_BITS (0x3 << 12)\n\n#define XIP_BASE     0x10000000\n#define XIP_QMI_BASE 0x400d0000\n#define IO_QSPI_BASE 0x40030000\n#define BOOTRAM_BASE 0x400e0000\n\n\n// https://github.com/raspberrypi/pico-sdk\n// src/rp2_common/hardware_base/include/hardware/address_mapped.h\n\n#define hw_alias_check_addr(addr) ((uintptr_t)(addr))\n#define hw_set_alias_untyped(addr) ((void *)(REG_ALIAS_SET_BITS + hw_alias_check_addr(addr)))\n#define hw_clear_alias_untyped(addr) ((void *)(REG_ALIAS_CLR_BITS + hw_alias_check_addr(addr)))\n#define hw_xor_alias_untyped(addr) ((void *)(REG_ALIAS_XOR_BITS + hw_alias_check_addr(addr)))\n\n__attribute__((always_inline))\nstatic void hw_set_bits(io_rw_32 *addr, uint32_t mask) {\n    *(io_rw_32 *) hw_set_alias_untyped((volatile void *) addr) = mask;\n}\n\n__attribute__((always_inline))\nstatic void hw_clear_bits(io_rw_32 *addr, uint32_t mask) {\n    *(io_rw_32 *) hw_clear_alias_untyped((volatile void *) addr) = mask;\n}\n\n__attribute__((always_inline))\nstatic void hw_xor_bits(io_rw_32 *addr, uint32_t mask) {\n    *(io_rw_32 *) hw_xor_alias_untyped((volatile void *) addr) = mask;\n}\n\n__attribute__((always_inline))\nstatic void hw_write_masked(io_rw_32 *addr, uint32_t values, uint32_t write_mask) {\n    hw_xor_bits(addr, (*addr ^ values) & write_mask);\n}\n\n\n// https://github.com/raspberrypi/pico-sdk\n// src/rp2_common/pico_platform_compiler/include/pico/platform/compiler.h\n\n#define pico_default_asm_volatile(...) __asm volatile (\".syntax unified\\n\" __VA_ARGS__)\n\n\n// https://github.com/raspberrypi/pico-sdk\n// src/rp2350/pico_platform/include/pico/platform.h\n\nstatic bool pico_processor_state_is_nonsecure(void) {\n//    // todo add a define to disable NS checking at all?\n//    // IDAU-Exempt addresses return S=1 when tested in the Secure state,\n//    // whereas executing a tt in the NonSecure state will always return S=0.\n//    uint32_t tt;\n//    pico_default_asm_volatile (\n//        \"movs %0, #0\\n\"\n//        \"tt %0, %0\\n\"\n//        : \"=r\" (tt) : : \"cc\"\n//    );\n//    return !(tt & (1u << 22));\n\n    return false;\n}\n\n\n// https://github.com/raspberrypi/pico-sdk\n// src/rp2_common/pico_bootrom/include/pico/bootrom_constants.h\n\n// RP2040 & RP2350\n#define ROM_DATA_SOFTWARE_GIT_REVISION          ROM_TABLE_CODE('G', 'R')\n#define ROM_FUNC_FLASH_ENTER_CMD_XIP            ROM_TABLE_CODE('C', 'X')\n#define ROM_FUNC_FLASH_EXIT_XIP                 ROM_TABLE_CODE('E', 'X')\n#define ROM_FUNC_FLASH_FLUSH_CACHE              ROM_TABLE_CODE('F', 'C')\n#define ROM_FUNC_CONNECT_INTERNAL_FLASH         ROM_TABLE_CODE('I', 'F')\n#define ROM_FUNC_FLASH_RANGE_ERASE              ROM_TABLE_CODE('R', 'E')\n#define ROM_FUNC_FLASH_RANGE_PROGRAM            ROM_TABLE_CODE('R', 'P')\n\n// RP2350 only\n#define ROM_FUNC_PICK_AB_PARTITION              ROM_TABLE_CODE('A', 'B')\n#define ROM_FUNC_CHAIN_IMAGE                    ROM_TABLE_CODE('C', 'I')\n#define ROM_FUNC_EXPLICIT_BUY                   ROM_TABLE_CODE('E', 'B')\n#define ROM_FUNC_FLASH_RUNTIME_TO_STORAGE_ADDR  ROM_TABLE_CODE('F', 'A')\n#define ROM_DATA_FLASH_DEVINFO16_PTR            ROM_TABLE_CODE('F', 'D')\n#define ROM_FUNC_FLASH_OP                       ROM_TABLE_CODE('F', 'O')\n#define ROM_FUNC_GET_B_PARTITION                ROM_TABLE_CODE('G', 'B')\n#define ROM_FUNC_GET_PARTITION_TABLE_INFO       ROM_TABLE_CODE('G', 'P')\n#define ROM_FUNC_GET_SYS_INFO                   ROM_TABLE_CODE('G', 'S')\n#define ROM_FUNC_GET_UF2_TARGET_PARTITION       ROM_TABLE_CODE('G', 'U')\n#define ROM_FUNC_LOAD_PARTITION_TABLE           ROM_TABLE_CODE('L', 'P')\n#define ROM_FUNC_OTP_ACCESS                     ROM_TABLE_CODE('O', 'A')\n#define ROM_DATA_PARTITION_TABLE_PTR            ROM_TABLE_CODE('P', 'T')\n#define ROM_FUNC_FLASH_RESET_ADDRESS_TRANS      ROM_TABLE_CODE('R', 'A')\n#define ROM_FUNC_REBOOT                         ROM_TABLE_CODE('R', 'B')\n#define ROM_FUNC_SET_ROM_CALLBACK               ROM_TABLE_CODE('R', 'C')\n#define ROM_FUNC_SECURE_CALL                    ROM_TABLE_CODE('S', 'C')\n#define ROM_FUNC_SET_NS_API_PERMISSION          ROM_TABLE_CODE('S', 'P')\n#define ROM_FUNC_BOOTROM_STATE_RESET            ROM_TABLE_CODE('S', 'R')\n#define ROM_FUNC_SET_BOOTROM_STACK              ROM_TABLE_CODE('S', 'S')\n#define ROM_DATA_SAVED_XIP_SETUP_FUNC_PTR       ROM_TABLE_CODE('X', 'F')\n#define ROM_FUNC_FLASH_SELECT_XIP_READ_MODE     ROM_TABLE_CODE('X', 'M')\n#define ROM_FUNC_VALIDATE_NS_BUFFER             ROM_TABLE_CODE('V', 'B')\n\n#define BOOTSEL_FLAG_GPIO_PIN_SPECIFIED         0x20\n\n#define BOOTROM_FUNC_TABLE_OFFSET 0x14\n\n// todo remove this (or #ifdef it for A1/A2)\n#define BOOTROM_IS_A2() ((*(volatile uint8_t *)0x13) == 2)\n#define BOOTROM_WELL_KNOWN_PTR_SIZE (BOOTROM_IS_A2() ? 2 : 4)\n\n#define BOOTROM_VTABLE_OFFSET 0x00\n#define BOOTROM_TABLE_LOOKUP_OFFSET     (BOOTROM_FUNC_TABLE_OFFSET + BOOTROM_WELL_KNOWN_PTR_SIZE)\n\n\n// https://github.com/raspberrypi/pico-sdk\n// src/common/boot_picoboot_headers/include/boot/picoboot_constants.h\n\n// values 0-7 are secure/non-secure\n#define REBOOT2_FLAG_REBOOT_TYPE_NORMAL       0x0 // param0 = diagnostic partition\n#define REBOOT2_FLAG_REBOOT_TYPE_BOOTSEL      0x2 // param0 = bootsel_flags, param1 = gpio_config\n#define REBOOT2_FLAG_REBOOT_TYPE_RAM_IMAGE    0x3 // param0 = image_base, param1 = image_end\n#define REBOOT2_FLAG_REBOOT_TYPE_FLASH_UPDATE 0x4 // param0 = update_base\n\n#define REBOOT2_FLAG_NO_RETURN_ON_SUCCESS    0x100\n\n#define RT_FLAG_FUNC_ARM_SEC    0x0004\n#define RT_FLAG_FUNC_ARM_NONSEC 0x0010\n#define RT_FLAG_DATA            0x0040\n\n\n// https://github.com/raspberrypi/pico-sdk\n// src/rp2_common/pico_bootrom/include/pico/bootrom.h\n\n#define ROM_TABLE_CODE(c1, c2) ((c1) | ((c2) << 8))\n\ntypedef void *(*rom_table_lookup_fn)(uint32_t code, uint32_t mask);\n\n__attribute__((always_inline))\nstatic void *rom_func_lookup_inline(uint32_t code) {\n    rom_table_lookup_fn rom_table_lookup = (rom_table_lookup_fn) (uintptr_t)*(uint16_t*)(BOOTROM_TABLE_LOOKUP_OFFSET);\n    if (pico_processor_state_is_nonsecure()) {\n        return rom_table_lookup(code, RT_FLAG_FUNC_ARM_NONSEC);\n    } else {\n        return rom_table_lookup(code, RT_FLAG_FUNC_ARM_SEC);\n    }\n}\n\n__attribute__((always_inline))\nstatic void *rom_data_lookup_inline(uint32_t code) {\n    rom_table_lookup_fn rom_table_lookup = (rom_table_lookup_fn) (uintptr_t)*(uint16_t*)(BOOTROM_TABLE_LOOKUP_OFFSET);\n    return rom_table_lookup(code, RT_FLAG_DATA);\n}\n\ntypedef int (*rom_reboot_fn)(uint32_t flags, uint32_t delay_ms, uint32_t p0, uint32_t p1);\n\n__attribute__((always_inline))\nint rom_reboot(uint32_t flags, uint32_t delay_ms, uint32_t p0, uint32_t p1) {\n    rom_reboot_fn func = (rom_reboot_fn) rom_func_lookup_inline(ROM_FUNC_REBOOT);\n    return func(flags, delay_ms, p0, p1);\n}\n\n\n// https://github.com/raspberrypi/pico-sdk\n// src/rp2_common/pico_bootrom/bootrom.c\n\nvoid reset_usb_boot(uint32_t usb_activity_gpio_pin_mask, uint32_t disable_interface_mask) {\n    uint32_t flags = disable_interface_mask;\n    if (usb_activity_gpio_pin_mask) {\n        flags |= BOOTSEL_FLAG_GPIO_PIN_SPECIFIED;\n        // the parameter is actually the gpio number, but we only care if BOOTSEL_FLAG_GPIO_PIN_SPECIFIED\n        usb_activity_gpio_pin_mask = (uint32_t)__builtin_ctz(usb_activity_gpio_pin_mask);\n    }\n    rom_reboot(REBOOT2_FLAG_REBOOT_TYPE_BOOTSEL | REBOOT2_FLAG_NO_RETURN_ON_SUCCESS, 10, flags, usb_activity_gpio_pin_mask);\n    __builtin_unreachable();\n}\n\n\n// https://github.com/raspberrypi/pico-sdk\n// src/rp2350/hardware_regs/include/hardware/regs/qmi.h\n\n#define QMI_DIRECT_CSR_EN_BITS      0x00000001\n#define QMI_DIRECT_CSR_RXEMPTY_BITS 0x00010000\n#define QMI_DIRECT_CSR_TXFULL_BITS  0x00000400\n#define QMI_M1_WFMT_RESET           0x00001000\n#define QMI_M1_WCMD_RESET           0x0000a002\n\n\n// https://github.com/raspberrypi/pico-sdk\n// src/rp2350/hardware_regs/include/hardware/regs/io_qspi.h\n\n#define IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_BITS       0x00003000\n#define IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_LSB        12\n#define IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_VALUE_LOW  0x2\n#define IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_VALUE_HIGH 0x3\n\n\n// https://github.com/raspberrypi/pico-sdk\n// src/rp2350/hardware_structs/include/hardware/structs/io_qspi.h\n\ntypedef struct {\n    io_rw_32 inte; // IO_QSPI_PROC0_INTE\n    io_rw_32 intf; // IO_QSPI_PROC0_INTF\n    io_ro_32 ints; // IO_QSPI_PROC0_INTS\n} io_qspi_irq_ctrl_hw_t;\n\ntypedef struct {\n    io_ro_32 status; // IO_QSPI_GPIO_QSPI_SCLK_STATUS\n    io_rw_32 ctrl;   // IO_QSPI_GPIO_QSPI_SCLK_CTRL\n} io_qspi_status_ctrl_hw_t;\n\ntypedef struct {\n    io_ro_32 usbphy_dp_status;                  // IO_QSPI_USBPHY_DP_STATUS\n    io_rw_32 usbphy_dp_ctrl;                    // IO_QSPI_USBPHY_DP_CTRL\n    io_ro_32 usbphy_dm_status;                  // IO_QSPI_USBPHY_DM_STATUS\n    io_rw_32 usbphy_dm_ctrl;                    // IO_QSPI_USBPHY_DM_CTRL\n    io_qspi_status_ctrl_hw_t io[6];\n    uint32_t _pad0[112];\n    io_ro_32 irqsummary_proc0_secure;           // IO_QSPI_IRQSUMMARY_PROC0_SECURE\n    io_ro_32 irqsummary_proc0_nonsecure;        // IO_QSPI_IRQSUMMARY_PROC0_NONSECURE\n    io_ro_32 irqsummary_proc1_secure;           // IO_QSPI_IRQSUMMARY_PROC1_SECURE\n    io_ro_32 irqsummary_proc1_nonsecure;        // IO_QSPI_IRQSUMMARY_PROC1_NONSECURE\n    io_ro_32 irqsummary_dormant_wake_secure;    // IO_QSPI_IRQSUMMARY_DORMANT_WAKE_SECURE\n    io_ro_32 irqsummary_dormant_wake_nonsecure; // IO_QSPI_IRQSUMMARY_DORMANT_WAKE_NONSECURE\n    io_rw_32 intr;                              // IO_QSPI_INTR\n\n    union {\n        struct {\n            io_qspi_irq_ctrl_hw_t proc0_irq_ctrl;\n            io_qspi_irq_ctrl_hw_t proc1_irq_ctrl;\n            io_qspi_irq_ctrl_hw_t dormant_wake_irq_ctrl;\n        };\n        io_qspi_irq_ctrl_hw_t irq_ctrl[3];\n    };\n} io_qspi_hw_t;\n\n#define io_qspi_hw ((io_qspi_hw_t *)IO_QSPI_BASE)\n\n\n// https://github.com/raspberrypi/pico-sdk\n// src/rp2350/hardware_structs/include/hardware/structs/qmi.h\n\ntypedef struct {\n    io_rw_32 timing; // QMI_M0_TIMING\n    io_rw_32 rfmt;   // QMI_M0_RFMT\n    io_rw_32 rcmd;   // QMI_M0_RCMD\n    io_rw_32 wfmt;   // QMI_M0_WFMT\n    io_rw_32 wcmd;   // QMI_M0_WCMD\n} qmi_mem_hw_t;\n\ntypedef struct {\n    io_rw_32 direct_csr; // QMI_DIRECT_CSR\n    io_wo_32 direct_tx;  // QMI_DIRECT_TX\n    io_ro_32 direct_rx;  // QMI_DIRECT_RX\n    qmi_mem_hw_t m[2];\n    io_rw_32 atrans[8];  // QMI_ATRANS0\n} qmi_hw_t;\n\n#define qmi_hw ((qmi_hw_t *)XIP_QMI_BASE)\n\n\n// https://github.com/raspberrypi/pico-sdk\n// src/rp2_common/hardware_xip_cache/include/hardware/xip_cache.h\n\n// Noop unless using XIP Cache-as-SRAM\n// Non-noop version in src/rp2_common/hardware_xip_cache/xip_cache.c\nstatic inline void xip_cache_clean_all(void) {}\n\n\n// https://github.com/raspberrypi/pico-sdk\n// src/rp2_common/hardware_flash/include/hardware/flash.h\n\n#define FLASH_PAGE_SIZE (1u << 8)\n#define FLASH_SECTOR_SIZE (1u << 12)\n#define FLASH_BLOCK_SIZE (1u << 16)\n\n\n// https://github.com/raspberrypi/pico-sdk\n// src/rp2_common/hardware_flash/flash.c\n\n#define BOOT2_SIZE_WORDS 64\n#define FLASH_BLOCK_ERASE_CMD 0xd8\n\nstatic uint32_t boot2_copyout[BOOT2_SIZE_WORDS];\nstatic bool boot2_copyout_valid = false;\n\nstatic ram_func void flash_init_boot2_copyout(void) {\n    if (boot2_copyout_valid)\n        return;\n    for (int i = 0; i < BOOT2_SIZE_WORDS; ++i)\n\t\tboot2_copyout[i] = ((uint32_t *)BOOTRAM_BASE)[i];\n    __compiler_memory_barrier();\n    boot2_copyout_valid = true;\n}\n\nstatic ram_func void flash_enable_xip_via_boot2(void) {\n    ((void (*)(void))((intptr_t)boot2_copyout+1))();\n}\n\n// This is a static symbol because the layout of FLASH_DEVINFO is liable to change from device to\n// device, so fields must have getters/setters.\nstatic io_rw_16 * ram_func flash_devinfo_ptr(void) {\n    // Note the lookup returns a pointer to a 32-bit pointer literal in the ROM\n    io_rw_16 **p = (io_rw_16 **) rom_data_lookup_inline(ROM_DATA_FLASH_DEVINFO16_PTR);\n    return *p;\n}\n\n// This is a RAM function because may be called during flash programming to enable save/restore of\n// QMI window 1 registers on RP2350:\nuint8_t ram_func flash_devinfo_get_cs_size(uint8_t cs) {\n    io_ro_16 *devinfo = (io_ro_16 *) flash_devinfo_ptr();\n    if (cs == 0u) {\n        return (uint8_t) (\n            (*devinfo & OTP_DATA_FLASH_DEVINFO_CS0_SIZE_BITS) >> OTP_DATA_FLASH_DEVINFO_CS0_SIZE_LSB\n        );\n    } else {\n        return (uint8_t) (\n            (*devinfo & OTP_DATA_FLASH_DEVINFO_CS1_SIZE_BITS) >> OTP_DATA_FLASH_DEVINFO_CS1_SIZE_LSB\n        );\n    }\n}\n\n// This is specifically for saving/restoring the registers modified by RP2350\n// flash_exit_xip() ROM func, not the entirety of the QMI window state.\ntypedef struct flash_rp2350_qmi_save_state {\n    uint32_t timing;\n    uint32_t rcmd;\n    uint32_t rfmt;\n} flash_rp2350_qmi_save_state_t;\n\nstatic ram_func void flash_rp2350_save_qmi_cs1(flash_rp2350_qmi_save_state_t *state) {\n    state->timing = qmi_hw->m[1].timing;\n    state->rcmd = qmi_hw->m[1].rcmd;\n    state->rfmt = qmi_hw->m[1].rfmt;\n}\n\nstatic ram_func void flash_rp2350_restore_qmi_cs1(const flash_rp2350_qmi_save_state_t *state) {\n    if (flash_devinfo_get_cs_size(1) == 0) {\n        // Case 1: The RP2350 ROM sets QMI to a clean (03h read) configuration\n        // during flash_exit_xip(), even though when CS1 is not enabled via\n        // FLASH_DEVINFO it does not issue an XIP exit sequence to CS1. In\n        // this case, restore the original register config for CS1 as it is\n        // still the correct config.\n        qmi_hw->m[1].timing = state->timing;\n        qmi_hw->m[1].rcmd = state->rcmd;\n        qmi_hw->m[1].rfmt = state->rfmt;\n    } else {\n        // Case 2: If RAM is attached to CS1, and the ROM has issued an XIP\n        // exit sequence to it, then the ROM re-initialisation of the QMI\n        // registers has actually not gone far enough. The old XIP write mode\n        // is no longer valid when the QSPI RAM is returned to a serial\n        // command state. Restore the default 02h serial write command config.\n        qmi_hw->m[1].wfmt = QMI_M1_WFMT_RESET;\n        qmi_hw->m[1].wcmd = QMI_M1_WCMD_RESET;\n    }\n}\n\nvoid ram_func flash_cs_force(bool high) {\n    uint32_t field_val = high ?\n        IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_VALUE_HIGH :\n        IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_VALUE_LOW;\n    hw_write_masked(&io_qspi_hw->io[1].ctrl,\n        field_val << IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_LSB,\n        IO_QSPI_GPIO_QSPI_SS_CTRL_OUTOVER_BITS\n    );\n}\n\n// Adapted from flash_range_program()\nvoid ram_func flash_range_write(uint32_t offset, const uint8_t *data, size_t count) {\n    flash_connect_internal_fn flash_connect_internal_func = (flash_connect_internal_fn)rom_func_lookup_inline(ROM_FUNC_CONNECT_INTERNAL_FLASH);\n    flash_exit_xip_fn flash_exit_xip_func = (flash_exit_xip_fn)rom_func_lookup_inline(ROM_FUNC_FLASH_EXIT_XIP);\n    flash_range_program_fn flash_range_program_func = (flash_range_program_fn)rom_func_lookup_inline(ROM_FUNC_FLASH_RANGE_PROGRAM);\n    flash_flush_cache_fn flash_flush_cache_func = (flash_flush_cache_fn)rom_func_lookup_inline(ROM_FUNC_FLASH_FLUSH_CACHE);\n    flash_init_boot2_copyout();\n    xip_cache_clean_all();\n    flash_rp2350_qmi_save_state_t qmi_save;\n    flash_rp2350_save_qmi_cs1(&qmi_save);\n\n    __compiler_memory_barrier();\n\n    flash_connect_internal_func();\n    flash_exit_xip_func();\n    flash_range_program_func(offset, data, count);\n    flash_flush_cache_func(); // Note this is needed to remove CSn IO force as well as cache flushing\n    flash_enable_xip_via_boot2();\n    flash_rp2350_restore_qmi_cs1(&qmi_save);\n}\n\n// Adapted from flash_range_erase()\nvoid ram_func flash_erase_blocks(uint32_t offset, size_t count) {\n    flash_connect_internal_fn flash_connect_internal_func = (flash_connect_internal_fn)rom_func_lookup_inline(ROM_FUNC_CONNECT_INTERNAL_FLASH);\n    flash_exit_xip_fn flash_exit_xip_func = (flash_exit_xip_fn)rom_func_lookup_inline(ROM_FUNC_FLASH_EXIT_XIP);\n    flash_range_erase_fn flash_range_erase_func = (flash_range_erase_fn)rom_func_lookup_inline(ROM_FUNC_FLASH_RANGE_ERASE);\n    flash_flush_cache_fn flash_flush_cache_func = (flash_flush_cache_fn)rom_func_lookup_inline(ROM_FUNC_FLASH_FLUSH_CACHE);\n    flash_init_boot2_copyout();\n    // Commit any pending writes to external RAM, to avoid losing them in the subsequent flush:\n    xip_cache_clean_all();\n    flash_rp2350_qmi_save_state_t qmi_save;\n    flash_rp2350_save_qmi_cs1(&qmi_save);\n\n    // No flash accesses after this point\n    __compiler_memory_barrier();\n\n    flash_connect_internal_func();\n    flash_exit_xip_func();\n    flash_range_erase_func(offset, count, FLASH_BLOCK_SIZE, FLASH_BLOCK_ERASE_CMD);\n    flash_flush_cache_func(); // Note this is needed to remove CSn IO force as well as cache flushing\n    flash_enable_xip_via_boot2();\n    flash_rp2350_restore_qmi_cs1(&qmi_save);\n}\n\nvoid ram_func flash_do_cmd(const uint8_t *txbuf, uint8_t *rxbuf, size_t count) {\n    flash_connect_internal_fn flash_connect_internal_func = (flash_connect_internal_fn)rom_func_lookup_inline(ROM_FUNC_CONNECT_INTERNAL_FLASH);\n    flash_exit_xip_fn flash_exit_xip_func = (flash_exit_xip_fn)rom_func_lookup_inline(ROM_FUNC_FLASH_EXIT_XIP);\n    flash_flush_cache_fn flash_flush_cache_func = (flash_flush_cache_fn)rom_func_lookup_inline(ROM_FUNC_FLASH_FLUSH_CACHE);\n    flash_init_boot2_copyout();\n    xip_cache_clean_all();\n\n    flash_rp2350_qmi_save_state_t qmi_save;\n    flash_rp2350_save_qmi_cs1(&qmi_save);\n\n    __compiler_memory_barrier();\n    flash_connect_internal_func();\n    flash_exit_xip_func();\n\n    flash_cs_force(0);\n    size_t tx_remaining = count;\n    size_t rx_remaining = count;\n\n    // QMI version -- no need to bound FIFO contents as QMI stalls on full DIRECT_RX.\n    hw_set_bits(&qmi_hw->direct_csr, QMI_DIRECT_CSR_EN_BITS);\n    while (tx_remaining || rx_remaining) {\n        uint32_t flags = qmi_hw->direct_csr;\n        bool can_put = !(flags & QMI_DIRECT_CSR_TXFULL_BITS);\n        bool can_get = !(flags & QMI_DIRECT_CSR_RXEMPTY_BITS);\n        if (can_put && tx_remaining) {\n            qmi_hw->direct_tx = *txbuf++;\n            --tx_remaining;\n        }\n        if (can_get && rx_remaining) {\n            *rxbuf++ = (uint8_t)qmi_hw->direct_rx;\n            --rx_remaining;\n        }\n    }\n    hw_clear_bits(&qmi_hw->direct_csr, QMI_DIRECT_CSR_EN_BITS);\n\n    flash_cs_force(1);\n\n    flash_flush_cache_func();\n    flash_enable_xip_via_boot2();\n    flash_rp2350_restore_qmi_cs1(&qmi_save);\n}\n\n*/\nimport \"C\"\n\nfunc enterBootloader() {\n\tC.reset_usb_boot(0, 0)\n}\n\nfunc doFlashCommand(tx []byte, rx []byte) error {\n\tif len(tx) != len(rx) {\n\t\treturn errFlashInvalidWriteLength\n\t}\n\n\tC.flash_do_cmd(\n\t\t(*C.uint8_t)(unsafe.Pointer(&tx[0])),\n\t\t(*C.uint8_t)(unsafe.Pointer(&rx[0])),\n\t\tC.ulong(len(tx)))\n\n\treturn nil\n}\n\n// Flash related code\nconst memoryStart = C.XIP_BASE // memory start for purpose of erase\n\nfunc (f flashBlockDevice) writeAt(p []byte, off int64) (n int, err error) {\n\tif writeAddress(off)+uintptr(C.XIP_BASE) > FlashDataEnd() {\n\t\treturn 0, errFlashCannotWritePastEOF\n\t}\n\n\tstate := interrupt.Disable()\n\tdefer interrupt.Restore(state)\n\n\t// rp2350 writes to offset, not actual address\n\t// e.g. real address 0x10003000 is written to at\n\t// 0x00003000\n\taddress := writeAddress(off)\n\tpadded := flashPad(p, int(f.WriteBlockSize()))\n\n\tC.flash_range_write(C.uint32_t(address),\n\t\t(*C.uint8_t)(unsafe.Pointer(&padded[0])),\n\t\tC.ulong(len(padded)))\n\n\treturn len(padded), nil\n}\n\nfunc (f flashBlockDevice) eraseBlocks(start, length int64) error {\n\taddress := writeAddress(start * f.EraseBlockSize())\n\tif address+uintptr(C.XIP_BASE) > FlashDataEnd() {\n\t\treturn errFlashCannotErasePastEOF\n\t}\n\n\tstate := interrupt.Disable()\n\tdefer interrupt.Restore(state)\n\n\tC.flash_erase_blocks(C.uint32_t(address), C.ulong(length*f.EraseBlockSize()))\n\n\treturn nil\n}\n"
  },
  {
    "path": "src/machine/machine_rp2350_usb.go",
    "content": "//go:build rp2350\n\npackage machine\n\nimport (\n\t\"device/rp\"\n\t\"machine/usb\"\n\t\"runtime/interrupt\"\n)\n\n// Configure the USB peripheral. The config is here for compatibility with the UART interface.\nfunc (dev *USBDevice) Configure(config UARTConfig) {\n\t// Reset usb controller\n\tresetBlock(rp.RESETS_RESET_USBCTRL)\n\tunresetBlockWait(rp.RESETS_RESET_USBCTRL)\n\n\t// Clear any previous state in dpram just in case\n\t_usbDPSRAM.clear()\n\n\t// Enable USB interrupt at processor\n\trp.USB.INTE.Set(0)\n\tintr := interrupt.New(rp.IRQ_USBCTRL_IRQ, handleUSBIRQ)\n\tintr.SetPriority(0x00)\n\tintr.Enable()\n\tirqSet(rp.IRQ_USBCTRL_IRQ, true)\n\n\t// Mux the controller to the onboard usb phy\n\trp.USB.USB_MUXING.Set(rp.USB_USB_MUXING_TO_PHY | rp.USB_USB_MUXING_SOFTCON)\n\n\t// Force VBUS detect so the device thinks it is plugged into a host\n\trp.USB.USB_PWR.Set(rp.USB_USB_PWR_VBUS_DETECT | rp.USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN)\n\n\t// Enable the USB controller in device mode.\n\trp.USB.MAIN_CTRL.Set(rp.USB_MAIN_CTRL_CONTROLLER_EN)\n\n\t// Enable an interrupt per EP0 transaction\n\trp.USB.SIE_CTRL.Set(rp.USB_SIE_CTRL_EP0_INT_1BUF)\n\n\t// Enable interrupts for when a buffer is done, when the bus is reset,\n\t// and when a setup packet is received\n\trp.USB.INTE.Set(rp.USB_INTE_BUFF_STATUS |\n\t\trp.USB_INTE_BUS_RESET |\n\t\trp.USB_INTE_SETUP_REQ)\n\n\t// Present full speed device by enabling pull up on DP\n\trp.USB.SIE_CTRL.SetBits(rp.USB_SIE_CTRL_PULLUP_EN)\n\n\t// 12.7.2 Disable phy isolation\n\trp.USB.SetMAIN_CTRL_PHY_ISO(0x0)\n}\n\nfunc handleUSBIRQ(intr interrupt.Interrupt) {\n\tstatus := rp.USB.INTS.Get()\n\n\t// Setup packet received\n\tif (status & rp.USB_INTS_SETUP_REQ) > 0 {\n\t\trp.USB.SIE_STATUS.Set(rp.USB_SIE_STATUS_SETUP_REC)\n\t\tsetup := usb.NewSetup(_usbDPSRAM.setupBytes())\n\n\t\tok := false\n\t\tif (setup.BmRequestType & usb.REQUEST_TYPE) == usb.REQUEST_STANDARD {\n\t\t\t// Standard Requests\n\t\t\tok = handleStandardSetup(setup)\n\t\t} else {\n\t\t\t// Class Interface Requests\n\t\t\tif setup.WIndex < uint16(len(usbSetupHandler)) && usbSetupHandler[setup.WIndex] != nil {\n\t\t\t\tok = usbSetupHandler[setup.WIndex](setup)\n\t\t\t}\n\t\t}\n\n\t\tif !ok {\n\t\t\t// Stall endpoint?\n\t\t\tUSBDev.SetStallEPIn(0)\n\t\t}\n\n\t}\n\n\t// Buffer status, one or more buffers have completed\n\tif (status & rp.USB_INTS_BUFF_STATUS) > 0 {\n\t\tif sendOnEP0DATADONE.offset > 0 {\n\t\t\tep := uint32(0)\n\t\t\tdata := sendOnEP0DATADONE.data\n\t\t\tcount := len(data) - sendOnEP0DATADONE.offset\n\t\t\tif ep == 0 && count > usb.EndpointPacketSize {\n\t\t\t\tcount = usb.EndpointPacketSize\n\t\t\t}\n\n\t\t\tsendViaEPIn(ep, data[sendOnEP0DATADONE.offset:], count)\n\t\t\tsendOnEP0DATADONE.offset += count\n\t\t\tif sendOnEP0DATADONE.offset == len(data) {\n\t\t\t\tsendOnEP0DATADONE.offset = 0\n\t\t\t}\n\t\t}\n\n\t\ts2 := rp.USB.BUFF_STATUS.Get()\n\n\t\t// OUT (PC -> rp2350)\n\t\tfor i := 0; i < 16; i++ {\n\t\t\tif s2&(1<<(i*2+1)) > 0 {\n\t\t\t\tbuf := handleEndpointRx(uint32(i))\n\t\t\t\tif usbRxHandler[i] == nil || usbRxHandler[i](buf) {\n\t\t\t\t\tAckUsbOutTransfer(uint32(i))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// IN (rp2350 -> PC)\n\t\tfor i := 0; i < 16; i++ {\n\t\t\tif s2&(1<<(i*2)) > 0 {\n\t\t\t\tif usbTxHandler[i] != nil {\n\t\t\t\t\tusbTxHandler[i]()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\trp.USB.BUFF_STATUS.Set(s2)\n\t}\n\n\t// Bus is reset\n\tif (status & rp.USB_INTS_BUS_RESET) > 0 {\n\t\trp.USB.SIE_STATUS.Set(rp.USB_SIE_STATUS_BUS_RESET)\n\t\t//fixRP2040UsbDeviceEnumeration()\n\n\t\trp.USB.ADDR_ENDP.Set(0)\n\t\tinitEndpoint(0, usb.ENDPOINT_TYPE_CONTROL)\n\t}\n}\n\nfunc handleUSBSetAddress(setup usb.Setup) bool {\n\t// Using 570μs timeout which is exactly the same as SAMD21.\n\tconst ackTimeout = 570\n\n\trp.USB.SIE_STATUS.Set(rp.USB_SIE_STATUS_ACK_REC)\n\tsendUSBPacket(0, []byte{}, 0)\n\n\t// Wait for transfer to complete with a timeout.\n\tt := timer.timeElapsed()\n\tfor (rp.USB.SIE_STATUS.Get() & rp.USB_SIE_STATUS_ACK_REC) == 0 {\n\t\tif dt := timer.timeElapsed() - t; dt >= ackTimeout {\n\t\t\treturn false\n\t\t}\n\t}\n\n\t// Set the device address to that requested by host.\n\trp.USB.ADDR_ENDP.Set(uint32(setup.WValueL) & rp.USB_ADDR_ENDP_ADDRESS_Msk)\n\treturn true\n}\n\nfunc armEPZeroStall() {\n\trp.USB.EP_STALL_ARM.Set(rp.USB_EP_STALL_ARM_EP0_IN)\n}\n"
  },
  {
    "path": "src/machine/machine_rp2_2040.go",
    "content": "//go:build rp2040\n\npackage machine\n\nimport (\n\t\"device/rp\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nconst (\n\tcpuFreq          = 200 * MHz\n\t_NUMBANK0_GPIOS  = 30\n\t_NUMBANK0_IRQS   = 4\n\t_NUMIRQ          = 32\n\trp2350ExtraReg   = 0\n\tRESETS_RESET_Msk = 0x01ffffff\n\tinitUnreset      = rp.RESETS_RESET_ADC |\n\t\trp.RESETS_RESET_RTC |\n\t\trp.RESETS_RESET_SPI0 |\n\t\trp.RESETS_RESET_SPI1 |\n\t\trp.RESETS_RESET_UART0 |\n\t\trp.RESETS_RESET_UART1 |\n\t\trp.RESETS_RESET_USBCTRL\n\tinitDontReset = rp.RESETS_RESET_IO_QSPI |\n\t\trp.RESETS_RESET_PADS_QSPI |\n\t\trp.RESETS_RESET_PLL_USB |\n\t\trp.RESETS_RESET_USBCTRL |\n\t\trp.RESETS_RESET_SYSCFG |\n\t\trp.RESETS_RESET_PLL_SYS\n\tpadEnableMask = rp.PADS_BANK0_GPIO0_IE_Msk |\n\t\trp.PADS_BANK0_GPIO0_OD_Msk\n)\n\nconst (\n\tPinOutput PinMode = iota\n\tPinInput\n\tPinInputPulldown\n\tPinInputPullup\n\tPinAnalog\n\tPinUART\n\tPinPWM\n\tPinI2C\n\tPinSPI\n\tPinPIO0\n\tPinPIO1\n)\n\n// Analog pins on RP2040.\nconst (\n\tADC0 Pin = GPIO26\n\tADC1 Pin = GPIO27\n\tADC2 Pin = GPIO28\n\tADC3 Pin = GPIO29\n\n\tthermADC = 30\n)\n\nconst (\n\tclkGPOUT0 clockIndex = iota // GPIO Muxing 0\n\tclkGPOUT1                   // GPIO Muxing 1\n\tclkGPOUT2                   // GPIO Muxing 2\n\tclkGPOUT3                   // GPIO Muxing 3\n\tclkRef                      // Watchdog and timers reference clock\n\tclkSys                      // Processors, bus fabric, memory, memory mapped registers\n\tclkPeri                     // Peripheral clock for UART and SPI\n\tclkUSB                      // USB clock\n\tclkADC                      // ADC clock\n\tclkRTC                      // Real time clock\n\tnumClocks\n)\n\nfunc calcClockDiv(srcFreq, freq uint32) uint32 {\n\t// Div register is 24.8 int.frac divider so multiply by 2^8 (left shift by 8)\n\treturn uint32((uint64(srcFreq) << 8) / uint64(freq))\n}\n\ntype clocksType struct {\n\tclk   [numClocks]clockType\n\tresus struct {\n\t\tctrl   volatile.Register32\n\t\tstatus volatile.Register32\n\t}\n\tfc0      fc\n\twakeEN0  volatile.Register32\n\twakeEN1  volatile.Register32\n\tsleepEN0 volatile.Register32\n\tsleepEN1 volatile.Register32\n\tenabled0 volatile.Register32\n\tenabled1 volatile.Register32\n\tintR     volatile.Register32\n\tintE     volatile.Register32\n\tintF     volatile.Register32\n\tintS     volatile.Register32\n}\n\n// GPIO function selectors\nconst (\n\tfnJTAG pinFunc = 0\n\tfnSPI  pinFunc = 1 // Connect one of the internal PL022 SPI peripherals to GPIO\n\tfnUART pinFunc = 2\n\tfnI2C  pinFunc = 3\n\t// Connect a PWM slice to GPIO. There are eight PWM slices,\n\t// each with two outputchannels (A/B). The B pin can also be used as an input,\n\t// for frequency and duty cyclemeasurement\n\tfnPWM pinFunc = 4\n\t// Software control of GPIO, from the single-cycle IO (SIO) block.\n\t// The SIO function (F5)must be selected for the processors to drive a GPIO,\n\t// but the input is always connected,so software can check the state of GPIOs at any time.\n\tfnSIO pinFunc = 5\n\t// Connect one of the programmable IO blocks (PIO) to GPIO. PIO can implement a widevariety of interfaces,\n\t// and has its own internal pin mapping hardware, allowing flexibleplacement of digital interfaces on bank 0 GPIOs.\n\t// The PIO function (F6, F7) must beselected for PIO to drive a GPIO, but the input is always connected,\n\t// so the PIOs canalways see the state of all pins.\n\tfnPIO0, fnPIO1 pinFunc = 6, 7\n\t// General purpose clock inputs/outputs. Can be routed to a number of internal clock domains onRP2040,\n\t// e.g. Input: to provide a 1 Hz clock for the RTC, or can be connected to an internalfrequency counter.\n\t// e.g. Output: optional integer divide\n\tfnGPCK pinFunc = 8\n\t// USB power control signals to/from the internal USB controller\n\tfnUSB  pinFunc = 9\n\tfnNULL pinFunc = 0x1f\n\n\tfnXIP pinFunc = 0\n)\n\n// validPins confirms that the SPI pin selection is a legitimate one\n// for the the 2040 chip.\nfunc (spi *SPI) validPins(config SPIConfig) error {\n\tvar okSDI, okSDO, okSCK bool\n\tswitch spi.Bus {\n\tcase rp.SPI0:\n\t\tokSDI = config.SDI == 0 || config.SDI == 4 || config.SDI == 16 || config.SDI == 20\n\t\tokSDO = config.SDO == 3 || config.SDO == 7 || config.SDO == 19 || config.SDO == 23\n\t\tokSCK = config.SCK == 2 || config.SCK == 6 || config.SCK == 18 || config.SCK == 22\n\tcase rp.SPI1:\n\t\tokSDI = config.SDI == 8 || config.SDI == 12 || config.SDI == 24 || config.SDI == 28\n\t\tokSDO = config.SDO == 11 || config.SDO == 15 || config.SDO == 27\n\t\tokSCK = config.SCK == 10 || config.SCK == 14 || config.SCK == 26\n\t}\n\tswitch {\n\tcase !okSDI:\n\t\treturn errSPIInvalidSDI\n\tcase !okSDO:\n\t\treturn errSPIInvalidSDO\n\tcase !okSCK:\n\t\treturn errSPIInvalidSCK\n\t}\n\treturn nil\n}\n\n// Configure configures the gpio pin as per mode.\nfunc (p Pin) Configure(config PinConfig) {\n\tif p == NoPin {\n\t\treturn\n\t}\n\tp.init()\n\tmask := uint32(1) << p\n\tswitch config.Mode {\n\tcase PinOutput:\n\t\tp.setFunc(fnSIO)\n\t\trp.SIO.GPIO_OE_SET.Set(mask)\n\tcase PinInput:\n\t\tp.setFunc(fnSIO)\n\t\tp.pulloff()\n\tcase PinInputPulldown:\n\t\tp.setFunc(fnSIO)\n\t\tp.pulldown()\n\tcase PinInputPullup:\n\t\tp.setFunc(fnSIO)\n\t\tp.pullup()\n\tcase PinAnalog:\n\t\tp.setFunc(fnNULL)\n\t\tp.pulloff()\n\tcase PinUART:\n\t\tp.setFunc(fnUART)\n\tcase PinPWM:\n\t\tp.setFunc(fnPWM)\n\tcase PinI2C:\n\t\t// IO config according to 4.3.1.3 of rp2040 datasheet.\n\t\tp.setFunc(fnI2C)\n\t\tp.pullup()\n\t\tp.setSchmitt(true)\n\t\tp.setSlew(false)\n\tcase PinSPI:\n\t\tp.setFunc(fnSPI)\n\tcase PinPIO0:\n\t\tp.setFunc(fnPIO0)\n\tcase PinPIO1:\n\t\tp.setFunc(fnPIO1)\n\t}\n}\n\nvar (\n\ttimer = (*timerType)(unsafe.Pointer(rp.TIMER))\n)\n\n// Enable or disable a specific interrupt on the executing core.\n// num is the interrupt number which must be in [0,31].\nfunc irqSet(num uint32, enabled bool) {\n\tif num >= _NUMIRQ {\n\t\treturn\n\t}\n\tirqSetMask(1<<num, enabled)\n}\n\nfunc irqSetMask(mask uint32, enabled bool) {\n\tif enabled {\n\t\t// Clear pending before enable\n\t\t// (if IRQ is actually asserted, it will immediately re-pend)\n\t\trp.PPB.NVIC_ICPR.Set(mask)\n\t\trp.PPB.NVIC_ISER.Set(mask)\n\t} else {\n\t\trp.PPB.NVIC_ICER.Set(mask)\n\t}\n}\n\nfunc (clks *clocksType) initRTC() {\n\t// clkRTC = pllUSB (48MHz) / 1024 = 46875Hz\n\tcrtc := clks.clock(clkRTC)\n\tcrtc.configure(0, // No GLMUX\n\t\trp.CLOCKS_CLK_RTC_CTRL_AUXSRC_CLKSRC_PLL_USB,\n\t\t48*MHz,\n\t\t46875)\n}\n\nfunc (clks *clocksType) initTicks() {} // No ticks on RP2040\n\n// startTick starts the watchdog tick.\n// cycles needs to be a divider that when applied to the xosc input,\n// produces a 1MHz clock. So if the xosc frequency is 12MHz,\n// this will need to be 12.\nfunc (wd *watchdogImpl) startTick(cycles uint32) {\n\trp.WATCHDOG.TICK.Set(cycles | rp.WATCHDOG_TICK_ENABLE)\n}\n\nfunc adjustCoreVoltage() bool {\n\tif cpuFreq <= 133*MHz {\n\t\treturn false\n\t}\n\t// The rp2040 is certified to run at 200MHz with the\n\t// core voltage set to 1150mV.\n\tconst targetVoltage = 1150\n\t// 0b0101 maps to 800mV and each step is 50mV.\n\tconst vreg = 0b0101 + (targetVoltage-800)/50\n\trp.VREG_AND_CHIP_RESET.SetVREG_VSEL(vreg)\n\treturn true\n}\n"
  },
  {
    "path": "src/machine/machine_rp2_2350.go",
    "content": "//go:build rp2350\n\npackage machine\n\nimport (\n\t\"device/rp\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nconst (\n\tcpuFreq          = 150 * MHz\n\t_NUMBANK0_GPIOS  = 48\n\t_NUMBANK0_IRQS   = 6\n\trp2350ExtraReg   = 1\n\t_NUMIRQ          = 51\n\tnotimpl          = \"rp2350: not implemented\"\n\tRESETS_RESET_Msk = 0x1fffffff\n\tinitUnreset      = rp.RESETS_RESET_ADC |\n\t\trp.RESETS_RESET_SPI0 |\n\t\trp.RESETS_RESET_SPI1 |\n\t\trp.RESETS_RESET_UART0 |\n\t\trp.RESETS_RESET_UART1 |\n\t\trp.RESETS_RESET_USBCTRL\n\tinitDontReset = rp.RESETS_RESET_USBCTRL |\n\t\trp.RESETS_RESET_SYSCFG |\n\t\trp.RESETS_RESET_PLL_USB |\n\t\trp.RESETS_RESET_PLL_SYS |\n\t\trp.RESETS_RESET_PADS_QSPI |\n\t\trp.RESETS_RESET_IO_QSPI |\n\t\trp.RESETS_RESET_JTAG\n\tpadEnableMask = rp.PADS_BANK0_GPIO0_IE_Msk |\n\t\trp.PADS_BANK0_GPIO0_OD_Msk |\n\t\trp.PADS_BANK0_GPIO0_ISO_Msk\n)\n\nconst (\n\tPinOutput PinMode = iota\n\tPinInput\n\tPinInputPulldown\n\tPinInputPullup\n\tPinAnalog\n\tPinUART\n\tPinPWM\n\tPinI2C\n\tPinSPI\n\tPinPIO0\n\tPinPIO1\n\tPinPIO2\n)\n\nconst (\n\tclkGPOUT0 clockIndex = iota // GPIO Muxing 0\n\tclkGPOUT1                   // GPIO Muxing 1\n\tclkGPOUT2                   // GPIO Muxing 2\n\tclkGPOUT3                   // GPIO Muxing 3\n\tclkRef                      // Watchdog and timers reference clock\n\tclkSys                      // Processors, bus fabric, memory, memory mapped registers\n\tclkPeri                     // Peripheral clock for UART and SPI\n\tClkHSTX                     // High speed interface\n\tclkUSB                      // USB clock\n\tclkADC                      // ADC clock\n\tnumClocks\n)\n\nfunc calcClockDiv(srcFreq, freq uint32) uint32 {\n\t// Div register is 4.16 int.frac divider so multiply by 2^16 (left shift by 16)\n\treturn uint32((uint64(srcFreq) << 16) / uint64(freq))\n}\n\ntype clocksType struct {\n\tclk               [numClocks]clockType\n\tdftclk_xosc_ctrl  volatile.Register32\n\tdftclk_rosc_ctrl  volatile.Register32\n\tdftclk_lposc_ctrl volatile.Register32\n\tresus             struct {\n\t\tctrl   volatile.Register32\n\t\tstatus volatile.Register32\n\t}\n\tfc0      fc\n\twakeEN0  volatile.Register32\n\twakeEN1  volatile.Register32\n\tsleepEN0 volatile.Register32\n\tsleepEN1 volatile.Register32\n\tenabled0 volatile.Register32\n\tenabled1 volatile.Register32\n\tintR     volatile.Register32\n\tintE     volatile.Register32\n\tintF     volatile.Register32\n\tintS     volatile.Register32\n}\n\n// GPIO function selectors\nconst (\n\t// Connect the high-speed transmit peripheral (HSTX) to GPIO.\n\tfnHSTX pinFunc = 0\n\tfnSPI  pinFunc = 1 // Connect one of the internal PL022 SPI peripherals to GPIO\n\tfnUART pinFunc = 2\n\tfnI2C  pinFunc = 3\n\t// Connect a PWM slice to GPIO. There are eight PWM slices,\n\t// each with two outputchannels (A/B). The B pin can also be used as an input,\n\t// for frequency and duty cyclemeasurement\n\tfnPWM pinFunc = 4\n\t// Software control of GPIO, from the single-cycle IO (SIO) block.\n\t// The SIO function (F5)must be selected for the processors to drive a GPIO,\n\t// but the input is always connected,so software can check the state of GPIOs at any time.\n\tfnSIO pinFunc = 5\n\t// Connect one of the programmable IO blocks (PIO) to GPIO. PIO can implement a widevariety of interfaces,\n\t// and has its own internal pin mapping hardware, allowing flexibleplacement of digital interfaces on bank 0 GPIOs.\n\t// The PIO function (F6, F7, F8) must beselected for PIO to drive a GPIO, but the input is always connected,\n\t// so the PIOs canalways see the state of all pins.\n\tfnPIO0, fnPIO1, fnPIO2 pinFunc = 6, 7, 8\n\t// General purpose clock outputs. Can drive a number of internal clocks (including PLL\n\t// \toutputs) onto GPIOs, with optional integer divide.\n\tfnGPCK pinFunc = 9\n\t// QSPI memory interface peripheral, used for execute-in-place from external QSPI flash or PSRAM memory devices.\n\tfnQMI pinFunc = 9\n\t// USB power control signals to/from the internal USB controller.\n\tfnUSB     pinFunc = 10\n\tfnUARTAlt pinFunc = 11\n\tfnNULL    pinFunc = 0x1f\n)\n\n// Configure configures the gpio pin as per mode.\nfunc (p Pin) Configure(config PinConfig) {\n\tif p == NoPin {\n\t\treturn\n\t}\n\tp.init()\n\n\tswitch config.Mode {\n\tcase PinOutput:\n\t\tp.setFunc(fnSIO)\n\t\tif is48Pin && p >= 32 {\n\t\t\tmask := uint32(1) << (p % 32)\n\t\t\trp.SIO.GPIO_HI_OE_SET.Set(mask)\n\t\t} else {\n\t\t\tmask := uint32(1) << p\n\t\t\trp.SIO.GPIO_OE_SET.Set(mask)\n\t\t}\n\tcase PinInput:\n\t\tp.setFunc(fnSIO)\n\t\tp.pulloff()\n\tcase PinInputPulldown:\n\t\tp.setFunc(fnSIO)\n\t\tp.pulldown()\n\tcase PinInputPullup:\n\t\tp.setFunc(fnSIO)\n\t\tp.pullup()\n\tcase PinAnalog:\n\t\tp.setFunc(fnNULL)\n\t\tp.pulloff()\n\t\t// Disable digital input.\n\t\tp.padCtrl().ClearBits(rp.PADS_BANK0_GPIO0_IE)\n\tcase PinUART:\n\t\tp.setFunc(fnUART)\n\tcase PinPWM:\n\t\tp.setFunc(fnPWM)\n\tcase PinI2C:\n\t\t// IO config according to 4.3.1.3 of rp2040 datasheet.\n\t\tp.setFunc(fnI2C)\n\t\tp.pullup()\n\t\tp.setSchmitt(true)\n\t\tp.setSlew(false)\n\tcase PinSPI:\n\t\tp.setFunc(fnSPI)\n\tcase PinPIO0:\n\t\tp.setFunc(fnPIO0)\n\tcase PinPIO1:\n\t\tp.setFunc(fnPIO1)\n\tcase PinPIO2:\n\t\tp.setFunc(fnPIO2)\n\t}\n}\n\nvar (\n\ttimer = (*timerType)(unsafe.Pointer(rp.TIMER0))\n)\n\n// Enable or disable a specific interrupt on the executing core.\n// num is the interrupt number which must be in [0,_NUMIRQ).\nfunc irqSet(num uint32, enabled bool) {\n\tif num >= _NUMIRQ {\n\t\treturn\n\t}\n\n\tregister_index := num / 32\n\tvar mask uint32 = 1 << (num % 32)\n\n\tif enabled {\n\t\t// Clear pending before enable\n\t\t//(if IRQ is actually asserted, it will immediately re-pend)\n\t\tif register_index == 0 {\n\t\t\trp.PPB.NVIC_ICPR0.Set(mask)\n\t\t\trp.PPB.NVIC_ISER0.Set(mask)\n\t\t} else {\n\t\t\trp.PPB.NVIC_ICPR1.Set(mask)\n\t\t\trp.PPB.NVIC_ISER1.Set(mask)\n\t\t}\n\t} else {\n\t\tif register_index == 0 {\n\t\t\trp.PPB.NVIC_ICER0.Set(mask)\n\t\t} else {\n\t\t\trp.PPB.NVIC_ICER1.Set(mask)\n\t\t}\n\t}\n}\n\nfunc (clks *clocksType) initRTC() {} // No RTC on RP2350.\n\nfunc (clks *clocksType) initTicks() {\n\trp.TICKS.SetTIMER0_CTRL_ENABLE(0)\n\trp.TICKS.SetTIMER0_CYCLES(12)\n\trp.TICKS.SetTIMER0_CTRL_ENABLE(1)\n}\n\n// startTick starts the watchdog tick.\n// On RP2040, the watchdog contained a tick generator used to generate a 1μs tick for the watchdog. This was also\n// distributed to the system timer. On RP2350, the watchdog instead takes a tick input from the system-level ticks block. See Section 8.5.\nfunc (wd *watchdogImpl) startTick(cycles uint32) {\n\trp.TICKS.WATCHDOG_CTRL.SetBits(1)\n}\n\nfunc adjustCoreVoltage() bool {\n\treturn false\n}\n"
  },
  {
    "path": "src/machine/machine_rp2_2350a.go",
    "content": "//go:build rp2350 && !rp2350b\n\npackage machine\n\nimport \"device/rp\"\n\n// Analog pins on RP2350a.\nconst (\n\tADC0 Pin = GPIO26\n\tADC1 Pin = GPIO27\n\tADC2 Pin = GPIO28\n\tADC3 Pin = GPIO29\n\n\t// fifth ADC channel.\n\tthermADC = 30\n)\n\n// validPins confirms that the SPI pin selection is a legitimate one\n// for the the 2350a chip.\nfunc (spi *SPI) validPins(config SPIConfig) error {\n\tvar okSDI, okSDO, okSCK bool\n\tswitch spi.Bus {\n\tcase rp.SPI0:\n\t\tokSDI = config.SDI == 0 || config.SDI == 4 || config.SDI == 16 || config.SDI == 20\n\t\tokSDO = config.SDO == 3 || config.SDO == 7 || config.SDO == 19 || config.SDO == 23\n\t\tokSCK = config.SCK == 2 || config.SCK == 6 || config.SCK == 18 || config.SCK == 22\n\tcase rp.SPI1:\n\t\tokSDI = config.SDI == 8 || config.SDI == 12 || config.SDI == 24 || config.SDI == 28\n\t\tokSDO = config.SDO == 11 || config.SDO == 15 || config.SDO == 27\n\t\tokSCK = config.SCK == 10 || config.SCK == 14 || config.SCK == 26\n\t}\n\tswitch {\n\tcase !okSDI:\n\t\treturn errSPIInvalidSDI\n\tcase !okSDO:\n\t\treturn errSPIInvalidSDO\n\tcase !okSCK:\n\t\treturn errSPIInvalidSCK\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "src/machine/machine_rp2_2350b.go",
    "content": "//go:build rp2350b\n\npackage machine\n\nimport \"device/rp\"\n\n// RP2350B has additional pins.\n\nconst (\n\tGPIO30 Pin = 30 // peripherals: PWM7 channel A, I2C1 SDA\n\tGPIO31 Pin = 31 // peripherals: PWM7 channel B, I2C1 SCL\n\tGPIO32 Pin = 32 // peripherals: PWM8 channel A, I2C0 SDA\n\tGPIO33 Pin = 33 // peripherals: PWM8 channel B, I2C0 SCL\n\tGPIO34 Pin = 34 // peripherals: PWM9 channel A, I2C1 SDA\n\tGPIO35 Pin = 35 // peripherals: PWM9 channel B, I2C1 SCL\n\tGPIO36 Pin = 36 // peripherals: PWM10 channel A, I2C0 SDA\n\tGPIO37 Pin = 37 // peripherals: PWM10 channel B, I2C0 SCL\n\tGPIO38 Pin = 38 // peripherals: PWM11 channel A, I2C1 SDA\n\tGPIO39 Pin = 39 // peripherals: PWM11 channel B, I2C1 SCL\n\tGPIO40 Pin = 40 // peripherals: PWM8 channel A, I2C0 SDA\n\tGPIO41 Pin = 41 // peripherals: PWM8 channel B, I2C0 SCL\n\tGPIO42 Pin = 42 // peripherals: PWM9 channel A, I2C1 SDA\n\tGPIO43 Pin = 43 // peripherals: PWM9 channel B, I2C1 SCL\n\tGPIO44 Pin = 44 // peripherals: PWM10 channel A, I2C0 SDA\n\tGPIO45 Pin = 45 // peripherals: PWM10 channel B, I2C0 SCL\n\tGPIO46 Pin = 46 // peripherals: PWM11 channel A, I2C1 SDA\n\tGPIO47 Pin = 47 // peripherals: PWM11 channel B, I2C1 SCL\n)\n\n// Analog pins on 2350b.\nconst (\n\tADC0 Pin = GPIO40\n\tADC1 Pin = GPIO41\n\tADC2 Pin = GPIO42\n\tADC3 Pin = GPIO43\n\tADC4 Pin = GPIO44\n\tADC5 Pin = GPIO45\n\tADC6 Pin = GPIO46\n\tADC7 Pin = GPIO47\n\t// Ninth ADC channel.\n\tthermADC = 48\n)\n\n// Additional PWMs on the RP2350B.\nvar (\n\tPWM8  = getPWMGroup(8)\n\tPWM9  = getPWMGroup(9)\n\tPWM10 = getPWMGroup(10)\n\tPWM11 = getPWMGroup(11)\n)\n\n// validPins confirms that the SPI pin selection is a legitimate one\n// for the the 2350b chip.\nfunc (spi *SPI) validPins(config SPIConfig) error {\n\tvar okSDI, okSDO, okSCK bool\n\tswitch spi.Bus {\n\tcase rp.SPI0:\n\t\tokSDI = config.SDI == 0 || config.SDI == 4 || config.SDI == 16 || config.SDI == 20 || config.SDI == 32 || config.SDI == 36\n\t\tokSDO = config.SDO == 3 || config.SDO == 7 || config.SDO == 19 || config.SDO == 23 || config.SDO == 35 || config.SDO == 39\n\t\tokSCK = config.SCK == 2 || config.SCK == 6 || config.SCK == 18 || config.SCK == 22 || config.SCK == 34 || config.SCK == 38\n\tcase rp.SPI1:\n\t\tokSDI = config.SDI == 8 || config.SDI == 12 || config.SDI == 24 || config.SDI == 28 || config.SDI == 40 || config.SDI == 44\n\t\tokSDO = config.SDO == 11 || config.SDO == 15 || config.SDO == 27 || config.SDO == 31 || config.SDO == 43 || config.SDO == 47\n\t\tokSCK = config.SCK == 10 || config.SCK == 14 || config.SCK == 26 || config.SCK == 30 || config.SCK == 42 || config.SCK == 46\n\t}\n\tswitch {\n\tcase !okSDI:\n\t\treturn errSPIInvalidSDI\n\tcase !okSDO:\n\t\treturn errSPIInvalidSDO\n\tcase !okSCK:\n\t\treturn errSPIInvalidSCK\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "src/machine/machine_rp2_adc.go",
    "content": "//go:build rp2040 || rp2350\n\npackage machine\n\nimport (\n\t\"device/rp\"\n\t\"errors\"\n\t\"sync\"\n)\n\n// ADCChannel is the ADC peripheral mux channel. 0-4.\ntype ADCChannel uint8\n\n// Used to serialise ADC sampling\nvar adcLock sync.Mutex\n\n// ADC peripheral reference voltage (mV)\nvar adcAref uint32\n\n// InitADC resets the ADC peripheral.\nfunc InitADC() {\n\trp.RESETS.RESET.SetBits(rp.RESETS_RESET_ADC)\n\trp.RESETS.RESET.ClearBits(rp.RESETS_RESET_ADC)\n\tfor !rp.RESETS.RESET_DONE.HasBits(rp.RESETS_RESET_ADC) {\n\t}\n\t// enable ADC\n\trp.ADC.CS.Set(rp.ADC_CS_EN)\n\tadcAref = 3300\n\twaitForReady()\n}\n\n// Configure sets the ADC pin to analog input mode.\nfunc (a ADC) Configure(config ADCConfig) error {\n\tc, err := a.GetADCChannel()\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn c.Configure(config)\n}\n\n// Get returns a one-shot ADC sample reading.\nfunc (a ADC) Get() uint16 {\n\tif c, err := a.GetADCChannel(); err == nil {\n\t\treturn c.getOnce()\n\t}\n\t// Not an ADC pin!\n\treturn 0\n}\n\n// GetADCChannel returns the channel associated with the ADC pin.\nfunc (a ADC) GetADCChannel() (c ADCChannel, err error) {\n\tif a.Pin < ADC0 {\n\t\treturn 0, errors.New(\"no ADC channel for pin value\")\n\t}\n\treturn ADCChannel(a.Pin - ADC0), nil\n}\n\n// Configure sets the channel's associated pin to analog input mode.\n// The powered on temperature sensor increases ADC_AVDD current by approximately 40 μA.\nfunc (c ADCChannel) Configure(config ADCConfig) error {\n\tif config.Reference != 0 {\n\t\tadcAref = config.Reference\n\t}\n\tp, err := c.Pin()\n\tif err != nil {\n\t\treturn err\n\t}\n\tp.Configure(PinConfig{Mode: PinAnalog})\n\treturn nil\n}\n\n// getOnce returns a one-shot ADC sample reading from an ADC channel.\nfunc (c ADCChannel) getOnce() uint16 {\n\t// Make it safe to sample multiple ADC channels in separate go routines.\n\tadcLock.Lock()\n\trp.ADC.CS.ReplaceBits(uint32(c)<<rp.ADC_CS_AINSEL_Pos, rp.ADC_CS_AINSEL_Msk, 0)\n\trp.ADC.CS.SetBits(rp.ADC_CS_START_ONCE)\n\n\twaitForReady()\n\tv := rp.ADC.RESULT.Get()\n\tadcLock.Unlock()\n\n\t// rp2040 is a 12-bit ADC, scale raw reading to 16-bits.\n\treturn uint16(v) << 4\n}\n\n// getVoltage does a one-shot sample and returns a millivolts reading.\n// Integer portion is stored in the high 16 bits and fractional in the low 16 bits.\nfunc (c ADCChannel) getVoltage() uint32 {\n\treturn (adcAref << 16) / (1 << 12) * uint32(c.getOnce()>>4)\n}\n\n// ReadTemperature does a one-shot sample of the internal temperature sensor and returns a milli-celsius reading.\nfunc ReadTemperature() (millicelsius int32) {\n\tif rp.ADC.CS.Get()&rp.ADC_CS_EN == 0 {\n\t\tInitADC()\n\t}\n\tthermChan, _ := ADC{Pin: thermADC}.GetADCChannel()\n\t// Enable temperature sensor bias source\n\trp.ADC.CS.SetBits(rp.ADC_CS_TS_EN)\n\n\t// T = 27 - (ADC_voltage - 0.706)/0.001721\n\t// 1/0.001721 ≈ 581\n\treturn int32(((int64(27000) << 16) - ((int64(thermChan.getVoltage()) - (int64(706) << 16)) * 581)) >> 16)\n}\n\n// waitForReady spins waiting for the ADC peripheral to become ready.\nfunc waitForReady() {\n\tfor !rp.ADC.CS.HasBits(rp.ADC_CS_READY) {\n\t}\n}\n\n// The Pin method returns the GPIO Pin associated with the ADC mux channel, if it has one.\nfunc (c ADCChannel) Pin() (p Pin, err error) {\n\treturn Pin(c) + ADC0, nil\n}\n"
  },
  {
    "path": "src/machine/machine_rp2_clocks.go",
    "content": "//go:build rp2040 || rp2350\n\npackage machine\n\nimport (\n\t\"device/arm\"\n\t\"device/rp\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nfunc CPUFrequency() uint32 {\n\treturn cpuFreq\n}\n\n// clockIndex identifies a hardware clock\ntype clockIndex uint8\n\ntype clockType struct {\n\tctrl     volatile.Register32\n\tdiv      volatile.Register32\n\tselected volatile.Register32\n}\n\ntype fc struct {\n\trefKHz   volatile.Register32\n\tminKHz   volatile.Register32\n\tmaxKHz   volatile.Register32\n\tdelay    volatile.Register32\n\tinterval volatile.Register32\n\tsrc      volatile.Register32\n\tstatus   volatile.Register32\n\tresult   volatile.Register32\n}\n\nvar clocks = (*clocksType)(unsafe.Pointer(rp.CLOCKS))\n\nvar configuredFreq [numClocks]uint32\n\ntype clock struct {\n\t*clockType\n\tcix clockIndex\n}\n\n// The delay in seconds for core voltage adjustments to\n// settle. Taken from the Pico SDK.\nconst _VREG_VOLTAGE_AUTO_ADJUST_DELAY = 1 / 1e3\n\n// clock returns the clock identified by cix.\nfunc (clks *clocksType) clock(cix clockIndex) clock {\n\treturn clock{\n\t\t&clks.clk[cix],\n\t\tcix,\n\t}\n}\n\n// hasGlitchlessMux returns true if clock contains a glitchless multiplexer.\n//\n// Clock muxing consists of two components:\n//\n// A glitchless mux, which can be switched freely, but whose inputs must be\n// free-running.\n//\n// An auxiliary (glitchy) mux, whose output glitches when switched, but has\n// no constraints on its inputs.\n//\n// Not all clocks have both types of mux.\nfunc (clk *clock) hasGlitchlessMux() bool {\n\treturn clk.cix == clkSys || clk.cix == clkRef\n}\n\n// configure configures the clock by selecting the main clock source src\n// and the auxiliary clock source auxsrc\n// and finally setting the clock frequency to freq\n// given the input clock source frequency srcFreq.\nfunc (clk *clock) configure(src, auxsrc, srcFreq, freq uint32) {\n\tif freq > srcFreq {\n\t\tpanic(\"clock frequency cannot be greater than source frequency\")\n\t}\n\n\tdiv := calcClockDiv(srcFreq, freq)\n\n\t// If increasing divisor, set divisor before source. Otherwise set source\n\t// before divisor. This avoids a momentary overspeed when e.g. switching\n\t// to a faster source and increasing divisor to compensate.\n\tif div > clk.div.Get() {\n\t\tclk.div.Set(div)\n\t}\n\n\t// If switching a glitchless slice (ref or sys) to an aux source, switch\n\t// away from aux *first* to avoid passing glitches when changing aux mux.\n\t// Assume (!!!) glitchless source 0 is no faster than the aux source.\n\tif clk.hasGlitchlessMux() && src == rp.CLOCKS_CLK_SYS_CTRL_SRC_CLKSRC_CLK_SYS_AUX {\n\t\tclk.ctrl.ClearBits(rp.CLOCKS_CLK_REF_CTRL_SRC_Msk)\n\t\tfor !clk.selected.HasBits(1) {\n\t\t}\n\t} else\n\t// If no glitchless mux, cleanly stop the clock to avoid glitches\n\t// propagating when changing aux mux. Note it would be a really bad idea\n\t// to do this on one of the glitchless clocks (clkSys, clkRef).\n\t{\n\t\t// Disable clock. On clkRef and ClkSys this does nothing,\n\t\t// all other clocks have the ENABLE bit in the same position.\n\t\tclk.ctrl.ClearBits(rp.CLOCKS_CLK_GPOUT0_CTRL_ENABLE_Msk)\n\t\tif configuredFreq[clk.cix] > 0 {\n\t\t\t// Delay for 3 cycles of the target clock, for ENABLE propagation.\n\t\t\t// Note XOSC_COUNT is not helpful here because XOSC is not\n\t\t\t// necessarily running, nor is timer... so, 3 cycles per loop:\n\t\t\tdelayCyc := configuredFreq[clkSys]/configuredFreq[clk.cix] + 1\n\t\t\tfor delayCyc != 0 {\n\t\t\t\t// This could be done more efficiently but TinyGo inline\n\t\t\t\t// assembly is not yet capable enough to express that. In the\n\t\t\t\t// meantime, this forces at least 3 cycles per loop.\n\t\t\t\tdelayCyc--\n\t\t\t\tarm.Asm(\"nop\\nnop\\nnop\")\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set aux mux first, and then glitchless mux if this clock has one.\n\tclk.ctrl.ReplaceBits(auxsrc<<rp.CLOCKS_CLK_SYS_CTRL_AUXSRC_Pos,\n\t\trp.CLOCKS_CLK_SYS_CTRL_AUXSRC_Msk, 0)\n\n\tif clk.hasGlitchlessMux() {\n\t\tclk.ctrl.ReplaceBits(src<<rp.CLOCKS_CLK_REF_CTRL_SRC_Pos,\n\t\t\trp.CLOCKS_CLK_REF_CTRL_SRC_Msk, 0)\n\t\tfor !clk.selected.HasBits(1 << src) {\n\t\t}\n\t}\n\n\t// Enable clock. On clkRef and clkSys this does nothing,\n\t// all other clocks have the ENABLE bit in the same position.\n\tclk.ctrl.SetBits(rp.CLOCKS_CLK_GPOUT0_CTRL_ENABLE)\n\n\t// Now that the source is configured, we can trust that the user-supplied\n\t// divisor is a safe value.\n\tclk.div.Set(div)\n\n\t// Store the configured frequency\n\tconfiguredFreq[clk.cix] = freq\n\n}\n\nvar pllsysFB, pllsysPD1, pllsysPD2 uint32\n\n// Compute clock dividers.\n//\n// Note that the entire init function is computed at compile time\n// by interp.\nfunc init() {\n\tfb, _, pd1, pd2, err := pllSearch{LockRefDiv: 1}.CalcDivs(xoscFreq*MHz, cpuFreq, MHz)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tpllsysFB, pllsysPD1, pllsysPD2 = uint32(fb), uint32(pd1), uint32(pd2)\n}\n\n// init initializes the clock hardware.\n//\n// Must be called before any other clock function.\nfunc (clks *clocksType) init() {\n\t// Start the watchdog tick\n\tWatchdog.startTick(xoscFreq)\n\n\t// Disable resus that may be enabled from previous software\n\trp.CLOCKS.SetCLK_SYS_RESUS_CTRL_CLEAR(0)\n\n\t// Enable the xosc\n\txosc.init()\n\n\t// Before we touch PLLs, switch sys and ref cleanly away from their aux sources.\n\tclks.clk[clkSys].ctrl.ClearBits(rp.CLOCKS_CLK_SYS_CTRL_SRC_Msk)\n\tfor !clks.clk[clkSys].selected.HasBits(0x1) {\n\t}\n\n\tclks.clk[clkRef].ctrl.ClearBits(rp.CLOCKS_CLK_REF_CTRL_SRC_Msk)\n\tfor !clks.clk[clkRef].selected.HasBits(0x1) {\n\t}\n\n\t// Configure PLLs\n\t//                   REF     FBDIV VCO            POSTDIV\n\t// pllSys: 12 / 1 = 12MHz * 125 = 1500MHZ / 6 / 2 = 125MHz\n\t// pllUSB: 12 / 1 = 12MHz * 40  = 480 MHz / 5 / 2 =  48MHz\n\tpllSys.init(1, pllsysFB, pllsysPD1, pllsysPD2)\n\tpllUSB.init(1, 40, 5, 2)\n\n\t// Configure clocks\n\t// clkRef = xosc (12MHz) / 1 = 12MHz\n\tcref := clks.clock(clkRef)\n\tcref.configure(rp.CLOCKS_CLK_REF_CTRL_SRC_XOSC_CLKSRC,\n\t\t0, // No aux mux\n\t\txoscFreq,\n\t\txoscFreq)\n\n\tif adjustCoreVoltage() {\n\t\t// Wait for the voltage to settle.\n\t\tconst cycles = _VREG_VOLTAGE_AUTO_ADJUST_DELAY * xoscFreq * MHz\n\t\tfor i := 0; i < cycles; i++ {\n\t\t\tarm.Asm(\"nop\")\n\t\t}\n\t}\n\n\t// clkSys = pllSys (125MHz) / 1 = 125MHz\n\tcsys := clks.clock(clkSys)\n\tcsys.configure(rp.CLOCKS_CLK_SYS_CTRL_SRC_CLKSRC_CLK_SYS_AUX,\n\t\trp.CLOCKS_CLK_SYS_CTRL_AUXSRC_CLKSRC_PLL_SYS,\n\t\tcpuFreq,\n\t\tcpuFreq)\n\n\t// clkUSB = pllUSB (48MHz) / 1 = 48MHz\n\tcusb := clks.clock(clkUSB)\n\tcusb.configure(0, // No GLMUX\n\t\trp.CLOCKS_CLK_USB_CTRL_AUXSRC_CLKSRC_PLL_USB,\n\t\t48*MHz,\n\t\t48*MHz)\n\n\t// clkADC = pllUSB (48MHZ) / 1 = 48MHz\n\tcadc := clks.clock(clkADC)\n\tcadc.configure(0, // No GLMUX\n\t\trp.CLOCKS_CLK_ADC_CTRL_AUXSRC_CLKSRC_PLL_USB,\n\t\t48*MHz,\n\t\t48*MHz)\n\n\tclks.initRTC()\n\n\t// clkPeri = clkSys. Used as reference clock for Peripherals.\n\t// No dividers so just select and enable.\n\t// Normally choose clkSys or clkUSB.\n\tcperi := clks.clock(clkPeri)\n\tcperi.configure(0,\n\t\trp.CLOCKS_CLK_PERI_CTRL_AUXSRC_CLK_SYS,\n\t\tcpuFreq,\n\t\tcpuFreq)\n\n\tclks.initTicks()\n}\n"
  },
  {
    "path": "src/machine/machine_rp2_flash.go",
    "content": "//go:build rp2040 || rp2350\n\npackage machine\n\nimport (\n\t\"unsafe\"\n)\n\n// EnterBootloader should perform a system reset in preparation\n// to switch to the bootloader to flash new firmware.\nfunc EnterBootloader() {\n\tenterBootloader()\n}\n\n// 13 = 1 + FLASH_RUID_DUMMY_BYTES(4) + FLASH_RUID_DATA_BYTES(8)\nvar deviceIDBuf [13]byte\n\n// DeviceID returns an identifier that is unique within\n// a particular chipset.\n//\n// The identity is one burnt into the MCU itself, or the\n// flash chip at time of manufacture.\n//\n// It's possible that two different vendors may allocate\n// the same DeviceID, so callers should take this into\n// account if needing to generate a globally unique id.\n//\n// The length of the hardware ID is vendor-specific, but\n// 8 bytes (64 bits) is common.\nfunc DeviceID() []byte {\n\tdeviceIDBuf[0] = 0x4b // FLASH_RUID_CMD\n\n\terr := doFlashCommand(deviceIDBuf[:], deviceIDBuf[:])\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\treturn deviceIDBuf[5:13]\n}\n\n// compile-time check for ensuring we fulfill BlockDevice interface\nvar _ BlockDevice = flashBlockDevice{}\n\nvar Flash flashBlockDevice\n\ntype flashBlockDevice struct {\n}\n\n// ReadAt reads the given number of bytes from the block device.\nfunc (f flashBlockDevice) ReadAt(p []byte, off int64) (n int, err error) {\n\tif readAddress(off) > FlashDataEnd() {\n\t\treturn 0, errFlashCannotReadPastEOF\n\t}\n\n\tdata := unsafe.Slice((*byte)(unsafe.Pointer(readAddress(off))), len(p))\n\tcopy(p, data)\n\n\treturn len(p), nil\n}\n\n// WriteAt writes the given number of bytes to the block device.\n// Only word (32 bits) length data can be programmed.\n// If the length of p is not long enough it will be padded with 0xFF bytes.\n// This method assumes that the destination is already erased.\nfunc (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) {\n\treturn f.writeAt(p, off)\n}\n\n// Size returns the number of bytes in this block device.\nfunc (f flashBlockDevice) Size() int64 {\n\treturn int64(FlashDataEnd() - FlashDataStart())\n}\n\nconst writeBlockSize = 1 << 8\n\n// WriteBlockSize returns the block size in which data can be written to\n// memory. It can be used by a client to optimize writes, non-aligned writes\n// should always work correctly.\nfunc (f flashBlockDevice) WriteBlockSize() int64 {\n\treturn writeBlockSize\n}\n\nconst eraseBlockSizeValue = 1 << 12\n\nfunc eraseBlockSize() int64 {\n\treturn eraseBlockSizeValue\n}\n\n// EraseBlockSize returns the smallest erasable area on this particular chip\n// in bytes. This is used for the block size in EraseBlocks.\nfunc (f flashBlockDevice) EraseBlockSize() int64 {\n\treturn eraseBlockSize()\n}\n\n// EraseBlocks erases the given number of blocks. An implementation may\n// transparently coalesce ranges of blocks into larger bundles if the chip\n// supports this. The start and len parameters are in block numbers, use\n// EraseBlockSize to map addresses to blocks.\nfunc (f flashBlockDevice) EraseBlocks(start, length int64) error {\n\treturn f.eraseBlocks(start, length)\n}\n\n// return the correct address to be used for write\nfunc writeAddress(off int64) uintptr {\n\treturn readAddress(off) - uintptr(memoryStart)\n}\n\n// return the correct address to be used for reads\nfunc readAddress(off int64) uintptr {\n\treturn FlashDataStart() + uintptr(off)\n}\n"
  },
  {
    "path": "src/machine/machine_rp2_gpio.go",
    "content": "//go:build rp2040 || rp2350\n\npackage machine\n\nimport (\n\t\"device/rp\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\ntype ioType struct {\n\tstatus volatile.Register32\n\tctrl   volatile.Register32\n}\n\ntype irqCtrl struct {\n\tintE [_NUMBANK0_IRQS]volatile.Register32\n\tintF [_NUMBANK0_IRQS]volatile.Register32\n\tintS [_NUMBANK0_IRQS]volatile.Register32\n}\n\ntype irqSummary struct {\n\tproc [2]struct {\n\t\tsecure    [2]volatile.Register32\n\t\tnonsecure [2]volatile.Register32\n\t}\n\tcomaWake struct {\n\t\tsecure    [2]volatile.Register32\n\t\tnonsecure [2]volatile.Register32\n\t}\n}\n\ntype ioBank0Type struct {\n\tio                 [_NUMBANK0_GPIOS]ioType\n\t_                  [rp2350ExtraReg][128]byte\n\tirqsum             [rp2350ExtraReg]irqSummary\n\tintR               [_NUMBANK0_IRQS]volatile.Register32\n\tproc0IRQctrl       irqCtrl\n\tproc1IRQctrl       irqCtrl\n\tdormantWakeIRQctrl irqCtrl\n}\n\nvar ioBank0 = (*ioBank0Type)(unsafe.Pointer(rp.IO_BANK0))\n\ntype padsBank0Type struct {\n\tvoltageSelect volatile.Register32\n\tio            [_NUMBANK0_GPIOS]volatile.Register32\n}\n\nvar padsBank0 = (*padsBank0Type)(unsafe.Pointer(rp.PADS_BANK0))\n\n// pinFunc represents a GPIO function.\n//\n// Each GPIO can have one function selected at a time.\n// Likewise, each peripheral input (e.g. UART0 RX) should only be  selected\n// on one GPIO at a time. If the same peripheral input is connected to multiple GPIOs,\n// the peripheral sees the logical OR of these GPIO inputs.\ntype pinFunc uint8\n\nfunc (p Pin) PortMaskSet() (*uint32, uint32) {\n\treturn (*uint32)(unsafe.Pointer(&rp.SIO.GPIO_OUT_SET)), 1 << p\n}\n\n// set drives the pin high\nfunc (p Pin) set() {\n\tif is48Pin && p >= 32 {\n\t\tmask := uint32(1) << (p % 32)\n\t\trp.SIO.GPIO_HI_OUT_SET.Set(mask)\n\t} else {\n\t\tmask := uint32(1) << p\n\t\trp.SIO.GPIO_OUT_SET.Set(mask)\n\t}\n}\n\nfunc (p Pin) PortMaskClear() (*uint32, uint32) {\n\treturn (*uint32)(unsafe.Pointer(&rp.SIO.GPIO_OUT_CLR)), 1 << p\n}\n\n// clr drives the pin low\nfunc (p Pin) clr() {\n\tif is48Pin && p >= 32 {\n\t\tmask := uint32(1) << (p % 32)\n\t\trp.SIO.GPIO_HI_OUT_CLR.Set(mask)\n\t} else {\n\t\tmask := uint32(1) << p\n\t\trp.SIO.GPIO_OUT_CLR.Set(mask)\n\t}\n}\n\n// xor toggles the pin\nfunc (p Pin) xor() {\n\tif is48Pin && p >= 32 {\n\t\tmask := uint32(1) << (p % 32)\n\t\trp.SIO.GPIO_HI_OUT_XOR.Set(mask)\n\t} else {\n\t\tmask := uint32(1) << p\n\t\trp.SIO.GPIO_OUT_XOR.Set(mask)\n\t}\n}\n\n// get returns the pin value\nfunc (p Pin) get() bool {\n\tif is48Pin && p >= 32 {\n\t\treturn rp.SIO.GPIO_HI_IN.HasBits(1 << (p % 32))\n\t}\n\treturn rp.SIO.GPIO_IN.HasBits(1 << p)\n}\n\nfunc (p Pin) ioCtrl() *volatile.Register32 {\n\treturn &ioBank0.io[p].ctrl\n}\n\nfunc (p Pin) padCtrl() *volatile.Register32 {\n\treturn &padsBank0.io[p]\n}\n\nfunc (p Pin) pullup() {\n\tp.padCtrl().SetBits(rp.PADS_BANK0_GPIO0_PUE)\n\tp.padCtrl().ClearBits(rp.PADS_BANK0_GPIO0_PDE)\n}\n\nfunc (p Pin) pulldown() {\n\tp.padCtrl().SetBits(rp.PADS_BANK0_GPIO0_PDE)\n\tp.padCtrl().ClearBits(rp.PADS_BANK0_GPIO0_PUE)\n}\n\nfunc (p Pin) pulloff() {\n\tp.padCtrl().ClearBits(rp.PADS_BANK0_GPIO0_PDE)\n\tp.padCtrl().ClearBits(rp.PADS_BANK0_GPIO0_PUE)\n}\n\n// setSlew sets pad slew rate control.\n// true sets to fast. false sets to slow.\nfunc (p Pin) setSlew(sr bool) {\n\tp.padCtrl().ReplaceBits(boolToBit(sr)<<rp.PADS_BANK0_GPIO0_SLEWFAST_Pos, rp.PADS_BANK0_GPIO0_SLEWFAST_Msk, 0)\n}\n\n// setSchmitt enables or disables Schmitt trigger.\nfunc (p Pin) setSchmitt(trigger bool) {\n\tp.padCtrl().ReplaceBits(boolToBit(trigger)<<rp.PADS_BANK0_GPIO0_SCHMITT_Pos, rp.PADS_BANK0_GPIO0_SCHMITT_Msk, 0)\n}\n\n// setFunc will set pin function to fn.\nfunc (p Pin) setFunc(fn pinFunc) {\n\t// Set input enable, Clear output disable\n\tp.padCtrl().ReplaceBits(rp.PADS_BANK0_GPIO0_IE, padEnableMask, 0)\n\n\t// Zero all fields apart from fsel; we want this IO to do what the peripheral tells it.\n\t// This doesn't affect e.g. pullup/pulldown, as these are in pad controls.\n\tp.ioCtrl().Set(uint32(fn) << rp.IO_BANK0_GPIO0_CTRL_FUNCSEL_Pos)\n}\n\n// init initializes the gpio pin\nfunc (p Pin) init() {\n\tif is48Pin && p >= 32 {\n\t\tmask := uint32(1) << (p % 32)\n\t\trp.SIO.GPIO_HI_OE_CLR.Set(mask)\n\t} else {\n\t\tmask := uint32(1) << p\n\t\trp.SIO.GPIO_OE_CLR.Set(mask)\n\t}\n\tp.clr()\n}\n\n// Set drives the pin high if value is true else drives it low.\nfunc (p Pin) Set(value bool) {\n\tif p == NoPin {\n\t\treturn\n\t}\n\tif value {\n\t\tp.set()\n\t} else {\n\t\tp.clr()\n\t}\n}\n\n// Get reads the pin value.\nfunc (p Pin) Get() bool {\n\treturn p.get()\n}\n\n// PinChange represents one or more trigger events that can happen on a given GPIO pin\n// on the RP2040. ORed PinChanges are valid input to most IRQ functions.\ntype PinChange uint8\n\n// Pin change interrupt constants for SetInterrupt.\nconst (\n\t// Edge falling\n\tPinFalling PinChange = 4 << iota\n\t// Edge rising\n\tPinRising\n\n\tPinToggle = PinFalling | PinRising\n)\n\n// Callbacks to be called for pins configured with SetInterrupt.\nvar (\n\tpinCallbacks [2][_NUMBANK0_GPIOS]func(Pin)\n\tsetInt       [2][_NUMBANK0_GPIOS]bool\n)\n\n// SetInterrupt sets an interrupt to be executed when a particular pin changes\n// state. The pin should already be configured as an input, including a pull up\n// or down if no external pull is provided.\n//\n// This call will replace a previously set callback on this pin. You can pass a\n// nil func to unset the pin change interrupt. If you do so, the change\n// parameter is ignored and can be set to any value (such as 0).\nfunc (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error {\n\tif p == NoPin {\n\t\treturn nil\n\t}\n\tif p > 31 || p < 0 {\n\t\treturn ErrInvalidInputPin\n\t}\n\tcore := CurrentCore()\n\tif callback == nil {\n\t\t// disable current interrupt\n\t\tp.setInterrupt(change, false)\n\t\tpinCallbacks[core][p] = nil\n\t\treturn nil\n\t}\n\n\tif pinCallbacks[core][p] != nil {\n\t\t// Callback already configured. Should disable callback by passing a nil callback first.\n\t\treturn ErrNoPinChangeChannel\n\t}\n\tp.setInterrupt(change, true)\n\tpinCallbacks[core][p] = callback\n\n\tif setInt[core][p] {\n\t\t// interrupt has already been set. Exit.\n\t\treturn nil\n\t}\n\tinterrupt.New(rp.IRQ_IO_IRQ_BANK0, gpioHandleInterrupt).Enable()\n\tirqSet(rp.IRQ_IO_IRQ_BANK0, true)\n\treturn nil\n}\n\n// gpioHandleInterrupt finds the corresponding pin for the interrupt.\n// C SDK equivalent of gpio_irq_handler\nfunc gpioHandleInterrupt(intr interrupt.Interrupt) {\n\n\tcore := CurrentCore()\n\tvar gpio Pin\n\tfor gpio = 0; gpio < _NUMBANK0_GPIOS; gpio++ {\n\t\tvar base *irqCtrl\n\t\tswitch core {\n\t\tcase 0:\n\t\t\tbase = &ioBank0.proc0IRQctrl\n\t\tcase 1:\n\t\t\tbase = &ioBank0.proc1IRQctrl\n\t\t}\n\n\t\tstatreg := base.intS[gpio>>3].Get()\n\t\tchange := getIntChange(gpio, statreg)\n\t\tif change != 0 {\n\t\t\tgpio.acknowledgeInterrupt(change)\n\t\t\tcallback := pinCallbacks[core][gpio]\n\t\t\tif callback != nil {\n\t\t\t\tcallback(gpio)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// events returns the bit representation of the pin change for the rp2040.\nfunc (change PinChange) events() uint32 {\n\treturn uint32(change)\n}\n\n// intBit is the bit storage form of a PinChange for a given Pin\n// in the IO_BANK0 interrupt registers (page 269 RP2040 Datasheet).\nfunc (p Pin) ioIntBit(change PinChange) uint32 {\n\treturn change.events() << (4 * (p % 8))\n}\n\n// Acquire interrupt data from a INT status register.\nfunc getIntChange(p Pin, status uint32) PinChange {\n\treturn PinChange(status>>(4*(p%8))) & 0xf\n}\n"
  },
  {
    "path": "src/machine/machine_rp2_i2c.go",
    "content": "//go:build rp2040 || rp2350\n\npackage machine\n\nimport (\n\t\"device/rp\"\n\t\"errors\"\n\t\"internal/itoa\"\n)\n\n// I2C on the RP2040/RP2350\nvar (\n\tI2C0  = &_I2C0\n\t_I2C0 = I2C{\n\t\tBus: rp.I2C0,\n\t}\n\tI2C1  = &_I2C1\n\t_I2C1 = I2C{\n\t\tBus: rp.I2C1,\n\t}\n)\n\n// The I2C target implementation is based on the C implementation from\n// here: https://github.com/vmilea/pico_i2c_slave\n\n// Features: Taken from datasheet.\n// Default controller mode, with target mode available (not simultaneously).\n// Default target address of RP2040: 0x055\n// Supports 10-bit addressing in controller mode\n// 16-element transmit buffer\n// 16-element receive buffer\n// Can be driven from DMA\n// Can generate interrupts\n// Fast mode plus max transfer speed (1000kb/s)\n\n// GPIO config\n// Each controller must connect its clock SCL and data SDA to one pair of GPIOs.\n// The I2C standard requires that drivers drivea signal low, or when not driven the signal will be pulled high.\n// This applies to SCL and SDA. The GPIO pads should be configured for:\n//  Pull-up enabled\n//  Slew rate limited\n//  Schmitt trigger enabled\n// Note: There should also be external pull-ups on the board as the internal pad pull-ups may not be strong enough to pull upexternal circuits.\n\n// I2CConfig is used to store config info for I2C.\ntype I2CConfig struct {\n\tFrequency uint32\n\t// SDA/SCL Serial Data and clock pins. Refer to datasheet to see\n\t// which pins match the desired bus.\n\tSDA, SCL Pin\n\tMode     I2CMode\n}\n\ntype I2C struct {\n\tBus          *rp.I2C0_Type\n\tmode         I2CMode\n\ttxInProgress bool\n}\n\nvar (\n\terrInvalidI2CBaudrate  = errors.New(\"i2c: invalid baudrate\")\n\terrInvalidTgtAddr      = errors.New(\"i2c: invalid target address: not in 0..0x80 or is reserved\")\n\terrI2CGeneric          = errors.New(\"i2c: generic error\")\n\terrI2CDisable          = errors.New(\"i2c: peripheral timeout in disable\")\n\terrInvalidI2CSDA       = errors.New(\"i2c: invalid SDA pin\")\n\terrInvalidI2CSCL       = errors.New(\"i2c: invalid SCL pin\")\n\terrI2CAlreadyListening = errors.New(\"i2c: already listening\")\n\terrI2CWrongMode        = errors.New(\"i2c: wrong mode\")\n\terrI2CUnderflow        = errors.New(\"i2c: underflow\")\n)\n\n// Tx performs a write and then a read transfer placing the result in\n// in r.\n//\n// Passing a nil value for w or r skips the transfer corresponding to write\n// or read, respectively.\n//\n//\ti2c.Tx(addr, nil, r)\n//\n// Performs only a read transfer.\n//\n//\ti2c.Tx(addr, w, nil)\n//\n// Performs only a write transfer.\nfunc (i2c *I2C) Tx(addr uint16, w, r []byte) error {\n\tif i2c.mode != I2CModeController {\n\t\treturn errI2CWrongMode\n\t}\n\treturn i2c.tx(uint8(addr), w, r)\n}\n\n// Listen starts listening for I2C requests sent to specified address\n//\n// addr is the address to listen to\nfunc (i2c *I2C) Listen(addr uint16) error {\n\tif i2c.mode != I2CModeTarget {\n\t\treturn errI2CWrongMode\n\t}\n\n\treturn i2c.listen(uint8(addr))\n}\n\n// Configure initializes i2c peripheral and configures I2C config's pins passed.\n// Here's a list of valid SDA and SCL GPIO pins on bus I2C0 of the rp2040:\n//\n//\tSDA: 0, 4, 8, 12, 16, 20\n//\tSCL: 1, 5, 9, 13, 17, 21\n//\n// Same as above for I2C1 bus:\n//\n//\tSDA: 2, 6, 10, 14, 18, 26\n//\tSCL: 3, 7, 11, 15, 19, 27\nfunc (i2c *I2C) Configure(config I2CConfig) error {\n\tconst defaultBaud uint32 = 100_000 // 100kHz standard mode\n\tif config.SCL == 0 && config.SDA == 0 {\n\t\t// If config pins are zero valued or clock pin is invalid then we set default values.\n\t\tswitch i2c.Bus {\n\t\tcase rp.I2C0:\n\t\t\tconfig.SCL = I2C0_SCL_PIN\n\t\t\tconfig.SDA = I2C0_SDA_PIN\n\t\tcase rp.I2C1:\n\t\t\tconfig.SCL = I2C1_SCL_PIN\n\t\t\tconfig.SDA = I2C1_SDA_PIN\n\t\t}\n\t}\n\tvar okSCL, okSDA bool\n\tswitch i2c.Bus {\n\tcase rp.I2C0:\n\t\tokSCL = (config.SCL+3)%4 == 0\n\t\tokSDA = (config.SDA+4)%4 == 0\n\tcase rp.I2C1:\n\t\tokSCL = (config.SCL+1)%4 == 0\n\t\tokSDA = (config.SDA+2)%4 == 0\n\t}\n\n\tswitch {\n\tcase !okSCL:\n\t\treturn errInvalidI2CSCL\n\tcase !okSDA:\n\t\treturn errInvalidI2CSDA\n\t}\n\n\tif config.Frequency == 0 {\n\t\tconfig.Frequency = defaultBaud\n\t}\n\tconfig.SDA.Configure(PinConfig{PinI2C})\n\tconfig.SCL.Configure(PinConfig{PinI2C})\n\treturn i2c.init(config)\n}\n\n// SetBaudRate sets the I2C frequency. It has the side effect of also\n// enabling the I2C hardware if disabled beforehand.\n//\n//go:inline\nfunc (i2c *I2C) SetBaudRate(br uint32) error {\n\n\tif br == 0 {\n\t\treturn errInvalidI2CBaudrate\n\t}\n\n\t// I2C is synchronous design that runs from clk_sys\n\tfreqin := CPUFrequency()\n\n\t// TODO there are some subtleties to I2C timing which we are completely ignoring here\n\tperiod := (freqin + br/2) / br\n\tlcnt := period * 3 / 5 // oof this one hurts\n\thcnt := period - lcnt\n\t// Check for out-of-range divisors:\n\tif hcnt > rp.I2C0_IC_FS_SCL_HCNT_IC_FS_SCL_HCNT_Msk || hcnt < 8 || lcnt > rp.I2C0_IC_FS_SCL_LCNT_IC_FS_SCL_LCNT_Msk || lcnt < 8 {\n\t\treturn errInvalidI2CBaudrate\n\t}\n\n\t// Per I2C-bus specification a device in standard or fast mode must\n\t// internally provide a hold time of at least 300ns for the SDA signal to\n\t// bridge the undefined region of the falling edge of SCL. A smaller hold\n\t// time of 120ns is used for fast mode plus.\n\n\t// sda_tx_hold_count = freq_in [cycles/s] * 300ns * (1s / 1e9ns)\n\t// Reduce 300/1e9 to 3/1e7 to avoid numbers that don't fit in uint.\n\t// Add 1 to avoid division truncation.\n\tsdaTxHoldCnt := ((freqin * 3) / 10000000) + 1\n\tif br >= 1_000_000 {\n\t\t// sda_tx_hold_count = freq_in [cycles/s] * 120ns * (1s / 1e9ns)\n\t\t// Reduce 120/1e9 to 3/25e6 to avoid numbers that don't fit in uint.\n\t\t// Add 1 to avoid division truncation.\n\t\tsdaTxHoldCnt = ((freqin * 3) / 25000000) + 1\n\t}\n\n\tif sdaTxHoldCnt > lcnt-2 {\n\t\treturn errInvalidI2CBaudrate\n\t}\n\terr := i2c.disable()\n\tif err != nil {\n\t\treturn err\n\t}\n\t// Always use \"fast\" mode (<= 400 kHz, works fine for standard mode too)\n\n\ti2c.Bus.IC_CON.ReplaceBits(rp.I2C0_IC_CON_SPEED_FAST<<rp.I2C0_IC_CON_SPEED_Pos, rp.I2C0_IC_CON_SPEED_Msk, 0)\n\ti2c.Bus.IC_FS_SCL_HCNT.Set(hcnt)\n\ti2c.Bus.IC_FS_SCL_LCNT.Set(lcnt)\n\n\ti2c.Bus.IC_FS_SPKLEN.Set(u32max(1, lcnt/16))\n\n\ti2c.Bus.IC_SDA_HOLD.ReplaceBits(sdaTxHoldCnt<<rp.I2C0_IC_SDA_HOLD_IC_SDA_TX_HOLD_Pos, rp.I2C0_IC_SDA_HOLD_IC_SDA_TX_HOLD_Msk, 0)\n\ti2c.enable()\n\treturn nil\n}\n\n//go:inline\nfunc (i2c *I2C) enable() {\n\ti2c.Bus.IC_ENABLE.ReplaceBits(rp.I2C0_IC_ENABLE_ENABLE<<rp.I2C0_IC_ENABLE_ENABLE_Pos, rp.I2C0_IC_ENABLE_ENABLE_Msk, 0)\n}\n\n// Implemented as per 4.3.10.3. Disabling DW_apb_i2c section.\n//\n//go:inline\nfunc (i2c *I2C) disable() error {\n\tconst timeout_us = 4_000\n\tdeadline := ticks() + timeout_us\n\ti2c.Bus.IC_ENABLE.Set(0)\n\tfor i2c.Bus.IC_ENABLE_STATUS.Get()&1 != 0 {\n\t\tif ticks() > deadline {\n\t\t\treturn errI2CDisable\n\t\t}\n\t}\n\treturn nil\n}\n\n//go:inline\nfunc (i2c *I2C) init(config I2CConfig) error {\n\ti2c.reset()\n\tif err := i2c.disable(); err != nil {\n\t\treturn err\n\t}\n\n\ti2c.mode = config.Mode\n\n\t// Configure as fast-mode with RepStart support, 7-bit addresses\n\tmode := uint32(rp.I2C0_IC_CON_SPEED_FAST<<rp.I2C0_IC_CON_SPEED_Pos) |\n\t\trp.I2C0_IC_CON_IC_RESTART_EN | rp.I2C0_IC_CON_TX_EMPTY_CTRL // sets TX_EMPTY_CTRL to enable TX_EMPTY interrupt status\n\tif config.Mode == I2CModeController {\n\t\tmode |= rp.I2C0_IC_CON_MASTER_MODE | rp.I2C0_IC_CON_IC_SLAVE_DISABLE\n\t}\n\ti2c.Bus.IC_CON.Set(mode)\n\n\t// Set FIFO watermarks to 1 to make things simpler. This is encoded by a register value of 0.\n\tif config.Mode == I2CModeController {\n\t\ti2c.Bus.IC_TX_TL.Set(0)\n\t\ti2c.Bus.IC_RX_TL.Set(0)\n\t}\n\n\t// Always enable the DREQ signalling -- harmless if DMA isn't listening\n\ti2c.Bus.IC_DMA_CR.Set(rp.I2C0_IC_DMA_CR_TDMAE | rp.I2C0_IC_DMA_CR_RDMAE)\n\treturn i2c.SetBaudRate(config.Frequency)\n}\n\n// reset sets I2C register RESET bits in the reset peripheral and then clears them.\n//\n//go:inline\nfunc (i2c *I2C) reset() {\n\tresetVal := i2c.deinit()\n\trp.RESETS.RESET.ClearBits(resetVal)\n\t// Wait until reset is done.\n\tfor !rp.RESETS.RESET_DONE.HasBits(resetVal) {\n\t}\n}\n\n// deinit sets reset bit for I2C. Must call reset to reenable I2C after deinit.\n//\n//go:inline\nfunc (i2c *I2C) deinit() (resetVal uint32) {\n\tswitch {\n\tcase i2c.Bus == rp.I2C0:\n\t\tresetVal = rp.RESETS_RESET_I2C0\n\tcase i2c.Bus == rp.I2C1:\n\t\tresetVal = rp.RESETS_RESET_I2C1\n\t}\n\t// Perform I2C reset.\n\trp.RESETS.RESET.SetBits(resetVal)\n\n\treturn resetVal\n}\n\n// tx performs blocking write followed by read to I2C bus.\nfunc (i2c *I2C) tx(addr uint8, tx, rx []byte) (err error) {\n\tconst timeout_us = 4_000\n\tdeadline := ticks() + timeout_us\n\tif addr >= 0x80 || isReservedI2CAddr(addr) {\n\t\treturn errInvalidTgtAddr\n\t}\n\ttxlen := len(tx)\n\trxlen := len(rx)\n\t// Quick return if possible.\n\tif txlen == 0 && rxlen == 0 {\n\t\treturn nil\n\t}\n\n\terr = i2c.disable()\n\tif err != nil {\n\t\treturn err\n\t}\n\ti2c.Bus.IC_TAR.Set(uint32(addr))\n\ti2c.enable()\n\tabort := false\n\tvar abortReason i2cAbortError\n\ttxStop := rxlen == 0\n\tfor txCtr := 0; txCtr < txlen; txCtr++ {\n\t\tif abort {\n\t\t\tbreak\n\t\t}\n\t\tfirst := txCtr == 0\n\t\tlast := txCtr == txlen-1 && rxlen == 0\n\t\ti2c.Bus.IC_DATA_CMD.Set(\n\t\t\t(boolToBit(first) << rp.I2C0_IC_DATA_CMD_RESTART_Pos) |\n\t\t\t\t(boolToBit(last && txStop) << rp.I2C0_IC_DATA_CMD_STOP_Pos) |\n\t\t\t\tuint32(tx[txCtr]))\n\n\t\t// Wait until the transmission of the address/data from the internal\n\t\t// shift register has completed. For this to function correctly, the\n\t\t// TX_EMPTY_CTRL flag in IC_CON must be set. The TX_EMPTY_CTRL flag\n\t\t// was set in i2c_init.\n\n\t\t// IC_RAW_INTR_STAT_TX_EMPTY: This bit is set to 1 when the transmit buffer is at or below\n\t\t// the threshold value set in the IC_TX_TL register and the\n\t\t// transmission of the address/data from the internal shift\n\t\t// register for the most recently popped command is\n\t\t// completed. It is automatically cleared by hardware when\n\t\t// the buffer level goes above the threshold. When\n\t\t// IC_ENABLE[0] is set to 0, the TX FIFO is flushed and held\n\t\t// in reset. There the TX FIFO looks like it has no data within\n\t\t// it, so this bit is set to 1, provided there is activity in the\n\t\t// controller or target state machines. When there is no longer\n\t\t// any activity, then with ic_en=0, this bit is set to 0.\n\t\tfor !i2c.interrupted(rp.I2C0_IC_RAW_INTR_STAT_TX_EMPTY) {\n\t\t\tif ticks() > deadline {\n\t\t\t\treturn errI2CWriteTimeout // If there was a timeout, don't attempt to do anything else.\n\t\t\t}\n\n\t\t\tbefore := ticks()\n\t\t\tgosched()\n\t\t\tdeadline += ticks() - before\n\t\t}\n\n\t\tabortReason = i2c.getAbortReason()\n\t\tif abortReason != 0 {\n\t\t\ti2c.clearAbortReason()\n\t\t\tabort = true\n\t\t}\n\t\tif abort || last {\n\t\t\t// If the transaction was aborted or if it completed\n\t\t\t// successfully wait until the STOP condition has occurred.\n\n\t\t\t// TODO Could there be an abort while waiting for the STOP\n\t\t\t// condition here? If so, additional code would be needed here\n\t\t\t// to take care of the abort.\n\t\t\tfor !i2c.interrupted(rp.I2C0_IC_RAW_INTR_STAT_STOP_DET) {\n\t\t\t\tif ticks() > deadline {\n\t\t\t\t\tif abort {\n\t\t\t\t\t\treturn abortReason\n\t\t\t\t\t}\n\t\t\t\t\treturn errI2CWriteTimeout\n\t\t\t\t}\n\n\t\t\t\tbefore := ticks()\n\t\t\t\tgosched()\n\t\t\t\tdeadline += ticks() - before\n\t\t\t}\n\t\t\ti2c.Bus.IC_CLR_STOP_DET.Get()\n\t\t}\n\t}\n\n\t// Midway check for abort. Related issue https://github.com/tinygo-org/tinygo/issues/3671.\n\t// The root cause for an abort after writing registers was \"tx data no ack\" (abort code=8).\n\t// If the abort code was not registered then the whole peripheral would remain in disabled state forever.\n\tabortReason = i2c.getAbortReason()\n\tif abortReason != 0 {\n\t\ti2c.clearAbortReason()\n\t\tabort = true\n\t}\n\n\trxStart := txlen == 0\n\tif rxlen > 0 && !abort {\n\t\tfor rxCtr := 0; rxCtr < rxlen; rxCtr++ {\n\t\t\tfirst := rxCtr == 0\n\t\t\tlast := rxCtr == rxlen-1\n\t\t\tfor i2c.writeAvailable() == 0 {\n\t\t\t\tbefore := ticks()\n\t\t\t\tgosched()\n\t\t\t\tdeadline += ticks() - before\n\t\t\t}\n\t\t\ti2c.Bus.IC_DATA_CMD.Set(\n\t\t\t\tboolToBit(first && rxStart)<<rp.I2C0_IC_DATA_CMD_RESTART_Pos |\n\t\t\t\t\tboolToBit(last)<<rp.I2C0_IC_DATA_CMD_STOP_Pos |\n\t\t\t\t\trp.I2C0_IC_DATA_CMD_CMD) // -> 1 for read\n\n\t\t\tfor !abort && i2c.readAvailable() == 0 {\n\t\t\t\tabortReason = i2c.getAbortReason()\n\t\t\t\tif abortReason != 0 {\n\t\t\t\t\ti2c.clearAbortReason()\n\t\t\t\t\tabort = true\n\t\t\t\t}\n\t\t\t\tif ticks() > deadline {\n\t\t\t\t\treturn errI2CReadTimeout // If there was a timeout, don't attempt to do anything else.\n\t\t\t\t}\n\n\t\t\t\tbefore := ticks()\n\t\t\t\tgosched()\n\t\t\t\tdeadline += ticks() - before\n\t\t\t}\n\t\t\tif abort {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\trx[rxCtr] = uint8(i2c.Bus.IC_DATA_CMD.Get())\n\t\t}\n\t}\n\t// From Pico SDK: A lot of things could have just happened due to the ingenious and\n\t// creative design of I2C. Try to figure things out.\n\tif abort {\n\t\tswitch {\n\t\tcase abortReason == 0 || abortReason&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK != 0:\n\t\t\t// No reported errors - seems to happen if there is nothing connected to the bus.\n\t\t\t// Address byte not acknowledged\n\t\t\terr = errI2CGeneric\n\t\tcase abortReason&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK != 0:\n\t\t\t// Address acknowledged, some data not acknowledged\n\t\t\tfallthrough\n\t\tdefault:\n\t\t\terr = abortReason\n\t\t}\n\t}\n\treturn err\n}\n\n// listen sets up for async handling of requests on the I2C bus.\nfunc (i2c *I2C) listen(addr uint8) error {\n\tif addr >= 0x80 || isReservedI2CAddr(addr) {\n\t\treturn errInvalidTgtAddr\n\t}\n\n\terr := i2c.disable()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ti2c.Bus.IC_SAR.Set(uint32(addr))\n\n\ti2c.enable()\n\n\treturn nil\n}\n\nfunc (i2c *I2C) WaitForEvent(buf []byte) (evt I2CTargetEvent, count int, err error) {\n\trxPtr := 0\n\tfor {\n\t\tstat := i2c.Bus.IC_RAW_INTR_STAT.Get()\n\n\t\tif stat&rp.I2C0_IC_INTR_MASK_M_RX_FULL != 0 {\n\t\t\tb := uint8(i2c.Bus.IC_DATA_CMD.Get())\n\t\t\tif rxPtr < len(buf) {\n\t\t\t\tbuf[rxPtr] = b\n\t\t\t\trxPtr++\n\t\t\t}\n\t\t}\n\n\t\t// Stop\n\t\tif stat&rp.I2C0_IC_INTR_MASK_M_STOP_DET != 0 {\n\t\t\tif rxPtr > 0 {\n\t\t\t\treturn I2CReceive, rxPtr, nil\n\t\t\t}\n\n\t\t\ti2c.Bus.IC_CLR_STOP_DET.Get() // clear\n\t\t\treturn I2CFinish, 0, nil\n\t\t}\n\n\t\t// Start or restart - ignore start, return on restart\n\t\tif stat&rp.I2C0_IC_INTR_MASK_M_START_DET != 0 {\n\t\t\ti2c.Bus.IC_CLR_START_DET.Get() // clear restart\n\n\t\t\t// Restart\n\t\t\tif rxPtr > 0 {\n\t\t\t\treturn I2CReceive, rxPtr, nil\n\t\t\t}\n\t\t}\n\n\t\t// Read request - leave flag set until we start to reply.\n\t\tif stat&rp.I2C0_IC_INTR_MASK_M_RD_REQ != 0 {\n\t\t\treturn I2CRequest, 0, nil\n\t\t}\n\n\t\tgosched()\n\t}\n}\n\nfunc (i2c *I2C) Reply(buf []byte) error {\n\ttxPtr := 0\n\n\tstat := i2c.Bus.IC_RAW_INTR_STAT.Get()\n\n\tif stat&rp.I2C0_IC_INTR_MASK_M_RD_REQ == 0 {\n\t\treturn errI2CWrongMode\n\t}\n\ti2c.Bus.IC_CLR_RD_REQ.Get() // clear restart\n\n\t// Clear any dangling TX abort\n\tif stat&rp.I2C0_IC_INTR_MASK_M_TX_ABRT != 0 {\n\t\ti2c.Bus.IC_CLR_TX_ABRT.Get()\n\t}\n\n\tfor txPtr < len(buf) {\n\t\tif i2c.Bus.GetIC_RAW_INTR_STAT_TX_EMPTY() != 0 {\n\t\t\ti2c.Bus.SetIC_DATA_CMD_DAT(uint32(buf[txPtr]))\n\t\t\ttxPtr++\n\t\t\t// The DW_apb_i2c flushes/resets/empties the\n\t\t\t// TX_FIFO and RX_FIFO whenever there is a transmit abort\n\t\t\t// caused by any of the events tracked by the\n\t\t\t// IC_TX_ABRT_SOURCE register.\n\t\t\t// In other words, it's safe to block until TX FIFO is\n\t\t\t// EMPTY--it will empty from being transmitted or on error.\n\t\t\tfor i2c.Bus.GetIC_RAW_INTR_STAT_TX_EMPTY() == 0 {\n\t\t\t}\n\t\t}\n\n\t\t// This Tx abort is a normal case - we're sending more\n\t\t// data than controller wants to receive\n\t\tif i2c.Bus.GetIC_RAW_INTR_STAT_TX_ABRT() != 0 {\n\t\t\ti2c.Bus.GetIC_CLR_TX_ABRT_CLR_TX_ABRT()\n\t\t\treturn nil\n\t\t}\n\n\t\tgosched()\n\t}\n\n\treturn nil\n}\n\n// writeAvailable determines non-blocking write space available\n//\n//go:inline\nfunc (i2c *I2C) writeAvailable() uint32 {\n\treturn rp.I2C0_IC_COMP_PARAM_1_TX_BUFFER_DEPTH_Pos - i2c.Bus.IC_TXFLR.Get()\n}\n\n// readAvailable determines number of bytes received\n//\n//go:inline\nfunc (i2c *I2C) readAvailable() uint32 {\n\treturn i2c.Bus.IC_RXFLR.Get()\n}\n\n// Equivalent to IC_CLR_TX_ABRT.Get() (side effect clears ABORT_REASON)\n//\n//go:inline\nfunc (i2c *I2C) clearAbortReason() {\n\t// Note clearing the abort flag also clears the reason, and\n\t// this instance of flag is clear-on-read! Note also the\n\t// IC_CLR_TX_ABRT register always reads as 0.\n\ti2c.Bus.IC_CLR_TX_ABRT.Get()\n}\n\n// getAbortReason reads IC_TX_ABRT_SOURCE register.\n//\n//go:inline\nfunc (i2c *I2C) getAbortReason() i2cAbortError {\n\treturn i2cAbortError(i2c.Bus.IC_TX_ABRT_SOURCE.Get())\n}\n\n// returns true if RAW_INTR_STAT bits in mask are all set. performs:\n//\n//\tRAW_INTR_STAT & mask == mask\n//\n//go:inline\nfunc (i2c *I2C) interrupted(mask uint32) bool {\n\treg := i2c.Bus.IC_RAW_INTR_STAT.Get()\n\treturn reg&mask == mask\n}\n\ntype i2cAbortError uint32\n\nfunc (b i2cAbortError) Error() string {\n\treturn \"i2c abort, reason \" + itoa.Uitoa(uint(b))\n}\n\nfunc (b i2cAbortError) Reasons() (reasons []string) {\n\tif b == 0 {\n\t\treturn nil\n\t}\n\tif b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK != 0 {\n\t\treasons = append(reasons, \"7-bit address no ack\")\n\t}\n\tif b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK != 0 {\n\t\treasons = append(reasons, \"10-bit address first byte no ack\")\n\t}\n\tif b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK != 0 {\n\t\treasons = append(reasons, \"10-bit address second byte no ack\")\n\t}\n\tif b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK != 0 {\n\t\treasons = append(reasons, \"tx data no ack\")\n\t}\n\tif b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_GCALL_NOACK != 0 {\n\t\treasons = append(reasons, \"general call no ack\")\n\t}\n\tif b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_GCALL_READ != 0 {\n\t\treasons = append(reasons, \"general call read\")\n\t}\n\tif b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_HS_ACKDET != 0 {\n\t\treasons = append(reasons, \"high speed ack detect\")\n\t}\n\tif b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_SBYTE_ACKDET != 0 {\n\t\treasons = append(reasons, \"start byte ack detect\")\n\t}\n\tif b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_HS_NORSTRT != 0 {\n\t\treasons = append(reasons, \"high speed no restart\")\n\t}\n\tif b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_SBYTE_NORSTRT != 0 {\n\t\treasons = append(reasons, \"start byte no restart\")\n\t}\n\tif b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_10B_RD_NORSTRT != 0 {\n\t\treasons = append(reasons, \"10-bit read no restart\")\n\t}\n\tif b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_MASTER_DIS != 0 {\n\t\treasons = append(reasons, \"master disabled\")\n\t}\n\tif b&rp.I2C0_IC_TX_ABRT_SOURCE_ARB_LOST != 0 {\n\t\treasons = append(reasons, \"arbitration lost\")\n\t}\n\tif b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_SLVFLUSH_TXFIFO != 0 {\n\t\treasons = append(reasons, \"slave flush tx fifo\")\n\t}\n\tif b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_SLV_ARBLOST != 0 {\n\t\treasons = append(reasons, \"slave arbitration lost\")\n\t}\n\tif b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_SLVRD_INTX != 0 {\n\t\treasons = append(reasons, \"slave read while inactive\")\n\t}\n\tif b&rp.I2C0_IC_TX_ABRT_SOURCE_ABRT_USER_ABRT != 0 {\n\t\treasons = append(reasons, \"user abort\")\n\t}\n\treturn reasons\n}\n"
  },
  {
    "path": "src/machine/machine_rp2_pins.go",
    "content": "//go:build rp2040 || rp2350 || gopher_badge || pico\n\npackage machine\n\nconst (\n\t// GPIO pins\n\tGPIO0  Pin = 0  // peripherals: PWM0 channel A, I2C0 SDA\n\tGPIO1  Pin = 1  // peripherals: PWM0 channel B, I2C0 SCL\n\tGPIO2  Pin = 2  // peripherals: PWM1 channel A, I2C1 SDA\n\tGPIO3  Pin = 3  // peripherals: PWM1 channel B, I2C1 SCL\n\tGPIO4  Pin = 4  // peripherals: PWM2 channel A, I2C0 SDA\n\tGPIO5  Pin = 5  // peripherals: PWM2 channel B, I2C0 SCL\n\tGPIO6  Pin = 6  // peripherals: PWM3 channel A, I2C1 SDA\n\tGPIO7  Pin = 7  // peripherals: PWM3 channel B, I2C1 SCL\n\tGPIO8  Pin = 8  // peripherals: PWM4 channel A, I2C0 SDA\n\tGPIO9  Pin = 9  // peripherals: PWM4 channel B, I2C0 SCL\n\tGPIO10 Pin = 10 // peripherals: PWM5 channel A, I2C1 SDA\n\tGPIO11 Pin = 11 // peripherals: PWM5 channel B, I2C1 SCL\n\tGPIO12 Pin = 12 // peripherals: PWM6 channel A, I2C0 SDA\n\tGPIO13 Pin = 13 // peripherals: PWM6 channel B, I2C0 SCL\n\tGPIO14 Pin = 14 // peripherals: PWM7 channel A, I2C1 SDA\n\tGPIO15 Pin = 15 // peripherals: PWM7 channel B, I2C1 SCL\n\tGPIO16 Pin = 16 // peripherals: PWM0 channel A, I2C0 SDA\n\tGPIO17 Pin = 17 // peripherals: PWM0 channel B, I2C0 SCL\n\tGPIO18 Pin = 18 // peripherals: PWM1 channel A, I2C1 SDA\n\tGPIO19 Pin = 19 // peripherals: PWM1 channel B, I2C1 SCL\n\tGPIO20 Pin = 20 // peripherals: PWM2 channel A, I2C0 SDA\n\tGPIO21 Pin = 21 // peripherals: PWM2 channel B, I2C0 SCL\n\tGPIO22 Pin = 22 // peripherals: PWM3 channel A\n\tGPIO23 Pin = 23 // peripherals: PWM3 channel B\n\tGPIO24 Pin = 24 // peripherals: PWM4 channel A\n\tGPIO25 Pin = 25 // peripherals: PWM4 channel B\n\tGPIO26 Pin = 26 // peripherals: PWM5 channel A, I2C1 SDA\n\tGPIO27 Pin = 27 // peripherals: PWM5 channel B, I2C1 SCL\n\tGPIO28 Pin = 28 // peripherals: PWM6 channel A\n\tGPIO29 Pin = 29 // peripherals: PWM6 channel B\n)\n"
  },
  {
    "path": "src/machine/machine_rp2_pll.go",
    "content": "//go:build rp2040 || rp2350\n\npackage machine\n\nimport (\n\t\"device/rp\"\n\t\"errors\"\n\t\"math\"\n\t\"math/bits\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\ntype pll struct {\n\tcs       volatile.Register32\n\tpwr      volatile.Register32\n\tfbDivInt volatile.Register32\n\tprim     volatile.Register32\n}\n\nvar (\n\tpllSys = (*pll)(unsafe.Pointer(rp.PLL_SYS))\n\tpllUSB = (*pll)(unsafe.Pointer(rp.PLL_USB))\n)\n\n// init initializes pll (Sys or USB) given the following parameters.\n//\n// Input clock divider, refdiv.\n//\n// Requested output frequency from the VCO (voltage controlled oscillator), vcoFreq.\n//\n// Post Divider 1, postDiv1 with range 1-7 and be >= postDiv2.\n//\n// Post Divider 2, postDiv2 with range 1-7.\nfunc (pll *pll) init(refdiv, fbdiv, postDiv1, postDiv2 uint32) {\n\trefFreq := xoscFreq / refdiv\n\n\t// What are we multiplying the reference clock by to get the vco freq\n\t// (The regs are called div, because you divide the vco output and compare it to the refclk)\n\n\t// Check fbdiv range\n\tif !(fbdiv >= 16 && fbdiv <= 320) {\n\t\tpanic(\"fbdiv should be in the range [16,320]\")\n\t}\n\n\t// Check divider ranges\n\tif !((postDiv1 >= 1 && postDiv1 <= 7) && (postDiv2 >= 1 && postDiv2 <= 7)) {\n\t\tpanic(\"postdiv1, postdiv1 should be in the range [1,7]\")\n\t}\n\n\t// postDiv1 should be >= postDiv2\n\t// from appnote page 11\n\t// postdiv1 is designed to operate with a higher input frequency\n\t// than postdiv2\n\tif postDiv1 < postDiv2 {\n\t\tpanic(\"postdiv1 should be greater than or equal to postdiv2\")\n\t}\n\n\t// Check that reference frequency is no greater than vcoFreq / 16\n\tvcoFreq := calcVCO(xoscFreq, fbdiv, refdiv)\n\tif refFreq > vcoFreq/16 {\n\t\tpanic(\"reference frequency should not be greater than vco frequency divided by 16\")\n\t}\n\n\t// div1 feeds into div2 so if div1 is 5 and div2 is 2 then you get a divide by 10\n\tpdiv := uint32(postDiv1)<<rp.PLL_SYS_PRIM_POSTDIV1_Pos | uint32(postDiv2)<<rp.PLL_SYS_PRIM_POSTDIV2_Pos\n\n\tif pll.cs.HasBits(rp.PLL_SYS_CS_LOCK) &&\n\t\trefdiv == pll.cs.Get()&rp.PLL_SYS_CS_REFDIV_Msk &&\n\t\tfbdiv == pll.fbDivInt.Get()&rp.PLL_SYS_FBDIV_INT_FBDIV_INT_Msk &&\n\t\tpdiv == pll.prim.Get()&(rp.PLL_SYS_PRIM_POSTDIV1_Msk&rp.PLL_SYS_PRIM_POSTDIV2_Msk) {\n\t\t// do not disrupt PLL that is already correctly configured and operating\n\t\treturn\n\t}\n\n\tvar pllRst uint32\n\tif pll == pllSys {\n\t\tpllRst = rp.RESETS_RESET_PLL_SYS\n\t} else {\n\t\tpllRst = rp.RESETS_RESET_PLL_USB\n\t}\n\tresetBlock(pllRst)\n\tunresetBlockWait(pllRst)\n\n\t// Load VCO-related dividers before starting VCO\n\tpll.cs.Set(refdiv)\n\tpll.fbDivInt.Set(fbdiv)\n\n\t// Turn on PLL\n\tpwr := uint32(rp.PLL_SYS_PWR_PD | rp.PLL_SYS_PWR_VCOPD)\n\tpll.pwr.ClearBits(pwr)\n\n\t// Wait for PLL to lock\n\tfor !(pll.cs.HasBits(rp.PLL_SYS_CS_LOCK)) {\n\t}\n\n\t// Set up post dividers\n\tpll.prim.Set(pdiv)\n\n\t// Turn on post divider\n\tpll.pwr.ClearBits(rp.PLL_SYS_PWR_POSTDIVPD)\n\n}\n\nvar errVCOOverflow = errors.New(\"VCO calculation overflow; use lower MHz\")\n\n// pllSearch enables searching for a good PLL configuration.\n// Example for 12MHz crystal and RP2040:\n//\n//\tfbdiv, refdiv, pd1, pd2, _ := pllSearch{LockRefDiv:1}.CalcDivs(12*MHz, 125*MHz, MHz)\n//\n// Example for 12MHz crystal and RP2350:\n//\n//\tfbdiv, refdiv, pd1, pd2, _ := pllSearch{LockRefDiv:1}.CalcDivs(12*MHz, 150*MHz, MHz)\ntype pllSearch struct {\n\tLowerVCO   bool\n\tLockRefDiv uint8\n}\n\nfunc (ps pllSearch) CalcDivs(xoscRef, targetFreq, MHz uint64) (fbdiv uint64, refdiv, pd1, pd2 uint8, err error) {\n\tgenTable()\n\tvar bestFreq, bestFbdiv uint64\n\tvar bestRefdiv, bestpd1, bestpd2 uint8\n\tmaxVCO, minVCO := 1600*MHz, 750*MHz\n\tvar bestMargin int64 = int64(maxVCO)\n\titers := 0\n\tfor refdiv = 1; refdiv < 64; refdiv++ {\n\t\tif ps.LockRefDiv != 0 && refdiv != ps.LockRefDiv {\n\t\t\tcontinue\n\t\t}\n\t\tfirstFBDiv := minVCO * uint64(refdiv) / xoscRef\n\t\tfor fbdiv = firstFBDiv; fbdiv < 321; fbdiv++ {\n\t\t\toverflow, vco := bits.Mul64(xoscRef, fbdiv)\n\t\t\tvco /= uint64(refdiv)\n\t\t\tif overflow != 0 {\n\t\t\t\treturn fbdiv, refdiv, pd1, pd2, errVCOOverflow\n\t\t\t} else if vco > maxVCO {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcalcPD12 := vco / targetFreq\n\t\t\tif calcPD12 < 1 {\n\t\t\t\tcalcPD12 = 1\n\t\t\t} else if calcPD12 > 49 {\n\t\t\t\tcalcPD12 = 49\n\t\t\t}\n\t\t\titers++\n\t\t\tpd1 = pdTable[calcPD12].hivco[0]\n\t\t\tpd2 = pdTable[calcPD12].hivco[1]\n\t\t\tfout, err := pllFreqOutPostdiv(xoscRef, fbdiv, MHz, refdiv, pd1, pd2)\n\t\t\tfound := false\n\t\t\tmargin := abs(int64(fout) - int64(targetFreq))\n\t\t\tif err == nil && margin <= bestMargin {\n\t\t\t\tfound = true\n\t\t\t\tbestFreq = fout\n\t\t\t\tbestFbdiv = fbdiv\n\t\t\t\tbestpd1 = pd1\n\t\t\t\tbestpd2 = pd2\n\t\t\t\tbestRefdiv = refdiv\n\t\t\t\tbestMargin = margin\n\t\t\t}\n\t\t\tpd1 = pdTable[calcPD12].lovco[0]\n\t\t\tpd2 = pdTable[calcPD12].lovco[1]\n\t\t\tfout, err = pllFreqOutPostdiv(xoscRef, fbdiv, MHz, refdiv, pd1, pd2)\n\t\t\tmargin = abs(int64(fout) - int64(targetFreq))\n\t\t\tif err == nil && margin <= bestMargin {\n\t\t\t\tfound = true\n\t\t\t\tbestFreq = fout\n\t\t\t\tbestFbdiv = fbdiv\n\t\t\t\tbestpd1 = pd1\n\t\t\t\tbestpd2 = pd2\n\t\t\t\tbestRefdiv = refdiv\n\t\t\t\tbestMargin = margin\n\t\t\t}\n\t\t\tif found && ps.LowerVCO {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\tif bestFreq == 0 {\n\t\treturn fbdiv, refdiv, pd1, pd2, errors.New(\"no best frequency found\")\n\t}\n\treturn bestFbdiv, bestRefdiv, bestpd1, bestpd2, nil\n}\n\nfunc abs(a int64) int64 {\n\tif a == math.MinInt64 {\n\t\treturn math.MaxInt64\n\t} else if a < 0 {\n\t\treturn -a\n\t}\n\treturn a\n}\n\nfunc pllFreqOutPostdiv(xosc, fbdiv, MHz uint64, refdiv, postdiv1, postdiv2 uint8) (foutpostdiv uint64, err error) {\n\t// testing grounds.\n\tconst (\n\t\tmhz    = 1\n\t\tcfref  = 12 * mhz // given by crystal oscillator selection.\n\t\tcrefd  = 1\n\t\tcfbdiv = 100\n\t\tcvco   = cfref * cfbdiv / crefd\n\t\tcpd1   = 6\n\t\tcpd2   = 2\n\t\tfoutpd = (cfref / crefd) * cfbdiv / (cpd1 * cpd2)\n\t)\n\trefFreq := xosc / uint64(refdiv)\n\toverflow, vco := bits.Mul64(xosc, fbdiv)\n\tvco /= uint64(refdiv)\n\tfoutpostdiv = vco / uint64(postdiv1*postdiv2)\n\tswitch {\n\tcase refdiv < 1 || refdiv > 63:\n\t\terr = errors.New(\"reference divider out of range\")\n\tcase fbdiv < 16 || fbdiv > 320:\n\t\terr = errors.New(\"feedback divider out of range\")\n\tcase postdiv1 < 1 || postdiv1 > 7:\n\t\terr = errors.New(\"postdiv1 out of range\")\n\tcase postdiv2 < 1 || postdiv2 > 7:\n\t\terr = errors.New(\"postdiv2 out of range\")\n\tcase postdiv1 < postdiv2:\n\t\terr = errors.New(\"user error: use higher value for postdiv1 for lower power consumption\")\n\tcase vco < 750*MHz || vco > 1600*MHz:\n\t\terr = errors.New(\"VCO out of range\")\n\tcase refFreq < 5*MHz:\n\t\terr = errors.New(\"minimum reference frequency breach\")\n\tcase refFreq > vco/16:\n\t\terr = errors.New(\"maximum reference frequency breach\")\n\tcase vco > 1200*MHz && vco < 1600*MHz && xosc < 75*MHz && refdiv != 1:\n\t\terr = errors.New(\"refdiv should be 1 for given VCO and reference frequency\")\n\tcase overflow != 0:\n\t\terr = errVCOOverflow\n\t}\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn foutpostdiv, nil\n}\n\nfunc calcVCO(xoscFreq, fbdiv, refdiv uint32) uint32 {\n\tconst maxXoscMHz = math.MaxUint32 / 320 / MHz // 13MHz maximum xosc apparently.\n\tif fbdiv > 320 || xoscFreq > math.MaxUint32/320 {\n\t\tpanic(\"invalid VCO calculation args\")\n\t}\n\treturn xoscFreq * fbdiv / refdiv\n}\n\nvar pdTable = [50]struct {\n\thivco [2]uint8\n\tlovco [2]uint8\n}{}\n\nfunc genTable() {\n\tif pdTable[1].hivco[1] != 0 {\n\t\treturn // Already generated.\n\t}\n\tfor product := 1; product < len(pdTable); product++ {\n\t\tbestProdhi := 255\n\t\tbestProdlo := 255\n\t\tfor pd1 := 7; pd1 > 0; pd1-- {\n\t\t\tfor pd2 := pd1; pd2 > 0; pd2-- {\n\t\t\t\tgotprod := pd1 * pd2\n\t\t\t\tif abs(int64(gotprod-product)) < abs(int64(bestProdlo-product)) {\n\t\t\t\t\tbestProdlo = gotprod\n\t\t\t\t\tpdTable[product].lovco[0] = uint8(pd1)\n\t\t\t\t\tpdTable[product].lovco[1] = uint8(pd2)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor pd1 := 1; pd1 < 8; pd1++ {\n\t\t\tfor pd2 := 1; pd2 <= pd1; pd2++ {\n\t\t\t\tgotprod := pd1 * pd2\n\t\t\t\tif abs(int64(gotprod-product)) < abs(int64(bestProdhi-product)) {\n\t\t\t\t\tbestProdhi = gotprod\n\t\t\t\t\tpdTable[product].hivco[0] = uint8(pd1)\n\t\t\t\t\tpdTable[product].hivco[1] = uint8(pd2)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_rp2_pwm.go",
    "content": "//go:build rp2040 || rp2350\n\npackage machine\n\nimport (\n\t\"device/rp\"\n\t\"errors\"\n\t\"math\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nvar (\n\tErrBadPeriod = errors.New(\"period outside valid range 8ns..268ms\")\n)\n\nconst (\n\tmaxPWMPins = _NUMBANK0_GPIOS - 1\n)\n\n// pwmGroup is one PWM peripheral, which consists of a counter and two output\n// channels. You can set the frequency using SetPeriod,\n// but only for all the channels in this PWM peripheral at once.\n//\n// div: integer value to reduce counting rate by. Must be greater than or equal to 1.\n//\n// cc: counter compare level. Contains 2 channel levels. The 16 LSBs are Channel A's level (Duty Cycle)\n// and the 16 MSBs are Channel B's level.\n//\n// top: Wrap. Highest number counter will reach before wrapping over. usually 0xffff.\n//\n// csr: Clock mode. PWM_CH0_CSR_DIVMODE_xxx registers have 4 possible modes, of which Free-running is used.\n// csr contains output polarity bit at PWM_CH0_CSR_x_INV where x is the channel.\n// csr contains phase correction bit at PWM_CH0_CSR_PH_CORRECT_Msk.\n// csr contains PWM enable bit at PWM_CH0_CSR_EN. If not enabled PWM will not be active.\n//\n// ctr: PWM counter value.\ntype pwmGroup struct {\n\tCSR volatile.Register32\n\tDIV volatile.Register32\n\tCTR volatile.Register32\n\tCC  volatile.Register32\n\tTOP volatile.Register32\n}\n\n// Equivalent of\n//\n//\tvar pwmSlice []pwmGroup = (*[8]pwmGroup)(unsafe.Pointer(rp.PWM))[:]\n//\treturn &pwmSlice[index]\n//\n// 0x14 is the size of a pwmGroup.\nfunc getPWMGroup(index uintptr) *pwmGroup {\n\treturn (*pwmGroup)(unsafe.Add(unsafe.Pointer(rp.PWM), 0x14*index))\n}\n\n// Hardware Pulse Width Modulation (PWM) API\n// PWM peripherals available on RP2040. Each peripheral has 2 pins available for\n// a total of 16 available PWM outputs. Some pins may not be available on some boards.\n//\n// The RP2040 PWM block has 8 identical slices. Each slice can drive two PWM output signals, or\n// measure the frequency or duty cycle of an input signal. This gives a total of up to 16 controllable\n// PWM outputs. All 30 GPIOs can be driven by the PWM block\n//\n// The PWM hardware functions by continuously comparing the input value to a free-running counter. This produces a\n// toggling output where the amount of time spent at the high output level is proportional to the input value. The fraction of\n// time spent at the high signal level is known as the duty cycle of the signal.\n//\n// The default behaviour of a PWM slice is to count upward until the wrap value (\\ref pwm_config_set_wrap) is reached, and then\n// immediately wrap to 0. PWM slices also offer a phase-correct mode, where the counter starts to count downward after\n// reaching TOP, until it reaches 0 again.\nvar (\n\tPWM0 = getPWMGroup(0)\n\tPWM1 = getPWMGroup(1)\n\tPWM2 = getPWMGroup(2)\n\tPWM3 = getPWMGroup(3)\n\tPWM4 = getPWMGroup(4)\n\tPWM5 = getPWMGroup(5)\n\tPWM6 = getPWMGroup(6)\n\tPWM7 = getPWMGroup(7)\n)\n\n// Configure enables and configures this PWM.\nfunc (pwm *pwmGroup) Configure(config PWMConfig) error {\n\treturn pwm.init(config, true)\n}\n\n// Channel returns a PWM channel for the given pin. If pin does\n// not belong to PWM peripheral ErrInvalidOutputPin error is returned.\n// It also configures pin as PWM output.\nfunc (pwm *pwmGroup) Channel(pin Pin) (channel uint8, err error) {\n\tif pin > maxPWMPins || pwmGPIOToSlice(pin) != pwm.peripheral() {\n\t\treturn 3, ErrInvalidOutputPin\n\t}\n\tpin.Configure(PinConfig{PinPWM})\n\treturn pwmGPIOToChannel(pin), nil\n}\n\n// Peripheral returns the RP2040 PWM peripheral which ranges from 0 to 7. Each\n// PWM peripheral has 2 channels, A and B which correspond to 0 and 1 in the program.\n// This number corresponds to the package's PWM0 throughout PWM7 handles\nfunc PWMPeripheral(pin Pin) (sliceNum uint8, err error) {\n\tif pin > maxPWMPins {\n\t\treturn 0, ErrInvalidOutputPin\n\t}\n\treturn pwmGPIOToSlice(pin), nil\n}\n\n// returns the number of the pwm peripheral (0-7)\nfunc (pwm *pwmGroup) peripheral() uint8 {\n\treturn uint8((uintptr(unsafe.Pointer(pwm)) - uintptr(unsafe.Pointer(rp.PWM))) / 0x14)\n}\n\n// SetPeriod updates the period of this PWM peripheral in nanoseconds.\n// To set a particular frequency, use the following formula:\n//\n//\tperiod = 1e9 / frequency\n//\n// Where frequency is in hertz. If you use a period of 0, a period\n// that works well for LEDs will be picked.\n//\n// SetPeriod will try not to modify TOP if possible to reach the target period.\n// If the period is unattainable with current TOP SetPeriod will modify TOP\n// by the bare minimum to reach the target period. It will also enable phase\n// correct to reach periods above 130ms.\nfunc (p *pwmGroup) SetPeriod(period uint64) error {\n\tif period == 0 {\n\t\tperiod = 1e5\n\t}\n\treturn p.setPeriod(period)\n}\n\n// Top returns the current counter top, for use in duty cycle calculation.\n//\n// The value returned here is hardware dependent. In general, it's best to treat\n// it as an opaque value that can be divided by some number and passed to Set\n// (see Set documentation for more information).\nfunc (p *pwmGroup) Top() uint32 {\n\treturn p.getWrap()\n}\n\n// Counter returns the current counter value of the timer in this PWM\n// peripheral. It may be useful for debugging.\nfunc (p *pwmGroup) Counter() uint32 {\n\treturn (p.CTR.Get() & rp.PWM_CH0_CTR_CH0_CTR_Msk) >> rp.PWM_CH0_CTR_CH0_CTR_Pos\n}\n\n// Period returns the used PWM period in nanoseconds.\nfunc (p *pwmGroup) Period() uint64 {\n\t// Lines below can overflow if operations done without care.\n\t// maxInt=255, maxFrac=15, maxTop=65536, maxPHC=1 => maxProduct= (16*255+15) * (65536*2*1e9) = 5.3673e17 < MaxUint64=1.8e19 (close call.)\n\tconst compileTimeCheckPeriod uint64 = (255*16 + 15) * (65535 + 1) * 2 * 1e9\n\tfreq := uint64(CPUFrequency())\n\ttop := p.getWrap()\n\tphc := p.getPhaseCorrect()\n\tInt, frac := p.getClockDiv()\n\treturn (16*uint64(Int) + uint64(frac)) * uint64((top+1)*(phc+1)*1e9) / (16 * freq) // cycles = (TOP+1) * (CSRPHCorrect + 1) * (DIV_INT + DIV_FRAC/16)\n}\n\n// SetInverting sets whether to invert the output of this channel.\n// Without inverting, a 25% duty cycle would mean the output is high for 25% of\n// the time and low for the rest. Inverting flips the output as if a NOT gate\n// was placed at the output, meaning that the output would be 25% low and 75%\n// high with a duty cycle of 25%.\nfunc (p *pwmGroup) SetInverting(channel uint8, inverting bool) {\n\tchannel &= 1\n\tp.setInverting(channel, inverting)\n}\n\n// Set updates the channel value. This is used to control the channel duty\n// cycle, in other words the fraction of time the channel output is high (or low\n// when inverted). For example, to set it to a 25% duty cycle, use:\n//\n//\tpwm.Set(channel, pwm.Top() / 4)\n//\n// pwm.Set(channel, 0) will set the output to low and pwm.Set(channel,\n// pwm.Top()) will set the output to high, assuming the output isn't inverted.\nfunc (p *pwmGroup) Set(channel uint8, value uint32) {\n\tval := uint16(value)\n\tchannel &= 1\n\tp.setChanLevel(channel, val)\n}\n\n// Get current level (last set by Set). Default value on initialization is 0.\nfunc (p *pwmGroup) Get(channel uint8) (value uint32) {\n\tchannel &= 1\n\treturn uint32(p.getChanLevel(channel))\n}\n\n// SetTop sets TOP control register. Max value is 16bit (0xffff).\nfunc (p *pwmGroup) SetTop(top uint32) {\n\tp.setWrap(uint16(top))\n}\n\n// SetCounter sets counter control register. Max value is 16bit (0xffff).\n// Useful for synchronising two different PWM peripherals.\nfunc (p *pwmGroup) SetCounter(ctr uint32) {\n\tp.CTR.Set(ctr)\n}\n\n// Enable enables or disables PWM peripheral channels.\nfunc (p *pwmGroup) Enable(enable bool) {\n\tp.enable(enable)\n}\n\n// IsEnabled returns true if peripheral is enabled.\nfunc (p *pwmGroup) IsEnabled() (enabled bool) {\n\treturn (p.CSR.Get()&rp.PWM_CH0_CSR_EN_Msk)>>rp.PWM_CH0_CSR_EN_Pos != 0\n}\n\n// Initialise a PWM with settings from a configuration object.\n// If start is true then PWM starts on initialization.\nfunc (pwm *pwmGroup) init(config PWMConfig, start bool) error {\n\t// Not enable Phase correction\n\tpwm.setPhaseCorrect(false)\n\n\t// Clock mode set by default to Free running\n\tpwm.setDivMode(rp.PWM_CH0_CSR_DIVMODE_DIV)\n\n\t// Set Output polarity (false/false)\n\tpwm.setInverting(0, false)\n\tpwm.setInverting(1, false)\n\n\t// Set wrap. The highest value the counter will reach before returning to zero, also known as TOP.\n\tpwm.setWrap(0xffff)\n\t// period is set after TOP (Wrap).\n\terr := pwm.SetPeriod(config.Period)\n\tif err != nil {\n\t\treturn err\n\t}\n\t// period already set beforea\n\t// Reset counter and compare (pwm level set to zero)\n\tpwm.CTR.ReplaceBits(0, rp.PWM_CH0_CTR_CH0_CTR_Msk, 0) // PWM_CH0_CTR_RESET\n\tpwm.CC.Set(0)                                         // PWM_CH0_CC_RESET\n\n\tpwm.enable(start)\n\treturn nil\n}\n\nfunc (pwm *pwmGroup) setPhaseCorrect(correct bool) {\n\tpwm.CSR.ReplaceBits(boolToBit(correct)<<rp.PWM_CH0_CSR_PH_CORRECT_Pos, rp.PWM_CH0_CSR_PH_CORRECT_Msk, 0)\n}\n\n// Takes any of the following:\n//\n//\trp.PWM_CH0_CSR_DIVMODE_DIV, rp.PWM_CH0_CSR_DIVMODE_FALL,\n//\trp.PWM_CH0_CSR_DIVMODE_LEVEL, rp.PWM_CH0_CSR_DIVMODE_RISE\nfunc (pwm *pwmGroup) setDivMode(mode uint32) {\n\tpwm.CSR.ReplaceBits(mode<<rp.PWM_CH0_CSR_DIVMODE_Pos, rp.PWM_CH0_CSR_DIVMODE_Msk, 0)\n}\n\n// setPeriod sets the pwm peripheral period (frequency). Calculates DIV_INT,DIV_FRAC and sets it from following equation:\n//\n//\tcycles = (TOP+1) * (CSRPHCorrect + 1) * (DIV_INT + DIV_FRAC/16)\n//\n// where cycles is amount of clock cycles per PWM period.\nfunc (pwm *pwmGroup) setPeriod(period uint64) error {\n\t// This period calculation algorithm consists of\n\t// 1. Calculating best-fit prescale at a slightly lower-than-max TOP value\n\t// 2. Calculate TOP value to reach target period given the calculated prescale\n\t// 3. Apply calculated Prescale from step 1 and calculated Top from step 2\n\tconst (\n\t\tmaxTop = math.MaxUint16\n\t\t// start algorithm at 95% Top. This allows us to undershoot period with prescale.\n\t\ttopStart     = 95 * maxTop / 100\n\t\tnanosecond   = 1                  // 1e-9 [s]\n\t\tmicrosecond  = 1000 * nanosecond  // 1e-6 [s]\n\t\tmilliseconds = 1000 * microsecond // 1e-3 [s]\n\t\t// Maximum Period is 268369920ns on rp2040, given by (16*255+15)*8*(1+0xffff)*(1+1)/16\n\t\t// With no phase shift max period is half of this value.\n\t\tmaxPeriod = 268 * milliseconds\n\t\t// This will be a compile time error if this method is at risk of overflowing. cpufreq=155MHz for typical RP2350.\n\t\tmaxCPUFreq                       = 4 * GHz // Can go up to 4GHz without overflowing :)\n\t\tcompileTimeCheckSetPeriod uint64 = 16 * maxPeriod * maxCPUFreq\n\t)\n\n\tif period > maxPeriod || period < 8 {\n\t\treturn ErrBadPeriod\n\t}\n\tif period > maxPeriod/2 {\n\t\tpwm.setPhaseCorrect(true) // Must enable Phase correct to reach large periods.\n\t}\n\n\t// clearing above expression:\n\t//  DIV_INT + DIV_FRAC/16 = cycles / ( (TOP+1) * (CSRPHCorrect+1) )  // DIV_FRAC/16 is always 0 in this equation\n\t// where cycles must be converted to time:\n\t//  target_period = cycles * period_per_cycle ==> cycles = target_period/period_per_cycle\n\tvar (\n\t\tfreq  = uint64(CPUFrequency())\n\t\tphc   = uint64(pwm.getPhaseCorrect())\n\t\trhs   = 16 * period * freq / ((1 + phc) * 1e9 * (1 + topStart)) // right-hand-side of equation, scaled so frac is not divided\n\t\twhole = rhs / 16\n\t\tfrac  = rhs % 16\n\t)\n\tswitch {\n\tcase whole > 0xff:\n\t\twhole = 0xff\n\tcase whole == 0:\n\t\t// whole calculation underflowed so setting to minimum\n\t\t// permissible value in DIV_INT register.\n\t\twhole = 1\n\t\tfrac = 0\n\t}\n\n\t// Step 2 is acquiring a better top value. Clearing the equation:\n\t// TOP =  cycles / ( (DIVINT+DIVFRAC/16) * (CSRPHCorrect+1) ) - 1\n\ttop := 16*period*freq/((1+phc)*1e9*(16*whole+frac)) - 1\n\tif top > maxTop {\n\t\ttop = maxTop\n\t}\n\tpwm.SetTop(uint32(top))\n\tpwm.setClockDiv(uint8(whole), uint8(frac))\n\treturn nil\n}\n\n// Int is integer value to reduce counting rate by. Must be greater than or equal to 1. DIV_INT is bits 4:11 (8 bits).\n// frac's (DIV_FRAC) default value on reset is 0. Max value for frac is 15 (4 bits). This is known as a fixed-point\n// fractional number.\n//\n//\tcycles = (TOP+1) * (CSRPHCorrect + 1) * (DIV_INT + DIV_FRAC/16)\nfunc (pwm *pwmGroup) setClockDiv(Int, frac uint8) {\n\tpwm.DIV.ReplaceBits((uint32(frac)<<rp.PWM_CH0_DIV_FRAC_Pos)|\n\t\tu32max(uint32(Int), 1)<<rp.PWM_CH0_DIV_INT_Pos, rp.PWM_CH0_DIV_FRAC_Msk|rp.PWM_CH0_DIV_INT_Msk, 0)\n}\n\n// Set the highest value the counter will reach before returning to 0. Also\n// known as TOP.\n//\n// The counter wrap value is double-buffered in hardware. This means that,\n// when the PWM is running, a write to the counter wrap value does not take\n// effect until after the next time the PWM slice wraps (or, in phase-correct\n// mode, the next time the slice reaches 0). If the PWM is not running, the\n// write is latched in immediately.\nfunc (pwm *pwmGroup) setWrap(wrap uint16) {\n\tpwm.TOP.ReplaceBits(uint32(wrap)<<rp.PWM_CH0_TOP_CH0_TOP_Pos, rp.PWM_CH0_TOP_CH0_TOP_Msk, 0)\n}\n\n// enables/disables the PWM peripheral with rp.PWM_CH0_CSR_EN bit.\nfunc (pwm *pwmGroup) enable(enable bool) {\n\tpwm.CSR.ReplaceBits(boolToBit(enable)<<rp.PWM_CH0_CSR_EN_Pos, rp.PWM_CH0_CSR_EN_Msk, 0)\n}\n\nfunc (pwm *pwmGroup) setInverting(channel uint8, invert bool) {\n\tvar pos uint8\n\tvar msk uint32\n\tswitch channel {\n\tcase 0:\n\t\tpos = rp.PWM_CH0_CSR_A_INV_Pos\n\t\tmsk = rp.PWM_CH0_CSR_A_INV_Msk\n\tcase 1:\n\t\tpos = rp.PWM_CH0_CSR_B_INV_Pos\n\t\tmsk = rp.PWM_CH0_CSR_B_INV_Msk\n\t}\n\tpwm.CSR.ReplaceBits(boolToBit(invert)<<pos, msk, 0)\n}\n\n// Set the current PWM counter compare value for one channel\n//\n// The counter compare register is double-buffered in hardware. This means\n// that, when the PWM is running, a write to the counter compare values does\n// not take effect until the next time the PWM slice wraps (or, in\n// phase-correct mode, the next time the slice reaches 0). If the PWM is not\n// running, the write is latched in immediately.\n// Channel is 0 for A, 1 for B.\nfunc (pwm *pwmGroup) setChanLevel(channel uint8, level uint16) {\n\tvar pos uint8\n\tvar mask uint32\n\tswitch channel {\n\tcase 0:\n\t\tpos = rp.PWM_CH0_CC_A_Pos\n\t\tmask = rp.PWM_CH0_CC_A_Msk\n\tcase 1:\n\t\tpos = rp.PWM_CH0_CC_B_Pos\n\t\tmask = rp.PWM_CH0_CC_B_Msk\n\t}\n\tpwm.CC.ReplaceBits(uint32(level)<<pos, mask, 0)\n}\n\nfunc (pwm *pwmGroup) getChanLevel(channel uint8) (level uint16) {\n\tvar pos uint8\n\tvar mask uint32\n\tswitch channel {\n\tcase 0:\n\t\tpos = rp.PWM_CH0_CC_A_Pos\n\t\tmask = rp.PWM_CH0_CC_A_Msk\n\tcase 1:\n\t\tpos = rp.PWM_CH0_CC_B_Pos\n\t\tmask = rp.PWM_CH0_CC_B_Msk\n\t}\n\n\tlevel = uint16((pwm.CC.Get() & mask) >> pos)\n\treturn level\n}\n\nfunc (pwm *pwmGroup) getWrap() (top uint32) {\n\treturn (pwm.TOP.Get() & rp.PWM_CH0_TOP_CH0_TOP_Msk) >> rp.PWM_CH0_TOP_CH0_TOP_Pos\n}\n\nfunc (pwm *pwmGroup) getPhaseCorrect() (phCorrect uint32) {\n\treturn (pwm.CSR.Get() & rp.PWM_CH0_CSR_PH_CORRECT_Msk) >> rp.PWM_CH0_CSR_PH_CORRECT_Pos\n}\n\nfunc (pwm *pwmGroup) getClockDiv() (Int, frac uint8) {\n\tdiv := pwm.DIV.Get()\n\treturn uint8((div & rp.PWM_CH0_DIV_INT_Msk) >> rp.PWM_CH0_DIV_INT_Pos), uint8((div & rp.PWM_CH0_DIV_FRAC_Msk) >> rp.PWM_CH0_DIV_FRAC_Pos)\n}\n\n// pwmGPIOToSlice Determine the PWM channel that is attached to the specified GPIO.\n// gpio must be less than 30. Returns the PWM slice number that controls the specified GPIO.\nfunc pwmGPIOToSlice(gpio Pin) (slicenum uint8) {\n\tif is48Pin && gpio >= 32 {\n\t\treturn uint8(8 + ((gpio-32)/2)%4)\n\t}\n\treturn (uint8(gpio) >> 1) & 7\n}\n\n// Determine the PWM channel that is attached to the specified GPIO.\n// Each slice 0 to 7 has two channels, A and B.\nfunc pwmGPIOToChannel(gpio Pin) (channel uint8) {\n\treturn uint8(gpio) & 1\n}\n"
  },
  {
    "path": "src/machine/machine_rp2_resets.go",
    "content": "//go:build rp2040 || rp2350\n\npackage machine\n\nimport (\n\t\"device/rp\"\n\t\"unsafe\"\n)\n\nvar resets = (*rp.RESETS_Type)(unsafe.Pointer(rp.RESETS))\n\n// resetBlock resets hardware blocks specified\n// by the bit pattern in bits.\nfunc resetBlock(bits uint32) {\n\tresets.RESET.SetBits(bits)\n}\n\n// unresetBlock brings hardware blocks specified by the\n// bit pattern in bits out of reset.\nfunc unresetBlock(bits uint32) {\n\tresets.RESET.ClearBits(bits)\n}\n\n// unresetBlockWait brings specified hardware blocks\n// specified by the bit pattern in bits\n// out of reset and wait for completion.\nfunc unresetBlockWait(bits uint32) {\n\tunresetBlock(bits)\n\tfor !resets.RESET_DONE.HasBits(bits) {\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_rp2_rng.go",
    "content": "//go:build rp2040 || rp2350\n\n// Implementation based on code located here:\n// https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/pico_lwip/random.c\n\npackage machine\n\nimport (\n\t\"device/rp\"\n)\n\nconst numberOfCycles = 32\n\n// GetRNG returns 32 bits of semi-random data based on ring oscillator.\n//\n// Unlike some other implementations of GetRNG, these random numbers are not\n// cryptographically secure and must not be used for cryptographic operations\n// (nonces, etc).\nfunc GetRNG() (uint32, error) {\n\tvar val uint32\n\tfor i := 0; i < 4; i++ {\n\t\tval = (val << 8) | uint32(roscRandByte())\n\t}\n\treturn val, nil\n}\n\nvar randomByte uint8\n\nfunc roscRandByte() uint8 {\n\tvar poly uint8\n\tfor i := 0; i < numberOfCycles; i++ {\n\t\tif randomByte&0x80 != 0 {\n\t\t\tpoly = 0x35\n\t\t} else {\n\t\t\tpoly = 0\n\t\t}\n\t\trandomByte = ((randomByte << 1) | uint8(rp.ROSC.GetRANDOMBIT()) ^ poly)\n\t\t// TODO: delay a little because the random bit is a little slow\n\t}\n\treturn randomByte\n}\n"
  },
  {
    "path": "src/machine/machine_rp2_spi.go",
    "content": "//go:build rp2040 || rp2350\n\npackage machine\n\nimport (\n\t\"device/rp\"\n\t\"errors\"\n\t\"unsafe\"\n)\n\n// SPI on the RP2040\nvar (\n\tSPI0 = &SPI{\n\t\tBus: rp.SPI0,\n\t}\n\tSPI1 = &SPI{\n\t\tBus: rp.SPI1,\n\t}\n)\n\n// SPIConfig is used to store config info for SPI.\ntype SPIConfig struct {\n\tFrequency uint32\n\t// LSB not supported on rp2040.\n\tLSBFirst bool\n\t// Mode's two most LSB are CPOL and CPHA. i.e. Mode==2 (0b10) is CPOL=1, CPHA=0\n\tMode uint8\n\t// Serial clock pin\n\tSCK Pin\n\t// TX or Serial Data Out (MOSI if rp2040 is master)\n\tSDO Pin\n\t// RX or Serial Data In (MISO if rp2040 is master)\n\tSDI Pin\n}\n\nvar (\n\tErrLSBNotSupported = errors.New(\"SPI LSB unsupported on PL022\")\n\tErrSPITimeout      = errors.New(\"SPI timeout\")\n\tErrSPIBaud         = errors.New(\"SPI baud too low or above 66.5Mhz\")\n\terrSPIInvalidSDI   = errors.New(\"invalid SPI SDI pin\")\n\terrSPIInvalidSDO   = errors.New(\"invalid SPI SDO pin\")\n\terrSPIInvalidSCK   = errors.New(\"invalid SPI SCK pin\")\n)\n\ntype SPI struct {\n\tBus *rp.SPI0_Type\n}\n\n// Tx handles read/write operation for SPI interface. Since SPI is a synchronous write/read\n// interface, there must always be the same number of bytes written as bytes read.\n// The Tx method knows about this, and offers a few different ways of calling it.\n//\n// This form sends the bytes in tx buffer, putting the resulting bytes read into the rx buffer.\n// Note that the tx and rx buffers must be the same size:\n//\n//\tspi.Tx(tx, rx)\n//\n// This form sends the tx buffer, ignoring the result. Useful for sending \"commands\" that return zeros\n// until all the bytes in the command packet have been received:\n//\n//\tspi.Tx(tx, nil)\n//\n// This form sends zeros, putting the result into the rx buffer. Good for reading a \"result packet\":\n//\n//\tspi.Tx(nil, rx)\n//\n// Remark: This implementation (RP2040) allows reading into buffer with a custom repeated\n// value on tx.\n//\n//\tspi.Tx([]byte{0xff}, rx) // may cause unwanted heap allocations.\n//\n// This form sends 0xff and puts the result into rx buffer. Useful for reading from SD cards\n// which require 0xff input on SI.\nfunc (spi *SPI) Tx(w, r []byte) (err error) {\n\tswitch {\n\tcase w == nil:\n\t\t// read only, so write zero and read a result.\n\t\terr = spi.rx(r, 0)\n\tcase r == nil:\n\t\t// write only\n\t\terr = spi.tx(w)\n\tcase len(w) == 1 && len(r) > 1:\n\t\t// Read with custom repeated value.\n\t\terr = spi.rx(r, w[0])\n\tdefault:\n\t\t// write/read\n\t\terr = spi.txrx(w, r)\n\t}\n\treturn err\n}\n\n// Write a single byte and read a single byte from TX/RX FIFO.\nfunc (spi *SPI) Transfer(w byte) (byte, error) {\n\tfor !spi.isWritable() {\n\t}\n\n\tspi.Bus.SSPDR.Set(uint32(w))\n\n\tfor !spi.isReadable() {\n\t}\n\treturn uint8(spi.Bus.SSPDR.Get()), nil\n}\n\nfunc (spi *SPI) SetBaudRate(br uint32) error {\n\tconst maxBaud uint32 = 66.5 * MHz // max output frequency is 66.5MHz on rp2040. see Note page 527.\n\t// Find smallest prescale value which puts output frequency in range of\n\t// post-divide. Prescale is an even number from 2 to 254 inclusive.\n\tvar prescale, postdiv uint32\n\tfreq := CPUFrequency()\n\tfor prescale = 2; prescale < 255; prescale += 2 {\n\t\tif uint64(freq) < uint64((prescale+2)*256)*uint64(br) {\n\t\t\tbreak\n\t\t}\n\t}\n\tif prescale > 254 || br > maxBaud {\n\t\treturn ErrSPIBaud\n\t}\n\t// Find largest post-divide which makes output <= baudrate. Post-divide is\n\t// an integer in the range 1 to 256 inclusive.\n\tfor postdiv = 256; postdiv > 1; postdiv-- {\n\t\tif freq/(prescale*(postdiv-1)) > br {\n\t\t\tbreak\n\t\t}\n\t}\n\tspi.Bus.SSPCPSR.Set(prescale)\n\tspi.Bus.SSPCR0.ReplaceBits((postdiv-1)<<rp.SPI0_SSPCR0_SCR_Pos, rp.SPI0_SSPCR0_SCR_Msk, 0)\n\treturn nil\n}\n\nfunc (spi *SPI) GetBaudRate() uint32 {\n\tfreqin := CPUFrequency()\n\tprescale := spi.Bus.SSPCPSR.Get()\n\tpostdiv := ((spi.Bus.SSPCR0.Get() & rp.SPI0_SSPCR0_SCR_Msk) >> rp.SPI0_SSPCR0_SCR_Pos) + 1\n\treturn freqin / (prescale * postdiv)\n}\n\n// Configure is intended to setup/initialize the SPI interface.\n// Default baudrate of 4MHz is used if Frequency == 0. Default\n// word length (data bits) is 8.\n// Below is a list of GPIO pins corresponding to SPI0 bus on the rp2040:\n//\n//\tSI : 0, 4, 17  a.k.a RX and MISO (if rp2040 is master)\n//\tSO : 3, 7, 19  a.k.a TX and MOSI (if rp2040 is master)\n//\tSCK: 2, 6, 18\n//\n// SPI1 bus GPIO pins:\n//\n//\tSI : 8, 12\n//\tSO : 11, 15\n//\tSCK: 10, 14\n//\n// No pin configuration is needed of SCK, SDO and SDI needed after calling Configure.\nfunc (spi *SPI) Configure(config SPIConfig) error {\n\tconst defaultBaud uint32 = 4 * MHz\n\tif config.SCK == 0 && config.SDO == 0 && config.SDI == 0 {\n\t\t// set default pins if config zero valued or invalid clock pin supplied.\n\t\tswitch spi.Bus {\n\t\tcase rp.SPI0:\n\t\t\tconfig.SCK = SPI0_SCK_PIN\n\t\t\tconfig.SDO = SPI0_SDO_PIN\n\t\t\tconfig.SDI = SPI0_SDI_PIN\n\t\tcase rp.SPI1:\n\t\t\tconfig.SCK = SPI1_SCK_PIN\n\t\t\tconfig.SDO = SPI1_SDO_PIN\n\t\t\tconfig.SDI = SPI1_SDI_PIN\n\t\t}\n\t}\n\tif err := spi.validPins(config); err != nil {\n\t\treturn err\n\t}\n\tif config.Frequency == 0 {\n\t\tconfig.Frequency = defaultBaud\n\t}\n\t// SPI pin configuration\n\tconfig.SCK.setFunc(fnSPI)\n\tconfig.SDO.setFunc(fnSPI)\n\tconfig.SDI.setFunc(fnSPI)\n\n\treturn spi.initSPI(config)\n}\n\nfunc (spi *SPI) initSPI(config SPIConfig) (err error) {\n\tspi.reset()\n\t// LSB-first not supported on PL022:\n\tif config.LSBFirst {\n\t\treturn ErrLSBNotSupported\n\t}\n\terr = spi.SetBaudRate(config.Frequency)\n\t// Set SPI Format (CPHA and CPOL) and frame format (default is Motorola)\n\tspi.setFormat(config.Mode)\n\n\t// Always enable DREQ signals -- harmless if DMA is not listening\n\tspi.Bus.SSPDMACR.SetBits(rp.SPI0_SSPDMACR_TXDMAE | rp.SPI0_SSPDMACR_RXDMAE)\n\t// Finally enable the SPI\n\tspi.Bus.SSPCR1.SetBits(rp.SPI0_SSPCR1_SSE)\n\treturn err\n}\n\n//go:inline\nfunc (spi *SPI) setFormat(mode uint8) {\n\tcpha := uint32(mode) & 1\n\tcpol := uint32(mode>>1) & 1\n\tspi.Bus.SSPCR0.ReplaceBits(\n\t\t(cpha<<rp.SPI0_SSPCR0_SPH_Pos)|\n\t\t\t(cpol<<rp.SPI0_SSPCR0_SPO_Pos)|\n\t\t\t(uint32(7)<<rp.SPI0_SSPCR0_DSS_Pos), // Set databits (SPI word length) to 8 bits.\n\t\trp.SPI0_SSPCR0_SPH_Msk|rp.SPI0_SSPCR0_SPO_Msk|rp.SPI0_SSPCR0_DSS_Msk|rp.SPI0_SSPCR0_FRF_Msk, 0)\n}\n\n// reset resets SPI and waits until reset is done.\n//\n//go:inline\nfunc (spi *SPI) reset() {\n\tresetVal := spi.deinit()\n\trp.RESETS.RESET.ClearBits(resetVal)\n\t// Wait until reset is done.\n\tfor !rp.RESETS.RESET_DONE.HasBits(resetVal) {\n\t}\n}\n\n//go:inline\nfunc (spi *SPI) deinit() (resetVal uint32) {\n\tswitch spi.Bus {\n\tcase rp.SPI0:\n\t\tresetVal = rp.RESETS_RESET_SPI0\n\tcase rp.SPI1:\n\t\tresetVal = rp.RESETS_RESET_SPI1\n\t}\n\t// Perform SPI reset.\n\trp.RESETS.RESET.SetBits(resetVal)\n\treturn resetVal\n}\n\n// isWritable returns false if no space is available to write. True if a write is possible\n//\n//go:inline\nfunc (spi *SPI) isWritable() bool {\n\treturn spi.Bus.SSPSR.HasBits(rp.SPI0_SSPSR_TNF)\n}\n\n// isReadable returns true if a read is possible i.e. data is present\n//\n//go:inline\nfunc (spi *SPI) isReadable() bool {\n\treturn spi.Bus.SSPSR.HasBits(rp.SPI0_SSPSR_RNE)\n}\n\n// PrintRegs prints SPI's peripheral common registries current values\nfunc (spi *SPI) PrintRegs() {\n\tcr0 := spi.Bus.SSPCR0.Get()\n\tcr1 := spi.Bus.SSPCR1.Get()\n\tdmacr := spi.Bus.SSPDMACR.Get()\n\tcpsr := spi.Bus.SSPCPSR.Get()\n\tdr := spi.Bus.SSPDR.Get()\n\tris := spi.Bus.SSPRIS.Get()\n\tprintln(\"CR0:\", cr0)\n\tprintln(\"CR1:\", cr1)\n\tprintln(\"DMACR:\", dmacr)\n\tprintln(\"CPSR:\", cpsr)\n\tprintln(\"DR:\", dr)\n\tprintln(\"RIS:\", ris)\n}\n\n//go:inline\nfunc (spi *SPI) isBusy() bool {\n\treturn spi.Bus.SSPSR.HasBits(rp.SPI0_SSPSR_BSY)\n}\n\n// tx writes buffer to SPI ignoring Rx.\nfunc (spi *SPI) tx(tx []byte) error {\n\tif len(tx) == 0 {\n\t\t// We don't have to do anything.\n\t\t// This avoids a panic in &tx[0] when len(tx) == 0.\n\t\treturn nil\n\t}\n\n\t// Pick the DMA channel reserved for this SPI peripheral.\n\tvar ch *dmaChannel\n\tvar dreq uint32\n\tif spi.Bus == rp.SPI0 {\n\t\tch = &dmaChannels[spi0DMAChannel]\n\t\tdreq = rp.DREQ_SPI0_TX\n\t} else { // SPI1\n\t\tch = &dmaChannels[spi1DMAChannel]\n\t\tdreq = rp.DREQ_SPI1_TX\n\t}\n\n\t// Configure the DMA peripheral as follows:\n\t//   - set read address, write address, and number of transfer units (bytes)\n\t//   - increment read address (in memory), don't increment write address (SSPDR)\n\t//   - set data size to single bytes\n\t//   - set the DREQ so that the DMA will fill the SPI FIFO as needed\n\t//   - start the transfer\n\tch.READ_ADDR.Set(uint32(unsafeNoEscape(unsafe.Pointer(unsafe.SliceData(tx)))))\n\tch.WRITE_ADDR.Set(uint32(uintptr(unsafe.Pointer(&spi.Bus.SSPDR))))\n\tch.TRANS_COUNT.Set(uint32(len(tx)))\n\tch.CTRL_TRIG.Set(rp.DMA_CH0_CTRL_TRIG_INCR_READ |\n\t\trp.DMA_CH0_CTRL_TRIG_DATA_SIZE_SIZE_BYTE<<rp.DMA_CH0_CTRL_TRIG_DATA_SIZE_Pos |\n\t\tdreq<<rp.DMA_CH0_CTRL_TRIG_TREQ_SEL_Pos |\n\t\trp.DMA_CH0_CTRL_TRIG_EN)\n\n\t// Wait until the transfer is complete.\n\t// TODO: do this more efficiently:\n\t//   - Add a new API to start the transfer, without waiting for it to\n\t//     complete. This way, the CPU can do something useful while the\n\t//     transfer is in progress.\n\t//   - If we have to wait, do so by waiting for an interrupt and blocking\n\t//     this goroutine until finished (so that other goroutines can run or\n\t//     the CPU can go to sleep).\n\tfor ch.CTRL_TRIG.Get()&rp.DMA_CH0_CTRL_TRIG_BUSY != 0 {\n\t}\n\n\t// Make sure the read buffer stays alive until this point (in the unlikely\n\t// case the tx slice wasn't read after this function returns and a GC cycle\n\t// happened inbetween).\n\tkeepAliveNoEscape(unsafe.Pointer(unsafe.SliceData(tx)))\n\n\t// We didn't read any result values, which means the RX FIFO has likely\n\t// overflown. We have to clean up this mess now.\n\n\t// Drain RX FIFO, then wait for shifting to finish (which may be *after*\n\t// TX FIFO drains), then drain RX FIFO again\n\tfor spi.isReadable() {\n\t\tspi.Bus.SSPDR.Get()\n\t}\n\tfor spi.isBusy() {\n\t}\n\tfor spi.isReadable() {\n\t\tspi.Bus.SSPDR.Get()\n\t}\n\t// Don't leave overrun flag set\n\tspi.Bus.SSPICR.Set(rp.SPI0_SSPICR_RORIC)\n\treturn nil\n}\n\n// rx reads buffer to SPI ignoring x.\n// txrepeat is output repeatedly on SO as data is read in from SI.\n// Generally this can be 0, but some devices require a specific value here,\n// e.g. SD cards expect 0xff\nfunc (spi *SPI) rx(rx []byte, txrepeat byte) error {\n\tplen := len(rx)\n\tconst fifoDepth = 8 // see txrx\n\tvar rxleft, txleft = plen, plen\n\tfor txleft != 0 || rxleft != 0 {\n\t\tif txleft != 0 && spi.isWritable() && rxleft < txleft+fifoDepth {\n\t\t\tspi.Bus.SSPDR.Set(uint32(txrepeat))\n\t\t\ttxleft--\n\t\t}\n\t\tif rxleft != 0 && spi.isReadable() {\n\t\t\trx[plen-rxleft] = uint8(spi.Bus.SSPDR.Get())\n\t\t\trxleft--\n\t\t\tcontinue\n\t\t}\n\t}\n\tfor spi.isBusy() {\n\t\tgosched()\n\t}\n\treturn nil\n}\n\n// Write len bytes from src to SPI. Simultaneously read len bytes from SPI to dst.\n// Note this function is guaranteed to exit in a known amount of time (bits sent * time per bit)\nfunc (spi *SPI) txrx(tx, rx []byte) error {\n\tplen := len(tx)\n\tif plen != len(rx) {\n\t\treturn ErrTxInvalidSliceSize\n\t}\n\t// Never have more transfers in flight than will fit into the RX FIFO,\n\t// else FIFO will overflow if this code is heavily interrupted.\n\tconst fifoDepth = 8\n\tvar rxleft, txleft = plen, plen\n\tfor txleft != 0 || rxleft != 0 {\n\t\tif txleft != 0 && spi.isWritable() && rxleft < txleft+fifoDepth {\n\t\t\tspi.Bus.SSPDR.Set(uint32(tx[plen-txleft]))\n\t\t\ttxleft--\n\t\t}\n\t\tif rxleft != 0 && spi.isReadable() {\n\t\t\trx[plen-rxleft] = uint8(spi.Bus.SSPDR.Get())\n\t\t\trxleft--\n\t\t}\n\t}\n\n\tif txleft != 0 || rxleft != 0 {\n\t\t// Transaction ended early due to timeout\n\t\treturn ErrSPITimeout\n\t}\n\tfor spi.isBusy() {\n\t\tgosched()\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "src/machine/machine_rp2_sync.go",
    "content": "//go:build rp2040 || rp2350\n\npackage machine\n\n// machine_rp2040_sync.go contains interrupt and\n// lock primitives similar to those found in Pico SDK's\n// irq.c\n\n// Clears interrupt flag on a pin\nfunc (p Pin) acknowledgeInterrupt(change PinChange) {\n\tioBank0.intR[p>>3].Set(p.ioIntBit(change))\n}\n\n// Basic interrupt setting via ioBANK0 for GPIO interrupts.\nfunc (p Pin) setInterrupt(change PinChange, enabled bool) {\n\t// Separate mask/force/status per-core, so check which core called, and\n\t// set the relevant IRQ controls.\n\tswitch CurrentCore() {\n\tcase 0:\n\t\tp.ctrlSetInterrupt(change, enabled, &ioBank0.proc0IRQctrl)\n\tcase 1:\n\t\tp.ctrlSetInterrupt(change, enabled, &ioBank0.proc1IRQctrl)\n\t}\n}\n\n// ctrlSetInterrupt acknowledges any pending interrupt and enables or disables\n// the interrupt for a given IRQ control bank (IOBANK, DormantIRQ, QSPI).\n//\n// pico-sdk calls this the _gpio_set_irq_enabled, not to be confused with\n// gpio_set_irq_enabled (no leading underscore).\nfunc (p Pin) ctrlSetInterrupt(change PinChange, enabled bool, base *irqCtrl) {\n\tp.acknowledgeInterrupt(change)\n\tenReg := &base.intE[p>>3]\n\tif enabled {\n\t\tenReg.SetBits(p.ioIntBit(change))\n\t} else {\n\t\tenReg.ClearBits(p.ioIntBit(change))\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_rp2_timer.go",
    "content": "//go:build rp2040 || rp2350\n\npackage machine\n\nimport (\n\t\"device/arm\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n)\n\nconst numTimers = 4\n\n// Alarm0 is reserved for sleeping by tinygo runtime code for RP2040.\n// Alarm0 is also IRQ0\nconst sleepAlarm = 0\nconst sleepAlarmIRQ = 0\n\n// The minimum sleep duration in μs (ticks)\nconst minSleep = 10\n\ntype timerType struct {\n\ttimeHW   volatile.Register32\n\ttimeLW   volatile.Register32\n\ttimeHR   volatile.Register32\n\ttimeLR   volatile.Register32\n\talarm    [numTimers]volatile.Register32\n\tarmed    volatile.Register32\n\ttimeRawH volatile.Register32\n\ttimeRawL volatile.Register32\n\tdbgPause volatile.Register32\n\tpause    volatile.Register32\n\tlocked   [rp2350ExtraReg]volatile.Register32\n\tsource   [rp2350ExtraReg]volatile.Register32\n\tintR     volatile.Register32\n\tintE     volatile.Register32\n\tintF     volatile.Register32\n\tintS     volatile.Register32\n}\n\n// TimeElapsed returns time elapsed since power up, in microseconds.\nfunc (tmr *timerType) timeElapsed() (us uint64) {\n\t// Need to make sure that the upper 32 bits of the timer\n\t// don't change, so read that first\n\thi := tmr.timeRawH.Get()\n\tvar lo, nextHi uint32\n\tfor {\n\t\t// Read the lower 32 bits\n\t\tlo = tmr.timeRawL.Get()\n\t\t// Now read the upper 32 bits again and\n\t\t// check that it hasn't incremented. If it has, loop around\n\t\t// and read the lower 32 bits again to get an accurate value\n\t\tnextHi = tmr.timeRawH.Get()\n\t\tif hi == nextHi {\n\t\t\tbreak\n\t\t}\n\t\thi = nextHi\n\t}\n\treturn uint64(hi)<<32 | uint64(lo)\n}\n\n// lightSleep will put the processor into a sleep state a short period\n// (up to approx 72mins per RP2040 datasheet, 4.6.3. Alarms).\n//\n// This function is a 'light' sleep and will return early if another\n// interrupt or event triggers.  This is intentional since the\n// primary use-case is for use by the TinyGo scheduler which will\n// re-sleep if needed.\nfunc (tmr *timerType) lightSleep(us uint64) {\n\t// minSleep is a way to avoid race conditions for short\n\t// sleeps by ensuring there is enough time to setup the\n\t// alarm before sleeping.  For very short sleeps, this\n\t// effectively becomes a 'busy loop'.\n\tif us < minSleep {\n\t\treturn\n\t}\n\n\t// Interrupt handler is essentially a no-op, we're just relying\n\t// on the side-effect of waking the CPU from \"wfe\"\n\tintr := interrupt.New(sleepAlarmIRQ, func(interrupt.Interrupt) {\n\t\t// Clear the IRQ\n\t\ttimer.intR.Set(1 << sleepAlarm)\n\t})\n\n\t// Reset interrupt flag\n\ttmr.intR.Set(1 << sleepAlarm)\n\n\t// Enable interrupt\n\ttmr.intE.SetBits(1 << sleepAlarm)\n\tintr.Enable()\n\n\t// Only the low 32 bits of time can be used for alarms\n\ttarget := uint64(tmr.timeRawL.Get()) + us\n\ttmr.alarm[sleepAlarm].Set(uint32(target))\n\n\t// Wait for sleep (or any other) interrupt\n\tarm.Asm(\"wfe\")\n\n\t// Disarm timer\n\ttmr.armed.Set(1 << sleepAlarm)\n\n\t// Disable interrupt\n\tintr.Disable()\n}\n\n// setDbgPause sets whether this timer is paused when a debugger is connected.\nfunc (tmr *timerType) setDbgPause(enable bool) {\n\tconst bitPos = 1\n\tconst bitMask = 0b11\n\tval := uint32(0b00)\n\tif enable {\n\t\t// Disable timer when debugger is connected to either core.\n\t\tval = 0b11\n\t}\n\ttmr.dbgPause.ReplaceBits(val, bitMask, bitPos)\n}\n"
  },
  {
    "path": "src/machine/machine_rp2_uart.go",
    "content": "//go:build rp2040 || rp2350\n\npackage machine\n\nimport (\n\t\"device/rp\"\n\t\"runtime/interrupt\"\n)\n\n// UART on the RP2040.\ntype UART struct {\n\tBuffer    *RingBuffer\n\tBus       *rp.UART0_Type\n\tInterrupt interrupt.Interrupt\n}\n\n// Configure the UART.\nfunc (uart *UART) Configure(config UARTConfig) error {\n\tinitUART(uart)\n\n\t// Default baud rate to 115200.\n\tif config.BaudRate == 0 {\n\t\tconfig.BaudRate = 115200\n\t}\n\n\t// Use default pins if pins are not set.\n\tif config.TX == 0 && config.RX == 0 {\n\t\t// use default pins\n\t\tconfig.TX = UART_TX_PIN\n\t\tconfig.RX = UART_RX_PIN\n\t}\n\n\tuart.SetBaudRate(config.BaudRate)\n\n\t// default to 8-1-N\n\tuart.SetFormat(8, 1, ParityNone)\n\n\t// Enable the UART, both TX and RX\n\tsettings := uint32(rp.UART0_UARTCR_UARTEN |\n\t\trp.UART0_UARTCR_RXE |\n\t\trp.UART0_UARTCR_TXE)\n\tconst bits = rp.UART0_UARTCR_UARTEN | rp.UART0_UARTCR_TXE\n\tif config.RTS != 0 {\n\t\tsettings |= rp.UART0_UARTCR_RTSEN\n\t}\n\tif config.CTS != 0 {\n\t\tsettings |= rp.UART0_UARTCR_CTSEN\n\t}\n\n\tuart.Bus.UARTCR.SetBits(settings)\n\n\t// set GPIO mux to UART for the pins\n\tif config.TX != NoPin {\n\t\tconfig.TX.Configure(PinConfig{Mode: PinUART})\n\t}\n\tif config.RX != NoPin {\n\t\tconfig.RX.Configure(PinConfig{Mode: PinUART})\n\t}\n\tif config.RTS != 0 {\n\t\tconfig.RTS.Configure(PinConfig{Mode: PinOutput})\n\t}\n\tif config.CTS != 0 {\n\t\tconfig.CTS.Configure(PinConfig{Mode: PinInput})\n\t}\n\n\t// Enable RX IRQ.\n\tuart.Interrupt.SetPriority(0x80)\n\tuart.Interrupt.Enable()\n\n\t// Setup interrupt on receive.\n\tuart.Bus.UARTIMSC.Set(rp.UART0_UARTIMSC_RXIM)\n\n\treturn nil\n}\n\n// SetBaudRate sets the baudrate to be used for the UART.\nfunc (uart *UART) SetBaudRate(br uint32) {\n\tdiv := 8 * CPUFrequency() / br\n\n\tibrd := div >> 7\n\tvar fbrd uint32\n\n\tswitch {\n\tcase ibrd == 0:\n\t\tibrd = 1\n\t\tfbrd = 0\n\tcase ibrd >= 65535:\n\t\tibrd = 65535\n\t\tfbrd = 0\n\tdefault:\n\t\tfbrd = ((div & 0x7f) + 1) / 2\n\t}\n\n\t// set PL011 baud divisor registers\n\tuart.Bus.UARTIBRD.Set(ibrd)\n\tuart.Bus.UARTFBRD.Set(fbrd)\n\n\t// PL011 needs a (dummy) line control register write.\n\t// See https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/hardware_uart/uart.c#L93-L95\n\tuart.Bus.UARTLCR_H.SetBits(0)\n}\n\n// WriteByte writes a byte of data to the UART.\nfunc (uart *UART) writeByte(c byte) error {\n\t// wait until buffer is not full\n\tfor uart.Bus.UARTFR.HasBits(rp.UART0_UARTFR_TXFF) {\n\t\tif !interrupt.In() {\n\t\t\tgosched()\n\t\t}\n\t}\n\n\t// write data\n\tuart.Bus.UARTDR.Set(uint32(c))\n\treturn nil\n}\n\nfunc (uart *UART) flush() {\n\tfor uart.Bus.UARTFR.HasBits(rp.UART0_UARTFR_BUSY) {\n\t\tif !interrupt.In() {\n\t\t\tgosched()\n\t\t}\n\t}\n}\n\n// SetFormat for number of data bits, stop bits, and parity for the UART.\nfunc (uart *UART) SetFormat(databits, stopbits uint8, parity UARTParity) error {\n\tvar pen, pev uint8\n\tif parity != ParityNone {\n\t\tpen = rp.UART0_UARTLCR_H_PEN\n\t}\n\tif parity == ParityEven {\n\t\tpev = rp.UART0_UARTLCR_H_EPS\n\t}\n\tuart.Bus.UARTLCR_H.SetBits(uint32((databits-5)<<rp.UART0_UARTLCR_H_WLEN_Pos |\n\t\t(stopbits-1)<<rp.UART0_UARTLCR_H_STP2_Pos |\n\t\tpen | pev))\n\n\treturn nil\n}\n\nfunc initUART(uart *UART) {\n\tvar resetVal uint32\n\tswitch {\n\tcase uart.Bus == rp.UART0:\n\t\tresetVal = rp.RESETS_RESET_UART0\n\tcase uart.Bus == rp.UART1:\n\t\tresetVal = rp.RESETS_RESET_UART1\n\t}\n\n\t// reset UART\n\trp.RESETS.RESET.SetBits(resetVal)\n\trp.RESETS.RESET.ClearBits(resetVal)\n\tfor !rp.RESETS.RESET_DONE.HasBits(resetVal) {\n\t}\n}\n\n// handleInterrupt should be called from the appropriate interrupt handler for\n// this UART instance.\nfunc (uart *UART) handleInterrupt(interrupt.Interrupt) {\n\tfor !uart.Bus.UARTFR.HasBits(rp.UART0_UARTFR_RXFE) {\n\t\tuart.Receive(byte((uart.Bus.UARTDR.Get() & 0xFF)))\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_rp2_usb.go",
    "content": "//go:build rp2040 || rp2350\n\npackage machine\n\nimport (\n\t\"machine/usb\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nconst NumberOfUSBEndpoints = 8\n\nvar (\n\tsendOnEP0DATADONE struct {\n\t\toffset int\n\t\tdata   []byte\n\t\tpid    uint32\n\t}\n\n\tendPoints = []uint32{\n\t\tusb.CONTROL_ENDPOINT:  usb.ENDPOINT_TYPE_CONTROL,\n\t\tusb.CDC_ENDPOINT_ACM:  (usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn),\n\t\tusb.CDC_ENDPOINT_OUT:  (usb.ENDPOINT_TYPE_BULK | usb.EndpointOut),\n\t\tusb.CDC_ENDPOINT_IN:   (usb.ENDPOINT_TYPE_BULK | usb.EndpointIn),\n\t\tusb.HID_ENDPOINT_IN:   (usb.ENDPOINT_TYPE_DISABLE), // Interrupt In\n\t\tusb.HID_ENDPOINT_OUT:  (usb.ENDPOINT_TYPE_DISABLE), // Interrupt Out\n\t\tusb.MIDI_ENDPOINT_IN:  (usb.ENDPOINT_TYPE_DISABLE), // Bulk In\n\t\tusb.MIDI_ENDPOINT_OUT: (usb.ENDPOINT_TYPE_DISABLE), // Bulk Out\n\t}\n)\n\nfunc initEndpoint(ep, config uint32) {\n\tval := uint32(usbEpControlEnable) | uint32(usbEpControlInterruptPerBuff)\n\toffset := ep*2*usbBufferLen + 0x100\n\tval |= offset\n\n\t// Bulk and interrupt endpoints must have their Packet ID reset to DATA0 when un-stalled.\n\tepXPIDReset[ep] = false // Default to false in case an endpoint is re-initialized.\n\n\tswitch config {\n\tcase usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn:\n\t\tval |= usbEpControlEndpointTypeInterrupt\n\t\t_usbDPSRAM.EPxControl[ep].In.Set(val)\n\t\tepXPIDReset[ep] = true\n\n\tcase usb.ENDPOINT_TYPE_BULK | usb.EndpointOut:\n\t\tval |= usbEpControlEndpointTypeBulk\n\t\t_usbDPSRAM.EPxControl[ep].Out.Set(val)\n\t\t_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)\n\t\t_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)\n\t\tepXPIDReset[ep] = true\n\n\tcase usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointOut:\n\t\tval |= usbEpControlEndpointTypeInterrupt\n\t\t_usbDPSRAM.EPxControl[ep].Out.Set(val)\n\t\t_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)\n\t\t_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)\n\t\tepXPIDReset[ep] = true\n\n\tcase usb.ENDPOINT_TYPE_BULK | usb.EndpointIn:\n\t\tval |= usbEpControlEndpointTypeBulk\n\t\t_usbDPSRAM.EPxControl[ep].In.Set(val)\n\t\tepXPIDReset[ep] = true\n\n\tcase usb.ENDPOINT_TYPE_CONTROL:\n\t\tval |= usbEpControlEndpointTypeControl\n\t\t_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBuf0CtrlData1Pid)\n\t\t_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)\n\n\t}\n}\n\n// SendUSBInPacket sends a packet for USB (interrupt in / bulk in).\nfunc SendUSBInPacket(ep uint32, data []byte) bool {\n\tsendUSBPacket(ep, data, 0)\n\treturn true\n}\n\n// Prevent file size increases: https://github.com/tinygo-org/tinygo/pull/998\n//\n//go:noinline\nfunc sendUSBPacket(ep uint32, data []byte, maxsize uint16) {\n\tcount := len(data)\n\tif 0 < int(maxsize) && int(maxsize) < count {\n\t\tcount = int(maxsize)\n\t}\n\n\tif ep == 0 {\n\t\tif count > usb.EndpointPacketSize {\n\t\t\tcount = usb.EndpointPacketSize\n\n\t\t\tsendOnEP0DATADONE.offset = count\n\t\t\tsendOnEP0DATADONE.data = data\n\t\t} else {\n\t\t\tsendOnEP0DATADONE.offset = 0\n\t\t}\n\t\tepXdata0[ep] = true\n\t}\n\n\tsendViaEPIn(ep, data, count)\n}\n\nfunc ReceiveUSBControlPacket() ([cdcLineInfoSize]byte, error) {\n\tvar b [cdcLineInfoSize]byte\n\tep := 0\n\n\tfor !_usbDPSRAM.EPxBufferControl[ep].Out.HasBits(usbBuf0CtrlFull) {\n\t\t// TODO: timeout\n\t}\n\n\tctrl := _usbDPSRAM.EPxBufferControl[ep].Out.Get()\n\t_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)\n\tsz := ctrl & usbBuf0CtrlLenMask\n\n\tcopy(b[:], _usbDPSRAM.EPxBuffer[ep].Buffer0[:sz])\n\n\t_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlData1Pid)\n\t_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)\n\n\treturn b, nil\n}\n\nfunc handleEndpointRx(ep uint32) []byte {\n\tctrl := _usbDPSRAM.EPxBufferControl[ep].Out.Get()\n\t_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)\n\tsz := ctrl & usbBuf0CtrlLenMask\n\n\treturn _usbDPSRAM.EPxBuffer[ep].Buffer0[:sz]\n}\n\n// AckUsbOutTransfer is called to acknowledge the completion of a USB OUT transfer.\nfunc AckUsbOutTransfer(ep uint32) {\n\tep = ep & 0x7F\n\tsetEPDataPID(ep, !epXdata0[ep])\n}\n\n// Set the USB endpoint Packet ID to DATA0 or DATA1.\nfunc setEPDataPID(ep uint32, dataOne bool) {\n\tepXdata0[ep] = dataOne\n\tif epXdata0[ep] || ep == 0 {\n\t\t_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlData1Pid)\n\t}\n\n\t_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)\n}\n\nfunc SendZlp() {\n\tsendUSBPacket(0, []byte{}, 0)\n}\n\nfunc sendViaEPIn(ep uint32, data []byte, count int) {\n\t// Prepare buffer control register value\n\tval := uint32(count) | usbBuf0CtrlAvail\n\n\t// DATA0 or DATA1\n\tepXdata0[ep&0x7F] = !epXdata0[ep&0x7F]\n\tif !epXdata0[ep&0x7F] {\n\t\tval |= usbBuf0CtrlData1Pid\n\t}\n\n\t// Mark as full\n\tval |= usbBuf0CtrlFull\n\n\tcopy(_usbDPSRAM.EPxBuffer[ep&0x7F].Buffer0[:], data[:count])\n\t_usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val)\n}\n\n// Set ENDPOINT_HALT/stall status on a USB IN endpoint.\nfunc (dev *USBDevice) SetStallEPIn(ep uint32) {\n\tep = ep & 0x7F\n\t// Prepare buffer control register value\n\tif ep == 0 {\n\t\tarmEPZeroStall()\n\t}\n\tval := uint32(usbBuf0CtrlFull)\n\t_usbDPSRAM.EPxBufferControl[ep].In.Set(val)\n\tval |= uint32(usbBuf0CtrlStall)\n\t_usbDPSRAM.EPxBufferControl[ep].In.Set(val)\n}\n\n// Set ENDPOINT_HALT/stall status on a USB OUT endpoint.\nfunc (dev *USBDevice) SetStallEPOut(ep uint32) {\n\tep = ep & 0x7F\n\tif ep == 0 {\n\t\tpanic(\"SetStallEPOut: EP0 OUT not valid\")\n\t}\n\tval := uint32(usbBuf0CtrlStall)\n\t_usbDPSRAM.EPxBufferControl[ep].Out.Set(val)\n}\n\n// Clear the ENDPOINT_HALT/stall on a USB IN endpoint.\nfunc (dev *USBDevice) ClearStallEPIn(ep uint32) {\n\tep = ep & 0x7F\n\tval := uint32(usbBuf0CtrlStall)\n\t_usbDPSRAM.EPxBufferControl[ep].In.ClearBits(val)\n\tif epXPIDReset[ep] {\n\t\t// Reset the PID to DATA0\n\t\tsetEPDataPID(ep, false)\n\t}\n}\n\n// Clear the ENDPOINT_HALT/stall on a USB OUT endpoint.\nfunc (dev *USBDevice) ClearStallEPOut(ep uint32) {\n\tep = ep & 0x7F\n\tval := uint32(usbBuf0CtrlStall)\n\t_usbDPSRAM.EPxBufferControl[ep].Out.ClearBits(val)\n\tif epXPIDReset[ep] {\n\t\t// Reset the PID to DATA0\n\t\tsetEPDataPID(ep, false)\n\t}\n}\n\ntype usbDPSRAM struct {\n\t// Note that EPxControl[0] is not EP0Control but 8-byte setup data.\n\tEPxControl [16]usbEndpointControlRegister\n\n\tEPxBufferControl [16]usbBufferControlRegister\n\n\tEPxBuffer [16]usbBuffer\n}\n\ntype usbEndpointControlRegister struct {\n\tIn  volatile.Register32\n\tOut volatile.Register32\n}\ntype usbBufferControlRegister struct {\n\tIn  volatile.Register32\n\tOut volatile.Register32\n}\n\ntype usbBuffer struct {\n\tBuffer0 [usbBufferLen]byte\n\tBuffer1 [usbBufferLen]byte\n}\n\nvar (\n\t_usbDPSRAM  = (*usbDPSRAM)(unsafe.Pointer(uintptr(0x50100000)))\n\tepXdata0    [16]bool\n\tepXPIDReset [16]bool\n\tsetupBytes  [8]byte\n)\n\nfunc (d *usbDPSRAM) setupBytes() []byte {\n\n\tdata := d.EPxControl[usb.CONTROL_ENDPOINT].In.Get()\n\tsetupBytes[0] = byte(data)\n\tsetupBytes[1] = byte(data >> 8)\n\tsetupBytes[2] = byte(data >> 16)\n\tsetupBytes[3] = byte(data >> 24)\n\n\tdata = d.EPxControl[usb.CONTROL_ENDPOINT].Out.Get()\n\tsetupBytes[4] = byte(data)\n\tsetupBytes[5] = byte(data >> 8)\n\tsetupBytes[6] = byte(data >> 16)\n\tsetupBytes[7] = byte(data >> 24)\n\n\treturn setupBytes[:]\n}\n\nfunc (d *usbDPSRAM) clear() {\n\tfor i := 0; i < len(d.EPxControl); i++ {\n\t\td.EPxControl[i].In.Set(0)\n\t\td.EPxControl[i].Out.Set(0)\n\t\td.EPxBufferControl[i].In.Set(0)\n\t\td.EPxBufferControl[i].Out.Set(0)\n\t}\n}\n\nconst (\n\t// DPRAM : Endpoint control register\n\tusbEpControlEnable                 = 0x80000000\n\tusbEpControlDoubleBuffered         = 0x40000000\n\tusbEpControlInterruptPerBuff       = 0x20000000\n\tusbEpControlInterruptPerDoubleBuff = 0x10000000\n\tusbEpControlEndpointType           = 0x0c000000\n\tusbEpControlInterruptOnStall       = 0x00020000\n\tusbEpControlInterruptOnNak         = 0x00010000\n\tusbEpControlBufferAddress          = 0x0000ffff\n\n\tusbEpControlEndpointTypeControl   = 0x00000000\n\tusbEpControlEndpointTypeISO       = 0x04000000\n\tusbEpControlEndpointTypeBulk      = 0x08000000\n\tusbEpControlEndpointTypeInterrupt = 0x0c000000\n\n\t// Endpoint buffer control bits\n\tusbBuf1CtrlFull     = 0x80000000\n\tusbBuf1CtrlLast     = 0x40000000\n\tusbBuf1CtrlData0Pid = 0x20000000\n\tusbBuf1CtrlData1Pid = 0x00000000\n\tusbBuf1CtrlSel      = 0x10000000\n\tusbBuf1CtrlStall    = 0x08000000\n\tusbBuf1CtrlAvail    = 0x04000000\n\tusbBuf1CtrlLenMask  = 0x03FF0000\n\tusbBuf0CtrlFull     = 0x00008000\n\tusbBuf0CtrlLast     = 0x00004000\n\tusbBuf0CtrlData0Pid = 0x00000000\n\tusbBuf0CtrlData1Pid = 0x00002000\n\tusbBuf0CtrlSel      = 0x00001000\n\tusbBuf0CtrlStall    = 0x00000800\n\tusbBuf0CtrlAvail    = 0x00000400\n\tusbBuf0CtrlLenMask  = 0x000003FF\n\n\tusbBufferLen = 64\n)\n"
  },
  {
    "path": "src/machine/machine_rp2_watchdog.go",
    "content": "//go:build rp2040 || rp2350\n\npackage machine\n\nimport (\n\t\"device/rp\"\n)\n\n// Watchdog provides access to the hardware watchdog available\n// in the RP2040.\nvar Watchdog = &watchdogImpl{}\n\nconst (\n\t// WatchdogMaxTimeout in milliseconds (approx 8.3s).\n\t//\n\t// Nominal 1us per watchdog tick, 24-bit counter,\n\t// but due to errata two ticks consumed per 1us.\n\t// See: Errata RP2040-E1\n\tWatchdogMaxTimeout = (rp.WATCHDOG_LOAD_LOAD_Msk / 1000) / 2\n)\n\ntype watchdogImpl struct {\n\t// The value to reset the counter to on each Update\n\tloadValue uint32\n}\n\n// Configure the watchdog.\n//\n// This method should not be called after the watchdog is started and on\n// some platforms attempting to reconfigure after starting the watchdog\n// is explicitly forbidden / will not work.\nfunc (wd *watchdogImpl) Configure(config WatchdogConfig) error {\n\t// x2 due to errata RP2040-E1\n\twd.loadValue = config.TimeoutMillis * 1000 * 2\n\tif wd.loadValue > rp.WATCHDOG_LOAD_LOAD_Msk {\n\t\twd.loadValue = rp.WATCHDOG_LOAD_LOAD_Msk\n\t}\n\n\trp.WATCHDOG.CTRL.ClearBits(rp.WATCHDOG_CTRL_ENABLE)\n\n\t// Reset everything apart from ROSC and XOSC\n\trp.PSM.WDSEL.Set(0x0001ffff &^ (rp.PSM_WDSEL_ROSC | rp.PSM_WDSEL_XOSC))\n\n\t// Pause watchdog during debug\n\trp.WATCHDOG.CTRL.SetBits(rp.WATCHDOG_CTRL_PAUSE_DBG0 | rp.WATCHDOG_CTRL_PAUSE_DBG1 | rp.WATCHDOG_CTRL_PAUSE_JTAG)\n\n\t// Load initial counter\n\trp.WATCHDOG.LOAD.Set(wd.loadValue)\n\n\treturn nil\n}\n\n// Starts the watchdog.\nfunc (wd *watchdogImpl) Start() error {\n\trp.WATCHDOG.CTRL.SetBits(rp.WATCHDOG_CTRL_ENABLE)\n\treturn nil\n}\n\n// Update the watchdog, indicating that the app is healthy.\nfunc (wd *watchdogImpl) Update() {\n\trp.WATCHDOG.LOAD.Set(wd.loadValue)\n}\n"
  },
  {
    "path": "src/machine/machine_rp2_xosc.go",
    "content": "//go:build rp2040 || rp2350\n\npackage machine\n\nimport (\n\t\"device/rp\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\n// On some boards, the XOSC can take longer than usual to stabilize. On such\n// boards, this is needed to avoid a hard fault on boot/reset. Refer to\n// PICO_XOSC_STARTUP_DELAY_MULTIPLIER in the Pico SDK for additional details.\nconst XOSC_STARTUP_DELAY_MULTIPLIER = 64\n\ntype xoscType struct {\n\tctrl     volatile.Register32\n\tstatus   volatile.Register32\n\tdormant  volatile.Register32\n\tstartup  volatile.Register32\n\treserved [3 - 3*rp2350ExtraReg]volatile.Register32\n\tcount    volatile.Register32\n}\n\nvar xosc = (*xoscType)(unsafe.Pointer(rp.XOSC))\n\n// init initializes the crystal oscillator system.\n//\n// This function will block until the crystal oscillator has stabilised.\nfunc (osc *xoscType) init() {\n\t// Assumes 1-15 MHz input\n\tif xoscFreq > 15 {\n\t\tpanic(\"xosc frequency cannot be greater than 15MHz\")\n\t}\n\tosc.ctrl.Set(rp.XOSC_CTRL_FREQ_RANGE_1_15MHZ)\n\n\t// Set xosc startup delay\n\tdelay := (((xoscFreq * MHz) / 1000) + 128) / 256 * XOSC_STARTUP_DELAY_MULTIPLIER\n\tosc.startup.Set(uint32(delay))\n\n\t// Set the enable bit now that we have set freq range and startup delay\n\tosc.ctrl.SetBits(rp.XOSC_CTRL_ENABLE_ENABLE << rp.XOSC_CTRL_ENABLE_Pos)\n\n\t// Wait for xosc to be stable\n\tfor !osc.status.HasBits(rp.XOSC_STATUS_STABLE) {\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_stm32.go",
    "content": "//go:build stm32\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nconst deviceName = stm32.Device\n\n// Peripheral abstraction layer for the stm32.\n\nconst (\n\tportA Pin = iota * 16\n\tportB\n\tportC\n\tportD\n\tportE\n\tportF\n\tportG\n\tportH\n\tportI\n\tportJ\n\tportK\n)\n\n// Peripheral operations sequence:\n//  1. Enable the clock to the alternate function.\n//  2. Enable clock to corresponding GPIO\n//  3. Attach the alternate function.\n//  4. Configure the input-output port and pins (of the corresponding GPIOx) to match the AF .\n//  5. If desired enable the nested vector interrupt control to generate interrupts.\n//  6. Program the AF/peripheral for the required configuration (eg baud rate for a USART) .\n\n// Given that the stm32 family has the AF and GPIO on different registers based on the chip,\n//  use the main function here for configuring, and use hooks in the more specific chip\n//  definition files\n// Also, the stm32f1xx series handles things differently from the stm32f0/2/3/4\n\n// ---------- General pin operations ----------\ntype PinChange uint8\n\nconst (\n\tPinRising PinChange = 1 << iota\n\tPinFalling\n\tPinToggle = PinRising | PinFalling\n)\n\n// Set the pin to high or low.\n// Warning: only use this on an output pin!\nfunc (p Pin) Set(high bool) {\n\tport := p.getPort()\n\tpin := uint8(p) % 16\n\tif high {\n\t\tport.BSRR.Set(1 << pin)\n\t} else {\n\t\tport.BSRR.Set(1 << (pin + 16))\n\t}\n}\n\n// Get returns the current value of a GPIO pin when the pin is configured as an\n// input or as an output.\nfunc (p Pin) Get() bool {\n\tport := p.getPort()\n\tpin := uint8(p) % 16\n\tval := port.IDR.Get() & (1 << pin)\n\treturn (val > 0)\n}\n\n// PortMaskSet returns the register and mask to enable a given GPIO pin. This\n// can be used to implement bit-banged drivers.\nfunc (p Pin) PortMaskSet() (*uint32, uint32) {\n\tport := p.getPort()\n\tpin := uint8(p) % 16\n\treturn &port.BSRR.Reg, 1 << pin\n}\n\n// PortMaskClear returns the register and mask to disable a given port. This can\n// be used to implement bit-banged drivers.\nfunc (p Pin) PortMaskClear() (*uint32, uint32) {\n\tport := p.getPort()\n\tpin := uint8(p) % 16\n\treturn &port.BSRR.Reg, 1 << (pin + 16)\n}\n\nvar deviceID [12]byte\n\n// DeviceID returns an identifier that is unique within\n// a particular chipset.\n//\n// The identity is one burnt into the MCU itself.\n//\n// The length of the device ID for STM32 is 12 bytes (96 bits).\nfunc DeviceID() []byte {\n\tfor i := 0; i < len(deviceID); i++ {\n\t\tword := (*volatile.Register32)(unsafe.Pointer(deviceIDAddr[i/4])).Get()\n\t\tdeviceID[i] = byte(word >> ((i % 4) * 8))\n\t}\n\n\treturn deviceID[:]\n}\n"
  },
  {
    "path": "src/machine/machine_stm32_adc_f1.go",
    "content": "//go:build stm32f103\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n\t\"unsafe\"\n)\n\nconst (\n\tCycles_1_5   = 0x0\n\tCycles_7_5   = 0x1\n\tCycles_13_5  = 0x2\n\tCycles_28_5  = 0x3\n\tCycles_41_5  = 0x4\n\tCycles_55_5  = 0x5\n\tCycles_71_5  = 0x6\n\tCycles_239_5 = 0x7\n)\n\n// InitADC initializes the registers needed for ADC1.\nfunc InitADC() {\n\t// Enable ADC clock\n\tenableAltFuncClock(unsafe.Pointer(stm32.ADC1))\n\n\t// enable\n\tstm32.ADC1.CR2.SetBits(stm32.ADC_CR2_ADON | stm32.ADC_CR2_ALIGN)\n\n\treturn\n}\n\n// Configure configures an ADC pin to be able to read analog data.\nfunc (a ADC) Configure(ADCConfig) {\n\ta.Pin.Configure(PinConfig{Mode: PinInputModeAnalog})\n\n\t// set sample time\n\tch := a.getChannel()\n\tif ch > 9 {\n\t\tstm32.ADC1.SMPR1.SetBits(Cycles_28_5 << (ch - 10) * stm32.ADC_SMPR1_SMP11_Pos)\n\t} else {\n\t\tstm32.ADC1.SMPR2.SetBits(Cycles_28_5 << (ch * stm32.ADC_SMPR2_SMP1_Pos))\n\t}\n\n\treturn\n}\n\n// Get returns the current value of a ADC pin in the range 0..0xffff.\n// TODO: DMA based implementation.\nfunc (a ADC) Get() uint16 {\n\t// set rank\n\tch := uint32(a.getChannel())\n\tstm32.ADC1.SetSQR3_SQ1(ch)\n\n\t// start conversion\n\tstm32.ADC1.CR2.SetBits(stm32.ADC_CR2_ADON)\n\n\t// wait for conversion to complete\n\tfor !stm32.ADC1.SR.HasBits(stm32.ADC_SR_EOC) {\n\t}\n\n\t// read result as 16 bit value\n\treturn uint16(stm32.ADC1.DR.Get())\n}\n\nfunc (a ADC) getChannel() uint8 {\n\tswitch a.Pin {\n\tcase PA0:\n\t\treturn 0\n\tcase PA1:\n\t\treturn 1\n\tcase PA2:\n\t\treturn 2\n\tcase PA3:\n\t\treturn 3\n\tcase PA4:\n\t\treturn 4\n\tcase PA5:\n\t\treturn 5\n\tcase PA6:\n\t\treturn 6\n\tcase PA7:\n\t\treturn 7\n\tcase PB0:\n\t\treturn 8\n\tcase PB1:\n\t\treturn 9\n\t}\n\n\treturn 0\n}\n"
  },
  {
    "path": "src/machine/machine_stm32_adc_f4.go",
    "content": "//go:build stm32f4\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n\t\"unsafe\"\n)\n\n// InitADC initializes the registers needed for ADC1.\nfunc InitADC() {\n\t// Enable ADC clock\n\tenableAltFuncClock(unsafe.Pointer(stm32.ADC1))\n\n\t// stop scan, and clear scan resolution\n\tstm32.ADC1.CR1.ClearBits(stm32.ADC_CR1_SCAN | stm32.ADC_CR1_RES_Msk)\n\n\t// set conversion mode and resolution\n\tstm32.ADC1.CR1.SetBits(stm32.ADC_CR1_RES_TwelveBit)\n\n\t// clear CONT, ALIGN, EXTEN and EXTSEL bits from CR2\n\tstm32.ADC1.CR2.ClearBits(stm32.ADC_CR2_CONT | stm32.ADC_CR2_ALIGN | stm32.ADC_CR2_EXTEN_Msk | stm32.ADC_CR2_EXTSEL_Msk)\n\n\t// set CONT, ALIGN, EXTEN and EXTSEL bits from CR2\n\tstm32.ADC1.CR2.SetBits(stm32.ADC_CR2_CONT_Single | stm32.ADC_CR2_ALIGN_Right)\n\n\tstm32.ADC1.SQR1.ClearBits(stm32.ADC_SQR1_L_Msk)\n\tstm32.ADC1.SQR1.SetBits(2 << stm32.ADC_SQR1_L_Pos) // 2 means 3 conversions\n\n\t// enable\n\tstm32.ADC1.CR2.SetBits(stm32.ADC_CR2_ADON)\n\n\treturn\n}\n\n// Configure configures an ADC pin to be able to read analog data.\nfunc (a ADC) Configure(ADCConfig) {\n\ta.Pin.ConfigureAltFunc(PinConfig{Mode: PinInputAnalog}, 0)\n\n\t// set sample time\n\tch := a.getChannel()\n\tif ch > 9 {\n\t\tstm32.ADC1.SMPR1.SetBits(stm32.ADC_SMPR1_SMP11_Cycles84 << (ch - 10) * stm32.ADC_SMPR1_SMP11_Pos)\n\t} else {\n\t\tstm32.ADC1.SMPR2.SetBits(stm32.ADC_SMPR2_SMP1_Cycles84 << (ch * stm32.ADC_SMPR2_SMP1_Pos))\n\t}\n\n\treturn\n}\n\n// Get returns the current value of a ADC pin in the range 0..0xffff.\n// TODO: DMA based implementation.\nfunc (a ADC) Get() uint16 {\n\t// set rank\n\tch := uint32(a.getChannel())\n\tstm32.ADC1.SQR3.SetBits(ch)\n\n\t// start conversion\n\tstm32.ADC1.CR2.SetBits(stm32.ADC_CR2_SWSTART)\n\n\t// wait for conversion to complete\n\tfor !stm32.ADC1.SR.HasBits(stm32.ADC_SR_EOC) {\n\t}\n\n\t// read 12-bit result as 16 bit value\n\tresult := uint16(stm32.ADC1.DR.Get()) << 4\n\n\t// clear flag\n\tstm32.ADC1.SR.ClearBits(stm32.ADC_SR_EOC)\n\n\t// clear rank\n\tstm32.ADC1.SQR3.ClearBits(ch)\n\n\treturn result\n}\n\nfunc (a ADC) getChannel() uint8 {\n\tswitch a.Pin {\n\tcase PA0:\n\t\treturn 0\n\tcase PA1:\n\t\treturn 1\n\tcase PA2:\n\t\treturn 2\n\tcase PA3:\n\t\treturn 3\n\tcase PA4:\n\t\treturn 4\n\tcase PA5:\n\t\treturn 5\n\tcase PA6:\n\t\treturn 6\n\tcase PA7:\n\t\treturn 7\n\tcase PB0:\n\t\treturn 8\n\tcase PB1:\n\t\treturn 9\n\tcase PC0:\n\t\treturn 10\n\tcase PC1:\n\t\treturn 11\n\tcase PC2:\n\t\treturn 12\n\tcase PC3:\n\t\treturn 13\n\tcase PC4:\n\t\treturn 14\n\tcase PC5:\n\t\treturn 15\n\t}\n\n\treturn 0\n}\n"
  },
  {
    "path": "src/machine/machine_stm32_exti_afio.go",
    "content": "//go:build stm32f1\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/volatile\"\n)\n\nfunc getEXTIConfigRegister(pin uint8) *volatile.Register32 {\n\tswitch (pin & 0xf) / 4 {\n\tcase 0:\n\t\treturn &stm32.AFIO.EXTICR1\n\tcase 1:\n\t\treturn &stm32.AFIO.EXTICR2\n\tcase 2:\n\t\treturn &stm32.AFIO.EXTICR3\n\tcase 3:\n\t\treturn &stm32.AFIO.EXTICR4\n\t}\n\treturn nil\n}\n\nfunc enableEXTIConfigRegisters() {\n\t// Enable AFIO\n\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_AFIOEN)\n}\n"
  },
  {
    "path": "src/machine/machine_stm32_exti_exti.go",
    "content": "//go:build stm32l5\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/volatile\"\n)\n\nfunc getEXTIConfigRegister(pin uint8) *volatile.Register32 {\n\tswitch (pin & 0xf) / 4 {\n\tcase 0:\n\t\treturn &stm32.EXTI.EXTICR1\n\tcase 1:\n\t\treturn &stm32.EXTI.EXTICR2\n\tcase 2:\n\t\treturn &stm32.EXTI.EXTICR3\n\tcase 3:\n\t\treturn &stm32.EXTI.EXTICR4\n\t}\n\treturn nil\n}\n\nfunc enableEXTIConfigRegisters() {\n\t// No-op\n}\n"
  },
  {
    "path": "src/machine/machine_stm32_exti_syscfg.go",
    "content": "//go:build stm32 && !stm32f1 && !stm32l5 && !stm32wlx\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/volatile\"\n)\n\nfunc getEXTIConfigRegister(pin uint8) *volatile.Register32 {\n\tswitch (pin & 0xf) / 4 {\n\tcase 0:\n\t\treturn &stm32.SYSCFG.EXTICR1\n\tcase 1:\n\t\treturn &stm32.SYSCFG.EXTICR2\n\tcase 2:\n\t\treturn &stm32.SYSCFG.EXTICR3\n\tcase 3:\n\t\treturn &stm32.SYSCFG.EXTICR4\n\t}\n\treturn nil\n}\n\nfunc enableEXTIConfigRegisters() {\n\t// Enable SYSCFG\n\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SYSCFGEN)\n}\n"
  },
  {
    "path": "src/machine/machine_stm32_exti_syscfg_noenable.go",
    "content": "//go:build stm32wlx\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/volatile\"\n)\n\nfunc getEXTIConfigRegister(pin uint8) *volatile.Register32 {\n\tswitch (pin & 0xf) / 4 {\n\tcase 0:\n\t\treturn &stm32.SYSCFG.EXTICR1\n\tcase 1:\n\t\treturn &stm32.SYSCFG.EXTICR2\n\tcase 2:\n\t\treturn &stm32.SYSCFG.EXTICR3\n\tcase 3:\n\t\treturn &stm32.SYSCFG.EXTICR4\n\t}\n\treturn nil\n}\n\nfunc enableEXTIConfigRegisters() {\n\t// No registers to enable\n}\n"
  },
  {
    "path": "src/machine/machine_stm32_flash.go",
    "content": "//go:build stm32f4 || stm32l4 || stm32wlx\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n\n\t\"unsafe\"\n)\n\n// compile-time check for ensuring we fulfill BlockDevice interface\nvar _ BlockDevice = flashBlockDevice{}\n\nvar Flash flashBlockDevice\n\ntype flashBlockDevice struct {\n}\n\n// ReadAt reads the given number of bytes from the block device.\nfunc (f flashBlockDevice) ReadAt(p []byte, off int64) (n int, err error) {\n\tif FlashDataStart()+uintptr(off)+uintptr(len(p)) > FlashDataEnd() {\n\t\treturn 0, errFlashCannotReadPastEOF\n\t}\n\n\tdata := unsafe.Slice((*byte)(unsafe.Pointer(FlashDataStart()+uintptr(off))), len(p))\n\tcopy(p, data)\n\n\treturn len(p), nil\n}\n\n// WriteAt writes the given number of bytes to the block device.\n// Only double-word (64 bits) length data can be programmed. See rm0461 page 78.\n// If the length of p is not long enough it will be padded with 0xFF bytes.\n// This method assumes that the destination is already erased.\nfunc (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) {\n\tif FlashDataStart()+uintptr(off)+uintptr(len(p)) > FlashDataEnd() {\n\t\treturn 0, errFlashCannotWritePastEOF\n\t}\n\n\tunlockFlash()\n\tdefer lockFlash()\n\n\tp = flashPad(p, int(f.WriteBlockSize()))\n\treturn writeFlashData(FlashDataStart()+uintptr(off), p)\n}\n\n// Size returns the number of bytes in this block device.\nfunc (f flashBlockDevice) Size() int64 {\n\treturn int64(FlashDataEnd() - FlashDataStart())\n}\n\n// WriteBlockSize returns the block size in which data can be written to\n// memory. It can be used by a client to optimize writes, non-aligned writes\n// should always work correctly.\nfunc (f flashBlockDevice) WriteBlockSize() int64 {\n\treturn writeBlockSize\n}\n\nfunc eraseBlockSize() int64 {\n\treturn eraseBlockSizeValue\n}\n\n// EraseBlockSize returns the smallest erasable area on this particular chip\n// in bytes. This is used for the block size in EraseBlocks.\n// It must be a power of two, and may be as small as 1. A typical size is 4096.\n// TODO: correctly handle processors that have differently sized blocks\n// in different areas of memory like the STM32F40x and STM32F1x.\nfunc (f flashBlockDevice) EraseBlockSize() int64 {\n\treturn eraseBlockSize()\n}\n\n// EraseBlocks erases the given number of blocks. An implementation may\n// transparently coalesce ranges of blocks into larger bundles if the chip\n// supports this. The start and len parameters are in block numbers, use\n// EraseBlockSize to map addresses to blocks.\n// Note that block 0 should map to the address of FlashDataStart().\nfunc (f flashBlockDevice) EraseBlocks(start, len int64) error {\n\tvar address uintptr = uintptr(start*f.EraseBlockSize()) + FlashDataStart()\n\tblk := int64(address-uintptr(memoryStart)) / f.EraseBlockSize()\n\n\tunlockFlash()\n\tdefer lockFlash()\n\n\tfor i := blk; i < blk+len; i++ {\n\t\tif err := eraseBlock(uint32(i)); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\nconst memoryStart = 0x08000000\n\nfunc unlockFlash() {\n\t// keys as described rm0461 page 76\n\tvar fkey1 uint32 = 0x45670123\n\tvar fkey2 uint32 = 0xCDEF89AB\n\n\t// Wait for the flash memory not to be busy\n\tfor stm32.FLASH.GetSR_BSY() != 0 {\n\t}\n\n\t// Check if the controller is unlocked already\n\tif stm32.FLASH.GetCR_LOCK() != 0 {\n\t\t// Write the first key\n\t\tstm32.FLASH.SetKEYR(fkey1)\n\t\t// Write the second key\n\t\tstm32.FLASH.SetKEYR(fkey2)\n\t}\n}\n\nfunc lockFlash() {\n\tstm32.FLASH.SetCR_LOCK(1)\n}\n"
  },
  {
    "path": "src/machine/machine_stm32_gpio_reva.go",
    "content": "//go:build stm32 && !stm32l4 && !stm32l5 && !stm32wlx\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n)\n\n// This variant of the GPIO input interrupt logic is for\n// chips with a smaller number of interrupt channels\n// (that fits in a single register).\n\n//\n// STM32 allows one interrupt source per pin number, with\n// the same pin number in different ports sharing a single\n// interrupt source (so PA0, PB0, PC0 all share).  Only a\n// single physical pin can be connected to each interrupt\n// line.\n//\n// To call interrupt callbacks, we record here for each\n// pin number the callback and the actual associated pin.\n//\n\n// Callbacks for pin interrupt events\nvar pinCallbacks [16]func(Pin)\n\n// The pin currently associated with interrupt callback\n// for a given slot.\nvar interruptPins [16]Pin\n\n// SetInterrupt sets an interrupt to be executed when a particular pin changes\n// state. The pin should already be configured as an input, including a pull up\n// or down if no external pull is provided.\n//\n// This call will replace a previously set callback on this pin. You can pass a\n// nil func to unset the pin change interrupt. If you do so, the change\n// parameter is ignored and can be set to any value (such as 0).\nfunc (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error {\n\tport := uint32(uint8(p) / 16)\n\tpin := uint8(p) % 16\n\n\tenableEXTIConfigRegisters()\n\n\tif callback == nil {\n\t\tstm32.EXTI.IMR.ClearBits(1 << pin)\n\t\tpinCallbacks[pin] = nil\n\t\treturn nil\n\t}\n\n\tif pinCallbacks[pin] != nil {\n\t\t// The pin was already configured.\n\t\t// To properly re-configure a pin, unset it first and set a new\n\t\t// configuration.\n\t\treturn ErrNoPinChangeChannel\n\t}\n\n\t// Set the callback now (before the interrupt is enabled) to avoid\n\t// possible race condition\n\tpinCallbacks[pin] = callback\n\tinterruptPins[pin] = p\n\n\tcrReg := getEXTIConfigRegister(pin)\n\tshift := (pin & 0x3) * 4\n\tcrReg.ReplaceBits(port, 0xf, shift)\n\n\tif (change & PinRising) != 0 {\n\t\tstm32.EXTI.RTSR.SetBits(1 << pin)\n\t}\n\tif (change & PinFalling) != 0 {\n\t\tstm32.EXTI.FTSR.SetBits(1 << pin)\n\t}\n\tstm32.EXTI.IMR.SetBits(1 << pin)\n\n\tintr := p.registerInterrupt()\n\tintr.SetPriority(0)\n\tintr.Enable()\n\n\treturn nil\n}\n\nfunc handlePinInterrupt(pin uint8) {\n\tif stm32.EXTI.PR.HasBits(1 << pin) {\n\t\t// Writing 1 to the pending register clears the\n\t\t// pending flag for that bit\n\t\tstm32.EXTI.PR.Set(1 << pin)\n\n\t\tcallback := pinCallbacks[pin]\n\t\tif callback != nil {\n\t\t\tcallback(interruptPins[pin])\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_stm32_gpio_revb.go",
    "content": "//go:build stm32l4 || stm32l5\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n)\n\n// This variant of the GPIO input interrupt logic is for\n// chips with a larger number of interrupt channels (more\n// than fits in a single register).\n\n//\n// STM32 allows one interrupt source per pin number, with\n// the same pin number in different ports sharing a single\n// interrupt source (so PA0, PB0, PC0 all share).  Only a\n// single physical pin can be connected to each interrupt\n// line.\n//\n// To call interrupt callbacks, we record here for each\n// pin number the callback and the actual associated pin.\n//\n\n// Callbacks for pin interrupt events\nvar pinCallbacks [16]func(Pin)\n\n// The pin currently associated with interrupt callback\n// for a given slot.\nvar interruptPins [16]Pin\n\n// SetInterrupt sets an interrupt to be executed when a particular pin changes\n// state. The pin should already be configured as an input, including a pull up\n// or down if no external pull is provided.\n//\n// This call will replace a previously set callback on this pin. You can pass a\n// nil func to unset the pin change interrupt. If you do so, the change\n// parameter is ignored and can be set to any value (such as 0).\nfunc (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error {\n\tport := uint32(uint8(p) / 16)\n\tpin := uint8(p) % 16\n\n\tenableEXTIConfigRegisters()\n\n\tif callback == nil {\n\t\tstm32.EXTI.IMR1.ClearBits(1 << pin)\n\t\tpinCallbacks[pin] = nil\n\t\treturn nil\n\t}\n\n\tif pinCallbacks[pin] != nil {\n\t\t// The pin was already configured.\n\t\t// To properly re-configure a pin, unset it first and set a new\n\t\t// configuration.\n\t\treturn ErrNoPinChangeChannel\n\t}\n\n\t// Set the callback now (before the interrupt is enabled) to avoid\n\t// possible race condition\n\tpinCallbacks[pin] = callback\n\tinterruptPins[pin] = p\n\n\tcrReg := getEXTIConfigRegister(pin)\n\tshift := (pin & 0x3) * 4\n\tcrReg.ReplaceBits(port, 0xf, shift)\n\n\tif (change & PinRising) != 0 {\n\t\tstm32.EXTI.RTSR1.SetBits(1 << pin)\n\t}\n\tif (change & PinFalling) != 0 {\n\t\tstm32.EXTI.FTSR1.SetBits(1 << pin)\n\t}\n\tstm32.EXTI.IMR1.SetBits(1 << pin)\n\n\tintr := p.registerInterrupt()\n\tintr.SetPriority(0)\n\tintr.Enable()\n\n\treturn nil\n}\n"
  },
  {
    "path": "src/machine/machine_stm32_gpio_revb_mp.go",
    "content": "//go:build stm32wlx\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n)\n\n//\n// This variant of the GPIO input interrupt logic is for\n// multi-core chips with a larger number of interrupt\n// channels (more than fits in a single register).\n//\n// This logic is currently used by the single-core stm32wle5\n// due to a patch in stm32-rs project that has renamed the\n// registers to match the dual-core names.  This renaming is\n// being discussed and may change in future.\n//\n\n//\n// STM32 allows one interrupt source per pin number, with\n// the same pin number in different ports sharing a single\n// interrupt source (so PA0, PB0, PC0 all share).  Only a\n// single physical pin can be connected to each interrupt\n// line.\n//\n// To call interrupt callbacks, we record here for each\n// pin number the callback and the actual associated pin.\n//\n\n// Callbacks for pin interrupt events\nvar pinCallbacks [16]func(Pin)\n\n// The pin currently associated with interrupt callback\n// for a given slot.\nvar interruptPins [16]Pin\n\n// SetInterrupt sets an interrupt to be executed when a particular pin changes\n// state. The pin should already be configured as an input, including a pull up\n// or down if no external pull is provided.\n//\n// This call will replace a previously set callback on this pin. You can pass a\n// nil func to unset the pin change interrupt. If you do so, the change\n// parameter is ignored and can be set to any value (such as 0).\nfunc (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error {\n\tport := uint32(uint8(p) / 16)\n\tpin := uint8(p) % 16\n\n\tenableEXTIConfigRegisters()\n\n\tif callback == nil {\n\t\tstm32.EXTI.C1IMR1.ClearBits(1 << pin)\n\t\tpinCallbacks[pin] = nil\n\t\treturn nil\n\t}\n\n\tif pinCallbacks[pin] != nil {\n\t\t// The pin was already configured.\n\t\t// To properly re-configure a pin, unset it first and set a new\n\t\t// configuration.\n\t\treturn ErrNoPinChangeChannel\n\t}\n\n\t// Set the callback now (before the interrupt is enabled) to avoid\n\t// possible race condition\n\tpinCallbacks[pin] = callback\n\tinterruptPins[pin] = p\n\n\tcrReg := getEXTIConfigRegister(pin)\n\tshift := (pin & 0x3) * 4\n\tcrReg.ReplaceBits(port, 0xf, shift)\n\n\tif (change & PinRising) != 0 {\n\t\tstm32.EXTI.RTSR1.SetBits(1 << pin)\n\t}\n\tif (change & PinFalling) != 0 {\n\t\tstm32.EXTI.FTSR1.SetBits(1 << pin)\n\t}\n\tstm32.EXTI.C1IMR1.SetBits(1 << pin)\n\n\tintr := p.registerInterrupt()\n\tintr.SetPriority(0)\n\tintr.Enable()\n\n\treturn nil\n}\n"
  },
  {
    "path": "src/machine/machine_stm32_i2c_reva.go",
    "content": "//go:build stm32f4 || stm32f1\n\npackage machine\n\n// I2C implementation for 'older' STM32 MCUs, including the F1 and F4 series\n// of MCUs.\n\nimport (\n\t\"device/stm32\"\n\t\"unsafe\"\n)\n\nconst (\n\tflagOVR     = 0x00010800\n\tflagAF      = 0x00010400\n\tflagARLO    = 0x00010200\n\tflagBERR    = 0x00010100\n\tflagTXE     = 0x00010080\n\tflagRXNE    = 0x00010040\n\tflagSTOPF   = 0x00010010\n\tflagADD10   = 0x00010008\n\tflagBTF     = 0x00010004\n\tflagADDR    = 0x00010002\n\tflagSB      = 0x00010001\n\tflagDUALF   = 0x00100080\n\tflagGENCALL = 0x00100010\n\tflagTRA     = 0x00100004\n\tflagBUSY    = 0x00100002\n\tflagMSL     = 0x00100001\n)\n\nfunc (i2c *I2C) hasFlag(flag uint32) bool {\n\tconst mask = 0x0000FFFF\n\tif uint8(flag>>16) == 1 {\n\t\treturn i2c.Bus.SR1.HasBits(flag & mask)\n\t} else {\n\t\treturn i2c.Bus.SR2.HasBits(flag & mask)\n\t}\n}\n\nfunc (i2c *I2C) clearFlag(flag uint32) {\n\tconst mask = 0x0000FFFF\n\ti2c.Bus.SR1.Set(^(flag & mask))\n}\n\n// clearFlagADDR reads both status registers to clear any pending ADDR flags.\nfunc (i2c *I2C) clearFlagADDR() {\n\ti2c.Bus.SR1.Get()\n\ti2c.Bus.SR2.Get()\n}\n\nfunc (i2c *I2C) waitForFlag(flag uint32, set bool) bool {\n\tconst tryMax = 10000\n\thasFlag := false\n\tfor i := 0; !hasFlag && i < tryMax; i++ {\n\t\thasFlag = i2c.hasFlag(flag) == set\n\t}\n\treturn hasFlag\n}\n\nfunc (i2c *I2C) waitForFlagOrError(flag uint32, set bool) bool {\n\tconst tryMax = 10000\n\thasFlag := false\n\tfor i := 0; !hasFlag && i < tryMax; i++ {\n\t\tif hasFlag = i2c.hasFlag(flag) == set; !hasFlag {\n\t\t\t// check for ACK failure\n\t\t\tif i2c.hasFlag(flagAF) {\n\t\t\t\t// generate stop condition\n\t\t\t\ti2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)\n\t\t\t\t// clear pending flags\n\t\t\t\ti2c.clearFlag(flagAF)\n\t\t\t\treturn false\n\t\t\t} else if i2c.hasFlag(flagSTOPF) {\n\t\t\t\t// clear stop flag\n\t\t\t\ti2c.clearFlag(flagSTOPF)\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t}\n\treturn hasFlag\n}\n\ntype transferOption uint32\n\nconst (\n\tframeFirst        = 0x00000001\n\tframeFirstAndNext = 0x00000002\n\tframeNext         = 0x00000004\n\tframeFirstAndLast = 0x00000008\n\tframeLastNoStop   = 0x00000010\n\tframeLast         = 0x00000020\n\tframeNoOption     = 0xFFFF0000\n)\n\n// I2C fast mode (Fm) duty cycle\nconst (\n\tDutyCycle2    = 0\n\tDutyCycle16x9 = 1\n)\n\n// I2CConfig is used to store config info for I2C.\ntype I2CConfig struct {\n\tFrequency uint32\n\tSCL       Pin\n\tSDA       Pin\n\tDutyCycle uint8\n}\n\n// Configure is intended to setup the STM32 I2C interface.\nfunc (i2c *I2C) Configure(config I2CConfig) error {\n\n\t// The following is the required sequence in controller mode.\n\t// 1. Program the peripheral input clock in I2C_CR2 Register in order to\n\t//    generate correct timings\n\t// 2. Configure the clock control registers\n\t// 3. Configure the rise time register\n\t// 4. Program the I2C_CR1 register to enable the peripheral\n\t// 5. Set the START bit in the I2C_CR1 register to generate a Start condition\n\n\t// disable I2C interface before any configuration changes\n\ti2c.Bus.CR1.ClearBits(stm32.I2C_CR1_PE)\n\n\t// reset I2C bus\n\ti2c.Bus.CR1.SetBits(stm32.I2C_CR1_SWRST)\n\ti2c.Bus.CR1.ClearBits(stm32.I2C_CR1_SWRST)\n\n\t// enable clock for I2C\n\tenableAltFuncClock(unsafe.Pointer(i2c.Bus))\n\n\t// init pins\n\tif config.SCL == 0 && config.SDA == 0 {\n\t\tconfig.SCL = I2C0_SCL_PIN\n\t\tconfig.SDA = I2C0_SDA_PIN\n\t}\n\ti2c.configurePins(config)\n\n\t// default to 100 kHz (Sm, standard mode) if no frequency is set\n\tif config.Frequency == 0 {\n\t\tconfig.Frequency = 100 * KHz\n\t}\n\n\t// configure I2C input clock\n\ti2c.Bus.CR2.SetBits(i2c.getFreqRange(config))\n\n\t// configure rise time\n\ti2c.Bus.TRISE.Set(i2c.getRiseTime(config))\n\n\t// configure clock control\n\ti2c.Bus.CCR.Set(i2c.getSpeed(config))\n\n\t// disable GeneralCall and NoStretch modes\n\ti2c.Bus.CR1.ClearBits(stm32.I2C_CR1_ENGC | stm32.I2C_CR1_NOSTRETCH)\n\n\t// enable I2C interface\n\ti2c.Bus.CR1.SetBits(stm32.I2C_CR1_PE)\n\n\treturn nil\n}\n\n// SetBaudRate sets the communication speed for I2C.\nfunc (i2c *I2C) SetBaudRate(br uint32) error {\n\t// TODO: implement\n\treturn errI2CNotImplemented\n}\n\nfunc (i2c *I2C) Tx(addr uint16, w, r []byte) error {\n\n\tif err := i2c.controllerTransmit(addr, w); nil != err {\n\t\treturn err\n\t}\n\n\tif len(r) > 0 {\n\t\tif err := i2c.controllerReceive(addr, r); nil != err {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (i2c *I2C) controllerTransmit(addr uint16, w []byte) error {\n\n\tif !i2c.waitForFlag(flagBUSY, false) {\n\t\treturn errI2CBusReadyTimeout\n\t}\n\n\t// disable POS\n\ti2c.Bus.CR1.ClearBits(stm32.I2C_CR1_POS)\n\n\tpos := 0\n\trem := len(w)\n\n\t// send peripheral address\n\tif err := i2c.controllerRequestWrite(addr, frameNoOption); nil != err {\n\t\treturn err\n\t}\n\n\t// clear ADDR flag\n\ti2c.clearFlagADDR()\n\n\tfor rem > 0 {\n\t\t// wait for TXE flag set\n\t\tif !i2c.waitForFlagOrError(flagTXE, true) {\n\t\t\treturn errI2CAckExpected\n\t\t}\n\n\t\t// write data to DR\n\t\ti2c.Bus.DR.Set(uint32(w[pos]))\n\t\t// update counters\n\t\tpos++\n\t\trem--\n\n\t\tif i2c.hasFlag(flagBTF) && rem != 0 {\n\t\t\t// write data to DR\n\t\t\ti2c.Bus.DR.Set(uint32(w[pos]))\n\t\t\t// update counters\n\t\t\tpos++\n\t\t\trem--\n\t\t}\n\n\t\t// wait for transfer finished flag BTF set\n\t\tif !i2c.waitForFlagOrError(flagBTF, true) {\n\t\t\treturn errI2CWriteTimeout\n\t\t}\n\t}\n\n\t// generate stop condition\n\ti2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)\n\n\treturn nil\n}\n\nfunc (i2c *I2C) controllerRequestWrite(addr uint16, option transferOption) error {\n\n\tif frameFirstAndLast == option || frameFirst == option || frameNoOption == option {\n\t\t// generate start condition\n\t\ti2c.Bus.CR1.SetBits(stm32.I2C_CR1_START)\n\t} else if false /* (hi2c->PreviousState == I2C_STATE_MASTER_BUSY_RX) */ {\n\t\t// generate restart condition\n\t\ti2c.Bus.CR1.SetBits(stm32.I2C_CR1_START)\n\t}\n\n\t// ensure start bit is set\n\tif !i2c.waitForFlag(flagSB, true) {\n\t\treturn errI2CSignalStartTimeout\n\t}\n\n\t// send peripheral address\n\ti2c.Bus.DR.Set(uint32(addr) << 1)\n\n\t// wait for address ACK from peripheral\n\tif !i2c.waitForFlagOrError(flagADDR, true) {\n\t\treturn errI2CSignalStartTimeout\n\t}\n\n\treturn nil\n}\n\nfunc (i2c *I2C) controllerReceive(addr uint16, r []byte) error {\n\n\tif !i2c.waitForFlag(flagBUSY, false) {\n\t\treturn errI2CBusReadyTimeout\n\t}\n\n\t// disable POS\n\ti2c.Bus.CR1.ClearBits(stm32.I2C_CR1_POS)\n\n\tpos := 0\n\trem := len(r)\n\n\t// send peripheral address\n\tif err := i2c.controllerRequestRead(addr, frameNoOption); nil != err {\n\t\treturn err\n\t}\n\n\tswitch rem {\n\tcase 0:\n\t\t// clear ADDR flag\n\t\ti2c.clearFlagADDR()\n\t\t// generate stop condition\n\t\ti2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)\n\n\tcase 1:\n\t\t// disable ACK\n\t\ti2c.Bus.CR1.ClearBits(stm32.I2C_CR1_ACK)\n\t\t// clear ADDR flag\n\t\ti2c.clearFlagADDR()\n\t\t// generate stop condition\n\t\ti2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)\n\n\tcase 2:\n\t\t// disable ACK\n\t\ti2c.Bus.CR1.ClearBits(stm32.I2C_CR1_ACK)\n\t\t// enable POS\n\t\ti2c.Bus.CR1.SetBits(stm32.I2C_CR1_POS)\n\t\t// clear ADDR flag\n\t\ti2c.clearFlagADDR()\n\n\tdefault:\n\t\t// enable ACK\n\t\ti2c.Bus.CR1.SetBits(stm32.I2C_CR1_ACK)\n\t\t// clear ADDR flag\n\t\ti2c.clearFlagADDR()\n\t}\n\n\tfor rem > 0 {\n\t\tswitch rem {\n\t\tcase 1:\n\t\t\t// wait until RXNE flag is set\n\t\t\tif !i2c.waitForFlagOrError(flagRXNE, true) {\n\t\t\t\treturn errI2CReadTimeout\n\t\t\t}\n\n\t\t\t// read data from DR\n\t\t\tr[pos] = byte(i2c.Bus.DR.Get())\n\n\t\t\t// update counters\n\t\t\tpos++\n\t\t\trem--\n\n\t\tcase 2:\n\t\t\t// wait until transfer finished flag BTF is set\n\t\t\tif !i2c.waitForFlag(flagBTF, true) {\n\t\t\t\treturn errI2CReadTimeout\n\t\t\t}\n\n\t\t\t// generate stop condition\n\t\t\ti2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)\n\n\t\t\t// read data from DR\n\t\t\tr[pos] = byte(i2c.Bus.DR.Get())\n\n\t\t\t// update counters\n\t\t\tpos++\n\t\t\trem--\n\n\t\t\t// read data from DR\n\t\t\tr[pos] = byte(i2c.Bus.DR.Get())\n\n\t\t\t// update counters\n\t\t\tpos++\n\t\t\trem--\n\n\t\tcase 3:\n\t\t\t// wait until transfer finished flag BTF is set\n\t\t\tif !i2c.waitForFlag(flagBTF, true) {\n\t\t\t\treturn errI2CReadTimeout\n\t\t\t}\n\n\t\t\t// disable ACK\n\t\t\ti2c.Bus.CR1.ClearBits(stm32.I2C_CR1_ACK)\n\n\t\t\t// read data from DR\n\t\t\tr[pos] = byte(i2c.Bus.DR.Get())\n\n\t\t\t// update counters\n\t\t\tpos++\n\t\t\trem--\n\n\t\t\t// wait until transfer finished flag BTF is set\n\t\t\tif !i2c.waitForFlag(flagBTF, true) {\n\t\t\t\treturn errI2CReadTimeout\n\t\t\t}\n\n\t\t\t// generate stop condition\n\t\t\ti2c.Bus.CR1.SetBits(stm32.I2C_CR1_STOP)\n\n\t\t\t// read data from DR\n\t\t\tr[pos] = byte(i2c.Bus.DR.Get())\n\n\t\t\t// update counters\n\t\t\tpos++\n\t\t\trem--\n\n\t\t\t// read data from DR\n\t\t\tr[pos] = byte(i2c.Bus.DR.Get())\n\n\t\t\t// update counters\n\t\t\tpos++\n\t\t\trem--\n\n\t\tdefault:\n\t\t\t// wait until RXNE flag is set\n\t\t\tif !i2c.waitForFlagOrError(flagRXNE, true) {\n\t\t\t\treturn errI2CReadTimeout\n\t\t\t}\n\n\t\t\t// read data from DR\n\t\t\tr[pos] = byte(i2c.Bus.DR.Get())\n\n\t\t\t// update counters\n\t\t\tpos++\n\t\t\trem--\n\n\t\t\tif i2c.hasFlag(flagBTF) {\n\t\t\t\t// read data from DR\n\t\t\t\tr[pos] = byte(i2c.Bus.DR.Get())\n\n\t\t\t\t// update counters\n\t\t\t\tpos++\n\t\t\t\trem--\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (i2c *I2C) controllerRequestRead(addr uint16, option transferOption) error {\n\n\t// enable ACK\n\ti2c.Bus.CR1.SetBits(stm32.I2C_CR1_ACK)\n\n\tif frameFirstAndLast == option || frameFirst == option || frameNoOption == option {\n\t\t// generate start condition\n\t\ti2c.Bus.CR1.SetBits(stm32.I2C_CR1_START)\n\t} else if false /* (hi2c->PreviousState == I2C_STATE_MASTER_BUSY_TX) */ {\n\t\t// generate restart condition\n\t\ti2c.Bus.CR1.SetBits(stm32.I2C_CR1_START)\n\t}\n\n\t// ensure start bit is set\n\tif !i2c.waitForFlag(flagSB, true) {\n\t\treturn errI2CSignalStartTimeout\n\t}\n\n\t// send peripheral address\n\ti2c.Bus.DR.Set(uint32(addr)<<1 | 1)\n\n\t// wait for address ACK from peripheral\n\tif !i2c.waitForFlagOrError(flagADDR, true) {\n\t\treturn errI2CSignalStartTimeout\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "src/machine/machine_stm32_i2c_revb.go",
    "content": "//go:build stm32l5 || stm32f7 || stm32l4 || stm32l0 || stm32wlx\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n\t\"unsafe\"\n)\n\n//go:linkname ticks runtime.ticks\nfunc ticks() int64\n\n// I2C implementation for 'newer' STM32 MCUs, including the F7, L5 and L4\n// series of MCUs.\n//\n// Currently, only 100KHz mode is supported\n\nconst (\n\tflagBUSY  = stm32.I2C_ISR_BUSY\n\tflagTCR   = stm32.I2C_ISR_TCR\n\tflagRXNE  = stm32.I2C_ISR_RXNE\n\tflagSTOPF = stm32.I2C_ISR_STOPF\n\tflagAF    = stm32.I2C_ISR_NACKF\n\tflagTXIS  = stm32.I2C_ISR_TXIS\n\tflagTXE   = stm32.I2C_ISR_TXE\n)\n\nconst (\n\tMAX_NBYTE_SIZE = 255\n\n\t// 100ms delay = 100e6ns / 16ns\n\t// In runtime_stm32_timers.go, tick is fixed at 16ns per tick\n\tTIMEOUT_TICKS = 100e6 / 16\n\n\tI2C_NO_STARTSTOP         = 0x0\n\tI2C_GENERATE_START_WRITE = 0x80000000 | stm32.I2C_CR2_START\n\tI2C_GENERATE_START_READ  = 0x80000000 | stm32.I2C_CR2_START | stm32.I2C_CR2_RD_WRN\n\tI2C_GENERATE_STOP        = 0x80000000 | stm32.I2C_CR2_STOP\n)\n\ntype I2C struct {\n\tBus             *stm32.I2C_Type\n\tAltFuncSelector uint8\n}\n\n// I2CConfig is used to store config info for I2C.\ntype I2CConfig struct {\n\tFrequency uint32\n\tSCL       Pin\n\tSDA       Pin\n}\n\nfunc (i2c *I2C) Configure(config I2CConfig) error {\n\t// Frequency range\n\tswitch config.Frequency {\n\tcase 0:\n\t\tconfig.Frequency = 100 * KHz\n\tcase 10 * KHz, 100 * KHz, 400 * KHz, 500 * KHz:\n\tdefault:\n\t\treturn errI2CNotImplemented\n\t}\n\n\t// disable I2C interface before any configuration changes\n\ti2c.Bus.CR1.ClearBits(stm32.I2C_CR1_PE)\n\n\t// enable clock for I2C\n\tenableAltFuncClock(unsafe.Pointer(i2c.Bus))\n\n\t// init pins\n\tif config.SCL == 0 && config.SDA == 0 {\n\t\tconfig.SCL = I2C0_SCL_PIN\n\t\tconfig.SDA = I2C0_SDA_PIN\n\t}\n\ti2c.configurePins(config)\n\n\ti2c.Bus.TIMINGR.Set(i2c.getFreqRange(config.Frequency))\n\n\t// Disable Own Address1 before set the Own Address1 configuration\n\ti2c.Bus.OAR1.ClearBits(stm32.I2C_OAR1_OA1EN)\n\n\t// 7 bit addressing, no self address\n\ti2c.Bus.OAR1.Set(stm32.I2C_OAR1_OA1EN)\n\n\t// Enable the AUTOEND by default, and enable NACK (should be disable only during Slave process\n\ti2c.Bus.CR2.Set(stm32.I2C_CR2_AUTOEND | stm32.I2C_CR2_NACK)\n\n\t// Disable Own Address2 / Dual Addressing\n\ti2c.Bus.OAR2.Set(0)\n\n\t// Disable Generalcall and NoStretch, Enable peripheral\n\ti2c.Bus.CR1.Set(stm32.I2C_CR1_PE)\n\n\treturn nil\n}\n\n// SetBaudRate sets the communication speed for I2C.\nfunc (i2c *I2C) SetBaudRate(br uint32) error {\n\tswitch br {\n\tcase 10 * KHz, 100 * KHz, 400 * KHz, 500 * KHz:\n\tdefault:\n\t\treturn errI2CNotImplemented\n\t}\n\n\t// disable I2C interface before any configuration changes\n\ti2c.Bus.CR1.ClearBits(stm32.I2C_CR1_PE)\n\n\ti2c.Bus.TIMINGR.Set(i2c.getFreqRange(br))\n\n\t// Disable Generalcall and NoStretch, Enable peripheral\n\ti2c.Bus.CR1.Set(stm32.I2C_CR1_PE)\n\n\treturn nil\n}\n\nfunc (i2c *I2C) Tx(addr uint16, w, r []byte) error {\n\tif len(w) > 0 {\n\t\tif err := i2c.controllerTransmit(addr, w); nil != err {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif len(r) > 0 {\n\t\tif err := i2c.controllerReceive(addr, r); nil != err {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (i2c *I2C) configurePins(config I2CConfig) {\n\tconfig.SCL.ConfigureAltFunc(PinConfig{Mode: PinModeI2CSCL}, i2c.AltFuncSelector)\n\tconfig.SDA.ConfigureAltFunc(PinConfig{Mode: PinModeI2CSDA}, i2c.AltFuncSelector)\n}\n\nfunc (i2c *I2C) controllerTransmit(addr uint16, w []byte) error {\n\tstart := ticks()\n\n\tif !i2c.waitOnFlagUntilTimeout(flagBUSY, false, start) {\n\t\treturn errI2CBusReadyTimeout\n\t}\n\n\tpos := 0\n\txferCount := len(w)\n\txferSize := uint8(xferCount)\n\tif xferCount > MAX_NBYTE_SIZE {\n\t\t// Large write, indicate reload\n\t\txferSize = MAX_NBYTE_SIZE\n\t\ti2c.transferConfig(addr, xferSize, stm32.I2C_CR2_RELOAD, I2C_GENERATE_START_WRITE)\n\t} else {\n\t\t// Small write, auto-end\n\t\ti2c.transferConfig(addr, xferSize, stm32.I2C_CR2_AUTOEND, I2C_GENERATE_START_WRITE)\n\t}\n\n\tfor xferCount > 0 {\n\t\tif !i2c.waitOnTXISFlagUntilTimeout(start) {\n\t\t\treturn errI2CWriteTimeout\n\t\t}\n\n\t\ti2c.Bus.TXDR.Set(uint32(w[pos]))\n\t\tpos++\n\t\txferCount--\n\t\txferSize--\n\n\t\t// If we've written the last byte of this chunk\n\t\tif xferCount != 0 && xferSize == 0 {\n\t\t\t// Wait for Transfer Complete Reload to be flagged\n\t\t\tif !i2c.waitOnFlagUntilTimeout(flagTCR, true, start) {\n\t\t\t\treturn errI2CWriteTimeout\n\t\t\t}\n\n\t\t\tif xferCount > MAX_NBYTE_SIZE {\n\t\t\t\t// Large write remaining, indicate reload\n\t\t\t\txferSize = MAX_NBYTE_SIZE\n\t\t\t\ti2c.transferConfig(addr, xferSize, stm32.I2C_CR2_RELOAD, I2C_NO_STARTSTOP)\n\t\t\t} else {\n\t\t\t\t// Small write, auto-end\n\t\t\t\txferSize = uint8(xferCount)\n\t\t\t\ti2c.transferConfig(addr, xferSize, stm32.I2C_CR2_AUTOEND, I2C_NO_STARTSTOP)\n\t\t\t}\n\t\t}\n\t}\n\n\tif !i2c.waitOnStopFlagUntilTimeout(start) {\n\t\treturn errI2CWriteTimeout\n\t}\n\n\ti2c.clearFlag(stm32.I2C_ISR_STOPF)\n\n\ti2c.resetCR2()\n\n\treturn nil\n}\n\nfunc (i2c *I2C) controllerReceive(addr uint16, r []byte) error {\n\tstart := ticks()\n\n\tif !i2c.waitOnFlagUntilTimeout(flagBUSY, false, start) {\n\t\treturn errI2CBusReadyTimeout\n\t}\n\n\tpos := 0\n\txferCount := len(r)\n\txferSize := uint8(xferCount)\n\tif xferCount > MAX_NBYTE_SIZE {\n\t\t// Large read, indicate reload\n\t\txferSize = MAX_NBYTE_SIZE\n\t\ti2c.transferConfig(addr, xferSize, stm32.I2C_CR2_RELOAD, I2C_GENERATE_START_READ)\n\t} else {\n\t\t// Small read, auto-end\n\t\ti2c.transferConfig(addr, xferSize, stm32.I2C_CR2_AUTOEND, I2C_GENERATE_START_READ)\n\t}\n\n\tfor xferCount > 0 {\n\t\tif !i2c.waitOnRXNEFlagUntilTimeout(start) {\n\t\t\treturn errI2CWriteTimeout\n\t\t}\n\n\t\tr[pos] = uint8(i2c.Bus.RXDR.Get())\n\t\tpos++\n\t\txferCount--\n\t\txferSize--\n\n\t\t// If we've read the last byte of this chunk\n\t\tif xferCount != 0 && xferSize == 0 {\n\t\t\t// Wait for Transfer Complete Reload to be flagged\n\t\t\tif !i2c.waitOnFlagUntilTimeout(flagTCR, true, start) {\n\t\t\t\treturn errI2CWriteTimeout\n\t\t\t}\n\n\t\t\tif xferCount > MAX_NBYTE_SIZE {\n\t\t\t\t// Large read remaining, indicate reload\n\t\t\t\txferSize = MAX_NBYTE_SIZE\n\t\t\t\ti2c.transferConfig(addr, xferSize, stm32.I2C_CR2_RELOAD, I2C_NO_STARTSTOP)\n\t\t\t} else {\n\t\t\t\t// Small read, auto-end\n\t\t\t\txferSize = uint8(xferCount)\n\t\t\t\ti2c.transferConfig(addr, xferSize, stm32.I2C_CR2_AUTOEND, I2C_NO_STARTSTOP)\n\t\t\t}\n\t\t}\n\t}\n\n\tif !i2c.waitOnStopFlagUntilTimeout(start) {\n\t\treturn errI2CWriteTimeout\n\t}\n\n\ti2c.clearFlag(stm32.I2C_ISR_STOPF)\n\n\ti2c.resetCR2()\n\n\treturn nil\n}\n\nfunc (i2c *I2C) waitOnFlagUntilTimeout(flag uint32, set bool, startTicks int64) bool {\n\tfor i2c.hasFlag(flag) != set {\n\t\tif (ticks() - startTicks) > TIMEOUT_TICKS {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\nfunc (i2c *I2C) waitOnRXNEFlagUntilTimeout(startTicks int64) bool {\n\tfor !i2c.hasFlag(flagRXNE) {\n\t\tif i2c.isAcknowledgeFailed(startTicks) {\n\t\t\treturn false\n\t\t}\n\n\t\tif i2c.hasFlag(flagSTOPF) {\n\t\t\ti2c.clearFlag(flagSTOPF)\n\t\t\ti2c.resetCR2()\n\t\t\treturn false\n\t\t}\n\n\t\tif (ticks() - startTicks) > TIMEOUT_TICKS {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\nfunc (i2c *I2C) waitOnTXISFlagUntilTimeout(startTicks int64) bool {\n\tfor !i2c.hasFlag(flagTXIS) {\n\t\tif i2c.isAcknowledgeFailed(startTicks) {\n\t\t\treturn false\n\t\t}\n\n\t\tif (ticks() - startTicks) > TIMEOUT_TICKS {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\nfunc (i2c *I2C) waitOnStopFlagUntilTimeout(startTicks int64) bool {\n\tfor !i2c.hasFlag(flagSTOPF) {\n\t\tif i2c.isAcknowledgeFailed(startTicks) {\n\t\t\treturn false\n\t\t}\n\n\t\tif (ticks() - startTicks) > TIMEOUT_TICKS {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\nfunc (i2c *I2C) isAcknowledgeFailed(startTicks int64) bool {\n\tif i2c.hasFlag(flagAF) {\n\t\t// Wait until STOP Flag is reset\n\t\t// AutoEnd should be initiate after AF\n\t\tfor !i2c.hasFlag(flagSTOPF) {\n\t\t\tif (ticks() - startTicks) > TIMEOUT_TICKS {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\n\t\ti2c.clearFlag(flagAF)\n\t\ti2c.clearFlag(flagSTOPF)\n\t\ti2c.flushTXDR()\n\t\ti2c.resetCR2()\n\n\t\treturn true\n\t}\n\n\treturn false\n}\n\nfunc (i2c *I2C) flushTXDR() {\n\t// If a pending TXIS flag is set, write a dummy data in TXDR to clear it\n\tif i2c.hasFlag(flagTXIS) {\n\t\ti2c.Bus.TXDR.Set(0)\n\t}\n\n\t// Flush TX register if not empty\n\tif !i2c.hasFlag(flagTXE) {\n\t\ti2c.clearFlag(flagTXE)\n\t}\n}\n\nfunc (i2c *I2C) resetCR2() {\n\ti2c.Bus.CR2.ClearBits(stm32.I2C_CR2_SADD_Msk |\n\t\tstm32.I2C_CR2_HEAD10R_Msk |\n\t\tstm32.I2C_CR2_NBYTES_Msk |\n\t\tstm32.I2C_CR2_RELOAD_Msk |\n\t\tstm32.I2C_CR2_RD_WRN_Msk)\n}\n\nfunc (i2c *I2C) transferConfig(addr uint16, size uint8, mode uint32, request uint32) {\n\tmask := uint32(stm32.I2C_CR2_SADD_Msk |\n\t\tstm32.I2C_CR2_NBYTES_Msk |\n\t\tstm32.I2C_CR2_RELOAD_Msk |\n\t\tstm32.I2C_CR2_AUTOEND_Msk |\n\t\t(stm32.I2C_CR2_RD_WRN & uint32(request>>(31-stm32.I2C_CR2_RD_WRN_Pos))) |\n\t\tstm32.I2C_CR2_START_Msk |\n\t\tstm32.I2C_CR2_STOP_Msk)\n\n\tvalue := (uint32(addr<<1) & stm32.I2C_CR2_SADD_Msk) |\n\t\t((uint32(size) << stm32.I2C_CR2_NBYTES_Pos) & stm32.I2C_CR2_NBYTES_Msk) |\n\t\tmode | request\n\n\ti2c.Bus.CR2.ReplaceBits(value, mask, 0)\n}\n\nfunc (i2c *I2C) hasFlag(flag uint32) bool {\n\treturn i2c.Bus.ISR.HasBits(flag)\n}\n\nfunc (i2c *I2C) clearFlag(flag uint32) {\n\tif flag == stm32.I2C_ISR_TXE {\n\t\ti2c.Bus.ISR.SetBits(flag)\n\t} else {\n\t\ti2c.Bus.ICR.SetBits(flag)\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_stm32_iwdg.go",
    "content": "//go:build stm32\n\npackage machine\n\nimport \"device/stm32\"\n\nvar (\n\tWatchdog = &watchdogImpl{}\n)\n\nconst (\n\t// WatchdogMaxTimeout in milliseconds (32.768s)\n\t//\n\t// Timeout is based on 12-bit counter with /256 divider on\n\t// 32.768kHz clock.  See 21.3.3 of RM0090 for table.\n\tWatchdogMaxTimeout = ((0xfff + 1) * 256 * 1024) / 32768\n)\n\nconst (\n\t// Enable access to PR, RLR and WINR registers (0x5555)\n\tiwdgKeyEnable = 0x5555\n\t// Reset the watchdog value (0xAAAA)\n\tiwdgKeyReset = 0xaaaa\n\t// Start the watchdog (0xCCCC)\n\tiwdgKeyStart = 0xcccc\n\t// Divide by 256\n\tiwdgDiv256 = 6\n)\n\ntype watchdogImpl struct {\n}\n\n// Configure the watchdog.\n//\n// This method should not be called after the watchdog is started and on\n// some platforms attempting to reconfigure after starting the watchdog\n// is explicitly forbidden / will not work.\nfunc (wd *watchdogImpl) Configure(config WatchdogConfig) error {\n\n\t// Enable configuration of IWDG\n\tstm32.IWDG.KR.Set(iwdgKeyEnable)\n\n\t// Unconditionally divide by /256 since we don't really need accuracy\n\t// less than 8ms\n\tstm32.IWDG.PR.Set(iwdgDiv256)\n\n\ttimeout := config.TimeoutMillis\n\tif timeout > WatchdogMaxTimeout {\n\t\ttimeout = WatchdogMaxTimeout\n\t}\n\n\t// Set reload value based on /256 divider\n\tstm32.IWDG.RLR.Set(((config.TimeoutMillis*32768 + (256 * 1024) - 1) / (256 * 1024)) - 1)\n\treturn nil\n}\n\n// Starts the watchdog.\nfunc (wd *watchdogImpl) Start() error {\n\tstm32.IWDG.KR.Set(iwdgKeyStart)\n\treturn nil\n}\n\n// Update the watchdog, indicating that `source` is healthy.\nfunc (wd *watchdogImpl) Update() {\n\tstm32.IWDG.KR.Set(iwdgKeyReset)\n}\n"
  },
  {
    "path": "src/machine/machine_stm32_moder_gpio.go",
    "content": "//go:build stm32 && !stm32f103\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n)\n\n// GPIO for the stm32 families except the stm32f1xx which uses a simpler but\n//  less flexible mechanism. Extend the go:build directive above to exclude other\n//  models in the stm32f1xx series as necessary\n\nconst (\n\t// Mode Flag\n\tPinOutput        PinMode = 0\n\tPinInput         PinMode = PinInputFloating\n\tPinInputFloating PinMode = 1\n\tPinInputPulldown PinMode = 2\n\tPinInputPullup   PinMode = 3\n\n\t// for UART\n\tPinModeUARTTX PinMode = 4\n\tPinModeUARTRX PinMode = 5\n\n\t// for I2C\n\tPinModeI2CSCL PinMode = 6\n\tPinModeI2CSDA PinMode = 7\n\n\t// for SPI\n\tPinModeSPICLK PinMode = 8\n\tPinModeSPISDO PinMode = 9\n\tPinModeSPISDI PinMode = 10\n\n\t// for analog/ADC\n\tPinInputAnalog PinMode = 11\n\n\t// for PWM\n\tPinModePWMOutput PinMode = 12\n)\n\n// Define several bitfields that have different names across chip families but\n// essentially have the same meaning.\nconst (\n\t// MODER bitfields.\n\tgpioModeInput     = 0\n\tgpioModeOutput    = 1\n\tgpioModeAlternate = 2\n\tgpioModeAnalog    = 3\n\tgpioModeMask      = 0x3\n\n\t// PUPDR bitfields.\n\tgpioPullFloating = 0\n\tgpioPullUp       = 1\n\tgpioPullDown     = 2\n\tgpioPullMask     = 0x3\n\n\t// OSPEED bitfields.\n\tgpioOutputSpeedVeryHigh = 3\n\tgpioOutputSpeedHigh     = 2\n\tgpioOutputSpeedMedium   = 1\n\tgpioOutputSpeedLow      = 0\n\tgpioOutputSpeedMask     = 0x3\n)\n\n// Configure this pin with the given configuration\nfunc (p Pin) Configure(config PinConfig) {\n\t// Use the default system alternate function; this\n\t//  will only be used if you try to call this with\n\t//  one of the peripheral modes instead of vanilla GPIO.\n\tp.ConfigureAltFunc(config, 0)\n}\n\n// Configure this pin with the given configuration including alternate\n//\n//\tfunction mapping if necessary.\nfunc (p Pin) ConfigureAltFunc(config PinConfig, altFunc uint8) {\n\t// Configure the GPIO pin.\n\tp.enableClock()\n\tport := p.getPort()\n\tpos := (uint8(p) % 16) * 2 // assume each field is two bits in size (with mask 0x3)\n\n\tswitch config.Mode {\n\n\t// GPIO\n\tcase PinInputFloating:\n\t\tport.MODER.ReplaceBits(gpioModeInput, gpioModeMask, pos)\n\t\tport.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)\n\tcase PinInputPulldown:\n\t\tport.MODER.ReplaceBits(gpioModeInput, gpioModeMask, pos)\n\t\tport.PUPDR.ReplaceBits(gpioPullDown, gpioPullMask, pos)\n\tcase PinInputPullup:\n\t\tport.MODER.ReplaceBits(gpioModeInput, gpioModeMask, pos)\n\t\tport.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos)\n\tcase PinOutput:\n\t\tport.MODER.ReplaceBits(gpioModeOutput, gpioModeMask, pos)\n\t\tport.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos)\n\n\t// UART\n\tcase PinModeUARTTX:\n\t\tport.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)\n\t\tport.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos)\n\t\tport.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos)\n\t\tp.SetAltFunc(altFunc)\n\tcase PinModeUARTRX:\n\t\tport.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)\n\t\tport.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)\n\t\tp.SetAltFunc(altFunc)\n\n\t// I2C\n\tcase PinModeI2CSCL:\n\t\tport.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)\n\t\tport.OTYPER.ReplaceBits(stm32.GPIO_OTYPER_OT0_OpenDrain, stm32.GPIO_OTYPER_OT0_Msk, pos/2)\n\t\tport.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)\n\t\tport.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos)\n\t\tp.SetAltFunc(altFunc)\n\tcase PinModeI2CSDA:\n\t\tport.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)\n\t\tport.OTYPER.ReplaceBits(stm32.GPIO_OTYPER_OT0_OpenDrain, stm32.GPIO_OTYPER_OT0_Msk, pos/2)\n\t\tport.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)\n\t\tport.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos)\n\t\tp.SetAltFunc(altFunc)\n\n\t// SPI\n\tcase PinModeSPICLK:\n\t\tport.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)\n\t\tport.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos)\n\t\tport.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)\n\t\tp.SetAltFunc(altFunc)\n\tcase PinModeSPISDO:\n\t\tport.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)\n\t\tport.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)\n\t\tport.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)\n\t\tp.SetAltFunc(altFunc)\n\tcase PinModeSPISDI:\n\t\tport.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)\n\t\tport.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)\n\t\tport.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)\n\t\tp.SetAltFunc(altFunc)\n\n\t// PWM\n\tcase PinModePWMOutput:\n\t\tport.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)\n\t\tport.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos)\n\t\tport.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)\n\t\tp.SetAltFunc(altFunc)\n\n\t// ADC\n\tcase PinInputAnalog:\n\t\tport.MODER.ReplaceBits(gpioModeAnalog, gpioModeMask, pos)\n\t\tport.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)\n\t}\n}\n\n// SetAltFunc maps the given alternative function to the I/O pin\nfunc (p Pin) SetAltFunc(af uint8) {\n\tport := p.getPort()\n\tpin := uint8(p) % 16\n\tpos := (pin % 8) * 4\n\tif pin < 8 {\n\t\tport.AFRL.ReplaceBits(uint32(af), 0xf, pos)\n\t} else {\n\t\tport.AFRH.ReplaceBits(uint32(af), 0xf, pos)\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_stm32_rng.go",
    "content": "//go:build stm32 && !(stm32f103 || stm32l0x1)\n\npackage machine\n\nimport \"device/stm32\"\n\nvar rngInitDone = false\n\nconst RNG_MAX_READ_RETRIES = 1000\n\n// GetRNG returns 32 bits of cryptographically secure random data\nfunc GetRNG() (uint32, error) {\n\tif !rngInitDone {\n\t\tinitRNG()\n\t\trngInitDone = true\n\t}\n\n\tif stm32.RNG.SR.HasBits(stm32.RNG_SR_CECS) {\n\t\treturn 0, ErrClockRNG\n\t}\n\tif stm32.RNG.SR.HasBits(stm32.RNG_SR_SECS) {\n\t\treturn 0, ErrSeedRNG\n\t}\n\n\tcnt := RNG_MAX_READ_RETRIES\n\tfor !stm32.RNG.SR.HasBits(stm32.RNG_SR_DRDY) {\n\t\tcnt--\n\t\tif cnt == 0 {\n\t\t\treturn 0, ErrTimeoutRNG\n\t\t}\n\t}\n\n\tret := stm32.RNG.DR.Get()\n\treturn ret, nil\n}\n"
  },
  {
    "path": "src/machine/machine_stm32_spi.go",
    "content": "//go:build stm32 && !stm32f7x2 && !stm32l5x2\n\npackage machine\n\n// Peripheral abstraction layer for SPI on the stm32 family\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\n// SPIConfig is used to store config info for SPI.\ntype SPIConfig struct {\n\tFrequency uint32\n\tSCK       Pin\n\tSDO       Pin\n\tSDI       Pin\n\tLSBFirst  bool\n\tMode      uint8\n}\n\n// Configure is intended to setup the STM32 SPI1 interface.\nfunc (spi *SPI) Configure(config SPIConfig) error {\n\n\t// -- CONFIGURING THE SPI IN MASTER MODE --\n\t//\n\t// 1. Select the BR[2:0] bits to define the serial clock baud rate (see\n\t// \t  SPI_CR1 register).\n\t// 2. Select the CPOL and CPHA bits to define one of the four relationships\n\t//    between the data transfer and the serial clock (see Figure 248). This\n\t//    step is not required when the TI mode is selected.\n\t// 3. Set the DFF bit to define 8- or 16-bit data frame format\n\t// 4. Configure the LSBFIRST bit in the SPI_CR1 register to define the frame\n\t//    format. This step is not required when the TI mode is selected.\n\t// 5. If the NSS pin is required in input mode, in hardware mode, connect the\n\t//    NSS pin to a high-level signal during the complete byte transmit\n\t//    sequence. In NSS software mode, set the SSM and SSI bits in the SPI_CR1\n\t//    register. If the NSS pin is required in output mode, the SSOE bit only\n\t//    should be set. This step is not required when the TI mode is selected.\n\t// 6. Set the FRF bit in SPI_CR2 to select the TI protocol for serial\n\t//    communications.\n\t// 7. The MSTR and SPE bits must be set (they remain set only if the NSS pin\n\t//    is connected to a high-level signal).\n\n\t// disable SPI interface before any configuration changes\n\tspi.Bus.CR1.ClearBits(stm32.SPI_CR1_SPE)\n\n\t// enable clock for SPI\n\tenableAltFuncClock(unsafe.Pointer(spi.Bus))\n\n\t// init pins\n\tif config.SCK == 0 && config.SDO == 0 && config.SDI == 0 {\n\t\tconfig.SCK = SPI0_SCK_PIN\n\t\tconfig.SDO = SPI0_SDO_PIN\n\t\tconfig.SDI = SPI0_SDI_PIN\n\t}\n\tspi.configurePins(config)\n\n\t// Get SPI baud rate based on the bus speed it's attached to\n\tvar conf uint32 = spi.getBaudRate(config)\n\n\t// set bit transfer order\n\tif config.LSBFirst {\n\t\tconf |= stm32.SPI_CR1_LSBFIRST\n\t}\n\n\t// set polarity and phase on the SPI interface\n\tswitch config.Mode {\n\tcase Mode1:\n\t\tconf |= stm32.SPI_CR1_CPHA\n\tcase Mode2:\n\t\tconf |= stm32.SPI_CR1_CPOL\n\tcase Mode3:\n\t\tconf |= stm32.SPI_CR1_CPOL\n\t\tconf |= stm32.SPI_CR1_CPHA\n\t}\n\n\t// configure as SPI master\n\tconf |= stm32.SPI_CR1_MSTR | stm32.SPI_CR1_SSI\n\n\t// enable the SPI interface\n\tconf |= stm32.SPI_CR1_SPE\n\n\t// use software CS (GPIO) by default\n\tconf |= stm32.SPI_CR1_SSM\n\n\t// now set the configuration\n\tspi.Bus.CR1.Set(conf)\n\n\t// Series-specific configuration to set 8-bit transfer mode\n\tspi.config8Bits()\n\n\t// enable SPI\n\tspi.Bus.CR1.SetBits(stm32.SPI_CR1_SPE)\n\n\treturn nil\n}\n\n// Transfer writes/reads a single byte using the SPI interface.\nfunc (spi *SPI) Transfer(w byte) (byte, error) {\n\n\t// 1. Enable the SPI by setting the SPE bit to 1.\n\t// 2. Write the first data item to be transmitted into the SPI_DR register\n\t//    (this clears the TXE flag).\n\t// 3. Wait until TXE=1 and write the second data item to be transmitted. Then\n\t//    wait until RXNE=1 and read the SPI_DR to get the first received data\n\t//    item (this clears the RXNE bit). Repeat this operation for each data\n\t//    item to be transmitted/received until the n–1 received data.\n\t// 4. Wait until RXNE=1 and read the last received data.\n\t// 5. Wait until TXE=1 and then wait until BSY=0 before disabling the SPI.\n\n\t// put output word (8-bit) in data register (DR), which is parallel-loaded\n\t// into shift register, and shifted out on MOSI.  Some series have 16-bit\n\t// register but writes must be strictly 8-bit to output a byte.  Writing\n\t// 16-bits indicates a packed transfer (2 bytes).\n\t(*volatile.Register8)(unsafe.Pointer(&spi.Bus.DR.Reg)).Set(w)\n\n\t// wait for SPI bus receive buffer not empty bit (RXNE) to be set.\n\t// warning: blocks forever until this condition is met.\n\tfor !spi.Bus.SR.HasBits(stm32.SPI_SR_RXNE) {\n\t}\n\n\t// copy input word (8-bit) in data register (DR), which was shifted in on MISO\n\t// and parallel-loaded into register.\n\tdata := byte(spi.Bus.DR.Get())\n\n\t// wait for SPI bus transmit buffer empty bit (TXE) to be set.\n\t// warning: blocks forever until this condition is met.\n\tfor !spi.Bus.SR.HasBits(stm32.SPI_SR_TXE) {\n\t}\n\n\t// wait for SPI bus busy bit (BSY) to be clear to indicate synchronous\n\t// transfer complete. this will effectively prevent this Transfer() function\n\t// from being capable of maintaining high-bandwidth communication throughput,\n\t// but it will help guarantee stability on the bus.\n\tfor spi.Bus.SR.HasBits(stm32.SPI_SR_BSY) {\n\t}\n\n\t// clear the overrun flag (only in full-duplex mode)\n\tif !spi.Bus.CR1.HasBits(stm32.SPI_CR1_RXONLY | stm32.SPI_CR1_BIDIMODE | stm32.SPI_CR1_BIDIOE) {\n\t\tspi.Bus.SR.Get()\n\t}\n\n\t// Return received data from SPI data register\n\treturn data, nil\n}\n"
  },
  {
    "path": "src/machine/machine_stm32_tim.go",
    "content": "//go:build stm32\n\npackage machine\n\n// The type alias `arrtype` should be defined to either uint32 or uint16\n// depending on the size of that register in the MCU's TIM_Type structure.\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n)\n\nconst PWM_MODE1 = 0x6\n\ntype TimerCallback func()\ntype ChannelCallback func(channel uint8)\n\ntype PinFunction struct {\n\tPin     Pin\n\tAltFunc uint8\n}\n\ntype TimerChannel struct {\n\tPins []PinFunction\n}\n\ntype TIM struct {\n\tEnableRegister *volatile.Register32\n\tEnableFlag     uint32\n\tDevice         *stm32.TIM_Type\n\tChannels       [4]TimerChannel\n\tUpInterrupt    interrupt.Interrupt\n\tOCInterrupt    interrupt.Interrupt\n\n\twraparoundCallback TimerCallback\n\tchannelCallbacks   [4]ChannelCallback\n\n\tbusFreq uint64\n}\n\n// Configure enables and configures this PWM.\nfunc (t *TIM) Configure(config PWMConfig) error {\n\t// Enable device\n\tt.EnableRegister.SetBits(t.EnableFlag)\n\n\terr := t.setPeriod(config.Period, true)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Auto-repeat\n\tt.Device.EGR.SetBits(stm32.TIM_EGR_UG)\n\n\t// Enable the timer\n\tt.Device.CR1.SetBits(stm32.TIM_CR1_CEN | stm32.TIM_CR1_ARPE)\n\n\treturn nil\n}\n\nfunc (t *TIM) Count() uint32 {\n\treturn uint32(t.Device.CNT.Get())\n}\n\n// SetWraparoundInterrupt configures a callback to be called each\n// time the timer 'wraps-around'.\n//\n// For example, if `Configure(PWMConfig{Period:1000000})` is used,\n// to set the timer period to 1ms, this callback will be called every\n// 1ms.\nfunc (t *TIM) SetWraparoundInterrupt(callback TimerCallback) error {\n\t// Disable this interrupt to prevent race conditions\n\t//t.UpInterrupt.Disable()\n\n\t// Ensure the interrupt handler for Update events is registered\n\tt.UpInterrupt = t.registerUPInterrupt()\n\n\t// Clear update flag\n\tt.Device.SR.ClearBits(stm32.TIM_SR_UIF)\n\n\tt.wraparoundCallback = callback\n\tt.UpInterrupt.SetPriority(0xc1)\n\tt.UpInterrupt.Enable()\n\n\t// Enable the hardware interrupt\n\tt.Device.DIER.SetBits(stm32.TIM_DIER_UIE)\n\n\treturn nil\n}\n\n// Sets a callback to be called when a channel reaches it's set-point.\n//\n// For example, if `t.Set(ch, t.Top() / 4)` is used then the callback will\n// be called every quarter-period of the timer's base Period.\nfunc (t *TIM) SetMatchInterrupt(channel uint8, callback ChannelCallback) error {\n\tt.channelCallbacks[channel] = callback\n\n\t// Ensure the interrupt handler for Output Compare events is registered\n\tt.OCInterrupt = t.registerOCInterrupt()\n\n\t// Clear the interrupt flag\n\tt.Device.SR.ClearBits(stm32.TIM_SR_CC1IF << channel)\n\n\t// Enable the interrupt\n\tt.OCInterrupt.SetPriority(0xc1)\n\tt.OCInterrupt.Enable()\n\n\t// Enable the hardware interrupt\n\tt.Device.DIER.SetBits(stm32.TIM_DIER_CC1IE << channel)\n\n\treturn nil\n}\n\n// SetPeriod updates the period of this PWM peripheral.\n// To set a particular frequency, use the following formula:\n//\n//\tperiod = 1e9 / frequency\n//\n// If you use a period of 0, a period that works well for LEDs will be picked.\n//\n// SetPeriod will not change the prescaler, but also won't change the current\n// value in any of the channels. This means that you may need to update the\n// value for the particular channel.\n//\n// Note that you cannot pick any arbitrary period after the PWM peripheral has\n// been configured. If you want to switch between frequencies, pick the lowest\n// frequency (longest period) once when calling Configure and adjust the\n// frequency here as needed.\nfunc (t *TIM) SetPeriod(period uint64) error {\n\treturn t.setPeriod(period, false)\n}\n\nfunc (t *TIM) setPeriod(period uint64, updatePrescaler bool) error {\n\tvar top uint64\n\tif period == 0 {\n\t\ttop = ARR_MAX\n\t} else {\n\t\ttop = (period / 1000) * (t.busFreq / 1000) / 1000\n\t}\n\n\tvar psc uint64\n\tif updatePrescaler {\n\t\tif top > ARR_MAX*PSC_MAX {\n\t\t\treturn ErrPWMPeriodTooLong\n\t\t}\n\n\t\t// Select the minimum PSC that scales the ARR value into\n\t\t// range to maintain precision in ARR for changing frequencies\n\t\t// later\n\t\tpsc = ceil(top, ARR_MAX)\n\t\ttop = top / psc\n\n\t\tt.Device.PSC.Set(uint32(psc - 1))\n\t} else {\n\t\tpsc = uint64(t.Device.PSC.Get()) + 1\n\t\ttop = top / psc\n\n\t\tif top > ARR_MAX {\n\t\t\treturn ErrPWMPeriodTooLong\n\t\t}\n\t}\n\n\tt.Device.ARR.Set(arrtype(top - 1))\n\treturn nil\n}\n\n// Top returns the current counter top, for use in duty cycle calculation. It\n// will only change with a call to Configure or SetPeriod, otherwise it is\n// constant.\n//\n// The value returned here is hardware dependent. In general, it's best to treat\n// it as an opaque value that can be divided by some number and passed to\n// pwm.Set (see pwm.Set for more information).\nfunc (t *TIM) Top() uint32 {\n\treturn uint32(t.Device.ARR.Get()) + 1\n}\n\n// Channel returns a PWM channel for the given pin.\nfunc (t *TIM) Channel(pin Pin) (uint8, error) {\n\n\tfor chi, ch := range t.Channels {\n\t\tfor _, p := range ch.Pins {\n\t\t\tif p.Pin == pin {\n\t\t\t\tt.configurePin(uint8(chi), p)\n\t\t\t\t//p.Pin.ConfigureAltFunc(PinConfig{Mode: PinModePWMOutput}, p.AltFunc)\n\t\t\t\treturn uint8(chi), nil\n\t\t\t}\n\t\t}\n\t}\n\n\treturn 0, ErrInvalidOutputPin\n}\n\n// Set updates the channel value. This is used to control the channel duty\n// cycle. For example, to set it to a 25% duty cycle, use:\n//\n//\tt.Set(ch, t.Top() / 4)\n//\n// ch.Set(0) will set the output to low and ch.Set(ch.Top()) will set the output\n// to high, assuming the output isn't inverted.\nfunc (t *TIM) Set(channel uint8, value uint32) {\n\tt.enableMainOutput()\n\n\tccr := t.channelCCR(channel)\n\tccmr, offset := t.channelCCMR(channel)\n\n\t// Disable interrupts whilst programming to prevent spurious OC interrupts\n\tmask := interrupt.Disable()\n\n\t// Set the PWM to Mode 1 (active below set value, inactive above)\n\t// Preload is disabled so we can change OC value within one update period.\n\tvar ccmrVal uint32\n\tccmrVal |= PWM_MODE1 << stm32.TIM_CCMR1_Output_OC1M_Pos\n\tccmr.ReplaceBits(ccmrVal, 0xFF, offset)\n\n\t// Set the compare value\n\tccr.Set(arrtype(value))\n\n\t// Enable the channel (if not already)\n\tt.Device.CCER.ReplaceBits(stm32.TIM_CCER_CC1E, 0xD, channel*4)\n\n\t// Force update\n\tt.Device.EGR.SetBits(stm32.TIM_EGR_CC1G << channel)\n\n\t// Reset Interrupt Flag\n\tt.Device.SR.ClearBits(stm32.TIM_SR_CC1IF << channel)\n\n\t// Restore interrupts\n\tinterrupt.Restore(mask)\n}\n\n// Unset disables a channel, including any configured interrupts.\nfunc (t *TIM) Unset(channel uint8) {\n\t// Disable interrupts whilst programming to prevent spurious OC interrupts\n\tmask := interrupt.Disable()\n\n\t// Disable the channel\n\tt.Device.CCER.ReplaceBits(0, 0xD, channel*4)\n\n\t// Reset to zero value\n\tccr := t.channelCCR(channel)\n\tccr.Set(0)\n\n\t// Disable the hardware interrupt\n\tt.Device.DIER.ClearBits(stm32.TIM_DIER_CC1IE << channel)\n\n\t// Clear the interrupt flag\n\tt.Device.SR.ClearBits(stm32.TIM_SR_CC1IF << channel)\n\n\t// Restore interrupts\n\tinterrupt.Restore(mask)\n}\n\n// SetInverting sets whether to invert the output of this channel.\n// Without inverting, a 25% duty cycle would mean the output is high for 25% of\n// the time and low for the rest. Inverting flips the output as if a NOT gate\n// was placed at the output, meaning that the output would be 25% low and 75%\n// high with a duty cycle of 25%.\nfunc (t *TIM) SetInverting(channel uint8, inverting bool) {\n\t// Enable the channel (if not already)\n\n\tvar val = uint32(0)\n\tif inverting {\n\t\tval |= stm32.TIM_CCER_CC1P\n\t}\n\n\tt.Device.CCER.ReplaceBits(val, stm32.TIM_CCER_CC1P_Msk, channel*4)\n}\n\nfunc (t *TIM) handleUPInterrupt(interrupt.Interrupt) {\n\tif t.Device.SR.HasBits(stm32.TIM_SR_UIF) {\n\t\t// clear the update flag\n\t\tt.Device.SR.ClearBits(stm32.TIM_SR_UIF)\n\n\t\tif t.wraparoundCallback != nil {\n\t\t\tt.wraparoundCallback()\n\t\t}\n\t}\n}\n\nfunc (t *TIM) handleOCInterrupt(interrupt.Interrupt) {\n\tif t.Device.SR.HasBits(stm32.TIM_SR_CC1IF) {\n\t\tif t.channelCallbacks[0] != nil {\n\t\t\tt.channelCallbacks[0](0)\n\t\t}\n\t}\n\tif t.Device.SR.HasBits(stm32.TIM_SR_CC2IF) {\n\t\tif t.channelCallbacks[1] != nil {\n\t\t\tt.channelCallbacks[1](1)\n\t\t}\n\t}\n\tif t.Device.SR.HasBits(stm32.TIM_SR_CC3IF) {\n\t\tif t.channelCallbacks[2] != nil {\n\t\t\tt.channelCallbacks[2](2)\n\t\t}\n\t}\n\tif t.Device.SR.HasBits(stm32.TIM_SR_CC4IF) {\n\t\tif t.channelCallbacks[3] != nil {\n\t\t\tt.channelCallbacks[3](3)\n\t\t}\n\t}\n\n\t// Reset interrupt flags\n\tt.Device.SR.ClearBits(stm32.TIM_SR_CC1IF | stm32.TIM_SR_CC2IF | stm32.TIM_SR_CC3IF | stm32.TIM_SR_CC4IF)\n}\n\nfunc (t *TIM) channelCCR(channel uint8) *arrRegType {\n\tswitch channel {\n\tcase 0:\n\t\treturn &t.Device.CCR1\n\tcase 1:\n\t\treturn &t.Device.CCR2\n\tcase 2:\n\t\treturn &t.Device.CCR3\n\tcase 3:\n\t\treturn &t.Device.CCR4\n\t}\n\n\treturn nil\n}\n\nfunc (t *TIM) channelCCMR(channel uint8) (reg *volatile.Register32, offset uint8) {\n\tswitch channel {\n\tcase 0:\n\t\treturn &t.Device.CCMR1_Output, 0\n\tcase 1:\n\t\treturn &t.Device.CCMR1_Output, 8\n\tcase 2:\n\t\treturn &t.Device.CCMR2_Output, 0\n\tcase 3:\n\t\treturn &t.Device.CCMR2_Output, 8\n\t}\n\n\treturn nil, 0\n}\n\n//go:inline\nfunc ceil(num uint64, denom uint64) uint64 {\n\treturn (num + denom - 1) / denom\n}\n"
  },
  {
    "path": "src/machine/machine_stm32_tim_moder.go",
    "content": "//go:build stm32 && !stm32f1\n\npackage machine\n\n// Configuration of a GPIO pin for PWM output for STM32 MCUs with MODER\n// register (most MCUs except STM32F1 series).\n\nfunc (t *TIM) configurePin(channel uint8, pf PinFunction) {\n\tpf.Pin.ConfigureAltFunc(PinConfig{Mode: PinModePWMOutput}, pf.AltFunc)\n}\n"
  },
  {
    "path": "src/machine/machine_stm32_uart.go",
    "content": "//go:build stm32\n\npackage machine\n\n// Peripheral abstraction layer for UARTs on the stm32 family.\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\n// UART representation\ntype UART struct {\n\tBuffer            *RingBuffer\n\tBus               *stm32.USART_Type\n\tInterrupt         interrupt.Interrupt\n\tTxAltFuncSelector uint8\n\tRxAltFuncSelector uint8\n\n\t// Registers specific to the chip\n\trxReg       *volatile.Register32\n\ttxReg       *volatile.Register32\n\tstatusReg   *volatile.Register32\n\ttxEmptyFlag uint32\n}\n\n// Configure the UART.\nfunc (uart *UART) Configure(config UARTConfig) {\n\t// Default baud rate to 115200.\n\tif config.BaudRate == 0 {\n\t\tconfig.BaudRate = 115200\n\t}\n\n\t// Set the GPIO pins to defaults if they're not set\n\tif config.TX == 0 && config.RX == 0 {\n\t\tconfig.TX = UART_TX_PIN\n\t\tconfig.RX = UART_RX_PIN\n\t}\n\n\t// STM32 families have different, but compatible, registers for\n\t// basic UART functions.  For each family populate the registers\n\t// into `uart`.\n\tuart.setRegisters()\n\n\t// Enable USART clock\n\tenableAltFuncClock(unsafe.Pointer(uart.Bus))\n\n\tuart.configurePins(config)\n\n\t// Set baud rate\n\tuart.SetBaudRate(config.BaudRate)\n\n\t// Enable USART port, tx, rx and rx interrupts\n\tuart.Bus.CR1.Set(stm32.USART_CR1_TE | stm32.USART_CR1_RE | stm32.USART_CR1_RXNEIE | stm32.USART_CR1_UE)\n\n\t// Enable RX IRQ\n\tuart.Interrupt.SetPriority(0xc0)\n\tuart.Interrupt.Enable()\n}\n\n// handleInterrupt should be called from the appropriate interrupt handler for\n// this UART instance.\nfunc (uart *UART) handleInterrupt(interrupt.Interrupt) {\n\tuart.Receive(byte((uart.rxReg.Get() & 0xFF)))\n}\n\n// SetBaudRate sets the communication speed for the UART. Defer to chip-specific\n// routines for calculation\nfunc (uart *UART) SetBaudRate(br uint32) {\n\tdivider := uart.getBaudRateDivisor(br)\n\tuart.Bus.BRR.Set(divider)\n}\n\n// WriteByte writes a byte of data to the UART.\nfunc (uart *UART) writeByte(c byte) error {\n\tuart.txReg.Set(uint32(c))\n\n\tfor !uart.statusReg.HasBits(uart.txEmptyFlag) {\n\t}\n\treturn nil\n}\n\nfunc (uart *UART) flush() {}\n"
  },
  {
    "path": "src/machine/machine_stm32f103.go",
    "content": "//go:build stm32 && stm32f103\n\npackage machine\n\n// Peripheral abstraction layer for the stm32.\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nfunc CPUFrequency() uint32 {\n\treturn 72000000\n}\n\nvar deviceIDAddr = []uintptr{0x1FFFF7E8, 0x1FFFF7EC, 0x1FFFF7F0}\n\n// Internal use: configured speed of the APB1 and APB2 timers, this should be kept\n// in sync with any changes to runtime package which configures the oscillators\n// and clock frequencies\nconst APB1_TIM_FREQ = 72e6 // 72MHz\nconst APB2_TIM_FREQ = 72e6 // 72MHz\n\nconst (\n\tPinInput       PinMode = 0 // Input mode\n\tPinOutput10MHz PinMode = 1 // Output mode, max speed 10MHz\n\tPinOutput2MHz  PinMode = 2 // Output mode, max speed 2MHz\n\tPinOutput50MHz PinMode = 3 // Output mode, max speed 50MHz\n\tPinOutput      PinMode = PinOutput2MHz\n\n\tPinInputModeAnalog     PinMode = 0  // Input analog mode\n\tPinInputModeFloating   PinMode = 4  // Input floating mode\n\tPinInputModePullUpDown PinMode = 8  // Input pull up/down mode\n\tPinInputModeReserved   PinMode = 12 // Input mode (reserved)\n\n\tPinOutputModeGPPushPull   PinMode = 0  // Output mode general purpose push/pull\n\tPinOutputModeGPOpenDrain  PinMode = 4  // Output mode general purpose open drain\n\tPinOutputModeAltPushPull  PinMode = 8  // Output mode alt. purpose push/pull\n\tPinOutputModeAltOpenDrain PinMode = 12 // Output mode alt. purpose open drain\n\n\t// Pull-up vs Pull down is not part of the CNF0 / CNF1 bits, but is\n\t// controlled by PxODR.  Encoded using the 'spare' bit 5.\n\tPinInputPulldown PinMode = PinInputModePullUpDown\n\tPinInputPullup   PinMode = PinInputModePullUpDown | 0x10\n)\n\n// Pin constants for all stm32f103 package sizes\nconst (\n\tPA0  = portA + 0\n\tPA1  = portA + 1\n\tPA2  = portA + 2\n\tPA3  = portA + 3\n\tPA4  = portA + 4\n\tPA5  = portA + 5\n\tPA6  = portA + 6\n\tPA7  = portA + 7\n\tPA8  = portA + 8\n\tPA9  = portA + 9\n\tPA10 = portA + 10\n\tPA11 = portA + 11\n\tPA12 = portA + 12\n\tPA13 = portA + 13\n\tPA14 = portA + 14\n\tPA15 = portA + 15\n\n\tPB0  = portB + 0\n\tPB1  = portB + 1\n\tPB2  = portB + 2\n\tPB3  = portB + 3\n\tPB4  = portB + 4\n\tPB5  = portB + 5\n\tPB6  = portB + 6\n\tPB7  = portB + 7\n\tPB8  = portB + 8\n\tPB9  = portB + 9\n\tPB10 = portB + 10\n\tPB11 = portB + 11\n\tPB12 = portB + 12\n\tPB13 = portB + 13\n\tPB14 = portB + 14\n\tPB15 = portB + 15\n\n\tPC0  = portC + 0\n\tPC1  = portC + 1\n\tPC2  = portC + 2\n\tPC3  = portC + 3\n\tPC4  = portC + 4\n\tPC5  = portC + 5\n\tPC6  = portC + 6\n\tPC7  = portC + 7\n\tPC8  = portC + 8\n\tPC9  = portC + 9\n\tPC10 = portC + 10\n\tPC11 = portC + 11\n\tPC12 = portC + 12\n\tPC13 = portC + 13\n\tPC14 = portC + 14\n\tPC15 = portC + 15\n\n\tPD0  = portD + 0\n\tPD1  = portD + 1\n\tPD2  = portD + 2\n\tPD3  = portD + 3\n\tPD4  = portD + 4\n\tPD5  = portD + 5\n\tPD6  = portD + 6\n\tPD7  = portD + 7\n\tPD8  = portD + 8\n\tPD9  = portD + 9\n\tPD10 = portD + 10\n\tPD11 = portD + 11\n\tPD12 = portD + 12\n\tPD13 = portD + 13\n\tPD14 = portD + 14\n\tPD15 = portD + 15\n\n\tPE0  = portE + 0\n\tPE1  = portE + 1\n\tPE2  = portE + 2\n\tPE3  = portE + 3\n\tPE4  = portE + 4\n\tPE5  = portE + 5\n\tPE6  = portE + 6\n\tPE7  = portE + 7\n\tPE8  = portE + 8\n\tPE9  = portE + 9\n\tPE10 = portE + 10\n\tPE11 = portE + 11\n\tPE12 = portE + 12\n\tPE13 = portE + 13\n\tPE14 = portE + 14\n\tPE15 = portE + 15\n\n\tPF0  = portF + 0\n\tPF1  = portF + 1\n\tPF2  = portF + 2\n\tPF3  = portF + 3\n\tPF4  = portF + 4\n\tPF5  = portF + 5\n\tPF6  = portF + 6\n\tPF7  = portF + 7\n\tPF8  = portF + 8\n\tPF9  = portF + 9\n\tPF10 = portF + 10\n\tPF11 = portF + 11\n\tPF12 = portF + 12\n\tPF13 = portF + 13\n\tPF14 = portF + 14\n\tPF15 = portF + 15\n)\n\n// Configure this pin with the given I/O settings.\n// stm32f1xx uses different technique for setting the GPIO pins than the stm32f407\nfunc (p Pin) Configure(config PinConfig) {\n\t// Configure the GPIO pin.\n\tp.enableClock()\n\tport := p.getPort()\n\tpin := uint8(p) % 16\n\tpos := (pin % 8) * 4\n\tif pin < 8 {\n\t\tport.CRL.ReplaceBits(uint32(config.Mode), 0xf, pos)\n\t} else {\n\t\tport.CRH.ReplaceBits(uint32(config.Mode), 0xf, pos)\n\t}\n\n\t// If configured for input pull-up or pull-down, set ODR\n\t// for desired pull-up or pull-down.\n\tif (config.Mode & 0xf) == PinInputModePullUpDown {\n\t\tvar pullup uint32\n\t\tif config.Mode == PinInputPullup {\n\t\t\tpullup = 1\n\t\t}\n\t\tport.ODR.ReplaceBits(pullup, 0x1, pin)\n\t}\n}\n\nfunc (p Pin) getPort() *stm32.GPIO_Type {\n\tswitch p / 16 {\n\tcase 0:\n\t\treturn stm32.GPIOA\n\tcase 1:\n\t\treturn stm32.GPIOB\n\tcase 2:\n\t\treturn stm32.GPIOC\n\tcase 3:\n\t\treturn stm32.GPIOD\n\tcase 4:\n\t\treturn stm32.GPIOE\n\tcase 5:\n\t\treturn stm32.GPIOF\n\tcase 6:\n\t\treturn stm32.GPIOG\n\tdefault:\n\t\tpanic(\"machine: unknown port\")\n\t}\n}\n\n// enableClock enables the clock for this desired GPIO port.\nfunc (p Pin) enableClock() {\n\tswitch p / 16 {\n\tcase 0:\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_IOPAEN)\n\tcase 1:\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_IOPBEN)\n\tcase 2:\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_IOPCEN)\n\tcase 3:\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_IOPDEN)\n\tcase 4:\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_IOPEEN)\n\tcase 5:\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_IOPFEN)\n\tcase 6:\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_IOPGEN)\n\tdefault:\n\t\tpanic(\"machine: unknown port\")\n\t}\n}\n\n// Enable peripheral clock. Expand to include all the desired peripherals\nfunc enableAltFuncClock(bus unsafe.Pointer) {\n\tswitch bus {\n\tcase unsafe.Pointer(stm32.USART1):\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART1EN)\n\tcase unsafe.Pointer(stm32.USART2):\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART2EN)\n\tcase unsafe.Pointer(stm32.I2C1):\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C1EN)\n\tcase unsafe.Pointer(stm32.SPI1):\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SPI1EN)\n\tcase unsafe.Pointer(stm32.ADC1):\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_ADC1EN)\n\tdefault:\n\t\tpanic(\"machine: unknown peripheral\")\n\t}\n}\n\nfunc (p Pin) registerInterrupt() interrupt.Interrupt {\n\tpin := uint8(p) % 16\n\n\tswitch pin {\n\tcase 0:\n\t\treturn interrupt.New(stm32.IRQ_EXTI0, func(interrupt.Interrupt) { handlePinInterrupt(0) })\n\tcase 1:\n\t\treturn interrupt.New(stm32.IRQ_EXTI1, func(interrupt.Interrupt) { handlePinInterrupt(1) })\n\tcase 2:\n\t\treturn interrupt.New(stm32.IRQ_EXTI2, func(interrupt.Interrupt) { handlePinInterrupt(2) })\n\tcase 3:\n\t\treturn interrupt.New(stm32.IRQ_EXTI3, func(interrupt.Interrupt) { handlePinInterrupt(3) })\n\tcase 4:\n\t\treturn interrupt.New(stm32.IRQ_EXTI4, func(interrupt.Interrupt) { handlePinInterrupt(4) })\n\tcase 5:\n\t\treturn interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(5) })\n\tcase 6:\n\t\treturn interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(6) })\n\tcase 7:\n\t\treturn interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(7) })\n\tcase 8:\n\t\treturn interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(8) })\n\tcase 9:\n\t\treturn interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(9) })\n\tcase 10:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(10) })\n\tcase 11:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(11) })\n\tcase 12:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(12) })\n\tcase 13:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(13) })\n\tcase 14:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(14) })\n\tcase 15:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(15) })\n\t}\n\n\treturn interrupt.Interrupt{}\n}\n\n//---------- UART related code\n\n// Configure the TX and RX pins\nfunc (uart *UART) configurePins(config UARTConfig) {\n\n\t// pins\n\tswitch config.TX {\n\tcase UART_ALT_TX_PIN:\n\t\t// use alternate TX/RX pins via AFIO mapping\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_AFIOEN)\n\t\tif uart.Bus == stm32.USART1 {\n\t\t\tstm32.AFIO.MAPR.SetBits(stm32.AFIO_MAPR_USART1_REMAP)\n\t\t} else if uart.Bus == stm32.USART2 {\n\t\t\tstm32.AFIO.MAPR.SetBits(stm32.AFIO_MAPR_USART2_REMAP)\n\t\t}\n\tdefault:\n\t\t// use standard TX/RX pins PA9 and PA10\n\t}\n\tconfig.TX.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltPushPull})\n\tconfig.RX.Configure(PinConfig{Mode: PinInputModeFloating})\n}\n\n// Determine the divisor for USARTs to get the given baudrate\nfunc (uart *UART) getBaudRateDivisor(br uint32) uint32 {\n\n\t// Note: PCLK2 (from APB2) used for USART1 and PCLK1 for USART2, 3, 4, 5\n\tvar divider uint32\n\tif uart.Bus == stm32.USART1 {\n\t\t// first divide by PCLK2 prescaler (div 1) and then desired baudrate\n\t\tdivider = CPUFrequency() / br\n\t} else {\n\t\t// first divide by PCLK1 prescaler (div 2) and then desired baudrate\n\t\tdivider = CPUFrequency() / 2 / br\n\t}\n\treturn divider\n}\n\n// Register names vary by ST processor, these are for STM F103xx\nfunc (uart *UART) setRegisters() {\n\tuart.rxReg = &uart.Bus.DR\n\tuart.txReg = &uart.Bus.DR\n\tuart.statusReg = &uart.Bus.SR\n\tuart.txEmptyFlag = stm32.USART_SR_TXE\n}\n\n//---------- SPI related types and code\n\ntype SPI struct {\n\tBus *stm32.SPI_Type\n}\n\n// There are 3 SPI interfaces on the STM32F103xx.\n// Since the first interface is named SPI1, both SPI0 and SPI1 refer to SPI1.\n// TODO: implement SPI2 and SPI3.\nvar (\n\tSPI1 = &SPI{Bus: stm32.SPI1}\n\tSPI0 = SPI1\n)\n\nfunc (spi *SPI) config8Bits() {\n\t// no-op on this series\n}\n\n// Set baud rate for SPI\nfunc (spi *SPI) getBaudRate(config SPIConfig) uint32 {\n\tvar conf uint32\n\n\t// set frequency dependent on PCLK2 prescaler (div 1)\n\tswitch {\n\tcase config.Frequency < 125000:\n\t\t// Note: impossible to achieve lower frequency with current PCLK2!\n\t\tconf |= stm32.SPI_CR1_BR_Div256\n\tcase config.Frequency < 250000:\n\t\tconf |= stm32.SPI_CR1_BR_Div256\n\tcase config.Frequency < 500000:\n\t\tconf |= stm32.SPI_CR1_BR_Div128\n\tcase config.Frequency < 1000000:\n\t\tconf |= stm32.SPI_CR1_BR_Div64\n\tcase config.Frequency < 2000000:\n\t\tconf |= stm32.SPI_CR1_BR_Div32\n\tcase config.Frequency < 4000000:\n\t\tconf |= stm32.SPI_CR1_BR_Div16\n\tdefault:\n\t\t// When its bigger than Div16, just round to the maximum frequency.\n\t\tconf |= stm32.SPI_CR1_BR_Div8\n\t}\n\treturn conf << stm32.SPI_CR1_BR_Pos\n}\n\n// Configure SPI pins for input output and clock\nfunc (spi *SPI) configurePins(config SPIConfig) {\n\tconfig.SCK.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltPushPull})\n\tconfig.SDO.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltPushPull})\n\tconfig.SDI.Configure(PinConfig{Mode: PinInputModeFloating})\n}\n\n//---------- I2C related types and code\n\n// There are 2 I2C interfaces on the STM32F103xx.\n// Since the first interface is named I2C1, both I2C0 and I2C1 refer to I2C1.\n// TODO: implement I2C2.\n\ntype I2C struct {\n\tBus *stm32.I2C_Type\n}\n\nvar (\n\tI2C1 = &I2C{Bus: stm32.I2C1}\n\tI2C0 = I2C1\n)\n\nfunc (i2c *I2C) configurePins(config I2CConfig) {\n\tif config.SDA == PB9 {\n\t\t// use alternate I2C1 pins PB8/PB9 via AFIO mapping\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_AFIOEN)\n\t\tstm32.AFIO.MAPR.SetBits(stm32.AFIO_MAPR_I2C1_REMAP)\n\t}\n\n\tconfig.SDA.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltOpenDrain})\n\tconfig.SCL.Configure(PinConfig{Mode: PinOutput50MHz + PinOutputModeAltOpenDrain})\n}\n\nfunc (i2c *I2C) getFreqRange(config I2CConfig) uint32 {\n\t// pclk1 clock speed is main frequency divided by PCLK1 prescaler (div 2)\n\tpclk1 := CPUFrequency() / 2\n\n\t// set frequency range to PCLK1 clock speed in MHz\n\t// aka setting the value 36 means to use 36 MHz clock\n\treturn pclk1 / 1000000\n}\n\nfunc (i2c *I2C) getRiseTime(config I2CConfig) uint32 {\n\t// These bits must be programmed with the maximum SCL rise time given in the\n\t// I2C bus specification, incremented by 1.\n\t// For instance: in Sm mode, the maximum allowed SCL rise time is 1000 ns.\n\t// If, in the I2C_CR2 register, the value of FREQ[5:0] bits is equal to 0x08\n\t// and PCLK1 = 125 ns, therefore the TRISE[5:0] bits must be programmed with\n\t// 09h (1000 ns / 125 ns = 8 + 1)\n\tfreqRange := i2c.getFreqRange(config)\n\tif config.Frequency > 100000 {\n\t\t// fast mode (Fm) adjustment\n\t\tfreqRange *= 300\n\t\tfreqRange /= 1000\n\t}\n\treturn (freqRange + 1) << stm32.I2C_TRISE_TRISE_Pos\n}\n\nfunc (i2c *I2C) getSpeed(config I2CConfig) uint32 {\n\tccr := func(pclk uint32, freq uint32, coeff uint32) uint32 {\n\t\treturn (((pclk - 1) / (freq * coeff)) + 1) & stm32.I2C_CCR_CCR_Msk\n\t}\n\tsm := func(pclk uint32, freq uint32) uint32 { // standard mode (Sm)\n\t\tif s := ccr(pclk, freq, 2); s < 4 {\n\t\t\treturn 4\n\t\t} else {\n\t\t\treturn s\n\t\t}\n\t}\n\tfm := func(pclk uint32, freq uint32, duty uint8) uint32 { // fast mode (Fm)\n\t\tif duty == DutyCycle2 {\n\t\t\treturn ccr(pclk, freq, 3)\n\t\t} else {\n\t\t\treturn ccr(pclk, freq, 25) | stm32.I2C_CCR_DUTY\n\t\t}\n\t}\n\tclock := CPUFrequency() / 2\n\tif config.Frequency <= 100000 {\n\t\treturn sm(clock, config.Frequency)\n\t} else {\n\t\ts := fm(clock, config.Frequency, config.DutyCycle)\n\t\tif (s & stm32.I2C_CCR_CCR_Msk) == 0 {\n\t\t\treturn 1\n\t\t} else {\n\t\t\treturn s | stm32.I2C_CCR_F_S\n\t\t}\n\t}\n}\n\n//---------- Timer related code\n\n// For Pin Mappings see RM0008, pg 179\n// https://www.st.com/resource/en/reference_manual/cd00171190-stm32f101xx-stm32f102xx-stm32f103xx-stm32f105xx-and-stm32f107xx-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf\n//\n// Note: for STM32F1 series the pin mapping is done 'per timer' not per channel,\n// not all channels on a timer have the same degrees of flexibility, and some\n// combinations are only available on some packages - so care is needed at app\n// level to ensure valid combinations of pins are used.\n//\n\nvar (\n\tTIM1 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM1EN,\n\t\tDevice:         stm32.TIM1,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PE9, 0b11}, {PA8, 0b00}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PE11, 0b11}, {PA9, 0b00}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PE13, 0b11}, {PA10, 0b00}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PE14, 0b11}, {PA11, 0b00}}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n\n\tTIM2 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM2EN,\n\t\tDevice:         stm32.TIM2,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PA0, 0b00}, {PA15, 0b01}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA1, 0b00}, {PB3, 0b01}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA2, 0b00}, {PB10, 0b10}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA3, 0b00}, {PB11, 0b10}}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM3 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM3EN,\n\t\tDevice:         stm32.TIM3,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PA6, 0b00}, {PC6, 0b11}, {PB4, 0b10}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA7, 0b00}, {PC7, 0b11}, {PB5, 0b10}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PB0, 0b00}, {PC8, 0b11}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PB1, 0b00}, {PC9, 0b11}}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM4 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM4EN,\n\t\tDevice:         stm32.TIM4,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PD12, 0b1}, {PB6, 0}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PD13, 0b1}, {PB7, 0}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PD14, 0b1}, {PB8, 0}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PD15, 0b1}, {PB9, 0}}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM5 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM5EN,\n\t\tDevice:         stm32.TIM5,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA3, 0b0}}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM6 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM6EN,\n\t\tDevice:         stm32.TIM6,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM7 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM7EN,\n\t\tDevice:         stm32.TIM7,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM8 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM8EN,\n\t\tDevice:         stm32.TIM8,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n\n\tTIM9 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM9EN,\n\t\tDevice:         stm32.TIM9,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PA2, 0b0}, {PE5, 0b1}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA3, 0b0}, {PE6, 0b1}}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n\n\tTIM10 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM10EN,\n\t\tDevice:         stm32.TIM10,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PB8, 0b0}, {PF6, 0b1}}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n\n\tTIM11 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM11EN,\n\t\tDevice:         stm32.TIM11,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PB9, 0b0}, {PF7, 0b1}}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n\n\tTIM12 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM12EN,\n\t\tDevice:         stm32.TIM12,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{}}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM13 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM13EN,\n\t\tDevice:         stm32.TIM13,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PA6, 0b0}, {PF8, 0b1}}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM14 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM14EN,\n\t\tDevice:         stm32.TIM14,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PA7, 0b0}, {PF9, 0b1}}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n)\n\nfunc (t *TIM) registerUPInterrupt() interrupt.Interrupt {\n\tswitch t {\n\tcase &TIM1:\n\t\treturn interrupt.New(stm32.IRQ_TIM1_UP, TIM1.handleUPInterrupt)\n\tcase &TIM2:\n\t\treturn interrupt.New(stm32.IRQ_TIM2, TIM2.handleUPInterrupt)\n\tcase &TIM3:\n\t\treturn interrupt.New(stm32.IRQ_TIM3, TIM3.handleUPInterrupt)\n\tcase &TIM4:\n\t\treturn interrupt.New(stm32.IRQ_TIM4, TIM4.handleUPInterrupt)\n\tcase &TIM5:\n\t\treturn interrupt.New(stm32.IRQ_TIM5, TIM5.handleUPInterrupt)\n\tcase &TIM6:\n\t\treturn interrupt.New(stm32.IRQ_TIM6, TIM6.handleUPInterrupt)\n\tcase &TIM7:\n\t\treturn interrupt.New(stm32.IRQ_TIM7, TIM7.handleUPInterrupt)\n\tcase &TIM8:\n\t\treturn interrupt.New(stm32.IRQ_TIM8_UP, TIM8.handleUPInterrupt)\n\t}\n\n\treturn interrupt.Interrupt{}\n}\n\nfunc (t *TIM) registerOCInterrupt() interrupt.Interrupt {\n\tswitch t {\n\tcase &TIM1:\n\t\treturn interrupt.New(stm32.IRQ_TIM1_CC, TIM1.handleOCInterrupt)\n\tcase &TIM2:\n\t\treturn interrupt.New(stm32.IRQ_TIM2, TIM2.handleOCInterrupt)\n\tcase &TIM3:\n\t\treturn interrupt.New(stm32.IRQ_TIM3, TIM3.handleOCInterrupt)\n\tcase &TIM4:\n\t\treturn interrupt.New(stm32.IRQ_TIM4, TIM4.handleOCInterrupt)\n\tcase &TIM5:\n\t\treturn interrupt.New(stm32.IRQ_TIM5, TIM5.handleOCInterrupt)\n\tcase &TIM6:\n\t\treturn interrupt.New(stm32.IRQ_TIM6, TIM6.handleOCInterrupt)\n\tcase &TIM7:\n\t\treturn interrupt.New(stm32.IRQ_TIM7, TIM7.handleOCInterrupt)\n\tcase &TIM8:\n\t\treturn interrupt.New(stm32.IRQ_TIM8_CC, TIM8.handleOCInterrupt)\n\t}\n\n\treturn interrupt.Interrupt{}\n}\n\nfunc (t *TIM) configurePin(channel uint8, pf PinFunction) {\n\tremap := uint32(pf.AltFunc)\n\n\tswitch t {\n\tcase &TIM1:\n\t\tstm32.AFIO.MAPR.ReplaceBits(remap<<stm32.AFIO_MAPR_TIM1_REMAP_Pos, stm32.AFIO_MAPR_TIM1_REMAP_Msk, 0)\n\tcase &TIM2:\n\t\tstm32.AFIO.MAPR.ReplaceBits(remap<<stm32.AFIO_MAPR_TIM2_REMAP_Pos, stm32.AFIO_MAPR_TIM2_REMAP_Msk, 0)\n\tcase &TIM3:\n\t\tstm32.AFIO.MAPR.ReplaceBits(remap<<stm32.AFIO_MAPR_TIM3_REMAP_Pos, stm32.AFIO_MAPR_TIM3_REMAP_Msk, 0)\n\tcase &TIM4:\n\t\tstm32.AFIO.MAPR.ReplaceBits(remap<<stm32.AFIO_MAPR_TIM4_REMAP_Pos, stm32.AFIO_MAPR_TIM4_REMAP_Msk, 0)\n\tcase &TIM5:\n\t\tstm32.AFIO.MAPR.ReplaceBits(remap<<stm32.AFIO_MAPR_TIM5CH4_IREMAP_Pos, stm32.AFIO_MAPR_TIM5CH4_IREMAP_Msk, 0)\n\tcase &TIM9:\n\t\tstm32.AFIO.MAPR.ReplaceBits(remap<<stm32.AFIO_MAPR2_TIM9_REMAP_Pos, stm32.AFIO_MAPR2_TIM9_REMAP_Msk, 0)\n\tcase &TIM10:\n\t\tstm32.AFIO.MAPR.ReplaceBits(remap<<stm32.AFIO_MAPR2_TIM10_REMAP_Pos, stm32.AFIO_MAPR2_TIM10_REMAP_Msk, 0)\n\tcase &TIM11:\n\t\tstm32.AFIO.MAPR.ReplaceBits(remap<<stm32.AFIO_MAPR2_TIM11_REMAP_Pos, stm32.AFIO_MAPR2_TIM11_REMAP_Msk, 0)\n\tcase &TIM13:\n\t\tstm32.AFIO.MAPR.ReplaceBits(remap<<stm32.AFIO_MAPR2_TIM13_REMAP_Pos, stm32.AFIO_MAPR2_TIM13_REMAP_Msk, 0)\n\tcase &TIM14:\n\t\tstm32.AFIO.MAPR.ReplaceBits(remap<<stm32.AFIO_MAPR2_TIM14_REMAP_Pos, stm32.AFIO_MAPR2_TIM14_REMAP_Msk, 0)\n\t}\n\n\tpf.Pin.Configure(PinConfig{Mode: PinOutput + PinOutputModeAltPushPull})\n}\n\nfunc (t *TIM) enableMainOutput() {\n\tt.Device.BDTR.SetBits(stm32.TIM_BDTR_MOE)\n}\n\ntype arrtype = uint32\ntype arrRegType = volatile.Register32\n\nconst (\n\tARR_MAX = 0x10000\n\tPSC_MAX = 0x10000\n)\n"
  },
  {
    "path": "src/machine/machine_stm32f4.go",
    "content": "//go:build stm32f4\n\npackage machine\n\n// Peripheral abstraction layer for the stm32f4\n\nimport (\n\t\"device/stm32\"\n\t\"errors\"\n\t\"internal/binary\"\n\t\"math/bits\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nvar deviceIDAddr = []uintptr{0x1FFF7A10, 0x1FFF7A14, 0x1FFF7A18}\n\nconst (\n\tPA0  = portA + 0\n\tPA1  = portA + 1\n\tPA2  = portA + 2\n\tPA3  = portA + 3\n\tPA4  = portA + 4\n\tPA5  = portA + 5\n\tPA6  = portA + 6\n\tPA7  = portA + 7\n\tPA8  = portA + 8\n\tPA9  = portA + 9\n\tPA10 = portA + 10\n\tPA11 = portA + 11\n\tPA12 = portA + 12\n\tPA13 = portA + 13\n\tPA14 = portA + 14\n\tPA15 = portA + 15\n\n\tPB0  = portB + 0\n\tPB1  = portB + 1\n\tPB2  = portB + 2\n\tPB3  = portB + 3\n\tPB4  = portB + 4\n\tPB5  = portB + 5\n\tPB6  = portB + 6\n\tPB7  = portB + 7\n\tPB8  = portB + 8\n\tPB9  = portB + 9\n\tPB10 = portB + 10\n\tPB11 = portB + 11\n\tPB12 = portB + 12\n\tPB13 = portB + 13\n\tPB14 = portB + 14\n\tPB15 = portB + 15\n\n\tPC0  = portC + 0\n\tPC1  = portC + 1\n\tPC2  = portC + 2\n\tPC3  = portC + 3\n\tPC4  = portC + 4\n\tPC5  = portC + 5\n\tPC6  = portC + 6\n\tPC7  = portC + 7\n\tPC8  = portC + 8\n\tPC9  = portC + 9\n\tPC10 = portC + 10\n\tPC11 = portC + 11\n\tPC12 = portC + 12\n\tPC13 = portC + 13\n\tPC14 = portC + 14\n\tPC15 = portC + 15\n\n\tPD0  = portD + 0\n\tPD1  = portD + 1\n\tPD2  = portD + 2\n\tPD3  = portD + 3\n\tPD4  = portD + 4\n\tPD5  = portD + 5\n\tPD6  = portD + 6\n\tPD7  = portD + 7\n\tPD8  = portD + 8\n\tPD9  = portD + 9\n\tPD10 = portD + 10\n\tPD11 = portD + 11\n\tPD12 = portD + 12\n\tPD13 = portD + 13\n\tPD14 = portD + 14\n\tPD15 = portD + 15\n\n\tPE0  = portE + 0\n\tPE1  = portE + 1\n\tPE2  = portE + 2\n\tPE3  = portE + 3\n\tPE4  = portE + 4\n\tPE5  = portE + 5\n\tPE6  = portE + 6\n\tPE7  = portE + 7\n\tPE8  = portE + 8\n\tPE9  = portE + 9\n\tPE10 = portE + 10\n\tPE11 = portE + 11\n\tPE12 = portE + 12\n\tPE13 = portE + 13\n\tPE14 = portE + 14\n\tPE15 = portE + 15\n\n\tPF0  = portF + 0\n\tPF1  = portF + 1\n\tPF2  = portF + 2\n\tPF3  = portF + 3\n\tPF4  = portF + 4\n\tPF5  = portF + 5\n\tPF6  = portF + 6\n\tPF7  = portF + 7\n\tPF8  = portF + 8\n\tPF9  = portF + 9\n\tPF10 = portF + 10\n\tPF11 = portF + 11\n\tPF12 = portF + 12\n\tPF13 = portF + 13\n\tPF14 = portF + 14\n\tPF15 = portF + 15\n\n\tPG0  = portG + 0\n\tPG1  = portG + 1\n\tPG2  = portG + 2\n\tPG3  = portG + 3\n\tPG4  = portG + 4\n\tPG5  = portG + 5\n\tPG6  = portG + 6\n\tPG7  = portG + 7\n\tPG8  = portG + 8\n\tPG9  = portG + 9\n\tPG10 = portG + 10\n\tPG11 = portG + 11\n\tPG12 = portG + 12\n\tPG13 = portG + 13\n\tPG14 = portG + 14\n\tPG15 = portG + 15\n\n\tPH0  = portH + 0\n\tPH1  = portH + 1\n\tPH2  = portH + 2\n\tPH3  = portH + 3\n\tPH4  = portH + 4\n\tPH5  = portH + 5\n\tPH6  = portH + 6\n\tPH7  = portH + 7\n\tPH8  = portH + 8\n\tPH9  = portH + 9\n\tPH10 = portH + 10\n\tPH11 = portH + 11\n\tPH12 = portH + 12\n\tPH13 = portH + 13\n\tPH14 = portH + 14\n\tPH15 = portH + 15\n\n\tPI0  = portI + 0\n\tPI1  = portI + 1\n\tPI2  = portI + 2\n\tPI3  = portI + 3\n\tPI4  = portI + 4\n\tPI5  = portI + 5\n\tPI6  = portI + 6\n\tPI7  = portI + 7\n\tPI8  = portI + 8\n\tPI9  = portI + 9\n\tPI10 = portI + 10\n\tPI11 = portI + 11\n\tPI12 = portI + 12\n\tPI13 = portI + 13\n\tPI14 = portI + 14\n\tPI15 = portI + 15\n\n\tPK0  = portK + 0\n\tPK1  = portK + 1\n\tPK2  = portK + 2\n\tPK3  = portK + 3\n\tPK4  = portK + 4\n\tPK5  = portK + 5\n\tPK6  = portK + 6\n\tPK7  = portK + 7\n\tPK8  = portK + 8\n\tPK9  = portK + 9\n\tPK10 = portK + 10\n\tPK11 = portK + 11\n\tPK12 = portK + 12\n\tPK13 = portK + 13\n\tPK14 = portK + 14\n\tPK15 = portK + 15\n)\n\nfunc (p Pin) getPort() *stm32.GPIO_Type {\n\tswitch p / 16 {\n\tcase 0:\n\t\treturn stm32.GPIOA\n\tcase 1:\n\t\treturn stm32.GPIOB\n\tcase 2:\n\t\treturn stm32.GPIOC\n\tcase 3:\n\t\treturn stm32.GPIOD\n\tcase 4:\n\t\treturn stm32.GPIOE\n\tcase 5:\n\t\treturn stm32.GPIOF\n\tcase 6:\n\t\treturn stm32.GPIOG\n\tcase 7:\n\t\treturn stm32.GPIOH\n\tcase 8:\n\t\treturn stm32.GPIOI\n\tcase 9:\n\t\treturn stm32.GPIOJ\n\tcase 10:\n\t\treturn stm32.GPIOK\n\tdefault:\n\t\tpanic(\"machine: unknown port\")\n\t}\n}\n\n// enableClock enables the clock for this desired GPIO port.\nfunc (p Pin) enableClock() {\n\tbit := p / 16\n\tif 0 <= bit && bit <= 10 {\n\t\tstm32.RCC.AHB1ENR.SetBits(0b1 << bit)\n\t} else {\n\t\tpanic(\"machine: unknown port\")\n\t}\n}\n\nfunc (p Pin) registerInterrupt() interrupt.Interrupt {\n\tpin := uint8(p) % 16\n\n\tswitch pin {\n\tcase 0:\n\t\treturn interrupt.New(stm32.IRQ_EXTI0, func(interrupt.Interrupt) { handlePinInterrupt(0) })\n\tcase 1:\n\t\treturn interrupt.New(stm32.IRQ_EXTI1, func(interrupt.Interrupt) { handlePinInterrupt(1) })\n\tcase 2:\n\t\treturn interrupt.New(stm32.IRQ_EXTI2, func(interrupt.Interrupt) { handlePinInterrupt(2) })\n\tcase 3:\n\t\treturn interrupt.New(stm32.IRQ_EXTI3, func(interrupt.Interrupt) { handlePinInterrupt(3) })\n\tcase 4:\n\t\treturn interrupt.New(stm32.IRQ_EXTI4, func(interrupt.Interrupt) { handlePinInterrupt(4) })\n\tcase 5:\n\t\treturn interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(5) })\n\tcase 6:\n\t\treturn interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(6) })\n\tcase 7:\n\t\treturn interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(7) })\n\tcase 8:\n\t\treturn interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(8) })\n\tcase 9:\n\t\treturn interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(9) })\n\tcase 10:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(10) })\n\tcase 11:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(11) })\n\tcase 12:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(12) })\n\tcase 13:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(13) })\n\tcase 14:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(14) })\n\tcase 15:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(15) })\n\t}\n\n\treturn interrupt.Interrupt{}\n}\n\n// Enable peripheral clock\nfunc enableAltFuncClock(bus unsafe.Pointer) {\n\tswitch bus {\n\tcase unsafe.Pointer(stm32.DAC): // DAC interface clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_DACEN)\n\tcase unsafe.Pointer(stm32.PWR): // Power interface clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN)\n\tcase unsafe.Pointer(stm32.CAN2): // CAN 2 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_CAN2EN)\n\tcase unsafe.Pointer(stm32.CAN1): // CAN 1 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_CAN1EN)\n\tcase unsafe.Pointer(stm32.I2C3): // I2C3 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C3EN)\n\tcase unsafe.Pointer(stm32.I2C2): // I2C2 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C2EN)\n\tcase unsafe.Pointer(stm32.I2C1): // I2C1 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C1EN)\n\tcase unsafe.Pointer(stm32.UART5): // UART5 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_UART5EN)\n\tcase unsafe.Pointer(stm32.UART4): // UART4 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_UART4EN)\n\tcase unsafe.Pointer(stm32.USART3): // USART3 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART3EN)\n\tcase unsafe.Pointer(stm32.USART2): // USART2 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART2EN)\n\tcase unsafe.Pointer(stm32.SPI3): // SPI3 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_SPI3EN)\n\tcase unsafe.Pointer(stm32.SPI2): // SPI2 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_SPI2EN)\n\tcase unsafe.Pointer(stm32.WWDG): // Window watchdog clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_WWDGEN)\n\tcase unsafe.Pointer(stm32.TIM14): // TIM14 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM14EN)\n\tcase unsafe.Pointer(stm32.TIM13): // TIM13 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM13EN)\n\tcase unsafe.Pointer(stm32.TIM12): // TIM12 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM12EN)\n\tcase unsafe.Pointer(stm32.TIM7): // TIM7 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM7EN)\n\tcase unsafe.Pointer(stm32.TIM6): // TIM6 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM6EN)\n\tcase unsafe.Pointer(stm32.TIM5): // TIM5 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM5EN)\n\tcase unsafe.Pointer(stm32.TIM4): // TIM4 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM4EN)\n\tcase unsafe.Pointer(stm32.TIM3): // TIM3 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM3EN)\n\tcase unsafe.Pointer(stm32.TIM2): // TIM2 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM2EN)\n\tcase unsafe.Pointer(stm32.TIM11): // TIM11 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM11EN)\n\tcase unsafe.Pointer(stm32.TIM10): // TIM10 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM10EN)\n\tcase unsafe.Pointer(stm32.TIM9): // TIM9 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM9EN)\n\tcase unsafe.Pointer(stm32.SYSCFG): // System configuration controller clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SYSCFGEN)\n\tcase unsafe.Pointer(stm32.SPI1): // SPI1 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SPI1EN)\n\tcase unsafe.Pointer(stm32.SDIO): // SDIO clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SDIOEN)\n\tcase unsafe.Pointer(stm32.ADC3): // ADC3 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_ADC3EN)\n\tcase unsafe.Pointer(stm32.ADC2): // ADC2 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_ADC2EN)\n\tcase unsafe.Pointer(stm32.ADC1): // ADC1 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_ADC1EN)\n\tcase unsafe.Pointer(stm32.USART6): // USART6 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART6EN)\n\tcase unsafe.Pointer(stm32.USART1): // USART1 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART1EN)\n\tcase unsafe.Pointer(stm32.TIM8): // TIM8 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM8EN)\n\tcase unsafe.Pointer(stm32.TIM1): // TIM1 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM1EN)\n\t}\n}\n\n//---------- Timer related code\n\nvar (\n\tTIM1 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM1EN,\n\t\tDevice:         stm32.TIM1,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PA8, AF1_TIM1_2}, {PE9, AF1_TIM1_2}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA9, AF1_TIM1_2}, {PE11, AF1_TIM1_2}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA10, AF1_TIM1_2}, {PE13, AF1_TIM1_2}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA11, AF1_TIM1_2}, {PE14, AF1_TIM1_2}}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n\n\tTIM2 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM2EN,\n\t\tDevice:         stm32.TIM2,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PA0, AF1_TIM1_2}, {PA5, AF1_TIM1_2}, {PA15, AF1_TIM1_2}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA1, AF1_TIM1_2}, {PB3, AF1_TIM1_2}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA2, AF1_TIM1_2}, {PB10, AF1_TIM1_2}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA3, AF1_TIM1_2}, {PB11, AF1_TIM1_2}}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM3 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM3EN,\n\t\tDevice:         stm32.TIM3,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PA6, AF2_TIM3_4_5}, {PB4, AF2_TIM3_4_5}, {PC6, AF2_TIM3_4_5}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA7, AF2_TIM3_4_5}, {PB5, AF2_TIM3_4_5}, {PC7, AF2_TIM3_4_5}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PB0, AF2_TIM3_4_5}, {PC8, AF2_TIM3_4_5}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PB1, AF2_TIM3_4_5}, {PC9, AF2_TIM3_4_5}}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM4 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM4EN,\n\t\tDevice:         stm32.TIM4,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PB6, AF2_TIM3_4_5}, {PD12, AF2_TIM3_4_5}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PB7, AF2_TIM3_4_5}, {PD13, AF2_TIM3_4_5}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PB8, AF2_TIM3_4_5}, {PD14, AF2_TIM3_4_5}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PB9, AF2_TIM3_4_5}, {PD15, AF2_TIM3_4_5}}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM5 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM5EN,\n\t\tDevice:         stm32.TIM5,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PH10, AF2_TIM3_4_5}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PH11, AF2_TIM3_4_5}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PH12, AF2_TIM3_4_5}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PI0, AF2_TIM3_4_5}}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM6 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM6EN,\n\t\tDevice:         stm32.TIM6,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM7 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM7EN,\n\t\tDevice:         stm32.TIM7,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM8 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM8EN,\n\t\tDevice:         stm32.TIM8,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PC6, AF3_TIM8_9_10_11}, {PI5, AF3_TIM8_9_10_11}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PC7, AF3_TIM8_9_10_11}, {PI6, AF3_TIM8_9_10_11}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PC8, AF3_TIM8_9_10_11}, {PI7, AF3_TIM8_9_10_11}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PC9, AF3_TIM8_9_10_11}, {PI2, AF3_TIM8_9_10_11}}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n\n\tTIM9 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM9EN,\n\t\tDevice:         stm32.TIM9,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PA2, AF3_TIM8_9_10_11}, {PE5, AF3_TIM8_9_10_11}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA3, AF3_TIM8_9_10_11}, {PE6, AF3_TIM8_9_10_11}}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n\n\tTIM10 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM10EN,\n\t\tDevice:         stm32.TIM10,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PB8, AF3_TIM8_9_10_11}, {PF6, AF3_TIM8_9_10_11}}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n\n\tTIM11 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM11EN,\n\t\tDevice:         stm32.TIM11,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PB9, AF3_TIM8_9_10_11}, {PF7, AF3_TIM8_9_10_11}}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n\n\tTIM12 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM12EN,\n\t\tDevice:         stm32.TIM12,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PB14, AF9_CAN1_CAN2_TIM12_13_14}, {PH6, AF9_CAN1_CAN2_TIM12_13_14}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PB15, AF9_CAN1_CAN2_TIM12_13_14}, {PH9, AF9_CAN1_CAN2_TIM12_13_14}}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM13 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM13EN,\n\t\tDevice:         stm32.TIM13,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PA6, AF9_CAN1_CAN2_TIM12_13_14}, {PF8, AF9_CAN1_CAN2_TIM12_13_14}}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM14 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM14EN,\n\t\tDevice:         stm32.TIM14,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PA7, AF9_CAN1_CAN2_TIM12_13_14}, {PF9, AF9_CAN1_CAN2_TIM12_13_14}}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n)\n\nfunc (t *TIM) registerUPInterrupt() interrupt.Interrupt {\n\tswitch t {\n\tcase &TIM1:\n\t\treturn interrupt.New(stm32.IRQ_TIM1_UP_TIM10, TIM1.handleUPInterrupt)\n\tcase &TIM2:\n\t\treturn interrupt.New(stm32.IRQ_TIM2, TIM2.handleUPInterrupt)\n\tcase &TIM3:\n\t\treturn interrupt.New(stm32.IRQ_TIM3, TIM3.handleUPInterrupt)\n\tcase &TIM4:\n\t\treturn interrupt.New(stm32.IRQ_TIM4, TIM4.handleUPInterrupt)\n\tcase &TIM5:\n\t\treturn interrupt.New(stm32.IRQ_TIM5, TIM5.handleUPInterrupt)\n\tcase &TIM6:\n\t\treturn interrupt.New(stm32.IRQ_TIM6_DAC, TIM6.handleUPInterrupt)\n\tcase &TIM7:\n\t\treturn interrupt.New(stm32.IRQ_TIM7, TIM7.handleUPInterrupt)\n\tcase &TIM8:\n\t\treturn interrupt.New(stm32.IRQ_TIM8_UP_TIM13, TIM8.handleUPInterrupt)\n\tcase &TIM9:\n\t\treturn interrupt.New(stm32.IRQ_TIM1_BRK_TIM9, TIM9.handleUPInterrupt)\n\tcase &TIM10:\n\t\treturn interrupt.New(stm32.IRQ_TIM1_UP_TIM10, TIM10.handleUPInterrupt)\n\tcase &TIM11:\n\t\treturn interrupt.New(stm32.IRQ_TIM1_TRG_COM_TIM11, TIM11.handleUPInterrupt)\n\tcase &TIM12:\n\t\treturn interrupt.New(stm32.IRQ_TIM8_BRK_TIM12, TIM12.handleUPInterrupt)\n\tcase &TIM13:\n\t\treturn interrupt.New(stm32.IRQ_TIM8_UP_TIM13, TIM13.handleUPInterrupt)\n\tcase &TIM14:\n\t\treturn interrupt.New(stm32.IRQ_TIM8_TRG_COM_TIM14, TIM14.handleUPInterrupt)\n\t}\n\n\treturn interrupt.Interrupt{}\n}\n\nfunc (t *TIM) registerOCInterrupt() interrupt.Interrupt {\n\tswitch t {\n\tcase &TIM1:\n\t\treturn interrupt.New(stm32.IRQ_TIM1_CC, TIM1.handleOCInterrupt)\n\tcase &TIM2:\n\t\treturn interrupt.New(stm32.IRQ_TIM2, TIM2.handleOCInterrupt)\n\tcase &TIM3:\n\t\treturn interrupt.New(stm32.IRQ_TIM3, TIM3.handleOCInterrupt)\n\tcase &TIM4:\n\t\treturn interrupt.New(stm32.IRQ_TIM4, TIM4.handleOCInterrupt)\n\tcase &TIM5:\n\t\treturn interrupt.New(stm32.IRQ_TIM5, TIM5.handleOCInterrupt)\n\tcase &TIM6:\n\t\treturn interrupt.New(stm32.IRQ_TIM6_DAC, TIM6.handleOCInterrupt)\n\tcase &TIM7:\n\t\treturn interrupt.New(stm32.IRQ_TIM7, TIM7.handleOCInterrupt)\n\tcase &TIM8:\n\t\treturn interrupt.New(stm32.IRQ_TIM8_UP_TIM13, TIM8.handleOCInterrupt)\n\tcase &TIM9:\n\t\treturn interrupt.New(stm32.IRQ_TIM1_BRK_TIM9, TIM9.handleOCInterrupt)\n\tcase &TIM10:\n\t\treturn interrupt.New(stm32.IRQ_TIM1_UP_TIM10, TIM10.handleOCInterrupt)\n\tcase &TIM11:\n\t\treturn interrupt.New(stm32.IRQ_TIM1_TRG_COM_TIM11, TIM11.handleOCInterrupt)\n\tcase &TIM12:\n\t\treturn interrupt.New(stm32.IRQ_TIM8_BRK_TIM12, TIM12.handleOCInterrupt)\n\tcase &TIM13:\n\t\treturn interrupt.New(stm32.IRQ_TIM8_UP_TIM13, TIM13.handleOCInterrupt)\n\tcase &TIM14:\n\t\treturn interrupt.New(stm32.IRQ_TIM8_TRG_COM_TIM14, TIM14.handleOCInterrupt)\n\t}\n\n\treturn interrupt.Interrupt{}\n}\n\nfunc (t *TIM) enableMainOutput() {\n\tt.Device.BDTR.SetBits(stm32.TIM_BDTR_MOE)\n}\n\ntype arrtype = uint32\ntype arrRegType = volatile.Register32\n\nconst (\n\tARR_MAX = 0x10000\n\tPSC_MAX = 0x10000\n)\n\nfunc initRNG() {\n\tstm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_RNGEN)\n\tstm32.RNG.CR.SetBits(stm32.RNG_CR_RNGEN)\n}\n\n// Alternative peripheral pin functions\nconst (\n\tAF0_SYSTEM                = 0\n\tAF1_TIM1_2                = 1\n\tAF2_TIM3_4_5              = 2\n\tAF3_TIM8_9_10_11          = 3\n\tAF4_I2C1_2_3              = 4\n\tAF5_SPI1_SPI2             = 5\n\tAF6_SPI3                  = 6\n\tAF7_USART1_2_3            = 7\n\tAF8_USART4_5_6            = 8\n\tAF9_CAN1_CAN2_TIM12_13_14 = 9\n\tAF10_OTG_FS_OTG_HS        = 10\n\tAF11_ETH                  = 11\n\tAF12_FSMC_SDIO_OTG_HS_1   = 12\n\tAF13_DCMI                 = 13\n\tAF14                      = 14\n\tAF15_EVENTOUT             = 15\n)\n\n// -- UART ---------------------------------------------------------------------\n\nfunc (uart *UART) configurePins(config UARTConfig) {\n\t// enable the alternate functions on the TX and RX pins\n\tconfig.TX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTTX}, uart.TxAltFuncSelector)\n\tconfig.RX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTRX}, uart.RxAltFuncSelector)\n}\n\nfunc (uart *UART) getBaudRateDivisor(baudRate uint32) uint32 {\n\tvar clock uint32\n\tswitch uart.Bus {\n\tcase stm32.USART1, stm32.USART6:\n\t\tclock = CPUFrequency() / 2 // APB2 Frequency\n\tcase stm32.USART2, stm32.USART3, stm32.UART4, stm32.UART5:\n\t\tclock = CPUFrequency() / 4 // APB1 Frequency\n\t}\n\treturn clock / baudRate\n}\n\nfunc (uart *UART) setRegisters() {\n\tuart.rxReg = &uart.Bus.DR\n\tuart.txReg = &uart.Bus.DR\n\tuart.statusReg = &uart.Bus.SR\n\tuart.txEmptyFlag = stm32.USART_SR_TXE\n}\n\n// -- SPI ----------------------------------------------------------------------\n\ntype SPI struct {\n\tBus             *stm32.SPI_Type\n\tAltFuncSelector uint8\n}\n\nfunc (spi *SPI) config8Bits() {\n\t// no-op on this series\n}\n\nfunc (spi *SPI) configurePins(config SPIConfig) {\n\tconfig.SCK.ConfigureAltFunc(PinConfig{Mode: PinModeSPICLK}, spi.AltFuncSelector)\n\tconfig.SDO.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDO}, spi.AltFuncSelector)\n\tconfig.SDI.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDI}, spi.AltFuncSelector)\n}\n\nfunc (spi *SPI) getBaudRate(config SPIConfig) uint32 {\n\tvar clock uint32\n\tswitch spi.Bus {\n\tcase stm32.SPI1:\n\t\tclock = CPUFrequency() / 2\n\tcase stm32.SPI2, stm32.SPI3:\n\t\tclock = CPUFrequency() / 4\n\t}\n\n\t// limit requested frequency to bus frequency and min frequency (DIV256)\n\tfreq := config.Frequency\n\tif min := clock / 256; freq < min {\n\t\tfreq = min\n\t} else if freq > clock {\n\t\tfreq = clock\n\t}\n\n\t// calculate the exact clock divisor (freq=clock/div -> div=clock/freq).\n\t// truncation is fine, since it produces a less-than-or-equal divisor, and\n\t// thus a greater-than-or-equal frequency.\n\t// divisors only come in consecutive powers of 2, so we can use log2 (or,\n\t// equivalently, bits.Len - 1) to convert to respective enum value.\n\tdiv := bits.Len32(clock/freq) - 1\n\n\t// but DIV1 (2^0) is not permitted, as the least divisor is DIV2 (2^1), so\n\t// subtract 1 from the log2 value, keeping a lower bound of 0\n\tif div < 0 {\n\t\tdiv = 0\n\t} else if div > 0 {\n\t\tdiv--\n\t}\n\n\t// finally, shift the enumerated value into position for SPI CR1\n\treturn uint32(div) << stm32.SPI_CR1_BR_Pos\n}\n\n// -- I2C ----------------------------------------------------------------------\n\ntype I2C struct {\n\tBus             *stm32.I2C_Type\n\tAltFuncSelector uint8\n}\n\nfunc (i2c *I2C) configurePins(config I2CConfig) {\n\tconfig.SCL.ConfigureAltFunc(PinConfig{Mode: PinModeI2CSCL}, i2c.AltFuncSelector)\n\tconfig.SDA.ConfigureAltFunc(PinConfig{Mode: PinModeI2CSDA}, i2c.AltFuncSelector)\n}\n\nfunc (i2c *I2C) getFreqRange(config I2CConfig) uint32 {\n\t// all I2C interfaces are on APB1\n\tclock := CPUFrequency() / 4\n\t// convert to MHz\n\tclock /= 1000000\n\t// must be between 2 MHz (or 4 MHz for fast mode (Fm)) and 50 MHz, inclusive\n\tvar min, max uint32 = 2, 50\n\tif config.Frequency > 100000 {\n\t\tmin = 4 // fast mode (Fm)\n\t}\n\tif clock < min {\n\t\tclock = min\n\t} else if clock > max {\n\t\tclock = max\n\t}\n\treturn clock << stm32.I2C_CR2_FREQ_Pos\n}\n\nfunc (i2c *I2C) getRiseTime(config I2CConfig) uint32 {\n\t// These bits must be programmed with the maximum SCL rise time given in the\n\t// I2C bus specification, incremented by 1.\n\t// For instance: in Sm mode, the maximum allowed SCL rise time is 1000 ns.\n\t// If, in the I2C_CR2 register, the value of FREQ[5:0] bits is equal to 0x08\n\t// and PCLK1 = 125 ns, therefore the TRISE[5:0] bits must be programmed with\n\t// 09h (1000 ns / 125 ns = 8 + 1)\n\tfreqRange := i2c.getFreqRange(config)\n\tif config.Frequency > 100000 {\n\t\t// fast mode (Fm) adjustment\n\t\tfreqRange *= 300\n\t\tfreqRange /= 1000\n\t}\n\treturn (freqRange + 1) << stm32.I2C_TRISE_TRISE_Pos\n}\n\nfunc (i2c *I2C) getSpeed(config I2CConfig) uint32 {\n\tccr := func(pclk uint32, freq uint32, coeff uint32) uint32 {\n\t\treturn (((pclk - 1) / (freq * coeff)) + 1) & stm32.I2C_CCR_CCR_Msk\n\t}\n\tsm := func(pclk uint32, freq uint32) uint32 { // standard mode (Sm)\n\t\tif s := ccr(pclk, freq, 2); s < 4 {\n\t\t\treturn 4\n\t\t} else {\n\t\t\treturn s\n\t\t}\n\t}\n\tfm := func(pclk uint32, freq uint32, duty uint8) uint32 { // fast mode (Fm)\n\t\tif duty == DutyCycle2 {\n\t\t\treturn ccr(pclk, freq, 3)\n\t\t} else {\n\t\t\treturn ccr(pclk, freq, 25) | stm32.I2C_CCR_DUTY\n\t\t}\n\t}\n\t// all I2C interfaces are on APB1\n\tclock := CPUFrequency() / 4\n\tif config.Frequency <= 100000 {\n\t\treturn sm(clock, config.Frequency)\n\t} else {\n\t\ts := fm(clock, config.Frequency, config.DutyCycle)\n\t\tif (s & stm32.I2C_CCR_CCR_Msk) == 0 {\n\t\t\treturn 1\n\t\t} else {\n\t\t\treturn s | stm32.I2C_CCR_F_S\n\t\t}\n\t}\n}\n\n//---------- Flash related code\n\n// the block size actually depends on the sector.\n// TODO: handle this correctly for sectors > 3\nconst eraseBlockSizeValue = 16384\n\n// see RM0090 page 75\nfunc sectorNumber(address uintptr) uint32 {\n\tswitch {\n\t// 0x0800 0000 - 0x0800 3FFF\n\tcase address >= 0x08000000 && address <= 0x08003FFF:\n\t\treturn 0\n\t// 0x0800 4000 - 0x0800 7FFF\n\tcase address >= 0x08004000 && address <= 0x08007FFF:\n\t\treturn 1\n\t// 0x0800 8000 - 0x0800 BFFF\n\tcase address >= 0x08008000 && address <= 0x0800BFFF:\n\t\treturn 2\n\t// 0x0800 C000 - 0x0800 FFFF\n\tcase address >= 0x0800C000 && address <= 0x0800FFFF:\n\t\treturn 3\n\t// 0x0801 0000 - 0x0801 FFFF\n\tcase address >= 0x08010000 && address <= 0x0801FFFF:\n\t\treturn 4\n\t// 0x0802 0000 - 0x0803 FFFF\n\tcase address >= 0x08020000 && address <= 0x0803FFFF:\n\t\treturn 5\n\t// 0x0804 0000 - 0x0805 FFFF\n\tcase address >= 0x08040000 && address <= 0x0805FFFF:\n\t\treturn 6\n\tcase address >= 0x08060000 && address <= 0x0807FFFF:\n\t\treturn 7\n\tcase address >= 0x08080000 && address <= 0x0809FFFF:\n\t\treturn 8\n\tcase address >= 0x080A0000 && address <= 0x080BFFFF:\n\t\treturn 9\n\tcase address >= 0x080C0000 && address <= 0x080DFFFF:\n\t\treturn 10\n\tcase address >= 0x080E0000 && address <= 0x080FFFFF:\n\t\treturn 11\n\tdefault:\n\t\treturn 0\n\t}\n}\n\n// calculate sector number from address\n// var sector uint32 = sectorNumber(address)\n\n// see RM0090 page 85\n// eraseBlock at the passed in block number\nfunc eraseBlock(block uint32) error {\n\twaitUntilFlashDone()\n\n\t// clear any previous errors\n\tstm32.FLASH.SR.SetBits(0xF0)\n\n\t// set SER bit\n\tstm32.FLASH.SetCR_SER(1)\n\tdefer stm32.FLASH.SetCR_SER(0)\n\n\t// set the block (aka sector) to be erased\n\tstm32.FLASH.SetCR_SNB(block)\n\tdefer stm32.FLASH.SetCR_SNB(0)\n\n\t// start the page erase\n\tstm32.FLASH.SetCR_STRT(1)\n\n\twaitUntilFlashDone()\n\n\tif err := checkError(); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nconst writeBlockSize = 2\n\n// see RM0090 page 86\n// must write data in word-length\nfunc writeFlashData(address uintptr, data []byte) (int, error) {\n\tif len(data)%writeBlockSize != 0 {\n\t\treturn 0, errFlashInvalidWriteLength\n\t}\n\n\twaitUntilFlashDone()\n\n\t// clear any previous errors\n\tstm32.FLASH.SR.SetBits(0xF0)\n\n\t// set parallelism to x32\n\tstm32.FLASH.SetCR_PSIZE(2)\n\n\tfor i := 0; i < len(data); i += writeBlockSize {\n\t\t// start write operation\n\t\tstm32.FLASH.SetCR_PG(1)\n\n\t\t*(*uint16)(unsafe.Pointer(address)) = binary.LittleEndian.Uint16(data[i : i+writeBlockSize])\n\n\t\twaitUntilFlashDone()\n\n\t\tif err := checkError(); err != nil {\n\t\t\treturn i, err\n\t\t}\n\n\t\t// end write operation\n\t\tstm32.FLASH.SetCR_PG(0)\n\t}\n\n\treturn len(data), nil\n}\n\nfunc waitUntilFlashDone() {\n\tfor stm32.FLASH.GetSR_BSY() != 0 {\n\t}\n}\n\nvar (\n\terrFlashPGS = errors.New(\"errFlashPGS\")\n\terrFlashPGP = errors.New(\"errFlashPGP\")\n\terrFlashPGA = errors.New(\"errFlashPGA\")\n\terrFlashWRP = errors.New(\"errFlashWRP\")\n)\n\nfunc checkError() error {\n\tswitch {\n\tcase stm32.FLASH.GetSR_PGSERR() != 0:\n\t\treturn errFlashPGS\n\tcase stm32.FLASH.GetSR_PGPERR() != 0:\n\t\treturn errFlashPGP\n\tcase stm32.FLASH.GetSR_PGAERR() != 0:\n\t\treturn errFlashPGA\n\tcase stm32.FLASH.GetSR_WRPERR() != 0:\n\t\treturn errFlashWRP\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "src/machine/machine_stm32f40x.go",
    "content": "//go:build stm32f4 && (stm32f405 || stm32f407)\n\npackage machine\n\nfunc CPUFrequency() uint32 {\n\treturn 168000000\n}\n\n// Internal use: configured speed of the APB1 and APB2 timers, this should be kept\n// in sync with any changes to runtime package which configures the oscillators\n// and clock frequencies\nconst APB1_TIM_FREQ = 42000000 * 2\nconst APB2_TIM_FREQ = 84000000 * 2\n"
  },
  {
    "path": "src/machine/machine_stm32f469.go",
    "content": "//go:build stm32f4 && stm32f469\n\npackage machine\n\nfunc CPUFrequency() uint32 {\n\treturn 180000000\n}\n\n// Internal use: configured speed of the APB1 and APB2 timers, this should be kept\n// in sync with any changes to runtime package which configures the oscillators\n// and clock frequencies\nconst APB1_TIM_FREQ = 45000000 * 2\nconst APB2_TIM_FREQ = 90000000 * 2\n"
  },
  {
    "path": "src/machine/machine_stm32f7.go",
    "content": "//go:build stm32f7\n\npackage machine\n\n// Peripheral abstraction layer for the stm32f4\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nvar deviceIDAddr = []uintptr{0x1FF0F420, 0x1FF0F424, 0x1FF0F428}\n\n// Alternative peripheral pin functions\nconst (\n\tAF0_SYSTEM                               = 0\n\tAF1_TIM1_2                               = 1\n\tAF2_TIM3_4_5                             = 2\n\tAF3_TIM8_9_10_11_LPTIM1                  = 3\n\tAF4_I2C1_2_3_USART1                      = 4\n\tAF5_SPI1_2_3_4_5_I2S1_2_3                = 5\n\tAF6_SPI2_3_I2S2_3_SAI1_UART4             = 6\n\tAF7_SPI2_3_I2S2_3_USART1_2_3_UART5       = 7\n\tAF8_SAI2_USART6_UART4_5_7_8_OTG1_FS      = 8\n\tAF9_CAN1_TIM12_13_14_QUADSPI_FMC_OTG2_HS = 9\n\tAF10_SAI2_QUADSPI_SDMMC2_OTG2_HS_OTG1_FS = 10\n\tAF11_SDMMC2                              = 11\n\tAF12_UART7_FMC_SDMMC1_OTG2_FS            = 12\n\tAF15_EVENTOUT                            = 15\n)\n\nconst (\n\tPA0  = portA + 0\n\tPA1  = portA + 1\n\tPA2  = portA + 2\n\tPA3  = portA + 3\n\tPA4  = portA + 4\n\tPA5  = portA + 5\n\tPA6  = portA + 6\n\tPA7  = portA + 7\n\tPA8  = portA + 8\n\tPA9  = portA + 9\n\tPA10 = portA + 10\n\tPA11 = portA + 11\n\tPA12 = portA + 12\n\tPA13 = portA + 13\n\tPA14 = portA + 14\n\tPA15 = portA + 15\n\n\tPB0  = portB + 0\n\tPB1  = portB + 1\n\tPB2  = portB + 2\n\tPB3  = portB + 3\n\tPB4  = portB + 4\n\tPB5  = portB + 5\n\tPB6  = portB + 6\n\tPB7  = portB + 7\n\tPB8  = portB + 8\n\tPB9  = portB + 9\n\tPB10 = portB + 10\n\tPB11 = portB + 11\n\tPB12 = portB + 12\n\tPB13 = portB + 13\n\tPB14 = portB + 14\n\tPB15 = portB + 15\n\n\tPC0  = portC + 0\n\tPC1  = portC + 1\n\tPC2  = portC + 2\n\tPC3  = portC + 3\n\tPC4  = portC + 4\n\tPC5  = portC + 5\n\tPC6  = portC + 6\n\tPC7  = portC + 7\n\tPC8  = portC + 8\n\tPC9  = portC + 9\n\tPC10 = portC + 10\n\tPC11 = portC + 11\n\tPC12 = portC + 12\n\tPC13 = portC + 13\n\tPC14 = portC + 14\n\tPC15 = portC + 15\n\n\tPD0  = portD + 0\n\tPD1  = portD + 1\n\tPD2  = portD + 2\n\tPD3  = portD + 3\n\tPD4  = portD + 4\n\tPD5  = portD + 5\n\tPD6  = portD + 6\n\tPD7  = portD + 7\n\tPD8  = portD + 8\n\tPD9  = portD + 9\n\tPD10 = portD + 10\n\tPD11 = portD + 11\n\tPD12 = portD + 12\n\tPD13 = portD + 13\n\tPD14 = portD + 14\n\tPD15 = portD + 15\n\n\tPE0  = portE + 0\n\tPE1  = portE + 1\n\tPE2  = portE + 2\n\tPE3  = portE + 3\n\tPE4  = portE + 4\n\tPE5  = portE + 5\n\tPE6  = portE + 6\n\tPE7  = portE + 7\n\tPE8  = portE + 8\n\tPE9  = portE + 9\n\tPE10 = portE + 10\n\tPE11 = portE + 11\n\tPE12 = portE + 12\n\tPE13 = portE + 13\n\tPE14 = portE + 14\n\tPE15 = portE + 15\n\n\tPF0  = portF + 0\n\tPF1  = portF + 1\n\tPF2  = portF + 2\n\tPF3  = portF + 3\n\tPF4  = portF + 4\n\tPF5  = portF + 5\n\tPF6  = portF + 6\n\tPF7  = portF + 7\n\tPF8  = portF + 8\n\tPF9  = portF + 9\n\tPF10 = portF + 10\n\tPF11 = portF + 11\n\tPF12 = portF + 12\n\tPF13 = portF + 13\n\tPF14 = portF + 14\n\tPF15 = portF + 15\n\n\tPG0  = portG + 0\n\tPG1  = portG + 1\n\tPG2  = portG + 2\n\tPG3  = portG + 3\n\tPG4  = portG + 4\n\tPG5  = portG + 5\n\tPG6  = portG + 6\n\tPG7  = portG + 7\n\tPG8  = portG + 8\n\tPG9  = portG + 9\n\tPG10 = portG + 10\n\tPG11 = portG + 11\n\tPG12 = portG + 12\n\tPG13 = portG + 13\n\tPG14 = portG + 14\n\tPG15 = portG + 15\n\n\tPH0  = portH + 0\n\tPH1  = portH + 1\n\tPH2  = portH + 2\n\tPH3  = portH + 3\n\tPH4  = portH + 4\n\tPH5  = portH + 5\n\tPH6  = portH + 6\n\tPH7  = portH + 7\n\tPH8  = portH + 8\n\tPH9  = portH + 9\n\tPH10 = portH + 10\n\tPH11 = portH + 11\n\tPH12 = portH + 12\n\tPH13 = portH + 13\n\tPH14 = portH + 14\n\tPH15 = portH + 15\n\n\tPI0  = portI + 0\n\tPI1  = portI + 1\n\tPI2  = portI + 2\n\tPI3  = portI + 3\n\tPI4  = portI + 4\n\tPI5  = portI + 5\n\tPI6  = portI + 6\n\tPI7  = portI + 7\n\tPI8  = portI + 8\n\tPI9  = portI + 9\n\tPI10 = portI + 10\n\tPI11 = portI + 11\n\tPI12 = portI + 12\n\tPI13 = portI + 13\n\tPI14 = portI + 14\n\tPI15 = portI + 15\n)\n\nfunc (p Pin) getPort() *stm32.GPIO_Type {\n\tswitch p / 16 {\n\tcase 0:\n\t\treturn stm32.GPIOA\n\tcase 1:\n\t\treturn stm32.GPIOB\n\tcase 2:\n\t\treturn stm32.GPIOC\n\tcase 3:\n\t\treturn stm32.GPIOD\n\tcase 4:\n\t\treturn stm32.GPIOE\n\tcase 5:\n\t\treturn stm32.GPIOF\n\tcase 6:\n\t\treturn stm32.GPIOG\n\tcase 7:\n\t\treturn stm32.GPIOH\n\tcase 8:\n\t\treturn stm32.GPIOI\n\tdefault:\n\t\tpanic(\"machine: unknown port\")\n\t}\n}\n\n// enableClock enables the clock for this desired GPIO port.\nfunc (p Pin) enableClock() {\n\tswitch p / 16 {\n\tcase 0:\n\t\tstm32.RCC.AHB1ENR.SetBits(stm32.RCC_AHB1ENR_GPIOAEN)\n\tcase 1:\n\t\tstm32.RCC.AHB1ENR.SetBits(stm32.RCC_AHB1ENR_GPIOBEN)\n\tcase 2:\n\t\tstm32.RCC.AHB1ENR.SetBits(stm32.RCC_AHB1ENR_GPIOCEN)\n\tcase 3:\n\t\tstm32.RCC.AHB1ENR.SetBits(stm32.RCC_AHB1ENR_GPIODEN)\n\tcase 4:\n\t\tstm32.RCC.AHB1ENR.SetBits(stm32.RCC_AHB1ENR_GPIOEEN)\n\tcase 5:\n\t\tstm32.RCC.AHB1ENR.SetBits(stm32.RCC_AHB1ENR_GPIOFEN)\n\tcase 6:\n\t\tstm32.RCC.AHB1ENR.SetBits(stm32.RCC_AHB1ENR_GPIOGEN)\n\tcase 7:\n\t\tstm32.RCC.AHB1ENR.SetBits(stm32.RCC_AHB1ENR_GPIOHEN)\n\tcase 8:\n\t\tstm32.RCC.AHB1ENR.SetBits(stm32.RCC_AHB1ENR_GPIOIEN)\n\tdefault:\n\t\tpanic(\"machine: unknown port\")\n\t}\n}\n\n// Enable peripheral clock\nfunc enableAltFuncClock(bus unsafe.Pointer) {\n\tswitch bus {\n\tcase unsafe.Pointer(stm32.DAC): // DAC interface clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_DACEN)\n\tcase unsafe.Pointer(stm32.PWR): // Power interface clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN)\n\tcase unsafe.Pointer(stm32.CAN1): // CAN 1 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_CAN1EN)\n\tcase unsafe.Pointer(stm32.I2C3): // I2C3 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C3EN)\n\tcase unsafe.Pointer(stm32.I2C2): // I2C2 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C2EN)\n\tcase unsafe.Pointer(stm32.I2C1): // I2C1 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C1EN)\n\tcase unsafe.Pointer(stm32.UART5): // UART5 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_UART5EN)\n\tcase unsafe.Pointer(stm32.UART4): // UART4 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_UART4EN)\n\tcase unsafe.Pointer(stm32.USART3): // USART3 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART3EN)\n\tcase unsafe.Pointer(stm32.USART2): // USART2 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART2EN)\n\tcase unsafe.Pointer(stm32.SPI3): // SPI3 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_SPI3EN)\n\tcase unsafe.Pointer(stm32.SPI2): // SPI2 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_SPI2EN)\n\tcase unsafe.Pointer(stm32.WWDG): // Window watchdog clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_WWDGEN)\n\tcase unsafe.Pointer(stm32.TIM14): // TIM14 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM14EN)\n\tcase unsafe.Pointer(stm32.TIM13): // TIM13 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM13EN)\n\tcase unsafe.Pointer(stm32.TIM12): // TIM12 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM12EN)\n\tcase unsafe.Pointer(stm32.TIM7): // TIM7 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM7EN)\n\tcase unsafe.Pointer(stm32.TIM6): // TIM6 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM6EN)\n\tcase unsafe.Pointer(stm32.TIM5): // TIM5 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM5EN)\n\tcase unsafe.Pointer(stm32.TIM4): // TIM4 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM4EN)\n\tcase unsafe.Pointer(stm32.TIM3): // TIM3 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM3EN)\n\tcase unsafe.Pointer(stm32.TIM2): // TIM2 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM2EN)\n\tcase unsafe.Pointer(stm32.TIM11): // TIM11 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM11EN)\n\tcase unsafe.Pointer(stm32.TIM10): // TIM10 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM10EN)\n\tcase unsafe.Pointer(stm32.TIM9): // TIM9 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM9EN)\n\tcase unsafe.Pointer(stm32.SYSCFG): // System configuration controller clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SYSCFGEN)\n\tcase unsafe.Pointer(stm32.SPI1): // SPI1 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SPI1EN)\n\tcase unsafe.Pointer(stm32.ADC3): // ADC3 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_ADC3EN)\n\tcase unsafe.Pointer(stm32.ADC2): // ADC2 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_ADC2EN)\n\tcase unsafe.Pointer(stm32.ADC1): // ADC1 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_ADC1EN)\n\tcase unsafe.Pointer(stm32.USART6): // USART6 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART6EN)\n\tcase unsafe.Pointer(stm32.USART1): // USART1 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART1EN)\n\tcase unsafe.Pointer(stm32.TIM8): // TIM8 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM8EN)\n\tcase unsafe.Pointer(stm32.TIM1): // TIM1 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM1EN)\n\t}\n}\n\nfunc (p Pin) registerInterrupt() interrupt.Interrupt {\n\tpin := uint8(p) % 16\n\n\tswitch pin {\n\tcase 0:\n\t\treturn interrupt.New(stm32.IRQ_EXTI0, func(interrupt.Interrupt) { handlePinInterrupt(0) })\n\tcase 1:\n\t\treturn interrupt.New(stm32.IRQ_EXTI1, func(interrupt.Interrupt) { handlePinInterrupt(1) })\n\tcase 2:\n\t\treturn interrupt.New(stm32.IRQ_EXTI2, func(interrupt.Interrupt) { handlePinInterrupt(2) })\n\tcase 3:\n\t\treturn interrupt.New(stm32.IRQ_EXTI3, func(interrupt.Interrupt) { handlePinInterrupt(3) })\n\tcase 4:\n\t\treturn interrupt.New(stm32.IRQ_EXTI4, func(interrupt.Interrupt) { handlePinInterrupt(4) })\n\tcase 5:\n\t\treturn interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(5) })\n\tcase 6:\n\t\treturn interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(6) })\n\tcase 7:\n\t\treturn interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(7) })\n\tcase 8:\n\t\treturn interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(8) })\n\tcase 9:\n\t\treturn interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(9) })\n\tcase 10:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(10) })\n\tcase 11:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(11) })\n\tcase 12:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(12) })\n\tcase 13:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(13) })\n\tcase 14:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(14) })\n\tcase 15:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(15) })\n\t}\n\n\treturn interrupt.Interrupt{}\n}\n\n//---------- Timer related code\n\nvar (\n\tTIM1 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM1EN,\n\t\tDevice:         stm32.TIM1,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA8, AF1_TIM1_2},\n\t\t\t\t{PE9, AF1_TIM1_2},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA9, AF1_TIM1_2},\n\t\t\t\t{PE11, AF1_TIM1_2},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA10, AF1_TIM1_2},\n\t\t\t\t{PE13, AF1_TIM1_2},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA11, AF1_TIM1_2},\n\t\t\t\t{PE14, AF1_TIM1_2},\n\t\t\t}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n\n\tTIM2 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM2EN,\n\t\tDevice:         stm32.TIM2,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA0, AF1_TIM1_2},\n\t\t\t\t{PA5, AF1_TIM1_2},\n\t\t\t\t{PA15, AF1_TIM1_2},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA1, AF1_TIM1_2},\n\t\t\t\t{PB3, AF1_TIM1_2},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA2, AF1_TIM1_2},\n\t\t\t\t{PB10, AF1_TIM1_2},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA3, AF1_TIM1_2},\n\t\t\t\t{PB11, AF1_TIM1_2},\n\t\t\t}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM3 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM3EN,\n\t\tDevice:         stm32.TIM3,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA6, AF2_TIM3_4_5},\n\t\t\t\t{PB4, AF2_TIM3_4_5},\n\t\t\t\t{PC6, AF2_TIM3_4_5},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA7, AF2_TIM3_4_5},\n\t\t\t\t{PB5, AF2_TIM3_4_5},\n\t\t\t\t{PC7, AF2_TIM3_4_5},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PB0, AF2_TIM3_4_5},\n\t\t\t\t{PC8, AF2_TIM3_4_5},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PB1, AF2_TIM3_4_5},\n\t\t\t\t{PC9, AF2_TIM3_4_5},\n\t\t\t}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM4 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM4EN,\n\t\tDevice:         stm32.TIM4,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PB6, AF2_TIM3_4_5},\n\t\t\t\t{PD12, AF2_TIM3_4_5},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PB7, AF2_TIM3_4_5},\n\t\t\t\t{PD13, AF2_TIM3_4_5},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PB8, AF2_TIM3_4_5},\n\t\t\t\t{PD14, AF2_TIM3_4_5},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PB9, AF2_TIM3_4_5},\n\t\t\t\t{PD15, AF2_TIM3_4_5},\n\t\t\t}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM5 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM5EN,\n\t\tDevice:         stm32.TIM5,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA0, AF2_TIM3_4_5},\n\t\t\t\t{PH10, AF2_TIM3_4_5},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA1, AF2_TIM3_4_5},\n\t\t\t\t{PH11, AF2_TIM3_4_5},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA2, AF2_TIM3_4_5},\n\t\t\t\t{PH12, AF2_TIM3_4_5},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA3, AF2_TIM3_4_5},\n\t\t\t\t{PI0, AF2_TIM3_4_5},\n\t\t\t}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM6 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM6EN,\n\t\tDevice:         stm32.TIM6,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM7 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM7EN,\n\t\tDevice:         stm32.TIM7,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM8 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM8EN,\n\t\tDevice:         stm32.TIM8,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PC6, AF3_TIM8_9_10_11_LPTIM1},\n\t\t\t\t{PI5, AF3_TIM8_9_10_11_LPTIM1},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PC7, AF3_TIM8_9_10_11_LPTIM1},\n\t\t\t\t{PI6, AF3_TIM8_9_10_11_LPTIM1},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PC8, AF3_TIM8_9_10_11_LPTIM1},\n\t\t\t\t{PI7, AF3_TIM8_9_10_11_LPTIM1},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PC9, AF3_TIM8_9_10_11_LPTIM1},\n\t\t\t\t{PI2, AF3_TIM8_9_10_11_LPTIM1},\n\t\t\t}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n\n\tTIM9 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM9EN,\n\t\tDevice:         stm32.TIM9,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA2, AF3_TIM8_9_10_11_LPTIM1},\n\t\t\t\t{PE5, AF3_TIM8_9_10_11_LPTIM1},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA3, AF3_TIM8_9_10_11_LPTIM1},\n\t\t\t\t{PE6, AF3_TIM8_9_10_11_LPTIM1},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n\n\tTIM10 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM10EN,\n\t\tDevice:         stm32.TIM10,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PB8, AF3_TIM8_9_10_11_LPTIM1},\n\t\t\t\t{PF6, AF3_TIM8_9_10_11_LPTIM1},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n\n\tTIM11 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM11EN,\n\t\tDevice:         stm32.TIM11,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PB9, AF3_TIM8_9_10_11_LPTIM1},\n\t\t\t\t{PF7, AF3_TIM8_9_10_11_LPTIM1},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n\n\tTIM12 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM12EN,\n\t\tDevice:         stm32.TIM12,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PB14, AF9_CAN1_TIM12_13_14_QUADSPI_FMC_OTG2_HS},\n\t\t\t\t{PH6, AF9_CAN1_TIM12_13_14_QUADSPI_FMC_OTG2_HS},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PB15, AF9_CAN1_TIM12_13_14_QUADSPI_FMC_OTG2_HS},\n\t\t\t\t{PH9, AF9_CAN1_TIM12_13_14_QUADSPI_FMC_OTG2_HS},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM13 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM13EN,\n\t\tDevice:         stm32.TIM13,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA6, AF9_CAN1_TIM12_13_14_QUADSPI_FMC_OTG2_HS},\n\t\t\t\t{PF8, AF9_CAN1_TIM12_13_14_QUADSPI_FMC_OTG2_HS},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM14 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM14EN,\n\t\tDevice:         stm32.TIM14,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA7, AF9_CAN1_TIM12_13_14_QUADSPI_FMC_OTG2_HS},\n\t\t\t\t{PF9, AF9_CAN1_TIM12_13_14_QUADSPI_FMC_OTG2_HS},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n)\n\nfunc (t *TIM) registerUPInterrupt() interrupt.Interrupt {\n\tswitch t {\n\tcase &TIM1:\n\t\treturn interrupt.New(stm32.IRQ_TIM1_UP_TIM10, TIM1.handleUPInterrupt)\n\tcase &TIM2:\n\t\treturn interrupt.New(stm32.IRQ_TIM2, TIM2.handleUPInterrupt)\n\tcase &TIM3:\n\t\treturn interrupt.New(stm32.IRQ_TIM3, TIM3.handleUPInterrupt)\n\tcase &TIM4:\n\t\treturn interrupt.New(stm32.IRQ_TIM4, TIM4.handleUPInterrupt)\n\tcase &TIM5:\n\t\treturn interrupt.New(stm32.IRQ_TIM5, TIM5.handleUPInterrupt)\n\tcase &TIM6:\n\t\treturn interrupt.New(stm32.IRQ_TIM6_DAC, TIM6.handleUPInterrupt)\n\tcase &TIM7:\n\t\treturn interrupt.New(stm32.IRQ_TIM7, TIM7.handleUPInterrupt)\n\tcase &TIM8:\n\t\treturn interrupt.New(stm32.IRQ_TIM8_UP_TIM13, TIM8.handleUPInterrupt)\n\tcase &TIM9:\n\t\treturn interrupt.New(stm32.IRQ_TIM1_BRK_TIM9, TIM9.handleUPInterrupt)\n\tcase &TIM10:\n\t\treturn interrupt.New(stm32.IRQ_TIM1_UP_TIM10, TIM10.handleUPInterrupt)\n\tcase &TIM11:\n\t\treturn interrupt.New(stm32.IRQ_TIM1_TRG_COM_TIM11, TIM11.handleUPInterrupt)\n\tcase &TIM12:\n\t\treturn interrupt.New(stm32.IRQ_TIM8_BRK_TIM12, TIM12.handleUPInterrupt)\n\tcase &TIM13:\n\t\treturn interrupt.New(stm32.IRQ_TIM8_UP_TIM13, TIM13.handleUPInterrupt)\n\tcase &TIM14:\n\t\treturn interrupt.New(stm32.IRQ_TIM8_TRG_COM_TIM14, TIM14.handleUPInterrupt)\n\t}\n\n\treturn interrupt.Interrupt{}\n}\n\nfunc (t *TIM) registerOCInterrupt() interrupt.Interrupt {\n\tswitch t {\n\tcase &TIM1:\n\t\treturn interrupt.New(stm32.IRQ_TIM1_CC, TIM1.handleUPInterrupt)\n\tcase &TIM2:\n\t\treturn interrupt.New(stm32.IRQ_TIM2, TIM2.handleOCInterrupt)\n\tcase &TIM3:\n\t\treturn interrupt.New(stm32.IRQ_TIM3, TIM3.handleOCInterrupt)\n\tcase &TIM4:\n\t\treturn interrupt.New(stm32.IRQ_TIM4, TIM4.handleOCInterrupt)\n\tcase &TIM5:\n\t\treturn interrupt.New(stm32.IRQ_TIM5, TIM5.handleOCInterrupt)\n\tcase &TIM6:\n\t\treturn interrupt.New(stm32.IRQ_TIM6_DAC, TIM6.handleOCInterrupt)\n\tcase &TIM7:\n\t\treturn interrupt.New(stm32.IRQ_TIM7, TIM7.handleOCInterrupt)\n\tcase &TIM8:\n\t\treturn interrupt.New(stm32.IRQ_TIM8_CC, TIM8.handleOCInterrupt)\n\tcase &TIM9:\n\t\treturn interrupt.New(stm32.IRQ_TIM1_BRK_TIM9, TIM9.handleOCInterrupt)\n\tcase &TIM10:\n\t\treturn interrupt.New(stm32.IRQ_TIM1_UP_TIM10, TIM10.handleOCInterrupt)\n\tcase &TIM11:\n\t\treturn interrupt.New(stm32.IRQ_TIM1_TRG_COM_TIM11, TIM11.handleOCInterrupt)\n\tcase &TIM12:\n\t\treturn interrupt.New(stm32.IRQ_TIM8_BRK_TIM12, TIM12.handleOCInterrupt)\n\tcase &TIM13:\n\t\treturn interrupt.New(stm32.IRQ_TIM8_UP_TIM13, TIM13.handleOCInterrupt)\n\tcase &TIM14:\n\t\treturn interrupt.New(stm32.IRQ_TIM8_TRG_COM_TIM14, TIM14.handleOCInterrupt)\n\t}\n\n\treturn interrupt.Interrupt{}\n}\n\nfunc (t *TIM) enableMainOutput() {\n\tt.Device.BDTR.SetBits(stm32.TIM_BDTR_MOE)\n}\n\ntype arrtype = uint32\ntype arrRegType = volatile.Register32\n\nconst (\n\tARR_MAX = 0x10000\n\tPSC_MAX = 0x10000\n)\n\nfunc initRNG() {\n\tstm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_RNGEN)\n\tstm32.RNG.CR.SetBits(stm32.RNG_CR_RNGEN)\n}\n"
  },
  {
    "path": "src/machine/machine_stm32f7x2.go",
    "content": "//go:build stm32f7x2\n\npackage machine\n\n// Peripheral abstraction layer for the stm32f407\n\nimport (\n\t\"device/stm32\"\n)\n\nfunc CPUFrequency() uint32 {\n\treturn 216000000\n}\n\n// Internal use: configured speed of the APB1 and APB2 timers, this should be kept\n// in sync with any changes to runtime package which configures the oscillators\n// and clock frequencies\nconst APB1_TIM_FREQ = 54e6  // 54MHz\nconst APB2_TIM_FREQ = 216e6 // 216MHz\n\n//---------- UART related code\n\n// Configure the UART.\nfunc (uart *UART) configurePins(config UARTConfig) {\n\t// enable the alternate functions on the TX and RX pins\n\tconfig.TX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTTX}, uart.TxAltFuncSelector)\n\tconfig.RX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTRX}, uart.RxAltFuncSelector)\n}\n\n// UART baudrate calc based on the bus and clockspeed\n// NOTE: keep this in sync with the runtime/runtime_stm32f7x2.go clock init code\nfunc (uart *UART) getBaudRateDivisor(baudRate uint32) uint32 {\n\tvar clock uint32\n\tswitch uart.Bus {\n\tcase stm32.USART1, stm32.USART6:\n\t\tclock = CPUFrequency() / 2 // APB2 Frequency\n\tcase stm32.USART2, stm32.USART3, stm32.UART4, stm32.UART5:\n\t\tclock = CPUFrequency() / 8 // APB1 Frequency\n\t}\n\treturn clock / baudRate\n}\n\n// Register names vary by ST processor, these are for STM F7x2\nfunc (uart *UART) setRegisters() {\n\tuart.rxReg = &uart.Bus.RDR\n\tuart.txReg = &uart.Bus.TDR\n\tuart.statusReg = &uart.Bus.ISR\n\tuart.txEmptyFlag = stm32.USART_ISR_TXE\n}\n\n//---------- I2C related code\n\n// Gets the value for TIMINGR register\nfunc (i2c *I2C) getFreqRange(br uint32) uint32 {\n\t// This is a 'magic' value calculated by STM32CubeMX\n\t// for 27MHz PCLK1 (216MHz CPU Freq / 8).\n\t// TODO: Do calculations based on PCLK1\n\tswitch br {\n\tcase 10 * KHz:\n\t\treturn 0x5010C0FF\n\tcase 100 * KHz:\n\t\treturn 0x00606A9B\n\tcase 400 * KHz:\n\t\treturn 0x00201625\n\tcase 500 * KHz:\n\t\treturn 0x00100429\n\tdefault:\n\t\treturn 0\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_stm32l0.go",
    "content": "//go:build stm32l0\n\npackage machine\n\n// Peripheral abstraction layer for the stm32l0\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/interrupt\"\n)\n\nfunc CPUFrequency() uint32 {\n\treturn 32000000\n}\n\nvar deviceIDAddr = []uintptr{0x1FF80050, 0x1FF80054, 0x1FF80058}\n\n// Internal use: configured speed of the APB1 and APB2 timers, this should be kept\n// in sync with any changes to runtime package which configures the oscillators\n// and clock frequencies\nconst APB1_TIM_FREQ = 32e6 // 32MHz\nconst APB2_TIM_FREQ = 32e6 // 32MHz\n\nconst (\n\tPA0  = portA + 0\n\tPA1  = portA + 1\n\tPA2  = portA + 2\n\tPA3  = portA + 3\n\tPA4  = portA + 4\n\tPA5  = portA + 5\n\tPA6  = portA + 6\n\tPA7  = portA + 7\n\tPA8  = portA + 8\n\tPA9  = portA + 9\n\tPA10 = portA + 10\n\tPA11 = portA + 11\n\tPA12 = portA + 12\n\tPA13 = portA + 13\n\tPA14 = portA + 14\n\tPA15 = portA + 15\n\n\tPB0  = portB + 0\n\tPB1  = portB + 1\n\tPB2  = portB + 2\n\tPB3  = portB + 3\n\tPB4  = portB + 4\n\tPB5  = portB + 5\n\tPB6  = portB + 6\n\tPB7  = portB + 7\n\tPB8  = portB + 8\n\tPB9  = portB + 9\n\tPB10 = portB + 10\n\tPB11 = portB + 11\n\tPB12 = portB + 12\n\tPB13 = portB + 13\n\tPB14 = portB + 14\n\tPB15 = portB + 15\n\n\tPC0  = portC + 0\n\tPC1  = portC + 1\n\tPC2  = portC + 2\n\tPC3  = portC + 3\n\tPC4  = portC + 4\n\tPC5  = portC + 5\n\tPC6  = portC + 6\n\tPC7  = portC + 7\n\tPC8  = portC + 8\n\tPC9  = portC + 9\n\tPC10 = portC + 10\n\tPC11 = portC + 11\n\tPC12 = portC + 12\n\tPC13 = portC + 13\n\tPC14 = portC + 14\n\tPC15 = portC + 15\n\n\tPD0  = portD + 0\n\tPD1  = portD + 1\n\tPD2  = portD + 2\n\tPD3  = portD + 3\n\tPD4  = portD + 4\n\tPD5  = portD + 5\n\tPD6  = portD + 6\n\tPD7  = portD + 7\n\tPD8  = portD + 8\n\tPD9  = portD + 9\n\tPD10 = portD + 10\n\tPD11 = portD + 11\n\tPD12 = portD + 12\n\tPD13 = portD + 13\n\tPD14 = portD + 14\n\tPD15 = portD + 15\n\n\tPE0  = portE + 0\n\tPE1  = portE + 1\n\tPE2  = portE + 2\n\tPE3  = portE + 3\n\tPE4  = portE + 4\n\tPE5  = portE + 5\n\tPE6  = portE + 6\n\tPE7  = portE + 7\n\tPE8  = portE + 8\n\tPE9  = portE + 9\n\tPE10 = portE + 10\n\tPE11 = portE + 11\n\tPE12 = portE + 12\n\tPE13 = portE + 13\n\tPE14 = portE + 14\n\tPE15 = portE + 15\n\n\tPH0 = portH + 0\n\tPH1 = portH + 1\n)\n\nfunc (p Pin) getPort() *stm32.GPIO_Type {\n\tswitch p / 16 {\n\tcase 0:\n\t\treturn stm32.GPIOA\n\tcase 1:\n\t\treturn stm32.GPIOB\n\tcase 2:\n\t\treturn stm32.GPIOC\n\tcase 3:\n\t\treturn stm32.GPIOD\n\tcase 4:\n\t\treturn stm32.GPIOE\n\tcase 7:\n\t\treturn stm32.GPIOH\n\tdefault:\n\t\tpanic(\"machine: unknown port\")\n\t}\n}\n\n// enableClock enables the clock for this desired GPIO port.\nfunc (p Pin) enableClock() {\n\tswitch p / 16 {\n\tcase 0:\n\t\tstm32.RCC.IOPENR.SetBits(stm32.RCC_IOPENR_IOPAEN)\n\tcase 1:\n\t\tstm32.RCC.IOPENR.SetBits(stm32.RCC_IOPENR_IOPBEN)\n\tcase 2:\n\t\tstm32.RCC.IOPENR.SetBits(stm32.RCC_IOPENR_IOPCEN)\n\tcase 3:\n\t\tstm32.RCC.IOPENR.SetBits(stm32.RCC_IOPENR_IOPDEN)\n\tcase 4:\n\t\tstm32.RCC.IOPENR.SetBits(stm32.RCC_IOPENR_IOPEEN)\n\tcase 7:\n\t\tstm32.RCC.IOPENR.SetBits(stm32.RCC_IOPENR_IOPHEN)\n\tdefault:\n\t\tpanic(\"machine: unknown port\")\n\t}\n}\n\nfunc (p Pin) registerInterrupt() interrupt.Interrupt {\n\tpin := uint8(p) % 16\n\n\tswitch pin {\n\tcase 0:\n\t\treturn interrupt.New(stm32.IRQ_EXTI0_1, func(interrupt.Interrupt) { handlePinInterrupt(0) })\n\tcase 1:\n\t\treturn interrupt.New(stm32.IRQ_EXTI0_1, func(interrupt.Interrupt) { handlePinInterrupt(1) })\n\tcase 2:\n\t\treturn interrupt.New(stm32.IRQ_EXTI2_3, func(interrupt.Interrupt) { handlePinInterrupt(2) })\n\tcase 3:\n\t\treturn interrupt.New(stm32.IRQ_EXTI2_3, func(interrupt.Interrupt) { handlePinInterrupt(3) })\n\tcase 4:\n\t\treturn interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(4) })\n\tcase 5:\n\t\treturn interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(5) })\n\tcase 6:\n\t\treturn interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(6) })\n\tcase 7:\n\t\treturn interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(7) })\n\tcase 8:\n\t\treturn interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(8) })\n\tcase 9:\n\t\treturn interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(9) })\n\tcase 10:\n\t\treturn interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(10) })\n\tcase 11:\n\t\treturn interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(11) })\n\tcase 12:\n\t\treturn interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(12) })\n\tcase 13:\n\t\treturn interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(13) })\n\tcase 14:\n\t\treturn interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(14) })\n\tcase 15:\n\t\treturn interrupt.New(stm32.IRQ_EXTI4_15, func(interrupt.Interrupt) { handlePinInterrupt(15) })\n\t}\n\n\treturn interrupt.Interrupt{}\n}\n\n//---------- UART related types and code\n\n// Configure the UART.\nfunc (uart *UART) configurePins(config UARTConfig) {\n\t// enable the alternate functions on the TX and RX pins\n\tconfig.TX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTTX}, uart.TxAltFuncSelector)\n\tconfig.RX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTRX}, uart.RxAltFuncSelector)\n}\n\n// UART baudrate calc based on the bus and clockspeed\nfunc (uart *UART) getBaudRateDivisor(baudRate uint32) uint32 {\n\tvar clock, rate uint32\n\tswitch uart.Bus {\n\tcase stm32.LPUART1:\n\t\tclock = CPUFrequency() / 2 // APB1 Frequency\n\t\trate = uint32((256 * clock) / baudRate)\n\tcase stm32.USART1:\n\t\tclock = CPUFrequency() / 2 // APB2 Frequency\n\t\trate = uint32(clock / baudRate)\n\tcase stm32.USART2:\n\t\tclock = CPUFrequency() / 2 // APB1 Frequency\n\t\trate = uint32(clock / baudRate)\n\t}\n\n\treturn rate\n}\n\n// Register names vary by ST processor, these are for STM L0 family\nfunc (uart *UART) setRegisters() {\n\tuart.rxReg = &uart.Bus.RDR\n\tuart.txReg = &uart.Bus.TDR\n\tuart.statusReg = &uart.Bus.ISR\n\tuart.txEmptyFlag = stm32.USART_ISR_TXE\n}\n\n//---------- SPI related types and code\n\n// SPI on the STM32Fxxx using MODER / alternate function pins\ntype SPI struct {\n\tBus             *stm32.SPI_Type\n\tAltFuncSelector uint8\n}\n\nfunc (spi *SPI) config8Bits() {\n\t// no-op on this series\n}\n\n// Set baud rate for SPI\nfunc (spi *SPI) getBaudRate(config SPIConfig) uint32 {\n\tvar conf uint32\n\n\tlocalFrequency := config.Frequency\n\n\t// Default\n\tif config.Frequency == 0 {\n\t\tconfig.Frequency = 4e6\n\t}\n\n\tif spi.Bus != stm32.SPI1 {\n\t\t// Assume it's SPI2 or SPI3 on APB1 at 1/2 the clock frequency of APB2, so\n\t\t//  we want to pretend to request 2x the baudrate asked for\n\t\tlocalFrequency = localFrequency * 2\n\t}\n\n\t// set frequency dependent on PCLK prescaler. Since these are rather weird\n\t// speeds due to the CPU frequency, pick a range up to that frequency for\n\t// clients to use more human-understandable numbers, e.g. nearest 100KHz\n\n\t// These are based on APB2 clock frequency (84MHz on the discovery board)\n\t// TODO: also include the MCU/APB clock setting in the equation\n\tswitch {\n\tcase localFrequency < 328125:\n\t\tconf = stm32.SPI_CR1_BR_Div256\n\tcase localFrequency < 656250:\n\t\tconf = stm32.SPI_CR1_BR_Div128\n\tcase localFrequency < 1312500:\n\t\tconf = stm32.SPI_CR1_BR_Div64\n\tcase localFrequency < 2625000:\n\t\tconf = stm32.SPI_CR1_BR_Div32\n\tcase localFrequency < 5250000:\n\t\tconf = stm32.SPI_CR1_BR_Div16\n\tcase localFrequency < 10500000:\n\t\tconf = stm32.SPI_CR1_BR_Div8\n\t\t// NOTE: many SPI components won't operate reliably (or at all) above 10MHz\n\t\t// Check the datasheet of the part\n\tcase localFrequency < 21000000:\n\t\tconf = stm32.SPI_CR1_BR_Div4\n\tcase localFrequency < 42000000:\n\t\tconf = stm32.SPI_CR1_BR_Div2\n\tdefault:\n\t\t// None of the specific baudrates were selected; choose the lowest speed\n\t\tconf = stm32.SPI_CR1_BR_Div256\n\t}\n\n\treturn conf << stm32.SPI_CR1_BR_Pos\n}\n\n// Configure SPI pins for input output and clock\nfunc (spi *SPI) configurePins(config SPIConfig) {\n\tconfig.SCK.ConfigureAltFunc(PinConfig{Mode: PinModeSPICLK}, spi.AltFuncSelector)\n\tconfig.SDO.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDO}, spi.AltFuncSelector)\n\tconfig.SDI.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDI}, spi.AltFuncSelector)\n}\n\n//---------- I2C related types and code\n\n// Gets the value for TIMINGR register\nfunc (i2c I2C) getFreqRange(br uint32) uint32 {\n\t// This is a 'magic' value calculated by STM32CubeMX\n\t// for 16MHz PCLK1.\n\t// TODO: Do calculations based on PCLK1\n\tswitch br {\n\tcase 10 * KHz:\n\t\treturn 0x40003EFF\n\tcase 100 * KHz:\n\t\treturn 0x00303D5B\n\tcase 400 * KHz:\n\t\treturn 0x0010061A\n\tcase 500 * KHz:\n\t\treturn 0x00000117\n\tdefault:\n\t\treturn 0\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_stm32l0x1.go",
    "content": "//go:build stm32l0x1\n\npackage machine\n\n// Peripheral abstraction layer for the stm32l0\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nconst (\n\tAF0_SYSTEM_SPI1_USART2_LPTIM_TIM21 = 0\n\tAF1_SPI1_I2C1_LPTIM                = 1\n\tAF2_LPTIM_TIM2                     = 2\n\tAF3_I2C1                           = 3\n\tAF4_I2C1_USART2_LPUART1_TIM22      = 4\n\tAF5_TIM2_21_22                     = 5\n\tAF6_LPUART1                        = 6\n\tAF7_COMP1_2                        = 7\n)\n\n// Enable peripheral clock\nfunc enableAltFuncClock(bus unsafe.Pointer) {\n\tswitch bus {\n\tcase unsafe.Pointer(stm32.PWR): // Power interface clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN)\n\tcase unsafe.Pointer(stm32.I2C3): // I2C3 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C3EN)\n\tcase unsafe.Pointer(stm32.I2C2): // I2C2 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C2EN)\n\tcase unsafe.Pointer(stm32.I2C1): // I2C1 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C1EN)\n\tcase unsafe.Pointer(stm32.USART5): // UART5 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART5EN)\n\tcase unsafe.Pointer(stm32.USART4): // UART4 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART4EN)\n\tcase unsafe.Pointer(stm32.USART2): // USART2 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART2EN)\n\tcase unsafe.Pointer(stm32.SPI2): // SPI2 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_SPI2EN)\n\tcase unsafe.Pointer(stm32.LPUART1): // LPUART1 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_LPUART1EN)\n\tcase unsafe.Pointer(stm32.WWDG): // Window watchdog clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_WWDGEN)\n\tcase unsafe.Pointer(stm32.TIM7): // TIM7 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM7EN)\n\tcase unsafe.Pointer(stm32.TIM6): // TIM6 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM6EN)\n\tcase unsafe.Pointer(stm32.TIM3): // TIM3 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM3EN)\n\tcase unsafe.Pointer(stm32.TIM2): // TIM2 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM2EN)\n\tcase unsafe.Pointer(stm32.SYSCFG): // System configuration controller clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SYSCFGEN)\n\tcase unsafe.Pointer(stm32.SPI1): // SPI1 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SPI1EN)\n\tcase unsafe.Pointer(stm32.ADC): // ADC clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_ADCEN)\n\tcase unsafe.Pointer(stm32.USART1): // USART1 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART1EN)\n\t}\n}\n\n//---------- Timer related code\n\nvar (\n\tTIM2 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM2EN,\n\t\tDevice:         stm32.TIM2,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PA0, AF2_LPTIM_TIM2}, {PA5, AF5_TIM2_21_22}, {PA8, AF5_TIM2_21_22}, {PA15, AF5_TIM2_21_22}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA1, AF2_LPTIM_TIM2}, {PB3, AF2_LPTIM_TIM2}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA2, AF2_LPTIM_TIM2}, {PB0, AF5_TIM2_21_22}, {PB10, AF2_LPTIM_TIM2}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA3, AF2_LPTIM_TIM2}, {PB1, AF5_TIM2_21_22}, {PB11, AF2_LPTIM_TIM2}}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM3 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM3EN,\n\t\tDevice:         stm32.TIM3,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM6 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM6EN,\n\t\tDevice:         stm32.TIM6,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM7 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM7EN,\n\t\tDevice:         stm32.TIM7,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM21 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM21EN,\n\t\tDevice:         stm32.TIM21,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n\n\tTIM22 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM22EN,\n\t\tDevice:         stm32.TIM2,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n)\n\nfunc (t *TIM) registerUPInterrupt() interrupt.Interrupt {\n\tswitch t {\n\tcase &TIM2:\n\t\treturn interrupt.New(stm32.IRQ_TIM2, TIM2.handleUPInterrupt)\n\tcase &TIM3:\n\t\treturn interrupt.New(stm32.IRQ_TIM3, TIM3.handleUPInterrupt)\n\tcase &TIM6:\n\t\treturn interrupt.New(stm32.IRQ_TIM6, TIM6.handleUPInterrupt)\n\tcase &TIM7:\n\t\treturn interrupt.New(stm32.IRQ_TIM7, TIM7.handleUPInterrupt)\n\tcase &TIM21:\n\t\treturn interrupt.New(stm32.IRQ_TIM21, TIM21.handleUPInterrupt)\n\tcase &TIM22:\n\t\treturn interrupt.New(stm32.IRQ_TIM22, TIM22.handleUPInterrupt)\n\t}\n\n\treturn interrupt.Interrupt{}\n}\n\nfunc (t *TIM) registerOCInterrupt() interrupt.Interrupt {\n\tswitch t {\n\tcase &TIM2:\n\t\treturn interrupt.New(stm32.IRQ_TIM2, TIM2.handleOCInterrupt)\n\tcase &TIM3:\n\t\treturn interrupt.New(stm32.IRQ_TIM3, TIM3.handleOCInterrupt)\n\tcase &TIM6:\n\t\treturn interrupt.New(stm32.IRQ_TIM6, TIM6.handleOCInterrupt)\n\tcase &TIM7:\n\t\treturn interrupt.New(stm32.IRQ_TIM7, TIM7.handleOCInterrupt)\n\tcase &TIM21:\n\t\treturn interrupt.New(stm32.IRQ_TIM21, TIM21.handleOCInterrupt)\n\tcase &TIM22:\n\t\treturn interrupt.New(stm32.IRQ_TIM22, TIM22.handleOCInterrupt)\n\t}\n\n\treturn interrupt.Interrupt{}\n}\n\nfunc (t *TIM) enableMainOutput() {\n\t// nothing to do - no BDTR register\n}\n\ntype arrtype = uint16\ntype arrRegType = volatile.Register16\n\nconst (\n\tARR_MAX = 0x10000\n\tPSC_MAX = 0x10000\n)\n"
  },
  {
    "path": "src/machine/machine_stm32l0x2.go",
    "content": "//go:build stm32l0x2\n\npackage machine\n\n// Peripheral abstraction layer for the stm32l0\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nconst (\n\tAF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22 = 0\n\tAF1_SPI1_2_I2S2_I2C1_TIM2_21                                      = 1\n\tAF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3                  = 2\n\tAF3_I2C1_TSC                                                      = 3\n\tAF4_I2C1_USART1_2_LPUART1_TIM3_22                                 = 4\n\tAF5_SPI2_I2S2_I2C2_USART1_TIM2_21_22                              = 5\n\tAF6_I2C1_2_LPUART1_USART4_5_TIM21                                 = 6\n\tAF7_I2C3_LPUART1_COMP1_2_TIM3                                     = 7\n)\n\n// Enable peripheral clock\nfunc enableAltFuncClock(bus unsafe.Pointer) {\n\tswitch bus {\n\tcase unsafe.Pointer(stm32.DAC): // DAC interface clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_DACEN)\n\tcase unsafe.Pointer(stm32.PWR): // Power interface clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN)\n\tcase unsafe.Pointer(stm32.I2C3): // I2C3 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C3EN)\n\tcase unsafe.Pointer(stm32.I2C2): // I2C2 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C2EN)\n\tcase unsafe.Pointer(stm32.I2C1): // I2C1 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C1EN)\n\tcase unsafe.Pointer(stm32.USART5): // UART5 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART5EN)\n\tcase unsafe.Pointer(stm32.USART4): // UART4 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART4EN)\n\tcase unsafe.Pointer(stm32.USART2): // USART2 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART2EN)\n\tcase unsafe.Pointer(stm32.SPI2): // SPI2 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_SPI2EN)\n\tcase unsafe.Pointer(stm32.LPUART1): // LPUART1 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_LPUART1EN)\n\tcase unsafe.Pointer(stm32.WWDG): // Window watchdog clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_WWDGEN)\n\tcase unsafe.Pointer(stm32.TIM7): // TIM7 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM7EN)\n\tcase unsafe.Pointer(stm32.TIM6): // TIM6 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM6EN)\n\tcase unsafe.Pointer(stm32.TIM3): // TIM3 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM3EN)\n\tcase unsafe.Pointer(stm32.TIM2): // TIM2 clock enable\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM2EN)\n\tcase unsafe.Pointer(stm32.SYSCFG): // System configuration controller clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SYSCFGEN)\n\tcase unsafe.Pointer(stm32.SPI1): // SPI1 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SPI1EN)\n\tcase unsafe.Pointer(stm32.ADC): // ADC clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_ADCEN)\n\tcase unsafe.Pointer(stm32.USART1): // USART1 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART1EN)\n\t}\n}\n\n//---------- Timer related code\n\nvar (\n\tTIM2 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM2EN,\n\t\tDevice:         stm32.TIM2,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA0, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3},\n\t\t\t\t{PA5, AF5_SPI2_I2S2_I2C2_USART1_TIM2_21_22},\n\t\t\t\t{PA15, AF5_SPI2_I2S2_I2C2_USART1_TIM2_21_22},\n\t\t\t\t{PE9, AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA1, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3},\n\t\t\t\t{PB3, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3},\n\t\t\t\t{PE10, AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA2, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3},\n\t\t\t\t{PB10, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3},\n\t\t\t\t{PE11, AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA3, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3},\n\t\t\t\t{PB11, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3},\n\t\t\t\t{PE12, AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22},\n\t\t\t}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM3 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM3EN,\n\t\tDevice:         stm32.TIM3,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA6, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3},\n\t\t\t\t{PB4, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3},\n\t\t\t\t{PC6, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3},\n\t\t\t\t{PE3, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA7, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3},\n\t\t\t\t{PB5, AF4_I2C1_USART1_2_LPUART1_TIM3_22},\n\t\t\t\t{PC7, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3},\n\t\t\t\t{PE4, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PB0, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3},\n\t\t\t\t{PC8, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3},\n\t\t\t\t{PE5, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PB1, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3},\n\t\t\t\t{PC9, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3},\n\t\t\t\t{PE6, AF2_SPI1_2_I2S2_LPUART1_USART5_USB_LPTIM1_TIM2_3},\n\t\t\t}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM6 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM6EN,\n\t\tDevice:         stm32.TIM6,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM7 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR,\n\t\tEnableFlag:     stm32.RCC_APB1ENR_TIM7EN,\n\t\tDevice:         stm32.TIM7,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM21 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM21EN,\n\t\tDevice:         stm32.TIM21,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA2, AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22},\n\t\t\t\t{PB13, AF6_I2C1_2_LPUART1_USART4_5_TIM21},\n\t\t\t\t{PD0, AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22},\n\t\t\t\t{PE5, AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA3, AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22},\n\t\t\t\t{PB14, AF6_I2C1_2_LPUART1_USART4_5_TIM21},\n\t\t\t\t{PD7, AF1_SPI1_2_I2S2_I2C1_TIM2_21},\n\t\t\t\t{PE6, AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n\n\tTIM22 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM22EN,\n\t\tDevice:         stm32.TIM2,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA6, AF5_SPI2_I2S2_I2C2_USART1_TIM2_21_22},\n\t\t\t\t{PB4, AF4_I2C1_USART1_2_LPUART1_TIM3_22},\n\t\t\t\t{PC6, AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22},\n\t\t\t\t{PE3, AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA7, AF5_SPI2_I2S2_I2C2_USART1_TIM2_21_22},\n\t\t\t\t{PB5, AF4_I2C1_USART1_2_LPUART1_TIM3_22},\n\t\t\t\t{PC7, AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22},\n\t\t\t\t{PE4, AF0_SYSTEM_SPI1_2_I2S2_USART1_2_LPUART1_USB_LPTIM1_TSC_TIM2_21_22},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n)\n\nfunc (t *TIM) registerUPInterrupt() interrupt.Interrupt {\n\tswitch t {\n\tcase &TIM2:\n\t\treturn interrupt.New(stm32.IRQ_TIM2, TIM2.handleUPInterrupt)\n\tcase &TIM3:\n\t\treturn interrupt.New(stm32.IRQ_TIM3, TIM3.handleUPInterrupt)\n\tcase &TIM6:\n\t\treturn interrupt.New(stm32.IRQ_TIM6_DAC, TIM6.handleUPInterrupt)\n\tcase &TIM7:\n\t\treturn interrupt.New(stm32.IRQ_TIM7, TIM7.handleUPInterrupt)\n\tcase &TIM21:\n\t\treturn interrupt.New(stm32.IRQ_TIM21, TIM21.handleUPInterrupt)\n\tcase &TIM22:\n\t\treturn interrupt.New(stm32.IRQ_TIM22, TIM22.handleUPInterrupt)\n\t}\n\n\treturn interrupt.Interrupt{}\n}\n\nfunc (t *TIM) registerOCInterrupt() interrupt.Interrupt {\n\tswitch t {\n\tcase &TIM2:\n\t\treturn interrupt.New(stm32.IRQ_TIM2, TIM2.handleOCInterrupt)\n\tcase &TIM3:\n\t\treturn interrupt.New(stm32.IRQ_TIM3, TIM3.handleOCInterrupt)\n\tcase &TIM6:\n\t\treturn interrupt.New(stm32.IRQ_TIM6_DAC, TIM6.handleOCInterrupt)\n\tcase &TIM7:\n\t\treturn interrupt.New(stm32.IRQ_TIM7, TIM7.handleOCInterrupt)\n\tcase &TIM21:\n\t\treturn interrupt.New(stm32.IRQ_TIM21, TIM21.handleOCInterrupt)\n\tcase &TIM22:\n\t\treturn interrupt.New(stm32.IRQ_TIM22, TIM22.handleOCInterrupt)\n\t}\n\n\treturn interrupt.Interrupt{}\n}\n\nfunc (t *TIM) enableMainOutput() {\n\t// nothing to do - no BDTR register\n}\n\ntype arrtype = uint16\ntype arrRegType = volatile.Register16\n\nconst (\n\tARR_MAX = 0x10000\n\tPSC_MAX = 0x10000\n)\n\nfunc initRNG() {\n\tstm32.RCC.AHBENR.SetBits(stm32.RCC_AHBENR_RNGEN)\n\tstm32.RNG.CR.SetBits(stm32.RNG_CR_RNGEN)\n}\n"
  },
  {
    "path": "src/machine/machine_stm32l4.go",
    "content": "//go:build stm32l4\n\npackage machine\n\nimport (\n\t\"device/stm32\"\n\t\"errors\"\n\t\"internal/binary\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\n// Peripheral abstraction layer for the stm32l4\n\nvar deviceIDAddr = []uintptr{0x1FFF7590, 0x1FFF7594, 0x1FFF7598}\n\nconst (\n\tAF0_SYSTEM             = 0\n\tAF1_TIM1_2_LPTIM1      = 1\n\tAF2_TIM1_2             = 2\n\tAF3_USART2             = 3\n\tAF4_I2C1_2_3           = 4\n\tAF5_SPI1_2             = 5\n\tAF6_SPI3               = 6\n\tAF7_USART1_2_3         = 7\n\tAF8_LPUART1            = 8\n\tAF9_CAN1_TSC           = 9\n\tAF10_USB_QUADSPI       = 10\n\tAF12_COMP1_2_SWPMI1    = 12\n\tAF13_SAI1              = 13\n\tAF14_TIM2_15_16_LPTIM2 = 14\n\tAF15_EVENTOUT          = 15\n)\n\nconst (\n\tPA0  = portA + 0\n\tPA1  = portA + 1\n\tPA2  = portA + 2\n\tPA3  = portA + 3\n\tPA4  = portA + 4\n\tPA5  = portA + 5\n\tPA6  = portA + 6\n\tPA7  = portA + 7\n\tPA8  = portA + 8\n\tPA9  = portA + 9\n\tPA10 = portA + 10\n\tPA11 = portA + 11\n\tPA12 = portA + 12\n\tPA13 = portA + 13\n\tPA14 = portA + 14\n\tPA15 = portA + 15\n\n\tPB0  = portB + 0\n\tPB1  = portB + 1\n\tPB2  = portB + 2\n\tPB3  = portB + 3\n\tPB4  = portB + 4\n\tPB5  = portB + 5\n\tPB6  = portB + 6\n\tPB7  = portB + 7\n\tPB8  = portB + 8\n\tPB9  = portB + 9\n\tPB10 = portB + 10\n\tPB11 = portB + 11\n\tPB12 = portB + 12\n\tPB13 = portB + 13\n\tPB14 = portB + 14\n\tPB15 = portB + 15\n\n\tPC0  = portC + 0\n\tPC1  = portC + 1\n\tPC2  = portC + 2\n\tPC3  = portC + 3\n\tPC4  = portC + 4\n\tPC5  = portC + 5\n\tPC6  = portC + 6\n\tPC7  = portC + 7\n\tPC8  = portC + 8\n\tPC9  = portC + 9\n\tPC10 = portC + 10\n\tPC11 = portC + 11\n\tPC12 = portC + 12\n\tPC13 = portC + 13\n\tPC14 = portC + 14\n\tPC15 = portC + 15\n\n\tPD0  = portD + 0\n\tPD1  = portD + 1\n\tPD2  = portD + 2\n\tPD3  = portD + 3\n\tPD4  = portD + 4\n\tPD5  = portD + 5\n\tPD6  = portD + 6\n\tPD7  = portD + 7\n\tPD8  = portD + 8\n\tPD9  = portD + 9\n\tPD10 = portD + 10\n\tPD11 = portD + 11\n\tPD12 = portD + 12\n\tPD13 = portD + 13\n\tPD14 = portD + 14\n\tPD15 = portD + 15\n\n\tPE0  = portE + 0\n\tPE1  = portE + 1\n\tPE2  = portE + 2\n\tPE3  = portE + 3\n\tPE4  = portE + 4\n\tPE5  = portE + 5\n\tPE6  = portE + 6\n\tPE7  = portE + 7\n\tPE8  = portE + 8\n\tPE9  = portE + 9\n\tPE10 = portE + 10\n\tPE11 = portE + 11\n\tPE12 = portE + 12\n\tPE13 = portE + 13\n\tPE14 = portE + 14\n\tPE15 = portE + 15\n)\n\n// IRQs are defined here as they vary in the SVDs, but do have consistent mapping\n// to Timer Interrupts.\nconst (\n\tirq_TIM1_BRK_TIM15     = 24\n\tirq_TIM1_UP_TIM16      = 25\n\tirq_TIM1_TRG_COM_TIM17 = 26\n\tirq_TIM1_CC            = 27\n\tirq_TIM2               = 28\n\tirq_TIM3               = 29\n\tirq_TIM4               = 30\n\tirq_TIM5               = 50\n\tirq_TIM6               = 54\n\tirq_TIM7               = 55\n\tirq_TIM8_BRK           = 43\n\tirq_TIM8_UP            = 44\n\tirq_TIM8_TRG_COM       = 45\n\tirq_TIM8_CC            = 46\n)\n\nfunc (p Pin) getPort() *stm32.GPIO_Type {\n\tswitch p / 16 {\n\tcase 0:\n\t\treturn stm32.GPIOA\n\tcase 1:\n\t\treturn stm32.GPIOB\n\tcase 2:\n\t\treturn stm32.GPIOC\n\tcase 3:\n\t\treturn stm32.GPIOD\n\tcase 4:\n\t\treturn stm32.GPIOE\n\tdefault:\n\t\tpanic(\"machine: unknown port\")\n\t}\n}\n\n// enableClock enables the clock for this desired GPIO port.\nfunc (p Pin) enableClock() {\n\tswitch p / 16 {\n\tcase 0:\n\t\tstm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_GPIOAEN)\n\tcase 1:\n\t\tstm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_GPIOBEN)\n\tcase 2:\n\t\tstm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_GPIOCEN)\n\tcase 3:\n\t\tstm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_GPIODEN)\n\tcase 4:\n\t\tstm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_GPIOEEN)\n\tdefault:\n\t\tpanic(\"machine: unknown port\")\n\t}\n}\n\n// Enable peripheral clock\nfunc enableAltFuncClock(bus unsafe.Pointer) {\n\tswitch bus {\n\tcase unsafe.Pointer(stm32.PWR): // Power interface clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_PWREN)\n\tcase unsafe.Pointer(stm32.I2C3): // I2C3 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_I2C3EN)\n\tcase unsafe.Pointer(stm32.I2C2): // I2C2 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_I2C2EN)\n\tcase unsafe.Pointer(stm32.I2C1): // I2C1 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_I2C1EN)\n\tcase unsafe.Pointer(stm32.UART4): // UART4 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_UART4EN)\n\tcase unsafe.Pointer(stm32.USART3): // USART3 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_USART3EN)\n\tcase unsafe.Pointer(stm32.USART2): // USART2 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_USART2EN)\n\tcase unsafe.Pointer(stm32.SPI3): // SPI3 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_SPI3EN)\n\tcase unsafe.Pointer(stm32.SPI2): // SPI2 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_SPI2EN)\n\tcase unsafe.Pointer(stm32.WWDG): // Window watchdog clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_WWDGEN)\n\tcase unsafe.Pointer(stm32.TIM7): // TIM7 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_TIM7EN)\n\tcase unsafe.Pointer(stm32.TIM6): // TIM6 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_TIM6EN)\n\tcase unsafe.Pointer(stm32.TIM3): // TIM3 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_TIM3EN)\n\tcase unsafe.Pointer(stm32.TIM2): // TIM2 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_TIM2EN)\n\tcase unsafe.Pointer(stm32.LPTIM2): // LPTIM2 clock enable\n\t\tstm32.RCC.APB1ENR2.SetBits(stm32.RCC_APB1ENR2_LPTIM2EN)\n\tcase unsafe.Pointer(stm32.LPUART1): // LPUART1 clock enable\n\t\tstm32.RCC.APB1ENR2.SetBits(stm32.RCC_APB1ENR2_LPUART1EN)\n\tcase unsafe.Pointer(stm32.TIM16): // TIM16 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM16EN)\n\tcase unsafe.Pointer(stm32.TIM15): // TIM15 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM15EN)\n\tcase unsafe.Pointer(stm32.SYSCFG): // System configuration controller clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SYSCFGEN)\n\tcase unsafe.Pointer(stm32.SPI1): // SPI1 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SPI1EN)\n\tcase unsafe.Pointer(stm32.USART1): // USART1 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART1EN)\n\tcase unsafe.Pointer(stm32.TIM1): // TIM1 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM1EN)\n\t}\n}\n\nfunc handlePinInterrupt(pin uint8) {\n\tif stm32.EXTI.PR1.HasBits(1 << pin) {\n\t\t// Writing 1 to the pending register clears the\n\t\t// pending flag for that bit\n\t\tstm32.EXTI.PR1.Set(1 << pin)\n\n\t\tcallback := pinCallbacks[pin]\n\t\tif callback != nil {\n\t\t\tcallback(interruptPins[pin])\n\t\t}\n\t}\n}\n\nfunc (p Pin) registerInterrupt() interrupt.Interrupt {\n\tpin := uint8(p) % 16\n\n\tswitch pin {\n\tcase 0:\n\t\treturn interrupt.New(stm32.IRQ_EXTI0, func(interrupt.Interrupt) { handlePinInterrupt(0) })\n\tcase 1:\n\t\treturn interrupt.New(stm32.IRQ_EXTI1, func(interrupt.Interrupt) { handlePinInterrupt(1) })\n\tcase 2:\n\t\treturn interrupt.New(stm32.IRQ_EXTI2, func(interrupt.Interrupt) { handlePinInterrupt(2) })\n\tcase 3:\n\t\treturn interrupt.New(stm32.IRQ_EXTI3, func(interrupt.Interrupt) { handlePinInterrupt(3) })\n\tcase 4:\n\t\treturn interrupt.New(stm32.IRQ_EXTI4, func(interrupt.Interrupt) { handlePinInterrupt(4) })\n\tcase 5:\n\t\treturn interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(5) })\n\tcase 6:\n\t\treturn interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(6) })\n\tcase 7:\n\t\treturn interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(7) })\n\tcase 8:\n\t\treturn interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(8) })\n\tcase 9:\n\t\treturn interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(9) })\n\tcase 10:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(10) })\n\tcase 11:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(11) })\n\tcase 12:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(12) })\n\tcase 13:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(13) })\n\tcase 14:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(14) })\n\tcase 15:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(15) })\n\t}\n\n\treturn interrupt.Interrupt{}\n}\n\n//---------- UART related code\n\n// Configure the UART.\nfunc (uart *UART) configurePins(config UARTConfig) {\n\t// enable the alternate functions on the TX and RX pins\n\tconfig.TX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTTX}, uart.TxAltFuncSelector)\n\tconfig.RX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTRX}, uart.RxAltFuncSelector)\n}\n\n// UART baudrate calc based on the bus and clockspeed\n// NOTE: keep this in sync with the runtime/runtime_stm32l5x2.go clock init code\nfunc (uart *UART) getBaudRateDivisor(baudRate uint32) uint32 {\n\treturn (CPUFrequency() / baudRate)\n}\n\n// Register names vary by ST processor, these are for STM L5\nfunc (uart *UART) setRegisters() {\n\tuart.rxReg = &uart.Bus.RDR\n\tuart.txReg = &uart.Bus.TDR\n\tuart.statusReg = &uart.Bus.ISR\n\tuart.txEmptyFlag = stm32.USART_ISR_TXE\n}\n\n//---------- SPI related types and code\n\n// SPI on the STM32Fxxx using MODER / alternate function pins\ntype SPI struct {\n\tBus             *stm32.SPI_Type\n\tAltFuncSelector uint8\n}\n\nfunc (spi *SPI) config8Bits() {\n\t// Set rx threshold to 8-bits, so RXNE flag is set for 1 byte\n\t// (common STM32 SPI implementation does 8-bit transfers only)\n\tspi.Bus.CR2.SetBits(stm32.SPI_CR2_FRXTH)\n}\n\n// Set baud rate for SPI\nfunc (spi *SPI) getBaudRate(config SPIConfig) uint32 {\n\tvar conf uint32\n\n\t// Default\n\tif config.Frequency == 0 {\n\t\tconfig.Frequency = 4e6\n\t}\n\n\tlocalFrequency := config.Frequency\n\n\t// set frequency dependent on PCLK prescaler. Since these are rather weird\n\t// speeds due to the CPU frequency, pick a range up to that frequency for\n\t// clients to use more human-understandable numbers, e.g. nearest 100KHz\n\n\t// These are based on 80MHz peripheral clock frequency\n\tswitch {\n\tcase localFrequency < 312500:\n\t\tconf = stm32.SPI_CR1_BR_Div256\n\tcase localFrequency < 625000:\n\t\tconf = stm32.SPI_CR1_BR_Div128\n\tcase localFrequency < 1250000:\n\t\tconf = stm32.SPI_CR1_BR_Div64\n\tcase localFrequency < 2500000:\n\t\tconf = stm32.SPI_CR1_BR_Div32\n\tcase localFrequency < 5000000:\n\t\tconf = stm32.SPI_CR1_BR_Div16\n\tcase localFrequency < 10000000:\n\t\tconf = stm32.SPI_CR1_BR_Div8\n\t\t// NOTE: many SPI components won't operate reliably (or at all) above 10MHz\n\t\t// Check the datasheet of the part\n\tcase localFrequency < 20000000:\n\t\tconf = stm32.SPI_CR1_BR_Div4\n\tcase localFrequency < 40000000:\n\t\tconf = stm32.SPI_CR1_BR_Div2\n\tdefault:\n\t\t// None of the specific baudrates were selected; choose the lowest speed\n\t\tconf = stm32.SPI_CR1_BR_Div256\n\t}\n\n\treturn conf << stm32.SPI_CR1_BR_Pos\n}\n\n// Configure SPI pins for input output and clock\nfunc (spi *SPI) configurePins(config SPIConfig) {\n\tconfig.SCK.ConfigureAltFunc(PinConfig{Mode: PinModeSPICLK}, spi.AltFuncSelector)\n\tconfig.SDO.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDO}, spi.AltFuncSelector)\n\tconfig.SDI.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDI}, spi.AltFuncSelector)\n}\n\n//---------- Timer related code\n\nvar (\n\tTIM1 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM1EN,\n\t\tDevice:         stm32.TIM1,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA8, AF1_TIM1_2_LPTIM1},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA9, AF1_TIM1_2_LPTIM1},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA10, AF1_TIM1_2_LPTIM1},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA11, AF1_TIM1_2_LPTIM1},\n\t\t\t}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n\n\tTIM2 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR1,\n\t\tEnableFlag:     stm32.RCC_APB1ENR1_TIM2EN,\n\t\tDevice:         stm32.TIM2,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA0, AF1_TIM1_2_LPTIM1},\n\t\t\t\t{PA5, AF1_TIM1_2_LPTIM1},\n\t\t\t\t{PA15, AF1_TIM1_2_LPTIM1},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA1, AF1_TIM1_2_LPTIM1},\n\t\t\t\t{PB3, AF1_TIM1_2_LPTIM1},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA2, AF1_TIM1_2_LPTIM1},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA3, AF1_TIM1_2_LPTIM1},\n\t\t\t}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM3 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR1,\n\t\tEnableFlag:     stm32.RCC_APB1ENR1_TIM3EN,\n\t\tDevice:         stm32.TIM3,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM6 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR1,\n\t\tEnableFlag:     stm32.RCC_APB1ENR1_TIM6EN,\n\t\tDevice:         stm32.TIM6,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM7 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR1,\n\t\tEnableFlag:     stm32.RCC_APB1ENR1_TIM7EN,\n\t\tDevice:         stm32.TIM7,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM15 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM15EN,\n\t\tDevice:         stm32.TIM15,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA2, AF14_TIM2_15_16_LPTIM2},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA3, AF14_TIM2_15_16_LPTIM2},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n\n\tTIM16 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM16EN,\n\t\tDevice:         stm32.TIM16,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{\n\t\t\t\t{PA6, AF14_TIM2_15_16_LPTIM2},\n\t\t\t}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n)\n\nfunc (t *TIM) registerUPInterrupt() interrupt.Interrupt {\n\tswitch t {\n\tcase &TIM1:\n\t\treturn interrupt.New(irq_TIM1_UP_TIM16, TIM1.handleUPInterrupt)\n\tcase &TIM2:\n\t\treturn interrupt.New(irq_TIM2, TIM2.handleUPInterrupt)\n\tcase &TIM3:\n\t\treturn interrupt.New(irq_TIM3, TIM3.handleUPInterrupt)\n\tcase &TIM6:\n\t\treturn interrupt.New(irq_TIM6, TIM6.handleUPInterrupt)\n\tcase &TIM7:\n\t\treturn interrupt.New(irq_TIM7, TIM7.handleUPInterrupt)\n\tcase &TIM15:\n\t\treturn interrupt.New(irq_TIM1_BRK_TIM15, TIM15.handleUPInterrupt)\n\tcase &TIM16:\n\t\treturn interrupt.New(irq_TIM1_UP_TIM16, TIM16.handleUPInterrupt)\n\t}\n\n\treturn interrupt.Interrupt{}\n}\n\nfunc (t *TIM) registerOCInterrupt() interrupt.Interrupt {\n\tswitch t {\n\tcase &TIM1:\n\t\treturn interrupt.New(irq_TIM1_CC, TIM1.handleUPInterrupt)\n\tcase &TIM2:\n\t\treturn interrupt.New(irq_TIM2, TIM2.handleOCInterrupt)\n\tcase &TIM3:\n\t\treturn interrupt.New(irq_TIM3, TIM3.handleOCInterrupt)\n\tcase &TIM6:\n\t\treturn interrupt.New(irq_TIM6, TIM6.handleOCInterrupt)\n\tcase &TIM7:\n\t\treturn interrupt.New(irq_TIM7, TIM7.handleOCInterrupt)\n\tcase &TIM15:\n\t\treturn interrupt.New(irq_TIM1_BRK_TIM15, TIM15.handleOCInterrupt)\n\tcase &TIM16:\n\t\treturn interrupt.New(irq_TIM1_UP_TIM16, TIM16.handleOCInterrupt)\n\t}\n\n\treturn interrupt.Interrupt{}\n}\n\nfunc (t *TIM) enableMainOutput() {\n\t// nothing to do - no BDTR register\n}\n\ntype arrtype = uint32\ntype arrRegType = volatile.Register32\n\nconst (\n\tARR_MAX = 0x10000\n\tPSC_MAX = 0x10000\n)\n\nfunc initRNG() {\n\tstm32.RCC.CRRCR.SetBits(stm32.RCC_CRRCR_HSI48ON)\n\tfor !stm32.RCC.CRRCR.HasBits(stm32.RCC_CRRCR_HSI48RDY) {\n\t}\n\n\tstm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_RNGEN)\n\tstm32.RNG.CR.SetBits(stm32.RNG_CR_RNGEN)\n}\n\n//---------- Flash related code\n\nconst eraseBlockSizeValue = 2048\n\n// see RM0394 page 83\n// eraseBlock of the passed in block number\nfunc eraseBlock(block uint32) error {\n\twaitUntilFlashDone()\n\n\t// clear any previous errors\n\tstm32.FLASH.SR.SetBits(0x3FA)\n\n\t// page erase operation\n\tstm32.FLASH.SetCR_PER(1)\n\tdefer stm32.FLASH.SetCR_PER(0)\n\n\t// set the page to be erased\n\tstm32.FLASH.SetCR_PNB(block)\n\n\t// start the page erase\n\tstm32.FLASH.SetCR_START(1)\n\n\twaitUntilFlashDone()\n\n\tif err := checkError(); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nconst writeBlockSize = 8\n\n// see RM0394 page 84\n// It is only possible to program double word (2 x 32-bit data).\nfunc writeFlashData(address uintptr, data []byte) (int, error) {\n\tif len(data)%writeBlockSize != 0 {\n\t\treturn 0, errFlashInvalidWriteLength\n\t}\n\n\twaitUntilFlashDone()\n\n\t// clear any previous errors\n\tstm32.FLASH.SR.SetBits(0x3FA)\n\n\tfor j := 0; j < len(data); j += writeBlockSize {\n\t\t// start page write operation\n\t\tstm32.FLASH.SetCR_PG(1)\n\n\t\t// write second word using double-word high order word\n\t\t*(*uint32)(unsafe.Pointer(address)) = binary.LittleEndian.Uint32(data[j : j+writeBlockSize/2])\n\n\t\taddress += writeBlockSize / 2\n\n\t\t// write first word using double-word low order word\n\t\t*(*uint32)(unsafe.Pointer(address)) = binary.LittleEndian.Uint32(data[j+writeBlockSize/2 : j+writeBlockSize])\n\n\t\twaitUntilFlashDone()\n\n\t\tif err := checkError(); err != nil {\n\t\t\treturn j, err\n\t\t}\n\n\t\t// end flash write\n\t\tstm32.FLASH.SetCR_PG(0)\n\t\taddress += writeBlockSize / 2\n\t}\n\n\treturn len(data), nil\n}\n\nfunc waitUntilFlashDone() {\n\tfor stm32.FLASH.GetSR_BSY() != 0 {\n\t}\n}\n\nvar (\n\terrFlashPGS  = errors.New(\"errFlashPGS\")\n\terrFlashSIZE = errors.New(\"errFlashSIZE\")\n\terrFlashPGA  = errors.New(\"errFlashPGA\")\n\terrFlashWRP  = errors.New(\"errFlashWRP\")\n\terrFlashPROG = errors.New(\"errFlashPROG\")\n)\n\nfunc checkError() error {\n\tswitch {\n\tcase stm32.FLASH.GetSR_PGSERR() != 0:\n\t\treturn errFlashPGS\n\tcase stm32.FLASH.GetSR_SIZERR() != 0:\n\t\treturn errFlashSIZE\n\tcase stm32.FLASH.GetSR_PGAERR() != 0:\n\t\treturn errFlashPGA\n\tcase stm32.FLASH.GetSR_WRPERR() != 0:\n\t\treturn errFlashWRP\n\tcase stm32.FLASH.GetSR_PROGERR() != 0:\n\t\treturn errFlashPROG\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "src/machine/machine_stm32l4x2.go",
    "content": "//go:build stm32l4x2\n\npackage machine\n\n// Peripheral abstraction layer for the stm32l4x2\n\nfunc CPUFrequency() uint32 {\n\treturn 80000000\n}\n\n// Internal use: configured speed of the APB1 and APB2 timers, this should be kept\n// in sync with any changes to runtime package which configures the oscillators\n// and clock frequencies\nconst APB1_TIM_FREQ = 80e6 // 80MHz\nconst APB2_TIM_FREQ = 80e6 // 80MHz\n\n//---------- I2C related code\n\n// Gets the value for TIMINGR register\nfunc (i2c *I2C) getFreqRange(br uint32) uint32 {\n\t// These are 'magic' values calculated by STM32CubeMX\n\t// for 80MHz PCLK1.\n\t// TODO: Do calculations based on PCLK1\n\tswitch br {\n\tcase 10 * KHz:\n\t\treturn 0xF010F3FE\n\tcase 100 * KHz:\n\t\treturn 0x10909CEC\n\tcase 400 * KHz:\n\t\treturn 0x00702991\n\tcase 500 * KHz:\n\t\treturn 0x00300E84\n\tdefault:\n\t\treturn 0\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_stm32l4x5.go",
    "content": "//go:build stm32l4x5\n\npackage machine\n\n// Peripheral abstraction layer for the stm32l4x5\n\nfunc CPUFrequency() uint32 {\n\treturn 120e6\n}\n\n// Internal use: configured speed of the APB1 and APB2 timers, this should be kept\n// in sync with any changes to runtime package which configures the oscillators\n// and clock frequencies\nconst APB1_TIM_FREQ = 120e6 // 120MHz\nconst APB2_TIM_FREQ = 120e6 // 120MHz\n\n//---------- I2C related code\n\n// Gets the value for TIMINGR register\nfunc (i2c *I2C) getFreqRange(br uint32) uint32 {\n\t// This is a 'magic' value calculated by STM32CubeMX\n\t// for 120MHz PCLK1.\n\t// TODO: Do calculations based on PCLK1\n\tswitch br {\n\tcase 10 * KHz:\n\t\treturn 0x0 // does this even work? zero is weird here.\n\tcase 100 * KHz:\n\t\treturn 0x307075B1\n\tcase 400 * KHz:\n\t\treturn 0x00B03FDB\n\tcase 500 * KHz:\n\t\treturn 0x005017C7\n\tdefault:\n\t\treturn 0\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_stm32l4x6.go",
    "content": "//go:build stm32l4x6\n\npackage machine\n\n// Peripheral abstraction layer for the stm32l4x6\n\nfunc CPUFrequency() uint32 {\n\treturn 80e6\n}\n\n// Internal use: configured speed of the APB1 and APB2 timers, this should be kept\n// in sync with any changes to runtime package which configures the oscillators\n// and clock frequencies\nconst APB1_TIM_FREQ = 80e6 // 80MHz\nconst APB2_TIM_FREQ = 80e6 // 80MHz\n\n//---------- I2C related code\n\n// Gets the value for TIMINGR register\nfunc (i2c *I2C) getFreqRange(br uint32) uint32 {\n\t// This is a 'magic' value calculated by STM32CubeMX\n\t// for 80MHz PCLK1.\n\t// TODO: Do calculations based on PCLK1\n\tswitch br {\n\tcase 10 * KHz:\n\t\treturn 0xF010F3FE\n\tcase 100 * KHz:\n\t\treturn 0x10909CEC\n\tcase 400 * KHz:\n\t\treturn 0x00702991\n\tcase 500 * KHz:\n\t\treturn 0x00300E84\n\tdefault:\n\t\treturn 0\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_stm32l5.go",
    "content": "//go:build stm32l5\n\npackage machine\n\n// Peripheral abstraction layer for the stm32l5\n\nimport (\n\t\"device/stm32\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nvar deviceIDAddr = []uintptr{0x0BFA0590, 0x0BFA0594, 0x0BFA0598}\n\nconst (\n\tAF0_SYSTEM                                = 0\n\tAF1_TIM1_2_5_8_LPTIM1                     = 1\n\tAF2_TIM1_2_3_4_5_LPTIM3                   = 2\n\tAF3_SPI2_SAI1_I2C4_USART2_TIM1_8_OCTOSPI1 = 3\n\tAF4_I2C1_2_3_4                            = 4\n\tAF5_SPI1_2_3_I2C4_DFSDM1_OCTOSPI1         = 5\n\tAF6_SPI3_I2C3_DFSDM1_COMP1                = 6\n\tAF7_USART1_2_3                            = 7\n\tAF8_UART4_5_LPUART1_SDMMC1                = 8\n\tAF9_FDCAN1_TSC                            = 9\n\tAF10_USB_OCTOSPI1                         = 10\n\tAF11_UCPD1                                = 11\n\tAF12_SDMMC1_COMP1_2_TIM1_8_FMC            = 12\n\tAF13_SAI1_2_TIM8                          = 13\n\tAF14_TIM2_8_15_16_17_LPTIM2               = 14\n\tAF15_EVENTOUT                             = 15\n)\n\nconst (\n\tPA0  = portA + 0\n\tPA1  = portA + 1\n\tPA2  = portA + 2\n\tPA3  = portA + 3\n\tPA4  = portA + 4\n\tPA5  = portA + 5\n\tPA6  = portA + 6\n\tPA7  = portA + 7\n\tPA8  = portA + 8\n\tPA9  = portA + 9\n\tPA10 = portA + 10\n\tPA11 = portA + 11\n\tPA12 = portA + 12\n\tPA13 = portA + 13\n\tPA14 = portA + 14\n\tPA15 = portA + 15\n\n\tPB0  = portB + 0\n\tPB1  = portB + 1\n\tPB2  = portB + 2\n\tPB3  = portB + 3\n\tPB4  = portB + 4\n\tPB5  = portB + 5\n\tPB6  = portB + 6\n\tPB7  = portB + 7\n\tPB8  = portB + 8\n\tPB9  = portB + 9\n\tPB10 = portB + 10\n\tPB11 = portB + 11\n\tPB12 = portB + 12\n\tPB13 = portB + 13\n\tPB14 = portB + 14\n\tPB15 = portB + 15\n\n\tPC0  = portC + 0\n\tPC1  = portC + 1\n\tPC2  = portC + 2\n\tPC3  = portC + 3\n\tPC4  = portC + 4\n\tPC5  = portC + 5\n\tPC6  = portC + 6\n\tPC7  = portC + 7\n\tPC8  = portC + 8\n\tPC9  = portC + 9\n\tPC10 = portC + 10\n\tPC11 = portC + 11\n\tPC12 = portC + 12\n\tPC13 = portC + 13\n\tPC14 = portC + 14\n\tPC15 = portC + 15\n\n\tPD0  = portD + 0\n\tPD1  = portD + 1\n\tPD2  = portD + 2\n\tPD3  = portD + 3\n\tPD4  = portD + 4\n\tPD5  = portD + 5\n\tPD6  = portD + 6\n\tPD7  = portD + 7\n\tPD8  = portD + 8\n\tPD9  = portD + 9\n\tPD10 = portD + 10\n\tPD11 = portD + 11\n\tPD12 = portD + 12\n\tPD13 = portD + 13\n\tPD14 = portD + 14\n\tPD15 = portD + 15\n\n\tPE0  = portE + 0\n\tPE1  = portE + 1\n\tPE2  = portE + 2\n\tPE3  = portE + 3\n\tPE4  = portE + 4\n\tPE5  = portE + 5\n\tPE6  = portE + 6\n\tPE7  = portE + 7\n\tPE8  = portE + 8\n\tPE9  = portE + 9\n\tPE10 = portE + 10\n\tPE11 = portE + 11\n\tPE12 = portE + 12\n\tPE13 = portE + 13\n\tPE14 = portE + 14\n\tPE15 = portE + 15\n\n\tPF0  = portF + 0\n\tPF1  = portF + 1\n\tPF2  = portF + 2\n\tPF3  = portF + 3\n\tPF4  = portF + 4\n\tPF5  = portF + 5\n\tPF6  = portF + 6\n\tPF7  = portF + 7\n\tPF8  = portF + 8\n\tPF9  = portF + 9\n\tPF10 = portF + 10\n\tPF11 = portF + 11\n\tPF12 = portF + 12\n\tPF13 = portF + 13\n\tPF14 = portF + 14\n\tPF15 = portF + 15\n\n\tPG0  = portG + 0\n\tPG1  = portG + 1\n\tPG2  = portG + 2\n\tPG3  = portG + 3\n\tPG4  = portG + 4\n\tPG5  = portG + 5\n\tPG6  = portG + 6\n\tPG7  = portG + 7\n\tPG8  = portG + 8\n\tPG9  = portG + 9\n\tPG10 = portG + 10\n\tPG11 = portG + 11\n\tPG12 = portG + 12\n\tPG13 = portG + 13\n\tPG14 = portG + 14\n\tPG15 = portG + 15\n\n\tPH0 = portH + 0\n\tPH1 = portH + 1\n)\n\nfunc (p Pin) getPort() *stm32.GPIO_Type {\n\tswitch p / 16 {\n\tcase 0:\n\t\treturn stm32.GPIOA\n\tcase 1:\n\t\treturn stm32.GPIOB\n\tcase 2:\n\t\treturn stm32.GPIOC\n\tcase 3:\n\t\treturn stm32.GPIOD\n\tcase 4:\n\t\treturn stm32.GPIOE\n\tcase 5:\n\t\treturn stm32.GPIOF\n\tcase 6:\n\t\treturn stm32.GPIOG\n\tcase 7:\n\t\treturn stm32.GPIOH\n\tdefault:\n\t\tpanic(\"machine: unknown port\")\n\t}\n}\n\n// enableClock enables the clock for this desired GPIO port.\nfunc (p Pin) enableClock() {\n\tswitch p / 16 {\n\tcase 0:\n\t\tstm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_GPIOAEN)\n\tcase 1:\n\t\tstm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_GPIOBEN)\n\tcase 2:\n\t\tstm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_GPIOCEN)\n\tcase 3:\n\t\tstm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_GPIODEN)\n\tcase 4:\n\t\tstm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_GPIOEEN)\n\tcase 5:\n\t\tstm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_GPIOFEN)\n\tcase 6:\n\t\tstm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_GPIOGEN)\n\tcase 7:\n\t\tstm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_GPIOHEN)\n\tdefault:\n\t\tpanic(\"machine: unknown port\")\n\t}\n}\n\n// Enable peripheral clock\nfunc enableAltFuncClock(bus unsafe.Pointer) {\n\tswitch bus {\n\tcase unsafe.Pointer(stm32.DAC): // DAC interface clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_DAC1EN)\n\tcase unsafe.Pointer(stm32.PWR): // Power interface clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_PWREN)\n\tcase unsafe.Pointer(stm32.I2C3): // I2C3 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_I2C3EN)\n\tcase unsafe.Pointer(stm32.I2C2): // I2C2 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_I2C2EN)\n\tcase unsafe.Pointer(stm32.I2C1): // I2C1 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_I2C1EN)\n\tcase unsafe.Pointer(stm32.UART5): // UART5 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_UART5EN)\n\tcase unsafe.Pointer(stm32.UART4): // UART4 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_UART4EN)\n\tcase unsafe.Pointer(stm32.USART3): // USART3 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_USART3EN)\n\tcase unsafe.Pointer(stm32.USART2): // USART2 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_USART2EN)\n\tcase unsafe.Pointer(stm32.SPI3): // SPI3 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_SP3EN)\n\tcase unsafe.Pointer(stm32.SPI2): // SPI2 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_SPI2EN)\n\tcase unsafe.Pointer(stm32.WWDG): // Window watchdog clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_WWDGEN)\n\tcase unsafe.Pointer(stm32.TIM7): // TIM7 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_TIM7EN)\n\tcase unsafe.Pointer(stm32.TIM6): // TIM6 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_TIM6EN)\n\tcase unsafe.Pointer(stm32.TIM5): // TIM5 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_TIM5EN)\n\tcase unsafe.Pointer(stm32.TIM4): // TIM4 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_TIM4EN)\n\tcase unsafe.Pointer(stm32.TIM3): // TIM3 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_TIM3EN)\n\tcase unsafe.Pointer(stm32.TIM2): // TIM2 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_TIM2EN)\n\tcase unsafe.Pointer(stm32.UCPD1): // UCPD1 clock enable\n\t\tstm32.RCC.APB1ENR2.SetBits(stm32.RCC_APB1ENR2_UCPD1EN)\n\tcase unsafe.Pointer(stm32.FDCAN1): // FDCAN1 clock enable\n\t\tstm32.RCC.APB1ENR2.SetBits(stm32.RCC_APB1ENR2_FDCAN1EN)\n\tcase unsafe.Pointer(stm32.LPTIM3): // LPTIM3 clock enable\n\t\tstm32.RCC.APB1ENR2.SetBits(stm32.RCC_APB1ENR2_LPTIM3EN)\n\tcase unsafe.Pointer(stm32.LPTIM2): // LPTIM2 clock enable\n\t\tstm32.RCC.APB1ENR2.SetBits(stm32.RCC_APB1ENR2_LPTIM2EN)\n\tcase unsafe.Pointer(stm32.I2C4): // I2C4 clock enable\n\t\tstm32.RCC.APB1ENR2.SetBits(stm32.RCC_APB1ENR2_I2C4EN)\n\tcase unsafe.Pointer(stm32.LPUART1): // LPUART1 clock enable\n\t\tstm32.RCC.APB1ENR2.SetBits(stm32.RCC_APB1ENR2_LPUART1EN)\n\tcase unsafe.Pointer(stm32.TIM17): // TIM17 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM17EN)\n\tcase unsafe.Pointer(stm32.TIM16): // TIM16 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM16EN)\n\tcase unsafe.Pointer(stm32.TIM15): // TIM15 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM15EN)\n\tcase unsafe.Pointer(stm32.SYSCFG): // System configuration controller clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SYSCFGEN)\n\tcase unsafe.Pointer(stm32.SPI1): // SPI1 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SPI1EN)\n\tcase unsafe.Pointer(stm32.USART1): // USART1 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART1EN)\n\tcase unsafe.Pointer(stm32.TIM8): // TIM8 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM8EN)\n\tcase unsafe.Pointer(stm32.TIM1): // TIM1 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM1EN)\n\t}\n}\n\nfunc (p Pin) registerInterrupt() interrupt.Interrupt {\n\tpin := uint8(p) % 16\n\n\tswitch pin {\n\tcase 0:\n\t\treturn interrupt.New(stm32.IRQ_EXTI0, func(interrupt.Interrupt) { handlePinInterrupt(0) })\n\tcase 1:\n\t\treturn interrupt.New(stm32.IRQ_EXTI1, func(interrupt.Interrupt) { handlePinInterrupt(1) })\n\tcase 2:\n\t\treturn interrupt.New(stm32.IRQ_EXTI2, func(interrupt.Interrupt) { handlePinInterrupt(2) })\n\tcase 3:\n\t\treturn interrupt.New(stm32.IRQ_EXTI3, func(interrupt.Interrupt) { handlePinInterrupt(3) })\n\tcase 4:\n\t\treturn interrupt.New(stm32.IRQ_EXTI4, func(interrupt.Interrupt) { handlePinInterrupt(4) })\n\tcase 5:\n\t\treturn interrupt.New(stm32.IRQ_EXTI5, func(interrupt.Interrupt) { handlePinInterrupt(5) })\n\tcase 6:\n\t\treturn interrupt.New(stm32.IRQ_EXTI6, func(interrupt.Interrupt) { handlePinInterrupt(6) })\n\tcase 7:\n\t\treturn interrupt.New(stm32.IRQ_EXTI7, func(interrupt.Interrupt) { handlePinInterrupt(7) })\n\tcase 8:\n\t\treturn interrupt.New(stm32.IRQ_EXTI8, func(interrupt.Interrupt) { handlePinInterrupt(8) })\n\tcase 9:\n\t\treturn interrupt.New(stm32.IRQ_EXTI9, func(interrupt.Interrupt) { handlePinInterrupt(9) })\n\tcase 10:\n\t\treturn interrupt.New(stm32.IRQ_EXTI10, func(interrupt.Interrupt) { handlePinInterrupt(10) })\n\tcase 11:\n\t\treturn interrupt.New(stm32.IRQ_EXTI11, func(interrupt.Interrupt) { handlePinInterrupt(11) })\n\tcase 12:\n\t\treturn interrupt.New(stm32.IRQ_EXTI12, func(interrupt.Interrupt) { handlePinInterrupt(12) })\n\tcase 13:\n\t\treturn interrupt.New(stm32.IRQ_EXTI13, func(interrupt.Interrupt) { handlePinInterrupt(13) })\n\tcase 14:\n\t\treturn interrupt.New(stm32.IRQ_EXTI14, func(interrupt.Interrupt) { handlePinInterrupt(14) })\n\tcase 15:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15, func(interrupt.Interrupt) { handlePinInterrupt(15) })\n\t}\n\n\treturn interrupt.Interrupt{}\n}\n\nfunc handlePinInterrupt(pin uint8) {\n\t// The pin abstraction doesn't differentiate pull-up\n\t// events from pull-down events, so combine them to\n\t// a single call here.\n\n\tif stm32.EXTI.RPR1.HasBits(1<<pin) || stm32.EXTI.FPR1.HasBits(1<<pin) {\n\t\t// Writing 1 to the pending register clears the\n\t\t// pending flag for that bit\n\t\tstm32.EXTI.RPR1.Set(1 << pin)\n\t\tstm32.EXTI.FPR1.Set(1 << pin)\n\n\t\tcallback := pinCallbacks[pin]\n\t\tif callback != nil {\n\t\t\tcallback(interruptPins[pin])\n\t\t}\n\t}\n}\n\n//---------- Timer related code\n\nvar (\n\tTIM1 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM1EN,\n\t\tDevice:         stm32.TIM1,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PA8, AF1_TIM1_2_5_8_LPTIM1}, {PE9, AF1_TIM1_2_5_8_LPTIM1}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA9, AF1_TIM1_2_5_8_LPTIM1}, {PE11, AF1_TIM1_2_5_8_LPTIM1}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA10, AF1_TIM1_2_5_8_LPTIM1}, {PE13, AF1_TIM1_2_5_8_LPTIM1}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA11, AF1_TIM1_2_5_8_LPTIM1}, {PE14, AF1_TIM1_2_5_8_LPTIM1}}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n\n\tTIM2 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR1,\n\t\tEnableFlag:     stm32.RCC_APB1ENR1_TIM2EN,\n\t\tDevice:         stm32.TIM2,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PA0, AF1_TIM1_2_5_8_LPTIM1}, {PA5, AF1_TIM1_2_5_8_LPTIM1}, {PA15, AF1_TIM1_2_5_8_LPTIM1}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA1, AF1_TIM1_2_5_8_LPTIM1}, {PB3, AF1_TIM1_2_5_8_LPTIM1}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA2, AF1_TIM1_2_5_8_LPTIM1}, {PB10, AF1_TIM1_2_5_8_LPTIM1}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA3, AF1_TIM1_2_5_8_LPTIM1}, {PB11, AF1_TIM1_2_5_8_LPTIM1}}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM3 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR1,\n\t\tEnableFlag:     stm32.RCC_APB1ENR1_TIM3EN,\n\t\tDevice:         stm32.TIM3,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PA6, AF2_TIM1_2_3_4_5_LPTIM3}, {PB4, AF2_TIM1_2_3_4_5_LPTIM3}, {PC6, AF2_TIM1_2_3_4_5_LPTIM3}, {PE3, AF2_TIM1_2_3_4_5_LPTIM3}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA7, AF2_TIM1_2_3_4_5_LPTIM3}, {PB5, AF2_TIM1_2_3_4_5_LPTIM3}, {PC7, AF2_TIM1_2_3_4_5_LPTIM3}, {PE4, AF2_TIM1_2_3_4_5_LPTIM3}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PB0, AF2_TIM1_2_3_4_5_LPTIM3}, {PC8, AF2_TIM1_2_3_4_5_LPTIM3}, {PE5, AF2_TIM1_2_3_4_5_LPTIM3}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PB1, AF2_TIM1_2_3_4_5_LPTIM3}, {PC9, AF2_TIM1_2_3_4_5_LPTIM3}, {PE6, AF2_TIM1_2_3_4_5_LPTIM3}}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM4 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR1,\n\t\tEnableFlag:     stm32.RCC_APB1ENR1_TIM4EN,\n\t\tDevice:         stm32.TIM4,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PB6, AF2_TIM1_2_3_4_5_LPTIM3}, {PD12, AF2_TIM1_2_3_4_5_LPTIM3}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PB7, AF2_TIM1_2_3_4_5_LPTIM3}, {PD13, AF2_TIM1_2_3_4_5_LPTIM3}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PB8, AF2_TIM1_2_3_4_5_LPTIM3}, {PD14, AF2_TIM1_2_3_4_5_LPTIM3}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PB9, AF2_TIM1_2_3_4_5_LPTIM3}, {PD15, AF2_TIM1_2_3_4_5_LPTIM3}}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM5 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR1,\n\t\tEnableFlag:     stm32.RCC_APB1ENR1_TIM5EN,\n\t\tDevice:         stm32.TIM5,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PA0, AF2_TIM1_2_3_4_5_LPTIM3}, {PF6, AF2_TIM1_2_3_4_5_LPTIM3}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA1, AF2_TIM1_2_3_4_5_LPTIM3}, {PF7, AF2_TIM1_2_3_4_5_LPTIM3}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA2, AF2_TIM1_2_3_4_5_LPTIM3}, {PF8, AF2_TIM1_2_3_4_5_LPTIM3}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA3, AF2_TIM1_2_3_4_5_LPTIM3}, {PF9, AF2_TIM1_2_3_4_5_LPTIM3}}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM6 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR1,\n\t\tEnableFlag:     stm32.RCC_APB1ENR1_TIM6EN,\n\t\tDevice:         stm32.TIM6,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM7 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR1,\n\t\tEnableFlag:     stm32.RCC_APB1ENR1_TIM7EN,\n\t\tDevice:         stm32.TIM7,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\n\tTIM8 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM8EN,\n\t\tDevice:         stm32.TIM8,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PC6, AF3_SPI2_SAI1_I2C4_USART2_TIM1_8_OCTOSPI1}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PC7, AF3_SPI2_SAI1_I2C4_USART2_TIM1_8_OCTOSPI1}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PC8, AF3_SPI2_SAI1_I2C4_USART2_TIM1_8_OCTOSPI1}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PC9, AF3_SPI2_SAI1_I2C4_USART2_TIM1_8_OCTOSPI1}}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n\n\tTIM15 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM15EN,\n\t\tDevice:         stm32.TIM15,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PA1, AF14_TIM2_8_15_16_17_LPTIM2}, {PB14, AF14_TIM2_8_15_16_17_LPTIM2}, {PF9, AF14_TIM2_8_15_16_17_LPTIM2}, {PG10, AF14_TIM2_8_15_16_17_LPTIM2}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA2, AF14_TIM2_8_15_16_17_LPTIM2}, {PB15, AF14_TIM2_8_15_16_17_LPTIM2}, {PF10, AF14_TIM2_8_15_16_17_LPTIM2}, {PG11, AF14_TIM2_8_15_16_17_LPTIM2}}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n\n\tTIM16 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM16EN,\n\t\tDevice:         stm32.TIM16,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PA6, AF14_TIM2_8_15_16_17_LPTIM2}, {PB8, AF14_TIM2_8_15_16_17_LPTIM2}, {PE0, AF14_TIM2_8_15_16_17_LPTIM2}}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n\n\tTIM17 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM17EN,\n\t\tDevice:         stm32.TIM17,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PA7, AF14_TIM2_8_15_16_17_LPTIM2}, {PB9, AF14_TIM2_8_15_16_17_LPTIM2}, {PE1, AF14_TIM2_8_15_16_17_LPTIM2}}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n)\n\nfunc (t *TIM) registerUPInterrupt() interrupt.Interrupt {\n\tswitch t {\n\tcase &TIM1:\n\t\treturn interrupt.New(stm32.IRQ_TIM1_UP, TIM1.handleUPInterrupt)\n\tcase &TIM2:\n\t\treturn interrupt.New(stm32.IRQ_TIM2, TIM2.handleUPInterrupt)\n\tcase &TIM3:\n\t\treturn interrupt.New(stm32.IRQ_TIM3, TIM3.handleUPInterrupt)\n\tcase &TIM4:\n\t\treturn interrupt.New(stm32.IRQ_TIM4, TIM4.handleUPInterrupt)\n\tcase &TIM5:\n\t\treturn interrupt.New(stm32.IRQ_TIM5, TIM5.handleUPInterrupt)\n\tcase &TIM6:\n\t\treturn interrupt.New(stm32.IRQ_TIM6, TIM6.handleUPInterrupt)\n\tcase &TIM7:\n\t\treturn interrupt.New(stm32.IRQ_TIM7, TIM7.handleUPInterrupt)\n\tcase &TIM8:\n\t\treturn interrupt.New(stm32.IRQ_TIM8_UP, TIM8.handleUPInterrupt)\n\tcase &TIM15:\n\t\treturn interrupt.New(stm32.IRQ_TIM15, TIM15.handleUPInterrupt)\n\tcase &TIM16:\n\t\treturn interrupt.New(stm32.IRQ_TIM16, TIM16.handleUPInterrupt)\n\tcase &TIM17:\n\t\treturn interrupt.New(stm32.IRQ_TIM17, TIM17.handleUPInterrupt)\n\t}\n\n\treturn interrupt.Interrupt{}\n}\n\nfunc (t *TIM) registerOCInterrupt() interrupt.Interrupt {\n\tswitch t {\n\tcase &TIM1:\n\t\treturn interrupt.New(stm32.IRQ_TIM1_CC, TIM1.handleOCInterrupt)\n\tcase &TIM2:\n\t\treturn interrupt.New(stm32.IRQ_TIM2, TIM2.handleOCInterrupt)\n\tcase &TIM3:\n\t\treturn interrupt.New(stm32.IRQ_TIM3, TIM3.handleOCInterrupt)\n\tcase &TIM4:\n\t\treturn interrupt.New(stm32.IRQ_TIM4, TIM4.handleOCInterrupt)\n\tcase &TIM5:\n\t\treturn interrupt.New(stm32.IRQ_TIM5, TIM5.handleOCInterrupt)\n\tcase &TIM6:\n\t\treturn interrupt.New(stm32.IRQ_TIM6, TIM6.handleOCInterrupt)\n\tcase &TIM7:\n\t\treturn interrupt.New(stm32.IRQ_TIM7, TIM7.handleOCInterrupt)\n\tcase &TIM8:\n\t\treturn interrupt.New(stm32.IRQ_TIM8_CC, TIM8.handleOCInterrupt)\n\tcase &TIM15:\n\t\treturn interrupt.New(stm32.IRQ_TIM15, TIM15.handleOCInterrupt)\n\tcase &TIM16:\n\t\treturn interrupt.New(stm32.IRQ_TIM16, TIM16.handleOCInterrupt)\n\tcase &TIM17:\n\t\treturn interrupt.New(stm32.IRQ_TIM17, TIM17.handleOCInterrupt)\n\t}\n\n\treturn interrupt.Interrupt{}\n}\n\nfunc (t *TIM) enableMainOutput() {\n\tt.Device.BDTR.SetBits(stm32.TIM_BDTR_MOE)\n}\n\ntype arrtype = uint32\ntype arrRegType = volatile.Register32\n\nconst (\n\tARR_MAX = 0x10000\n\tPSC_MAX = 0x10000\n)\n\nfunc initRNG() {\n\tstm32.RCC.CRRCR.SetBits(stm32.RCC_CRRCR_HSI48ON)\n\tfor !stm32.RCC.CRRCR.HasBits(stm32.RCC_CRRCR_HSI48RDY) {\n\t}\n\n\tstm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_RNGEN)\n\tstm32.RNG.CR.SetBits(stm32.RNG_CR_RNGEN)\n}\n"
  },
  {
    "path": "src/machine/machine_stm32l5x2.go",
    "content": "//go:build stm32l5x2\n\npackage machine\n\n// Peripheral abstraction layer for the stm32f407\n\nimport (\n\t\"device/stm32\"\n)\n\nfunc CPUFrequency() uint32 {\n\treturn 110000000\n}\n\n// Internal use: configured speed of the APB1 and APB2 timers, this should be kept\n// in sync with any changes to runtime package which configures the oscillators\n// and clock frequencies\nconst APB1_TIM_FREQ = 110e6 // 110MHz\nconst APB2_TIM_FREQ = 110e6 // 110MHz\n\n//---------- UART related code\n\n// Configure the UART.\nfunc (uart *UART) configurePins(config UARTConfig) {\n\tif config.RX.getPort() == stm32.GPIOG || config.TX.getPort() == stm32.GPIOG {\n\t\t// Enable VDDIO2 power supply, which is an independent power supply for the PGx pins\n\t\tstm32.PWR.CR2.SetBits(stm32.PWR_CR2_IOSV)\n\t}\n\n\t// enable the alternate functions on the TX and RX pins\n\tconfig.TX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTTX}, uart.TxAltFuncSelector)\n\tconfig.RX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTRX}, uart.RxAltFuncSelector)\n}\n\n// UART baudrate calc based on the bus and clockspeed\n// NOTE: keep this in sync with the runtime/runtime_stm32l5x2.go clock init code\nfunc (uart *UART) getBaudRateDivisor(baudRate uint32) uint32 {\n\treturn 256 * (CPUFrequency() / baudRate)\n}\n\n// Register names vary by ST processor, these are for STM L5\nfunc (uart *UART) setRegisters() {\n\tuart.rxReg = &uart.Bus.RDR\n\tuart.txReg = &uart.Bus.TDR\n\tuart.statusReg = &uart.Bus.ISR\n\tuart.txEmptyFlag = stm32.USART_ISR_TXE\n}\n\n//---------- I2C related code\n\n// Gets the value for TIMINGR register\nfunc (i2c *I2C) getFreqRange(br uint32) uint32 {\n\t// This is a 'magic' value calculated by STM32CubeMX\n\t// for 110MHz PCLK1.\n\t// TODO: Do calculations based on PCLK1\n\tswitch br {\n\tcase 10 * KHz:\n\t\treturn 0x0 // does this even work? zero is weird here.\n\tcase 100 * KHz:\n\t\treturn 0x40505681\n\tcase 400 * KHz:\n\t\treturn 0x00A03AC8\n\tcase 500 * KHz:\n\t\treturn 0x005015B6\n\tdefault:\n\t\treturn 0\n\t}\n}\n"
  },
  {
    "path": "src/machine/machine_stm32wlx.go",
    "content": "//go:build stm32wlx\n\npackage machine\n\n// Peripheral abstraction layer for the stm32wle5\n\nimport (\n\t\"device/stm32\"\n\t\"errors\"\n\t\"internal/binary\"\n\t\"math/bits\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nvar deviceIDAddr = []uintptr{0x1FFF7590, 0x1FFF7594, 0x1FFF7598}\n\nconst (\n\tAF0_SYSTEM             = 0\n\tAF1_TIM1_2_LPTIM1      = 1\n\tAF2_TIM1_2             = 2\n\tAF3_SPIS2_TIM1_LPTIM3  = 3\n\tAF4_I2C1_2_3           = 4\n\tAF5_SPI1_SPI2S2        = 5\n\tAF6_RF                 = 6\n\tAF7_USART1_2           = 7\n\tAF8_LPUART1            = 8\n\tAF12_COMP1_2_TIM1      = 12\n\tAF13_DEBUG             = 13\n\tAF14_TIM2_16_17_LPTIM2 = 14\n\tAF15_EVENTOUT          = 15\n)\n\nconst (\n\tSYSCLK        = 48e6\n\tAPB1_TIM_FREQ = SYSCLK\n\tAPB2_TIM_FREQ = SYSCLK\n)\n\nfunc CPUFrequency() uint32 {\n\treturn SYSCLK\n}\n\nconst (\n\tPA0  = portA + 0\n\tPA1  = portA + 1\n\tPA2  = portA + 2\n\tPA3  = portA + 3\n\tPA4  = portA + 4\n\tPA5  = portA + 5\n\tPA6  = portA + 6\n\tPA7  = portA + 7\n\tPA8  = portA + 8\n\tPA9  = portA + 9\n\tPA10 = portA + 10\n\tPA11 = portA + 11\n\tPA12 = portA + 12\n\tPA13 = portA + 13\n\tPA14 = portA + 14\n\tPA15 = portA + 15\n\n\tPB0  = portB + 0\n\tPB1  = portB + 1\n\tPB2  = portB + 2\n\tPB3  = portB + 3\n\tPB4  = portB + 4\n\tPB5  = portB + 5\n\tPB6  = portB + 6\n\tPB7  = portB + 7\n\tPB8  = portB + 8\n\tPB9  = portB + 9\n\tPB10 = portB + 10\n\tPB11 = portB + 11\n\tPB12 = portB + 12\n\tPB13 = portB + 13\n\tPB14 = portB + 14\n\tPB15 = portB + 15\n\n\tPC0  = portC + 0\n\tPC1  = portC + 1\n\tPC2  = portC + 2\n\tPC3  = portC + 3\n\tPC4  = portC + 4\n\tPC5  = portC + 5\n\tPC6  = portC + 6\n\tPC7  = portC + 7\n\tPC8  = portC + 8\n\tPC9  = portC + 9\n\tPC10 = portC + 10\n\tPC11 = portC + 11\n\tPC12 = portC + 12\n\tPC13 = portC + 13\n\tPC14 = portC + 14\n\tPC15 = portC + 15\n\n\tPH3 = portH + 3\n)\n\nfunc (p Pin) getPort() *stm32.GPIO_Type {\n\tswitch p / 16 {\n\tcase 0:\n\t\treturn stm32.GPIOA\n\tcase 1:\n\t\treturn stm32.GPIOB\n\tcase 2:\n\t\treturn stm32.GPIOC\n\tcase 7:\n\t\treturn stm32.GPIOH\n\tdefault:\n\t\tpanic(\"machine: unknown port\")\n\t}\n}\n\n// enableClock enables the clock for this desired GPIO port.\nfunc (p Pin) enableClock() {\n\tswitch p / 16 {\n\tcase 0:\n\t\tstm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_GPIOAEN)\n\tcase 1:\n\t\tstm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_GPIOBEN)\n\tcase 2:\n\t\tstm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_GPIOCEN)\n\tcase 7:\n\t\tstm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_GPIOHEN)\n\tdefault:\n\t\tpanic(\"machine: unknown port\")\n\t}\n}\n\n// Enable peripheral clock\nfunc enableAltFuncClock(bus unsafe.Pointer) {\n\tswitch bus {\n\t// APB1ENR1\n\tcase unsafe.Pointer(stm32.LPTIM1): // LPTIM1 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_LPTIM1EN)\n\tcase unsafe.Pointer(stm32.DAC): // DAC clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_DAC1EN)\n\tcase unsafe.Pointer(stm32.I2C3): // I2C3 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_I2C3EN)\n\tcase unsafe.Pointer(stm32.I2C2): // I2C2 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_I2C2EN)\n\tcase unsafe.Pointer(stm32.I2C1): // I2C1 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_I2C1EN)\n\tcase unsafe.Pointer(stm32.USART2): // USART2 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_USART2EN)\n\tcase unsafe.Pointer(stm32.SPI2): // SPI2S2 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_SPI2S2EN)\n\tcase unsafe.Pointer(stm32.WWDG): // Window watchdog clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_WWDGEN)\n\tcase unsafe.Pointer(stm32.TIM2): // TIM2 clock enable\n\t\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_TIM2EN)\n\t// APB1ENR2\n\tcase unsafe.Pointer(stm32.LPTIM3): // LPTIM3 clock enable\n\t\tstm32.RCC.APB1ENR2.SetBits(stm32.RCC_APB1ENR2_LPTIM3EN)\n\tcase unsafe.Pointer(stm32.LPTIM2): // LPTIM2 clock enable\n\t\tstm32.RCC.APB1ENR2.SetBits(stm32.RCC_APB1ENR2_LPTIM2EN)\n\tcase unsafe.Pointer(stm32.LPUART): // LPUART clock enable\n\t\tstm32.RCC.APB1ENR2.SetBits(stm32.RCC_APB1ENR2_LPUART1EN)\n\t//APB2ENR\n\tcase unsafe.Pointer(stm32.TIM17): // TIM17 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM17EN)\n\tcase unsafe.Pointer(stm32.TIM16): // TIM16 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM16EN)\n\tcase unsafe.Pointer(stm32.USART1): // USART1 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART1EN)\n\tcase unsafe.Pointer(stm32.SPI1): // SPI1 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SPI1EN)\n\tcase unsafe.Pointer(stm32.TIM1): // TIM1 clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM1EN)\n\tcase unsafe.Pointer(stm32.ADC): // ADC clock enable\n\t\tstm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_ADCEN)\n\n\t}\n}\n\nfunc handlePinInterrupt(pin uint8) {\n\tif stm32.EXTI.PR1.HasBits(1 << pin) {\n\t\t// Writing 1 to the pending register clears the\n\t\t// pending flag for that bit\n\t\tstm32.EXTI.PR1.Set(1 << pin)\n\n\t\tcallback := pinCallbacks[pin]\n\t\tif callback != nil {\n\t\t\tcallback(interruptPins[pin])\n\t\t}\n\t}\n}\n\nfunc (p Pin) registerInterrupt() interrupt.Interrupt {\n\tpin := uint8(p) % 16\n\n\tswitch pin {\n\tcase 0:\n\t\treturn interrupt.New(stm32.IRQ_EXTI0, func(interrupt.Interrupt) { handlePinInterrupt(0) })\n\tcase 1:\n\t\treturn interrupt.New(stm32.IRQ_EXTI1, func(interrupt.Interrupt) { handlePinInterrupt(1) })\n\tcase 2:\n\t\treturn interrupt.New(stm32.IRQ_EXTI2, func(interrupt.Interrupt) { handlePinInterrupt(2) })\n\tcase 3:\n\t\treturn interrupt.New(stm32.IRQ_EXTI3, func(interrupt.Interrupt) { handlePinInterrupt(3) })\n\tcase 4:\n\t\treturn interrupt.New(stm32.IRQ_EXTI4, func(interrupt.Interrupt) { handlePinInterrupt(4) })\n\tcase 5:\n\t\treturn interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(5) })\n\tcase 6:\n\t\treturn interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(6) })\n\tcase 7:\n\t\treturn interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(7) })\n\tcase 8:\n\t\treturn interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(8) })\n\tcase 9:\n\t\treturn interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(9) })\n\tcase 10:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(10) })\n\tcase 11:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(11) })\n\tcase 12:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(12) })\n\tcase 13:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(13) })\n\tcase 14:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(14) })\n\tcase 15:\n\t\treturn interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(15) })\n\t}\n\n\treturn interrupt.Interrupt{}\n}\n\n// -- SPI ----------------------------------------------------------------------\n\ntype SPI struct {\n\tBus             *stm32.SPI_Type\n\tAltFuncSelector uint8\n}\n\nfunc (spi *SPI) config8Bits() {\n\t// Set rx threshold to 8-bits, so RXNE flag is set for 1 byte\n\t// (common STM32 SPI implementation does 8-bit transfers only)\n\tspi.Bus.CR2.SetBits(stm32.SPI_CR2_FRXTH)\n}\n\nfunc (spi *SPI) configurePins(config SPIConfig) {\n\tconfig.SCK.ConfigureAltFunc(PinConfig{Mode: PinModeSPICLK}, spi.AltFuncSelector)\n\tconfig.SDO.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDO}, spi.AltFuncSelector)\n\tconfig.SDI.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDI}, spi.AltFuncSelector)\n}\n\nfunc (spi *SPI) getBaudRate(config SPIConfig) uint32 {\n\tvar clock uint32\n\n\t// We keep this switch and separate management of SPI Clocks\n\t// for future improvement of system/bus clocks and prescalers\n\tswitch spi.Bus {\n\tcase stm32.SPI1:\n\t\tclock = CPUFrequency()\n\tcase stm32.SPI2, stm32.SPI3:\n\t\tclock = CPUFrequency()\n\t}\n\n\t// limit requested frequency to bus frequency and min frequency (DIV256)\n\tfreq := config.Frequency\n\tif min := clock / 256; freq < min {\n\t\tfreq = min\n\t} else if freq > clock {\n\t\tfreq = clock\n\t}\n\n\t// calculate the exact clock divisor (freq=clock/div -> div=clock/freq).\n\t// truncation is fine, since it produces a less-than-or-equal divisor, and\n\t// thus a greater-than-or-equal frequency.\n\t// divisors only come in consecutive powers of 2, so we can use log2 (or,\n\t// equivalently, bits.Len - 1) to convert to respective enum value.\n\tdiv := bits.Len32(clock/freq) - 1\n\n\t// but DIV1 (2^0) is not permitted, as the least divisor is DIV2 (2^1), so\n\t// subtract 1 from the log2 value, keeping a lower bound of 0\n\tif div < 0 {\n\t\tdiv = 0\n\t} else if div > 0 {\n\t\tdiv--\n\t}\n\n\t// finally, shift the enumerated value into position for SPI CR1\n\treturn uint32(div) << stm32.SPI_CR1_BR_Pos\n}\n\n//---------- I2C related code\n\n// Gets the value for TIMINGR register\nfunc (i2c *I2C) getFreqRange(br uint32) uint32 {\n\t// This is a 'magic' value calculated by STM32CubeMX\n\t// for 48Mhz PCLK1.\n\t// TODO: Do calculations based on PCLK1\n\tswitch br {\n\tcase 10 * KHz:\n\t\treturn 0x9010DEFF\n\tcase 100 * KHz:\n\t\treturn 0x20303E5D\n\tcase 400 * KHz:\n\t\treturn 0x2010091A\n\tcase 500 * KHz:\n\t\treturn 0x00201441\n\tdefault:\n\t\treturn 0\n\t}\n}\n\n//---------- UART related code\n\n// Configure the UART.\nfunc (uart UART) configurePins(config UARTConfig) {\n\t// enable the alternate functions on the TX and RX pins\n\tconfig.TX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTTX}, uart.TxAltFuncSelector)\n\tconfig.RX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTRX}, uart.RxAltFuncSelector)\n}\n\n// UART baudrate calc based on the bus and clockspeed\n// NOTE: keep this in sync with the runtime/runtime_stm32wle5.go clock init code\nfunc (uart *UART) getBaudRateDivisor(baudRate uint32) uint32 {\n\tvar br uint32\n\tuartClock := CPUFrequency() // No Prescaler configuration\n\tbr = uint32((uartClock + baudRate/2) / baudRate)\n\treturn (br)\n}\n\n// Register names vary by ST processor, these are for STM L5\nfunc (uart *UART) setRegisters() {\n\tuart.rxReg = &uart.Bus.RDR\n\tuart.txReg = &uart.Bus.TDR\n\tuart.statusReg = &uart.Bus.ISR\n\tuart.txEmptyFlag = stm32.USART_ISR_TXFNF //(TXFNF == TXE == bit 7, but depends alternate RM0461/1094)\n}\n\n//---------- Timer related code\n\nvar (\n\tTIM1 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM1EN,\n\t\tDevice:         stm32.TIM1,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PA8, AF1_TIM1_2_LPTIM1}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA9, AF1_TIM1_2_LPTIM1}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA10, AF1_TIM1_2_LPTIM1}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA11, AF1_TIM1_2_LPTIM1}}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n\tTIM2 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB1ENR1,\n\t\tEnableFlag:     stm32.RCC_APB1ENR1_TIM2EN,\n\t\tDevice:         stm32.TIM2,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PA0, AF1_TIM1_2_LPTIM1}, {PA5, AF1_TIM1_2_LPTIM1}, {PA15, AF1_TIM1_2_LPTIM1}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA1, AF1_TIM1_2_LPTIM1}, {PB3, AF1_TIM1_2_LPTIM1}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA2, AF1_TIM1_2_LPTIM1}, {PB10, AF1_TIM1_2_LPTIM1}}},\n\t\t\tTimerChannel{Pins: []PinFunction{{PA3, AF1_TIM1_2_LPTIM1}, {PB11, AF1_TIM1_2_LPTIM1}}},\n\t\t},\n\t\tbusFreq: APB1_TIM_FREQ,\n\t}\n\tTIM16 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM16EN,\n\t\tDevice:         stm32.TIM16,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PA6, AF14_TIM2_16_17_LPTIM2}}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n\tTIM17 = TIM{\n\t\tEnableRegister: &stm32.RCC.APB2ENR,\n\t\tEnableFlag:     stm32.RCC_APB2ENR_TIM17EN,\n\t\tDevice:         stm32.TIM17,\n\t\tChannels: [4]TimerChannel{\n\t\t\tTimerChannel{Pins: []PinFunction{{PA7, AF1_TIM1_2_LPTIM1}, {PB9, AF1_TIM1_2_LPTIM1}}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t\tTimerChannel{Pins: []PinFunction{}},\n\t\t},\n\t\tbusFreq: APB2_TIM_FREQ,\n\t}\n)\n\nfunc (t *TIM) registerUPInterrupt() interrupt.Interrupt {\n\tswitch t {\n\tcase &TIM1:\n\t\treturn interrupt.New(stm32.IRQ_TIM1_UP, TIM1.handleUPInterrupt)\n\tcase &TIM2:\n\t\treturn interrupt.New(stm32.IRQ_TIM2, TIM2.handleUPInterrupt)\n\tcase &TIM16:\n\t\treturn interrupt.New(stm32.IRQ_TIM16, TIM16.handleUPInterrupt)\n\tcase &TIM17:\n\t\treturn interrupt.New(stm32.IRQ_TIM17, TIM17.handleUPInterrupt)\n\t}\n\n\treturn interrupt.Interrupt{}\n}\n\nfunc (t *TIM) registerOCInterrupt() interrupt.Interrupt {\n\tswitch t {\n\tcase &TIM1:\n\t\treturn interrupt.New(stm32.IRQ_TIM1_CC, TIM1.handleOCInterrupt)\n\tcase &TIM2:\n\t\treturn interrupt.New(stm32.IRQ_TIM2, TIM2.handleOCInterrupt)\n\tcase &TIM16:\n\t\treturn interrupt.New(stm32.IRQ_TIM16, TIM16.handleOCInterrupt)\n\tcase &TIM17:\n\t\treturn interrupt.New(stm32.IRQ_TIM17, TIM17.handleOCInterrupt)\n\t}\n\n\treturn interrupt.Interrupt{}\n}\n\nfunc (t *TIM) enableMainOutput() {\n\tt.Device.BDTR.SetBits(stm32.TIM_BDTR_MOE)\n}\n\nfunc initRNG() {\n\tstm32.RCC.AHB3ENR.SetBits(stm32.RCC_AHB3ENR_RNGEN)\n\n\t// Enable RNG with config.A  (See RM0453 22.6.2)\n\tstm32.RNG.CR.Set(0x40F00D40)   // RNG Config. A\n\tstm32.RNG.HTCR.Set(0x17590ABC) // MAGIC NUMBER\n\tstm32.RNG.HTCR.Set(0x0000AA74) // HTCR VALUE\n\tstm32.RNG.CR.Set(0x00F00D4C)   // CONFIG A  + RNG_EN=1 + IE=1\n}\n\n//----------\n\ntype arrtype = uint32\ntype arrRegType = volatile.Register32\n\nconst (\n\tARR_MAX = 0x10000\n\tPSC_MAX = 0x10000\n)\n\n//---------- Flash related code\n\nconst eraseBlockSizeValue = 2048\n\n// eraseBlock of the passed in block number\nfunc eraseBlock(block uint32) error {\n\twaitUntilFlashDone()\n\n\t// check if operation is allowed.\n\tif stm32.FLASH.GetSR_PESD() != 0 {\n\t\treturn errFlashCannotErasePage\n\t}\n\n\t// clear any previous errors\n\tstm32.FLASH.SR.SetBits(0x3FA)\n\n\t// page erase operation\n\tstm32.FLASH.SetCR_PER(1)\n\tdefer stm32.FLASH.SetCR_PER(0)\n\n\t// set the address to the page to be written\n\tstm32.FLASH.SetCR_PNB(block)\n\tdefer stm32.FLASH.SetCR_PNB(0)\n\n\t// start the page erase\n\tstm32.FLASH.SetCR_STRT(1)\n\n\twaitUntilFlashDone()\n\n\tif err := checkError(); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nconst writeBlockSize = 8\n\nfunc writeFlashData(address uintptr, data []byte) (int, error) {\n\tif len(data)%writeBlockSize != 0 {\n\t\treturn 0, errFlashInvalidWriteLength\n\t}\n\n\twaitUntilFlashDone()\n\n\t// check if operation is allowed\n\tif stm32.FLASH.GetSR_PESD() != 0 {\n\t\treturn 0, errFlashNotAllowedWriteData\n\t}\n\n\t// clear any previous errors\n\tstm32.FLASH.SR.SetBits(0x3FA)\n\n\tfor j := 0; j < len(data); j += writeBlockSize {\n\t\t// start page write operation\n\t\tstm32.FLASH.SetCR_PG(1)\n\n\t\t// write first word using double-word high order word\n\t\t*(*uint32)(unsafe.Pointer(address)) = binary.LittleEndian.Uint32(data[j : j+writeBlockSize/2])\n\n\t\taddress += writeBlockSize / 2\n\n\t\t// write second word using double-word low order word\n\t\t*(*uint32)(unsafe.Pointer(address)) = binary.LittleEndian.Uint32(data[j+writeBlockSize/2 : j+writeBlockSize])\n\n\t\twaitUntilFlashDone()\n\n\t\tif err := checkError(); err != nil {\n\t\t\treturn j, err\n\t\t}\n\n\t\t// end flash write\n\t\tstm32.FLASH.SetCR_PG(0)\n\t\taddress += writeBlockSize / 2\n\t}\n\n\treturn len(data), nil\n}\n\nfunc waitUntilFlashDone() {\n\tfor stm32.FLASH.GetSR_BSY() != 0 {\n\t}\n\n\tfor stm32.FLASH.GetSR_CFGBSY() != 0 {\n\t}\n}\n\nvar (\n\terrFlashPGS  = errors.New(\"errFlashPGS\")\n\terrFlashSIZE = errors.New(\"errFlashSIZE\")\n\terrFlashPGA  = errors.New(\"errFlashPGA\")\n\terrFlashWRP  = errors.New(\"errFlashWRP\")\n\terrFlashPROG = errors.New(\"errFlashPROG\")\n)\n\nfunc checkError() error {\n\tswitch {\n\tcase stm32.FLASH.GetSR_PGSERR() != 0:\n\t\treturn errFlashPGS\n\tcase stm32.FLASH.GetSR_SIZERR() != 0:\n\t\treturn errFlashSIZE\n\tcase stm32.FLASH.GetSR_PGAERR() != 0:\n\t\treturn errFlashPGA\n\tcase stm32.FLASH.GetSR_WRPERR() != 0:\n\t\treturn errFlashWRP\n\tcase stm32.FLASH.GetSR_PROGERR() != 0:\n\t\treturn errFlashPROG\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "src/machine/machine_tkey.go",
    "content": "//go:build tkey\n\npackage machine\n\nimport (\n\t\"device/tkey\"\n\t\"errors\"\n\t\"strconv\"\n)\n\nconst deviceName = \"TKey\"\n\n// GPIO pins modes are only here to match the Pin interface.\n// The actual configuration is fixed in the hardware.\nconst (\n\tPinOutput PinMode = iota\n\tPinInput\n\tPinInputPullup\n\tPinInputPulldown\n)\n\nconst (\n\tLED_BLUE  = Pin(tkey.TK1_MMIO_TK1_LED_B_BIT)\n\tLED_GREEN = Pin(tkey.TK1_MMIO_TK1_LED_G_BIT)\n\tLED_RED   = Pin(tkey.TK1_MMIO_TK1_LED_R_BIT)\n\n\tLED = LED_GREEN\n\n\tTKEY_TOUCH = Pin(3) // 3 is unused, but we need a value here to match the Pin interface.\n\tBUTTON     = TKEY_TOUCH\n\n\tGPIO1 = Pin(tkey.TK1_MMIO_TK1_GPIO1_BIT + 8)\n\tGPIO2 = Pin(tkey.TK1_MMIO_TK1_GPIO2_BIT + 8)\n\tGPIO3 = Pin(tkey.TK1_MMIO_TK1_GPIO3_BIT + 8)\n\tGPIO4 = Pin(tkey.TK1_MMIO_TK1_GPIO4_BIT + 8)\n)\n\nvar touchConfig, gpio1Config, gpio2Config PinConfig\n\n// No config needed for TKey, just to match the Pin interface.\nfunc (p Pin) Configure(config PinConfig) {\n\tswitch p {\n\tcase BUTTON:\n\t\ttouchConfig = config\n\n\t\t// Clear any pending touch events.\n\t\ttkey.TOUCH.STATUS.Set(0)\n\tcase GPIO1:\n\t\tgpio1Config = config\n\tcase GPIO2:\n\t\tgpio2Config = config\n\t}\n}\n\n// Set pin to high or low.\nfunc (p Pin) Set(high bool) {\n\tswitch p {\n\tcase LED_BLUE, LED_GREEN, LED_RED:\n\t\tif high {\n\t\t\ttkey.TK1.LED.SetBits(1 << uint(p))\n\t\t} else {\n\t\t\ttkey.TK1.LED.ClearBits(1 << uint(p))\n\t\t}\n\tcase GPIO3, GPIO4:\n\t\tif high {\n\t\t\ttkey.TK1.GPIO.SetBits(1 << uint(p-8))\n\t\t} else {\n\t\t\ttkey.TK1.GPIO.ClearBits(1 << uint(p-8))\n\t\t}\n\t}\n}\n\n// Get returns the current value of a pin.\nfunc (p Pin) Get() bool {\n\tpushed := false\n\tmode := PinInput\n\n\tswitch p {\n\tcase BUTTON:\n\t\tmode = touchConfig.Mode\n\t\tif tkey.TOUCH.STATUS.HasBits(1) {\n\t\t\ttkey.TOUCH.STATUS.Set(0)\n\t\t\tpushed = true\n\t\t}\n\tcase GPIO1:\n\t\tmode = gpio1Config.Mode\n\t\tpushed = tkey.TK1.GPIO.HasBits(1 << uint(p-8))\n\tcase GPIO2:\n\t\tmode = gpio2Config.Mode\n\t\tpushed = tkey.TK1.GPIO.HasBits(1 << uint(p-8))\n\tcase GPIO3, GPIO4:\n\t\tmode = PinOutput\n\t\tpushed = tkey.TK1.GPIO.HasBits(1 << uint(p-8))\n\tcase LED_BLUE, LED_GREEN, LED_RED:\n\t\tmode = PinOutput\n\t\tpushed = tkey.TK1.LED.HasBits(1 << uint(p))\n\t}\n\n\tswitch mode {\n\tcase PinInputPullup:\n\t\treturn !pushed\n\tcase PinInput, PinInputPulldown, PinOutput:\n\t\treturn pushed\n\t}\n\n\treturn false\n}\n\ntype UART struct {\n\tBus *tkey.UART_Type\n}\n\nvar (\n\tDefaultUART = UART0\n\tUART0       = &_UART0\n\t_UART0      = UART{Bus: tkey.UART}\n)\n\n// The TKey UART is fixed at 62500 baud, 8N1.\nfunc (uart *UART) Configure(config UARTConfig) error {\n\tif !(config.BaudRate == 62500 || config.BaudRate == 0) {\n\t\treturn errors.New(\"uart: only 62500 baud rate is supported\")\n\t}\n\n\treturn nil\n}\n\n// Write a slice of data bytes to the UART.\nfunc (uart *UART) Write(data []byte) (n int, err error) {\n\tfor _, c := range data {\n\t\tif err := uart.WriteByte(c); err != nil {\n\t\t\treturn n, err\n\t\t}\n\t}\n\treturn len(data), nil\n}\n\n// WriteByte writes a byte of data to the UART.\nfunc (uart *UART) WriteByte(c byte) error {\n\tfor uart.Bus.TX_STATUS.Get() == 0 {\n\t}\n\n\tuart.Bus.TX_DATA.Set(uint32(c))\n\n\treturn nil\n}\n\n// Buffered returns the number of bytes buffered in the UART.\nfunc (uart *UART) Buffered() int {\n\treturn int(uart.Bus.RX_BYTES.Get())\n}\n\n// ReadByte reads a byte of data from the UART.\nfunc (uart *UART) ReadByte() (byte, error) {\n\tfor uart.Bus.RX_STATUS.Get() == 0 {\n\t}\n\n\treturn byte(uart.Bus.RX_DATA.Get()), nil\n}\n\n// DTR is not available on the TKey.\nfunc (uart *UART) DTR() bool {\n\treturn false\n}\n\n// RTS is not available on the TKey.\nfunc (uart *UART) RTS() bool {\n\treturn false\n}\n\n// GetRNG returns 32 bits of cryptographically secure random data\nfunc GetRNG() (uint32, error) {\n\tfor tkey.TRNG.STATUS.Get() == 0 {\n\t}\n\n\treturn uint32(tkey.TRNG.ENTROPY.Get()), nil\n}\n\n// DesignName returns the FPGA design name.\nfunc DesignName() (string, string) {\n\tn0 := tkey.TK1.NAME0.Get()\n\tname0 := string([]byte{byte(n0 >> 24), byte(n0 >> 16), byte(n0 >> 8), byte(n0)})\n\tn1 := tkey.TK1.NAME1.Get()\n\tname1 := string([]byte{byte(n1 >> 24), byte(n1 >> 16), byte(n1 >> 8), byte(n1)})\n\n\treturn name0, name1\n}\n\n// DesignVersion returns the FPGA design version.\nfunc DesignVersion() string {\n\tversion := tkey.TK1.VERSION.Get()\n\n\treturn strconv.Itoa(int(version))\n}\n\n// CDI returns 8 words of Compound Device Identifier (CDI) generated and written by the firmware when the application is loaded.\nfunc CDI() []byte {\n\tcdi := make([]byte, 32)\n\tfor i := 0; i < 8; i++ {\n\t\tc := tkey.TK1.CDI_FIRST[i].Get()\n\t\tcdi[i*4] = byte(c >> 24)\n\t\tcdi[i*4+1] = byte(c >> 16)\n\t\tcdi[i*4+2] = byte(c >> 8)\n\t\tcdi[i*4+3] = byte(c)\n\t}\n\treturn cdi\n}\n\n// UDI returns 2 words of Unique Device Identifier (UDI). Only available in firmware mode.\nfunc UDI() []byte {\n\tudi := make([]byte, 8)\n\tfor i := 0; i < 2; i++ {\n\t\tc := tkey.TK1.UDI_FIRST[i].Get()\n\t\tudi[i*4] = byte(c >> 24)\n\t\tudi[i*4+1] = byte(c >> 16)\n\t\tudi[i*4+2] = byte(c >> 8)\n\t\tudi[i*4+3] = byte(c)\n\t}\n\treturn udi\n}\n\n// UDS returns 8 words of Unique Device Secret. Part of the FPGA design, changed when provisioning a TKey.\n// Only available in firmware mode. UDS is only readable once per power cycle.\nfunc UDS() []byte {\n\tuds := make([]byte, 32)\n\tfor i := 0; i < 8; i++ {\n\t\tc := tkey.UDS.DATA[i].Get()\n\t\tuds[i*4] = byte(c >> 24)\n\t\tuds[i*4+1] = byte(c >> 16)\n\t\tuds[i*4+2] = byte(c >> 8)\n\t\tuds[i*4+3] = byte(c)\n\t}\n\treturn uds\n}\n"
  },
  {
    "path": "src/machine/machine_tkey_rom.go",
    "content": "//go:build tkey\n\npackage machine\n\n/*\n\t#define TK1_MMIO_TK1_BLAKE2S 0xff000040\n\n\ttypedef unsigned char uint8_t;\n\ttypedef unsigned long uint32_t;\n\ttypedef unsigned long size_t;\n\n\t// blake2s state context\n\ttypedef struct {\n\t\tuint8_t b[64]; // input buffer\n\t\tuint32_t h[8]; // chained state\n\t\tuint32_t t[2]; // total number of bytes\n\t\tsize_t c;      // pointer for b[]\n\t\tsize_t outlen; // digest size\n\t} blake2s_ctx;\n\n\ttypedef int (*fw_blake2s_p)(void *out, unsigned long outlen, const void *key,\n\t\tunsigned long keylen, const void *in,\n\t\tunsigned long inlen, blake2s_ctx *ctx);\n\n\tint blake2s(void *out, unsigned long outlen, const void *key, unsigned long keylen, const void *in, unsigned long inlen)\n\t{\n\t\tfw_blake2s_p const fw_blake2s =\n\t    \t(fw_blake2s_p) * (volatile uint32_t *)TK1_MMIO_TK1_BLAKE2S;\n\t\tblake2s_ctx ctx;\n\n\t\treturn fw_blake2s(out, outlen, key, keylen, in, inlen, &ctx);\n\t}\n*/\nimport \"C\"\nimport (\n\t\"errors\"\n\t\"unsafe\"\n)\n\nvar (\n\tErrBLAKE2sInvalid = errors.New(\"invalid params for call to BLAKE2s\")\n\tErrBLAKE2sFailed  = errors.New(\"call to BLAKE2s failed\")\n)\n\nfunc BLAKE2s(output []byte, key []byte, input []byte) error {\n\tif len(output) == 0 || len(input) == 0 {\n\t\treturn ErrBLAKE2sInvalid\n\t}\n\n\top := unsafe.Pointer(&output[0])\n\tkp := unsafe.Pointer(&key[0])\n\tip := unsafe.Pointer(&input[0])\n\n\tif res := C.blake2s(op, C.size_t(len(output)), kp, C.size_t(len(key)), ip, C.size_t(len(input))); res != 0 {\n\t\treturn ErrBLAKE2sFailed\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "src/machine/pdm.go",
    "content": "package machine\n\ntype PDMConfig struct {\n\tStereo bool\n\tDIN    Pin\n\tCLK    Pin\n}\n"
  },
  {
    "path": "src/machine/pwm.go",
    "content": "package machine\n\nimport \"errors\"\n\nvar (\n\tErrPWMPeriodTooLong = errors.New(\"pwm: period too long\")\n)\n\n// PWMConfig allows setting some configuration while configuring a PWM\n// peripheral. A zero PWMConfig is ready to use for simple applications such as\n// dimming LEDs.\ntype PWMConfig struct {\n\t// PWM period in nanosecond. Leaving this zero will pick a reasonable period\n\t// value for use with LEDs.\n\t// If you want to configure a frequency instead of a period, you can use the\n\t// following formula to calculate a period from a frequency:\n\t//\n\t//     period = 1e9 / frequency\n\t//\n\tPeriod uint64\n}\n"
  },
  {
    "path": "src/machine/runtime.go",
    "content": "package machine\n\nimport (\n\t_ \"unsafe\"\n)\n\n//\n// This file provides access to runtime package that would not otherwise\n// be permitted due to linker dependencies.\n//\n\n//go:linkname gosched runtime.Gosched\nfunc gosched()\n"
  },
  {
    "path": "src/machine/serial-none.go",
    "content": "//go:build baremetal && serial.none\n\npackage machine\n\n// Serial is a null device: writes to it are ignored.\nvar Serial = NullSerial{}\n\nfunc InitSerial() {\n\tSerial.Configure(UARTConfig{})\n}\n"
  },
  {
    "path": "src/machine/serial-rtt.go",
    "content": "//go:build baremetal && serial.rtt\n\n// Implement Segger RTT support.\n// This is mostly useful for targets that only have a debug connection\n// available, and no serial output (or input). It is somewhat like semihosting,\n// but not unusably slow.\n// It was originally specified by Segger, but support is available in OpenOCD\n// for at least the DAPLink debuggers so I assume it works on any SWD debugger.\n\npackage machine\n\nimport (\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\n// This symbol name is known by the compiler, see monitor.go.\n//\n//go:linkname rttSerialInstance _SEGGER_RTT\nvar rttSerialInstance rttSerial\n\nvar Serial = &rttSerialInstance\n\nfunc InitSerial() {\n\tSerial.Configure(UARTConfig{})\n}\n\nconst (\n\t// Some constants, see:\n\t// https://github.com/SEGGERMicro/RTT/blob/master/RTT/SEGGER_RTT.h\n\n\trttMaxNumUpBuffers   = 1\n\trttMaxNumDownBuffers = 1\n\trttBufferSizeUp      = 1024\n\trttBufferSizeDown    = 16\n\n\trttModeNoBlockSkip     = 0\n\trttModeNoBlockTrim     = 1\n\trttModeBlockIfFifoFull = 2\n)\n\n// The debugger knows about the layout of this struct, so it must not change.\n// This is SEGGER_RTT_CB.\ntype rttControlBlock struct {\n\tid                [16]volatile.Register8\n\tmaxNumUpBuffers   int32\n\tmaxNumDownBuffers int32\n\tbuffersUp         [rttMaxNumUpBuffers]rttBuffer\n\tbuffersDown       [rttMaxNumDownBuffers]rttBuffer\n}\n\n// Up or down buffer.\n// This is SEGGER_RTT_BUFFER_UP and SEGGER_RTT_BUFFER_DOWN.\ntype rttBuffer struct {\n\tname        *byte\n\tbuffer      *volatile.Register8\n\tbufferSize  uint32\n\twriteOffset volatile.Register32\n\treadOffset  volatile.Register32\n\tflags       uint32\n}\n\n// Static buffers, for the default up and down buffer.\nvar (\n\trttBufferUpData   [rttBufferSizeUp]volatile.Register8\n\trttBufferDownData [rttBufferSizeDown]volatile.Register8\n)\n\ntype rttSerial struct {\n\trttControlBlock\n}\n\nfunc (s *rttSerial) Configure(config UARTConfig) error {\n\ts.maxNumUpBuffers = rttMaxNumUpBuffers\n\ts.maxNumDownBuffers = rttMaxNumDownBuffers\n\n\ts.buffersUp[0].name = &[]byte(\"Terminal\\x00\")[0]\n\ts.buffersUp[0].buffer = &rttBufferUpData[0]\n\ts.buffersUp[0].bufferSize = rttBufferSizeUp\n\ts.buffersUp[0].flags = rttModeNoBlockSkip\n\n\ts.buffersDown[0].name = &[]byte(\"Terminal\\x00\")[0]\n\ts.buffersDown[0].buffer = &rttBufferDownData[0]\n\ts.buffersDown[0].bufferSize = rttBufferSizeDown\n\ts.buffersDown[0].flags = rttModeNoBlockSkip\n\n\tid := \"SEGGER RTT\"\n\tfor i := 0; i < len(id); i++ {\n\t\ts.id[i].Set(id[i])\n\t}\n\n\treturn nil\n}\n\nfunc (b *rttBuffer) writeByte(c byte) {\n\tstate := interrupt.Disable()\n\treadOffset := b.readOffset.Get()\n\twriteOffset := b.writeOffset.Get()\n\tnewWriteOffset := writeOffset + 1\n\tif newWriteOffset == b.bufferSize {\n\t\tnewWriteOffset = 0\n\t}\n\tif newWriteOffset != readOffset {\n\t\tunsafe.Slice(b.buffer, b.bufferSize)[writeOffset].Set(c)\n\t\tb.writeOffset.Set(newWriteOffset)\n\t}\n\tinterrupt.Restore(state)\n}\n\nfunc (b *rttBuffer) readByte() byte {\n\treadOffset := b.readOffset.Get()\n\twriteOffset := b.writeOffset.Get()\n\tfor readOffset == writeOffset {\n\t\treadOffset = b.readOffset.Get()\n\t}\n\tc := unsafe.Slice(b.buffer, b.bufferSize)[readOffset].Get()\n\tb.readOffset.Set(readOffset + 1)\n\treturn c\n}\n\nfunc (b *rttBuffer) buffered() int {\n\treadOffset := b.readOffset.Get()\n\twriteOffset := b.writeOffset.Get()\n\treturn int((writeOffset - readOffset) % rttBufferSizeDown)\n}\n\n// Write a single byte to the RTT output buffer.\n//\n// This method is set to not be inlined, to avoid blowing up binary size as a\n// result of inlining writeByte everywhere a println exists.\n//\n//go:noinline\nfunc (s *rttSerial) WriteByte(b byte) error {\n\ts.buffersUp[0].writeByte(b)\n\treturn nil\n}\n\nfunc (s *rttSerial) ReadByte() (byte, error) {\n\treturn s.buffersDown[0].readByte(), errNoByte\n}\n\nfunc (s *rttSerial) Buffered() int {\n\treturn s.buffersDown[0].buffered()\n}\n\nfunc (s *rttSerial) Write(data []byte) (n int, err error) {\n\tfor _, v := range data {\n\t\ts.WriteByte(v)\n\t}\n\treturn len(data), nil\n}\n"
  },
  {
    "path": "src/machine/serial-uart.go",
    "content": "//go:build baremetal && serial.uart\n\npackage machine\n\n// Serial is implemented via the default (usually the first) UART on the chip.\nvar Serial = DefaultUART\n\nfunc InitSerial() {\n\tSerial.Configure(UARTConfig{})\n}\n"
  },
  {
    "path": "src/machine/serial-usb.go",
    "content": "//go:build baremetal && serial.usb\n\npackage machine\n\n// Serial is implemented via USB (USB-CDC).\nvar Serial Serialer\n\nfunc InitSerial() {\n\tinitUSB()\n\tSerial = USBCDC\n}\n"
  },
  {
    "path": "src/machine/serial.go",
    "content": "package machine\n\nimport \"errors\"\n\nvar errNoByte = errors.New(\"machine: no byte read\")\n\n// UARTConfig is a struct with which a UART (or similar object) can be\n// configured. The baud rate is usually respected, but TX and RX may be ignored\n// depending on the chip and the type of object.\ntype UARTConfig struct {\n\tBaudRate uint32\n\tTX       Pin\n\tRX       Pin\n\tRTS      Pin\n\tCTS      Pin\n}\n\n// NullSerial is a serial version of /dev/null (or null router): it drops\n// everything that is written to it.\ntype NullSerial struct {\n}\n\n// Configure does nothing: the null serial has no configuration.\nfunc (ns NullSerial) Configure(config UARTConfig) error {\n\treturn nil\n}\n\n// WriteByte is a no-op: the null serial doesn't write bytes.\nfunc (ns NullSerial) WriteByte(b byte) error {\n\treturn nil\n}\n\n// ReadByte always returns an error because there aren't any bytes to read.\nfunc (ns NullSerial) ReadByte() (byte, error) {\n\treturn 0, errNoByte\n}\n\n// Buffered returns how many bytes are buffered in the UART. It always returns 0\n// as there are no bytes to read.\nfunc (ns NullSerial) Buffered() int {\n\treturn 0\n}\n\n// Write is a no-op: none of the data is being written and it will not return an\n// error.\nfunc (ns NullSerial) Write(p []byte) (n int, err error) {\n\treturn len(p), nil\n}\n"
  },
  {
    "path": "src/machine/spi.go",
    "content": "//go:build !baremetal || atmega || esp32 || fe310 || k210 || nrf || (nxp && !mk66f18) || rp2040 || rp2350 || sam || (stm32 && !stm32f7x2 && !stm32l5x2)\n\npackage machine\n\nimport \"errors\"\n\n// SPI phase and polarity configs CPOL and CPHA\nconst (\n\tMode0 = 0\n\tMode1 = 1\n\tMode2 = 2\n\tMode3 = 3\n)\n\nvar (\n\tErrTxInvalidSliceSize      = errors.New(\"SPI write and read slices must be same size\")\n\terrSPIInvalidMachineConfig = errors.New(\"SPI port was not configured properly by the machine\")\n)\n\n// If you are getting a compile error on this line please check to see you've\n// correctly implemented the methods on the SPI type. They must match\n// the interface method signatures type to type perfectly.\n// If not implementing the SPI type please remove your target from the build tags\n// at the top of this file.\nvar _ interface { // 2\n\tConfigure(config SPIConfig) error\n\tTx(w, r []byte) error\n\tTransfer(w byte) (byte, error)\n} = (*SPI)(nil)\n"
  },
  {
    "path": "src/machine/spi_tx.go",
    "content": "//go:build atmega || fe310 || k210 || (nxp && !mk66f18) || (stm32 && !stm32f7x2 && !stm32l5x2)\n\n// This file implements the SPI Tx function for targets that don't have a custom\n// (faster) implementation for it.\n\npackage machine\n\n// Tx handles read/write operation for SPI interface. Since SPI is a synchronous write/read\n// interface, there must always be the same number of bytes written as bytes read.\n// The Tx method knows about this, and offers a few different ways of calling it.\n//\n// This form sends the bytes in tx buffer, putting the resulting bytes read into the rx buffer.\n// Note that the tx and rx buffers must be the same size:\n//\n//\tspi.Tx(tx, rx)\n//\n// This form sends the tx buffer, ignoring the result. Useful for sending \"commands\" that return zeros\n// until all the bytes in the command packet have been received:\n//\n//\tspi.Tx(tx, nil)\n//\n// This form sends zeros, putting the result into the rx buffer. Good for reading a \"result packet\":\n//\n//\tspi.Tx(nil, rx)\nfunc (spi *SPI) Tx(w, r []byte) error {\n\tvar err error\n\n\tswitch {\n\tcase w == nil:\n\t\t// read only, so write zero and read a result.\n\t\tfor i := range r {\n\t\t\tr[i], err = spi.Transfer(0)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\tcase r == nil:\n\t\t// write only\n\t\tfor _, b := range w {\n\t\t\t_, err = spi.Transfer(b)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\n\tdefault:\n\t\t// write/read\n\t\tif len(w) != len(r) {\n\t\t\treturn ErrTxInvalidSliceSize\n\t\t}\n\n\t\tfor i, b := range w {\n\t\t\tr[i], err = spi.Transfer(b)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "src/machine/uart.go",
    "content": "//go:build atmega || esp || nrf || sam || sifive || stm32 || k210 || nxp || rp2040 || rp2350\n\npackage machine\n\nimport \"errors\"\n\nvar errUARTBufferEmpty = errors.New(\"UART buffer empty\")\n\n// UARTParity is the parity setting to be used for UART communication.\ntype UARTParity uint8\n\nconst (\n\t// ParityNone means to not use any parity checking. This is\n\t// the most common setting.\n\tParityNone UARTParity = iota\n\n\t// ParityEven means to expect that the total number of 1 bits sent\n\t// should be an even number.\n\tParityEven\n\n\t// ParityOdd means to expect that the total number of 1 bits sent\n\t// should be an odd number.\n\tParityOdd\n)\n\n// To implement the UART interface for a board, you must declare a concrete type as follows:\n//\n// \t\ttype UART struct {\n// \t\t\tBuffer *RingBuffer\n// \t\t}\n//\n// You can also add additional members to this struct depending on your implementation,\n// but the *RingBuffer is required.\n// When you are declaring your UARTs for your board, make sure that you also declare the\n// RingBuffer using the NewRingBuffer() function when you declare your UART:\n//\n//\t\tUART{Buffer: NewRingBuffer()}\n//\n\n// Read from the RX buffer.\nfunc (uart *UART) Read(data []byte) (n int, err error) {\n\t// check if RX buffer is empty\n\tsize := uart.Buffered()\n\tif size == 0 {\n\t\treturn 0, nil\n\t}\n\n\t// Make sure we do not read more from buffer than the data slice can hold.\n\tif len(data) < size {\n\t\tsize = len(data)\n\t}\n\n\t// only read number of bytes used from buffer\n\tfor i := 0; i < size; i++ {\n\t\tv, _ := uart.ReadByte()\n\t\tdata[i] = v\n\t}\n\n\treturn size, nil\n}\n\n// WriteByte writes a byte of data over the UART's Tx.\n// This function blocks until the data is finished being sent.\nfunc (uart *UART) WriteByte(c byte) error {\n\terr := uart.writeByte(c)\n\tif err != nil {\n\t\treturn err\n\t}\n\tuart.flush() // flush() blocks until all data has been transmitted.\n\treturn nil\n}\n\n// Write data over the UART's Tx.\n// This function blocks until the data is finished being sent.\nfunc (uart *UART) Write(data []byte) (n int, err error) {\n\tfor i, v := range data {\n\t\terr = uart.writeByte(v)\n\t\tif err != nil {\n\t\t\treturn i, err\n\t\t}\n\t}\n\tuart.flush() // flush() blocks until all data has been transmitted.\n\treturn len(data), nil\n}\n\n// ReadByte reads a single byte from the RX buffer.\n// If there is no data in the buffer, returns an error.\nfunc (uart *UART) ReadByte() (byte, error) {\n\t// check if RX buffer is empty\n\tbuf, ok := uart.Buffer.Get()\n\tif !ok {\n\t\treturn 0, errUARTBufferEmpty\n\t}\n\treturn buf, nil\n}\n\n// Buffered returns the number of bytes currently stored in the RX buffer.\nfunc (uart *UART) Buffered() int {\n\treturn int(uart.Buffer.Used())\n}\n\n// Receive handles adding data to the UART's data buffer.\n// Usually called by the IRQ handler for a machine.\nfunc (uart *UART) Receive(data byte) {\n\tuart.Buffer.Put(data)\n}\n"
  },
  {
    "path": "src/machine/usb/adc/doc.go",
    "content": "// package adc is for USB Audio Device Class devices.\npackage adc\n"
  },
  {
    "path": "src/machine/usb/adc/midi/buffer.go",
    "content": "package midi\n\nimport (\n\t\"runtime/volatile\"\n)\n\nconst bufferSize = 128\n\n// RingBuffer is ring buffer implementation inspired by post at\n// https://www.embeddedrelated.com/showthread/comp.arch.embedded/77084-1.php\ntype RingBuffer struct {\n\trxbuffer [bufferSize][4]byte\n\thead     volatile.Register8\n\ttail     volatile.Register8\n}\n\n// NewRingBuffer returns a new ring buffer.\nfunc NewRingBuffer() *RingBuffer {\n\treturn &RingBuffer{}\n}\n\n// Used returns how many bytes in buffer have been used.\nfunc (rb *RingBuffer) Used() uint8 {\n\treturn uint8(rb.head.Get() - rb.tail.Get())\n}\n\n// Put stores a byte in the buffer. If the buffer is already\n// full, the method will return false.\nfunc (rb *RingBuffer) Put(val []byte) bool {\n\tif rb.Used() != bufferSize {\n\t\trb.head.Set(rb.head.Get() + 1)\n\t\tcopy(rb.rxbuffer[rb.head.Get()%bufferSize][:], val)\n\t\treturn true\n\t}\n\treturn false\n}\n\n// Get returns a byte from the buffer. If the buffer is empty,\n// the method will return a false as the second value.\nfunc (rb *RingBuffer) Get() ([]byte, bool) {\n\tif rb.Used() != 0 {\n\t\trb.tail.Set(rb.tail.Get() + 1)\n\t\treturn rb.rxbuffer[rb.tail.Get()%bufferSize][:], true\n\t}\n\treturn nil, false\n}\n\n// Clear resets the head and tail pointer to zero.\nfunc (rb *RingBuffer) Clear() {\n\trb.head.Set(0)\n\trb.tail.Set(0)\n}\n"
  },
  {
    "path": "src/machine/usb/adc/midi/messages.go",
    "content": "package midi\n\nimport (\n\t\"errors\"\n)\n\n// From USB-MIDI section 4.1 \"Code Index Number (CIN) Classifications\"\nconst (\n\tCINSystemCommon2   = 0x2\n\tCINSystemCommon3   = 0x3\n\tCINSysExStart      = 0x4\n\tCINSysExEnd1       = 0x5\n\tCINSysExEnd2       = 0x6\n\tCINSysExEnd3       = 0x7\n\tCINNoteOff         = 0x8\n\tCINNoteOn          = 0x9\n\tCINPoly            = 0xA\n\tCINControlChange   = 0xB\n\tCINProgramChange   = 0xC\n\tCINChannelPressure = 0xD\n\tCINPitchBendChange = 0xE\n\tCINSingleByte      = 0xF\n)\n\n// Standard MIDI channel messages\nconst (\n\tMsgNoteOff           = 0x80\n\tMsgNoteOn            = 0x90\n\tMsgPolyAftertouch    = 0xA0\n\tMsgControlChange     = 0xB0\n\tMsgProgramChange     = 0xC0\n\tMsgChannelAftertouch = 0xD0\n\tMsgPitchBend         = 0xE0\n\tMsgSysExStart        = 0xF0\n\tMsgSysExEnd          = 0xF7\n)\n\n// Standard MIDI control change messages\nconst (\n\tCCModulationWheel       = 0x01\n\tCCBreathController      = 0x02\n\tCCFootPedal             = 0x04\n\tCCPortamentoTime        = 0x05\n\tCCDataEntry             = 0x06\n\tCCVolume                = 0x07\n\tCCBalance               = 0x08\n\tCCPan                   = 0x0A\n\tCCExpression            = 0x0B\n\tCCEffectControl1        = 0x0C\n\tCCEffectControl2        = 0x0D\n\tCCGeneralPurpose1       = 0x10\n\tCCGeneralPurpose2       = 0x11\n\tCCGeneralPurpose3       = 0x12\n\tCCGeneralPurpose4       = 0x13\n\tCCBankSelect            = 0x20\n\tCCModulationDepthRange  = 0x21\n\tCCBreathControllerDepth = 0x22\n\tCCFootPedalDepth        = 0x24\n\tCCEffectsLevel          = 0x5B\n\tCCTremeloLevel          = 0x5C\n\tCCChorusLevel           = 0x5D\n\tCCCelesteLevel          = 0x5E\n\tCCPhaserLevel           = 0x5F\n\tCCDataIncrement         = 0x60\n\tCCDataDecrement         = 0x61\n\tCCNRPNLSB               = 0x62\n\tCCNRPNMSB               = 0x63\n\tCCRPNLSB                = 0x64\n\tCCRPNMSB                = 0x65\n\tCCAllSoundOff           = 0x78\n\tCCResetAllControllers   = 0x79\n\tCCAllNotesOff           = 0x7B\n\tCCChannelVolume         = 0x7F\n)\n\nvar (\n\terrInvalidMIDICable        = errors.New(\"invalid MIDI cable\")\n\terrInvalidMIDIChannel      = errors.New(\"invalid MIDI channel\")\n\terrInvalidMIDIVelocity     = errors.New(\"invalid MIDI velocity\")\n\terrInvalidMIDIControl      = errors.New(\"invalid MIDI control number\")\n\terrInvalidMIDIControlValue = errors.New(\"invalid MIDI control value\")\n\terrInvalidMIDIPatch        = errors.New(\"invalid MIDI patch number\")\n\terrInvalidMIDIPitchBend    = errors.New(\"invalid MIDI pitch bend value\")\n\terrInvalidMIDISysExData    = errors.New(\"invalid MIDI SysEx data\")\n)\n\n// NoteOn sends a channel note on message.\n// The cable parameter is the cable number 0-15.\n// The channel parameter is the MIDI channel number 1-16.\nfunc (m *midi) NoteOn(cable, channel uint8, note Note, velocity uint8) error {\n\tswitch {\n\tcase cable > 15:\n\t\treturn errInvalidMIDICable\n\tcase channel == 0 || channel > 16:\n\t\treturn errInvalidMIDIChannel\n\tcase velocity > 127:\n\t\treturn errInvalidMIDIVelocity\n\t}\n\n\tm.msg[0], m.msg[1], m.msg[2], m.msg[3] = ((cable&0xf)<<4)|CINNoteOn, MsgNoteOn|((channel-1)&0xf), byte(note)&0x7f, velocity&0x7f\n\t_, err := m.Write(m.msg[:])\n\treturn err\n}\n\n// NoteOff sends a channel note off message.\n// The cable parameter is the cable number 0-15.\n// The channel parameter is the MIDI channel number 1-16.\nfunc (m *midi) NoteOff(cable, channel uint8, note Note, velocity uint8) error {\n\tswitch {\n\tcase cable > 15:\n\t\treturn errInvalidMIDICable\n\tcase channel == 0 || channel > 16:\n\t\treturn errInvalidMIDIChannel\n\tcase velocity > 127:\n\t\treturn errInvalidMIDIVelocity\n\t}\n\n\tm.msg[0], m.msg[1], m.msg[2], m.msg[3] = ((cable&0xf)<<4)|CINNoteOff, MsgNoteOff|((channel-1)&0xf), byte(note)&0x7f, velocity&0x7f\n\t_, err := m.Write(m.msg[:])\n\treturn err\n}\n\n// ControlChange sends a channel continuous controller message.\n// The cable parameter is the cable number 0-15.\n// The channel parameter is the MIDI channel number 1-16.\n// The control parameter is the controller number 0-127.\n// The value parameter is the controller value 0-127.\nfunc (m *midi) ControlChange(cable, channel, control, value uint8) error {\n\tswitch {\n\tcase cable > 15:\n\t\treturn errInvalidMIDICable\n\tcase channel == 0 || channel > 16:\n\t\treturn errInvalidMIDIChannel\n\tcase control > 127:\n\t\treturn errInvalidMIDIControl\n\tcase value > 127:\n\t\treturn errInvalidMIDIControlValue\n\t}\n\n\tm.msg[0], m.msg[1], m.msg[2], m.msg[3] = ((cable&0xf)<<4)|CINControlChange, MsgControlChange|((channel-1)&0xf), control&0x7f, value&0x7f\n\t_, err := m.Write(m.msg[:])\n\treturn err\n}\n\n// ProgramChange sends a channel program change message.\n// The cable parameter is the cable number 0-15.\n// The channel parameter is the MIDI channel number 1-16.\n// The patch parameter is the program number 0-127.\nfunc (m *midi) ProgramChange(cable, channel uint8, patch uint8) error {\n\tswitch {\n\tcase cable > 15:\n\t\treturn errInvalidMIDICable\n\tcase channel == 0 || channel > 16:\n\t\treturn errInvalidMIDIChannel\n\tcase patch > 127:\n\t\treturn errInvalidMIDIPatch\n\t}\n\n\tm.msg[0], m.msg[1], m.msg[2] = ((cable&0xf)<<4)|CINProgramChange, MsgProgramChange|((channel-1)&0xf), patch&0x7f\n\t_, err := m.Write(m.msg[:3])\n\treturn err\n}\n\n// PitchBend sends a channel pitch bend message.\n// The cable parameter is the cable number 0-15.\n// The channel parameter is the MIDI channel number 1-16.\n// The bend parameter is the 14-bit pitch bend value (maximum 0x3FFF).\n// Setting bend above 0x2000 (up to 0x3FFF) will increase the pitch.\n// Setting bend below 0x2000 (down to 0x0000) will decrease the pitch.\nfunc (m *midi) PitchBend(cable, channel uint8, bend uint16) error {\n\tswitch {\n\tcase cable > 15:\n\t\treturn errInvalidMIDICable\n\tcase channel == 0 || channel > 16:\n\t\treturn errInvalidMIDIChannel\n\tcase bend > 0x3FFF:\n\t\treturn errInvalidMIDIPitchBend\n\t}\n\n\tm.msg[0], m.msg[1], m.msg[2], m.msg[3] = ((cable&0xf)<<4)|CINPitchBendChange, MsgPitchBend|((channel-1)&0xf), byte(bend&0x7f), byte(bend>>7)&0x7f\n\t_, err := m.Write(m.msg[:])\n\treturn err\n}\n\n// SysEx sends a System Exclusive message.\n// The cable parameter is the cable number 0-15.\n// The data parameter is a slice with the data to send.\n// It needs to start with the manufacturer ID, which is either\n// 1 or 3 bytes in length.\n// The data slice should not include the SysEx start (0xF0) or\n// end (0xF7) bytes, only the data in between.\nfunc (m *midi) SysEx(cable uint8, data []byte) error {\n\tswitch {\n\tcase cable > 15:\n\t\treturn errInvalidMIDICable\n\tcase len(data) < 3:\n\t\treturn errInvalidMIDISysExData\n\t}\n\n\t// write start\n\tm.msg[0], m.msg[1] = ((cable&0xf)<<4)|CINSysExStart, MsgSysExStart\n\tm.msg[2], m.msg[3] = data[0], data[1]\n\tif _, err := m.Write(m.msg[:]); err != nil {\n\t\treturn err\n\t}\n\n\t// write middle\n\ti := 2\n\tfor ; i < len(data)-2; i += 3 {\n\t\tm.msg[0], m.msg[1] = ((cable&0xf)<<4)|CINSysExStart, data[i]\n\t\tm.msg[2], m.msg[3] = data[i+1], data[i+2]\n\t\tif _, err := m.Write(m.msg[:]); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\t// write end\n\tswitch len(data) - i {\n\tcase 2:\n\t\tm.msg[0], m.msg[1] = ((cable&0xf)<<4)|CINSysExEnd3, data[i]\n\t\tm.msg[2], m.msg[3] = data[i+1], MsgSysExEnd\n\tcase 1:\n\t\tm.msg[0], m.msg[1] = ((cable&0xf)<<4)|CINSysExEnd2, data[i]\n\t\tm.msg[2], m.msg[3] = MsgSysExEnd, 0\n\tcase 0:\n\t\tm.msg[0], m.msg[1] = ((cable&0xf)<<4)|CINSysExEnd1, MsgSysExEnd\n\t\tm.msg[2], m.msg[3] = 0, 0\n\t}\n\tif _, err := m.Write(m.msg[:]); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "src/machine/usb/adc/midi/midi.go",
    "content": "package midi\n\nimport (\n\t\"machine\"\n\t\"machine/usb\"\n\t\"machine/usb/descriptor\"\n)\n\nconst (\n\tmidiEndpointOut = usb.MIDI_ENDPOINT_OUT // from PC\n\tmidiEndpointIn  = usb.MIDI_ENDPOINT_IN  // to PC\n)\n\nvar Midi *midi\n\ntype midi struct {\n\tmsg       [4]byte\n\tbuf       *RingBuffer\n\trxHandler func([]byte)\n\ttxHandler func()\n\twaitTxc   bool\n}\n\nfunc init() {\n\tif Midi == nil {\n\t\tMidi = newMidi()\n\t}\n}\n\n// New returns the USB MIDI port.\n// Deprecated, better to just use Port()\nfunc New() *midi {\n\treturn Port()\n}\n\n// Port returns the USB midi port.\nfunc Port() *midi {\n\treturn Midi\n}\n\nfunc newMidi() *midi {\n\tm := &midi{\n\t\tbuf: NewRingBuffer(),\n\t}\n\tmachine.ConfigureUSBEndpoint(descriptor.CDCMIDI,\n\t\t[]usb.EndpointConfig{\n\t\t\t{\n\t\t\t\tIndex:     usb.MIDI_ENDPOINT_OUT,\n\t\t\t\tIsIn:      false,\n\t\t\t\tType:      usb.ENDPOINT_TYPE_BULK,\n\t\t\t\tRxHandler: m.RxHandler,\n\t\t\t},\n\t\t\t{\n\t\t\t\tIndex:     usb.MIDI_ENDPOINT_IN,\n\t\t\t\tIsIn:      true,\n\t\t\t\tType:      usb.ENDPOINT_TYPE_BULK,\n\t\t\t\tTxHandler: m.TxHandler,\n\t\t\t},\n\t\t},\n\t\t[]usb.SetupConfig{},\n\t)\n\treturn m\n}\n\n// SetHandler is now deprecated, please use SetRxHandler().\nfunc (m *midi) SetHandler(rxHandler func([]byte)) {\n\tm.SetRxHandler(rxHandler)\n}\n\n// SetRxHandler sets the handler function for incoming MIDI messages.\nfunc (m *midi) SetRxHandler(rxHandler func([]byte)) {\n\tm.rxHandler = rxHandler\n}\n\n// SetTxHandler sets the handler function for outgoing MIDI messages.\nfunc (m *midi) SetTxHandler(txHandler func()) {\n\tm.txHandler = txHandler\n}\n\nfunc (m *midi) Write(b []byte) (n int, err error) {\n\ts, e := 0, 0\n\tfor s = 0; s < len(b); s += 4 {\n\t\te = s + 4\n\t\tif e > len(b) {\n\t\t\te = len(b)\n\t\t}\n\n\t\tm.tx(b[s:e])\n\t}\n\treturn e, nil\n}\n\n// sendUSBPacket sends a MIDIPacket.\nfunc (m *midi) sendUSBPacket(b []byte) {\n\tmachine.SendUSBInPacket(midiEndpointIn, b)\n}\n\n// from BulkIn\nfunc (m *midi) TxHandler() {\n\tif m.txHandler != nil {\n\t\tm.txHandler()\n\t}\n\n\tm.waitTxc = false\n\tif b, ok := m.buf.Get(); ok {\n\t\tm.waitTxc = true\n\t\tm.sendUSBPacket(b)\n\t}\n}\n\nfunc (m *midi) tx(b []byte) {\n\tif machine.USBDev.InitEndpointComplete {\n\t\tif m.waitTxc {\n\t\t\tm.buf.Put(b)\n\t\t} else {\n\t\t\tm.waitTxc = true\n\t\t\tm.sendUSBPacket(b)\n\t\t}\n\t}\n}\n\n// from BulkOut\nfunc (m *midi) RxHandler(b []byte) {\n\tif m.rxHandler != nil {\n\t\tm.rxHandler(b)\n\t}\n}\n"
  },
  {
    "path": "src/machine/usb/adc/midi/notes.go",
    "content": "package midi\n\n// Note represents a MIDI note number. For example, Note(69) is A4 or 440Hz.\ntype Note uint8\n\n// Define all the notes in a format similar to the Tone library in the Arduino\n// IDE.\nconst (\n\tA0 Note = iota + 21 // 27.5Hz\n\tAS0\n\tB0\n\tC1\n\tCS1\n\tD1\n\tDS1\n\tE1\n\tF1\n\tFS1\n\tG1\n\tGS1\n\tA1 // 55Hz\n\tAS1\n\tB1\n\tC2\n\tCS2\n\tD2\n\tDS2\n\tE2\n\tF2\n\tFS2\n\tG2\n\tGS2\n\tA2 // 110Hz\n\tAS2\n\tB2\n\tC3\n\tCS3\n\tD3\n\tDS3\n\tE3\n\tF3\n\tFS3\n\tG3\n\tGS3\n\tA3 // 220Hz\n\tAS3\n\tB3\n\tC4\n\tCS4\n\tD4\n\tDS4\n\tE4\n\tF4\n\tFS4\n\tG4\n\tGS4\n\tA4 // 440Hz\n\tAS4\n\tB4\n\tC5\n\tCS5\n\tD5\n\tDS5\n\tE5\n\tF5\n\tFS5\n\tG5\n\tGS5\n\tA5 // 880Hz\n\tAS5\n\tB5\n\tC6\n\tCS6\n\tD6\n\tDS6\n\tE6\n\tF6\n\tFS6\n\tG6\n\tGS6\n\tA6 // 1760Hz\n\tAS6\n\tB6\n\tC7\n\tCS7\n\tD7\n\tDS7\n\tE7\n\tF7\n\tFS7\n\tG7\n\tGS7\n\tA7 // 3520Hz\n\tAS7\n\tB7\n\tC8\n\tCS8\n\tD8\n\tDS8\n\tE8\n\tF8\n\tFS8\n\tG8\n\tGS8\n\tA8 // 7040Hz\n\tAS8\n\tB8\n)\n"
  },
  {
    "path": "src/machine/usb/cdc/buffer.go",
    "content": "package cdc\n\nimport (\n\t\"runtime/volatile\"\n)\n\nconst rxRingBufferSize = 128\n\n// rxRingBuffer is ring buffer implementation inspired by post at\n// https://www.embeddedrelated.com/showthread/comp.arch.embedded/77084-1.php\ntype rxRingBuffer struct {\n\tbuffer [rxRingBufferSize]volatile.Register8\n\thead   volatile.Register8\n\ttail   volatile.Register8\n}\n\n// NewRxRingBuffer returns a new ring buffer.\nfunc NewRxRingBuffer() *rxRingBuffer {\n\treturn &rxRingBuffer{}\n}\n\n// Used returns how many bytes in buffer have been used.\nfunc (rb *rxRingBuffer) Used() uint8 {\n\treturn uint8(rb.head.Get() - rb.tail.Get())\n}\n\n// Put stores a byte in the buffer. If the buffer is already\n// full, the method will return false.\nfunc (rb *rxRingBuffer) Put(val byte) bool {\n\tif rb.Used() != rxRingBufferSize {\n\t\trb.head.Set(rb.head.Get() + 1)\n\t\trb.buffer[rb.head.Get()%rxRingBufferSize].Set(val)\n\t\treturn true\n\t}\n\treturn false\n}\n\n// Get returns a byte from the buffer. If the buffer is empty,\n// the method will return a false as the second value.\nfunc (rb *rxRingBuffer) Get() (byte, bool) {\n\tif rb.Used() != 0 {\n\t\trb.tail.Set(rb.tail.Get() + 1)\n\t\treturn rb.buffer[rb.tail.Get()%rxRingBufferSize].Get(), true\n\t}\n\treturn 0, false\n}\n\n// Clear resets the head and tail pointer to zero.\nfunc (rb *rxRingBuffer) Clear() {\n\trb.head.Set(0)\n\trb.tail.Set(0)\n}\n\nconst txRingBufferSize = 8\n\n// txRingBuffer is ring buffer implementation inspired by post at\n// https://www.embeddedrelated.com/showthread/comp.arch.embedded/77084-1.php\ntype txRingBuffer struct {\n\tbuffer [txRingBufferSize]struct {\n\t\tbuf  [64]byte\n\t\tsize int\n\t}\n\thead volatile.Register8\n\ttail volatile.Register8\n}\n\n// NewTxRingBuffer returns a new ring buffer.\nfunc NewTxRingBuffer() *txRingBuffer {\n\treturn &txRingBuffer{}\n}\n\n// Used returns how many bytes in buffer have been used.\nfunc (rb *txRingBuffer) Used() uint8 {\n\treturn uint8(rb.head.Get() - rb.tail.Get())\n}\n\n// Put stores a byte in the buffer. If the buffer is already\n// full, the method will return false.\nfunc (rb *txRingBuffer) Put(val []byte) bool {\n\tif rb.Used() == txRingBufferSize {\n\t\treturn false\n\t}\n\n\tif rb.Used() == 0 {\n\t\trb.head.Set(rb.head.Get() + 1)\n\t\trb.buffer[rb.head.Get()%txRingBufferSize].size = 0\n\t}\n\tbuf := &rb.buffer[rb.head.Get()%txRingBufferSize]\n\n\tfor i := 0; i < len(val); i++ {\n\t\tif buf.size == 64 {\n\t\t\t// next\n\t\t\t// TODO: Make sure that data is not corrupted even when the buffer is full\n\t\t\trb.head.Set(rb.head.Get() + 1)\n\t\t\tbuf = &rb.buffer[rb.head.Get()%txRingBufferSize]\n\t\t\trb.buffer[rb.head.Get()%txRingBufferSize].size = 0\n\t\t}\n\t\tbuf.buf[buf.size] = val[i]\n\t\tbuf.size++\n\t}\n\treturn true\n}\n\n// Get returns a byte from the buffer. If the buffer is empty,\n// the method will return a false as the second value.\nfunc (rb *txRingBuffer) Get() ([]byte, bool) {\n\tif rb.Used() != 0 {\n\t\trb.tail.Set(rb.tail.Get() + 1)\n\t\tsize := rb.buffer[rb.tail.Get()%txRingBufferSize].size\n\t\treturn rb.buffer[rb.tail.Get()%txRingBufferSize].buf[:size], true\n\t}\n\treturn nil, false\n}\n\n// Clear resets the head and tail pointer to zero.\nfunc (rb *txRingBuffer) Clear() {\n\trb.head.Set(0)\n\trb.tail.Set(0)\n}\n"
  },
  {
    "path": "src/machine/usb/cdc/cdc.go",
    "content": "package cdc\n\nconst (\n\tcdcEndpointACM = 1\n\tcdcEndpointOut = 2\n\tcdcEndpointIn  = 3\n)\n\n// New returns USBCDC struct.\nfunc New() *USBCDC {\n\tif USB == nil {\n\t\tUSB = &USBCDC{\n\t\t\trxBuffer: NewRxRingBuffer(),\n\t\t\ttxBuffer: NewTxRingBuffer(),\n\t\t}\n\t}\n\treturn USB\n}\n\nconst (\n\t// bmRequestType\n\tusb_REQUEST_HOSTTODEVICE = 0x00\n\tusb_REQUEST_DEVICETOHOST = 0x80\n\tusb_REQUEST_DIRECTION    = 0x80\n\n\tusb_REQUEST_STANDARD = 0x00\n\tusb_REQUEST_CLASS    = 0x20\n\tusb_REQUEST_VENDOR   = 0x40\n\tusb_REQUEST_TYPE     = 0x60\n\n\tusb_REQUEST_DEVICE    = 0x00\n\tusb_REQUEST_INTERFACE = 0x01\n\tusb_REQUEST_ENDPOINT  = 0x02\n\tusb_REQUEST_OTHER     = 0x03\n\tusb_REQUEST_RECIPIENT = 0x1F\n\n\tusb_REQUEST_DEVICETOHOST_CLASS_INTERFACE    = (usb_REQUEST_DEVICETOHOST | usb_REQUEST_CLASS | usb_REQUEST_INTERFACE)\n\tusb_REQUEST_HOSTTODEVICE_CLASS_INTERFACE    = (usb_REQUEST_HOSTTODEVICE | usb_REQUEST_CLASS | usb_REQUEST_INTERFACE)\n\tusb_REQUEST_DEVICETOHOST_STANDARD_INTERFACE = (usb_REQUEST_DEVICETOHOST | usb_REQUEST_STANDARD | usb_REQUEST_INTERFACE)\n\n\t// CDC Class requests\n\tusb_CDC_SET_LINE_CODING        = 0x20\n\tusb_CDC_GET_LINE_CODING        = 0x21\n\tusb_CDC_SET_CONTROL_LINE_STATE = 0x22\n\tusb_CDC_SEND_BREAK             = 0x23\n\n\tusb_CDC_V1_10                         = 0x0110\n\tusb_CDC_COMMUNICATION_INTERFACE_CLASS = 0x02\n\n\tusb_CDC_CALL_MANAGEMENT             = 0x01\n\tusb_CDC_ABSTRACT_CONTROL_MODEL      = 0x02\n\tusb_CDC_HEADER                      = 0x00\n\tusb_CDC_ABSTRACT_CONTROL_MANAGEMENT = 0x02\n\tusb_CDC_UNION                       = 0x06\n\tusb_CDC_CS_INTERFACE                = 0x24\n\tusb_CDC_CS_ENDPOINT                 = 0x25\n\tusb_CDC_DATA_INTERFACE_CLASS        = 0x0A\n\n\tusb_CDC_LINESTATE_DTR = 0x01\n\tusb_CDC_LINESTATE_RTS = 0x02\n)\n"
  },
  {
    "path": "src/machine/usb/cdc/doc.go",
    "content": "// package cdc is for USB Communication Device Class devices.\npackage cdc\n"
  },
  {
    "path": "src/machine/usb/cdc/usbcdc.go",
    "content": "package cdc\n\nimport (\n\t\"errors\"\n\t\"machine\"\n\t\"machine/usb\"\n\t\"runtime/interrupt\"\n)\n\nvar (\n\tErrBufferEmpty = errors.New(\"USB-CDC buffer empty\")\n)\n\nconst cdcLineInfoSize = 7\n\ntype cdcLineInfo struct {\n\tdwDTERate   uint32\n\tbCharFormat uint8\n\tbParityType uint8\n\tbDataBits   uint8\n\tlineState   uint8\n}\n\n// Read from the RX buffer.\nfunc (usbcdc *USBCDC) Read(data []byte) (n int, err error) {\n\t// check if RX buffer is empty\n\tsize := usbcdc.Buffered()\n\tif size == 0 {\n\t\treturn 0, nil\n\t}\n\n\t// Make sure we do not read more from buffer than the data slice can hold.\n\tif len(data) < size {\n\t\tsize = len(data)\n\t}\n\n\t// only read number of bytes used from buffer\n\tfor i := 0; i < size; i++ {\n\t\tv, _ := usbcdc.ReadByte()\n\t\tdata[i] = v\n\t}\n\n\treturn size, nil\n}\n\n// ReadByte reads a single byte from the RX buffer.\n// If there is no data in the buffer, returns an error.\nfunc (usbcdc *USBCDC) ReadByte() (byte, error) {\n\t// check if RX buffer is empty\n\tbuf, ok := usbcdc.rxBuffer.Get()\n\tif !ok {\n\t\treturn 0, ErrBufferEmpty\n\t}\n\treturn buf, nil\n}\n\n// Buffered returns the number of bytes currently stored in the RX buffer.\nfunc (usbcdc *USBCDC) Buffered() int {\n\treturn int(usbcdc.rxBuffer.Used())\n}\n\n// Receive handles adding data to the UART's data buffer.\n// Usually called by the IRQ handler for a machine.\nfunc (usbcdc *USBCDC) Receive(data byte) {\n\tusbcdc.rxBuffer.Put(data)\n}\n\n// USBCDC is the USB CDC aka serial over USB interface.\ntype USBCDC struct {\n\trxBuffer *rxRingBuffer\n\ttxBuffer *txRingBuffer\n\twaitTxc  bool\n}\n\nvar (\n\t// USB is a USB CDC interface.\n\tUSB *USBCDC\n\n\tusbLineInfo = cdcLineInfo{115200, 0x00, 0x00, 0x08, 0x00}\n)\n\n// Configure the USB CDC interface. The config is here for compatibility with the UART interface.\nfunc (usbcdc *USBCDC) Configure(config machine.UARTConfig) error {\n\treturn nil\n}\n\n// Flush flushes buffered data.\nfunc (usbcdc *USBCDC) Flush() {\n\tmask := interrupt.Disable()\n\tif b, ok := usbcdc.txBuffer.Get(); ok {\n\t\tmachine.SendUSBInPacket(cdcEndpointIn, b)\n\t} else {\n\t\tusbcdc.waitTxc = false\n\t}\n\tinterrupt.Restore(mask)\n}\n\n// Write data to the USBCDC.\nfunc (usbcdc *USBCDC) Write(data []byte) (n int, err error) {\n\tif usbLineInfo.lineState > 0 {\n\t\tmask := interrupt.Disable()\n\t\tusbcdc.txBuffer.Put(data)\n\t\tif !usbcdc.waitTxc {\n\t\t\tusbcdc.waitTxc = true\n\t\t\tusbcdc.Flush()\n\t\t}\n\t\tinterrupt.Restore(mask)\n\t}\n\treturn len(data), nil\n}\n\n// WriteByte writes a byte of data to the USB CDC interface.\nfunc (usbcdc *USBCDC) WriteByte(c byte) error {\n\tusbcdc.Write([]byte{c})\n\treturn nil\n}\n\nfunc (usbcdc *USBCDC) DTR() bool {\n\treturn (usbLineInfo.lineState & usb_CDC_LINESTATE_DTR) > 0\n}\n\nfunc (usbcdc *USBCDC) RTS() bool {\n\treturn (usbLineInfo.lineState & usb_CDC_LINESTATE_RTS) > 0\n}\n\nfunc cdcCallbackRx(b []byte) {\n\tfor i := range b {\n\t\tUSB.Receive(b[i])\n\t}\n}\n\nvar cdcSetupBuff [cdcLineInfoSize]byte\n\nfunc cdcSetup(setup usb.Setup) bool {\n\tif setup.BmRequestType == usb_REQUEST_DEVICETOHOST_CLASS_INTERFACE {\n\t\tif setup.BRequest == usb_CDC_GET_LINE_CODING {\n\t\t\tcdcSetupBuff[0] = byte(usbLineInfo.dwDTERate)\n\t\t\tcdcSetupBuff[1] = byte(usbLineInfo.dwDTERate >> 8)\n\t\t\tcdcSetupBuff[2] = byte(usbLineInfo.dwDTERate >> 16)\n\t\t\tcdcSetupBuff[3] = byte(usbLineInfo.dwDTERate >> 24)\n\t\t\tcdcSetupBuff[4] = byte(usbLineInfo.bCharFormat)\n\t\t\tcdcSetupBuff[5] = byte(usbLineInfo.bParityType)\n\t\t\tcdcSetupBuff[6] = byte(usbLineInfo.bDataBits)\n\n\t\t\tmachine.SendUSBInPacket(0, cdcSetupBuff[:])\n\t\t\treturn true\n\t\t}\n\t}\n\n\tif setup.BmRequestType == usb_REQUEST_HOSTTODEVICE_CLASS_INTERFACE {\n\t\tif setup.BRequest == usb_CDC_SET_LINE_CODING {\n\t\t\tb, err := machine.ReceiveUSBControlPacket()\n\t\t\tif err != nil {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tusbLineInfo.dwDTERate = uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24\n\t\t\tusbLineInfo.bCharFormat = b[4]\n\t\t\tusbLineInfo.bParityType = b[5]\n\t\t\tusbLineInfo.bDataBits = b[6]\n\t\t}\n\n\t\tif setup.BRequest == usb_CDC_SET_CONTROL_LINE_STATE {\n\t\t\tusbLineInfo.lineState = setup.WValueL\n\t\t}\n\n\t\tif setup.BRequest == usb_CDC_SET_LINE_CODING || setup.BRequest == usb_CDC_SET_CONTROL_LINE_STATE {\n\t\t\t// auto-reset into the bootloader\n\t\t\tif usbLineInfo.dwDTERate == 1200 && usbLineInfo.lineState&usb_CDC_LINESTATE_DTR == 0 {\n\t\t\t\tmachine.EnterBootloader()\n\t\t\t} else {\n\t\t\t\t// TODO: cancel any reset\n\t\t\t}\n\t\t\tmachine.SendZlp()\n\t\t}\n\n\t\tif setup.BRequest == usb_CDC_SEND_BREAK {\n\t\t\t// TODO: something with this value?\n\t\t\t// breakValue = ((uint16_t)setup.wValueH << 8) | setup.wValueL;\n\t\t\t// return false;\n\t\t\tmachine.SendZlp()\n\t\t}\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunc EnableUSBCDC() {\n\tmachine.USBCDC = New()\n\tmachine.EnableCDC(USB.Flush, cdcCallbackRx, cdcSetup)\n}\n"
  },
  {
    "path": "src/machine/usb/config.go",
    "content": "package usb\n\ntype EndpointConfig struct {\n\tIndex          uint8\n\tIsIn           bool\n\tTxHandler      func()\n\tRxHandler      func([]byte)\n\tDelayRxHandler func([]byte) bool\n\tStallHandler   func(Setup) bool\n\tType           uint8\n}\n\ntype SetupConfig struct {\n\tIndex   uint8\n\tHandler func(Setup) bool\n}\n"
  },
  {
    "path": "src/machine/usb/descriptor/cdc.go",
    "content": "package descriptor\n\nconst (\n\tcdcFunctionalHeader         = 0\n\tcdcFunctionalCallManagement = 0x1\n\tcdcFunctionalACM            = 0x2\n\tcdcFunctionalDirect         = 0x3\n\tcdcFunctionalRinger         = 0x4\n\tcdcFunctionalCall           = 0x5\n\tcdcFunctionalUnion          = 0x6\n\tcdcFunctionalCountry        = 0x7\n\tcdcFunctionalOperational    = 0x8\n\tcdcFunctionalUSB            = 0x9\n\tcdcFunctionalNetwork        = 0xa\n\tcdcFunctionalProtocol       = 0xb\n\tcdcFunctionalExtension      = 0xc\n\tcdcFunctionalMulti          = 0xd\n\tcdcFunctionalCAPI           = 0xe\n\tcdcFunctionalEthernet       = 0xf\n\tcdcFunctionalATM            = 0x10\n)\n\nvar classSpecificCDCHeader = [classSpecificTypeLen]byte{\n\tclassSpecificTypeLen,\n\tTypeClassSpecific,\n\tcdcFunctionalHeader,\n\t0x10, //\n\t0x1,  //\n}\n\nvar ClassSpecificCDCHeader = ClassSpecificType{\n\tdata: classSpecificCDCHeader[:],\n}\n\nvar classSpecificCDCCallManagement = [classSpecificTypeLen]byte{\n\tclassSpecificTypeLen,\n\tTypeClassSpecific,\n\tcdcFunctionalCallManagement,\n\t0x0, //\n\t0x1, //\n}\n\nvar ClassSpecificCDCCallManagement = ClassSpecificType{\n\tdata: classSpecificCDCCallManagement[:],\n}\n\nvar classSpecificCDCACM = [classSpecificTypeLen]byte{\n\t4,\n\tTypeClassSpecific,\n\tcdcFunctionalACM,\n\t0x2, //\n}\n\nvar ClassSpecificCDCACM = ClassSpecificType{\n\tdata: classSpecificCDCACM[:],\n}\n\nvar classSpecificCDCUnion = [classSpecificTypeLen]byte{\n\tclassSpecificTypeLen,\n\tTypeClassSpecific,\n\tcdcFunctionalUnion,\n\t0x0, //\n\t0x1, //\n}\n\nvar ClassSpecificCDCUnion = ClassSpecificType{\n\tdata: classSpecificCDCUnion[:],\n}\n\nvar interfaceAssociationCDC = [interfaceAssociationTypeLen]byte{\n\tinterfaceAssociationTypeLen,\n\tTypeInterfaceAssociation,\n\t0x00, // FirstInterface\n\t0x02, // InterfaceCount\n\t0x02, // FunctionClass\n\t0x02, // FunctionSubClass\n\t0x01, // FunctionProtocol\n\t0x00, // Function\n}\n\nvar InterfaceAssociationCDC = InterfaceAssociationType{\n\tdata: interfaceAssociationCDC[:],\n}\n\nvar deviceCDC = [deviceTypeLen]byte{\n\tdeviceTypeLen,\n\tTypeDevice,\n\t0x00, 0x02, // USB version\n\t0xef,       // device class\n\t0x02,       // device subclass\n\t0x01,       // protocol\n\t0x40,       // maxpacketsize\n\t0x86, 0x28, // vendor id\n\t0x2d, 0x80, // product id\n\t0x00, 0x01, // device\n\t0x01, // manufacturer\n\t0x02, // product\n\t0x03, // SerialNumber\n\t0x01, // NumConfigurations\n}\n\nvar DeviceCDC = DeviceType{\n\tdata: deviceCDC[:],\n}\n\nvar configurationCDC = [configurationTypeLen]byte{\n\tconfigurationTypeLen,\n\tTypeConfiguration,\n\t0x4b, 0x00, // adjust length as needed\n\t0x02, // number of interfaces\n\t0x01, // configuration value\n\t0x00, // index to string description\n\t0xa0, // attributes\n\t0x32, // maxpower\n}\n\nvar ConfigurationCDC = ConfigurationType{\n\tdata: configurationCDC[:],\n}\n\nvar interfaceCDCControl = [interfaceTypeLen]byte{\n\tinterfaceTypeLen,\n\tTypeInterface,\n\t0x00, // InterfaceNumber\n\t0x00, // AlternateSetting\n\t0x01, // NumEndpoints\n\t0x02, // InterfaceClass\n\t0x02, // InterfaceSubClass\n\t0x01, // InterfaceProtocol\n\t0x00, // Interface\n}\n\nvar InterfaceCDCControl = InterfaceType{\n\tdata: interfaceCDCControl[:],\n}\n\nvar interfaceCDCData = [interfaceTypeLen]byte{\n\tinterfaceTypeLen,\n\tTypeInterface,\n\t0x01, // InterfaceNumber\n\t0x00, // AlternateSetting\n\t0x02, // NumEndpoints\n\t0x0a, // InterfaceClass\n\t0x00, // InterfaceSubClass\n\t0x00, // InterfaceProtocol\n\t0x00, // Interface\n}\n\nvar InterfaceCDCData = InterfaceType{\n\tdata: interfaceCDCData[:],\n}\n\nvar CDC = Descriptor{\n\tDevice: DeviceCDC.Bytes(),\n\tConfiguration: Append([][]byte{\n\t\tConfigurationCDC.Bytes(),\n\t\tInterfaceAssociationCDC.Bytes(),\n\t\tInterfaceCDCControl.Bytes(),\n\t\tClassSpecificCDCHeader.Bytes(),\n\t\tClassSpecificCDCCallManagement.Bytes(),\n\t\tClassSpecificCDCACM.Bytes(),\n\t\tClassSpecificCDCUnion.Bytes(),\n\t\tEndpointEP1IN.Bytes(),\n\t\tInterfaceCDCData.Bytes(),\n\t\tEndpointEP2OUT.Bytes(),\n\t\tEndpointEP3IN.Bytes(),\n\t}),\n}\n"
  },
  {
    "path": "src/machine/usb/descriptor/classspecific.go",
    "content": "package descriptor\n\nconst (\n\tclassSpecificTypeLen = 5\n)\n\ntype ClassSpecificType struct {\n\tdata []byte\n}\n\nfunc (d ClassSpecificType) Bytes() []byte {\n\treturn d.data[:d.data[0]]\n}\n\nfunc (d ClassSpecificType) Length(v uint8) {\n\td.data[0] = byte(v)\n}\n"
  },
  {
    "path": "src/machine/usb/descriptor/configuration.go",
    "content": "package descriptor\n\nimport (\n\t\"internal/binary\"\n)\n\nconst (\n\tconfigurationTypeLen = 9\n)\n\ntype ConfigurationType struct {\n\tdata []byte\n}\n\nfunc (d ConfigurationType) Bytes() []byte {\n\treturn d.data\n}\n\nfunc (d ConfigurationType) Length(v uint8) {\n\td.data[0] = byte(v)\n}\n\nfunc (d ConfigurationType) Type(v uint8) {\n\td.data[1] = byte(v)\n}\n\nfunc (d ConfigurationType) TotalLength(v uint16) {\n\tbinary.LittleEndian.PutUint16(d.data[2:4], v)\n}\n\nfunc (d ConfigurationType) NumInterfaces(v uint8) {\n\td.data[4] = byte(v)\n}\n\nfunc (d ConfigurationType) ConfigurationValue(v uint8) {\n\td.data[5] = byte(v)\n}\n\nfunc (d ConfigurationType) Configuration(v uint8) {\n\td.data[6] = byte(v)\n}\n\nfunc (d ConfigurationType) Attributes(v uint8) {\n\td.data[7] = byte(v)\n}\n\nfunc (d ConfigurationType) MaxPower(v uint8) {\n\td.data[8] = byte(v)\n}\n"
  },
  {
    "path": "src/machine/usb/descriptor/descriptor.go",
    "content": "package descriptor\n\nimport (\n\t\"runtime/volatile\"\n)\n\nconst (\n\tTypeDevice                = 0x1\n\tTypeConfiguration         = 0x2\n\tTypeString                = 0x3\n\tTypeInterface             = 0x4\n\tTypeEndpoint              = 0x5\n\tTypeDeviceQualifier       = 0x6\n\tTypeInterfaceAssociation  = 0xb\n\tTypeClassHID              = 0x21\n\tTypeHIDReport             = 0x22\n\tTypeClassSpecific         = 0x24\n\tTypeClassSpecificEndpoint = 0x25\n)\n\n// DeviceDescBank is the USB device endpoint .\ntype DeviceDescBank struct {\n\tADDR      volatile.Register32\n\tPCKSIZE   volatile.Register32\n\tEXTREG    volatile.Register16\n\tSTATUS_BK volatile.Register8\n\t_reserved [5]volatile.Register8\n}\n\ntype Device struct {\n\tDeviceDescBank [2]DeviceDescBank\n}\n\ntype Descriptor struct {\n\tDevice        []byte\n\tConfiguration []byte\n\tHID           map[uint16][]byte\n}\n\nfunc (d *Descriptor) Configure(idVendor, idProduct uint16) {\n\tdev := DeviceType{d.Device}\n\tdev.VendorID(idVendor)\n\tdev.ProductID(idProduct)\n\n\tconf := ConfigurationType{d.Configuration}\n\tconf.TotalLength(uint16(len(d.Configuration)))\n}\n\nfunc Append[T any](slices [][]T) []T {\n\tvar size, pos int\n\n\tfor _, s := range slices {\n\t\tsize += len(s)\n\t}\n\n\tresult := make([]T, size)\n\n\tfor _, s := range slices {\n\t\tpos += copy(result[pos:], s)\n\t}\n\n\treturn result\n}\n"
  },
  {
    "path": "src/machine/usb/descriptor/device.go",
    "content": "package descriptor\n\nimport (\n\t\"internal/binary\"\n)\n\nconst (\n\tdeviceTypeLen = 18\n)\n\ntype DeviceType struct {\n\tdata []byte\n}\n\nfunc (d DeviceType) Bytes() []byte {\n\treturn d.data\n}\n\nfunc (d DeviceType) Length(v uint8) {\n\td.data[0] = byte(v)\n}\n\nfunc (d DeviceType) Type(v uint8) {\n\td.data[1] = byte(v)\n}\n\nfunc (d DeviceType) USB(v uint16) {\n\tbinary.LittleEndian.PutUint16(d.data[2:4], v)\n}\n\nfunc (d DeviceType) DeviceClass(v uint8) {\n\td.data[4] = byte(v)\n}\n\nfunc (d DeviceType) DeviceSubClass(v uint8) {\n\td.data[5] = byte(v)\n}\n\nfunc (d DeviceType) DeviceProtocol(v uint8) {\n\td.data[6] = byte(v)\n}\n\nfunc (d DeviceType) MaxPacketSize0(v uint8) {\n\td.data[7] = byte(v)\n}\n\nfunc (d DeviceType) VendorID(v uint16) {\n\tbinary.LittleEndian.PutUint16(d.data[8:10], v)\n}\n\nfunc (d DeviceType) ProductID(v uint16) {\n\tbinary.LittleEndian.PutUint16(d.data[10:12], v)\n}\n\nfunc (d DeviceType) Device(v uint16) {\n\tbinary.LittleEndian.PutUint16(d.data[12:14], v)\n}\n\nfunc (d DeviceType) Manufacturer(v uint8) {\n\td.data[14] = byte(v)\n}\n\nfunc (d DeviceType) Product(v uint8) {\n\td.data[15] = byte(v)\n}\n\nfunc (d DeviceType) SerialNumber(v uint8) {\n\td.data[16] = byte(v)\n}\n\nfunc (d DeviceType) NumConfigurations(v uint8) {\n\td.data[17] = byte(v)\n}\n"
  },
  {
    "path": "src/machine/usb/descriptor/doc.go",
    "content": "// package descriptor is for the USB descriptor definitions.\n// For the actual implementations, see the individual packages.\npackage descriptor\n"
  },
  {
    "path": "src/machine/usb/descriptor/endpoint.go",
    "content": "package descriptor\n\nimport (\n\t\"internal/binary\"\n)\n\n/* Endpoint Descriptor\nUSB 2.0 Specification: 9.6.6 Endpoint\n*/\n\nconst (\n\tTransferTypeControl uint8 = iota\n\tTransferTypeIsochronous\n\tTransferTypeBulk\n\tTransferTypeInterrupt\n)\n\nvar endpointEP1IN = [endpointTypeLen]byte{\n\tendpointTypeLen,\n\tTypeEndpoint,\n\t0x81, // EndpointAddress\n\t0x03, // Attributes\n\t0x10, // MaxPacketSizeL\n\t0x00, // MaxPacketSizeH\n\t0x10, // Interval\n}\n\nvar EndpointEP1IN = EndpointType{\n\tdata: endpointEP1IN[:],\n}\n\nvar endpointEP2OUT = [endpointTypeLen]byte{\n\tendpointTypeLen,\n\tTypeEndpoint,\n\t0x02, // EndpointAddress\n\t0x02, // Attributes\n\t0x40, // MaxPacketSizeL\n\t0x00, // MaxPacketSizeH\n\t0x00, // Interval\n}\n\nvar EndpointEP2OUT = EndpointType{\n\tdata: endpointEP2OUT[:],\n}\n\nvar endpointEP3IN = [endpointTypeLen]byte{\n\tendpointTypeLen,\n\tTypeEndpoint,\n\t0x83, // EndpointAddress\n\t0x02, // Attributes\n\t0x40, // MaxPacketSizeL\n\t0x00, // MaxPacketSizeH\n\t0x00, // Interval\n}\n\nvar EndpointEP3IN = EndpointType{\n\tdata: endpointEP3IN[:],\n}\n\nvar endpointEP4IN = [endpointTypeLen]byte{\n\tendpointTypeLen,\n\tTypeEndpoint,\n\t0x84, // EndpointAddress\n\t0x03, // Attributes\n\t0x40, // MaxPacketSizeL\n\t0x00, // MaxPacketSizeH\n\t0x01, // Interval\n}\n\nvar EndpointEP4IN = EndpointType{\n\tdata: endpointEP4IN[:],\n}\n\nvar endpointEP5OUT = [endpointTypeLen]byte{\n\tendpointTypeLen,\n\tTypeEndpoint,\n\t0x05, // EndpointAddress\n\t0x03, // Attributes\n\t0x40, // MaxPacketSizeL\n\t0x00, // MaxPacketSizeH\n\t0x01, // Interval\n}\n\nvar EndpointEP5OUT = EndpointType{\n\tdata: endpointEP5OUT[:],\n}\n\n// Mass Storage Class bulk in endpoint\nvar endpointMSCIN = [endpointTypeLen]byte{\n\tendpointTypeLen,\n\tTypeEndpoint,\n\t0x86,             // EndpointAddress\n\tTransferTypeBulk, // Attributes\n\t0x40,             // MaxPacketSizeL (64 bytes)\n\t0x00,             // MaxPacketSizeH\n\t0x00,             // Interval\n}\n\nvar EndpointMSCIN = EndpointType{\n\tdata: endpointMSCIN[:],\n}\n\n// Mass Storage Class bulk out endpoint\nvar endpointMSCOUT = [endpointTypeLen]byte{\n\tendpointTypeLen,\n\tTypeEndpoint,\n\t0x07,             // EndpointAddress\n\tTransferTypeBulk, // Attributes\n\t0x40,             // MaxPacketSizeL (64 bytes)\n\t0x00,             // MaxPacketSizeH\n\t0x00,             // Interval\n}\n\nvar EndpointMSCOUT = EndpointType{\n\tdata: endpointMSCOUT[:],\n}\n\nconst (\n\tendpointTypeLen = 7\n)\n\ntype EndpointType struct {\n\tdata []byte\n}\n\nfunc (d EndpointType) Bytes() []byte {\n\treturn d.data\n}\n\nfunc (d EndpointType) Length(v uint8) {\n\td.data[0] = byte(v)\n}\n\nfunc (d EndpointType) Type(v uint8) {\n\td.data[1] = byte(v)\n}\n\nfunc (d EndpointType) EndpointAddress(v uint8) {\n\td.data[2] = byte(v)\n}\n\nfunc (d EndpointType) Attributes(v uint8) {\n\td.data[3] = byte(v)\n}\n\nfunc (d EndpointType) MaxPacketSize(v uint16) {\n\tbinary.LittleEndian.PutUint16(d.data[4:6], v)\n}\n\nfunc (d EndpointType) Interval(v uint8) {\n\td.data[6] = byte(v)\n}\n\nfunc (d EndpointType) GetMaxPacketSize() uint16 {\n\treturn binary.LittleEndian.Uint16(d.data[4:6])\n}\n"
  },
  {
    "path": "src/machine/usb/descriptor/hid.go",
    "content": "package descriptor\n\nimport (\n\t\"errors\"\n\t\"internal/binary\"\n\t\"internal/bytealg\"\n)\n\nvar configurationCDCHID = [configurationTypeLen]byte{\n\tconfigurationTypeLen,\n\tTypeConfiguration,\n\t0x64, 0x00, // adjust length as needed\n\t0x03, // number of interfaces\n\t0x01, // configuration value\n\t0x00, // index to string description\n\t0xa0, // attributes\n\t0x32, // maxpower\n}\n\nvar ConfigurationCDCHID = ConfigurationType{\n\tdata: configurationCDCHID[:],\n}\n\nvar interfaceHID = [interfaceTypeLen]byte{\n\tinterfaceTypeLen,\n\tTypeInterface,\n\t0x02, // InterfaceNumber\n\t0x00, // AlternateSetting\n\t0x02, // NumEndpoints\n\t0x03, // InterfaceClass\n\t0x00, // InterfaceSubClass\n\t0x00, // InterfaceProtocol\n\t0x00, // Interface\n}\n\nvar InterfaceHID = InterfaceType{\n\tdata: interfaceHID[:],\n}\n\nconst (\n\tClassHIDTypeLen = 9\n)\n\ntype ClassHIDType struct {\n\tdata []byte\n}\n\nfunc (d ClassHIDType) Bytes() []byte {\n\treturn d.data[:]\n}\n\nfunc (d ClassHIDType) Length(v uint8) {\n\td.data[0] = byte(v)\n}\n\nfunc (d ClassHIDType) Type(v uint8) {\n\td.data[1] = byte(v)\n}\n\nfunc (d ClassHIDType) HID(v uint16) {\n\tbinary.LittleEndian.PutUint16(d.data[2:4], v)\n}\n\nfunc (d ClassHIDType) CountryCode(v uint8) {\n\td.data[4] = byte(v)\n}\n\nfunc (d ClassHIDType) NumDescriptors(v uint8) {\n\td.data[5] = byte(v)\n}\n\nfunc (d ClassHIDType) ClassType(v uint8) {\n\td.data[6] = byte(v)\n}\n\nfunc (d ClassHIDType) ClassLength(v uint16) {\n\tbinary.LittleEndian.PutUint16(d.data[7:9], v)\n}\n\nvar errNoClassHIDFound = errors.New(\"no classHID found\")\n\n// FindClassHIDType tries to find the ClassHID class in the descriptor.\nfunc FindClassHIDType(des, class []byte) (ClassHIDType, error) {\n\tif len(des) < ClassHIDTypeLen || len(class) == 0 {\n\t\treturn ClassHIDType{}, errNoClassHIDFound\n\t}\n\n\t// search only for ClassHIDType without the ClassLength,\n\t// in case it has already been set.\n\tidx := bytealg.Index(des, class[:ClassHIDTypeLen-2])\n\tif idx == -1 {\n\t\treturn ClassHIDType{}, errNoClassHIDFound\n\t}\n\n\treturn ClassHIDType{data: des[idx : idx+ClassHIDTypeLen]}, nil\n}\n\nvar classHID = [ClassHIDTypeLen]byte{\n\tClassHIDTypeLen,\n\tTypeClassHID,\n\t0x11, // HID version L\n\t0x01, // HID version H\n\t0x00, // CountryCode\n\t0x01, // NumDescriptors\n\t0x22, // ClassType\n\t0x91, // ClassLength L\n\t0x00, // ClassLength H\n}\n\nvar ClassHID = ClassHIDType{\n\tdata: classHID[:],\n}\n\nvar CDCHID = Descriptor{\n\tDevice: DeviceCDC.Bytes(),\n\tConfiguration: Append([][]byte{\n\t\tConfigurationCDCHID.Bytes(),\n\t\tInterfaceAssociationCDC.Bytes(),\n\t\tInterfaceCDCControl.Bytes(),\n\t\tClassSpecificCDCHeader.Bytes(),\n\t\tClassSpecificCDCACM.Bytes(),\n\t\tClassSpecificCDCUnion.Bytes(),\n\t\tClassSpecificCDCCallManagement.Bytes(),\n\t\tEndpointEP1IN.Bytes(),\n\t\tInterfaceCDCData.Bytes(),\n\t\tEndpointEP2OUT.Bytes(),\n\t\tEndpointEP3IN.Bytes(),\n\t\tInterfaceHID.Bytes(),\n\t\tClassHID.Bytes(),\n\t\tEndpointEP4IN.Bytes(),\n\t\tEndpointEP5OUT.Bytes(),\n\t}),\n\tHID: map[uint16][]byte{\n\t\t2: Append([][]byte{ // Update ClassLength in classHID whenever the array length is modified!\n\t\t\tHIDUsagePageGenericDesktop,\n\t\t\tHIDUsageDesktopKeyboard,\n\t\t\tHIDCollectionApplication,\n\t\t\tHIDReportID(2),\n\n\t\t\tHIDUsagePageKeyboard,\n\t\t\tHIDUsageMinimum(224),\n\t\t\tHIDUsageMaximum(231),\n\t\t\tHIDLogicalMinimum(0),\n\t\t\tHIDLogicalMaximum(1),\n\t\t\tHIDReportSize(1),\n\t\t\tHIDReportCount(8),\n\t\t\tHIDInputDataVarAbs,\n\t\t\tHIDReportCount(1),\n\t\t\tHIDReportSize(8),\n\t\t\tHIDInputConstVarAbs,\n\t\t\tHIDReportCount(3),\n\t\t\tHIDReportSize(1),\n\t\t\tHIDUsagePageLED,\n\t\t\tHIDUsageMinimum(1),\n\t\t\tHIDUsageMaximum(3),\n\t\t\tHIDOutputDataVarAbs,\n\t\t\tHIDReportCount(5),\n\t\t\tHIDReportSize(1),\n\t\t\tHIDOutputConstVarAbs,\n\t\t\tHIDReportCount(6),\n\t\t\tHIDReportSize(8),\n\t\t\tHIDLogicalMinimum(0),\n\t\t\tHIDLogicalMaximum(255),\n\n\t\t\tHIDUsagePageKeyboard,\n\t\t\tHIDUsageMinimum(0),\n\t\t\tHIDUsageMaximum(255),\n\t\t\tHIDInputDataAryAbs,\n\t\t\tHIDCollectionEnd,\n\n\t\t\tHIDUsagePageGenericDesktop,\n\t\t\tHIDUsageDesktopMouse,\n\t\t\tHIDCollectionApplication,\n\t\t\tHIDUsageDesktopPointer,\n\t\t\tHIDCollectionPhysical,\n\t\t\tHIDReportID(1),\n\n\t\t\tHIDUsagePageButton,\n\t\t\tHIDUsageMinimum(1),\n\t\t\tHIDUsageMaximum(5),\n\t\t\tHIDLogicalMinimum(0),\n\t\t\tHIDLogicalMaximum(1),\n\t\t\tHIDReportCount(5),\n\t\t\tHIDReportSize(1),\n\t\t\tHIDInputDataVarAbs,\n\t\t\tHIDReportCount(1),\n\t\t\tHIDReportSize(3),\n\t\t\tHIDInputConstVarAbs,\n\n\t\t\tHIDUsagePageGenericDesktop,\n\t\t\tHIDUsageDesktopX,\n\t\t\tHIDUsageDesktopY,\n\t\t\tHIDUsageDesktopWheel,\n\t\t\tHIDLogicalMinimum(-127),\n\t\t\tHIDLogicalMaximum(127),\n\t\t\tHIDReportSize(8),\n\t\t\tHIDReportCount(3),\n\t\t\tHIDInputDataVarRel,\n\t\t\tHIDCollectionEnd,\n\t\t\tHIDCollectionEnd,\n\n\t\t\tHIDUsagePageConsumer,\n\t\t\tHIDUsageConsumerControl,\n\t\t\tHIDCollectionApplication,\n\t\t\tHIDReportID(3),\n\t\t\tHIDLogicalMinimum(0),\n\t\t\tHIDLogicalMaximum(8191),\n\t\t\tHIDUsageMinimum(0),\n\t\t\tHIDUsageMaximum(0x1FFF),\n\t\t\tHIDReportSize(16),\n\t\t\tHIDReportCount(1),\n\t\t\tHIDInputDataAryAbs,\n\t\t\tHIDCollectionEnd,\n\t\t}),\n\t},\n}\n"
  },
  {
    "path": "src/machine/usb/descriptor/hidreport.go",
    "content": "package descriptor\n\nimport \"math\"\n\nconst (\n\thidUsagePage       = 0x04\n\thidUsage           = 0x08\n\thidLogicalMinimum  = 0x14\n\thidLogicalMaximum  = 0x24\n\thidUsageMinimum    = 0x18\n\thidUsageMaximum    = 0x28\n\thidPhysicalMinimum = 0x34\n\thidPhysicalMaximum = 0x44\n\thidUnitExponent    = 0x54\n\thidUnit            = 0x64\n\thidCollection      = 0xA0\n\thidInput           = 0x80\n\thidOutput          = 0x90\n\thidReportSize      = 0x74\n\thidReportCount     = 0x94\n\thidReportID        = 0x84\n)\n\nconst (\n\thidSizeValue0 = 0x00\n\thidSizeValue1 = 0x01\n\thidSizeValue2 = 0x02\n\thidSizeValue4 = 0x03\n)\n\nvar (\n\tHIDUsagePageGenericDesktop     = HIDUsagePage(0x01)\n\tHIDUsagePageSimulationControls = HIDUsagePage(0x02)\n\tHIDUsagePageVRControls         = HIDUsagePage(0x03)\n\tHIDUsagePageSportControls      = HIDUsagePage(0x04)\n\tHIDUsagePageGameControls       = HIDUsagePage(0x05)\n\tHIDUsagePageGenericControls    = HIDUsagePage(0x06)\n\tHIDUsagePageKeyboard           = HIDUsagePage(0x07)\n\tHIDUsagePageLED                = HIDUsagePage(0x08)\n\tHIDUsagePageButton             = HIDUsagePage(0x09)\n\tHIDUsagePageOrdinal            = HIDUsagePage(0x0A)\n\tHIDUsagePageTelephony          = HIDUsagePage(0x0B)\n\tHIDUsagePageConsumer           = HIDUsagePage(0x0C)\n\tHIDUsagePageDigitizers         = HIDUsagePage(0x0D)\n\tHIDUsagePageHaptics            = HIDUsagePage(0x0E)\n\tHIDUsagePagePhysicalInput      = HIDUsagePage(0x0F)\n\tHIDUsagePageUnicode            = HIDUsagePage(0x10)\n\tHIDUsagePageSoC                = HIDUsagePage(0x11)\n\tHIDUsagePageEyeHeadTrackers    = HIDUsagePage(0x12)\n\tHIDUsagePageAuxDisplay         = HIDUsagePage(0x14)\n\tHIDUsagePageSensors            = HIDUsagePage(0x20)\n\tHIDUsagePageMedicalInstrument  = HIDUsagePage(0x40)\n\tHIDUsagePageBrailleDisplay     = HIDUsagePage(0x41)\n\tHIDUsagePageLighting           = HIDUsagePage(0x59)\n\tHIDUsagePageMonitor            = HIDUsagePage(0x80)\n\tHIDUsagePageMonitorEnum        = HIDUsagePage(0x81)\n\tHIDUsagePageVESA               = HIDUsagePage(0x82)\n\tHIDUsagePagePower              = HIDUsagePage(0x84)\n\tHIDUsagePageBatterySystem      = HIDUsagePage(0x85)\n\tHIDUsagePageBarcodeScanner     = HIDUsagePage(0x8C)\n\tHIDUsagePageScales             = HIDUsagePage(0x8D)\n\tHIDUsagePageMagneticStripe     = HIDUsagePage(0x8E)\n\tHIDUsagePageCameraControl      = HIDUsagePage(0x90)\n\tHIDUsagePageArcade             = HIDUsagePage(0x91)\n\tHIDUsagePageGaming             = HIDUsagePage(0x92)\n)\n\nvar (\n\tHIDUsageDesktopPointer         = HIDUsage(0x01)\n\tHIDUsageDesktopMouse           = HIDUsage(0x02)\n\tHIDUsageDesktopJoystick        = HIDUsage(0x04)\n\tHIDUsageDesktopGamepad         = HIDUsage(0x05)\n\tHIDUsageDesktopKeyboard        = HIDUsage(0x06)\n\tHIDUsageDesktopKeypad          = HIDUsage(0x07)\n\tHIDUsageDesktopMultiaxis       = HIDUsage(0x08)\n\tHIDUsageDesktopTablet          = HIDUsage(0x09)\n\tHIDUsageDesktopWaterCooling    = HIDUsage(0x0A)\n\tHIDUsageDesktopChassis         = HIDUsage(0x0B)\n\tHIDUsageDesktopWireless        = HIDUsage(0x0C)\n\tHIDUsageDesktopPortable        = HIDUsage(0x0D)\n\tHIDUsageDesktopSystemMultiaxis = HIDUsage(0x0E)\n\tHIDUsageDesktopSpatial         = HIDUsage(0x0F)\n\tHIDUsageDesktopAssistive       = HIDUsage(0x10)\n\tHIDUsageDesktopDock            = HIDUsage(0x11)\n\tHIDUsageDesktopDockable        = HIDUsage(0x12)\n\tHIDUsageDesktopCallState       = HIDUsage(0x13)\n\tHIDUsageDesktopX               = HIDUsage(0x30)\n\tHIDUsageDesktopY               = HIDUsage(0x31)\n\tHIDUsageDesktopZ               = HIDUsage(0x32)\n\tHIDUsageDesktopRx              = HIDUsage(0x33)\n\tHIDUsageDesktopRy              = HIDUsage(0x34)\n\tHIDUsageDesktopRz              = HIDUsage(0x35)\n\tHIDUsageDesktopSlider          = HIDUsage(0x36)\n\tHIDUsageDesktopDial            = HIDUsage(0x37)\n\tHIDUsageDesktopWheel           = HIDUsage(0x38)\n\tHIDUsageDesktopHatSwitch       = HIDUsage(0x39)\n\tHIDUsageDesktopCountedBuffer   = HIDUsage(0x3A)\n)\n\nvar (\n\tHIDUsageConsumerControl             = HIDUsage(0x01)\n\tHIDUsageConsumerNumericKeypad       = HIDUsage(0x02)\n\tHIDUsageConsumerProgrammableButtons = HIDUsage(0x03)\n\tHIDUsageConsumerMicrophone          = HIDUsage(0x04)\n\tHIDUsageConsumerHeadphone           = HIDUsage(0x05)\n\tHIDUsageConsumerGraphicEqualizer    = HIDUsage(0x06)\n)\n\nvar (\n\tHIDCollectionPhysical    = HIDCollection(0x00)\n\tHIDCollectionApplication = HIDCollection(0x01)\n\tHIDCollectionEnd         = []byte{0xC0}\n)\n\nvar (\n\t// Input (Data,Ary,Abs), Key arrays (6 bytes)\n\tHIDInputDataAryAbs = HIDInput(0x00)\n\n\t// Input (Data, Variable, Absolute), Modifier byte\n\tHIDInputDataVarAbs = HIDInput(0x02)\n\n\t// Input (Const,Var,Abs), Modifier byte\n\tHIDInputConstVarAbs = HIDInput(0x03)\n\n\t// Input (Data, Variable, Relative), 2 position bytes (X & Y)\n\tHIDInputDataVarRel = HIDInput(0x06)\n\n\t// Output (Data, Variable, Absolute), Modifier byte\n\tHIDOutputDataVarAbs = HIDOutput(0x02)\n\n\t// Output (Const, Variable, Absolute), Modifier byte\n\tHIDOutputConstVarAbs = HIDOutput(0x03)\n)\n\nfunc hidShortItem(tag byte, value uint32) []byte {\n\tswitch {\n\tcase value <= math.MaxUint8:\n\t\treturn []byte{tag | hidSizeValue1, byte(value)}\n\tcase value <= math.MaxUint16:\n\t\treturn []byte{tag | hidSizeValue2, byte(value), byte(value >> 8)}\n\tdefault:\n\t\treturn []byte{tag | hidSizeValue4, byte(value), byte(value >> 8), byte(value >> 16), byte(value >> 24)}\n\t}\n}\n\nfunc hidShortItemSigned(tag byte, value int32) []byte {\n\tswitch {\n\tcase math.MinInt8 <= value && value <= math.MaxInt8:\n\t\treturn []byte{tag | hidSizeValue1, byte(value)}\n\tcase math.MinInt16 <= value && value <= math.MaxInt16:\n\t\treturn []byte{tag | hidSizeValue2, byte(value), byte(value >> 8)}\n\tdefault:\n\t\treturn []byte{tag | hidSizeValue4, byte(value), byte(value >> 8), byte(value >> 16), byte(value >> 24)}\n\t}\n}\n\nfunc HIDReportSize(size int) []byte {\n\treturn hidShortItem(hidReportSize, uint32(size))\n}\n\nfunc HIDReportCount(count int) []byte {\n\treturn hidShortItem(hidReportCount, uint32(count))\n}\n\nfunc HIDReportID(id int) []byte {\n\treturn hidShortItem(hidReportID, uint32(id))\n}\n\nfunc HIDLogicalMinimum(min int) []byte {\n\treturn hidShortItemSigned(hidLogicalMinimum, int32(min))\n}\n\nfunc HIDLogicalMaximum(max int) []byte {\n\treturn hidShortItemSigned(hidLogicalMaximum, int32(max))\n}\n\nfunc HIDUsageMinimum(min int) []byte {\n\treturn hidShortItem(hidUsageMinimum, uint32(min))\n}\n\nfunc HIDUsageMaximum(max int) []byte {\n\treturn hidShortItem(hidUsageMaximum, uint32(max))\n}\n\nfunc HIDPhysicalMinimum(min int) []byte {\n\treturn hidShortItemSigned(hidPhysicalMinimum, int32(min))\n}\n\nfunc HIDPhysicalMaximum(max int) []byte {\n\treturn hidShortItemSigned(hidPhysicalMaximum, int32(max))\n}\n\nfunc HIDUnitExponent(exp int) []byte {\n\t// 4 Bit two's complement\n\treturn hidShortItem(hidUnitExponent, uint32(exp&0xF))\n}\n\nfunc HIDUnit(unit uint32) []byte {\n\treturn hidShortItem(hidUnit, unit)\n}\n\nfunc HIDUsagePage(id uint16) []byte {\n\treturn hidShortItem(hidUsagePage, uint32(id))\n}\n\nfunc HIDUsage(id uint32) []byte {\n\treturn hidShortItem(hidUsage, id)\n}\n\nfunc HIDCollection(id uint32) []byte {\n\treturn hidShortItem(hidCollection, id)\n}\n\nfunc HIDInput(flags uint32) []byte {\n\treturn hidShortItem(hidInput, flags)\n}\n\nfunc HIDOutput(flags uint32) []byte {\n\treturn hidShortItem(hidOutput, flags)\n}\n"
  },
  {
    "path": "src/machine/usb/descriptor/interface.go",
    "content": "package descriptor\n\nconst (\n\tinterfaceTypeLen = 9\n)\n\ntype InterfaceType struct {\n\tdata []byte\n}\n\nfunc (d InterfaceType) Bytes() []byte {\n\treturn d.data\n}\n\nfunc (d InterfaceType) Length(v uint8) {\n\td.data[0] = byte(v)\n}\n\nfunc (d InterfaceType) Type(v uint8) {\n\td.data[1] = byte(v)\n}\n\nfunc (d InterfaceType) InterfaceNumber(v uint8) {\n\td.data[2] = byte(v)\n}\n\nfunc (d InterfaceType) AlternateSetting(v uint8) {\n\td.data[3] = byte(v)\n}\n\nfunc (d InterfaceType) NumEndpoints(v uint8) {\n\td.data[4] = byte(v)\n}\n\nfunc (d InterfaceType) InterfaceClass(v uint8) {\n\td.data[5] = byte(v)\n}\n\nfunc (d InterfaceType) InterfaceSubClass(v uint8) {\n\td.data[6] = byte(v)\n}\n\nfunc (d InterfaceType) InterfaceProtocol(v uint8) {\n\td.data[7] = byte(v)\n}\n\nfunc (d InterfaceType) Interface(v uint8) {\n\td.data[8] = byte(v)\n}\n"
  },
  {
    "path": "src/machine/usb/descriptor/interfaceassociation.go",
    "content": "package descriptor\n\nconst (\n\tinterfaceAssociationTypeLen = 8\n)\n\ntype InterfaceAssociationType struct {\n\tdata []byte\n}\n\nfunc (d InterfaceAssociationType) Bytes() []byte {\n\treturn d.data\n}\n\nfunc (d InterfaceAssociationType) Length(v uint8) {\n\td.data[0] = byte(v)\n}\n\nfunc (d InterfaceAssociationType) Type(v uint8) {\n\td.data[1] = byte(v)\n}\n\nfunc (d InterfaceAssociationType) FirstInterface(v uint8) {\n\td.data[2] = byte(v)\n}\n\nfunc (d InterfaceAssociationType) InterfaceCount(v uint8) {\n\td.data[3] = byte(v)\n}\n\nfunc (d InterfaceAssociationType) FunctionClass(v uint8) {\n\td.data[4] = byte(v)\n}\n\nfunc (d InterfaceAssociationType) FunctionSubClass(v uint8) {\n\td.data[5] = byte(v)\n}\n\nfunc (d InterfaceAssociationType) FunctionProtocol(v uint8) {\n\td.data[6] = byte(v)\n}\n\nfunc (d InterfaceAssociationType) Function(v uint8) {\n\td.data[7] = byte(v)\n}\n"
  },
  {
    "path": "src/machine/usb/descriptor/joystick.go",
    "content": "package descriptor\n\nvar deviceJoystick = [deviceTypeLen]byte{\n\tdeviceTypeLen,\n\tTypeDevice,\n\t0x00, 0x02, // USB version\n\t0xef,       // device class\n\t0x02,       // subclass\n\t0x01,       // protocol\n\t0x40,       // maxpacketsize\n\t0x41, 0x23, // vendor id\n\t0x36, 0x80, // product id\n\t0x00, 0x01, // device\n\t0x01, // manufacturer\n\t0x02, // product\n\t0x03, // SerialNumber\n\t0x01, // NumConfigurations\n}\n\nvar DeviceJoystick = DeviceType{\n\tdata: deviceJoystick[:],\n}\n\nvar configurationCDCJoystick = [configurationTypeLen]byte{\n\tconfigurationTypeLen,\n\tTypeConfiguration,\n\t0x6b, 0x00, // adjust length as needed\n\t0x03, // number of interfaces\n\t0x01, // configuration value\n\t0x00, // index to string description\n\t0xa0, // attributes\n\t0xfa, // maxpower\n}\n\nvar ConfigurationCDCJoystick = ConfigurationType{\n\tdata: configurationCDCJoystick[:],\n}\n\nvar interfaceHIDJoystick = [interfaceTypeLen]byte{\n\tinterfaceTypeLen,\n\tTypeInterface,\n\t0x02, // InterfaceNumber\n\t0x00, // AlternateSetting\n\t0x02, // NumEndpoints\n\t0x03, // InterfaceClass\n\t0x00, // InterfaceSubClass\n\t0x00, // InterfaceProtocol\n\t0x00, // Interface\n}\n\nvar InterfaceHIDJoystick = InterfaceType{\n\tdata: interfaceHIDJoystick[:],\n}\n\nvar classHIDJoystick = [ClassHIDTypeLen]byte{\n\tClassHIDTypeLen,\n\tTypeClassHID,\n\t0x11, // HID version L\n\t0x01, // HID version H\n\t0x00, // CountryCode\n\t0x01, // NumDescriptors\n\t0x22, // ClassType\n\t0x00, // ClassLength L\n\t0x00, // ClassLength H\n}\n\nvar ClassHIDJoystick = ClassHIDType{\n\tdata: classHIDJoystick[:],\n}\n\nvar JoystickDefaultHIDReport = Append([][]byte{\n\tHIDUsagePageGenericDesktop,\n\tHIDUsageDesktopJoystick,\n\tHIDCollectionApplication,\n\tHIDReportID(1),\n\tHIDUsagePageButton,\n\tHIDUsageMinimum(1),\n\tHIDUsageMaximum(16),\n\tHIDLogicalMinimum(0),\n\tHIDLogicalMaximum(1),\n\tHIDReportSize(1),\n\tHIDReportCount(16),\n\tHIDUnitExponent(0),\n\tHIDUnit(0),\n\tHIDInputDataVarAbs,\n\n\tHIDUsagePageGenericDesktop,\n\tHIDUsageDesktopHatSwitch,\n\tHIDLogicalMinimum(0),\n\tHIDLogicalMaximum(7),\n\tHIDPhysicalMinimum(0),\n\tHIDPhysicalMaximum(315),\n\tHIDUnit(0x14),\n\tHIDReportCount(1),\n\tHIDReportSize(4),\n\tHIDInputDataVarAbs,\n\tHIDUsageDesktopHatSwitch,\n\tHIDReportCount(1),\n\tHIDReportSize(4),\n\tHIDInputConstVarAbs,\n\tHIDUsageDesktopPointer,\n\tHIDLogicalMinimum(-32767),\n\tHIDLogicalMaximum(32767),\n\tHIDPhysicalMinimum(0),\n\tHIDPhysicalMaximum(0),\n\tHIDUnit(0),\n\tHIDReportCount(6),\n\tHIDReportSize(16),\n\tHIDCollectionPhysical,\n\tHIDUsageDesktopX,\n\tHIDUsageDesktopY,\n\tHIDUsageDesktopZ,\n\tHIDUsageDesktopRx,\n\tHIDUsageDesktopRy,\n\tHIDUsageDesktopRz,\n\tHIDInputDataVarAbs,\n\tHIDCollectionEnd,\n\tHIDCollectionEnd,\n})\n\n// CDCJoystick requires that you append the JoystickDescriptor\n// to the Configuration before using. This is in order to support\n// custom configurations.\nvar CDCJoystick = Descriptor{\n\tDevice: DeviceJoystick.Bytes(),\n\tConfiguration: Append([][]byte{\n\t\tConfigurationCDCJoystick.Bytes(),\n\t\tInterfaceAssociationCDC.Bytes(),\n\t\tInterfaceCDCControl.Bytes(),\n\t\tClassSpecificCDCHeader.Bytes(),\n\t\tClassSpecificCDCACM.Bytes(),\n\t\tClassSpecificCDCUnion.Bytes(),\n\t\tClassSpecificCDCCallManagement.Bytes(),\n\t\tEndpointEP1IN.Bytes(),\n\t\tInterfaceCDCData.Bytes(),\n\t\tEndpointEP2OUT.Bytes(),\n\t\tEndpointEP3IN.Bytes(),\n\t\tInterfaceHIDJoystick.Bytes(),\n\t\tClassHIDJoystick.Bytes(),\n\t\tEndpointEP4IN.Bytes(),\n\t\tEndpointEP5OUT.Bytes(),\n\t}),\n\tHID: map[uint16][]byte{},\n}\n"
  },
  {
    "path": "src/machine/usb/descriptor/midi.go",
    "content": "package descriptor\n\nvar interfaceAssociationMIDI = [interfaceAssociationTypeLen]byte{\n\tinterfaceAssociationTypeLen,\n\tTypeInterfaceAssociation,\n\t0x02, // EndpointAddress\n\t0x02, // Attributes\n\t0x01, // MaxPacketSizeL\n\t0x01, // MaxPacketSizeH\n\t0x00, // Interval\n\t0x00, // Interval\n}\n\nvar InterfaceAssociationMIDI = InterfaceAssociationType{\n\tdata: interfaceAssociationMIDI[:],\n}\n\nvar interfaceAudio = [interfaceTypeLen]byte{\n\tinterfaceTypeLen,\n\tTypeInterface,\n\t0x02, // InterfaceNumber\n\t0x00, // AlternateSetting\n\t0x00, // NumEndpoints\n\t0x01, // InterfaceClass\n\t0x01, // InterfaceSubClass\n\t0x00, // InterfaceProtocol\n\t0x00, // Interface\n}\n\nvar InterfaceAudio = InterfaceType{\n\tdata: interfaceAudio[:],\n}\n\nvar interfaceMIDIStreaming = [interfaceTypeLen]byte{\n\tinterfaceTypeLen,\n\tTypeInterface,\n\t0x03, // InterfaceNumber\n\t0x00, // AlternateSetting\n\t0x02, // NumEndpoints\n\t0x01, // InterfaceClass\n\t0x03, // InterfaceSubClass\n\t0x00, // InterfaceProtocol\n\t0x00, // Interface\n}\n\nvar InterfaceMIDIStreaming = InterfaceType{\n\tdata: interfaceMIDIStreaming[:],\n}\n\nconst classSpecificAudioTypeLen = 9\n\nvar classSpecificAudioInterface = [classSpecificAudioTypeLen]byte{\n\tclassSpecificAudioTypeLen,\n\tTypeClassSpecific,\n\t0x01,\n\t0x00, //\n\t0x01, //\n\t0x09,\n\t0x00,\n\t0x01,\n\t0x03,\n}\n\nvar ClassSpecificAudioInterface = ClassSpecificType{\n\tdata: classSpecificAudioInterface[:],\n}\n\nconst classSpecificMIDIHeaderLen = 7\n\nvar classSpecificMIDIHeader = [classSpecificMIDIHeaderLen]byte{\n\tclassSpecificMIDIHeaderLen,\n\tTypeClassSpecific,\n\t0x01,\n\t0x00, //\n\t0x01, //\n\t0x41,\n\t0x00,\n}\n\nvar ClassSpecificMIDIHeader = ClassSpecificType{\n\tdata: classSpecificMIDIHeader[:],\n}\n\nconst classSpecificMIDIInJackLen = 6\n\nvar classSpecificMIDIInJack1 = [classSpecificMIDIInJackLen]byte{\n\tclassSpecificMIDIInJackLen,\n\tTypeClassSpecific,\n\t0x02, // MIDI In jack\n\t0x01, // Jack type (embedded)\n\t0x01, // Jack ID\n\t0x00, // iJack\n}\n\nvar ClassSpecificMIDIInJack1 = ClassSpecificType{\n\tdata: classSpecificMIDIInJack1[:],\n}\n\nvar classSpecificMIDIInJack2 = [classSpecificMIDIInJackLen]byte{\n\tclassSpecificMIDIInJackLen,\n\tTypeClassSpecific,\n\t0x02, // MIDI In jack\n\t0x02, // Jack type (external)\n\t0x02, // Jack ID\n\t0x00, // iJack\n}\n\nvar ClassSpecificMIDIInJack2 = ClassSpecificType{\n\tdata: classSpecificMIDIInJack2[:],\n}\n\nconst classSpecificMIDIOutJackLen = 9\n\nvar classSpecificMIDIOutJack1 = [classSpecificMIDIOutJackLen]byte{\n\tclassSpecificMIDIOutJackLen,\n\tTypeClassSpecific,\n\t0x03, // MIDI Out jack\n\t0x01, // Jack type (embedded)\n\t0x03, // Jack ID\n\t0x01, // number of input pins\n\t0x02, // source ID\n\t0x01, // source pin\n\t0x00, // iJack\n}\n\nvar ClassSpecificMIDIOutJack1 = ClassSpecificType{\n\tdata: classSpecificMIDIOutJack1[:],\n}\n\nvar classSpecificMIDIOutJack2 = [classSpecificMIDIOutJackLen]byte{\n\tclassSpecificMIDIOutJackLen,\n\tTypeClassSpecific,\n\t0x03, // MIDI Out jack\n\t0x02, // Jack type (external)\n\t0x04, // Jack ID\n\t0x01, // number of input pins\n\t0x01, // source ID\n\t0x01, // source pin\n\t0x00, // iJack\n}\n\nvar ClassSpecificMIDIOutJack2 = ClassSpecificType{\n\tdata: classSpecificMIDIOutJack2[:],\n}\n\nconst classSpecificMIDIEndpointLen = 5\n\nvar classSpecificMIDIOutEndpoint = [classSpecificMIDIEndpointLen]byte{\n\tclassSpecificMIDIEndpointLen,\n\tTypeClassSpecificEndpoint,\n\t0x01, // CS endpoint\n\t0x01, // number MIDI IN jacks\n\t0x01, // assoc Jack ID\n}\n\nvar ClassSpecificMIDIOutEndpoint = ClassSpecificType{\n\tdata: classSpecificMIDIOutEndpoint[:],\n}\n\nvar classSpecificMIDIInEndpoint = [classSpecificMIDIEndpointLen]byte{\n\tclassSpecificMIDIEndpointLen,\n\tTypeClassSpecificEndpoint,\n\t0x01, // CS endpoint\n\t0x01, // number MIDI Out jacks\n\t0x03, // assoc Jack ID\n}\n\nvar ClassSpecificMIDIInEndpoint = ClassSpecificType{\n\tdata: classSpecificMIDIInEndpoint[:],\n}\n\nconst endpointMIDITypeLen = 9\n\nvar endpointEP6IN = [endpointMIDITypeLen]byte{\n\tendpointMIDITypeLen,\n\tTypeEndpoint,\n\t0x86, // EndpointAddress\n\t0x02, // Attributes\n\t0x40, // MaxPacketSizeL\n\t0x00, // MaxPacketSizeH\n\t0x00, // Interval\n\t0x00, // refresh\n\t0x00, // sync address\n}\n\nvar EndpointEP6IN = EndpointType{\n\tdata: endpointEP6IN[:],\n}\n\nvar endpointEP7OUT = [endpointMIDITypeLen]byte{\n\tendpointMIDITypeLen,\n\tTypeEndpoint,\n\t0x07, // EndpointAddress\n\t0x02, // Attributes\n\t0x40, // MaxPacketSizeL\n\t0x00, // MaxPacketSizeH\n\t0x00, // Interval\n\t0x00, // refresh\n\t0x00, // sync address\n}\n\nvar EndpointEP7OUT = EndpointType{\n\tdata: endpointEP7OUT[:],\n}\n\nvar configurationCDCMIDI = [configurationTypeLen]byte{\n\tconfigurationTypeLen,\n\tTypeConfiguration,\n\t0xaf, 0x00, // adjust length as needed\n\t0x04, // number of interfaces\n\t0x01, // configuration value\n\t0x00, // index to string description\n\t0xa0, // attributes\n\t0x32, // maxpower\n}\n\nvar ConfigurationCDCMIDI = ConfigurationType{\n\tdata: configurationCDCMIDI[:],\n}\n\nvar CDCMIDI = Descriptor{\n\tDevice: DeviceCDC.Bytes(),\n\tConfiguration: Append([][]byte{\n\t\tConfigurationCDCMIDI.Bytes(),\n\t\tInterfaceAssociationCDC.Bytes(),\n\t\tInterfaceCDCControl.Bytes(),\n\t\tClassSpecificCDCHeader.Bytes(),\n\t\tClassSpecificCDCACM.Bytes(),\n\t\tClassSpecificCDCUnion.Bytes(),\n\t\tClassSpecificCDCCallManagement.Bytes(),\n\t\tEndpointEP1IN.Bytes(),\n\t\tInterfaceCDCData.Bytes(),\n\t\tEndpointEP2OUT.Bytes(),\n\t\tEndpointEP3IN.Bytes(),\n\t\tInterfaceAssociationMIDI.Bytes(),\n\t\tInterfaceAudio.Bytes(),\n\t\tClassSpecificAudioInterface.Bytes(),\n\t\tInterfaceMIDIStreaming.Bytes(),\n\t\tClassSpecificMIDIHeader.Bytes(),\n\t\tClassSpecificMIDIInJack1.Bytes(),\n\t\tClassSpecificMIDIInJack2.Bytes(),\n\t\tClassSpecificMIDIOutJack1.Bytes(),\n\t\tClassSpecificMIDIOutJack2.Bytes(),\n\t\tEndpointEP7OUT.Bytes(),\n\t\tClassSpecificMIDIOutEndpoint.Bytes(),\n\t\tEndpointEP6IN.Bytes(),\n\t\tClassSpecificMIDIInEndpoint.Bytes(),\n\t}),\n}\n"
  },
  {
    "path": "src/machine/usb/descriptor/msc.go",
    "content": "package descriptor\n\nconst (\n\tinterfaceClassMSC = 0x08\n\tmscSubclassSCSI   = 0x06\n\tmscProtocolBOT    = 0x50\n)\n\nvar interfaceAssociationMSC = [interfaceAssociationTypeLen]byte{\n\tinterfaceAssociationTypeLen,\n\tTypeInterfaceAssociation,\n\t0x02,              // FirstInterface\n\t0x01,              // InterfaceCount\n\tinterfaceClassMSC, // FunctionClass\n\tmscSubclassSCSI,   // FunctionSubClass\n\tmscProtocolBOT,    // FunctionProtocol\n\t0x00,              // Function\n}\n\nvar InterfaceAssociationMSC = InterfaceAssociationType{\n\tdata: interfaceAssociationMSC[:],\n}\n\nvar interfaceMSC = [interfaceTypeLen]byte{\n\tinterfaceTypeLen,  // Length\n\tTypeInterface,     // DescriptorType\n\t0x02,              // InterfaceNumber\n\t0x00,              // AlternateSetting\n\t0x02,              // NumEndpoints\n\tinterfaceClassMSC, // InterfaceClass (Mass Storage)\n\tmscSubclassSCSI,   // InterfaceSubClass (SCSI Transparent)\n\tmscProtocolBOT,    // InterfaceProtocol (Bulk-Only Transport)\n\t0x00,              // Interface\n}\n\nvar InterfaceMSC = InterfaceType{\n\tdata: interfaceMSC[:],\n}\n\nvar configurationMSC = [configurationTypeLen]byte{\n\tconfigurationTypeLen,\n\tTypeConfiguration,\n\t0x6a, 0x00, // wTotalLength\n\t0x03, // number of interfaces (bNumInterfaces)\n\t0x01, // configuration value (bConfigurationValue)\n\t0x00, // index to string description (iConfiguration)\n\t0xa0, // attributes (bmAttributes)\n\t0x32, // maxpower (100 mA) (bMaxPower)\n}\n\nvar ConfigurationMSC = ConfigurationType{\n\tdata: configurationMSC[:],\n}\n\n// Mass Storage Class\nvar MSC = Descriptor{\n\tDevice: DeviceCDC.Bytes(),\n\tConfiguration: Append([][]byte{\n\t\tConfigurationMSC.Bytes(),\n\t\tInterfaceAssociationCDC.Bytes(),\n\t\tInterfaceCDCControl.Bytes(),\n\t\tClassSpecificCDCHeader.Bytes(),\n\t\tClassSpecificCDCACM.Bytes(),\n\t\tClassSpecificCDCUnion.Bytes(),\n\t\tClassSpecificCDCCallManagement.Bytes(),\n\t\tEndpointEP1IN.Bytes(),\n\t\tInterfaceCDCData.Bytes(),\n\t\tEndpointEP2OUT.Bytes(),\n\t\tEndpointEP3IN.Bytes(),\n\t\tInterfaceAssociationMSC.Bytes(),\n\t\tInterfaceMSC.Bytes(),\n\t\tEndpointMSCIN.Bytes(),\n\t\tEndpointMSCOUT.Bytes(),\n\t}),\n}\n"
  },
  {
    "path": "src/machine/usb/doc.go",
    "content": "// package usb contains the subpackages with USB descriptors and device\n// implementations for standard USB device classes such as the Communcation\n// Data Class (CDC), Human Interface Device (HID), and Audio Device Class (ADC).\npackage usb\n"
  },
  {
    "path": "src/machine/usb/hid/buffer.go",
    "content": "package hid\n\nimport (\n\t\"runtime/volatile\"\n)\n\nconst bufferSize = 128\n\n// RingBuffer is ring buffer implementation inspired by post at\n// https://www.embeddedrelated.com/showthread/comp.arch.embedded/77084-1.php\ntype RingBuffer struct {\n\trxbuffer [bufferSize][9]byte\n\thead     volatile.Register8\n\ttail     volatile.Register8\n}\n\n// NewRingBuffer returns a new ring buffer.\nfunc NewRingBuffer() *RingBuffer {\n\treturn &RingBuffer{}\n}\n\n// Used returns how many bytes in buffer have been used.\nfunc (rb *RingBuffer) Used() uint8 {\n\treturn uint8(rb.head.Get() - rb.tail.Get())\n}\n\n// Put stores a byte in the buffer. If the buffer is already\n// full, the method will return false.\nfunc (rb *RingBuffer) Put(val []byte) bool {\n\tif rb.Used() != bufferSize {\n\t\trb.head.Set(rb.head.Get() + 1)\n\t\tcopy(rb.rxbuffer[rb.head.Get()%bufferSize][:], val)\n\t\treturn true\n\t}\n\treturn false\n}\n\n// Get returns a byte from the buffer. If the buffer is empty,\n// the method will return a false as the second value.\nfunc (rb *RingBuffer) Get() ([]byte, bool) {\n\tif rb.Used() != 0 {\n\t\trb.tail.Set(rb.tail.Get() + 1)\n\t\treturn rb.rxbuffer[rb.tail.Get()%bufferSize][:], true\n\t}\n\treturn nil, false\n}\n\n// Clear resets the head and tail pointer to zero.\nfunc (rb *RingBuffer) Clear() {\n\trb.head.Set(0)\n\trb.tail.Set(0)\n}\n"
  },
  {
    "path": "src/machine/usb/hid/doc.go",
    "content": "// package hid is for USB Human Interface Devices.\npackage hid\n"
  },
  {
    "path": "src/machine/usb/hid/hid.go",
    "content": "package hid\n\nimport (\n\t\"errors\"\n\t\"machine\"\n\t\"machine/usb\"\n\t\"machine/usb/descriptor\"\n)\n\n// from usb-hid.go\nvar (\n\tErrHIDInvalidPort    = errors.New(\"invalid USB port\")\n\tErrHIDInvalidCore    = errors.New(\"invalid USB core\")\n\tErrHIDReportTransfer = errors.New(\"failed to transfer HID report\")\n)\n\nconst (\n\thidEndpoint = usb.HID_ENDPOINT_IN\n\n\tREPORT_TYPE_INPUT   = 1\n\tREPORT_TYPE_OUTPUT  = 2\n\tREPORT_TYPE_FEATURE = 3\n)\n\ntype hidDevicer interface {\n\tTxHandler() bool\n\tRxHandler([]byte) bool\n}\n\nvar devices [5]hidDevicer\nvar size int\n\n// SetHandler sets the handler. Only the first time it is called, it\n// calls machine.EnableHID for USB configuration\nfunc SetHandler(d hidDevicer) {\n\tif size == 0 {\n\t\tmachine.ConfigureUSBEndpoint(descriptor.CDCHID,\n\t\t\t[]usb.EndpointConfig{\n\t\t\t\t{\n\t\t\t\t\tIndex:     usb.HID_ENDPOINT_OUT,\n\t\t\t\t\tIsIn:      false,\n\t\t\t\t\tType:      usb.ENDPOINT_TYPE_INTERRUPT,\n\t\t\t\t\tRxHandler: rxHandler,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tIndex:     usb.HID_ENDPOINT_IN,\n\t\t\t\t\tIsIn:      true,\n\t\t\t\t\tType:      usb.ENDPOINT_TYPE_INTERRUPT,\n\t\t\t\t\tTxHandler: txHandler,\n\t\t\t\t},\n\t\t\t},\n\t\t\t[]usb.SetupConfig{\n\t\t\t\t{\n\t\t\t\t\tIndex:   usb.HID_INTERFACE,\n\t\t\t\t\tHandler: setupHandler,\n\t\t\t\t},\n\t\t\t})\n\t}\n\n\tdevices[size] = d\n\tsize++\n}\n\nfunc txHandler() {\n\tfor _, d := range devices {\n\t\tif d == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif done := d.TxHandler(); done {\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc rxHandler(b []byte) {\n\tfor _, d := range devices {\n\t\tif d == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif done := d.RxHandler(b); done {\n\t\t\treturn\n\t\t}\n\t}\n}\n\nvar DefaultSetupHandler = setupHandler\n\nfunc setupHandler(setup usb.Setup) bool {\n\tok := false\n\tif setup.BmRequestType == usb.SET_REPORT_TYPE && setup.BRequest == usb.SET_IDLE {\n\t\tmachine.SendZlp()\n\t\tok = true\n\t}\n\treturn ok\n}\n\n// SendUSBPacket sends a HIDPacket.\nfunc SendUSBPacket(b []byte) {\n\tmachine.SendUSBInPacket(hidEndpoint, b)\n}\n"
  },
  {
    "path": "src/machine/usb/hid/joystick/joystick.go",
    "content": "package joystick\n\nimport (\n\t\"machine\"\n\t\"machine/usb\"\n\t\"machine/usb/descriptor\"\n\t\"machine/usb/hid\"\n)\n\nvar Joystick *joystick\n\ntype joystick struct {\n\tState\n\tbuf           *hid.RingBuffer\n\twaitTxc       bool\n\trxHandlerFunc func(b []byte)\n\tsetupFunc     func(setup usb.Setup) bool\n}\n\nfunc init() {\n\tif Joystick == nil {\n\t\tJoystick = newDefaultJoystick()\n\t}\n}\n\n// UseSettings overrides the Joystick settings. This function must be\n// called from init().\nfunc UseSettings(def Definitions, rxHandlerFunc func(b []byte), setupFunc func(setup usb.Setup) bool, hidDesc []byte) *joystick {\n\tjs := &joystick{\n\t\tbuf:   hid.NewRingBuffer(),\n\t\tState: def.NewState(),\n\t}\n\tif setupFunc == nil {\n\t\tsetupFunc = hid.DefaultSetupHandler\n\t}\n\tif rxHandlerFunc == nil {\n\t\trxHandlerFunc = js.rxHandlerFunc\n\t}\n\tif len(hidDesc) == 0 {\n\t\thidDesc = descriptor.JoystickDefaultHIDReport\n\t}\n\tclass, err := descriptor.FindClassHIDType(descriptor.CDCJoystick.Configuration, descriptor.ClassHIDJoystick.Bytes())\n\tif err != nil {\n\t\t// TODO: some way to notify about error\n\t\treturn nil\n\t}\n\n\tclass.ClassLength(uint16(len(hidDesc)))\n\tdescriptor.CDCJoystick.HID[2] = hidDesc\n\n\tmachine.ConfigureUSBEndpoint(descriptor.CDCJoystick,\n\t\t[]usb.EndpointConfig{\n\t\t\t{\n\t\t\t\tIndex:     usb.HID_ENDPOINT_OUT,\n\t\t\t\tIsIn:      false,\n\t\t\t\tType:      usb.ENDPOINT_TYPE_INTERRUPT,\n\t\t\t\tRxHandler: rxHandlerFunc,\n\t\t\t},\n\t\t\t{\n\t\t\t\tIndex:     usb.HID_ENDPOINT_IN,\n\t\t\t\tIsIn:      true,\n\t\t\t\tType:      usb.ENDPOINT_TYPE_INTERRUPT,\n\t\t\t\tTxHandler: js.handler,\n\t\t\t},\n\t\t},\n\t\t[]usb.SetupConfig{\n\t\t\t{\n\t\t\t\tIndex:   usb.HID_INTERFACE,\n\t\t\t\tHandler: setupFunc,\n\t\t\t},\n\t\t},\n\t)\n\tJoystick = js\n\treturn js\n}\n\nfunc newDefaultJoystick() *joystick {\n\tdef := DefaultDefinitions()\n\tjs := UseSettings(def, nil, nil, nil)\n\treturn js\n}\n\n// Port returns the USB Joystick port.\nfunc Port() *joystick {\n\treturn Joystick\n}\n\nfunc (m *joystick) handler() {\n\tm.waitTxc = false\n\tif b, ok := m.buf.Get(); ok {\n\t\tm.waitTxc = true\n\t\thid.SendUSBPacket(b)\n\t}\n}\n\nfunc (m *joystick) tx(b []byte) {\n\tif machine.USBDev.InitEndpointComplete {\n\t\tif m.waitTxc {\n\t\t\tm.buf.Put(b)\n\t\t} else {\n\t\t\tm.waitTxc = true\n\t\t\thid.SendUSBPacket(b)\n\t\t}\n\t}\n}\n\nfunc (m *joystick) ready() bool {\n\treturn true\n}\n\nfunc (m *joystick) rxHandler(b []byte) {\n\tif m.rxHandlerFunc != nil {\n\t\tm.rxHandlerFunc(b)\n\t}\n}\n\n// to InterruptOut\nfunc (m *joystick) SendReport(reportID byte, b []byte) {\n\tm.tx(append([]byte{reportID}, b...))\n}\n\nfunc (m *joystick) SendState() {\n\tb, _ := m.State.MarshalBinary()\n\tm.tx(b)\n}\n"
  },
  {
    "path": "src/machine/usb/hid/joystick/state.go",
    "content": "package joystick\n\nimport (\n\t\"machine/usb/descriptor\"\n\n\t\"encoding/binary\"\n)\n\ntype HatDirection uint8\n\nconst (\n\tHatUp HatDirection = iota\n\tHatRightUp\n\tHatRight\n\tHatRightDown\n\tHatDown\n\tHatLeftDown\n\tHatLeft\n\tHatLeftUp\n\tHatCenter\n)\n\ntype Constraint struct {\n\tMinIn  int\n\tMaxIn  int\n\tMinOut int16\n\tMaxOut int16\n}\n\ntype AxisValue struct {\n\tconstraint Constraint\n\tValue      int\n}\n\nfunc fit(x, in_min, in_max int, out_min, out_max int16) int16 {\n\treturn int16((x-in_min)*(int(out_max)-int(out_min))/(in_max-in_min) + int(out_min))\n}\n\nfunc fitf(x, in_min, in_max, out_min, out_max float32) float32 {\n\treturn x - in_min*(out_max-out_min)/(in_max-in_min) + out_min\n}\n\nfunc limit(v, max int) int {\n\tif v > max {\n\t\tv = max\n\t} else if v < -max {\n\t\tv = -max\n\t}\n\treturn v\n}\n\ntype Definitions struct {\n\tReportID     byte\n\tButtonCnt    int\n\tHatSwitchCnt int\n\tAxisDefs     []Constraint\n\tdescriptor   []byte\n}\n\nfunc (c Definitions) Descriptor() []byte {\n\tif len(c.descriptor) > 0 {\n\t\treturn c.descriptor\n\t}\n\t// TODO: build hid descriptor\n\treturn nil\n}\n\nfunc (c Definitions) NewState() State {\n\tbufSize := 1\n\thatSwitches := make([]HatDirection, c.HatSwitchCnt)\n\tfor i := range hatSwitches {\n\t\thatSwitches[i] = HatCenter\n\t}\n\taxises := make([]*AxisValue, 0, len(c.AxisDefs))\n\tfor _, v := range c.AxisDefs {\n\n\t\taxises = append(axises, &AxisValue{\n\t\t\tconstraint: v,\n\t\t\tValue:      0,\n\t\t})\n\t}\n\tbtnSize := (c.ButtonCnt + 7) / 8\n\tbufSize += btnSize\n\tbufSize += (len(hatSwitches) + 1) / 2\n\tbufSize += len(axises) * 2\n\tinitBuf := make([]byte, bufSize)\n\tinitBuf[0] = c.ReportID\n\treturn State{\n\t\tbuf:         initBuf,\n\t\tButtons:     make([]byte, btnSize),\n\t\tHatSwitches: hatSwitches,\n\t\tAxises:      axises,\n\t}\n}\n\ntype State struct {\n\tbuf         []byte\n\tButtons     []byte\n\tHatSwitches []HatDirection\n\tAxises      []*AxisValue\n}\n\nfunc (s State) MarshalBinary() ([]byte, error) {\n\ts.buf = s.buf[0:1]\n\ts.buf = append(s.buf, s.Buttons...)\n\tif len(s.HatSwitches) > 0 {\n\t\that := byte(0)\n\t\tfor i, v := range s.HatSwitches {\n\t\t\tif i != 0 && i%2 == 0 {\n\t\t\t\ts.buf = append(s.buf, hat)\n\t\t\t\that = 0\n\t\t\t}\n\t\t\that <<= 4\n\t\t\that |= byte(v & 0xf)\n\t\t}\n\t\ts.buf = append(s.buf, hat)\n\t}\n\tfor _, v := range s.Axises {\n\t\tc := v.constraint\n\t\tval := fit(v.Value, c.MinIn, c.MaxIn, c.MinOut, c.MaxOut)\n\t\ts.buf = binary.LittleEndian.AppendUint16(s.buf, uint16(val))\n\t}\n\treturn s.buf, nil\n}\n\nfunc (s State) Button(index int) bool {\n\tidx := index / 8\n\tbit := uint8(1 << (index % 8))\n\treturn s.Buttons[idx]&bit > 0\n}\n\nfunc (s State) SetButton(index int, push bool) {\n\tidx := index / 8\n\tbit := uint8(1 << (index % 8))\n\tb := s.Buttons[idx]\n\tb &= ^bit\n\tif push {\n\t\tb |= bit\n\t}\n\ts.Buttons[idx] = b\n}\n\nfunc (s State) Hat(index int) HatDirection {\n\treturn s.HatSwitches[index]\n}\n\nfunc (s State) SetHat(index int, dir HatDirection) {\n\ts.HatSwitches[index] = dir\n}\n\nfunc (s State) Axis(index int) int {\n\treturn s.Axises[index].Value\n}\n\nfunc (s State) SetAxis(index int, v int) {\n\ts.Axises[index].Value = v\n}\n\nfunc DefaultDefinitions() Definitions {\n\treturn Definitions{\n\t\tReportID:     1,\n\t\tButtonCnt:    16,\n\t\tHatSwitchCnt: 1,\n\t\tAxisDefs: []Constraint{\n\t\t\t{MinIn: -32767, MaxIn: 32767, MinOut: -32767, MaxOut: 32767},\n\t\t\t{MinIn: -32767, MaxIn: 32767, MinOut: -32767, MaxOut: 32767},\n\t\t\t{MinIn: -32767, MaxIn: 32767, MinOut: -32767, MaxOut: 32767},\n\t\t\t{MinIn: -32767, MaxIn: 32767, MinOut: -32767, MaxOut: 32767},\n\t\t\t{MinIn: -32767, MaxIn: 32767, MinOut: -32767, MaxOut: 32767},\n\t\t\t{MinIn: -32767, MaxIn: 32767, MinOut: -32767, MaxOut: 32767},\n\t\t},\n\t\tdescriptor: descriptor.JoystickDefaultHIDReport,\n\t}\n}\n"
  },
  {
    "path": "src/machine/usb/hid/keyboard/keyboard.go",
    "content": "package keyboard\n\nimport (\n\t\"errors\"\n\t\"machine\"\n\t\"machine/usb/hid\"\n)\n\n// from usb-hid-keyboard.go\nvar (\n\tErrInvalidCodepoint = errors.New(\"invalid Unicode codepoint\")\n\tErrInvalidKeycode   = errors.New(\"invalid keyboard keycode\")\n\tErrInvalidUTF8      = errors.New(\"invalid UTF-8 encoding\")\n\tErrKeypressMaximum  = errors.New(\"maximum keypresses exceeded\")\n)\n\nvar Keyboard *keyboard\n\n// Keyboard represents a USB HID keyboard device with support for international\n// layouts and various control, system, multimedia, and consumer keycodes.\n//\n// Keyboard implements the io.Writer interface that translates UTF-8 encoded\n// byte strings into sequences of keypress events.\ntype keyboard struct {\n\t// led holds the current state of all keyboard LEDs:\n\t//   1=NumLock  2=CapsLock  4=ScrollLock  8=Compose  16=Kana\n\tled uint8\n\n\t// mod holds the current state of all keyboard modifier keys:\n\t//    1=LeftCtrl    2=LeftShift    4=LeftAlt     8=LeftGUI\n\t//   16=RightCtrl  32=RightShift  64=RightAlt  128=RightGUI\n\tmod uint8\n\n\t// key holds a list of all keyboard keys currently pressed.\n\tkey [hidKeyboardKeyCount]uint8\n\tcon [hidKeyboardConCount]uint16\n\tsys [hidKeyboardSysCount]uint8\n\n\t// decode holds the current state of the UTF-8 decoder.\n\tdecode decodeState\n\n\t// wideChar holds high bits for the UTF-8 decoder.\n\twideChar uint16\n\n\tbuf     *hid.RingBuffer\n\twaitTxc bool\n}\n\n// decodeState represents a state in the UTF-8 decode state machine.\ntype decodeState uint8\n\n// Constant enumerated values of type decodeState.\nconst (\n\tdecodeReset decodeState = iota\n\tdecodeByte1\n\tdecodeByte2\n\tdecodeByte3\n)\n\nfunc init() {\n\tif Keyboard == nil {\n\t\tKeyboard = newKeyboard()\n\t\thid.SetHandler(Keyboard)\n\t}\n}\n\n// New returns the USB hid-keyboard port.\n// Deprecated, better to just use Port()\nfunc New() *keyboard {\n\treturn Port()\n}\n\n// Port returns the USB hid-keyboard port.\nfunc Port() *keyboard {\n\treturn Keyboard\n}\n\nfunc newKeyboard() *keyboard {\n\treturn &keyboard{\n\t\tbuf: hid.NewRingBuffer(),\n\t}\n}\n\nfunc (kb *keyboard) TxHandler() bool {\n\tkb.waitTxc = false\n\tif b, ok := kb.buf.Get(); ok {\n\t\tkb.waitTxc = true\n\t\thid.SendUSBPacket(b)\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunc (kb *keyboard) RxHandler(b []byte) bool {\n\tif len(b) >= 2 && b[0] == 2 /* ReportID */ {\n\t\tkb.led = b[1]\n\t}\n\treturn false\n}\n\nfunc (kb *keyboard) tx(b []byte) {\n\tif machine.USBDev.InitEndpointComplete {\n\t\tif kb.waitTxc {\n\t\t\tkb.buf.Put(b)\n\t\t} else {\n\t\t\tkb.waitTxc = true\n\t\t\thid.SendUSBPacket(b)\n\t\t}\n\t}\n}\n\nfunc (kb *keyboard) NumLockLed() bool {\n\treturn kb.led&1 != 0\n}\n\nfunc (kb *keyboard) CapsLockLed() bool {\n\treturn kb.led&2 != 0\n}\n\nfunc (kb *keyboard) ScrollLockLed() bool {\n\treturn kb.led&4 != 0\n}\n\nfunc (kb *keyboard) ready() bool {\n\treturn true\n}\n\n// Write transmits press-and-release key sequences for each Keycode translated\n// from the given UTF-8 byte string. Write implements the io.Writer interface\n// and conforms to all documented conventions for arguments and return values.\nfunc (kb *keyboard) Write(b []byte) (n int, err error) {\n\tfor _, c := range b {\n\t\tif err = kb.WriteByte(c); nil != err {\n\t\t\tbreak\n\t\t}\n\t\tn += 1\n\t}\n\treturn\n}\n\n// WriteByte processes a single byte from a UTF-8 byte string. This method is a\n// stateful method with respect to the receiver Keyboard, meaning that its exact\n// behavior will depend on the current state of its UTF-8 decode state machine:\n//\n//  1. If the given byte is a valid ASCII encoding (0-127), then a keypress\n//     sequence is immediately transmitted for the respective Keycode.\n//  2. If the given byte represents the final byte in a multi-byte codepoint,\n//     then a keypress sequence is immediately transmitted by translating the\n//     multi-byte codepoint to its respective Keycode.\n//  3. If the given byte appears to represent high bits for a multi-byte\n//     codepoint, then the bits are copied to the receiver's internal state\n//     machine buffer for use by a subsequent call to WriteByte() (or Write())\n//     that completes the codepoint.\n//  4. If the given byte is out of range, or contains illegal bits for the\n//     current state of the UTF-8 decoder, then the UTF-8 decode state machine\n//     is reset to its initial state.\n//\n// In cases 3 and 4, a keypress sequence is not generated and no data is\n// transmitted. In case 3, additional bytes must be received via WriteByte()\n// (or Write()) to complete or discard the current codepoint.\nfunc (kb *keyboard) WriteByte(b byte) error {\n\tswitch {\n\tcase b < 0x80:\n\t\t// 1-byte encoding (0x00-0x7F)\n\t\tkb.decode = decodeByte1\n\t\treturn kb.write(uint16(b))\n\n\tcase b < 0xC0:\n\t\t// 2nd, 3rd, or 4th byte (0x80-0xBF)\n\t\tb = Keycode(b).key()\n\t\tswitch kb.decode {\n\t\tcase decodeByte2:\n\t\t\tkb.decode = decodeByte1\n\t\t\treturn kb.write(kb.wideChar | uint16(b))\n\t\tcase decodeByte3:\n\t\t\tkb.decode = decodeByte2\n\t\t\tkb.wideChar |= uint16(b) << 6\n\t\t}\n\n\tcase b < 0xE0:\n\t\t// 2-byte encoding (0xC2-0xDF), or illegal byte 2 (0xC0-0xC1)\n\t\tkb.decode = decodeByte2\n\t\tkb.wideChar = uint16(b&0x1F) << 6\n\n\tcase b < 0xF0:\n\t\t// 3-byte encoding (0xE0-0xEF)\n\t\tkb.decode = decodeByte3\n\t\tkb.wideChar = uint16(b&0x0F) << 12\n\n\tdefault:\n\t\t// 4-byte encoding unsupported (0xF0-0xF4), or illegal byte 4 (0xF5-0xFF)\n\t\tkb.decode = decodeReset\n\t\treturn ErrInvalidUTF8\n\t}\n\treturn nil\n}\n\nfunc (kb *keyboard) write(p uint16) error {\n\tc := keycode(p)\n\tif 0 == c {\n\t\treturn ErrInvalidCodepoint\n\t}\n\tif d := deadkey(c); 0 != d {\n\t\tif err := kb.writeKeycode(d); nil != err {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn kb.writeKeycode(c)\n}\n\nfunc (kb *keyboard) writeKeycode(c Keycode) error {\n\tvar b [9]byte\n\tb[0] = 0x02\n\tb[1] = c.mod()\n\tb[2] = 0\n\tb[3] = c.key()\n\tb[4] = 0\n\tb[5] = 0\n\tb[6] = 0\n\tb[7] = 0\n\tb[8] = 0\n\tif !kb.sendKey(false, b[:]) {\n\t\treturn hid.ErrHIDReportTransfer\n\t}\n\n\tb[1] = 0\n\tb[3] = 0\n\tif !kb.sendKey(false, b[:]) {\n\t\treturn hid.ErrHIDReportTransfer\n\t}\n\treturn nil\n}\n\n// Press transmits a press-and-release sequence for the given Keycode, which\n// simulates a discrete keypress event.\n//\n// The following values of Keycode are supported:\n//\n//\t0x0020 - 0x007F  ASCII               (U+0020 to U+007F)  [USES LAYOUT]\n//\t0x0080 - 0xC1FF  Unicode             (U+0080 to U+C1FF)  [USES LAYOUT]\n//\t0xC200 - 0xDFFF  UTF-8 packed        (U+0080 to U+07FF)  [USES LAYOUT]\n//\t0xE000 - 0xE0FF  Modifier key        (bitmap, 8 keys, Shift/Ctrl/Alt/GUI)\n//\t0xE200 - 0xE2FF  System key          (HID usage code, page 1)\n//\t0xE400 - 0xE7FF  Media/Consumer key  (HID usage code, page 12)\n//\t0xF000 - 0xFFFF  Normal key          (HID usage code, page 7)\nfunc (kb *keyboard) Press(c Keycode) error {\n\tif err := kb.Down(c); nil != err {\n\t\treturn err\n\t}\n\treturn kb.Up(c)\n}\n\nfunc (kb *keyboard) sendKey(consumer bool, b []byte) bool {\n\tkb.tx(b)\n\treturn true\n}\n\nfunc (kb *keyboard) keyboardSendKeys(consumer bool) bool {\n\tvar b [9]byte\n\n\tif !consumer {\n\t\tb[0] = 0x02 // REPORT_ID\n\t\tb[1] = kb.mod\n\t\tb[2] = 0x02\n\t\tb[3] = kb.key[0]\n\t\tb[4] = kb.key[1]\n\t\tb[5] = kb.key[2]\n\t\tb[6] = kb.key[3]\n\t\tb[7] = kb.key[4]\n\t\tb[8] = kb.key[5]\n\t\treturn kb.sendKey(consumer, b[:])\n\n\t} else {\n\t\tb[0] = 0x03 // REPORT_ID\n\t\tb[1] = uint8(kb.con[0])\n\t\tb[2] = uint8((kb.con[0] & 0x0300) >> 8)\n\n\t\treturn kb.sendKey(consumer, b[:3])\n\t}\n}\n\n// Down transmits a key-down event for the given Keycode.\n//\n// The host will interpret the key as being held down continuously until a\n// corresponding key-up event is transmitted, e.g., via method Up().\n//\n// See godoc comment on method Press() for details on what input is accepted and\n// how it is interpreted.\nfunc (kb *keyboard) Down(c Keycode) error {\n\tvar res uint8\n\tmsb := c >> 8\n\tif msb >= 0xC2 {\n\t\tif msb < 0xE0 {\n\t\t\tc = ((msb & 0x1F) << 6) | Keycode(c.key())\n\t\t} else {\n\t\t\tswitch msb {\n\t\t\tcase 0xF0:\n\t\t\t\treturn kb.down(uint8(c), 0)\n\n\t\t\tcase 0xE0:\n\t\t\t\treturn kb.down(0, uint8(c))\n\n\t\t\tcase 0xE2:\n\t\t\t\treturn kb.downSys(uint8(c))\n\n\t\t\tdefault:\n\t\t\t\tif 0xE4 <= msb && msb <= 0xE7 {\n\t\t\t\t\treturn kb.downCon(uint16(c & 0x03FF))\n\t\t\t\t}\n\t\t\t\treturn ErrInvalidKeycode\n\t\t\t}\n\t\t}\n\t}\n\tc = keycode(uint16(c))\n\tif 0 == c {\n\t\treturn ErrInvalidCodepoint\n\t}\n\tif d := deadkey(c); 0 != d {\n\t\tres = kb.mod\n\t\tif 0 != res {\n\t\t\tkb.mod = 0\n\t\t\tkb.keyboardSendKeys(false)\n\t\t}\n\t\tkb.down(d.key(), d.mod())\n\t\tkb.up(d.key(), d.mod())\n\t}\n\treturn kb.down(c.key(), c.mod()|res)\n}\n\nfunc (kb *keyboard) down(key uint8, mod uint8) error {\n\tsend := false\n\tif 0 != mod {\n\t\tif kb.mod&mod != mod {\n\t\t\tkb.mod |= mod\n\t\t\tsend = true\n\t\t}\n\t}\n\tif 0 != key {\n\t\tfor _, k := range kb.key {\n\t\t\tif k == key {\n\t\t\t\tgoto end\n\t\t\t}\n\t\t}\n\t\tfor i, k := range kb.key {\n\t\t\tif 0 == k {\n\t\t\t\tkb.key[i] = key\n\t\t\t\tsend = true\n\t\t\t\tgoto end\n\t\t\t}\n\t\t}\n\t\treturn ErrKeypressMaximum\n\t}\nend:\n\tif send {\n\t\tif !kb.keyboardSendKeys(false) {\n\t\t\treturn hid.ErrHIDReportTransfer\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (kb *keyboard) downCon(key uint16) error {\n\tif 0 == key {\n\t\treturn ErrInvalidKeycode\n\t}\n\tfor _, k := range kb.con {\n\t\tif key == k {\n\t\t\treturn nil // already pressed\n\t\t}\n\t}\n\tfor i, k := range kb.con {\n\t\tif 0 == k {\n\t\t\tkb.con[i] = key\n\t\t\tif !kb.keyboardSendKeys(true) {\n\t\t\t\treturn hid.ErrHIDReportTransfer\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn ErrKeypressMaximum\n}\n\nfunc (kb *keyboard) downSys(key uint8) error {\n\tif 0 == key {\n\t\treturn ErrInvalidKeycode\n\t}\n\tfor _, k := range kb.sys {\n\t\tif key == k {\n\t\t\treturn nil // already pressed\n\t\t}\n\t}\n\tfor i, k := range kb.sys {\n\t\tif 0 == k {\n\t\t\tkb.sys[i] = key\n\t\t\tif !kb.keyboardSendKeys(true) {\n\t\t\t\treturn hid.ErrHIDReportTransfer\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn ErrKeypressMaximum\n}\n\n// Up transmits a key-up event for the given Keycode.\n//\n// See godoc comment on method Press() for details on what input is accepted and\n// how it is interpreted.\nfunc (kb *keyboard) Up(c Keycode) error {\n\tmsb := c >> 8\n\tif msb >= 0xC2 {\n\t\tif msb < 0xE0 {\n\t\t\tc = ((msb & 0x1F) << 6) | Keycode(c.key())\n\t\t} else {\n\t\t\tswitch msb {\n\t\t\tcase 0xF0:\n\t\t\t\treturn kb.up(uint8(c), 0)\n\n\t\t\tcase 0xE0:\n\t\t\t\treturn kb.up(0, uint8(c))\n\n\t\t\tcase 0xE2:\n\t\t\t\treturn kb.upSys(uint8(c))\n\n\t\t\tdefault:\n\t\t\t\tif 0xE4 <= msb && msb <= 0xE7 {\n\t\t\t\t\treturn kb.upCon(uint16(c & 0x03FF))\n\t\t\t\t}\n\t\t\t\treturn ErrInvalidKeycode\n\t\t\t}\n\t\t}\n\t}\n\tc = keycode(uint16(c))\n\tif 0 == c {\n\t\treturn ErrInvalidCodepoint\n\t}\n\treturn kb.up(c.key(), c.mod())\n}\n\n// Release transmits a key-up event for all keyboard keys currently pressed as\n// if the user removed his/her hands from the keyboard entirely.\nfunc (kb *keyboard) Release() error {\n\n\tbits := uint16(kb.mod)\n\tkb.mod = 0\n\tfor i, k := range kb.key {\n\t\tbits |= uint16(k)\n\t\tkb.key[i] = 0\n\t}\n\tif 0 != bits {\n\t\tif !kb.keyboardSendKeys(false) {\n\t\t\treturn hid.ErrHIDReportTransfer\n\t\t}\n\t}\n\tbits = 0\n\tfor i, k := range kb.con {\n\t\tbits |= k\n\t\tkb.con[i] = 0\n\t}\n\tfor i, k := range kb.sys {\n\t\tbits |= uint16(k)\n\t\tkb.sys[i] = 0\n\t}\n\tif 0 != bits {\n\t\tif !kb.keyboardSendKeys(true) {\n\t\t\treturn hid.ErrHIDReportTransfer\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (kb *keyboard) up(key uint8, mod uint8) error {\n\tsend := false\n\tif 0 != mod {\n\t\tif kb.mod&mod != 0 {\n\t\t\tkb.mod &^= mod\n\t\t\tsend = true\n\t\t}\n\t}\n\tif 0 != key {\n\t\tfor i, k := range kb.key {\n\t\t\tif key == k {\n\t\t\t\tkb.key[i] = 0\n\t\t\t\tsend = true\n\t\t\t}\n\t\t}\n\t}\n\tif send {\n\t\tif !kb.keyboardSendKeys(false) {\n\t\t\treturn hid.ErrHIDReportTransfer\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (kb *keyboard) upCon(key uint16) error {\n\tif 0 == key {\n\t\treturn ErrInvalidKeycode\n\t}\n\tfor i, k := range kb.con {\n\t\tif key == k {\n\t\t\tkb.con[i] = 0\n\t\t\tif !kb.keyboardSendKeys(true) {\n\t\t\t\treturn hid.ErrHIDReportTransfer\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (kb *keyboard) upSys(key uint8) error {\n\tif 0 == key {\n\t\treturn ErrInvalidKeycode\n\t}\n\tfor i, k := range kb.sys {\n\t\tif key == k {\n\t\t\tkb.sys[i] = 0\n\t\t\tif !kb.keyboardSendKeys(true) {\n\t\t\t\treturn hid.ErrHIDReportTransfer\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "src/machine/usb/hid/keyboard/keycode.go",
    "content": "package keyboard\n\n// Keycode is a package-defined bitmap used to encode the value of a given key.\ntype Keycode uint16\n\n// keycode returns the given Unicode codepoint translated to a Keycode sequence.\n// Unicode codepoints greater than U+FFFF are unsupported.\n//\n//go:inline\nfunc keycode(p uint16) Keycode {\n\tif p < 0x80 {\n\t\treturn ascii[p]\n\t} else if p >= 0xA0 && p < 0x0100 {\n\t\treturn iso88591[p-0xA0]\n\t} else if uint16(UNICODE20AC) == p {\n\t\treturn UNICODE20AC.mask()\n\t}\n\treturn 0\n}\n\n//go:inline\nfunc deadkey(c Keycode) Keycode {\n\tswitch c & deadkeysMask {\n\tcase acuteAccentBits:\n\t\treturn deadkeyAcuteAccent\n\tcase circumflexBits:\n\t\treturn deadkeyCircumflex\n\tcase diaeresisBits:\n\t\treturn deadkeyDiaeresis\n\tcase graveAccentBits:\n\t\treturn deadkeyGraveAccent\n\tcase tildeBits:\n\t\treturn deadkeyTilde\n\t}\n\treturn 0\n}\n\n//go:inline\nfunc (c Keycode) mask() Keycode { return c & keycodeMask }\n\n//go:inline\nfunc (c Keycode) key() uint8 { return uint8(c & keyMask) }\n\n//go:inline\nfunc (c Keycode) mod() uint8 {\n\tvar m Keycode\n\tif 0 != c&shiftMask {\n\t\tm |= KeyModifierShift\n\t}\n\tif 0 != c&altgrMask {\n\t\tm |= KeyModifierRightAlt\n\t}\n\treturn uint8(m)\n}\n\n//go:inline\nfunc (c Keycode) Shift() Keycode { return c | KeyModifierShift }\n\nconst (\n\thidKeyboardKeyCount = 6 // Max number of simultaneous keypresses\n\thidKeyboardSysCount = 3\n\thidKeyboardConCount = 4\n)\n\n// Keycodes common to all Keyboard layouts\nconst (\n\tKeyModifierCtrl       Keycode = 0x01 | 0xE000\n\tKeyModifierShift      Keycode = 0x02 | 0xE000\n\tKeyModifierAlt        Keycode = 0x04 | 0xE000\n\tKeyModifierGUI        Keycode = 0x08 | 0xE000\n\tKeyModifierLeftCtrl   Keycode = 0x01 | 0xE000\n\tKeyModifierLeftShift  Keycode = 0x02 | 0xE000\n\tKeyModifierLeftAlt    Keycode = 0x04 | 0xE000\n\tKeyModifierLeftGUI    Keycode = 0x08 | 0xE000\n\tKeyModifierRightCtrl  Keycode = 0x10 | 0xE000\n\tKeyModifierRightShift Keycode = 0x20 | 0xE000\n\tKeyModifierRightAlt   Keycode = 0x40 | 0xE000\n\tKeyModifierRightGUI   Keycode = 0x80 | 0xE000\n\n\t// KeySystemXXX is not supported now\n\tKeySystemPowerDown Keycode = 0x81 | 0xE200\n\tKeySystemSleep     Keycode = 0x82 | 0xE200\n\tKeySystemWakeUp    Keycode = 0x83 | 0xE200\n\n\tKeyMediaPlay        Keycode = 0xB0 | 0xE400\n\tKeyMediaPause       Keycode = 0xB1 | 0xE400\n\tKeyMediaRecord      Keycode = 0xB2 | 0xE400\n\tKeyMediaFastForward Keycode = 0xB3 | 0xE400\n\tKeyMediaRewind      Keycode = 0xB4 | 0xE400\n\tKeyMediaNextTrack   Keycode = 0xB5 | 0xE400\n\tKeyMediaPrevTrack   Keycode = 0xB6 | 0xE400\n\tKeyMediaStop        Keycode = 0xB7 | 0xE400\n\tKeyMediaEject       Keycode = 0xB8 | 0xE400\n\tKeyMediaRandomPlay  Keycode = 0xB9 | 0xE400\n\tKeyMediaPlayPause   Keycode = 0xCD | 0xE400\n\tKeyMediaPlaySkip    Keycode = 0xCE | 0xE400\n\tKeyMediaMute        Keycode = 0xE2 | 0xE400\n\tKeyMediaVolumeInc   Keycode = 0xE9 | 0xE400\n\tKeyMediaVolumeDec   Keycode = 0xEA | 0xE400\n\n\tKeyA           Keycode = 4 | 0xF000\n\tKeyB           Keycode = 5 | 0xF000\n\tKeyC           Keycode = 6 | 0xF000\n\tKeyD           Keycode = 7 | 0xF000\n\tKeyE           Keycode = 8 | 0xF000\n\tKeyF           Keycode = 9 | 0xF000\n\tKeyG           Keycode = 10 | 0xF000\n\tKeyH           Keycode = 11 | 0xF000\n\tKeyI           Keycode = 12 | 0xF000\n\tKeyJ           Keycode = 13 | 0xF000\n\tKeyK           Keycode = 14 | 0xF000\n\tKeyL           Keycode = 15 | 0xF000\n\tKeyM           Keycode = 16 | 0xF000\n\tKeyN           Keycode = 17 | 0xF000\n\tKeyO           Keycode = 18 | 0xF000\n\tKeyP           Keycode = 19 | 0xF000\n\tKeyQ           Keycode = 20 | 0xF000\n\tKeyR           Keycode = 21 | 0xF000\n\tKeyS           Keycode = 22 | 0xF000\n\tKeyT           Keycode = 23 | 0xF000\n\tKeyU           Keycode = 24 | 0xF000\n\tKeyV           Keycode = 25 | 0xF000\n\tKeyW           Keycode = 26 | 0xF000\n\tKeyX           Keycode = 27 | 0xF000\n\tKeyY           Keycode = 28 | 0xF000\n\tKeyZ           Keycode = 29 | 0xF000\n\tKey1           Keycode = 30 | 0xF000\n\tKey2           Keycode = 31 | 0xF000\n\tKey3           Keycode = 32 | 0xF000\n\tKey4           Keycode = 33 | 0xF000\n\tKey5           Keycode = 34 | 0xF000\n\tKey6           Keycode = 35 | 0xF000\n\tKey7           Keycode = 36 | 0xF000\n\tKey8           Keycode = 37 | 0xF000\n\tKey9           Keycode = 38 | 0xF000\n\tKey0           Keycode = 39 | 0xF000\n\tKeyEnter       Keycode = 40 | 0xF000\n\tKeyEsc         Keycode = 41 | 0xF000\n\tKeyBackspace   Keycode = 42 | 0xF000\n\tKeyTab         Keycode = 43 | 0xF000\n\tKeySpace       Keycode = 44 | 0xF000\n\tKeyMinus       Keycode = 45 | 0xF000\n\tKeyEqual       Keycode = 46 | 0xF000\n\tKeyLeftBrace   Keycode = 47 | 0xF000\n\tKeyRightBrace  Keycode = 48 | 0xF000\n\tKeyBackslash   Keycode = 49 | 0xF000\n\tKeyNonUsNum    Keycode = 50 | 0xF000\n\tKeySemicolon   Keycode = 51 | 0xF000\n\tKeyQuote       Keycode = 52 | 0xF000\n\tKeyTilde       Keycode = 53 | 0xF000\n\tKeyComma       Keycode = 54 | 0xF000\n\tKeyPeriod      Keycode = 55 | 0xF000\n\tKeySlash       Keycode = 56 | 0xF000\n\tKeyCapsLock    Keycode = 57 | 0xF000\n\tKeyF1          Keycode = 58 | 0xF000\n\tKeyF2          Keycode = 59 | 0xF000\n\tKeyF3          Keycode = 60 | 0xF000\n\tKeyF4          Keycode = 61 | 0xF000\n\tKeyF5          Keycode = 62 | 0xF000\n\tKeyF6          Keycode = 63 | 0xF000\n\tKeyF7          Keycode = 64 | 0xF000\n\tKeyF8          Keycode = 65 | 0xF000\n\tKeyF9          Keycode = 66 | 0xF000\n\tKeyF10         Keycode = 67 | 0xF000\n\tKeyF11         Keycode = 68 | 0xF000\n\tKeyF12         Keycode = 69 | 0xF000\n\tKeyPrintscreen Keycode = 70 | 0xF000\n\tKeyScrollLock  Keycode = 71 | 0xF000\n\tKeyPause       Keycode = 72 | 0xF000\n\tKeyInsert      Keycode = 73 | 0xF000\n\tKeyHome        Keycode = 74 | 0xF000\n\tKeyPageUp      Keycode = 75 | 0xF000\n\tKeyDelete      Keycode = 76 | 0xF000\n\tKeyEnd         Keycode = 77 | 0xF000\n\tKeyPageDown    Keycode = 78 | 0xF000\n\tKeyRight       Keycode = 79 | 0xF000\n\tKeyLeft        Keycode = 80 | 0xF000\n\tKeyDown        Keycode = 81 | 0xF000\n\tKeyUp          Keycode = 82 | 0xF000\n\tKeyNumLock     Keycode = 83 | 0xF000\n\tKeypadSlash    Keycode = 84 | 0xF000\n\tKeypadAsterisk Keycode = 85 | 0xF000\n\tKeypadMinus    Keycode = 86 | 0xF000\n\tKeypadPlus     Keycode = 87 | 0xF000\n\tKeypadEnter    Keycode = 88 | 0xF000\n\tKeypad1        Keycode = 89 | 0xF000\n\tKeypad2        Keycode = 90 | 0xF000\n\tKeypad3        Keycode = 91 | 0xF000\n\tKeypad4        Keycode = 92 | 0xF000\n\tKeypad5        Keycode = 93 | 0xF000\n\tKeypad6        Keycode = 94 | 0xF000\n\tKeypad7        Keycode = 95 | 0xF000\n\tKeypad8        Keycode = 96 | 0xF000\n\tKeypad9        Keycode = 97 | 0xF000\n\tKeypad0        Keycode = 98 | 0xF000\n\tKeypadPeriod   Keycode = 99 | 0xF000\n\tKeyNonUSBS     Keycode = 100 | 0xF000\n\tKeyMenu        Keycode = 101 | 0xF000\n\tKeyF13         Keycode = 104 | 0xF000\n\tKeyF14         Keycode = 105 | 0xF000\n\tKeyF15         Keycode = 106 | 0xF000\n\tKeyF16         Keycode = 107 | 0xF000\n\tKeyF17         Keycode = 108 | 0xF000\n\tKeyF18         Keycode = 109 | 0xF000\n\tKeyF19         Keycode = 110 | 0xF000\n\tKeyF20         Keycode = 111 | 0xF000\n\tKeyF21         Keycode = 112 | 0xF000\n\tKeyF22         Keycode = 113 | 0xF000\n\tKeyF23         Keycode = 114 | 0xF000\n\tKeyF24         Keycode = 115 | 0xF000\n\n\t// International keys for Japanese and other language keyboards\n\tKeyInternational1 Keycode = 0x87 | 0xF000 // JIS \"\\\" and \"_\"\n\tKeyInternational2 Keycode = 0x88 | 0xF000 // JIS Katakana/Hiragana\n\tKeyInternational3 Keycode = 0x89 | 0xF000 // JIS \"¥\" and \"|\"\n\tKeyInternational4 Keycode = 0x8A | 0xF000 // JIS Henkan\n\tKeyInternational5 Keycode = 0x8B | 0xF000 // JIS Muhenkan\n\tKeyInternational6 Keycode = 0x8C | 0xF000 // JIS Numpad \",\"\n\n\t// Language keys for input method switching\n\tKeyLanguage1 Keycode = 0x90 | 0xF000 // Hangul/English\n\tKeyLanguage2 Keycode = 0x91 | 0xF000 // Hanja\n\tKeyLanguage3 Keycode = 0x92 | 0xF000 // JIS Katakana\n\tKeyLanguage4 Keycode = 0x93 | 0xF000 // JIS Hiragana\n\tKeyLanguage5 Keycode = 0x94 | 0xF000 // JIS Zenkaku/Hankaku\n\n\tKeyUpArrow    Keycode = KeyUp\n\tKeyDownArrow  Keycode = KeyDown\n\tKeyLeftArrow  Keycode = KeyLeft\n\tKeyRightArrow Keycode = KeyRight\n\tKeyReturn     Keycode = KeyEnter\n\tKeyLeftCtrl   Keycode = KeyModifierLeftCtrl\n\tKeyLeftShift  Keycode = KeyModifierLeftShift\n\tKeyLeftAlt    Keycode = KeyModifierLeftAlt\n\tKeyLeftGUI    Keycode = KeyModifierLeftGUI\n\tKeyRightCtrl  Keycode = KeyModifierRightCtrl\n\tKeyRightShift Keycode = KeyModifierRightShift\n\tKeyRightAlt   Keycode = KeyModifierRightAlt\n\tKeyRightGUI   Keycode = KeyModifierRightGUI\n\n\t// QMK compatibility aliases for international keys\n\tKeyInt1 Keycode = KeyInternational1\n\tKeyInt2 Keycode = KeyInternational2\n\tKeyInt3 Keycode = KeyInternational3\n\tKeyInt4 Keycode = KeyInternational4\n\tKeyInt5 Keycode = KeyInternational5\n\tKeyInt6 Keycode = KeyInternational6\n\n\t// QMK compatibility aliases for language keys\n\tKeyLng1 Keycode = KeyLanguage1\n\tKeyLng2 Keycode = KeyLanguage2\n\tKeyLng3 Keycode = KeyLanguage3\n\tKeyLng4 Keycode = KeyLanguage4\n\tKeyLng5 Keycode = KeyLanguage5\n\n\t// Common keyboard layout aliases\n\tKeyRo               Keycode = KeyInternational1 // Japanese \"ろ\"\n\tKeyKatakanaHiragana Keycode = KeyInternational2 // Japanese Katakana/Hiragana\n\tKeyYen              Keycode = KeyInternational3 // Japanese \"¥\"\n\tKeyHenkan           Keycode = KeyInternational4 // Japanese Henkan\n\tKeyMuhenkan         Keycode = KeyInternational5 // Japanese Muhenkan\n\tKeyKpJpComma        Keycode = KeyInternational6 // Japanese Numpad \",\"\n\tKeyHangeul          Keycode = KeyLanguage1      // Korean Hangul/English\n\tKeyHanja            Keycode = KeyLanguage2      // Korean Hanja\n\tKeyKatakana         Keycode = KeyLanguage3      // Japanese Katakana\n\tKeyHiragana         Keycode = KeyLanguage4      // Japanese Hiragana\n\tKeyZenkakuHankaku   Keycode = KeyLanguage5      // Japanese Zenkaku/Hankaku\n)\n\n// Keycodes for layout US English (0x0904)\nconst (\n\tkeycodeMask Keycode = 0x07FF\n\tkeyMask     Keycode = 0x003F\n\n\tshiftMask          Keycode = 0x0040\n\taltgrMask          Keycode = 0x0080\n\tdeadkeysMask       Keycode = 0x0700\n\tcircumflexBits     Keycode = 0x0100\n\tacuteAccentBits    Keycode = 0x0200\n\tgraveAccentBits    Keycode = 0x0300\n\ttildeBits          Keycode = 0x0400\n\tdiaeresisBits      Keycode = 0x0500\n\tdeadkeyCircumflex  Keycode = Key6 | shiftMask\n\tdeadkeyAcuteAccent Keycode = KeyQuote\n\tdeadkeyGraveAccent Keycode = KeyTilde\n\tdeadkeyTilde       Keycode = KeyTilde | shiftMask\n\tdeadkeyDiaeresis   Keycode = KeyQuote | shiftMask\n\n\tASCII00 Keycode = 0            //   0  NUL\n\tASCII01 Keycode = 0            //   1  SOH\n\tASCII02 Keycode = 0            //   2  STX\n\tASCII03 Keycode = 0            //   3  ETX\n\tASCII04 Keycode = 0            //   4  EOT\n\tASCII05 Keycode = 0            //   5  ENQ\n\tASCII06 Keycode = 0            //   6  ACK\n\tASCII07 Keycode = 0            //   7  BEL\n\tASCII08 Keycode = KeyBackspace //   8  BS\n\tASCII09 Keycode = KeyTab       //   9  TAB\n\tASCII0A Keycode = KeyEnter     //  10  LF\n\tASCII0B Keycode = 0            //  11  VT\n\tASCII0C Keycode = 0            //  12  FF\n\tASCII0D Keycode = 0            //  13  CR\n\tASCII0E Keycode = 0            //  14  SO\n\tASCII0F Keycode = 0            //  15  SI\n\tASCII10 Keycode = 0            //  16  DEL\n\tASCII11 Keycode = 0            //  17  DC1\n\tASCII12 Keycode = 0            //  18  DC2\n\tASCII13 Keycode = 0            //  19  DC3\n\tASCII14 Keycode = 0            //  20  DC4\n\tASCII15 Keycode = 0            //  21  NAK\n\tASCII16 Keycode = 0            //  22  SYN\n\tASCII17 Keycode = 0            //  23  ETB\n\tASCII18 Keycode = 0            //  24  CAN\n\tASCII19 Keycode = 0            //  25  EM\n\tASCII1A Keycode = 0            //  26  SUB\n\tASCII1B Keycode = 0            //  27  ESC\n\tASCII1C Keycode = 0            //  28  FS\n\tASCII1D Keycode = 0            //  29  GS\n\tASCII1E Keycode = 0            //  30  RS\n\tASCII1F Keycode = 0            //  31  US\n\n\tASCII20     Keycode = KeySpace                             //  32   SPACE\n\tASCII21     Keycode = Key1 | shiftMask                     //  33   !\n\tASCII22     Keycode = diaeresisBits | KeySpace             //  34   \"\n\tASCII23     Keycode = Key3 | shiftMask                     //  35   #\n\tASCII24     Keycode = Key4 | shiftMask                     //  36   $\n\tASCII25     Keycode = Key5 | shiftMask                     //  37   %\n\tASCII26     Keycode = Key7 | shiftMask                     //  38   &\n\tASCII27     Keycode = acuteAccentBits | KeySpace           //  39   '\n\tASCII28     Keycode = Key9 | shiftMask                     //  40   (\n\tASCII29     Keycode = Key0 | shiftMask                     //  41   )\n\tASCII2A     Keycode = Key8 | shiftMask                     //  42   *\n\tASCII2B     Keycode = KeyEqual | shiftMask                 //  43   +\n\tASCII2C     Keycode = KeyComma                             //  44   ,\n\tASCII2D     Keycode = KeyMinus                             //  45   -\n\tASCII2E     Keycode = KeyPeriod                            //  46   .\n\tASCII2F     Keycode = KeySlash                             //  47   /\n\tASCII30     Keycode = Key0                                 //  48   0\n\tASCII31     Keycode = Key1                                 //  49   1\n\tASCII32     Keycode = Key2                                 //  50   2\n\tASCII33     Keycode = Key3                                 //  51   3\n\tASCII34     Keycode = Key4                                 //  52   4\n\tASCII35     Keycode = Key5                                 //  53   5\n\tASCII36     Keycode = Key6                                 //  54   6\n\tASCII37     Keycode = Key7                                 //  55   7\n\tASCII38     Keycode = Key8                                 //  55   8\n\tASCII39     Keycode = Key9                                 //  57   9\n\tASCII3A     Keycode = KeySemicolon | shiftMask             //  58   :\n\tASCII3B     Keycode = KeySemicolon                         //  59   ;\n\tASCII3C     Keycode = KeyComma | shiftMask                 //  60   <\n\tASCII3D     Keycode = KeyEqual                             //  61   =\n\tASCII3E     Keycode = KeyPeriod | shiftMask                //  62   >\n\tASCII3F     Keycode = KeySlash | shiftMask                 //  63   ?\n\tASCII40     Keycode = Key2 | shiftMask                     //  64   @\n\tASCII41     Keycode = KeyA | shiftMask                     //  65   A\n\tASCII42     Keycode = KeyB | shiftMask                     //  66   B\n\tASCII43     Keycode = KeyC | shiftMask                     //  67   C\n\tASCII44     Keycode = KeyD | shiftMask                     //  68   D\n\tASCII45     Keycode = KeyE | shiftMask                     //  69   E\n\tASCII46     Keycode = KeyF | shiftMask                     //  70   F\n\tASCII47     Keycode = KeyG | shiftMask                     //  71   G\n\tASCII48     Keycode = KeyH | shiftMask                     //  72   H\n\tASCII49     Keycode = KeyI | shiftMask                     //  73   I\n\tASCII4A     Keycode = KeyJ | shiftMask                     //  74   J\n\tASCII4B     Keycode = KeyK | shiftMask                     //  75   K\n\tASCII4C     Keycode = KeyL | shiftMask                     //  76   L\n\tASCII4D     Keycode = KeyM | shiftMask                     //  77   M\n\tASCII4E     Keycode = KeyN | shiftMask                     //  78   N\n\tASCII4F     Keycode = KeyO | shiftMask                     //  79   O\n\tASCII50     Keycode = KeyP | shiftMask                     //  80   P\n\tASCII51     Keycode = KeyQ | shiftMask                     //  81   Q\n\tASCII52     Keycode = KeyR | shiftMask                     //  82   R\n\tASCII53     Keycode = KeyS | shiftMask                     //  83   S\n\tASCII54     Keycode = KeyT | shiftMask                     //  84   T\n\tASCII55     Keycode = KeyU | shiftMask                     //  85   U\n\tASCII56     Keycode = KeyV | shiftMask                     //  86   V\n\tASCII57     Keycode = KeyW | shiftMask                     //  87   W\n\tASCII58     Keycode = KeyX | shiftMask                     //  88   X\n\tASCII59     Keycode = KeyY | shiftMask                     //  89   Y\n\tASCII5A     Keycode = KeyZ | shiftMask                     //  90   Z\n\tASCII5B     Keycode = KeyLeftBrace                         //  91   [\n\tASCII5C     Keycode = KeyBackslash                         //  92   \\\n\tASCII5D     Keycode = KeyRightBrace                        //  93   ]\n\tASCII5E     Keycode = circumflexBits | KeySpace            //  94   ^\n\tASCII5F     Keycode = KeyMinus | shiftMask                 //  95\n\tASCII60     Keycode = graveAccentBits | KeySpace           //  96   `\n\tASCII61     Keycode = KeyA                                 //  97   a\n\tASCII62     Keycode = KeyB                                 //  98   b\n\tASCII63     Keycode = KeyC                                 //  99   c\n\tASCII64     Keycode = KeyD                                 // 100   d\n\tASCII65     Keycode = KeyE                                 // 101   e\n\tASCII66     Keycode = KeyF                                 // 102   f\n\tASCII67     Keycode = KeyG                                 // 103   g\n\tASCII68     Keycode = KeyH                                 // 104   h\n\tASCII69     Keycode = KeyI                                 // 105   i\n\tASCII6A     Keycode = KeyJ                                 // 106   j\n\tASCII6B     Keycode = KeyK                                 // 107   k\n\tASCII6C     Keycode = KeyL                                 // 108   l\n\tASCII6D     Keycode = KeyM                                 // 109   m\n\tASCII6E     Keycode = KeyN                                 // 110   n\n\tASCII6F     Keycode = KeyO                                 // 111   o\n\tASCII70     Keycode = KeyP                                 // 112   p\n\tASCII71     Keycode = KeyQ                                 // 113   q\n\tASCII72     Keycode = KeyR                                 // 114   r\n\tASCII73     Keycode = KeyS                                 // 115   s\n\tASCII74     Keycode = KeyT                                 // 116   t\n\tASCII75     Keycode = KeyU                                 // 117   u\n\tASCII76     Keycode = KeyV                                 // 118   v\n\tASCII77     Keycode = KeyW                                 // 119   w\n\tASCII78     Keycode = KeyX                                 // 120   x\n\tASCII79     Keycode = KeyY                                 // 121   y\n\tASCII7A     Keycode = KeyZ                                 // 122   z\n\tASCII7B     Keycode = KeyLeftBrace | shiftMask             // 123   {\n\tASCII7C     Keycode = KeyBackslash | shiftMask             // 124   |\n\tASCII7D     Keycode = KeyRightBrace | shiftMask            // 125   }\n\tASCII7E     Keycode = tildeBits | KeySpace                 // 126   ~\n\tASCII7F     Keycode = KeyBackspace                         // 127   DEL\n\tISO88591A0  Keycode = KeySpace                             // 160         Nonbreakng Space\n\tISO88591A1  Keycode = Key1 | altgrMask                     // 161   ¡     Inverted Exclamation\n\tISO88591A2  Keycode = KeyC | altgrMask | shiftMask         // 162   ¢     Cent SIGN\n\tISO88591A3  Keycode = Key4 | altgrMask | shiftMask         // 163   £     Pound Sign\n\tISO88591A4  Keycode = Key4 | altgrMask                     // 164   ¤     Currency or Euro Sign\n\tISO88591A5  Keycode = KeyMinus | altgrMask                 // 165   ¥     YEN SIGN\n\tISO88591A6  Keycode = KeyBackslash | altgrMask | shiftMask // 166   ¦     BROKEN BAR\t\t\t??\n\tISO88591A7  Keycode = KeyS | altgrMask | shiftMask         // 167   §     SECTION SIGN\n\tISO88591A8  Keycode = KeyQuote | altgrMask | shiftMask     // 168   ¨     DIAERESIS\n\tISO88591A9  Keycode = KeyC | altgrMask                     // 169   ©     COPYRIGHT SIGN\n\tISO88591AA  Keycode = 0                                    // 170   ª     FEMININE ORDINAL\n\tISO88591AB  Keycode = KeyLeftBrace | altgrMask             // 171   «     LEFT DOUBLE ANGLE QUOTE\n\tISO88591AC  Keycode = KeyBackslash | altgrMask             // 172   ¬     NOT SIGN\t\t\t??\n\tISO88591AD  Keycode = 0                                    // 173         SOFT HYPHEN\n\tISO88591AE  Keycode = KeyR | altgrMask                     // 174   ®     REGISTERED SIGN\n\tISO88591AF  Keycode = 0                                    // 175   ¯     MACRON\n\tISO88591B0  Keycode = KeySemicolon | altgrMask | shiftMask // 176   °     DEGREE SIGN\n\tISO88591B1  Keycode = 0                                    // 177   ±     PLUS-MINUS SIGN\n\tISO88591B2  Keycode = Key2 | altgrMask                     // 178   ²     SUPERSCRIPT TWO\n\tISO88591B3  Keycode = Key3 | altgrMask                     // 179   ³     SUPERSCRIPT THREE\n\tISO88591B4  Keycode = KeyQuote | altgrMask                 // 180   ´     ACUTE ACCENT\n\tISO88591B5  Keycode = KeyM | altgrMask                     // 181   µ     MICRO SIGN\n\tISO88591B6  Keycode = KeySemicolon | altgrMask             // 182   ¶     PILCROW SIGN\n\tISO88591B7  Keycode = 0                                    // 183   ·     MIDDLE DOT\n\tISO88591B8  Keycode = 0                                    // 184   ¸     CEDILLA\n\tISO88591B9  Keycode = Key1 | altgrMask | shiftMask         // 185   ¹     SUPERSCRIPT ONE\n\tISO88591BA  Keycode = 0                                    // 186   º     MASCULINE ORDINAL\n\tISO88591BB  Keycode = KeyRightBrace | altgrMask            // 187   »     RIGHT DOUBLE ANGLE QUOTE\n\tISO88591BC  Keycode = Key6 | altgrMask                     // 188   ¼     FRACTION ONE QUARTER\n\tISO88591BD  Keycode = Key7 | altgrMask                     // 189   ½     FRACTION ONE HALF\n\tISO88591BE  Keycode = Key8 | altgrMask                     // 190   ¾     FRACTION THREE QUARTERS\n\tISO88591BF  Keycode = KeySlash | altgrMask                 // 191   ¿     INVERTED QUESTION MARK\n\tISO88591C0  Keycode = graveAccentBits | KeyA | shiftMask   // 192   À     A GRAVE\n\tISO88591C1  Keycode = KeyA | altgrMask | shiftMask         // 193   Á     A ACUTE\n\tISO88591C2  Keycode = circumflexBits | KeyA | shiftMask    // 194   Â     A CIRCUMFLEX\n\tISO88591C3  Keycode = tildeBits | KeyA | shiftMask         // 195   Ã     A TILDE\n\tISO88591C4  Keycode = KeyQ | altgrMask | shiftMask         // 196   Ä     A DIAERESIS\n\tISO88591C5  Keycode = KeyW | altgrMask | shiftMask         // 197   Å     A RING ABOVE\n\tISO88591C6  Keycode = KeyZ | altgrMask | shiftMask         // 198   Æ     AE\n\tISO88591C7  Keycode = KeyComma | altgrMask | shiftMask     // 199   Ç     C CEDILLA\n\tISO88591C8  Keycode = graveAccentBits | KeyE | shiftMask   // 200   È     E GRAVE\n\tISO88591C9  Keycode = KeyE | altgrMask | shiftMask         // 201   É     E ACUTE\n\tISO88591CA  Keycode = circumflexBits | KeyE | shiftMask    // 202   Ê     E CIRCUMFLEX\n\tISO88591CB  Keycode = diaeresisBits | KeyE | shiftMask     // 203   Ë     E DIAERESIS\n\tISO88591CC  Keycode = graveAccentBits | KeyI | shiftMask   // 204   Ì     I GRAVE\n\tISO88591CD  Keycode = KeyI | altgrMask | shiftMask         // 205   Í     I ACUTE\n\tISO88591CE  Keycode = circumflexBits | KeyI | shiftMask    // 206   Î     I CIRCUMFLEX\n\tISO88591CF  Keycode = diaeresisBits | KeyI | shiftMask     // 207   Ï     I DIAERESIS\n\tISO88591D0  Keycode = KeyD | altgrMask | shiftMask         // 208   Ð     ETH\n\tISO88591D1  Keycode = KeyN | altgrMask | shiftMask         // 209   Ñ     N TILDE\n\tISO88591D2  Keycode = graveAccentBits | KeyO | shiftMask   // 210   Ò     O GRAVE\n\tISO88591D3  Keycode = KeyO | altgrMask | shiftMask         // 211   Ó     O ACUTE\n\tISO88591D4  Keycode = circumflexBits | KeyO | shiftMask    // 212   Ô     O CIRCUMFLEX\n\tISO88591D5  Keycode = tildeBits | KeyO | shiftMask         // 213   Õ     O TILDE\n\tISO88591D6  Keycode = KeyP | altgrMask | shiftMask         // 214   Ö     O DIAERESIS\n\tISO88591D7  Keycode = KeyEqual | altgrMask                 // 215   ×     MULTIPLICATION\n\tISO88591D8  Keycode = KeyL | altgrMask | shiftMask         // 216   Ø     O STROKE\n\tISO88591D9  Keycode = graveAccentBits | KeyU | shiftMask   // 217   Ù     U GRAVE\n\tISO88591DA  Keycode = KeyU | altgrMask | shiftMask         // 218   Ú     U ACUTE\n\tISO88591DB  Keycode = circumflexBits | KeyU | shiftMask    // 219   Û     U CIRCUMFLEX\n\tISO88591DC  Keycode = KeyY | altgrMask | shiftMask         // 220   Ü     U DIAERESIS\n\tISO88591DD  Keycode = acuteAccentBits | KeyY | shiftMask   // 221   Ý     Y ACUTE\n\tISO88591DE  Keycode = KeyT | altgrMask | shiftMask         // 222   Þ     THORN\n\tISO88591DF  Keycode = KeyS | altgrMask                     // 223   ß     SHARP S\n\tISO88591E0  Keycode = graveAccentBits | KeyA               // 224   à     a GRAVE\n\tISO88591E1  Keycode = KeyA | altgrMask                     // 225   á     a ACUTE\n\tISO88591E2  Keycode = circumflexBits | KeyA                // 226   â     a CIRCUMFLEX\n\tISO88591E3  Keycode = tildeBits | KeyA                     // 227   ã     a TILDE\n\tISO88591E4  Keycode = diaeresisBits | KeyA                 // 228   ä     a DIAERESIS\n\tISO88591E5  Keycode = KeyW | altgrMask                     // 229   å     a RING ABOVE\n\tISO88591E6  Keycode = KeyZ | altgrMask                     // 230   æ     ae\n\tISO88591E7  Keycode = KeyComma | altgrMask                 // 231   ç     c CEDILLA\n\tISO88591E8  Keycode = graveAccentBits | KeyE               // 232   è     e GRAVE\n\tISO88591E9  Keycode = acuteAccentBits | KeyE               // 233   é     e ACUTE\n\tISO88591EA  Keycode = circumflexBits | KeyE                // 234   ê     e CIRCUMFLEX\n\tISO88591EB  Keycode = diaeresisBits | KeyE                 // 235   ë     e DIAERESIS\n\tISO88591EC  Keycode = graveAccentBits | KeyI               // 236   ì     i GRAVE\n\tISO88591ED  Keycode = KeyI | altgrMask                     // 237   í     i ACUTE\n\tISO88591EE  Keycode = circumflexBits | KeyI                // 238   î     i CIRCUMFLEX\n\tISO88591EF  Keycode = diaeresisBits | KeyI                 // 239   ï     i DIAERESIS\n\tISO88591F0  Keycode = KeyD | altgrMask                     // 240   ð     ETH\n\tISO88591F1  Keycode = KeyN | altgrMask                     // 241   ñ     n TILDE\n\tISO88591F2  Keycode = graveAccentBits | KeyO               // 242   ò     o GRAVE\n\tISO88591F3  Keycode = KeyO | altgrMask                     // 243   ó     o ACUTE\n\tISO88591F4  Keycode = circumflexBits | KeyO                // 244   ô     o CIRCUMFLEX\n\tISO88591F5  Keycode = tildeBits | KeyO                     // 245   õ     o TILDE\n\tISO88591F6  Keycode = KeyP | altgrMask                     // 246   ö     o DIAERESIS\n\tISO88591F7  Keycode = KeyEqual | altgrMask | shiftMask     // 247   ÷     DIVISION\n\tISO88591F8  Keycode = KeyL | altgrMask                     // 248   ø     o STROKE\n\tISO88591F9  Keycode = graveAccentBits | KeyU               // 249   ù     u GRAVE\n\tISO88591FA  Keycode = KeyU | altgrMask                     // 250   ú     u ACUTE\n\tISO88591FB  Keycode = circumflexBits | KeyU                // 251   û     u CIRCUMFLEX\n\tISO88591FC  Keycode = KeyY | altgrMask                     // 252   ü     u DIAERESIS\n\tISO88591FD  Keycode = acuteAccentBits | KeyY               // 253   ý     y ACUTE\n\tISO88591FE  Keycode = KeyT | altgrMask                     // 254   þ     THORN\n\tISO88591FF  Keycode = diaeresisBits | KeyY                 // 255   ÿ     y DIAERESIS\n\tUNICODE20AC Keycode = Key5 | altgrMask                     // 20AC  €     Euro Sign\n)\n\nvar ascii = [...]Keycode{\n\tASCII00.mask(), ASCII01.mask(), ASCII02.mask(), ASCII03.mask(),\n\tASCII04.mask(), ASCII05.mask(), ASCII06.mask(), ASCII07.mask(),\n\tASCII08.mask(), ASCII09.mask(), ASCII0A.mask(), ASCII0B.mask(),\n\tASCII0C.mask(), ASCII0D.mask(), ASCII0E.mask(), ASCII0F.mask(),\n\tASCII10.mask(), ASCII11.mask(), ASCII12.mask(), ASCII13.mask(),\n\tASCII14.mask(), ASCII15.mask(), ASCII16.mask(), ASCII17.mask(),\n\tASCII18.mask(), ASCII19.mask(), ASCII1A.mask(), ASCII1B.mask(),\n\tASCII1C.mask(), ASCII1D.mask(), ASCII1E.mask(), ASCII1F.mask(),\n\tASCII20.mask(), ASCII21.mask(), ASCII22.mask(), ASCII23.mask(),\n\tASCII24.mask(), ASCII25.mask(), ASCII26.mask(), ASCII27.mask(),\n\tASCII28.mask(), ASCII29.mask(), ASCII2A.mask(), ASCII2B.mask(),\n\tASCII2C.mask(), ASCII2D.mask(), ASCII2E.mask(), ASCII2F.mask(),\n\tASCII30.mask(), ASCII31.mask(), ASCII32.mask(), ASCII33.mask(),\n\tASCII34.mask(), ASCII35.mask(), ASCII36.mask(), ASCII37.mask(),\n\tASCII38.mask(), ASCII39.mask(), ASCII3A.mask(), ASCII3B.mask(),\n\tASCII3C.mask(), ASCII3D.mask(), ASCII3E.mask(), ASCII3F.mask(),\n\tASCII40.mask(), ASCII41.mask(), ASCII42.mask(), ASCII43.mask(),\n\tASCII44.mask(), ASCII45.mask(), ASCII46.mask(), ASCII47.mask(),\n\tASCII48.mask(), ASCII49.mask(), ASCII4A.mask(), ASCII4B.mask(),\n\tASCII4C.mask(), ASCII4D.mask(), ASCII4E.mask(), ASCII4F.mask(),\n\tASCII50.mask(), ASCII51.mask(), ASCII52.mask(), ASCII53.mask(),\n\tASCII54.mask(), ASCII55.mask(), ASCII56.mask(), ASCII57.mask(),\n\tASCII58.mask(), ASCII59.mask(), ASCII5A.mask(), ASCII5B.mask(),\n\tASCII5C.mask(), ASCII5D.mask(), ASCII5E.mask(), ASCII5F.mask(),\n\tASCII60.mask(), ASCII61.mask(), ASCII62.mask(), ASCII63.mask(),\n\tASCII64.mask(), ASCII65.mask(), ASCII66.mask(), ASCII67.mask(),\n\tASCII68.mask(), ASCII69.mask(), ASCII6A.mask(), ASCII6B.mask(),\n\tASCII6C.mask(), ASCII6D.mask(), ASCII6E.mask(), ASCII6F.mask(),\n\tASCII70.mask(), ASCII71.mask(), ASCII72.mask(), ASCII73.mask(),\n\tASCII74.mask(), ASCII75.mask(), ASCII76.mask(), ASCII77.mask(),\n\tASCII78.mask(), ASCII79.mask(), ASCII7A.mask(), ASCII7B.mask(),\n\tASCII7C.mask(), ASCII7D.mask(), ASCII7E.mask(), ASCII7F.mask(),\n}\n\nvar iso88591 = [...]Keycode{\n\tISO88591A0.mask(), ISO88591A1.mask(), ISO88591A2.mask(), ISO88591A3.mask(),\n\tISO88591A4.mask(), ISO88591A5.mask(), ISO88591A6.mask(), ISO88591A7.mask(),\n\tISO88591A8.mask(), ISO88591A9.mask(), ISO88591AA.mask(), ISO88591AB.mask(),\n\tISO88591AC.mask(), ISO88591AD.mask(), ISO88591AE.mask(), ISO88591AF.mask(),\n\tISO88591B0.mask(), ISO88591B1.mask(), ISO88591B2.mask(), ISO88591B3.mask(),\n\tISO88591B4.mask(), ISO88591B5.mask(), ISO88591B6.mask(), ISO88591B7.mask(),\n\tISO88591B8.mask(), ISO88591B9.mask(), ISO88591BA.mask(), ISO88591BB.mask(),\n\tISO88591BC.mask(), ISO88591BD.mask(), ISO88591BE.mask(), ISO88591BF.mask(),\n\tISO88591C0.mask(), ISO88591C1.mask(), ISO88591C2.mask(), ISO88591C3.mask(),\n\tISO88591C4.mask(), ISO88591C5.mask(), ISO88591C6.mask(), ISO88591C7.mask(),\n\tISO88591C8.mask(), ISO88591C9.mask(), ISO88591CA.mask(), ISO88591CB.mask(),\n\tISO88591CC.mask(), ISO88591CD.mask(), ISO88591CE.mask(), ISO88591CF.mask(),\n\tISO88591D0.mask(), ISO88591D1.mask(), ISO88591D2.mask(), ISO88591D3.mask(),\n\tISO88591D4.mask(), ISO88591D5.mask(), ISO88591D6.mask(), ISO88591D7.mask(),\n\tISO88591D8.mask(), ISO88591D9.mask(), ISO88591DA.mask(), ISO88591DB.mask(),\n\tISO88591DC.mask(), ISO88591DD.mask(), ISO88591DE.mask(), ISO88591DF.mask(),\n\tISO88591E0.mask(), ISO88591E1.mask(), ISO88591E2.mask(), ISO88591E3.mask(),\n\tISO88591E4.mask(), ISO88591E5.mask(), ISO88591E6.mask(), ISO88591E7.mask(),\n\tISO88591E8.mask(), ISO88591E9.mask(), ISO88591EA.mask(), ISO88591EB.mask(),\n\tISO88591EC.mask(), ISO88591ED.mask(), ISO88591EE.mask(), ISO88591EF.mask(),\n\tISO88591F0.mask(), ISO88591F1.mask(), ISO88591F2.mask(), ISO88591F3.mask(),\n\tISO88591F4.mask(), ISO88591F5.mask(), ISO88591F6.mask(), ISO88591F7.mask(),\n\tISO88591F8.mask(), ISO88591F9.mask(), ISO88591FA.mask(), ISO88591FB.mask(),\n\tISO88591FC.mask(), ISO88591FD.mask(), ISO88591FE.mask(), ISO88591FF.mask(),\n}\n"
  },
  {
    "path": "src/machine/usb/hid/mouse/mouse.go",
    "content": "package mouse\n\nimport (\n\t\"machine\"\n\t\"machine/usb/hid\"\n)\n\nvar Mouse *mouse\n\ntype Button byte\n\nconst (\n\tLeft Button = 1 << iota\n\tRight\n\tMiddle\n\tBack\n\tForward\n)\n\ntype mouse struct {\n\tbuf     *hid.RingBuffer\n\tbutton  Button\n\twaitTxc bool\n}\n\nfunc init() {\n\tif Mouse == nil {\n\t\tMouse = newMouse()\n\t\thid.SetHandler(Mouse)\n\t}\n}\n\n// New returns the USB hid-mouse port.\n// Deprecated, better to just use Port()\nfunc New() *mouse {\n\treturn Port()\n}\n\n// Port returns the USB hid-mouse port.\nfunc Port() *mouse {\n\treturn Mouse\n}\n\nfunc newMouse() *mouse {\n\treturn &mouse{\n\t\tbuf: hid.NewRingBuffer(),\n\t}\n}\n\nfunc (m *mouse) TxHandler() bool {\n\tm.waitTxc = false\n\tif b, ok := m.buf.Get(); ok {\n\t\tm.waitTxc = true\n\t\thid.SendUSBPacket(b[:5])\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunc (m *mouse) RxHandler(b []byte) bool {\n\treturn false\n}\n\nfunc (m *mouse) tx(b []byte) {\n\tif machine.USBDev.InitEndpointComplete {\n\t\tif m.waitTxc {\n\t\t\tm.buf.Put(b)\n\t\t} else {\n\t\t\tm.waitTxc = true\n\t\t\thid.SendUSBPacket(b)\n\t\t}\n\t}\n}\n\n// Move is a function that moves the mouse cursor.\nfunc (m *mouse) Move(vx, vy int) {\n\tif vx == 0 && vy == 0 {\n\t\treturn\n\t}\n\n\tif vx < -128 {\n\t\tvx = -128\n\t}\n\tif vx > 127 {\n\t\tvx = 127\n\t}\n\n\tif vy < -128 {\n\t\tvy = -128\n\t}\n\tif vy > 127 {\n\t\tvy = 127\n\t}\n\n\tm.tx([]byte{\n\t\t0x01, byte(m.button), byte(vx), byte(vy), 0x00,\n\t})\n}\n\n// Click clicks the mouse button.\nfunc (m *mouse) Click(btn Button) {\n\tm.Press(btn)\n\tm.Release(btn)\n}\n\n// Press presses the given mouse buttons.\nfunc (m *mouse) Press(btn Button) {\n\tm.button |= btn\n\tm.tx([]byte{\n\t\t0x01, byte(m.button), 0x00, 0x00, 0x00,\n\t})\n}\n\n// Release releases the given mouse buttons.\nfunc (m *mouse) Release(btn Button) {\n\tm.button &= ^btn\n\tm.tx([]byte{\n\t\t0x01, byte(m.button), 0x00, 0x00, 0x00,\n\t})\n}\n\n// Wheel controls the mouse wheel.\nfunc (m *mouse) Wheel(v int) {\n\tif v == 0 {\n\t\treturn\n\t}\n\n\tif v < -128 {\n\t\tv = -128\n\t}\n\tif v > 127 {\n\t\tv = 127\n\t}\n\n\tm.tx([]byte{\n\t\t0x01, byte(m.button), 0x00, 0x00, byte(v),\n\t})\n}\n\n// WheelDown turns the mouse wheel down.\nfunc (m *mouse) WheelDown() {\n\tm.Wheel(-1)\n}\n\n// WheelUp turns the mouse wheel up.\nfunc (m *mouse) WheelUp() {\n\tm.Wheel(1)\n}\n"
  },
  {
    "path": "src/machine/usb/msc/cbw.go",
    "content": "package msc\n\nimport (\n\t\"encoding/binary\"\n\t\"machine/usb/msc/csw\"\n\t\"machine/usb/msc/scsi\"\n)\n\nconst (\n\tcbwMsgLen = 31         // Command Block Wrapper (CBW) message length\n\tSignature = 0x43425355 // \"USBC\" in little endian\n)\n\ntype CBW struct {\n\tHasCmd bool\n\tData   []byte\n}\n\nfunc (c *CBW) Tag() uint32 {\n\treturn binary.LittleEndian.Uint32(c.Data[4:8])\n}\n\nfunc (c *CBW) length() int {\n\treturn len(c.Data)\n}\n\nfunc (c *CBW) validLength() bool {\n\treturn len(c.Data) == cbwMsgLen\n}\n\nfunc (c *CBW) validSignature() bool {\n\treturn binary.LittleEndian.Uint32(c.Data[:4]) == Signature\n}\n\nfunc (c *CBW) SCSICmd() scsi.Cmd {\n\treturn scsi.Cmd{Data: c.Data[15:]}\n}\n\nfunc (c *CBW) transferLength() uint32 {\n\treturn binary.LittleEndian.Uint32(c.Data[8:12])\n}\n\n// isIn returns true if the command direction is from the device to the host.\nfunc (c *CBW) isIn() bool {\n\treturn c.Data[12]>>7 != 0\n}\n\n// isOut returns true if the command direction is from the host to the device.\nfunc (c *CBW) isOut() bool {\n\treturn !c.isIn()\n}\n\nfunc (c *CBW) CSW(status csw.Status, residue uint32, b []byte) {\n\t// Signature: \"USBS\" 53425355h (little endian)\n\tbinary.LittleEndian.PutUint32(b[:4], csw.Signature)\n\t// Tag: (same as CBW)\n\tcopy(b[4:8], c.Data[4:8])\n\t// Data Residue: (untransferred bytes)\n\tbinary.LittleEndian.PutUint32(b[8:12], residue)\n\t// Status:\n\tb[12] = byte(status)\n}\n"
  },
  {
    "path": "src/machine/usb/msc/csw/csw.go",
    "content": "package csw\n\ntype Status uint8\n\nconst (\n\tStatusPassed Status = iota\n\tStatusFailed\n\tStatusPhaseError\n)\n\nconst (\n\tMsgLen    = 13\n\tSignature = 0x53425355 // \"USBS\" in little endian\n)\n"
  },
  {
    "path": "src/machine/usb/msc/disk.go",
    "content": "package msc\n\nimport (\n\t\"encoding/binary\"\n\t\"errors\"\n\t\"fmt\"\n\t\"machine\"\n\t\"time\"\n)\n\nvar (\n\terrWriteOutOfBounds = errors.New(\"WriteAt offset out of bounds\")\n)\n\n// RegisterBlockDevice registers a BlockDevice provider with the MSC driver\nfunc (m *msc) RegisterBlockDevice(dev machine.BlockDevice) {\n\tm.dev = dev\n\n\tif cap(m.blockCache) != int(dev.WriteBlockSize()) {\n\t\tm.blockCache = make([]byte, dev.WriteBlockSize())\n\t\tm.buf = make([]byte, dev.WriteBlockSize())\n\t}\n\n\tm.blockSizeRaw = uint32(m.dev.WriteBlockSize())\n\tm.blockCount = uint32(m.dev.Size()) / m.blockSizeUSB\n\t// Read/write/erase operations must be aligned to the underlying hardware blocks. In order to align\n\t// them we assume the provided block device is aligned to the end of the underlying hardware block\n\t// device and offset all reads/writes by the remaining bytes that don't make up a full block.\n\tm.blockOffset = uint32(m.dev.Size()) % m.blockSizeUSB\n\t// FIXME: Figure out what to do if the emulated write block size is larger than the erase block size\n\n\t// Set VPD UNMAP fields\n\tfor i := range vpdPages {\n\t\tif vpdPages[i].PageCode == 0xb0 {\n\t\t\t// 0xb0 - 5.4.5 Block Limits VPD page (B0h)\n\t\t\tif len(vpdPages[i].Data) >= 28 {\n\t\t\t\t// Set the OPTIMAL UNMAP GRANULARITY (write blocks per erase block)\n\t\t\t\tgranularity := uint32(dev.EraseBlockSize()) / m.blockSizeUSB\n\t\t\t\tbinary.BigEndian.PutUint32(vpdPages[i].Data[24:28], granularity)\n\t\t\t}\n\t\t\tif len(vpdPages[i].Data) >= 32 {\n\t\t\t\t// Set the UNMAP GRANULARITY ALIGNMENT (first sector of first full erase block)\n\t\t\t\t// The unmap granularity alignment is used to calculate an optimal unmap request starting LBA as follows:\n\t\t\t\t// optimal unmap request starting LBA = (n * OPTIMAL UNMAP GRANULARITY) + UNMAP GRANULARITY ALIGNMENT\n\t\t\t\t// where n is zero or any positive integer value\n\t\t\t\t// https://www.seagate.com/files/staticfiles/support/docs/manual/Interface%20manuals/100293068j.pdf\n\n\t\t\t\t// We assume the block device is aligned to the end of the underlying block device\n\t\t\t\tblockOffset := uint32(dev.EraseBlockSize()) % m.blockSizeUSB\n\t\t\t\t// Set the UGAVALID bit to indicate that the UNMAP GRANULARITY ALIGNMENT is valid\n\t\t\t\tblockOffset |= 0x80000000\n\t\t\t\tbinary.BigEndian.PutUint32(vpdPages[i].Data[28:32], blockOffset)\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t}\n}\n\nvar _ machine.BlockDevice = (*RecorderDisk)(nil)\n\n// RecorderDisk is a block device that records actions taken on it\ntype RecorderDisk struct {\n\tdev  machine.BlockDevice\n\tlog  []RecorderRecord\n\tlast time.Time\n\ttime time.Time\n}\n\ntype RecorderRecord struct {\n\tOpCode RecorderOpCode\n\tOffset int64\n\tLength int\n\tData   []byte\n\tTime   int64\n\tvalid  bool\n}\n\ntype RecorderOpCode uint8\n\nconst (\n\tRecorderOpCodeRead RecorderOpCode = iota\n\tRecorderOpCodeWrite\n\tRecorderOpCodeEraseBlocks\n)\n\n// NewRecorderDisk creates a new RecorderDisk instance\nfunc NewRecorderDisk(dev machine.BlockDevice, count int) *RecorderDisk {\n\td := &RecorderDisk{\n\t\tdev:  dev,\n\t\tlog:  make([]RecorderRecord, 0, count),\n\t\tlast: time.Now(),\n\t}\n\tfor i := 0; i < count; i++ {\n\t\td.log = append(d.log, RecorderRecord{\n\t\t\tOpCode: RecorderOpCodeRead,\n\t\t\tOffset: 0,\n\t\t\tLength: 0,\n\t\t\tData:   make([]byte, dev.WriteBlockSize()),\n\t\t\tTime:   0,\n\t\t})\n\t}\n\treturn d\n}\n\nfunc (d *RecorderDisk) Size() int64 {\n\treturn d.dev.Size()\n}\n\nfunc (d *RecorderDisk) WriteBlockSize() int64 {\n\treturn d.dev.WriteBlockSize()\n}\n\nfunc (d *RecorderDisk) EraseBlockSize() int64 {\n\treturn d.dev.EraseBlockSize()\n}\n\nfunc (d *RecorderDisk) EraseBlocks(startBlock, numBlocks int64) error {\n\td.Record(RecorderOpCodeEraseBlocks, startBlock, int(numBlocks), []byte{})\n\treturn d.dev.EraseBlocks(startBlock, numBlocks)\n}\n\nfunc (d *RecorderDisk) ReadAt(buffer []byte, offset int64) (int, error) {\n\tn, err := d.dev.ReadAt(buffer, offset)\n\td.Record(RecorderOpCodeRead, offset, n, buffer)\n\treturn n, err\n}\n\nfunc (d *RecorderDisk) WriteAt(buffer []byte, offset int64) (int, error) {\n\tn, err := d.dev.WriteAt(buffer, offset)\n\td.Record(RecorderOpCodeWrite, offset, n, buffer)\n\treturn n, err\n}\n\nfunc (d *RecorderDisk) Record(opCode RecorderOpCode, offset int64, length int, data []byte) {\n\tn := len(d.log) - 1\n\t// Shift the log entries up to make room for a new entry\n\tfor i := 0; i < n; i++ {\n\t\td.log[i].OpCode = d.log[i+1].OpCode\n\t\td.log[i].Offset = d.log[i+1].Offset\n\t\td.log[i].Length = d.log[i+1].Length\n\t\td.log[i].Data = d.log[i].Data[:len(d.log[i+1].Data)]\n\t\tcopy(d.log[i].Data, d.log[i+1].Data)\n\t\td.log[i].Time = d.log[i+1].Time\n\t\td.log[i].valid = d.log[i+1].valid\n\t}\n\n\t// Append the new record\n\td.log[n].OpCode = opCode\n\td.log[n].Offset = offset\n\td.log[n].Length = length\n\td.log[n].Data = d.log[n].Data[:len(data)]\n\tcopy(d.log[n].Data, data)\n\td.log[n].Time = time.Since(d.time).Microseconds()\n\td.time = d.time.Add(time.Since(d.time))\n\td.log[n].valid = true\n}\n\nfunc (d *RecorderDisk) ClearLog() {\n\tfor i := range d.log {\n\t\td.log[i].valid = false\n\t}\n\td.time = time.Now()\n}\n\nfunc (d *RecorderDisk) GetLog() []RecorderRecord {\n\treturn d.log\n}\n\nfunc (r *RecorderRecord) String() (string, bool) {\n\topCode := \"Unknown\"\n\tswitch r.OpCode {\n\tcase RecorderOpCodeRead:\n\t\topCode = \"Read\"\n\tcase RecorderOpCodeWrite:\n\t\topCode = \"Write\"\n\tcase RecorderOpCodeEraseBlocks:\n\t\topCode = \"EraseBlocks\"\n\t}\n\treturn fmt.Sprintf(\"%s: %05d+%02d t:%d | % 0x\", opCode, r.Offset, r.Length, r.Time, r.Data), r.valid\n}\n"
  },
  {
    "path": "src/machine/usb/msc/msc.go",
    "content": "package msc\n\nimport (\n\t\"machine\"\n\t\"machine/usb\"\n\t\"machine/usb/descriptor\"\n\t\"machine/usb/msc/csw\"\n\t\"machine/usb/msc/scsi\"\n\t\"time\"\n)\n\ntype mscState uint8\n\nconst (\n\tmscStateCmd mscState = iota\n\tmscStateData\n\tmscStateStatus\n\tmscStateStatusSent\n\tmscStateNeedReset\n)\n\nconst (\n\tmscInterface = 2\n)\n\nvar MSC *msc\n\ntype msc struct {\n\tbuf           []byte     // Buffer for incoming/outgoing data\n\tblockCache    []byte     // Buffer for block read/write data\n\ttaskQueued    bool       // Flag to indicate if the buffer has a task queued\n\trxStalled     bool       // Flag to indicate if the RX endpoint is stalled\n\ttxStalled     bool       // Flag to indicate if the TX endpoint is stalled\n\tmaxPacketSize uint32     // Maximum packet size for the IN endpoint\n\trespStatus    csw.Status // Response status for the last command\n\tsendZLP       bool       // Flag to indicate if a zero-length packet should be sent before sending CSW\n\n\tcbw           *CBW   // Last received Command Block Wrapper\n\tqueuedBytes   uint32 // Number of bytes queued for sending\n\tsentBytes     uint32 // Number of bytes sent\n\ttransferBytes uint32 // Total bytes to send\n\tcswBuf        []byte // CSW response buffer\n\tstate         mscState\n\n\tmaxLUN       uint8 // Maximum Logical Unit Number (n-1 for n LUNs)\n\tdev          machine.BlockDevice\n\tblockCount   uint32 // Number of blocks in the device\n\tblockOffset  uint32 // Byte offset of the first block in the device for aligned writes\n\tblockSizeUSB uint32 // Write block size as presented to the host over USB\n\tblockSizeRaw uint32 // Write block size of the underlying device hardware\n\treadOnly     bool\n\n\tvendorID   [8]byte  // Max 8 ASCII characters\n\tproductID  [16]byte // Max 16 ASCII characters\n\tproductRev [4]byte  // Max 4 ASCII characters\n\n\tsenseKey           scsi.Sense\n\taddlSenseCode      scsi.SenseCode\n\taddlSenseQualifier uint8\n}\n\n// Port returns the USB Mass Storage port\nfunc Port(dev machine.BlockDevice) *msc {\n\tif MSC == nil {\n\t\tMSC = newMSC(dev)\n\t}\n\treturn MSC\n}\n\nfunc newMSC(dev machine.BlockDevice) *msc {\n\t// Size our buffer to match the maximum packet size of the IN endpoint\n\tmaxPacketSize := descriptor.EndpointMSCIN.GetMaxPacketSize()\n\tm := &msc{\n\t\t// Some platforms require reads/writes to be aligned to the full underlying hardware block\n\t\tblockCache:    make([]byte, dev.WriteBlockSize()),\n\t\tblockSizeUSB:  512,\n\t\tbuf:           make([]byte, dev.WriteBlockSize()),\n\t\tcswBuf:        make([]byte, csw.MsgLen),\n\t\tcbw:           &CBW{Data: make([]byte, 31)},\n\t\tmaxPacketSize: uint32(maxPacketSize),\n\t}\n\tm.RegisterBlockDevice(dev)\n\n\t// Set default inquiry data fields\n\tm.SetVendorID(\"TinyGo\")\n\tm.SetProductID(\"Mass Storage\")\n\tm.SetProductRev(\"1.0\")\n\n\t// Initialize the USB Mass Storage Class (MSC) port\n\tmachine.ConfigureUSBEndpoint(descriptor.MSC,\n\t\t[]usb.EndpointConfig{\n\t\t\t{\n\t\t\t\tIndex:        usb.MSC_ENDPOINT_IN,\n\t\t\t\tIsIn:         true,\n\t\t\t\tType:         usb.ENDPOINT_TYPE_BULK,\n\t\t\t\tTxHandler:    txHandler,\n\t\t\t\tStallHandler: setupPacketHandler,\n\t\t\t},\n\t\t\t{\n\t\t\t\tIndex:          usb.MSC_ENDPOINT_OUT,\n\t\t\t\tIsIn:           false,\n\t\t\t\tType:           usb.ENDPOINT_TYPE_BULK,\n\t\t\t\tDelayRxHandler: rxHandler,\n\t\t\t\tStallHandler:   setupPacketHandler,\n\t\t\t},\n\t\t},\n\t\t[]usb.SetupConfig{\n\t\t\t{\n\t\t\t\tIndex:   mscInterface,\n\t\t\t\tHandler: setupPacketHandler,\n\t\t\t},\n\t\t},\n\t)\n\n\tgo m.processTasks()\n\n\treturn m\n}\n\nfunc (m *msc) processTasks() {\n\t// Process tasks that cannot be done in an interrupt context\n\tfor {\n\t\tif m.taskQueued {\n\t\t\tcmd := m.cbw.SCSICmd()\n\t\t\tswitch cmd.CmdType() {\n\t\t\tcase scsi.CmdWrite:\n\t\t\t\tm.scsiWrite(cmd, m.buf)\n\t\t\tcase scsi.CmdUnmap:\n\t\t\t\tm.scsiUnmap(m.buf)\n\t\t\t}\n\n\t\t\t// Acknowledge the received data from the host\n\t\t\tm.queuedBytes = 0\n\t\t\tm.taskQueued = false\n\t\t\tmachine.AckUsbOutTransfer(usb.MSC_ENDPOINT_OUT)\n\t\t}\n\t\ttime.Sleep(100 * time.Microsecond)\n\t}\n}\n\nfunc (m *msc) ready() bool {\n\treturn m.dev != nil\n}\n\nfunc (m *msc) resetBuffer(length int) {\n\t// Reset the buffer to the specified length\n\tm.buf = m.buf[:length]\n\tfor i := 0; i < length; i++ {\n\t\tm.buf[i] = 0\n\t}\n}\n\nfunc (m *msc) sendUSBPacket(b []byte) {\n\tif machine.USBDev.InitEndpointComplete {\n\t\t// Send the USB packet\n\t\tmachine.SendUSBInPacket(usb.MSC_ENDPOINT_IN, b)\n\t}\n}\n\nfunc (m *msc) sendCSW(status csw.Status) {\n\t// Generate CSW packet into m.cswBuf and send it\n\tresidue := uint32(0)\n\texpected := m.cbw.transferLength()\n\tif expected >= m.sentBytes {\n\t\tresidue = expected - m.sentBytes\n\t}\n\tm.cbw.CSW(status, residue, m.cswBuf)\n\tm.state = mscStateStatusSent\n\tm.sendUSBPacket(m.cswBuf)\n}\n\nfunc txHandler() {\n\tif MSC != nil {\n\t\tMSC.txHandler()\n\t}\n}\n\nfunc (m *msc) txHandler() {\n\tm.run([]byte{}, false)\n}\n\nfunc rxHandler(b []byte) bool {\n\tack := true\n\tif MSC != nil {\n\t\tack = MSC.run(b, true)\n\t}\n\treturn ack\n}\n\n/*\n\tConnection Happy Path Overview:\n\n0. MSC starts out in mscStateCmd status.\n\n1. Host sends CBW (Command Block Wrapper) packet to MSC.\n  - CBW contains the SCSI command to be executed, the length of the data to be transferred, etc.\n\n2. MSC receives CBW.\n  - CBW is validated and saved.\n  - State is changed to mscStateData.\n  - MSC routes the command to the appropriate SCSI command handler.\n\n3. The MSC SCSI command handler responds with the initial data packet (if applicable).\n  - If no data packet is needed, state is changed to mscStateStatus and step 4 is skipped.\n\n4. The host acks the data packet and MSC calls m.scsiDataTransfer() to continue sending (or\nreceiving) data.\n  - This cycle continues until all data requested in the CBW is sent/received.\n  - State is changed to mscStateStatus.\n  - MSC waits for the host to ACK the final data packet.\n\n5. MSC then sends a CSW (Command Status Wrapper) to the host to report the final status of the\ncommand execution and moves to mscStateStatusSent.\n\n6. The host ACKs the CSW and the MSC moves back to mscStateCmd, waiting for the next CBW.\n*/\nfunc (m *msc) run(b []byte, isEpOut bool) bool {\n\tack := true\n\n\tswitch m.state {\n\tcase mscStateCmd:\n\t\t// Receiving a new command block wrapper (CBW)\n\n\t\t// IN endpoint transfer complete confirmation, no action needed\n\t\tif !isEpOut {\n\t\t\treturn ack\n\t\t}\n\n\t\t// Create a temporary CBW wrapper to validate the incoming data. Has to be temporary\n\t\t// to avoid it escaping into the heap since we're in interrupt context\n\t\tcbw := CBW{Data: b}\n\n\t\t// Verify size and signature\n\t\tif !cbw.validLength() || !cbw.validSignature() {\n\t\t\t// 6.6.1 CBW Not Valid\n\t\t\t// https://usb.org/sites/default/files/usbmassbulk_10.pdf\n\t\t\tm.state = mscStateNeedReset\n\t\t\tm.stallEndpoint(usb.MSC_ENDPOINT_IN)\n\t\t\tm.stallEndpoint(usb.MSC_ENDPOINT_OUT)\n\t\t\tm.stallEndpoint(usb.CONTROL_ENDPOINT)\n\t\t\treturn ack\n\t\t}\n\n\t\t// Save the validated CBW for later reference\n\t\tcopy(m.cbw.Data, b)\n\n\t\t// Move on to the data transfer phase next go around (after sending the first message)\n\t\tm.state = mscStateData\n\t\tm.transferBytes = cbw.transferLength()\n\t\tm.queuedBytes = 0\n\t\tm.sentBytes = 0\n\t\tm.respStatus = csw.StatusPassed\n\n\t\tm.scsiCmdBegin()\n\n\tcase mscStateData:\n\t\t// Transfer data\n\t\tack = m.scsiDataTransfer(b)\n\n\tcase mscStateStatus:\n\t// Sending CSW status response\n\t// Placed after the switch statement so we can send the CSW without having to send a packet\n\t// to cycle back through this block, e.g. with TEST UNIT READY which sends only a CSW after\n\t// setting the sense key/add'l code/qualifier internally\n\n\tcase mscStateStatusSent:\n\t\t// Wait for the status phase to complete\n\t\tif !isEpOut && m.queuedBytes == csw.MsgLen {\n\t\t\t// Status confirmed sent, wait for next CBW\n\t\t\tm.state = mscStateCmd\n\t\t} else {\n\t\t\t// We're not expecting any data here, ignore it. Original log line:\n\t\t\t// TU_LOG1(\"  Warning expect SCSI Status but received unknown data\\r\\n\");\n\t\t}\n\n\tcase mscStateNeedReset:\n\t\t// Received an invalid CBW message, stop everything until we get reset\n\t}\n\n\t// Send CSW status response\n\t// Placed after the switch statement so we can send the CSW without having to send a packet\n\t// to cycle back through this block, e.g. with TEST UNIT READY which sends only a CSW after\n\t// setting the sense key/add'l code/qualifier internally\n\tif m.state == mscStateStatus && !m.txStalled {\n\t\tif m.cbw.transferLength() > m.sentBytes && m.cbw.isIn() {\n\t\t\t// 6.7.2 The Thirteen Cases - Case 5 (Hi > Di): STALL before status\n\t\t\tm.stallEndpoint(usb.MSC_ENDPOINT_IN)\n\t\t} else if m.sendZLP {\n\t\t\t// Send a zero-length packet to force the end of the transfer before we send a CSW\n\t\t\tm.queuedBytes = 0\n\t\t\tm.sendZLP = false\n\t\t\tm.sendUSBPacket(m.buf[:0])\n\t\t} else {\n\t\t\tm.sendCSW(m.respStatus)\n\t\t\tm.state = mscStateCmd\n\t\t}\n\t}\n\n\treturn ack\n}\n"
  },
  {
    "path": "src/machine/usb/msc/scsi/scsi.go",
    "content": "package scsi\n\nimport (\n\t\"encoding/binary\"\n\t\"fmt\"\n)\n\ntype Cmd struct {\n\tData []byte\n}\n\nfunc (c *Cmd) CmdType() CmdType {\n\treturn CmdType(c.Data[0])\n}\n\nfunc (c *Cmd) BlockCount() uint32 {\n\treturn uint32(binary.BigEndian.Uint16(c.Data[7:9]))\n}\n\nfunc (c *Cmd) LBA() uint32 {\n\treturn binary.BigEndian.Uint32(c.Data[2:6])\n}\n\nfunc (c Cmd) String() string {\n\tcmdType := c.CmdType()\n\tswitch cmdType {\n\tcase CmdRead:\n\t\treturn fmt.Sprintf(\"%-28s LBA: % 3d, Block Count: %d\", cmdType, c.LBA(), c.BlockCount())\n\tcase CmdWrite:\n\t\treturn fmt.Sprintf(\"%-28s LBA: % 3d, Block Count: %d\", cmdType, c.LBA(), c.BlockCount())\n\tdefault:\n\t\treturn fmt.Sprintf(\"%-28s % x\", cmdType, c.Data)\n\t}\n}\n\ntype CmdType uint8\n\nconst (\n\tCmdTestUnitReady             CmdType = 0x00 // TEST UNIT READY is used to determine if a device is ready to transfer data (read/write). The device does not perform a self-test operation\n\tCmdRequestSense              CmdType = 0x03 // REQUEST SENSE returns the current sense data (status or error information)\n\tCmdInquiry                   CmdType = 0x12 // INQUIRY is used to obtain basic information from a target device\n\tCmdModeSelect6               CmdType = 0x15 // MODE SELECT (6) provides a means for the application client to specify medium, logical unit, or peripheral device parameters to the device server\n\tCmdModeSelect10              CmdType = 0x55 // MODE SELECT (10) provides a means for the application client to specify medium, logical unit, or peripheral device parameters to the device server\n\tCmdModeSense6                CmdType = 0x1A // MODE SENSE (6) provides a means for a device server to report parameters to an application client\n\tCmdModeSense10               CmdType = 0x5A // MODE SENSE (10) provides a means for a device server to report parameters to an application client with 64-bit logical block addressing\n\tCmdStartStopUnit             CmdType = 0x1B // START STOP UNIT is used to start or stop the medium in a device server\n\tCmdPreventAllowMediumRemoval CmdType = 0x1E // PREVENT ALLOW MEDIUM REMOVAL is used to prevent or allow the removal of storage medium from a device server\n\tCmdReadFormatCapacity        CmdType = 0x23 // READ FORMAT CAPACITY allows the Host to request a list of the possible format capacities for an installed writable media\n\tCmdReadCapacity              CmdType = 0x25 // READ CAPACITY command is used to obtain data capacity information from a target device\n\tCmdRead                      CmdType = 0x28 // READ (10) requests that the device server read the specified logical block(s) and transfer them to the data-in buffer\n\tCmdWrite                     CmdType = 0x2A // WRITE (10) requests that the device server transfer the specified logical block(s) from the data-out buffer and write them\n\tCmdUnmap                     CmdType = 0x42 // UNMAP command is used to inform the device server that the specified logical block(s) are no longer in use\n)\n\nfunc (c CmdType) String() string {\n\tswitch c {\n\tcase CmdTestUnitReady:\n\t\treturn \"TEST UNIT READY\"\n\tcase CmdRequestSense:\n\t\treturn \"REQUEST SENSE\"\n\tcase CmdInquiry:\n\t\treturn \"INQUIRY\"\n\tcase CmdModeSelect6:\n\t\treturn \"MODE SELECT (6)\"\n\tcase CmdModeSelect10:\n\t\treturn \"MODE SELECT (10)\"\n\tcase CmdModeSense6:\n\t\treturn \"MODE SENSE (6)\"\n\tcase CmdModeSense10:\n\t\treturn \"MODE SENSE (10)\"\n\tcase CmdStartStopUnit:\n\t\treturn \"START STOP UNIT\"\n\tcase CmdPreventAllowMediumRemoval:\n\t\treturn \"PREVENT ALLOW MEDIUM REMOVAL\"\n\tcase CmdReadFormatCapacity:\n\t\treturn \"READ FORMAT CAPACITY\"\n\tcase CmdReadCapacity:\n\t\treturn \"READ CAPACITY\"\n\tcase CmdRead:\n\t\treturn \"READ (10)\"\n\tcase CmdWrite:\n\t\treturn \"WRITE (10)\"\n\tcase CmdUnmap:\n\t\treturn \"UNMAP\"\n\tdefault:\n\t\treturn fmt.Sprintf(\"Unknown Command (0x%0x)\", byte(c))\n\t}\n}\n\ntype Sense uint8\n\nconst (\n\t// 4.5.6 Sense key and sense code definitions\n\t// https://www.t10.org/ftp/t10/document.08/08-309r0.pdf\n\tSenseNone           Sense = 0x00 // No specific Sense Key. This indicates no error condition\n\tSenseRecoveredError Sense = 0x01 // The last command completed successfully, but with some recovery action performed\n\tSenseNotReady       Sense = 0x02 // The LUN addressed is not ready to be accessed\n\tSenseMediumError    Sense = 0x03 // The command terminated with an unrecoverable error condition\n\tSenseHardwareError  Sense = 0x04 // The drive detected an unrecoverable hardware failure while performing the command or during a self test\n\tSenseIllegalRequest Sense = 0x05 // An illegal parameter was provided in the command descriptor block or the additional parameters\n\tSenseUnitAttention  Sense = 0x06 // The disk drive may have been reset\n\tSenseDataProtect    Sense = 0x07 // A read or write command was attempted on a block that is protected from this operation and was not performed\n\tSenseBlankCheck     Sense = 0x08 // A write-once device or a sequential-access device encountered blank medium or format-defined end-of-data indication while reading or that a write-once device encountered a non-blank medium while writing\n\tSenseFirmwareError  Sense = 0x09 // Vendor specific sense key\n\tSenseAbortedCommand Sense = 0x0B // The disk drive aborted the command\n\tSenseVolumeOverflow Sense = 0x0D // A buffered peripheral device has reached the end of medium partition and data remains in the buffer that has not been written to the medium\n\tSenseMiscompare     Sense = 0x0E // The source data did not match the data read from the medium\n)\n\ntype SenseCode uint8\n\nconst (\n\t// SenseNotReady\n\tSenseCodeMediumNotPresent SenseCode = 0x3A // The storage medium is not present in the device (e.g. empty CD-ROM drive or flash card reader)\n\n\t// SenseIllegalRequest\n\tSenseCodeInvalidCmdOpCode  SenseCode = 0x20 // The command operation code is not supported by the device\n\tSenseCodeInvalidFieldInCDB SenseCode = 0x24 // The command descriptor block (CDB) contains an invalid field\n\n\t// SenseDataProtect\n\tSenseCodeWriteProtected SenseCode = 0x27 // The media is write protected\n\n\t// SenseAbortedCommand\n\tSenseCodeLUNCommFailure      SenseCode = 0x08 // LUN communication failure\n\tSenseCodeAbortedCmd          SenseCode = 0x0B // The command was aborted by the device\n\tSenseCodeMsgReject           SenseCode = 0x43 // The command was rejected by the device\n\tSenseCodeOverlapCmdAttempted SenseCode = 0x4E // The command was rejected by the device because it was overlapped by another command\n\n\t// SenseVolumeOverflow\n\tSenseCodeLBAOutOfRange SenseCode = 0x21 // The logical block address (LBA) is beyond the end of the volume\n)\n\nconst (\n\tInquiryRespLen            = 36\n\tModeSense6RespLen         = 4\n\tModeSense10RespLen        = 8\n\tReadCapacityRespLen       = 8\n\tReadFormatCapacityRespLen = 12\n\tRequestSenseRespLen       = 18\n)\n"
  },
  {
    "path": "src/machine/usb/msc/scsi.go",
    "content": "package msc\n\nimport (\n\t\"encoding/binary\"\n\t\"machine/usb\"\n\t\"machine/usb/msc/csw\"\n\t\"machine/usb/msc/scsi\"\n)\n\nfunc (m *msc) scsiCmdBegin() {\n\tcmd := m.cbw.SCSICmd()\n\tcmdType := cmd.CmdType()\n\n\t// Handle multi-packet commands\n\tswitch cmdType {\n\tcase scsi.CmdRead, scsi.CmdWrite:\n\t\tm.scsiCmdReadWrite(cmd)\n\t\treturn\n\tcase scsi.CmdUnmap:\n\t\tm.scsiCmdUnmap(cmd)\n\t\treturn\n\t}\n\n\tif m.transferBytes > 0 && m.cbw.isOut() {\n\t\t// Reject any other multi-packet commands\n\t\tif m.transferBytes > m.maxPacketSize {\n\t\t\tm.sendScsiError(csw.StatusFailed, scsi.SenseIllegalRequest, scsi.SenseCodeInvalidCmdOpCode)\n\t\t\treturn\n\t\t} else {\n\t\t\t// Original comment from TinyUSB:\n\t\t\t// Didn't check for case 9 (Ho > Dn), which requires examining scsi command first\n\t\t\t// but it is OK to just receive data then responded with failed status\n\t\t}\n\t}\n\tswitch cmdType {\n\tcase scsi.CmdTestUnitReady:\n\t\tm.scsiTestUnitReady()\n\tcase scsi.CmdReadCapacity:\n\t\tm.scsiCmdReadCapacity(cmd)\n\tcase scsi.CmdReadFormatCapacity:\n\t\tm.scsiCmdReadFormatCapacity(cmd)\n\tcase scsi.CmdInquiry:\n\t\tm.scsiCmdInquiry(cmd)\n\tcase scsi.CmdModeSense6, scsi.CmdModeSense10:\n\t\tm.scsiCmdModeSense(cmd)\n\tcase scsi.CmdRequestSense:\n\t\tm.scsiCmdRequestSense()\n\tcase scsi.CmdPreventAllowMediumRemoval:\n\t\tm.scsiCmdPreventAllowMediumRemoval(cmd)\n\tdefault:\n\t\t// We don't support this command, error out\n\t\tm.sendScsiError(csw.StatusFailed, scsi.SenseIllegalRequest, scsi.SenseCodeInvalidCmdOpCode)\n\t}\n\n\tif len(m.buf) == 0 {\n\t\tif m.transferBytes > 0 {\n\t\t\t// 6.7.2 The Thirteen Cases - Case 4 (Hi > Dn)\n\t\t\t// https://usb.org/sites/default/files/usbmassbulk_10.pdf\n\t\t\tm.sendScsiError(csw.StatusFailed, scsi.SenseIllegalRequest, 0)\n\t\t} else {\n\t\t\t// 6.7.1 The Thirteen Cases - Case 1 Hn = Dn: all good\n\t\t\t// https://usb.org/sites/default/files/usbmassbulk_10.pdf\n\t\t\tm.state = mscStateStatus\n\t\t}\n\t} else {\n\t\tif m.transferBytes == 0 {\n\t\t\t// 6.7.1 The Thirteen Cases - Case 2 (Hn < Di)\n\t\t\t// https://usb.org/sites/default/files/usbmassbulk_10.pdf\n\t\t\tm.sendScsiError(csw.StatusFailed, scsi.SenseIllegalRequest, 0)\n\t\t} else {\n\t\t\t// Make sure we don't return more data than the host is expecting\n\t\t\tif m.cbw.transferLength() < uint32(len(m.buf)) {\n\t\t\t\tm.buf = m.buf[:m.cbw.transferLength()]\n\t\t\t}\n\t\t\tm.queuedBytes = uint32(len(m.buf))\n\t\t\tm.sendUSBPacket(m.buf)\n\t\t}\n\t}\n}\n\nfunc (m *msc) scsiDataTransfer(b []byte) bool {\n\tcmd := m.cbw.SCSICmd()\n\tcmdType := cmd.CmdType()\n\n\tswitch cmdType {\n\tcase scsi.CmdWrite, scsi.CmdUnmap:\n\t\tif m.readOnly {\n\t\t\tm.sendScsiError(csw.StatusFailed, scsi.SenseDataProtect, scsi.SenseCodeWriteProtected)\n\t\t\treturn true\n\t\t}\n\t\treturn m.scsiQueueTask(cmdType, b)\n\t}\n\n\t// Update our sent bytes count to include the just-confirmed bytes\n\tm.sentBytes += m.queuedBytes\n\n\tif m.sentBytes >= m.transferBytes {\n\t\t// Transfer complete, send CSW after transfer confirmed\n\t\tm.state = mscStateStatus\n\t} else if cmdType == scsi.CmdRead {\n\t\tm.scsiRead(cmd)\n\t} else {\n\t\t// Other multi-packet commands are rejected in m.scsiCmdBegin()\n\t}\n\n\treturn true\n}\n\nfunc (m *msc) scsiTestUnitReady() {\n\tm.resetBuffer(0)\n\tm.queuedBytes = 0\n\n\t// Check if the device is ready\n\tif !m.ready() {\n\t\t// If not ready set sense data\n\t\tm.senseKey = scsi.SenseNotReady\n\t\tm.addlSenseCode = scsi.SenseCodeMediumNotPresent\n\t\tm.addlSenseQualifier = 0x00\n\t} else {\n\t\tm.senseKey = 0\n\t\tm.addlSenseCode = 0\n\t\tm.addlSenseQualifier = 0\n\t}\n}\n\nfunc (m *msc) scsiCmdReadCapacity(cmd scsi.Cmd) {\n\tm.resetBuffer(scsi.ReadCapacityRespLen)\n\tm.queuedBytes = scsi.ReadCapacityRespLen\n\n\t// Last LBA address (big endian)\n\tbinary.BigEndian.PutUint32(m.buf[:4], m.blockCount-1)\n\t// Block size (big endian)\n\tbinary.BigEndian.PutUint32(m.buf[4:8], m.blockSizeUSB)\n}\n\nfunc (m *msc) scsiCmdReadFormatCapacity(cmd scsi.Cmd) {\n\tm.resetBuffer(scsi.ReadFormatCapacityRespLen)\n\tm.queuedBytes = scsi.ReadFormatCapacityRespLen\n\n\t// bytes 0-2 - reserved\n\tm.buf[3] = 8 // Capacity list length\n\n\t// Number of blocks (big endian)\n\tbinary.BigEndian.PutUint32(m.buf[4:8], m.blockCount)\n\t// Block size (24-bit, big endian)\n\tbinary.BigEndian.PutUint32(m.buf[8:12], m.blockSizeUSB)\n\t// Descriptor Type - formatted media\n\tm.buf[8] = 2\n}\n\n// MODE SENSE(6) / MODE SENSE(10) - Only used here to indicate that the device is write protected\nfunc (m *msc) scsiCmdModeSense(cmd scsi.Cmd) {\n\trespLen := uint32(scsi.ModeSense6RespLen)\n\tif cmd.CmdType() == scsi.CmdModeSense10 {\n\t\trespLen = scsi.ModeSense10RespLen\n\t}\n\tm.resetBuffer(int(respLen))\n\tm.queuedBytes = respLen\n\n\t// The host allows a good amount of leeway in response size\n\t// Reset total bytes to what we'll actually send\n\tif m.transferBytes > respLen {\n\t\tm.transferBytes = respLen\n\t\tm.sendZLP = true\n\t}\n\n\treadOnly := byte(0)\n\tif m.readOnly {\n\t\treadOnly = 0x80\n\t}\n\n\tswitch cmd.CmdType() {\n\tcase scsi.CmdModeSense6:\n\t\t// byte 0 - Number of bytes after this one\n\t\tm.buf[0] = byte(respLen) - 1\n\t\t// byte 1 - Medium type (0x00 for direct access block device)\n\t\t// Bit 7 indicates write protected\n\t\tm.buf[2] = readOnly\n\t\t// byte 3 - Block descriptor length: 0 (not supported)\n\tcase scsi.CmdModeSense10:\n\t\t// bytes 0-1 - Number of bytes after this one\n\t\tm.buf[1] = byte(respLen) - 2\n\t\t// byte 2 - Medium type (0x00 for direct access block device)\n\t\t// Bit 7 indicates write protected\n\t\tm.buf[3] = readOnly\n\t}\n}\n\n// PREVENT/ALLOW MEDIUM REMOVAL - A flash drive doesn't have a removable medium, so this is a no-op\nfunc (m *msc) scsiCmdPreventAllowMediumRemoval(cmd scsi.Cmd) {\n\tm.resetBuffer(0)\n\tm.queuedBytes = 0\n\n\t// Check if the device is ready\n\tif !m.ready() {\n\t\t// If not ready set sense data\n\t\tm.senseKey = scsi.SenseNotReady\n\t\tm.addlSenseCode = scsi.SenseCodeMediumNotPresent\n\t\tm.addlSenseQualifier = 0x00\n\t} else {\n\t\tm.senseKey = 0\n\t\tm.addlSenseCode = 0\n\t\tm.addlSenseQualifier = 0\n\t}\n\n\tm.state = mscStateStatus\n}\n\n// REQUEST SENSE - Returns error status codes when an error status is sent\nfunc (m *msc) scsiCmdRequestSense() {\n\t// Set the buffer size to the SCSI sense message size and clear\n\tm.resetBuffer(scsi.RequestSenseRespLen)\n\tm.queuedBytes = scsi.RequestSenseRespLen\n\tm.transferBytes = scsi.RequestSenseRespLen\n\n\t// 0x70 - current error, 0x71 - deferred error (not used)\n\tm.buf[0] = 0xF0 // 0x70 for current error plus 0x80 for valid flag bit\n\t// byte 1 - reserved\n\tm.buf[2] = uint8(m.senseKey) & 0x0F // Incorrect Length Indicator bit not supported\n\t// bytes 3-6 - Information (not used)\n\t// byte 7 - Additional Sense Length (bytes remaining in the message)\n\tm.buf[7] = scsi.RequestSenseRespLen - 8\n\t// bytes 8-11 - Command Specific Information (not used)\n\tm.buf[12] = byte(m.addlSenseCode) // Additional Sense Code (optional)\n\tm.buf[13] = m.addlSenseQualifier  // Additional Sense Code Qualifier (optional)\n\t// bytes 14-17 - reserved\n\n\t// Clear sense data after copied to buffer\n\tm.senseKey = 0\n\tm.addlSenseCode = 0\n\tm.addlSenseQualifier = 0\n}\n\nfunc (m *msc) scsiCmdUnmap(cmd scsi.Cmd) {\n\t// Unmap sends a header in the CBW and a parameter list in the data stage\n\t// The parameter list has an 8 byte header and 16 bytes per item. If it's less than 24 bytes it's\n\t// not the format we're expecting and we won't be able to decode it. Same for if there isn't a\n\t// 8 byte header plus multiples of 16 bytes after that\n\tparamLen := binary.BigEndian.Uint16(m.cbw.Data[7:9])\n\tif paramLen < 24 || (paramLen-8)%16 != 0 {\n\t\tm.sendScsiError(csw.StatusFailed, scsi.SenseIllegalRequest, scsi.SenseCodeInvalidFieldInCDB)\n\t\treturn\n\t}\n}\n\nfunc (m *msc) scsiQueueTask(cmdType scsi.CmdType, b []byte) bool {\n\t// Check if the incoming data is larger than our buffer\n\tif int(m.queuedBytes)+len(b) > cap(m.buf) {\n\t\tm.sendScsiError(csw.StatusFailed, scsi.SenseIllegalRequest, scsi.SenseCodeInvalidFieldInCDB)\n\t\treturn true\n\t}\n\n\t// Save the incoming data in our buffer for processing outside of interrupt context.\n\tif m.taskQueued {\n\t\t// If we already have a full task queue we can't accept this data\n\t\tm.sendScsiError(csw.StatusFailed, scsi.SenseAbortedCommand, scsi.SenseCodeMsgReject)\n\t\treturn true\n\t}\n\n\t// Copy the queued task data into our buffer\n\tstart := m.queuedBytes\n\tend := start + uint32(len(b))\n\tm.buf = m.buf[:end]\n\tcopy(m.buf[start:end], b)\n\tm.queuedBytes += uint32(len(b))\n\n\tswitch cmdType {\n\tcase scsi.CmdWrite:\n\t\t// If we're writing data wait until we have a full write block of data that can be processed.\n\t\tif m.queuedBytes == uint32(cap(m.blockCache)) || (m.sentBytes+m.queuedBytes >= m.transferBytes) {\n\t\t\tm.taskQueued = true\n\t\t}\n\tcase scsi.CmdUnmap:\n\t\tm.taskQueued = true\n\t}\n\n\t// Don't acknowledge the incoming data until we can process it.\n\treturn !m.taskQueued\n}\n\nfunc (m *msc) sendScsiError(status csw.Status, key scsi.Sense, code scsi.SenseCode) {\n\t// Generate CSW into m.cswBuf\n\texpected := m.cbw.transferLength()\n\tresidue := uint32(0)\n\tif expected > m.sentBytes {\n\t\tresidue = expected - m.sentBytes\n\t}\n\n\t// Prepare to send CSW\n\tm.sendZLP = true // Ensure the transaction is signaled as ended before a CSW is sent\n\tm.respStatus = status\n\tm.state = mscStateStatus\n\n\t// Set the sense data\n\tm.senseKey = key\n\tm.addlSenseCode = code\n\tm.addlSenseQualifier = 0x00 // Not used\n\n\tif expected > 0 && residue > 0 {\n\t\tif m.cbw.isIn() {\n\t\t\tm.stallEndpoint(usb.MSC_ENDPOINT_IN)\n\t\t} else {\n\t\t\tm.stallEndpoint(usb.MSC_ENDPOINT_OUT)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/machine/usb/msc/scsi_inquiry.go",
    "content": "package msc\n\nimport (\n\t\"encoding/binary\"\n\t\"machine/usb/msc/csw\"\n\t\"machine/usb/msc/scsi\"\n)\n\ntype vpdPage struct {\n\tPageCode   uint8\n\tPageLength uint8\n\t// Page data\n\t// First four bytes are always Device Type, Page Code, and Page Length (2 bytes) and are omitted here\n\tData []byte\n}\n\n// These must be sorted in ascending order by PageCode\nvar vpdPages = []vpdPage{\n\t{\n\t\t// 0xb0 - 5.4.5 Block Limits VPD page (B0h)\n\t\t// https://www.seagate.com/files/staticfiles/support/docs/manual/Interface%20manuals/100293068j.pdf\n\t\tPageCode:   0xb0,\n\t\tPageLength: 0x3c, // 60 bytes\n\t\tData: []byte{\n\t\t\t0x00, 0x00, // WSNZ, MAXIMUM COMPARE AND WRITE LENGTH - Not supported\n\t\t\t0x00, 0x00, // OPTIMAL TRANSFER LENGTH GRANULARITY - Not supported\n\t\t\t0x00, 0x00, 0x00, 0x00, // MAXIMUM TRANSFER LENGTH - Not supported\n\t\t\t0x00, 0x00, 0x00, 0x00, // OPTIMAL TRANSFER LENGTH - Not supported\n\t\t\t0x00, 0x00, 0x00, 0x00, // MAXIMUM PREFETCH LENGTH - Not supported\n\t\t\t0xFF, 0xFF, 0xFF, 0xFF, // MAXIMUM UNMAP LBA COUNT - Maximum count supported\n\t\t\t0x00, 0x00, 0x00, 0x03, // MAXIMUM UNMAP BLOCK DESCRIPTOR COUNT - Max 3 descriptors\n\t\t\t0x00, 0x00, 0x00, 0x00, // OPTIMAL UNMAP GRANULARITY\n\t\t\t0x00, 0x00, 0x00, 0x00, // UNMAP GRANULARITY ALIGNMENT (bit 7 on byte 28 sets UGAVALID)\n\t\t\t// From here on all bytes are zero and can be omitted from the response\n\t\t\t// 0x00, 0x00, 0x00, 0x00, // MAXIMUM WRITE SAME LENGTH - Not supported\n\t\t\t// 0x00, 0x00, 0x00, 0x00, // (8-bytes)\n\t\t\t// 0x00, 0x00, 0x00, 0x00, // MAXIMUM ATOMIC TRANSFER LENGTH - Not supported\n\t\t\t// 0x00, 0x00, 0x00, 0x00, // ATOMIC ALIGNMENT - Not supported\n\t\t\t// 0x00, 0x00, 0x00, 0x00, // ATOMIC TRANSFER LENGTH GRANULARITY - Not supported\n\t\t\t// 0x00, 0x00, 0x00, 0x00, // MAXIMUM ATOMIC TRANSFER LENGTH WITH ATOMIC BOUNDARY - Not supported\n\t\t\t// 0x00, 0x00, 0x00, 0x00, // MAXIMUM ATOMIC BOUNDARY SIZE - Not supported\n\t\t},\n\t},\n\t{\n\t\t// 0xb1 - 5.4.3 Block Device Characteristics VPD page (B1h)\n\t\t// https://www.seagate.com/files/staticfiles/support/docs/manual/Interface%20manuals/100293068j.pdf\n\t\tPageCode:   0xb1,\n\t\tPageLength: 0x3c, // 60 bytes (bytes 9+ are all reserved/zero)\n\t\tData: []byte{\n\t\t\t0x00, 0x01, // Rotation rate (0x0001 - non-rotating medium)\n\t\t\t0x00, // Product type - 0x00: Not indicated, 0x04: MMC/eMMC, 0x05: SD card\n\t\t\t0x00, // WABEREQ/WACEREQ/Form Factor - Not specified\n\t\t\t0x00, // ZBC/BOCS/FUAB/VBULS\n\t\t\t// Reserved (55 bytes)\n\t\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t\t\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t\t\t0x00, 0x00, 0x00, 0x00, 0x00,\n\t\t},\n\t},\n\t{\n\t\t// 0xb2 - 5.4.13 Logical Block Provisioning VPD page (B2h)\n\t\t// https://www.seagate.com/files/staticfiles/support/docs/manual/Interface%20manuals/100293068j.pdf\n\t\tPageCode:   0xB2,\n\t\tPageLength: 0x04,\n\t\tData: []byte{\n\t\t\t0x00, // Logical Block Provisioning Threshold Exponent\n\t\t\t0x80, // 0x80 - LBPU (UNMAP command supported)\n\t\t\t0x00, // Minimum percentage/Provisioning type - Not specified\n\t\t\t0x00, // Threshold percentage - Not supported\n\t\t},\n\t},\n}\n\nfunc (m *msc) scsiCmdInquiry(cmd scsi.Cmd) {\n\tevpd := cmd.Data[1] & 0x01\n\tpageCode := cmd.Data[2]\n\n\t// PAGE CODE (byte 2) can't be set if the EVPD bit is not set\n\tif evpd == 0 {\n\t\tif pageCode == 0 {\n\t\t\t// Standard INQUIRY command\n\t\t\tm.scsiStdInquiry(cmd)\n\t\t} else {\n\t\t\t// 3.6.1 INQUIRY command introduction\n\t\t\t// https://www.seagate.com/files/staticfiles/support/docs/manual/Interface%20manuals/100293068j.pdf\n\t\t\tm.sendScsiError(csw.StatusFailed, scsi.SenseIllegalRequest, scsi.SenseCodeInvalidFieldInCDB)\n\t\t\treturn\n\t\t}\n\t} else {\n\t\tm.scsiEvpdInquiry(cmd, pageCode)\n\t}\n}\n\nfunc (m *msc) scsiEvpdInquiry(cmd scsi.Cmd, pageCode uint8) {\n\tvar pageLength int\n\tswitch pageCode {\n\tcase 0x00:\n\t\t// 5.4.18 Supported Vital Product Data pages (00h)\n\t\t// https://www.seagate.com/files/staticfiles/support/docs/manual/Interface%20manuals/100293068j.pdf\n\n\t\tpageLength = len(vpdPages) + 1 // Number of pages + 1 for 0x00 (excluded from vpdPages[])\n\t\tm.resetBuffer(pageLength + 4)  // n+4 supported VPD pages\n\t\t// bytes 4+ - Supported VPD pages in ascending order\n\t\tfor i := 0; i < len(vpdPages); i++ {\n\t\t\tm.buf[4+i] = vpdPages[i].PageCode\n\t\t}\n\tdefault:\n\t\tfound := false\n\t\tfor i := range vpdPages {\n\t\t\tif vpdPages[i].PageCode == pageCode {\n\t\t\t\t// Our advertised page length is \"for entertainment use only\". Some pages have dozens of\n\t\t\t\t// reserved (zero) bytes at the end that don't actually need to be sent. If we omit them\n\t\t\t\t// from our response they are (correctly) presumed to be zero bytes by the host\n\t\t\t\tpageLength = int(vpdPages[i].PageLength)\n\t\t\t\t// We actually just send the length of the bytes we have plus the same four byte header,\n\t\t\t\t// but declare the length of the response according to the spec as appropriate\n\t\t\t\tm.resetBuffer(len(vpdPages[i].Data) + 4)\n\t\t\t\tcopy(m.buf[4:], vpdPages[i].Data)\n\t\t\t\tfound = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif !found {\n\t\t\t// VPD page not found, send error\n\t\t\tm.sendScsiError(csw.StatusFailed, scsi.SenseIllegalRequest, scsi.SenseCodeInvalidFieldInCDB)\n\t\t\treturn\n\t\t}\n\t}\n\n\t// byte 0 - Peripheral Qualifier/Peripheral Device Type (0x00 for direct access block device)\n\tm.buf[1] = pageCode\n\tbinary.BigEndian.PutUint16(m.buf[2:4], uint16(pageLength))\n\n\t// Set total bytes to the length of our response\n\tm.queuedBytes = uint32(len(m.buf))\n\tm.transferBytes = uint32(len(m.buf))\n}\n\nfunc (m *msc) scsiStdInquiry(cmd scsi.Cmd) {\n\tm.resetBuffer(scsi.InquiryRespLen)\n\tm.queuedBytes = scsi.InquiryRespLen\n\tm.transferBytes = scsi.InquiryRespLen\n\n\t// byte 0 - Device Type (0x00 for direct access block device)\n\t// byte 1 - Removable media bit\n\tm.buf[1] = 0x80\n\t// byte 2 - Version 0x00 - We claim conformance to no standard\n\t// byte 3 - Response data format\n\tm.buf[3] = 2\n\t// byte 4 - Additional length (number of bytes after this one)\n\tm.buf[4] = scsi.InquiryRespLen - 5\n\t// byte 5 - Not used\n\t// byte 6 - Not used\n\t// byte 7 - Not used\n\t// bytes 8-15 - Vendor ID\n\tcopy(m.buf[8:16], m.vendorID[:])\n\t// bytes 16-31 - Product ID\n\tcopy(m.buf[16:32], m.productID[:])\n\t// bytes 32-35 - Product revision level\n\tcopy(m.buf[32:36], m.productRev[:])\n}\n"
  },
  {
    "path": "src/machine/usb/msc/scsi_readwrite.go",
    "content": "package msc\n\nimport (\n\t\"errors\"\n\t\"machine/usb/msc/csw\"\n\t\"machine/usb/msc/scsi\"\n)\n\nvar invalidWriteError = errors.New(\"invalid write offset or length\")\n\nfunc (m *msc) scsiCmdReadWrite(cmd scsi.Cmd) {\n\tstatus := m.validateScsiReadWrite(cmd)\n\tif status != csw.StatusPassed {\n\t\tm.sendScsiError(status, scsi.SenseIllegalRequest, scsi.SenseCodeInvalidCmdOpCode)\n\t} else if m.transferBytes > 0 {\n\t\tif cmd.CmdType() == scsi.CmdRead {\n\t\t\tm.scsiRead(cmd)\n\t\t} else {\n\t\t\t// WRITE(10) and UNMAP commands don't take any action until the data stage begins\n\t\t}\n\t} else {\n\t\t// Zero byte transfer. No practical use case\n\t\tm.state = mscStateStatus\n\t}\n}\n\n// Validate SCSI READ(10) and WRITE(10) commands\nfunc (m *msc) validateScsiReadWrite(cmd scsi.Cmd) csw.Status {\n\tblockCount := cmd.BlockCount()\n\t// CBW wrapper transfer length\n\tif m.transferBytes == 0 {\n\t\t// If the SCSI command's block count doesn't loosely match the wrapper's transfer length something's wrong\n\t\tif blockCount > 0 {\n\t\t\treturn csw.StatusPhaseError\n\t\t}\n\t\t// Zero length transfer. No practical use case, but explicitly not an error according to the spec\n\t\treturn csw.StatusPassed\n\t}\n\tif (cmd.CmdType() == scsi.CmdRead && m.cbw.isOut()) || (cmd.CmdType() == scsi.CmdWrite && m.cbw.isIn()) {\n\t\t// If the command is READ(10) and the data direction is from host to device that's a problem\n\t\t// 6.7.3 The Thirteen Cases - Case 10 (Ho <> Di)\n\t\t// If the command is WRITE(10) and the data direction is from device to host that's also a problem\n\t\t// 6.7.2 The Thirteen Cases - Case 8 (Hi <> Do)\n\t\t// https://usb.org/sites/default/files/usbmassbulk_10.pdf\n\t\treturn csw.StatusPhaseError\n\t}\n\tif blockCount == 0 {\n\t\t// We already checked for zero length transfer above, so this is a problem\n\t\t// 6.7.2 The Thirteen Cases - Case 4 (Hi > Dn)\n\t\t// https://usb.org/sites/default/files/usbmassbulk_10.pdf\n\t\treturn csw.StatusFailed\n\t}\n\tif m.transferBytes/blockCount == 0 {\n\t\t// Block size shouldn't be small enough to round to zero\n\t\t// 6.7.2 The Thirteen Cases - Case 7 (Hi < Di) READ(10) or\n\t\t// 6.7.3 The Thirteen Cases - Case 13 (Ho < Do) WRITE(10)\n\t\t// https://usb.org/sites/default/files/usbmassbulk_10.pdf\n\t\treturn csw.StatusPhaseError\n\t}\n\treturn csw.StatusPassed\n}\n\nfunc (m *msc) usbToRawOffset(lba, offset uint32) (int64, int64) {\n\t// Convert the emulated block address to the underlying hardware block's start and offset\n\trawLBA := (lba*m.blockSizeUSB + offset) / m.blockSizeRaw\n\trawBlockOffset := int64((lba*m.blockSizeUSB + offset) % m.blockSizeRaw)\n\treturn int64(m.blockOffset + rawLBA*m.blockSizeRaw), rawBlockOffset\n}\n\nfunc (m *msc) readBlock(b []byte, lba, offset uint32) (n int, err error) {\n\t// Convert the emulated block address to the underlying hardware block's start and offset\n\tblockStart, blockOffset := m.usbToRawOffset(lba, offset)\n\n\t// Read a full block from the underlying device into the block cache\n\tn, err = m.dev.ReadAt(m.blockCache, blockStart)\n\tn -= int(blockOffset)\n\tif n > len(b) {\n\t\tn = len(b)\n\t}\n\n\tcopy(b, m.blockCache[blockOffset:])\n\n\treturn n, err\n}\n\nfunc (m *msc) writeBlock(b []byte, lba, offset uint32) (n int, err error) {\n\t// Convert the emulated block address to the underlying hardware block's start and offset\n\tblockStart, blockOffset := m.usbToRawOffset(lba, offset)\n\n\tif blockOffset != 0 || len(b) != int(m.blockSizeRaw) {\n\t\treturn 0, invalidWriteError\n\t}\n\n\t// Write the full block to the underlying device\n\tn, err = m.dev.WriteAt(b, blockStart)\n\tn -= int(blockOffset)\n\tif n > len(b) {\n\t\tn = len(b)\n\t}\n\n\treturn n, err\n}\n\nfunc (m *msc) scsiRead(cmd scsi.Cmd) {\n\t// Make sure we don't exceed the buffer size\n\treadEnd := m.transferBytes - m.sentBytes\n\tif readEnd > m.maxPacketSize {\n\t\treadEnd = m.maxPacketSize\n\t}\n\t// Resize the buffer to fit the read size\n\tm.resetBuffer(int(readEnd))\n\n\t// Read data from the emulated block device\n\tn, err := m.readBlock(m.buf[:readEnd], cmd.LBA(), m.sentBytes)\n\tif err != nil || n == 0 {\n\t\tm.sendScsiError(csw.StatusFailed, scsi.SenseNotReady, scsi.SenseCodeMediumNotPresent)\n\t\treturn\n\t}\n\n\tm.queuedBytes = readEnd\n\tm.sendUSBPacket(m.buf)\n}\n\nfunc (m *msc) scsiWrite(cmd scsi.Cmd, b []byte) {\n\tif m.readOnly {\n\t\tm.sendScsiError(csw.StatusFailed, scsi.SenseDataProtect, scsi.SenseCodeWriteProtected)\n\t\treturn\n\t}\n\n\t// Write data to the block device\n\tn, err := m.writeBlock(b, cmd.LBA(), m.sentBytes)\n\tif err != nil || n < len(b) {\n\t\tm.sentBytes += uint32(n)\n\t\tm.sendScsiError(csw.StatusFailed, scsi.SenseNotReady, scsi.SenseCodeMediumNotPresent)\n\t} else {\n\t\tm.sentBytes += uint32(len(b))\n\t}\n\n\tif m.sentBytes >= m.transferBytes {\n\t\t// Data transfer is complete, send CSW\n\t\tm.state = mscStateStatus\n\t\tm.run([]byte{}, true)\n\t}\n}\n"
  },
  {
    "path": "src/machine/usb/msc/scsi_unmap.go",
    "content": "package msc\n\nimport (\n\t\"encoding/binary\"\n\t\"machine/usb/msc/csw\"\n\t\"machine/usb/msc/scsi\"\n)\n\ntype Error int\n\nconst (\n\terrorLBAOutOfRange Error = iota\n)\n\nfunc (e Error) Error() string {\n\tswitch e {\n\tcase errorLBAOutOfRange:\n\t\treturn \"LBA out of range\"\n\tdefault:\n\t\treturn \"unknown error\"\n\t}\n}\n\nfunc (m *msc) scsiUnmap(b []byte) {\n\t// Execute Order 66 (0x42) to wipe out the blocks\n\t// 3.54 Unmap Command (SBC-4)\n\t// https://www.seagate.com/files/staticfiles/support/docs/manual/Interface%20manuals/100293068j.pdf\n\tif m.readOnly {\n\t\tm.sendScsiError(csw.StatusFailed, scsi.SenseDataProtect, scsi.SenseCodeWriteProtected)\n\t\treturn\n\t}\n\n\t// blockDescLen is the remaining length of block descriptors in the message, offset 8 bytes from\n\t// the start of this packet\n\tvar blockDescLen uint16\n\n\t// Decode the parameter list\n\tmsgLen := binary.BigEndian.Uint16(b[:2])\n\t// Length of the block descriptor portion of the message\n\tblockDescLen = binary.BigEndian.Uint16(b[2:4])\n\t// Do some sanity checks on the message lengths (max 3 block descriptors to fit in one 64 byte packet)\n\tif msgLen < 8 || blockDescLen < 16 || msgLen-blockDescLen != 6 || blockDescLen > (3*16) {\n\t\tm.sendScsiError(csw.StatusFailed, scsi.SenseIllegalRequest, scsi.SenseCodeInvalidFieldInCDB)\n\t\treturn\n\t}\n\n\t// descEnd marks the end of the last full block descriptor in this packet\n\tdescEnd := int(blockDescLen + 8)\n\n\t// Unmap the blocks we can from this packet\n\tfor i := 8; i < descEnd; i += 16 {\n\t\terr := m.unmapBlocksFromDescriptor(b[i:], uint64(m.blockCount))\n\t\tif err != nil {\n\t\t\t// TODO: Might need a better error code here for device errors?\n\t\t\tm.sendScsiError(csw.StatusFailed, scsi.SenseVolumeOverflow, scsi.SenseCodeLBAOutOfRange)\n\t\t\treturn\n\t\t}\n\t}\n\n\t// FIXME: We need to handle erase block alignment\n\n\tm.sentBytes += uint32(len(b))\n\tif m.sentBytes >= m.transferBytes {\n\t\t// Order 66 complete, send CSW to establish galactic empire\n\t\tm.state = mscStateStatus\n\t\tm.run([]byte{}, true)\n\t}\n}\n\nfunc (m *msc) unmapBlocksFromDescriptor(b []byte, numBlocks uint64) error {\n\tblockCount := binary.BigEndian.Uint32(b[8:12])\n\tif blockCount == 0 {\n\t\t// No blocks to unmap. Explicitly not an error per the spec\n\t\treturn nil\n\t}\n\t// This is technically a 64-bit LBA, but we can't address that many bytes\n\t// let alone blocks, so we just use the lower 32 bits\n\tlba := binary.BigEndian.Uint32(b[4:8])\n\n\t// Make sure the unmap command doesn't extend past the end of the volume\n\tif lba+blockCount > m.blockCount {\n\t\treturn errorLBAOutOfRange\n\t}\n\n\t// Convert the emulated block size to the underlying hardware erase block size\n\tblockStart := int64(lba*m.blockSizeUSB) / m.dev.EraseBlockSize()\n\trawBlockCount := int64(blockCount*m.blockSizeUSB) / m.dev.EraseBlockSize()\n\n\t// Unmap the blocks\n\treturn m.dev.EraseBlocks(blockStart, rawBlockCount)\n}\n"
  },
  {
    "path": "src/machine/usb/msc/setup.go",
    "content": "package msc\n\nimport (\n\t\"machine\"\n\t\"machine/usb\"\n)\n\nfunc setupPacketHandler(setup usb.Setup) bool {\n\tif MSC != nil {\n\t\treturn MSC.setupPacketHandler(setup)\n\t}\n\treturn false\n}\n\nfunc (m *msc) setupPacketHandler(setup usb.Setup) bool {\n\tok := false\n\twValue := (uint16(setup.WValueH) << 8) | uint16(setup.WValueL)\n\tswitch setup.BRequest {\n\tcase usb.CLEAR_FEATURE:\n\t\tif setup.BmRequestType == 0x02 { // Host-to-Device | Standard | Endpoint\n\t\t\tok = m.handleClearFeature(setup, wValue)\n\t\t}\n\tcase usb.GET_MAX_LUN:\n\t\tif setup.BmRequestType == 0xA1 { // Device-to-Host | Class | Interface\n\t\t\tok = m.handleGetMaxLun(setup, wValue)\n\t\t}\n\tcase usb.MSC_RESET:\n\t\tif setup.BmRequestType == 0x21 { // Host-to-Device | Class | Interface\n\t\t\tok = m.handleReset(setup, wValue)\n\t\t}\n\t}\n\treturn ok\n}\n\n// Handles the CLEAR_FEATURE request for clearing ENDPOINT_HALT/stall\nfunc (m *msc) handleClearFeature(setup usb.Setup, wValue uint16) bool {\n\tok := false\n\t// wValue is the feature selector (0x00 for ENDPOINT_HALT)\n\t// We aren't handling any other feature selectors\n\t// https://wiki.osdev.org/Universal_Serial_Bus#CLEAR_FEATURE\n\tif wValue != 0 {\n\t\treturn ok\n\t}\n\t// Clearing the stall is not enough, continue stalling until a reset is received first\n\t// 6.6.1 CBW Not Valid\n\t// If the CBW is not valid, the device shall STALL the Bulk-In pipe. Also, the device\n\t// shall either STALL the Bulk-Out pipe, or the device shall accept and discard any\n\t// Bulk-Out data. The device shall maintain this state until a Reset Recovery\n\t// For Reset Recovery the host shall issue in the following order: :\n\t// (a) a Bulk-Only Mass Storage Reset (handleReset())\n\t// (b) a Clear Feature HALT to the Bulk-In endpoint (clear stall IN)\n\t// (c) a Clear Feature HALT to the Bulk-Out endpoint (clear stall OUT)\n\t// https://usb.org/sites/default/files/usbmassbulk_10.pdf\n\tif m.state == mscStateNeedReset {\n\t\twIndex := setup.WIndex & 0x7F // Clear the direction bit from the endpoint address for comparison\n\t\tif wIndex == usb.MSC_ENDPOINT_IN {\n\t\t\tm.stallEndpoint(usb.MSC_ENDPOINT_IN)\n\t\t} else if wIndex == usb.MSC_ENDPOINT_OUT {\n\t\t\tm.stallEndpoint(usb.MSC_ENDPOINT_OUT)\n\t\t}\n\t\tmachine.SendZlp()\n\t\treturn true\n\t}\n\n\t// Clear the direction bit from the endpoint address for comparison\n\twIndex := setup.WIndex & 0x7F\n\n\t// Clear the IN/OUT stalls if addressed to the endpoint\n\tif wIndex == usb.MSC_ENDPOINT_IN {\n\t\tm.clearStallEndpoint(usb.MSC_ENDPOINT_IN)\n\t\tok = true\n\t}\n\tif wIndex == usb.MSC_ENDPOINT_OUT {\n\t\tm.clearStallEndpoint(usb.MSC_ENDPOINT_OUT)\n\t\tok = true\n\t}\n\t// Send a CSW if needed to resume after the IN endpoint stall is cleared\n\tif m.state == mscStateStatus && wIndex == usb.MSC_ENDPOINT_IN {\n\t\tm.sendCSW(m.respStatus)\n\t\tok = true\n\t}\n\n\tif ok {\n\t\tmachine.SendZlp()\n\t}\n\treturn ok\n}\n\n// 3.2 Get Max LUN\n// https://usb.org/sites/default/files/usbmassbulk_10.pdf\nfunc (m *msc) handleGetMaxLun(setup usb.Setup, wValue uint16) bool {\n\tif setup.WIndex != mscInterface || setup.WLength != 1 || wValue != 0 {\n\t\treturn false\n\t}\n\t// Send the maximum LUN ID number (zero-indexed, so n-1) supported by the device\n\tm.resetBuffer(1) // Shrink buffer to 1 byte\n\tm.buf[0] = m.maxLUN\n\treturn machine.SendUSBInPacket(usb.CONTROL_ENDPOINT, m.buf)\n}\n\n// 3.1 Bulk-Only Mass Storage Reset\n// https://usb.org/sites/default/files/usbmassbulk_10.pdf\nfunc (m *msc) handleReset(setup usb.Setup, wValue uint16) bool {\n\tif setup.WIndex != mscInterface || setup.WLength != 0 || wValue != 0 {\n\t\treturn false\n\t}\n\t// Reset to command waiting state\n\tm.state = mscStateCmd\n\n\t// Reset transfer state\n\tm.resetBuffer(0)\n\tm.senseKey = 0\n\tm.addlSenseCode = 0\n\tm.addlSenseQualifier = 0\n\n\t// Send a zero-length packet (ZLP) to indicate the reset is complete\n\tmachine.SendZlp()\n\n\t// Return true to indicate successful reset\n\treturn true\n}\n\nfunc (m *msc) stallEndpoint(ep uint8) {\n\tif ep == usb.MSC_ENDPOINT_IN {\n\t\tm.txStalled = true\n\t\tmachine.USBDev.SetStallEPIn(usb.MSC_ENDPOINT_IN)\n\t} else if ep == usb.MSC_ENDPOINT_OUT {\n\t\tm.rxStalled = true\n\t\tmachine.USBDev.SetStallEPOut(usb.MSC_ENDPOINT_OUT)\n\t} else if ep == usb.CONTROL_ENDPOINT {\n\t\tmachine.USBDev.SetStallEPIn(usb.CONTROL_ENDPOINT)\n\t}\n}\n\nfunc (m *msc) clearStallEndpoint(ep uint8) {\n\tif ep == usb.MSC_ENDPOINT_IN {\n\t\tmachine.USBDev.ClearStallEPIn(usb.MSC_ENDPOINT_IN)\n\t\tm.txStalled = false\n\t} else if ep == usb.MSC_ENDPOINT_OUT {\n\t\tmachine.USBDev.ClearStallEPOut(usb.MSC_ENDPOINT_OUT)\n\t\tm.rxStalled = false\n\t}\n}\n\nfunc (m *msc) setStringField(field []byte, value string) {\n\tcopy(field, []byte(value))\n\tfor i := len(value); i < len(field); i++ {\n\t\tfield[i] = 0x20 // Fill remaining bytes with spaces\n\t}\n}\n\nfunc (m *msc) SetVendorID(vendorID string) {\n\tm.setStringField(m.vendorID[:], vendorID)\n}\n\nfunc (m *msc) SetProductID(productID string) {\n\tm.setStringField(m.productID[:], productID)\n}\n\nfunc (m *msc) SetProductRev(productRev string) {\n\tm.setStringField(m.productRev[:], productRev)\n}\n\nfunc SetVendorID(vendorID string) {\n\tif MSC != nil {\n\t\tMSC.SetVendorID(vendorID)\n\t}\n}\nfunc SetProductID(productID string) {\n\tif MSC != nil {\n\t\tMSC.SetProductID(productID)\n\t}\n}\nfunc SetProductRev(productRev string) {\n\tif MSC != nil {\n\t\tMSC.SetProductRev(productRev)\n\t}\n}\n"
  },
  {
    "path": "src/machine/usb/usb.go",
    "content": "package usb\n\nvar (\n\t// TODO: allow setting these\n\tSTRING_LANGUAGE = [2]uint16{(3 << 8) | (2 + 2), 0x0409} // English\n)\n\nconst (\n\tDescriptorConfigCDC = 1 << iota\n\tDescriptorConfigHID\n\tDescriptorConfigMIDI\n\tDescriptorConfigJoystick\n)\n\nconst (\n\tIMANUFACTURER = 1\n\tIPRODUCT      = 2\n\tISERIAL       = 3\n\n\tENDPOINT_TYPE_DISABLE     = 0xFF\n\tENDPOINT_TYPE_CONTROL     = 0x00\n\tENDPOINT_TYPE_ISOCHRONOUS = 0x01\n\tENDPOINT_TYPE_BULK        = 0x02\n\tENDPOINT_TYPE_INTERRUPT   = 0x03\n\n\tEndpointOut = 0x00\n\tEndpointIn  = 0x80\n\n\tEndpointPacketSize = 64 // 64 for Full Speed, EPT size max is 1024\n\n\t// bRequest - standard requests\n\tGET_STATUS        = 0\n\tCLEAR_FEATURE     = 1\n\tSET_FEATURE       = 3\n\tSET_ADDRESS       = 5\n\tGET_DESCRIPTOR    = 6\n\tSET_DESCRIPTOR    = 7\n\tGET_CONFIGURATION = 8\n\tSET_CONFIGURATION = 9\n\tGET_INTERFACE     = 10\n\tSET_INTERFACE     = 11\n\n\t// bRequest - HID class-specific requests\n\tGET_REPORT      = 1\n\tGET_IDLE        = 2\n\tGET_PROTOCOL    = 3\n\tSET_REPORT      = 9\n\tSET_IDLE        = 10\n\tSET_PROTOCOL    = 11\n\tSET_REPORT_TYPE = 33\n\n\t// bRequest - MSC class-specific requests\n\tGET_MAX_LUN = 0xFE\n\tMSC_RESET   = 0xFF\n\n\tDEVICE_CLASS_COMMUNICATIONS  = 0x02\n\tDEVICE_CLASS_HUMAN_INTERFACE = 0x03\n\tDEVICE_CLASS_STORAGE         = 0x08\n\tDEVICE_CLASS_VENDOR_SPECIFIC = 0xFF\n\n\tCONFIG_POWERED_MASK  = 0x40\n\tCONFIG_BUS_POWERED   = 0x80\n\tCONFIG_SELF_POWERED  = 0xC0\n\tCONFIG_REMOTE_WAKEUP = 0x20\n\n\t// Interface\n\tNumberOfInterfaces = 3\n\tCDC_ACM_INTERFACE  = 0 // CDC ACM\n\tCDC_DATA_INTERFACE = 1 // CDC Data\n\tCDC_FIRST_ENDPOINT = 1\n\tHID_INTERFACE      = 2 // HID\n\n\t// Endpoint\n\tCONTROL_ENDPOINT  = 0\n\tCDC_ENDPOINT_ACM  = 1\n\tCDC_ENDPOINT_OUT  = 2\n\tCDC_ENDPOINT_IN   = 3\n\tHID_ENDPOINT_IN   = 4 // for Interrupt In\n\tHID_ENDPOINT_OUT  = 5 // for Interrupt Out\n\tMIDI_ENDPOINT_IN  = 6 // for Bulk In\n\tMIDI_ENDPOINT_OUT = 7 // for Bulk Out\n\tMSC_ENDPOINT_IN   = 6 // for Bulk In\n\tMSC_ENDPOINT_OUT  = 7 // for Bulk Out\n\n\t// bmRequestType\n\tREQUEST_HOSTTODEVICE = 0x00\n\tREQUEST_DEVICETOHOST = 0x80\n\tREQUEST_DIRECTION    = 0x80\n\n\tREQUEST_STANDARD = 0x00\n\tREQUEST_CLASS    = 0x20\n\tREQUEST_VENDOR   = 0x40\n\tREQUEST_TYPE     = 0x60\n\n\tREQUEST_DEVICE    = 0x00\n\tREQUEST_INTERFACE = 0x01\n\tREQUEST_ENDPOINT  = 0x02\n\tREQUEST_OTHER     = 0x03\n\tREQUEST_RECIPIENT = 0x1F\n\n\tREQUEST_DEVICETOHOST_CLASS_INTERFACE    = (REQUEST_DEVICETOHOST | REQUEST_CLASS | REQUEST_INTERFACE)\n\tREQUEST_HOSTTODEVICE_CLASS_INTERFACE    = (REQUEST_HOSTTODEVICE | REQUEST_CLASS | REQUEST_INTERFACE)\n\tREQUEST_DEVICETOHOST_STANDARD_INTERFACE = (REQUEST_DEVICETOHOST | REQUEST_STANDARD | REQUEST_INTERFACE)\n)\n\ntype Setup struct {\n\tBmRequestType uint8\n\tBRequest      uint8\n\tWValueL       uint8\n\tWValueH       uint8\n\tWIndex        uint16\n\tWLength       uint16\n}\n\nfunc NewSetup(data []byte) Setup {\n\tu := Setup{}\n\tu.BmRequestType = uint8(data[0])\n\tu.BRequest = uint8(data[1])\n\tu.WValueL = uint8(data[2])\n\tu.WValueH = uint8(data[3])\n\tu.WIndex = uint16(data[4]) | (uint16(data[5]) << 8)\n\tu.WLength = uint16(data[6]) | (uint16(data[7]) << 8)\n\treturn u\n}\n\nvar (\n\t// VendorID aka VID is the officially assigned vendor number\n\t// for this USB device. Only set this if you know what you are doing,\n\t// since changing it can make it difficult to reflash some devices.\n\tVendorID uint16\n\n\t// ProductID aka PID is the product number associated with the officially assigned\n\t// vendor number for this USB device. Only set this if you know what you are doing,\n\t// since changing it can make it difficult to reflash some devices.\n\tProductID uint16\n\n\t// Manufacturer is the manufacturer name displayed for this USB device.\n\tManufacturer string\n\n\t// Product is the product name displayed for this USB device.\n\tProduct string\n\n\t// Serial is the serial value displayed for this USB device. Assign a value to\n\t// transmit the serial to the host when requested.\n\tSerial string\n)\n"
  },
  {
    "path": "src/machine/usb.go",
    "content": "//go:build sam || nrf52840 || rp2040 || rp2350\n\npackage machine\n\nimport (\n\t\"machine/usb\"\n\t\"machine/usb/descriptor\"\n\n\t\"errors\"\n)\n\ntype USBDevice struct {\n\tinitcomplete         bool\n\tInitEndpointComplete bool\n}\n\nvar (\n\tUSBDev = &USBDevice{}\n\tUSBCDC Serialer\n)\n\nfunc initUSB() {\n\tenableUSBCDC()\n\tUSBDev.Configure(UARTConfig{})\n}\n\n// Using go:linkname here because there's a circular dependency between the\n// machine package and the machine/usb/cdc package.\n//\n//go:linkname enableUSBCDC machine/usb/cdc.EnableUSBCDC\nfunc enableUSBCDC()\n\ntype Serialer interface {\n\tWriteByte(c byte) error\n\tWrite(data []byte) (n int, err error)\n\tConfigure(config UARTConfig) error\n\tBuffered() int\n\tReadByte() (byte, error)\n\tDTR() bool\n\tRTS() bool\n}\n\nvar usbDescriptor descriptor.Descriptor\n\nfunc usbVendorID() uint16 {\n\tif usb.VendorID != 0 {\n\t\treturn usb.VendorID\n\t}\n\n\treturn usb_VID\n}\n\nfunc usbProductID() uint16 {\n\tif usb.ProductID != 0 {\n\t\treturn usb.ProductID\n\t}\n\n\treturn usb_PID\n}\n\nfunc usbManufacturer() string {\n\tif usb.Manufacturer != \"\" {\n\t\treturn usb.Manufacturer\n\t}\n\n\treturn usb_STRING_MANUFACTURER\n}\n\nfunc usbProduct() string {\n\tif usb.Product != \"\" {\n\t\treturn usb.Product\n\t}\n\n\treturn usb_STRING_PRODUCT\n}\n\nfunc usbSerial() string {\n\tif usb.Serial != \"\" {\n\t\treturn usb.Serial\n\t}\n\treturn \"\"\n}\n\n// strToUTF16LEDescriptor converts a utf8 string into a string descriptor\n// note: the following code only converts ascii characters to UTF16LE. In order\n// to do a \"proper\" conversion, we would need to pull in the 'unicode/utf16'\n// package, which at the time this was written added 512 bytes to the compiled\n// binary.\nfunc strToUTF16LEDescriptor(in string, out []byte) {\n\tout[0] = byte(len(out))\n\tout[1] = descriptor.TypeString\n\tfor i, rune := range in {\n\t\tout[(i<<1)+2] = byte(rune)\n\t\tout[(i<<1)+3] = 0\n\t}\n\treturn\n}\n\nconst cdcLineInfoSize = 7\n\nvar (\n\tErrUSBReadTimeout  = errors.New(\"USB read timeout\")\n\tErrUSBBytesRead    = errors.New(\"USB invalid number of bytes read\")\n\tErrUSBBytesWritten = errors.New(\"USB invalid number of bytes written\")\n)\n\nvar (\n\tusbEndpointDescriptors [NumberOfUSBEndpoints]descriptor.Device\n\n\tisEndpointHalt        = false\n\tisRemoteWakeUpEnabled = false\n\n\tusbConfiguration uint8\n\tusbSetInterface  uint8\n)\n\n//go:align 4\nvar udd_ep_control_cache_buffer [256]uint8\n\n//go:align 4\nvar udd_ep_in_cache_buffer [NumberOfUSBEndpoints][64]uint8\n\n//go:align 4\nvar udd_ep_out_cache_buffer [NumberOfUSBEndpoints][64]uint8\n\n// usb_trans_buffer max size is 255 since that is max size\n// for a descriptor (bLength is 1 byte), and the biggest use\n// for this buffer is to transmit string descriptors.  If\n// this buffer is used for new purposes in future the length\n// must be revisited.\nvar usb_trans_buffer [255]uint8\n\nvar (\n\tusbTxHandler    [NumberOfUSBEndpoints]func()\n\tusbRxHandler    [NumberOfUSBEndpoints]func([]byte) bool\n\tusbSetupHandler [usb.NumberOfInterfaces]func(usb.Setup) bool\n\tusbStallHandler [NumberOfUSBEndpoints]func(usb.Setup) bool\n)\n\n// sendDescriptor creates and sends the various USB descriptor types that\n// can be requested by the host.\nfunc sendDescriptor(setup usb.Setup) {\n\tswitch setup.WValueH {\n\tcase descriptor.TypeConfiguration:\n\t\tsendUSBPacket(0, usbDescriptor.Configuration, setup.WLength)\n\t\treturn\n\tcase descriptor.TypeDevice:\n\t\tusbDescriptor.Configure(usbVendorID(), usbProductID())\n\t\tsendUSBPacket(0, usbDescriptor.Device, setup.WLength)\n\t\treturn\n\n\tcase descriptor.TypeString:\n\t\tswitch setup.WValueL {\n\t\tcase 0:\n\t\t\tusb_trans_buffer[0] = 0x04\n\t\t\tusb_trans_buffer[1] = 0x03\n\t\t\tusb_trans_buffer[2] = 0x09\n\t\t\tusb_trans_buffer[3] = 0x04\n\t\t\tsendUSBPacket(0, usb_trans_buffer[:4], setup.WLength)\n\n\t\tcase usb.IPRODUCT:\n\t\t\tb := usb_trans_buffer[:(len(usbProduct())<<1)+2]\n\t\t\tstrToUTF16LEDescriptor(usbProduct(), b)\n\t\t\tsendUSBPacket(0, b, setup.WLength)\n\n\t\tcase usb.IMANUFACTURER:\n\t\t\tb := usb_trans_buffer[:(len(usbManufacturer())<<1)+2]\n\t\t\tstrToUTF16LEDescriptor(usbManufacturer(), b)\n\t\t\tsendUSBPacket(0, b, setup.WLength)\n\n\t\tcase usb.ISERIAL:\n\t\t\tsz := len(usbSerial())\n\t\t\tif sz == 0 {\n\t\t\t\tSendZlp()\n\t\t\t} else {\n\t\t\t\tb := usb_trans_buffer[:(sz<<1)+2]\n\t\t\t\tstrToUTF16LEDescriptor(usbSerial(), b)\n\t\t\t\tsendUSBPacket(0, b, setup.WLength)\n\t\t\t}\n\t\t}\n\t\treturn\n\tcase descriptor.TypeHIDReport:\n\t\tif h, ok := usbDescriptor.HID[setup.WIndex]; ok {\n\t\t\tsendUSBPacket(0, h, setup.WLength)\n\t\t\treturn\n\t\t}\n\tcase descriptor.TypeDeviceQualifier:\n\t\t// skip\n\tdefault:\n\t}\n\n\t// do not know how to handle this message, so return zero\n\tSendZlp()\n\treturn\n}\n\nfunc handleStandardSetup(setup usb.Setup) bool {\n\tswitch setup.BRequest {\n\tcase usb.GET_STATUS:\n\t\tusb_trans_buffer[0] = 0\n\t\tusb_trans_buffer[1] = 0\n\n\t\tif setup.BmRequestType != 0 { // endpoint\n\t\t\tif isEndpointHalt {\n\t\t\t\tusb_trans_buffer[0] = 1\n\t\t\t}\n\t\t}\n\n\t\tsendUSBPacket(0, usb_trans_buffer[:2], setup.WLength)\n\t\treturn true\n\n\tcase usb.CLEAR_FEATURE:\n\t\tif setup.WValueL == 1 { // DEVICEREMOTEWAKEUP\n\t\t\tisRemoteWakeUpEnabled = false\n\t\t} else if setup.WValueL == 0 { // ENDPOINTHALT\n\t\t\tif idx := setup.WIndex & 0x7F; idx < NumberOfUSBEndpoints && usbStallHandler[idx] != nil {\n\t\t\t\t// Host has requested to clear an endpoint stall. If the request is addressed to\n\t\t\t\t// an endpoint with a configured StallHandler, forward the message on.\n\t\t\t\t// The 0x7F mask is used to clear the direction bit from the endpoint number\n\t\t\t\treturn usbStallHandler[idx](setup)\n\t\t\t}\n\t\t\tisEndpointHalt = false\n\t\t}\n\t\tSendZlp()\n\t\treturn true\n\n\tcase usb.SET_FEATURE:\n\t\tif setup.WValueL == 1 { // DEVICEREMOTEWAKEUP\n\t\t\tisRemoteWakeUpEnabled = true\n\t\t} else if setup.WValueL == 0 { // ENDPOINTHALT\n\t\t\tif idx := setup.WIndex & 0x7F; idx < NumberOfUSBEndpoints && usbStallHandler[idx] != nil {\n\t\t\t\t// Host has requested to stall an endpoint. If the request is addressed to\n\t\t\t\t// an endpoint with a configured StallHandler, forward the message on.\n\t\t\t\t// The 0x7F mask is used to clear the direction bit from the endpoint number\n\t\t\t\treturn usbStallHandler[idx](setup)\n\t\t\t}\n\t\t\tisEndpointHalt = true\n\t\t}\n\t\tSendZlp()\n\t\treturn true\n\n\tcase usb.SET_ADDRESS:\n\t\treturn handleUSBSetAddress(setup)\n\n\tcase usb.GET_DESCRIPTOR:\n\t\tsendDescriptor(setup)\n\t\treturn true\n\n\tcase usb.SET_DESCRIPTOR:\n\t\treturn false\n\n\tcase usb.GET_CONFIGURATION:\n\t\tusb_trans_buffer[0] = usbConfiguration\n\t\tsendUSBPacket(0, usb_trans_buffer[:1], setup.WLength)\n\t\treturn true\n\n\tcase usb.SET_CONFIGURATION:\n\t\tif setup.BmRequestType&usb.REQUEST_RECIPIENT == usb.REQUEST_DEVICE {\n\t\t\tfor i := 1; i < len(endPoints); i++ {\n\t\t\t\tinitEndpoint(uint32(i), endPoints[i])\n\t\t\t}\n\n\t\t\tusbConfiguration = setup.WValueL\n\t\t\tUSBDev.InitEndpointComplete = true\n\n\t\t\tSendZlp()\n\t\t\treturn true\n\t\t} else {\n\t\t\treturn false\n\t\t}\n\n\tcase usb.GET_INTERFACE:\n\t\tusb_trans_buffer[0] = usbSetInterface\n\t\tsendUSBPacket(0, usb_trans_buffer[:1], setup.WLength)\n\t\treturn true\n\n\tcase usb.SET_INTERFACE:\n\t\tusbSetInterface = setup.WValueL\n\n\t\tSendZlp()\n\t\treturn true\n\n\tdefault:\n\t\treturn true\n\t}\n}\n\nfunc EnableCDC(txHandler func(), rxHandler func([]byte), setupHandler func(usb.Setup) bool) {\n\tif len(usbDescriptor.Device) == 0 {\n\t\tusbDescriptor = descriptor.CDC\n\t}\n\t// Initialization of endpoints is required even for non-CDC\n\tConfigureUSBEndpoint(usbDescriptor,\n\t\t[]usb.EndpointConfig{\n\t\t\t{\n\t\t\t\tIndex: usb.CDC_ENDPOINT_ACM,\n\t\t\t\tIsIn:  true,\n\t\t\t\tType:  usb.ENDPOINT_TYPE_INTERRUPT,\n\t\t\t},\n\t\t\t{\n\t\t\t\tIndex:     usb.CDC_ENDPOINT_OUT,\n\t\t\t\tIsIn:      false,\n\t\t\t\tType:      usb.ENDPOINT_TYPE_BULK,\n\t\t\t\tRxHandler: rxHandler,\n\t\t\t},\n\t\t\t{\n\t\t\t\tIndex:     usb.CDC_ENDPOINT_IN,\n\t\t\t\tIsIn:      true,\n\t\t\t\tType:      usb.ENDPOINT_TYPE_BULK,\n\t\t\t\tTxHandler: txHandler,\n\t\t\t},\n\t\t},\n\t\t[]usb.SetupConfig{\n\t\t\t{\n\t\t\t\tIndex:   usb.CDC_ACM_INTERFACE,\n\t\t\t\tHandler: setupHandler,\n\t\t\t},\n\t\t})\n}\n\nfunc ConfigureUSBEndpoint(desc descriptor.Descriptor, epSettings []usb.EndpointConfig, setup []usb.SetupConfig) {\n\tusbDescriptor = desc\n\n\tfor _, ep := range epSettings {\n\t\tif ep.IsIn {\n\t\t\tendPoints[ep.Index] = uint32(ep.Type | usb.EndpointIn)\n\t\t\tif ep.TxHandler != nil {\n\t\t\t\tusbTxHandler[ep.Index] = ep.TxHandler\n\t\t\t}\n\t\t} else {\n\t\t\tendPoints[ep.Index] = uint32(ep.Type | usb.EndpointOut)\n\t\t\tif ep.RxHandler != nil {\n\t\t\t\tusbRxHandler[ep.Index] = func(b []byte) bool {\n\t\t\t\t\tep.RxHandler(b)\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t} else if ep.DelayRxHandler != nil {\n\t\t\t\tusbRxHandler[ep.Index] = ep.DelayRxHandler\n\t\t\t}\n\t\t}\n\t\tif ep.StallHandler != nil {\n\t\t\tusbStallHandler[ep.Index] = ep.StallHandler\n\t\t}\n\t}\n\n\tfor _, s := range setup {\n\t\tusbSetupHandler[s.Index] = s.Handler\n\t}\n}\n"
  },
  {
    "path": "src/machine/virt.go",
    "content": "//go:build tinygo.riscv32 && virt\n\n// Machine implementation for VirtIO targets.\n// At the moment only QEMU RISC-V is supported, but support for ARM for example\n// should not be difficult to add with a change to virtioFindDevice.\n\npackage machine\n\nimport (\n\t\"errors\"\n\t\"runtime/volatile\"\n\t\"sync\"\n\t\"unsafe\"\n)\n\nconst deviceName = \"riscv-qemu\"\n\nfunc (p Pin) Set(high bool) {\n\t// no pins defined\n}\n\nvar rngLock sync.Mutex\nvar rngDevice *virtioDevice1\nvar rngBuf volatile.Register32\n\nvar errNoRNG = errors.New(\"machine: no entropy source found\")\nvar errNoRNGData = errors.New(\"machine: entropy source didn't return enough data\")\n\n// GetRNG returns random numbers from a VirtIO entropy source.\n// When running in QEMU, it requires adding the RNG device:\n//\n//\t-device virtio-rng-device\nfunc GetRNG() (uint32, error) {\n\trngLock.Lock()\n\n\t// Initialize the device on first use.\n\tif rngDevice == nil {\n\t\t// Search for an available RNG.\n\t\trngDevice = virtioFindDevice(virtioDeviceEntropySource)\n\t\tif rngDevice == nil {\n\t\t\trngLock.Unlock()\n\t\t\treturn 0, errNoRNG\n\t\t}\n\n\t\t// Initialize the device.\n\t\trngDevice.status.Set(0) // reset device\n\t\trngDevice.status.Set(virtioDeviceStatusAcknowledge)\n\t\trngDevice.status.Set(virtioDeviceStatusAcknowledge | virtioDeviceStatusDriver)\n\t\trngDevice.hostFeaturesSel.Set(0)\n\t\trngDevice.status.Set(virtioDeviceStatusAcknowledge | virtioDeviceStatusDriver | virtioDeviceStatusDriverOk)\n\t\trngDevice.guestPageSize.Set(4096)\n\n\t\t// Configure queue, according to section 4.2.4 \"Legacy interface\".\n\t\t// Note: we're skipping checks for queuePFM and queueNumMax.\n\t\trngDevice.queueSel.Set(0)      // use queue 0 (the only queue)\n\t\trngDevice.queueNum.Set(1)      // use a single buffer in the queue\n\t\trngDevice.queueAlign.Set(4096) // default alignment appears to be 4096\n\t\trngDevice.queuePFN.Set(uint32(uintptr(unsafe.Pointer(&rngQueue))) / 4096)\n\n\t\t// Configure the only buffer in the queue (but don't increment\n\t\t// rngQueue.available yet).\n\t\trngQueue.buffers[0].address = uint64(uintptr(unsafe.Pointer(&rngBuf)))\n\t\trngQueue.buffers[0].length = uint32(unsafe.Sizeof(rngBuf))\n\t\trngQueue.buffers[0].flags = 2 // 2 means write-only buffer\n\t}\n\n\t// Increment the available ring buffer. This doesn't actually change the\n\t// buffer index (it's a ring with a single entry), but the number needs to\n\t// be incremented otherwise the device won't recognize a new buffer.\n\tindex := rngQueue.available.index\n\trngQueue.available.index = index + 1\n\trngDevice.queueNotify.Set(0) // notify the device of the 'new' (reused) buffer\n\tfor rngQueue.used.index.Get() != index+1 {\n\t\t// Busy wait until the RNG buffer is filled.\n\t\t// A better way would be to wait for an interrupt, but since this driver\n\t\t// implementation is mostly used for testing it's good enough for now.\n\t}\n\n\t// Check that we indeed got 4 bytes back.\n\tif rngQueue.used.ring[0].length != 4 {\n\t\trngLock.Unlock()\n\t\treturn 0, errNoRNGData\n\t}\n\n\t// Read the resulting random numbers.\n\tresult := rngBuf.Get()\n\n\trngLock.Unlock()\n\n\treturn result, nil\n}\n\n// Implement a driver for the VirtIO entropy device.\n// https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html\n// http://wiki.osdev.org/Virtio\n// http://www.dumais.io/index.php?article=aca38a9a2b065b24dfa1dee728062a12\n\nconst (\n\tvirtioDeviceStatusAcknowledge = 1\n\tvirtioDeviceStatusDriver      = 2\n\tvirtioDeviceStatusDriverOk    = 4\n\tvirtioDeviceStatusFeaturesOk  = 8\n\tvirtioDeviceStatusFailed      = 128\n)\n\nconst (\n\tvirtioDeviceReserved = iota\n\tvirtioDeviceNetworkCard\n\tvirtioDeviceBlockDevice\n\tvirtioDeviceConsole\n\tvirtioDeviceEntropySource\n\t// there are more device types\n)\n\n// VirtIO device version 1\ntype virtioDevice1 struct {\n\tmagic            volatile.Register32 // always 0x74726976\n\tversion          volatile.Register32\n\tdeviceID         volatile.Register32\n\tvendorID         volatile.Register32\n\thostFeatures     volatile.Register32\n\thostFeaturesSel  volatile.Register32\n\t_                [2]uint32\n\tguestFeatures    volatile.Register32\n\tguestFeaturesSel volatile.Register32\n\tguestPageSize    volatile.Register32\n\t_                uint32\n\tqueueSel         volatile.Register32\n\tqueueNumMax      volatile.Register32\n\tqueueNum         volatile.Register32\n\tqueueAlign       volatile.Register32\n\tqueuePFN         volatile.Register32\n\t_                [3]uint32\n\tqueueNotify      volatile.Register32\n\t_                [3]uint32\n\tinterruptStatus  volatile.Register32\n\tinterruptAck     volatile.Register32\n\t_                [2]uint32\n\tstatus           volatile.Register32\n}\n\n// VirtIO queue, with a single buffer.\ntype virtioQueue struct {\n\tbuffers [1]struct {\n\t\taddress uint64\n\t\tlength  uint32\n\t\tflags   uint16\n\t\tnext    uint16\n\t} // 16 bytes\n\n\tavailable struct {\n\t\tflags      uint16\n\t\tindex      uint16\n\t\tring       [1]uint16\n\t\teventIndex uint16\n\t} // 8 bytes\n\n\t_ [4096 - 16*1 - 8*1]byte // padding (to align on a 4096 byte boundary)\n\n\tused struct {\n\t\tflags uint16\n\t\tindex volatile.Register16\n\t\tring  [1]struct {\n\t\t\tindex  uint32\n\t\t\tlength uint32\n\t\t}\n\t\tavailEvent uint16\n\t}\n}\n\nfunc virtioFindDevice(deviceID uint32) *virtioDevice1 {\n\t// On RISC-V, QEMU defines 8 VirtIO devices starting at 0x10001000 and\n\t// repeating every 0x1000 bytes.\n\t// The memory map can be seen in the QEMU source code:\n\t// https://github.com/qemu/qemu/blob/master/hw/riscv/virt.c\n\tfor i := 0; i < 8; i++ {\n\t\tdev := (*virtioDevice1)(unsafe.Pointer(uintptr(0x10001000 + i*0x1000)))\n\t\tif dev.magic.Get() != 0x74726976 || dev.version.Get() != 1 || dev.deviceID.Get() != deviceID {\n\t\t\tcontinue\n\t\t}\n\t\treturn dev\n\t}\n\treturn nil\n}\n\n// A VirtIO queue needs to be page-aligned.\n//\n//go:align 4096\nvar rngQueue virtioQueue\n"
  },
  {
    "path": "src/machine/watchdog.go",
    "content": "//go:build nrf52840 || nrf52833 || rp2040 || rp2350 || atsamd21 || atsamd51 || atsame5x || stm32\n\npackage machine\n\n// WatchdogConfig holds configuration for the watchdog timer.\ntype WatchdogConfig struct {\n\t// The timeout (in milliseconds) before the watchdog fires.\n\t//\n\t// If the requested timeout exceeds `MaxTimeout` it will be rounded\n\t// down.\n\tTimeoutMillis uint32\n}\n\n// watchdog must be implemented by any platform supporting watchdog functionality\ntype watchdog interface {\n\t// Configure the watchdog.\n\t//\n\t// This method should not be called after the watchdog is started and on\n\t// some platforms attempting to reconfigure after starting the watchdog\n\t// is explicitly forbidden / will not work.\n\tConfigure(config WatchdogConfig) error\n\n\t// Starts the watchdog.\n\tStart() error\n\n\t// Update the watchdog, indicating that the app is healthy.\n\tUpdate()\n}\n\n// Ensure required public symbols var exists and meets interface spec\nvar _ = watchdog(Watchdog)\n\n// Ensure required public constants exist\nconst _ = WatchdogMaxTimeout\n"
  },
  {
    "path": "src/os/deadline_test.go",
    "content": "//go:build posix && !baremetal && !js\n\npackage os_test\n\nimport (\n\t\"errors\"\n\t. \"os\"\n\t\"testing\"\n)\n\nfunc TestDeadlines(t *testing.T) {\n\t// Create a handle to a known-good, existing file\n\tf, err := Open(\"/dev/null\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif err := f.SetDeadline(0); err == nil {\n\t\tif err != nil {\n\t\t\tt.Errorf(\"wanted nil, got %v\", err)\n\t\t}\n\t}\n\n\tif err := f.SetDeadline(1); err == nil {\n\t\tif !errors.Is(err, ErrNotImplemented) {\n\t\t\tt.Errorf(\"wanted ErrNotImplemented, got %v\", err)\n\t\t}\n\t}\n\n\tif err := f.SetReadDeadline(1); err == nil {\n\t\tif !errors.Is(err, ErrNotImplemented) {\n\t\t\tt.Errorf(\"wanted ErrNotImplemented, got %v\", err)\n\t\t}\n\t}\n\n\tif err := f.SetWriteDeadline(1); err == nil {\n\t\tif !errors.Is(err, ErrNotImplemented) {\n\t\t\tt.Errorf(\"wanted ErrNotImplemented, got %v\", err)\n\t\t}\n\t}\n\n\t// Closed files must return an error\n\tf.Close()\n\n\tif err := f.SetDeadline(0); err == nil {\n\t\tif err != ErrClosed {\n\t\t\tt.Errorf(\"wanted ErrClosed, got %v\", err)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/os/dir.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os\n\nimport (\n\t\"io/fs\"\n\t\"sort\"\n)\n\ntype readdirMode int\n\nconst (\n\treaddirName readdirMode = iota\n\treaddirDirEntry\n\treaddirFileInfo\n)\n\n// Readdir reads the contents of the directory associated with file and\n// returns a slice of up to n FileInfo values, as would be returned\n// by Lstat, in directory order. Subsequent calls on the same file will yield\n// further FileInfos.\n//\n// If n > 0, Readdir returns at most n FileInfo structures. In this case, if\n// Readdir returns an empty slice, it will return a non-nil error\n// explaining why. At the end of a directory, the error is io.EOF.\n//\n// If n <= 0, Readdir returns all the FileInfo from the directory in\n// a single slice. In this case, if Readdir succeeds (reads all\n// the way to the end of the directory), it returns the slice and a\n// nil error. If it encounters an error before the end of the\n// directory, Readdir returns the FileInfo read until that point\n// and a non-nil error.\n//\n// Most clients are better served by the more efficient ReadDir method.\nfunc (f *File) Readdir(n int) ([]FileInfo, error) {\n\tif f == nil {\n\t\treturn nil, ErrInvalid\n\t}\n\t_, _, infos, err := f.readdir(n, readdirFileInfo)\n\tif infos == nil {\n\t\t// Readdir has historically always returned a non-nil empty slice, never nil,\n\t\t// even on error (except misuse with nil receiver above).\n\t\t// Keep it that way to avoid breaking overly sensitive callers.\n\t\tinfos = []FileInfo{}\n\t}\n\treturn infos, err\n}\n\n// Readdirnames reads the contents of the directory associated with file\n// and returns a slice of up to n names of files in the directory,\n// in directory order. Subsequent calls on the same file will yield\n// further names.\n//\n// If n > 0, Readdirnames returns at most n names. In this case, if\n// Readdirnames returns an empty slice, it will return a non-nil error\n// explaining why. At the end of a directory, the error is io.EOF.\n//\n// If n <= 0, Readdirnames returns all the names from the directory in\n// a single slice. In this case, if Readdirnames succeeds (reads all\n// the way to the end of the directory), it returns the slice and a\n// nil error. If it encounters an error before the end of the\n// directory, Readdirnames returns the names read until that point and\n// a non-nil error.\nfunc (f *File) Readdirnames(n int) (names []string, err error) {\n\tif f == nil {\n\t\treturn nil, ErrInvalid\n\t}\n\tnames, _, _, err = f.readdir(n, readdirName)\n\tif names == nil {\n\t\t// Readdirnames has historically always returned a non-nil empty slice, never nil,\n\t\t// even on error (except misuse with nil receiver above).\n\t\t// Keep it that way to avoid breaking overly sensitive callers.\n\t\tnames = []string{}\n\t}\n\treturn names, err\n}\n\n// A DirEntry is an entry read from a directory\n// (using the ReadDir function or a File's ReadDir method).\ntype DirEntry = fs.DirEntry\n\n// ReadDir reads the contents of the directory associated with the file f\n// and returns a slice of DirEntry values in directory order.\n// Subsequent calls on the same file will yield later DirEntry records in the directory.\n//\n// If n > 0, ReadDir returns at most n DirEntry records.\n// In this case, if ReadDir returns an empty slice, it will return an error explaining why.\n// At the end of a directory, the error is io.EOF.\n//\n// If n <= 0, ReadDir returns all the DirEntry records remaining in the directory.\n// When it succeeds, it returns a nil error (not io.EOF).\nfunc (f *File) ReadDir(n int) ([]DirEntry, error) {\n\tif f == nil {\n\t\treturn nil, ErrInvalid\n\t}\n\t_, dirents, _, err := f.readdir(n, readdirDirEntry)\n\tif dirents == nil {\n\t\t// Match Readdir and Readdirnames: don't return nil slices.\n\t\tdirents = []DirEntry{}\n\t}\n\treturn dirents, err\n}\n\n// testingForceReadDirLstat forces ReadDir to call Lstat, for testing that code path.\n// This can be difficult to provoke on some Unix systems otherwise.\nvar testingForceReadDirLstat bool\n\n// ReadDir reads the named directory,\n// returning all its directory entries sorted by filename.\n// If an error occurs reading the directory,\n// ReadDir returns the entries it was able to read before the error,\n// along with the error.\nfunc ReadDir(name string) ([]DirEntry, error) {\n\tf, err := Open(name)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer f.Close()\n\n\tdirs, err := f.ReadDir(-1)\n\tsort.Slice(dirs, func(i, j int) bool { return dirs[i].Name() < dirs[j].Name() })\n\treturn dirs, err\n}\n"
  },
  {
    "path": "src/os/dir_darwin.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os\n\nimport (\n\t\"io\"\n\t\"runtime\"\n\t\"syscall\"\n\t\"unsafe\"\n)\n\n// Auxiliary information if the File describes a directory\ntype dirInfo struct {\n\tdir uintptr // Pointer to DIR structure from dirent.h\n}\n\nfunc (d *dirInfo) close() {\n\tif d.dir == 0 {\n\t\treturn\n\t}\n\tclosedir(d.dir)\n\td.dir = 0\n}\n\nfunc (f *File) readdir(n int, mode readdirMode) (names []string, dirents []DirEntry, infos []FileInfo, err error) {\n\tif f.dirinfo == nil {\n\t\tdir, call, errno := darwinOpenDir(syscallFd(f.handle.(unixFileHandle)))\n\t\tif errno != nil {\n\t\t\treturn nil, nil, nil, &PathError{Op: call, Path: f.name, Err: errno}\n\t\t}\n\t\tf.dirinfo = &dirInfo{\n\t\t\tdir: dir,\n\t\t}\n\t}\n\td := f.dirinfo\n\n\tsize := n\n\tif size <= 0 {\n\t\tsize = 100\n\t\tn = -1\n\t}\n\n\tvar dirent syscall.Dirent\n\tvar entptr *syscall.Dirent\n\tfor len(names)+len(dirents)+len(infos) < size || n == -1 {\n\t\tif errno := readdir_r(d.dir, &dirent, &entptr); errno != 0 {\n\t\t\tif errno == syscall.EINTR {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn names, dirents, infos, &PathError{Op: \"readdir\", Path: f.name, Err: errno}\n\t\t}\n\t\tif entptr == nil { // EOF\n\t\t\tbreak\n\t\t}\n\t\tif dirent.Ino == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tname := (*[len(syscall.Dirent{}.Name)]byte)(unsafe.Pointer(&dirent.Name))[:]\n\t\tfor i, c := range name {\n\t\t\tif c == 0 {\n\t\t\t\tname = name[:i]\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\t// Check for useless names before allocating a string.\n\t\tif string(name) == \".\" || string(name) == \"..\" {\n\t\t\tcontinue\n\t\t}\n\t\tif mode == readdirName {\n\t\t\tnames = append(names, string(name))\n\t\t} else if mode == readdirDirEntry {\n\t\t\tde, err := newUnixDirent(f.name, string(name), dtToType(dirent.Type))\n\t\t\tif IsNotExist(err) {\n\t\t\t\t// File disappeared between readdir and stat.\n\t\t\t\t// Treat as if it didn't exist.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\treturn nil, dirents, nil, err\n\t\t\t}\n\t\t\tdirents = append(dirents, de)\n\t\t} else {\n\t\t\tinfo, err := lstat(f.name + \"/\" + string(name))\n\t\t\tif IsNotExist(err) {\n\t\t\t\t// File disappeared between readdir + stat.\n\t\t\t\t// Treat as if it didn't exist.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, infos, err\n\t\t\t}\n\t\t\tinfos = append(infos, info)\n\t\t}\n\t\truntime.KeepAlive(f)\n\t}\n\n\tif n > 0 && len(names)+len(dirents)+len(infos) == 0 {\n\t\treturn nil, nil, nil, io.EOF\n\t}\n\treturn names, dirents, infos, nil\n}\n\nfunc dtToType(typ uint8) FileMode {\n\tswitch typ {\n\tcase syscall.DT_BLK:\n\t\treturn ModeDevice\n\tcase syscall.DT_CHR:\n\t\treturn ModeDevice | ModeCharDevice\n\tcase syscall.DT_DIR:\n\t\treturn ModeDir\n\tcase syscall.DT_FIFO:\n\t\treturn ModeNamedPipe\n\tcase syscall.DT_LNK:\n\t\treturn ModeSymlink\n\tcase syscall.DT_REG:\n\t\treturn 0\n\tcase syscall.DT_SOCK:\n\t\treturn ModeSocket\n\t}\n\treturn ^FileMode(0)\n}\n\n// darwinOpenDir returns a pointer to a DIR structure suitable for\n// ReadDir. In case of an error, the name of the failed\n// syscall is returned along with a syscall.Errno.\n// Borrowed from upstream's internal/poll/fd_opendir_darwin.go\nfunc darwinOpenDir(fd syscallFd) (uintptr, string, error) {\n\t// fdopendir(3) takes control of the file descriptor,\n\t// so use a dup.\n\tfd2, err := syscall.Dup(fd)\n\tif err != nil {\n\t\treturn 0, \"dup\", err\n\t}\n\tvar dir uintptr\n\tfor {\n\t\tdir, err = fdopendir(fd2)\n\t\tif err != syscall.EINTR {\n\t\t\tbreak\n\t\t}\n\t}\n\tif err != nil {\n\t\tsyscall.Close(fd2)\n\t\treturn 0, \"fdopendir\", err\n\t}\n\treturn dir, \"\", nil\n}\n\n// Implemented in syscall/syscall_libc_darwin_*.go.\n\n//go:linkname fdopendir syscall.fdopendir\nfunc fdopendir(fd int) (dir uintptr, err error)\n\n//go:linkname closedir syscall.closedir\nfunc closedir(dir uintptr) (err error)\n\n//go:linkname readdir_r syscall.readdir_r\nfunc readdir_r(dir uintptr, entry *syscall.Dirent, result **syscall.Dirent) (res syscall.Errno)\n"
  },
  {
    "path": "src/os/dir_other.go",
    "content": "//go:build baremetal || js || windows || wasm_unknown || nintendoswitch\n\n// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os\n\nimport (\n\t\"syscall\"\n)\n\ntype dirInfo struct {\n}\n\nfunc (*dirInfo) close() {\n}\n\nfunc (f *File) readdir(n int, mode readdirMode) (names []string, dirents []DirEntry, infos []FileInfo, err error) {\n\treturn nil, nil, nil, &PathError{Op: \"readdir unimplemented\", Err: syscall.ENOTDIR}\n}\n"
  },
  {
    "path": "src/os/dir_test.go",
    "content": "//go:build darwin || (linux && !baremetal && !js && !wasip1 && !wasip2 && !386 && !arm)\n\npackage os_test\n\nimport (\n\t. \"os\"\n\t\"testing\"\n)\n\nfunc testReaddirnames(dir string, contents []string, t *testing.T) {\n\tfile, err := Open(dir)\n\tif err != nil {\n\t\tt.Fatalf(\"open %q failed: %v\", dir, err)\n\t}\n\tdefer file.Close()\n\ts, err2 := file.Readdirnames(-1)\n\tif err2 != nil {\n\t\tt.Fatalf(\"Readdirnames %q failed: %v\", dir, err2)\n\t}\n\tfor _, m := range contents {\n\t\tfound := false\n\t\tfor _, n := range s {\n\t\t\tif n == \".\" || n == \"..\" {\n\t\t\t\tt.Errorf(\"got %q in directory\", n)\n\t\t\t}\n\t\t\tif !equal(m, n) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif found {\n\t\t\t\tt.Error(\"present twice:\", m)\n\t\t\t}\n\t\t\tfound = true\n\t\t}\n\t\tif !found {\n\t\t\tt.Error(\"could not find\", m)\n\t\t}\n\t}\n\tif s == nil {\n\t\tt.Error(\"Readdirnames returned nil instead of empty slice\")\n\t}\n}\n\nfunc testReaddir(dir string, contents []string, t *testing.T) {\n\tfile, err := Open(dir)\n\tif err != nil {\n\t\tt.Fatalf(\"open %q failed: %v\", dir, err)\n\t}\n\tdefer file.Close()\n\ts, err2 := file.Readdir(-1)\n\tif err2 != nil {\n\t\tt.Fatalf(\"Readdir %q failed: %v\", dir, err2)\n\t}\n\tfor _, m := range contents {\n\t\tfound := false\n\t\tfor _, n := range s {\n\t\t\tif n.Name() == \".\" || n.Name() == \"..\" {\n\t\t\t\tt.Errorf(\"got %q in directory\", n.Name())\n\t\t\t}\n\t\t\tif !equal(m, n.Name()) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif found {\n\t\t\t\tt.Error(\"present twice:\", m)\n\t\t\t}\n\t\t\tfound = true\n\t\t}\n\t\tif !found {\n\t\t\tt.Error(\"could not find\", m)\n\t\t}\n\t}\n\tif s == nil {\n\t\tt.Error(\"Readdir returned nil instead of empty slice\")\n\t}\n}\n\nfunc testReadDir(dir string, contents []string, t *testing.T) {\n\tfile, err := Open(dir)\n\tif err != nil {\n\t\tt.Fatalf(\"open %q failed: %v\", dir, err)\n\t}\n\tdefer file.Close()\n\ts, err2 := file.ReadDir(-1)\n\tif err2 != nil {\n\t\tt.Fatalf(\"ReadDir %q failed: %v\", dir, err2)\n\t}\n\tfor _, m := range contents {\n\t\tfound := false\n\t\tfor _, n := range s {\n\t\t\tif n.Name() == \".\" || n.Name() == \"..\" {\n\t\t\t\tt.Errorf(\"got %q in directory\", n)\n\t\t\t}\n\t\t\tif !equal(m, n.Name()) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif found {\n\t\t\t\tt.Error(\"present twice:\", m)\n\t\t\t}\n\t\t\tfound = true\n\t\t\tlstat, err := Lstat(dir + \"/\" + m)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tif n.IsDir() != lstat.IsDir() {\n\t\t\t\tt.Errorf(\"%s: IsDir=%v, want %v\", m, n.IsDir(), lstat.IsDir())\n\t\t\t}\n\t\t\tif n.Type() != lstat.Mode().Type() {\n\t\t\t\tt.Errorf(\"%s: IsDir=%v, want %v\", m, n.Type(), lstat.Mode().Type())\n\t\t\t}\n\t\t\tinfo, err := n.Info()\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"%s: Info: %v\", m, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif !SameFile(info, lstat) {\n\t\t\t\tt.Errorf(\"%s: Info: SameFile(info, lstat) = false\", m)\n\t\t\t}\n\t\t}\n\t\tif !found {\n\t\t\tt.Error(\"could not find\", m)\n\t\t}\n\t}\n\tif s == nil {\n\t\tt.Error(\"ReadDir returned nil instead of empty slice\")\n\t}\n}\n\nfunc TestFileReaddirnames(t *testing.T) {\n\ttestReaddirnames(\".\", dot, t)\n\ttestReaddirnames(TempDir(), nil, t)\n}\n\nfunc TestFileReaddir(t *testing.T) {\n\ttestReaddir(\".\", dot, t)\n\ttestReaddir(TempDir(), nil, t)\n}\n\nfunc TestFileReadDir(t *testing.T) {\n\ttestReadDir(\".\", dot, t)\n\ttestReadDir(TempDir(), nil, t)\n}\n\nfunc TestReadDir(t *testing.T) {\n\tdirname := \"rumpelstilzchen\"\n\t_, err := ReadDir(dirname)\n\tif err == nil {\n\t\tt.Fatalf(\"ReadDir %s: error expected, none found\", dirname)\n\t}\n\n\tdirname = \"testdata\"\n\tlist, err := ReadDir(dirname)\n\tif err != nil {\n\t\tt.Fatalf(\"ReadDir %s: %v\", dirname, err)\n\t}\n\n\tfoundFile := false\n\tfoundSubDir := false\n\tfor _, dir := range list {\n\t\tswitch {\n\t\tcase !dir.IsDir() && dir.Name() == \"hello\":\n\t\t\tfoundFile = true\n\t\tcase dir.IsDir() && dir.Name() == \"issue37161\":\n\t\t\tfoundSubDir = true\n\t\t}\n\t}\n\tif !foundFile {\n\t\tt.Fatalf(\"ReadDir %s: hello file not found\", dirname)\n\t}\n\tif !foundSubDir {\n\t\tt.Fatalf(\"ReadDir %s: testdata directory not found\", dirname)\n\t}\n}\n\n// TestReadNonDir just verifies that opening a non-directory returns an error.\nfunc TestReadNonDir(t *testing.T) {\n\t// Use filename of this source file; it is known to exist, and go tests run in source tree.\n\tdirname := \"dir_test.go\"\n\t_, err := ReadDir(dirname)\n\tif err == nil {\n\t\tt.Fatalf(\"ReadDir %s: error on non-dir expected, none found\", dirname)\n\t}\n}\n"
  },
  {
    "path": "src/os/dir_unix.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build linux && !baremetal && !wasip1 && !wasip2 && !wasm_unknown && !nintendoswitch\n\npackage os\n\nimport (\n\t\"io\"\n\t\"syscall\"\n\t\"unsafe\"\n)\n\n// Auxiliary information if the File describes a directory\ntype dirInfo struct {\n\tnbuf int             // length of buf; return value from Getdirentries\n\tbufp int             // location of next record in buf.\n\tbuf  [blockSize]byte // buffer for directory I/O\n}\n\nconst (\n\t// More than 5760 to work around https://golang.org/issue/24015.\n\tblockSize = 8192 - 2*unsafe.Sizeof(int(0))\n)\n\nfunc (d *dirInfo) close() {\n}\n\nfunc (f *File) readdir(n int, mode readdirMode) (names []string, dirents []DirEntry, infos []FileInfo, err error) {\n\t// If this file has no dirinfo, create one.\n\tif f.dirinfo == nil {\n\t\tf.dirinfo = new(dirInfo)\n\t}\n\td := f.dirinfo\n\n\t// Change the meaning of n for the implementation below.\n\t//\n\t// The n above was for the public interface of \"if n <= 0,\n\t// Readdir returns all the FileInfo from the directory in a\n\t// single slice\".\n\t//\n\t// But below, we use only negative to mean looping until the\n\t// end and positive to mean bounded, with positive\n\t// terminating at 0.\n\tif n == 0 {\n\t\tn = -1\n\t}\n\n\tfor n != 0 {\n\t\t// Refill the buffer if necessary\n\t\tif d.bufp >= d.nbuf {\n\t\t\td.bufp = 0\n\t\t\tvar errno error\n\t\t\td.nbuf, errno = syscall.ReadDirent(syscallFd(f.handle.(unixFileHandle)), d.buf[:])\n\t\t\tif d.nbuf < 0 {\n\t\t\t\terrno = handleSyscallError(errno)\n\t\t\t}\n\t\t\tif errno != nil {\n\t\t\t\treturn names, dirents, infos, &PathError{Op: \"readdirent\", Path: f.name, Err: errno}\n\t\t\t}\n\t\t\tif d.nbuf <= 0 {\n\t\t\t\tbreak // EOF\n\t\t\t}\n\t\t}\n\n\t\t// Drain the buffer\n\t\tbuf := d.buf[d.bufp:d.nbuf]\n\t\treclen, ok := direntReclen(buf)\n\t\tif !ok || reclen > uint64(len(buf)) {\n\t\t\tbreak\n\t\t}\n\t\trec := buf[:reclen]\n\t\td.bufp += int(reclen)\n\t\tino, ok := direntIno(rec)\n\t\tif !ok {\n\t\t\tbreak\n\t\t}\n\t\tif ino == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tconst namoff = uint64(unsafe.Offsetof(syscall.Dirent{}.Name))\n\t\tnamlen, ok := direntNamlen(rec)\n\t\tif !ok || namoff+namlen > uint64(len(rec)) {\n\t\t\tbreak\n\t\t}\n\t\tname := rec[namoff : namoff+namlen]\n\t\tfor i, c := range name {\n\t\t\tif c == 0 {\n\t\t\t\tname = name[:i]\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\t// Check for useless names before allocating a string.\n\t\tif string(name) == \".\" || string(name) == \"..\" {\n\t\t\tcontinue\n\t\t}\n\t\tif n > 0 { // see 'n == 0' comment above\n\t\t\tn--\n\t\t}\n\t\tif mode == readdirName {\n\t\t\tnames = append(names, string(name))\n\t\t} else if mode == readdirDirEntry {\n\t\t\tde, err := newUnixDirent(f.name, string(name), direntType(rec))\n\t\t\tif IsNotExist(err) {\n\t\t\t\t// File disappeared between readdir and stat.\n\t\t\t\t// Treat as if it didn't exist.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\treturn nil, dirents, nil, err\n\t\t\t}\n\t\t\tdirents = append(dirents, de)\n\t\t} else {\n\t\t\tinfo, err := lstat(f.name + \"/\" + string(name))\n\t\t\tif IsNotExist(err) {\n\t\t\t\t// File disappeared between readdir + stat.\n\t\t\t\t// Treat as if it didn't exist.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, infos, err\n\t\t\t}\n\t\t\tinfos = append(infos, info)\n\t\t}\n\t}\n\n\tif n > 0 && len(names)+len(dirents)+len(infos) == 0 {\n\t\treturn nil, nil, nil, io.EOF\n\t}\n\treturn names, dirents, infos, nil\n}\n\n// readInt returns the size-bytes unsigned integer in native byte order at offset off.\nfunc readInt(b []byte, off, size uintptr) (u uint64, ok bool) {\n\tif len(b) < int(off+size) {\n\t\treturn 0, false\n\t}\n\tif isBigEndian {\n\t\treturn readIntBE(b[off:], size), true\n\t}\n\treturn readIntLE(b[off:], size), true\n}\n\nfunc readIntBE(b []byte, size uintptr) uint64 {\n\tswitch size {\n\tcase 1:\n\t\treturn uint64(b[0])\n\tcase 2:\n\t\t_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808\n\t\treturn uint64(b[1]) | uint64(b[0])<<8\n\tcase 4:\n\t\t_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808\n\t\treturn uint64(b[3]) | uint64(b[2])<<8 | uint64(b[1])<<16 | uint64(b[0])<<24\n\tcase 8:\n\t\t_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808\n\t\treturn uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |\n\t\t\tuint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56\n\tdefault:\n\t\tpanic(\"syscall: readInt with unsupported size\")\n\t}\n}\n\nfunc readIntLE(b []byte, size uintptr) uint64 {\n\tswitch size {\n\tcase 1:\n\t\treturn uint64(b[0])\n\tcase 2:\n\t\t_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808\n\t\treturn uint64(b[0]) | uint64(b[1])<<8\n\tcase 4:\n\t\t_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808\n\t\treturn uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24\n\tcase 8:\n\t\t_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808\n\t\treturn uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |\n\t\t\tuint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56\n\tdefault:\n\t\tpanic(\"syscall: readInt with unsupported size\")\n\t}\n}\n"
  },
  {
    "path": "src/os/dir_wasi.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file was derived from src/os/dir_darwin.go since the logic for WASI is\n// fairly similar: we use fdopendir, fdclosedir, and readdir from wasi-libc in\n// a similar way that the darwin code uses functions from libc.\n\n//go:build wasip1 || wasip2\n\npackage os\n\nimport (\n\t\"io\"\n\t\"runtime\"\n\t\"syscall\"\n\t\"unsafe\"\n)\n\n// opaque DIR* returned by fdopendir\n//\n// We add an unused field so it is not the empty struct, which is usually\n// a special case in Go.\ntype dirInfo struct{ _ int32 }\n\nfunc (d *dirInfo) close() {\n\tsyscall.Fdclosedir(uintptr(unsafe.Pointer(d)))\n}\n\nfunc (f *File) readdir(n int, mode readdirMode) (names []string, dirents []DirEntry, infos []FileInfo, err error) {\n\tif f.dirinfo == nil {\n\t\tdir, errno := syscall.Fdopendir(syscallFd(f.handle.(unixFileHandle)))\n\t\tif errno != nil {\n\t\t\treturn nil, nil, nil, &PathError{Op: \"fdopendir\", Path: f.name, Err: errno}\n\t\t}\n\t\tf.dirinfo = (*dirInfo)(unsafe.Pointer(dir))\n\t}\n\td := uintptr(unsafe.Pointer(f.dirinfo))\n\n\t// see src/os/dir_unix.go\n\tif n == 0 {\n\t\tn = -1\n\t}\n\n\tfor n != 0 {\n\t\tdirent, errno := syscall.Readdir(d)\n\t\tif errno != nil {\n\t\t\tif errno == syscall.EINTR {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn names, dirents, infos, &PathError{Op: \"readdir\", Path: f.name, Err: errno}\n\t\t}\n\t\tif dirent == nil { // EOF\n\t\t\tbreak\n\t\t}\n\t\tname := dirent.Name()\n\t\t// Check for useless names before allocating a string.\n\t\tif string(name) == \".\" || string(name) == \"..\" {\n\t\t\tcontinue\n\t\t}\n\t\tif n > 0 {\n\t\t\tn--\n\t\t}\n\t\tif mode == readdirName {\n\t\t\tnames = append(names, string(name))\n\t\t} else if mode == readdirDirEntry {\n\t\t\tde, err := newUnixDirent(f.name, string(name), dtToType(dirent.Type))\n\t\t\tif IsNotExist(err) {\n\t\t\t\t// File disappeared between readdir and stat.\n\t\t\t\t// Treat as if it didn't exist.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\treturn nil, dirents, nil, err\n\t\t\t}\n\t\t\tdirents = append(dirents, de)\n\t\t} else {\n\t\t\tinfo, err := lstat(f.name + \"/\" + string(name))\n\t\t\tif IsNotExist(err) {\n\t\t\t\t// File disappeared between readdir + stat.\n\t\t\t\t// Treat as if it didn't exist.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, infos, err\n\t\t\t}\n\t\t\tinfos = append(infos, info)\n\t\t}\n\t\truntime.KeepAlive(f)\n\t}\n\n\tif n > 0 && len(names)+len(dirents)+len(infos) == 0 {\n\t\treturn nil, nil, nil, io.EOF\n\t}\n\treturn names, dirents, infos, nil\n}\n\nfunc dtToType(typ uint8) FileMode {\n\tswitch typ {\n\tcase syscall.DT_BLK:\n\t\treturn ModeDevice\n\tcase syscall.DT_CHR:\n\t\treturn ModeDevice | ModeCharDevice\n\tcase syscall.DT_DIR:\n\t\treturn ModeDir\n\tcase syscall.DT_FIFO:\n\t\treturn ModeNamedPipe\n\tcase syscall.DT_LNK:\n\t\treturn ModeSymlink\n\tcase syscall.DT_REG:\n\t\treturn 0\n\t}\n\treturn ^FileMode(0)\n}\n"
  },
  {
    "path": "src/os/dirent_linux.go",
    "content": "//go:build !baremetal && !js && !wasip1 && !wasip2 && !wasm_unknown && !nintendoswitch\n\n// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os\n\nimport (\n\t\"syscall\"\n\t\"unsafe\"\n)\n\nfunc direntIno(buf []byte) (uint64, bool) {\n\treturn readInt(buf, unsafe.Offsetof(syscall.Dirent{}.Ino), unsafe.Sizeof(syscall.Dirent{}.Ino))\n}\n\nfunc direntReclen(buf []byte) (uint64, bool) {\n\treturn readInt(buf, unsafe.Offsetof(syscall.Dirent{}.Reclen), unsafe.Sizeof(syscall.Dirent{}.Reclen))\n}\n\nfunc direntNamlen(buf []byte) (uint64, bool) {\n\treclen, ok := direntReclen(buf)\n\tif !ok {\n\t\treturn 0, false\n\t}\n\treturn reclen - uint64(unsafe.Offsetof(syscall.Dirent{}.Name)), true\n}\n\nfunc direntType(buf []byte) FileMode {\n\toff := unsafe.Offsetof(syscall.Dirent{}.Type)\n\tif off >= uintptr(len(buf)) {\n\t\treturn ^FileMode(0) // unknown\n\t}\n\ttyp := buf[off]\n\tswitch typ {\n\tcase syscall.DT_BLK:\n\t\treturn ModeDevice\n\tcase syscall.DT_CHR:\n\t\treturn ModeDevice | ModeCharDevice\n\tcase syscall.DT_DIR:\n\t\treturn ModeDir\n\tcase syscall.DT_FIFO:\n\t\treturn ModeNamedPipe\n\tcase syscall.DT_LNK:\n\t\treturn ModeSymlink\n\tcase syscall.DT_REG:\n\t\treturn 0\n\tcase syscall.DT_SOCK:\n\t\treturn ModeSocket\n\t}\n\treturn ^FileMode(0) // unknown\n}\n"
  },
  {
    "path": "src/os/endian_little.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// TODO: exclude big endian targets here and include them in endian_big.go, once tinygo supports one\n\npackage os\n\nconst isBigEndian = false\n"
  },
  {
    "path": "src/os/env.go",
    "content": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// General environment variables.\n\npackage os\n\nimport (\n\t\"internal/testlog\"\n\t\"syscall\"\n)\n\n// Expand replaces ${var} or $var in the string based on the mapping function.\n// For example, os.ExpandEnv(s) is equivalent to os.Expand(s, os.Getenv).\nfunc Expand(s string, mapping func(string) string) string {\n\tvar buf []byte\n\t// ${} is all ASCII, so bytes are fine for this operation.\n\ti := 0\n\tfor j := 0; j < len(s); j++ {\n\t\tif s[j] == '$' && j+1 < len(s) {\n\t\t\tif buf == nil {\n\t\t\t\tbuf = make([]byte, 0, 2*len(s))\n\t\t\t}\n\t\t\tbuf = append(buf, s[i:j]...)\n\t\t\tname, w := getShellName(s[j+1:])\n\t\t\tif name == \"\" && w > 0 {\n\t\t\t\t// Encountered invalid syntax; eat the\n\t\t\t\t// characters.\n\t\t\t} else if name == \"\" {\n\t\t\t\t// Valid syntax, but $ was not followed by a\n\t\t\t\t// name. Leave the dollar character untouched.\n\t\t\t\tbuf = append(buf, s[j])\n\t\t\t} else {\n\t\t\t\tbuf = append(buf, mapping(name)...)\n\t\t\t}\n\t\t\tj += w\n\t\t\ti = j + 1\n\t\t}\n\t}\n\tif buf == nil {\n\t\treturn s\n\t}\n\treturn string(buf) + s[i:]\n}\n\n// ExpandEnv replaces ${var} or $var in the string according to the values\n// of the current environment variables. References to undefined\n// variables are replaced by the empty string.\nfunc ExpandEnv(s string) string {\n\treturn Expand(s, Getenv)\n}\n\n// isShellSpecialVar reports whether the character identifies a special\n// shell variable such as $*.\nfunc isShellSpecialVar(c uint8) bool {\n\tswitch c {\n\tcase '*', '#', '$', '@', '!', '?', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':\n\t\treturn true\n\t}\n\treturn false\n}\n\n// isAlphaNum reports whether the byte is an ASCII letter, number, or underscore\nfunc isAlphaNum(c uint8) bool {\n\treturn c == '_' || '0' <= c && c <= '9' || 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z'\n}\n\n// getShellName returns the name that begins the string and the number of bytes\n// consumed to extract it. If the name is enclosed in {}, it's part of a ${}\n// expansion and two more bytes are needed than the length of the name.\nfunc getShellName(s string) (string, int) {\n\tswitch {\n\tcase s[0] == '{':\n\t\tif len(s) > 2 && isShellSpecialVar(s[1]) && s[2] == '}' {\n\t\t\treturn s[1:2], 3\n\t\t}\n\t\t// Scan to closing brace\n\t\tfor i := 1; i < len(s); i++ {\n\t\t\tif s[i] == '}' {\n\t\t\t\tif i == 1 {\n\t\t\t\t\treturn \"\", 2 // Bad syntax; eat \"${}\"\n\t\t\t\t}\n\t\t\t\treturn s[1:i], i + 1\n\t\t\t}\n\t\t}\n\t\treturn \"\", 1 // Bad syntax; eat \"${\"\n\tcase isShellSpecialVar(s[0]):\n\t\treturn s[0:1], 1\n\t}\n\t// Scan alphanumerics.\n\tvar i int\n\tfor i = 0; i < len(s) && isAlphaNum(s[i]); i++ {\n\t}\n\treturn s[:i], i\n}\n\n// Getenv retrieves the value of the environment variable named by the key.\n// It returns the value, which will be empty if the variable is not present.\n// To distinguish between an empty value and an unset value, use LookupEnv.\nfunc Getenv(key string) string {\n\ttestlog.Getenv(key)\n\tv, _ := syscall.Getenv(key)\n\treturn v\n}\n\n// LookupEnv retrieves the value of the environment variable named\n// by the key. If the variable is present in the environment the\n// value (which may be empty) is returned and the boolean is true.\n// Otherwise the returned value will be empty and the boolean will\n// be false.\nfunc LookupEnv(key string) (string, bool) {\n\ttestlog.Getenv(key)\n\treturn syscall.Getenv(key)\n}\n\n// Setenv sets the value of the environment variable named by the key.\n// It returns an error, if any.\nfunc Setenv(key, value string) error {\n\terr := syscall.Setenv(key, value)\n\tif err != nil {\n\t\treturn NewSyscallError(\"setenv\", err)\n\t}\n\treturn nil\n}\n\n// Unsetenv unsets a single environment variable.\nfunc Unsetenv(key string) error {\n\treturn syscall.Unsetenv(key)\n}\n\n// Clearenv deletes all environment variables.\nfunc Clearenv() {\n\tsyscall.Clearenv()\n}\n\n// Environ returns a copy of strings representing the environment,\n// in the form \"key=value\".\nfunc Environ() []string {\n\treturn syscall.Environ()\n}\n"
  },
  {
    "path": "src/os/env_test.go",
    "content": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os_test\n\nimport (\n\t. \"os\"\n\t\"reflect\"\n\t\"strings\"\n\t\"testing\"\n)\n\n// testGetenv gives us a controlled set of variables for testing Expand.\nfunc testGetenv(s string) string {\n\tswitch s {\n\tcase \"*\":\n\t\treturn \"all the args\"\n\tcase \"#\":\n\t\treturn \"NARGS\"\n\tcase \"$\":\n\t\treturn \"PID\"\n\tcase \"1\":\n\t\treturn \"ARGUMENT1\"\n\tcase \"HOME\":\n\t\treturn \"/usr/gopher\"\n\tcase \"H\":\n\t\treturn \"(Value of H)\"\n\tcase \"home_1\":\n\t\treturn \"/usr/foo\"\n\tcase \"_\":\n\t\treturn \"underscore\"\n\t}\n\treturn \"\"\n}\n\nvar expandTests = []struct {\n\tin, out string\n}{\n\t{\"\", \"\"},\n\t{\"$*\", \"all the args\"},\n\t{\"$$\", \"PID\"},\n\t{\"${*}\", \"all the args\"},\n\t{\"$1\", \"ARGUMENT1\"},\n\t{\"${1}\", \"ARGUMENT1\"},\n\t{\"now is the time\", \"now is the time\"},\n\t{\"$HOME\", \"/usr/gopher\"},\n\t{\"$home_1\", \"/usr/foo\"},\n\t{\"${HOME}\", \"/usr/gopher\"},\n\t{\"${H}OME\", \"(Value of H)OME\"},\n\t{\"A$$$#$1$H$home_1*B\", \"APIDNARGSARGUMENT1(Value of H)/usr/foo*B\"},\n\t{\"start$+middle$^end$\", \"start$+middle$^end$\"},\n\t{\"mixed$|bag$$$\", \"mixed$|bagPID$\"},\n\t{\"$\", \"$\"},\n\t{\"$}\", \"$}\"},\n\t{\"${\", \"\"},  // invalid syntax; eat up the characters\n\t{\"${}\", \"\"}, // invalid syntax; eat up the characters\n}\n\nfunc TestExpand(t *testing.T) {\n\tfor _, test := range expandTests {\n\t\tresult := Expand(test.in, testGetenv)\n\t\tif result != test.out {\n\t\t\tt.Errorf(\"Expand(%q)=%q; expected %q\", test.in, result, test.out)\n\t\t}\n\t}\n}\n\nvar global interface{}\n\nfunc BenchmarkExpand(b *testing.B) {\n\tb.Run(\"noop\", func(b *testing.B) {\n\t\tvar s string\n\t\tb.ReportAllocs()\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\ts = Expand(\"tick tick tick tick\", func(string) string { return \"\" })\n\t\t}\n\t\tglobal = s\n\t})\n\tb.Run(\"multiple\", func(b *testing.B) {\n\t\tvar s string\n\t\tb.ReportAllocs()\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\ts = Expand(\"$a $a $a $a\", func(string) string { return \"boom\" })\n\t\t}\n\t\tglobal = s\n\t})\n}\n\nfunc TestConsistentEnviron(t *testing.T) {\n\te0 := Environ()\n\tfor i := 0; i < 10; i++ {\n\t\te1 := Environ()\n\t\tif !reflect.DeepEqual(e0, e1) {\n\t\t\tt.Fatalf(\"environment changed\")\n\t\t}\n\t}\n}\n\nfunc TestUnsetenv(t *testing.T) {\n\tconst testKey = \"GO_TEST_UNSETENV\"\n\tset := func() bool {\n\t\tprefix := testKey + \"=\"\n\t\tfor _, key := range Environ() {\n\t\t\tif strings.HasPrefix(key, prefix) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\tif err := Setenv(testKey, \"1\"); err != nil {\n\t\tt.Fatalf(\"Setenv: %v\", err)\n\t}\n\tif !set() {\n\t\tt.Error(\"Setenv didn't set TestUnsetenv\")\n\t}\n\tif err := Unsetenv(testKey); err != nil {\n\t\tt.Fatalf(\"Unsetenv: %v\", err)\n\t}\n\tif set() {\n\t\tt.Fatal(\"Unsetenv didn't clear TestUnsetenv\")\n\t}\n}\n\nfunc TestClearenv(t *testing.T) {\n\tconst testKey = \"GO_TEST_CLEARENV\"\n\tconst testValue = \"1\"\n\n\t// reset env\n\tdefer func(origEnv []string) {\n\t\tfor _, pair := range origEnv {\n\t\t\t// Environment variables on Windows can begin with =\n\t\t\t// https://blogs.msdn.com/b/oldnewthing/archive/2010/05/06/10008132.aspx\n\t\t\ti := strings.Index(pair[1:], \"=\") + 1\n\t\t\tif err := Setenv(pair[:i], pair[i+1:]); err != nil {\n\t\t\t\tt.Errorf(\"Setenv(%q, %q) failed during reset: %v\", pair[:i], pair[i+1:], err)\n\t\t\t}\n\t\t}\n\t}(Environ())\n\n\tif err := Setenv(testKey, testValue); err != nil {\n\t\tt.Fatalf(\"Setenv(%q, %q) failed: %v\", testKey, testValue, err)\n\t}\n\tif _, ok := LookupEnv(testKey); !ok {\n\t\tt.Errorf(\"Setenv(%q, %q) didn't set $%s\", testKey, testValue, testKey)\n\t}\n\tClearenv()\n\tif val, ok := LookupEnv(testKey); ok {\n\t\tt.Errorf(\"Clearenv() didn't clear $%s, remained with value %q\", testKey, val)\n\t}\n}\n\nfunc TestLookupEnv(t *testing.T) {\n\tconst smallpox = \"SMALLPOX\"      // No one has smallpox.\n\tvalue, ok := LookupEnv(smallpox) // Should not exist.\n\tif ok || value != \"\" {\n\t\tt.Fatalf(\"%s=%q\", smallpox, value)\n\t}\n\tdefer Unsetenv(smallpox)\n\terr := Setenv(smallpox, \"virus\")\n\tif err != nil {\n\t\tt.Fatalf(\"failed to release smallpox virus\")\n\t}\n\t_, ok = LookupEnv(smallpox)\n\tif !ok {\n\t\tt.Errorf(\"smallpox release failed; world remains safe but LookupEnv is broken\")\n\t}\n}\n\n// On Windows, Environ was observed to report keys with a single leading \"=\".\n// Check that they are properly reported by LookupEnv and can be set by SetEnv.\n// See https://golang.org/issue/49886.\nfunc TestEnvironConsistency(t *testing.T) {\n\tfor _, kv := range Environ() {\n\t\ti := strings.Index(kv, \"=\")\n\t\tif i == 0 {\n\t\t\t// We observe in practice keys with a single leading \"=\" on Windows.\n\t\t\t// TODO(#49886): Should we consume only the first leading \"=\" as part\n\t\t\t// of the key, or parse through arbitrarily many of them until a non-=,\n\t\t\t// or try each possible key/value boundary until LookupEnv succeeds?\n\t\t\ti = strings.Index(kv[1:], \"=\") + 1\n\t\t}\n\t\tif i < 0 {\n\t\t\tt.Errorf(\"Environ entry missing '=': %q\", kv)\n\t\t}\n\n\t\tk := kv[:i]\n\t\tv := kv[i+1:]\n\t\tv2, ok := LookupEnv(k)\n\t\tif ok && v == v2 {\n\t\t\t//t.Logf(\"LookupEnv(%q) = %q, %t\", k, v2, ok)\n\t\t} else {\n\t\t\tt.Errorf(\"Environ contains %q, but LookupEnv(%q) = %q, %t\", kv, k, v2, ok)\n\t\t}\n\n\t\t// Since k=v is already present in the environment,\n\t\t// setting it should be a no-op.\n\t\tif err := Setenv(k, v); err == nil {\n\t\t\t//t.Logf(\"Setenv(%q, %q)\", k, v)\n\t\t} else {\n\t\t\tt.Errorf(\"Environ contains %q, but SetEnv(%q, %q) = %q\", kv, k, v, err)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/os/env_unix_test.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build darwin || linux || wasip1 || wasip2\n\npackage os_test\n\nimport (\n\t\"fmt\"\n\t. \"os\"\n\t\"testing\"\n)\n\nvar setenvEinvalTests = []struct {\n\tk, v string\n}{\n\t{\"\", \"\"},      // empty key\n\t{\"k=v\", \"\"},   // '=' in key\n\t{\"\\x00\", \"\"},  // '\\x00' in key\n\t{\"k\", \"\\x00\"}, // '\\x00' in value\n}\n\nfunc TestSetenvUnixEinval(t *testing.T) {\n\tfor _, tt := range setenvEinvalTests {\n\t\terr := Setenv(tt.k, tt.v)\n\t\tif err == nil {\n\t\t\tt.Errorf(`Setenv(%q, %q) == nil, want error`, tt.k, tt.v)\n\t\t}\n\t}\n}\n\nvar shellSpecialVarTests = []struct {\n\tk, v string\n}{\n\t{\"*\", \"asterisk\"},\n\t{\"#\", \"pound\"},\n\t{\"$\", \"dollar\"},\n\t{\"@\", \"at\"},\n\t{\"!\", \"exclamation mark\"},\n\t{\"?\", \"question mark\"},\n\t{\"-\", \"dash\"},\n}\n\nfunc TestExpandEnvShellSpecialVar(t *testing.T) {\n\tfor _, tt := range shellSpecialVarTests {\n\t\tSetenv(tt.k, tt.v)\n\t\tdefer Unsetenv(tt.k)\n\n\t\targRaw := fmt.Sprintf(\"$%s\", tt.k)\n\t\targWithBrace := fmt.Sprintf(\"${%s}\", tt.k)\n\t\tif gotRaw, gotBrace := ExpandEnv(argRaw), ExpandEnv(argWithBrace); gotRaw != gotBrace {\n\t\t\tt.Errorf(\"ExpandEnv(%q) = %q, ExpandEnv(%q) = %q; expect them to be equal\", argRaw, gotRaw, argWithBrace, gotBrace)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/os/errors.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os\n\nimport (\n\t\"errors\"\n\t\"io/fs\"\n\t\"syscall\"\n)\n\n// Portable analogs of some common system call errors.\n//\n// Errors returned from this package may be tested against these errors\n// with errors.Is.\nvar (\n\t// ErrInvalid indicates an invalid argument.\n\t// Methods on File will return this error when the receiver is nil.\n\tErrInvalid = fs.ErrInvalid // \"invalid argument\"\n\n\tErrPermission = fs.ErrPermission // \"permission denied\"\n\tErrExist      = fs.ErrExist      // \"file already exists\"\n\tErrNotExist   = fs.ErrNotExist   // \"file does not exist\"\n\tErrClosed     = fs.ErrClosed     // \"file already closed\"\n\n\t// Note that these are exported for use in the Filesystem interface.\n\tErrUnsupported    = errors.New(\"operation not supported\")\n\tErrNotImplemented = errors.New(\"operation not implemented\")\n)\n\n// The following code is copied from the official implementation.\n// src/internal/poll/fd.go\n\n// ErrNoDeadline is returned when a request is made to set a deadline\n// on a file type that does not use the poller.\nvar ErrNoDeadline = errors.New(\"file type does not support deadline\")\n\n// ErrDeadlineExceeded is returned for an expired deadline.\n// This is exported by the os package as os.ErrDeadlineExceeded.\nvar ErrDeadlineExceeded error = &DeadlineExceededError{}\n\n// DeadlineExceededError is returned for an expired deadline.\ntype DeadlineExceededError struct{}\n\n// Implement the net.Error interface.\n// The string is \"i/o timeout\" because that is what was returned\n// by earlier Go versions. Changing it may break programs that\n// match on error strings.\nfunc (e *DeadlineExceededError) Error() string   { return \"i/o timeout\" }\nfunc (e *DeadlineExceededError) Timeout() bool   { return true }\nfunc (e *DeadlineExceededError) Temporary() bool { return true }\n\n// The following code is copied from the official implementation.\n// https://github.com/golang/go/blob/4ce6a8e89668b87dce67e2f55802903d6eb9110a/src/os/error.go#L65-L104\n\nfunc NewSyscallError(syscall string, err error) error {\n\tif err == nil {\n\t\treturn nil\n\t}\n\treturn &SyscallError{syscall, err}\n}\n\n// PathError records an error and the operation and file path that caused it.\ntype PathError = fs.PathError\n\n// SyscallError records an error from a specific system call.\ntype SyscallError struct {\n\tSyscall string\n\tErr     error\n}\n\nfunc (e *SyscallError) Error() string { return e.Syscall + \": \" + e.Err.Error() }\n\nfunc (e *SyscallError) Unwrap() error { return e.Err }\n\ntype timeout interface {\n\tTimeout() bool\n}\n\n// Timeout reports whether this error represents a timeout.\nfunc (e *SyscallError) Timeout() bool {\n\tt, ok := e.Err.(timeout)\n\treturn ok && t.Timeout()\n}\n\nfunc IsExist(err error) bool {\n\treturn underlyingErrorIs(err, ErrExist)\n}\n\nfunc IsNotExist(err error) bool {\n\treturn underlyingErrorIs(err, ErrNotExist)\n}\n\nfunc IsPermission(err error) bool {\n\treturn underlyingErrorIs(err, ErrPermission)\n}\n\nfunc IsTimeout(err error) bool {\n\tterr, ok := underlyingError(err).(timeout)\n\treturn ok && terr.Timeout()\n}\n\nfunc underlyingErrorIs(err, target error) bool {\n\t// Note that this function is not errors.Is:\n\t// underlyingError only unwraps the specific error-wrapping types\n\t// that it historically did, not all errors implementing Unwrap().\n\terr = underlyingError(err)\n\tif err == target {\n\t\treturn true\n\t}\n\t// To preserve prior behavior, only examine syscall errors.\n\te, ok := err.(syscall.Errno)\n\treturn ok && e.Is(target)\n}\n\n// underlyingError returns the underlying error for known os error types.\nfunc underlyingError(err error) error {\n\tswitch err := err.(type) {\n\tcase *PathError:\n\t\treturn err.Err\n\tcase *SyscallError:\n\t\treturn err.Err\n\t}\n\treturn err\n}\n"
  },
  {
    "path": "src/os/exec/exec.go",
    "content": "package exec\n\nimport \"os\"\n\n// An ExitError reports an unsuccessful exit by a command.\ntype ExitError struct {\n\t*os.ProcessState\n\n\t// Stderr holds a subset of the standard error output from the\n\t// Cmd.Output method if standard error was not otherwise being\n\t// collected.\n\t//\n\t// If the error output is long, Stderr may contain only a prefix\n\t// and suffix of the output, with the middle replaced with\n\t// text about the number of omitted bytes.\n\t//\n\t// Stderr is provided for debugging, for inclusion in error messages.\n\t// Users with other needs should redirect Cmd.Stderr as needed.\n\tStderr []byte\n}\n\nfunc (e *ExitError) Error() string {\n\treturn e.ProcessState.String()\n}\n"
  },
  {
    "path": "src/os/exec.go",
    "content": "package os\n\nimport (\n\t\"errors\"\n\t\"syscall\"\n)\n\nvar (\n\tErrNotImplementedDir   = errors.New(\"directory setting not implemented\")\n\tErrNotImplementedSys   = errors.New(\"sys setting not implemented\")\n\tErrNotImplementedFiles = errors.New(\"files setting not implemented\")\n)\n\ntype Signal interface {\n\tString() string\n\tSignal() // to distinguish from other Stringers\n}\n\n// Getpid returns the process id of the caller, or -1 if unavailable.\nfunc Getpid() int {\n\treturn syscall.Getpid()\n}\n\n// Getppid returns the process id of the caller's parent, or -1 if unavailable.\nfunc Getppid() int {\n\treturn syscall.Getppid()\n}\n\ntype ProcAttr struct {\n\tDir   string\n\tEnv   []string\n\tFiles []*File\n\tSys   *syscall.SysProcAttr\n}\n\n// ErrProcessDone indicates a Process has finished.\nvar ErrProcessDone = errors.New(\"os: process already finished\")\n\ntype ProcessState struct {\n}\n\nfunc (p *ProcessState) String() string {\n\treturn \"\" // TODO\n}\nfunc (p *ProcessState) Success() bool {\n\treturn false // TODO\n}\n\n// Sys returns system-dependent exit information about\n// the process. Convert it to the appropriate underlying\n// type, such as syscall.WaitStatus on Unix, to access its contents.\nfunc (p *ProcessState) Sys() interface{} {\n\treturn nil // TODO\n}\n\nfunc (p *ProcessState) Exited() bool {\n\treturn false // TODO\n}\n\n// ExitCode returns the exit code of the exited process, or -1\n// if the process hasn't exited or was terminated by a signal.\nfunc (p *ProcessState) ExitCode() int {\n\treturn -1 // TODO\n}\n\ntype Process struct {\n\tPid int\n}\n\n// StartProcess starts a new process with the program, arguments and attributes specified by name, argv and attr.\n// Arguments to the process (os.Args) are passed via argv.\nfunc StartProcess(name string, argv []string, attr *ProcAttr) (*Process, error) {\n\treturn startProcess(name, argv, attr)\n}\n\nfunc (p *Process) Wait() (*ProcessState, error) {\n\tif p.Pid == -1 {\n\t\treturn nil, syscall.EINVAL\n\t}\n\treturn nil, ErrNotImplemented\n}\n\nfunc (p *Process) Kill() error {\n\treturn ErrNotImplemented\n}\n\nfunc (p *Process) Signal(sig Signal) error {\n\treturn ErrNotImplemented\n}\n\nfunc Ignore(sig ...Signal) {\n\t// leave all the signals unaltered\n\treturn\n}\n\n// Release releases any resources associated with the Process p,\n// rendering it unusable in the future.\n// Release only needs to be called if Wait is not.\nfunc (p *Process) Release() error {\n\treturn p.release()\n}\n\n// FindProcess looks for a running process by its pid.\n// Keep compatibility with golang and always succeed and return new proc with pid on Linux.\nfunc FindProcess(pid int) (*Process, error) {\n\treturn findProcess(pid)\n}\n"
  },
  {
    "path": "src/os/exec_linux.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build linux && !baremetal && !tinygo.wasm && !nintendoswitch\n\npackage os\n\nimport (\n\t\"errors\"\n\t\"runtime\"\n\t\"syscall\"\n)\n\n// The only signal values guaranteed to be present in the os package on all\n// systems are os.Interrupt (send the process an interrupt) and os.Kill (force\n// the process to exit). On Windows, sending os.Interrupt to a process with\n// os.Process.Signal is not implemented; it will return an error instead of\n// sending a signal.\nvar (\n\tInterrupt Signal = syscall.SIGINT\n\tKill      Signal = syscall.SIGKILL\n)\n\n// Keep compatible with golang and always succeed and return new proc with pid on Linux.\nfunc findProcess(pid int) (*Process, error) {\n\treturn &Process{Pid: pid}, nil\n}\n\nfunc (p *Process) release() error {\n\t// NOOP for unix.\n\tp.Pid = -1\n\t// no need for a finalizer anymore\n\truntime.SetFinalizer(p, nil)\n\treturn nil\n}\n\n// This function is a wrapper around the forkExec function, which is a wrapper around the fork and execve system calls.\n// The StartProcess function creates a new process by forking the current process and then calling execve to replace the current process with the new process.\n// It thereby replaces the newly created process with the specified command and arguments.\n// Differences to upstream golang implementation (https://cs.opensource.google/go/go/+/master:src/syscall/exec_unix.go;l=143):\n// * No setting of Process Attributes\n// * Ignoring Ctty\n// * No ForkLocking (might be introduced by #4273)\n// * No parent-child communication via pipes (TODO)\n// * No waiting for crashes child processes to prohibit zombie process accumulation / Wait status checking (TODO)\nfunc forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) {\n\tif argv == nil {\n\t\treturn 0, errors.New(\"exec: no argv\")\n\t}\n\n\tif len(argv) == 0 {\n\t\treturn 0, errors.New(\"exec: no argv\")\n\t}\n\n\tif attr == nil {\n\t\tattr = new(ProcAttr)\n\t}\n\n\tp, err := fork()\n\tpid = int(p)\n\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\t// else code runs in child, which then should exec the new process\n\terr = execve(argv0, argv, attr.Env)\n\tif err != nil {\n\t\t// exec failed\n\t\treturn 0, err\n\t}\n\t// 3. TODO: use pipes to communicate back child status\n\treturn pid, nil\n}\n\n// In Golang, the idiomatic way to create a new process is to use the StartProcess function.\n// Since the Model of operating system processes in tinygo differs from the one in Golang, we need to implement the StartProcess function differently.\n// The startProcess function is a wrapper around the forkExec function, which is a wrapper around the fork and execve system calls.\n// The StartProcess function creates a new process by forking the current process and then calling execve to replace the current process with the new process.\n// It thereby replaces the newly created process with the specified command and arguments.\nfunc startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {\n\tif attr != nil {\n\t\tif attr.Dir != \"\" {\n\t\t\treturn nil, ErrNotImplementedDir\n\t\t}\n\n\t\tif attr.Sys != nil {\n\t\t\treturn nil, ErrNotImplementedSys\n\t\t}\n\n\t\tif len(attr.Files) != 0 {\n\t\t\treturn nil, ErrNotImplementedFiles\n\t\t}\n\t}\n\n\tpid, err := forkExec(name, argv, attr)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn findProcess(pid)\n}\n"
  },
  {
    "path": "src/os/exec_linux_test.go",
    "content": "//go:build linux && !baremetal && !tinygo.wasm\n\npackage os_test\n\nimport (\n\t\"errors\"\n\t. \"os\"\n\t\"runtime\"\n\t\"syscall\"\n\t\"testing\"\n)\n\n// Test the functionality of the forkExec function, which is used to fork and exec a new process.\n// This test is not run on Windows, as forkExec is not supported on Windows.\n// This test is not run on Plan 9, as forkExec is not supported on Plan 9.\nfunc TestForkExec(t *testing.T) {\n\tif runtime.GOOS != \"linux\" {\n\t\tt.Logf(\"skipping test on %s\", runtime.GOOS)\n\t\treturn\n\t}\n\n\tproc, err := StartProcess(\"/bin/echo\", []string{\"hello\", \"world\"}, &ProcAttr{})\n\tif !errors.Is(err, nil) {\n\t\tt.Fatalf(\"forkExec failed: %v\", err)\n\t}\n\n\tif proc == nil {\n\t\tt.Fatalf(\"proc is nil\")\n\t}\n\n\tif proc.Pid == 0 {\n\t\tt.Fatalf(\"forkExec failed: new process has pid 0\")\n\t}\n}\n\nfunc TestForkExecErrNotExist(t *testing.T) {\n\tproc, err := StartProcess(\"invalid\", []string{\"invalid\"}, &ProcAttr{})\n\tif !errors.Is(err, ErrNotExist) {\n\t\tt.Fatalf(\"wanted ErrNotExist, got %s\\n\", err)\n\t}\n\n\tif proc != nil {\n\t\tt.Fatalf(\"wanted nil, got %v\\n\", proc)\n\t}\n}\n\nfunc TestForkExecProcDir(t *testing.T) {\n\tproc, err := StartProcess(\"/bin/echo\", []string{\"hello\", \"world\"}, &ProcAttr{Dir: \"dir\"})\n\tif !errors.Is(err, ErrNotImplementedDir) {\n\t\tt.Fatalf(\"wanted ErrNotImplementedDir, got %v\\n\", err)\n\t}\n\n\tif proc != nil {\n\t\tt.Fatalf(\"wanted nil, got %v\\n\", proc)\n\t}\n}\n\nfunc TestForkExecProcSys(t *testing.T) {\n\tproc, err := StartProcess(\"/bin/echo\", []string{\"hello\", \"world\"}, &ProcAttr{Sys: &syscall.SysProcAttr{}})\n\tif !errors.Is(err, ErrNotImplementedSys) {\n\t\tt.Fatalf(\"wanted ErrNotImplementedSys, got %v\\n\", err)\n\t}\n\n\tif proc != nil {\n\t\tt.Fatalf(\"wanted nil, got %v\\n\", proc)\n\t}\n}\n\nfunc TestForkExecProcFiles(t *testing.T) {\n\tproc, err := StartProcess(\"/bin/echo\", []string{\"hello\", \"world\"}, &ProcAttr{Files: []*File{}})\n\tif !errors.Is(err, ErrNotImplementedFiles) {\n\t\tt.Fatalf(\"wanted ErrNotImplementedFiles, got %v\\n\", err)\n\t}\n\n\tif proc != nil {\n\t\tt.Fatalf(\"wanted nil, got %v\\n\", proc)\n\t}\n}\n"
  },
  {
    "path": "src/os/exec_other.go",
    "content": "//go:build (!aix && !android && !freebsd && !linux && !netbsd && !openbsd && !plan9 && !solaris) || baremetal || tinygo.wasm || nintendoswitch\n\npackage os\n\nimport \"syscall\"\n\nvar (\n\tInterrupt Signal = syscall.SIGINT\n\tKill      Signal = syscall.SIGKILL\n)\n\nfunc findProcess(pid int) (*Process, error) {\n\treturn &Process{Pid: pid}, nil\n}\n\nfunc (p *Process) release() error {\n\tp.Pid = -1\n\treturn nil\n}\n\nfunc forkExec(_ string, _ []string, _ *ProcAttr) (pid int, err error) {\n\treturn 0, ErrNotImplemented\n}\n\nfunc startProcess(_ string, _ []string, _ *ProcAttr) (proc *Process, err error) {\n\treturn &Process{Pid: 0}, ErrNotImplemented\n}\n"
  },
  {
    "path": "src/os/exec_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os_test\n\nimport (\n\t. \"os\"\n\t\"testing\"\n)\n\nfunc TestFindProcess(t *testing.T) {\n\t// NOTE: For now, we only test the Linux case since only exec_posix.go is currently the only implementation.\n\t// Linux guarantees that there is pid 0\n\tproc, err := FindProcess(0)\n\tif err != nil {\n\t\tt.Error(\"FindProcess(0): wanted err == nil, got %v:\", err)\n\t}\n\n\tif proc.Pid != 0 {\n\t\tt.Error(\"Expected pid 0, got: \", proc.Pid)\n\t}\n\n\tpid0 := Process{Pid: 0}\n\tif *proc != pid0 {\n\t\tt.Error(\"Expected &Process{Pid: 0}, got\", *proc)\n\t}\n}\n"
  },
  {
    "path": "src/os/executable_darwin.go",
    "content": "//go:build darwin\n\npackage os\n\n// via runtime because we need argc/argv ptrs\nfunc runtime_executable_path() string\n\nfunc Executable() (string, error) {\n\tp := runtime_executable_path()\n\tif p != \"\" && p[0] == '/' {\n\t\t// absolute path\n\t\treturn p, nil\n\t}\n\tcwd, err := Getwd()\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn joinPath(cwd, p), nil\n}\n"
  },
  {
    "path": "src/os/executable_other.go",
    "content": "//go:build (!linux && !darwin) || baremetal\n\npackage os\n\nimport \"errors\"\n\nfunc Executable() (string, error) {\n\treturn \"\", errors.New(\"Executable not implemented\")\n}\n"
  },
  {
    "path": "src/os/executable_procfs.go",
    "content": "// The following is copied from Go 1.17 official implementation.\n\n// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build linux && !baremetal\n\npackage os\n\nfunc Executable() (string, error) {\n\tpath, err := Readlink(\"/proc/self/exe\")\n\n\t// When the executable has been deleted then Readlink returns a\n\t// path appended with \" (deleted)\".\n\treturn stringsTrimSuffix(path, \" (deleted)\"), err\n}\n\n// stringsTrimSuffix is the same as strings.TrimSuffix.\nfunc stringsTrimSuffix(s, suffix string) string {\n\tif len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix {\n\t\treturn s[:len(s)-len(suffix)]\n\t}\n\treturn s\n}\n"
  },
  {
    "path": "src/os/export_test.go",
    "content": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os\n\n// Export for testing.\n\nvar ErrWriteAtInAppendMode = errWriteAtInAppendMode\nvar ErrPatternHasSeparator = errPatternHasSeparator\n"
  },
  {
    "path": "src/os/export_windows_test.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os\n\n// Export for testing.\n\nvar (\n\tFixLongPath     = fixLongPath\n\tCanUseLongPaths = canUseLongPaths\n)\n"
  },
  {
    "path": "src/os/file.go",
    "content": "// Portions copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file was originally copied from Go, see:\n// https://github.com/golang/go/blob/master/src/os/file.go\n//\n// Some of the code inherited from Go is not used anymore in Tinygo, but we keep\n// changes to a minimum to help simplify bringing changes (e.g. the lstat global\n// is not used here anymore, but we might need it if we add tests from Go in\n// this package).\n\n// Package os implements a subset of the Go \"os\" package. See\n// https://godoc.org/os for details.\n//\n// Note that the current implementation is blocking. This limitation should be\n// removed in a future version.\npackage os\n\nimport (\n\t\"errors\"\n\t\"io\"\n\t\"io/fs\"\n\t\"runtime\"\n\t\"syscall\"\n\t\"time\"\n)\n\n// Seek whence values.\n//\n// Deprecated: Use io.SeekStart, io.SeekCurrent, and io.SeekEnd.\nconst (\n\tSEEK_SET int = io.SeekStart\n\tSEEK_CUR int = io.SeekCurrent\n\tSEEK_END int = io.SeekEnd\n)\n\n// lstat is overridden in tests.\nvar lstat = Lstat\n\n// Mkdir creates a directory. If the operation fails, it will return an error of\n// type *PathError.\nfunc Mkdir(path string, perm FileMode) error {\n\tfs, suffix := findMount(path)\n\tif fs == nil {\n\t\treturn &PathError{Op: \"mkdir\", Path: path, Err: ErrNotExist}\n\t}\n\terr := fs.Mkdir(suffix, perm)\n\tif err != nil {\n\t\treturn &PathError{Op: \"mkdir\", Path: path, Err: err}\n\t}\n\treturn nil\n}\n\n// Many functions in package syscall return a count of -1 instead of 0.\n// Using fixCount(call()) instead of call() corrects the count.\nfunc fixCount(n int, err error) (int, error) {\n\tif n < 0 {\n\t\tn = 0\n\t}\n\treturn n, err\n}\n\n// Remove removes a file or (empty) directory. If the operation fails, it will\n// return an error of type *PathError.\nfunc Remove(path string) error {\n\tfs, suffix := findMount(path)\n\tif fs == nil {\n\t\treturn &PathError{Op: \"remove\", Path: path, Err: ErrNotExist}\n\t}\n\terr := fs.Remove(suffix)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// Name returns the name of the file with which it was opened.\nfunc (f *File) Name() string {\n\treturn f.name\n}\n\n// OpenFile opens the named file. If the operation fails, the returned error\n// will be of type *PathError.\nfunc OpenFile(name string, flag int, perm FileMode) (*File, error) {\n\tfs, suffix := findMount(name)\n\tif fs == nil {\n\t\treturn nil, &PathError{Op: \"open\", Path: name, Err: ErrNotExist}\n\t}\n\thandle, err := fs.OpenFile(suffix, flag, perm)\n\tif err != nil {\n\t\treturn nil, &PathError{Op: \"open\", Path: name, Err: err}\n\t}\n\tf := NewFile(handle, name)\n\tf.appendMode = (flag & O_APPEND) != 0\n\treturn f, nil\n}\n\n// Open opens the file named for reading.\nfunc Open(name string) (*File, error) {\n\treturn OpenFile(name, O_RDONLY, 0)\n}\n\n// Create creates the named file, overwriting it if it already exists.\nfunc Create(name string) (*File, error) {\n\treturn OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)\n}\n\n// Read reads up to len(b) bytes from the File. It returns the number of bytes\n// read and any error encountered. At end of file, Read returns 0, io.EOF.\nfunc (f *File) Read(b []byte) (n int, err error) {\n\tif f.handle == nil {\n\t\terr = ErrClosed\n\t} else {\n\t\tn, err = f.handle.Read(b)\n\t}\n\t// TODO: want to always wrap, like upstream, but ReadFile() compares against exactly io.EOF?\n\tif err != nil && err != io.EOF {\n\t\terr = &PathError{Op: \"read\", Path: f.name, Err: err}\n\t}\n\treturn\n}\n\nvar errNegativeOffset = errors.New(\"negative offset\")\n\n// ReadAt reads up to len(b) bytes from the File at the given absolute offset.\n// It returns the number of bytes read and any error encountered, possible io.EOF.\n// At end of file, Read returns 0, io.EOF.\nfunc (f *File) ReadAt(b []byte, offset int64) (n int, err error) {\n\tif offset < 0 {\n\t\treturn 0, &PathError{Op: \"readat\", Path: f.name, Err: errNegativeOffset}\n\t}\n\tif f.handle == nil {\n\t\treturn 0, &PathError{Op: \"readat\", Path: f.name, Err: ErrClosed}\n\t}\n\n\tfor len(b) > 0 {\n\t\tm, e := f.handle.ReadAt(b, offset)\n\t\tif e != nil {\n\t\t\t// TODO: want to always wrap, like upstream, but TestReadAtEOF compares against exactly io.EOF?\n\t\t\tif e != io.EOF {\n\t\t\t\terr = &PathError{Op: \"readat\", Path: f.name, Err: e}\n\t\t\t} else {\n\t\t\t\terr = e\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t\tn += m\n\t\tb = b[m:]\n\t\toffset += int64(m)\n\t}\n\n\treturn\n}\n\n// Write writes len(b) bytes to the File. It returns the number of bytes written\n// and an error, if any. Write returns a non-nil error when n != len(b).\nfunc (f *File) Write(b []byte) (n int, err error) {\n\tif f.handle == nil {\n\t\terr = ErrClosed\n\t} else {\n\t\tn, err = f.handle.Write(b)\n\t}\n\tif err != nil {\n\t\terr = &PathError{Op: \"write\", Path: f.name, Err: err}\n\t}\n\treturn\n}\n\n// WriteString is like Write, but writes the contents of string s rather than a\n// slice of bytes.\nfunc (f *File) WriteString(s string) (n int, err error) {\n\treturn f.Write([]byte(s))\n}\n\nvar errWriteAtInAppendMode = errors.New(\"os: invalid use of WriteAt on file opened with O_APPEND\")\n\n// WriteAt writes len(b) bytes to the File starting at byte offset off.\n// It returns the number of bytes written and an error, if any.\n// WriteAt returns a non-nil error when n != len(b).\n//\n// If file was opened with the O_APPEND flag, WriteAt returns an error.\nfunc (f *File) WriteAt(b []byte, offset int64) (n int, err error) {\n\tswitch {\n\tcase offset < 0:\n\t\treturn 0, &PathError{Op: \"writeat\", Path: f.name, Err: errNegativeOffset}\n\tcase f.handle == nil:\n\t\treturn 0, &PathError{Op: \"writeat\", Path: f.name, Err: ErrClosed}\n\tcase f.appendMode:\n\t\t// Go does not wrap this error but it would be more consistent\n\t\t// if it did.\n\t\treturn 0, errWriteAtInAppendMode\n\t}\n\tfor len(b) > 0 {\n\t\tm, e := f.handle.WriteAt(b, offset)\n\t\tif e != nil {\n\t\t\terr = &PathError{Op: \"writeat\", Path: f.name, Err: e}\n\t\t\tbreak\n\t\t}\n\t\tn += m\n\t\tb = b[m:]\n\t\toffset += int64(m)\n\t}\n\treturn\n}\n\n// Close closes the File, rendering it unusable for I/O.\nfunc (f *File) Close() (err error) {\n\tif f.handle == nil {\n\t\terr = ErrClosed\n\t} else {\n\t\t// Some platforms manage extra state other than the system handle which\n\t\t// needs to be released when the file is closed. For example, darwin\n\t\t// files have a DIR object holding a dup of the file descriptor, and\n\t\t// linux files hold a buffer which needs to be released to a pool.\n\t\t//\n\t\t// These platform-specific logic is provided by the (*file).close method\n\t\t// which is why we do not call the handle's Close method directly.\n\t\terr = f.file.close()\n\t\tif err == nil {\n\t\t\tf.handle = nil\n\t\t}\n\t}\n\tif err != nil {\n\t\terr = &PathError{Op: \"close\", Path: f.name, Err: err}\n\t}\n\treturn\n}\n\n// Seek sets the offset for the next Read or Write on file to offset, interpreted\n// according to whence: 0 means relative to the origin of the file, 1 means\n// relative to the current offset, and 2 means relative to the end.\n// It returns the new offset and an error, if any.\n// The behavior of Seek on a file opened with O_APPEND is not specified.\n//\n// If f is a directory, the behavior of Seek varies by operating\n// system; you can seek to the beginning of the directory on Unix-like\n// operating systems, but not on Windows.\nfunc (f *File) Seek(offset int64, whence int) (ret int64, err error) {\n\tif f.handle == nil {\n\t\terr = ErrClosed\n\t} else {\n\t\tret, err = f.handle.Seek(offset, whence)\n\t}\n\tif err != nil {\n\t\terr = &PathError{Op: \"seek\", Path: f.name, Err: err}\n\t}\n\treturn\n}\n\nfunc (f *File) SyscallConn() (conn syscall.RawConn, err error) {\n\tif f.handle == nil {\n\t\terr = ErrClosed\n\t} else {\n\t\terr = ErrNotImplemented\n\t}\n\treturn\n}\n\n// SetDeadline sets the read and write deadlines for a File.\n// Calls to SetDeadline for files that do not support deadlines will return ErrNoDeadline\n// This stub always returns ErrNoDeadline.\n// A zero value for t means I/O operations will not time out.\nfunc (f *File) SetDeadline(t time.Time) error {\n\tif f.handle == nil {\n\t\treturn ErrClosed\n\t}\n\treturn f.setDeadline(t)\n}\n\n// SetReadDeadline sets the deadline for future Read calls and any\n// currently-blocked Read call.\nfunc (f *File) SetReadDeadline(t time.Time) error {\n\treturn f.setReadDeadline(t)\n}\n\n// SetWriteDeadline sets the deadline for any future Write calls and any\n// currently-blocked Write call.\nfunc (f *File) SetWriteDeadline(t time.Time) error {\n\treturn f.setWriteDeadline(t)\n}\n\n// fd is an internal interface that is used to try a type assertion in order to\n// call the Fd() method of the underlying file handle if it is implemented.\ntype fd interface {\n\tFd() uintptr\n}\n\n// Fd returns the file handle referencing the open file.\nfunc (f *File) Fd() uintptr {\n\thandle, ok := f.handle.(fd)\n\tif ok {\n\t\treturn handle.Fd()\n\t}\n\treturn ^uintptr(0)\n}\n\n// Sync commits the current contents of the file to stable storage.\n// Typically, this means flushing the file system's in-memory copy of recently\n// written data to disk.\nfunc (f *File) Sync() (err error) {\n\tif f.handle == nil {\n\t\terr = ErrClosed\n\t} else {\n\t\terr = f.handle.Sync()\n\t}\n\treturn\n}\n\n// Chmod changes the mode of the file to mode. If there is an error, it will be\n// of type *PathError.\nfunc (f *File) Chmod(mode FileMode) (err error) {\n\tif f.handle == nil {\n\t\terr = ErrClosed\n\t} else {\n\t\terr = f.chmod(mode)\n\t}\n\treturn\n}\n\n// Chdir changes the current working directory to the file, which must be a\n// directory. If there is an error, it will be of type *PathError.\nfunc (f *File) Chdir() (err error) {\n\tif f.handle == nil {\n\t\terr = ErrClosed\n\t} else {\n\t\terr = f.chdir()\n\t}\n\treturn\n}\n\n// LinkError records an error during a link or symlink or rename system call and\n// the paths that caused it.\ntype LinkError struct {\n\tOp  string\n\tOld string\n\tNew string\n\tErr error\n}\n\nfunc (e *LinkError) Error() string {\n\treturn e.Op + \" \" + e.Old + \" \" + e.New + \": \" + e.Err.Error()\n}\n\nfunc (e *LinkError) Unwrap() error {\n\treturn e.Err\n}\n\n// OpenFile flag values.\nconst (\n\tO_RDONLY int = syscall.O_RDONLY\n\tO_WRONLY int = syscall.O_WRONLY\n\tO_RDWR   int = syscall.O_RDWR\n\tO_APPEND int = syscall.O_APPEND\n\tO_CREATE int = syscall.O_CREAT\n\tO_EXCL   int = syscall.O_EXCL\n\tO_SYNC   int = syscall.O_SYNC\n\tO_TRUNC  int = syscall.O_TRUNC\n)\n\nfunc Getwd() (string, error) {\n\treturn syscall.Getwd()\n}\n\n// TempDir returns the default directory to use for temporary files.\n//\n// On Unix systems, it returns $TMPDIR if non-empty, else /tmp.\n// On Windows, it uses GetTempPath, returning the first non-empty\n// value from %TMP%, %TEMP%, %USERPROFILE%, or the Windows directory.\n//\n// The directory is neither guaranteed to exist nor have accessible\n// permissions.\nfunc TempDir() string {\n\treturn tempDir()\n}\n\n// UserHomeDir returns the current user's home directory.\n//\n// On Unix, including macOS, it returns the $HOME environment variable.\n// On Windows, it returns %USERPROFILE%.\n// On Plan 9, it returns the $home environment variable.\nfunc UserHomeDir() (string, error) {\n\tenv, enverr := \"HOME\", \"$HOME\"\n\tswitch runtime.GOOS {\n\tcase \"windows\":\n\t\tenv, enverr = \"USERPROFILE\", \"%userprofile%\"\n\tcase \"plan9\":\n\t\tenv, enverr = \"home\", \"$home\"\n\t}\n\tif v := Getenv(env); v != \"\" {\n\t\treturn v, nil\n\t}\n\t// On some geese the home directory is not always defined.\n\tswitch runtime.GOOS {\n\tcase \"android\":\n\t\treturn \"/sdcard\", nil\n\tcase \"ios\":\n\t\treturn \"/\", nil\n\t}\n\treturn \"\", errors.New(enverr + \" is not defined\")\n}\n\ntype (\n\tFileMode = fs.FileMode\n\tFileInfo = fs.FileInfo\n)\n\n// The followings are copied from Go 1.16 or 1.17 official implementation:\n// https://github.com/golang/go/blob/go1.16/src/os/file.go\n\n// DirFS returns a file system (an fs.FS) for the tree of files rooted at the directory dir.\n//\n// Note that DirFS(\"/prefix\") only guarantees that the Open calls it makes to the\n// operating system will begin with \"/prefix\": DirFS(\"/prefix\").Open(\"file\") is the\n// same as os.Open(\"/prefix/file\"). So if /prefix/file is a symbolic link pointing outside\n// the /prefix tree, then using DirFS does not stop the access any more than using\n// os.Open does. DirFS is therefore not a general substitute for a chroot-style security\n// mechanism when the directory tree contains arbitrary content.\nfunc DirFS(dir string) fs.FS {\n\treturn dirFS(dir)\n}\n\nfunc containsAny(s, chars string) bool {\n\tfor i := 0; i < len(s); i++ {\n\t\tfor j := 0; j < len(chars); j++ {\n\t\t\tif s[i] == chars[j] {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t}\n\treturn false\n}\n\ntype dirFS string\n\nfunc (dir dirFS) Open(name string) (fs.File, error) {\n\tif !fs.ValidPath(name) || runtime.GOOS == \"windows\" && containsAny(name, `\\:`) {\n\t\treturn nil, &PathError{Op: \"open\", Path: name, Err: ErrInvalid}\n\t}\n\tf, err := Open(string(dir) + \"/\" + name)\n\tif err != nil {\n\t\treturn nil, err // nil fs.File\n\t}\n\treturn f, nil\n}\n\nfunc (dir dirFS) Stat(name string) (fs.FileInfo, error) {\n\tif !fs.ValidPath(name) || runtime.GOOS == \"windows\" && containsAny(name, `\\:`) {\n\t\treturn nil, &PathError{Op: \"stat\", Path: name, Err: ErrInvalid}\n\t}\n\tf, err := Stat(string(dir) + \"/\" + name)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn f, nil\n}\n\n// ReadFile reads the named file and returns the contents.\n// A successful call returns err == nil, not err == EOF.\n// Because ReadFile reads the whole file, it does not treat an EOF from Read\n// as an error to be reported.\nfunc ReadFile(name string) ([]byte, error) {\n\tf, err := Open(name)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer f.Close()\n\n\tvar size int\n\tif info, err := f.Stat(); err == nil {\n\t\tsize64 := info.Size()\n\t\tif int64(int(size64)) == size64 {\n\t\t\tsize = int(size64)\n\t\t}\n\t}\n\tsize++ // one byte for final read at EOF\n\n\t// If a file claims a small size, read at least 512 bytes.\n\t// In particular, files in Linux's /proc claim size 0 but\n\t// then do not work right if read in small pieces,\n\t// so an initial read of 1 byte would not work correctly.\n\tif size < 512 {\n\t\tsize = 512\n\t}\n\n\tdata := make([]byte, 0, size)\n\tfor {\n\t\tif len(data) >= cap(data) {\n\t\t\td := append(data[:cap(data)], 0)\n\t\t\tdata = d[:len(data)]\n\t\t}\n\t\tn, err := f.Read(data[len(data):cap(data)])\n\t\tdata = data[:len(data)+n]\n\t\tif err != nil {\n\t\t\tif err == io.EOF {\n\t\t\t\terr = nil\n\t\t\t}\n\t\t\treturn data, err\n\t\t}\n\t}\n}\n\n// WriteFile writes data to the named file, creating it if necessary.\n// If the file does not exist, WriteFile creates it with permissions perm (before umask);\n// otherwise WriteFile truncates it before writing, without changing permissions.\nfunc WriteFile(name string, data []byte, perm FileMode) error {\n\tf, err := OpenFile(name, O_WRONLY|O_CREATE|O_TRUNC, perm)\n\tif err != nil {\n\t\treturn err\n\t}\n\t_, err = f.Write(data)\n\tif err1 := f.Close(); err1 != nil && err == nil {\n\t\terr = err1\n\t}\n\treturn err\n}\n\n// The defined file mode bits are the most significant bits of the FileMode.\n// The nine least-significant bits are the standard Unix rwxrwxrwx permissions.\n// The values of these bits should be considered part of the public API and\n// may be used in wire protocols or disk representations: they must not be\n// changed, although new bits might be added.\nconst (\n\t// The single letters are the abbreviations\n\t// used by the String method's formatting.\n\tModeDir        = fs.ModeDir        // d: is a directory\n\tModeAppend     = fs.ModeAppend     // a: append-only\n\tModeExclusive  = fs.ModeExclusive  // l: exclusive use\n\tModeTemporary  = fs.ModeTemporary  // T: temporary file; Plan 9 only\n\tModeSymlink    = fs.ModeSymlink    // L: symbolic link\n\tModeDevice     = fs.ModeDevice     // D: device file\n\tModeNamedPipe  = fs.ModeNamedPipe  // p: named pipe (FIFO)\n\tModeSocket     = fs.ModeSocket     // S: Unix domain socket\n\tModeSetuid     = fs.ModeSetuid     // u: setuid\n\tModeSetgid     = fs.ModeSetgid     // g: setgid\n\tModeCharDevice = fs.ModeCharDevice // c: Unix character device, when ModeDevice is set\n\tModeSticky     = fs.ModeSticky     // t: sticky\n\tModeIrregular  = fs.ModeIrregular  // ?: non-regular file; nothing else is known about this file\n\n\t// Mask for the type bits. For regular files, none will be set.\n\tModeType = fs.ModeType\n\n\tModePerm = fs.ModePerm // Unix permission bits, 0o777\n)\n"
  },
  {
    "path": "src/os/file_anyos.go",
    "content": "//go:build !baremetal && !js && !wasm_unknown && !nintendoswitch\n\n// Portions copyright 2009-2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os\n\nimport (\n\t\"io\"\n\t\"syscall\"\n)\n\nfunc init() {\n\t// Mount the host filesystem at the root directory. This is what most\n\t// programs will be expecting.\n\tMount(\"/\", unixFilesystem{})\n}\n\n// Stdin, Stdout, and Stderr are open Files pointing to the standard input,\n// standard output, and standard error file descriptors.\nvar (\n\tStdin  = NewFile(uintptr(syscall.Stdin), \"/dev/stdin\")\n\tStdout = NewFile(uintptr(syscall.Stdout), \"/dev/stdout\")\n\tStderr = NewFile(uintptr(syscall.Stderr), \"/dev/stderr\")\n)\n\n// isOS indicates whether we're running on a real operating system with\n// filesystem support.\nconst isOS = true\n\n// Chdir changes the current working directory to the named directory.\n// If there is an error, it will be of type *PathError.\nfunc Chdir(dir string) error {\n\tif e := syscall.Chdir(dir); e != nil {\n\t\treturn &PathError{Op: \"chdir\", Path: dir, Err: e}\n\t}\n\treturn nil\n}\n\n// Rename renames (moves) oldpath to newpath.\n// If newpath already exists and is not a directory, Rename replaces it.\n// OS-specific restrictions may apply when oldpath and newpath are in different directories.\n// If there is an error, it will be of type *LinkError.\nfunc Rename(oldpath, newpath string) error {\n\treturn rename(oldpath, newpath)\n}\n\n// unixFilesystem is an empty handle for a Unix/Linux filesystem. All operations\n// are relative to the current working directory.\ntype unixFilesystem struct {\n}\n\nfunc (fs unixFilesystem) Mkdir(path string, perm FileMode) error {\n\treturn handleSyscallError(syscall.Mkdir(path, uint32(perm)))\n}\n\nfunc (fs unixFilesystem) Remove(path string) error {\n\t// System call interface forces us to know\n\t// whether name is a file or directory.\n\t// Try both: it is cheaper on average than\n\t// doing a Stat plus the right one.\n\te := handleSyscallError(syscall.Unlink(path))\n\tif e == nil {\n\t\treturn nil\n\t}\n\te1 := handleSyscallError(syscall.Rmdir(path))\n\tif e1 == nil {\n\t\treturn nil\n\t}\n\n\t// Both failed: figure out which error to return.\n\t// OS X and Linux differ on whether unlink(dir)\n\t// returns EISDIR, so can't use that. However,\n\t// both agree that rmdir(file) returns ENOTDIR,\n\t// so we can use that to decide which error is real.\n\t// Rmdir might also return ENOTDIR if given a bad\n\t// file path, like /etc/passwd/foo, but in that case,\n\t// both errors will be ENOTDIR, so it's okay to\n\t// use the error from unlink.\n\tif e1 != syscall.ENOTDIR {\n\t\te = e1\n\t}\n\treturn &PathError{Op: \"remove\", Path: path, Err: e}\n}\n\nfunc (fs unixFilesystem) OpenFile(path string, flag int, perm FileMode) (uintptr, error) {\n\tfp, err := syscall.Open(path, flag, uint32(perm))\n\treturn uintptr(fp), handleSyscallError(err)\n}\n\n// unixFileHandle is a Unix file pointer with associated methods that implement\n// the FileHandle interface.\ntype unixFileHandle uintptr\n\n// Read reads up to len(b) bytes from the File. It returns the number of bytes\n// read and any error encountered. At end of file, Read returns 0, io.EOF.\nfunc (f unixFileHandle) Read(b []byte) (n int, err error) {\n\tn, err = syscall.Read(syscallFd(f), b)\n\t// In case of EISDIR, n == -1.\n\t// This breaks the assumption that n always represent the number of read bytes.\n\tif err == syscall.EISDIR {\n\t\tn = 0\n\t}\n\terr = handleSyscallError(err)\n\tif n == 0 && len(b) > 0 && err == nil {\n\t\terr = io.EOF\n\t}\n\treturn\n}\n\n// Write writes len(b) bytes to the File. It returns the number of bytes written\n// and an error, if any. Write returns a non-nil error when n != len(b).\nfunc (f unixFileHandle) Write(b []byte) (n int, err error) {\n\tn, err = syscall.Write(syscallFd(f), b)\n\terr = handleSyscallError(err)\n\treturn\n}\n\n// Close closes the File, rendering it unusable for I/O.\nfunc (f unixFileHandle) Close() error {\n\treturn handleSyscallError(syscall.Close(syscallFd(f)))\n}\n\nfunc (f unixFileHandle) Fd() uintptr {\n\treturn uintptr(f)\n}\n\n// Chmod changes the mode of the named file to mode.\n// If the file is a symbolic link, it changes the mode of the link's target.\n// If there is an error, it will be of type *PathError.\n//\n// A different subset of the mode bits are used, depending on the\n// operating system.\n//\n// On Unix, the mode's permission bits, ModeSetuid, ModeSetgid, and\n// ModeSticky are used.\n//\n// On Windows, only the 0200 bit (owner writable) of mode is used; it\n// controls whether the file's read-only attribute is set or cleared.\n// The other bits are currently unused. For compatibility with Go 1.12\n// and earlier, use a non-zero mode. Use mode 0400 for a read-only\n// file and 0600 for a readable+writable file.\nfunc Chmod(name string, mode FileMode) error {\n\tlongName := fixLongPath(name)\n\te := ignoringEINTR(func() error {\n\t\treturn syscall.Chmod(longName, syscallMode(mode))\n\t})\n\tif e != nil {\n\t\treturn &PathError{Op: \"chmod\", Path: name, Err: e}\n\t}\n\treturn nil\n}\n\n// Chown changes the numeric uid and gid of the named file.\n// If the file is a symbolic link, it changes the uid and gid of the link's target.\n// A uid or gid of -1 means to not change that value.\n// If there is an error, it will be of type *PathError.\nfunc Chown(name string, uid, gid int) error {\n\te := ignoringEINTR(func() error {\n\t\treturn syscall.Chown(name, uid, gid)\n\t})\n\tif e != nil {\n\t\treturn &PathError{Op: \"chown\", Path: name, Err: e}\n\t}\n\treturn nil\n}\n\n// ignoringEINTR makes a function call and repeats it if it returns an\n// EINTR error. This appears to be required even though we install all\n// signal handlers with SA_RESTART: see #22838, #38033, #38836, #40846.\n// Also #20400 and #36644 are issues in which a signal handler is\n// installed without setting SA_RESTART. None of these are the common case,\n// but there are enough of them that it seems that we can't avoid\n// an EINTR loop.\nfunc ignoringEINTR(fn func() error) error {\n\tfor {\n\t\terr := fn()\n\t\tif err != syscall.EINTR {\n\t\t\treturn err\n\t\t}\n\t}\n}\n\n// handleSyscallError converts syscall errors into regular os package errors.\n// The err parameter must be either nil or of type syscall.Errno.\nfunc handleSyscallError(err error) error {\n\tif err == nil {\n\t\treturn nil\n\t}\n\tswitch err.(syscall.Errno) {\n\tcase syscall.EEXIST:\n\t\treturn ErrExist\n\tcase syscall.ENOENT:\n\t\treturn ErrNotExist\n\tdefault:\n\t\treturn err\n\t}\n}\n\n// syscallMode returns the syscall-specific mode bits from Go's portable mode bits.\nfunc syscallMode(i FileMode) (o uint32) {\n\to |= uint32(i.Perm())\n\tif i&ModeSetuid != 0 {\n\t\to |= syscall.S_ISUID\n\t}\n\tif i&ModeSetgid != 0 {\n\t\to |= syscall.S_ISGID\n\t}\n\tif i&ModeSticky != 0 {\n\t\to |= syscall.S_ISVTX\n\t}\n\t// No mapping for Go's ModeTemporary (plan9 only).\n\treturn\n}\n"
  },
  {
    "path": "src/os/file_anyos_test.go",
    "content": "//go:build !baremetal && !js\n\npackage os_test\n\nimport (\n\t\"errors\"\n\t\"io\"\n\t. \"os\"\n\t\"runtime\"\n\t\"testing\"\n)\n\n// TestTempDir assumes that the test environment has a filesystem with a working temp dir.\nfunc TestTempDir(t *testing.T) {\n\tname := TempDir() + \"/_os_test_TestTempDir\"\n\tRemove(name)\n\tf, err := OpenFile(name, O_RDWR|O_CREATE, 0644)\n\tif err != nil {\n\t\tt.Errorf(\"OpenFile %s: %s\", name, err)\n\t\treturn\n\t}\n\terr = f.Close()\n\tif err != nil {\n\t\tt.Errorf(\"Close %s: %s\", name, err)\n\t}\n\terr = Remove(name)\n\tif err != nil {\n\t\tt.Errorf(\"Remove %s: %s\", name, err)\n\t}\n}\n\nfunc TestChdir(t *testing.T) {\n\t// Save and restore the current working directory after the test, otherwise\n\t// we might break other tests that depend on it.\n\t//\n\t// Note that it doesn't work if Chdir is broken, but then this test should\n\t// fail and highlight the issue if that is the case.\n\toldDir, err := Getwd()\n\tif err != nil {\n\t\tt.Errorf(\"Getwd() returned %v\", err)\n\t\treturn\n\t}\n\tdefer Chdir(oldDir)\n\n\t// create and cd into a new directory\n\tdir := \"_os_test_TestChDir\"\n\tRemove(dir)\n\terr = Mkdir(dir, 0755)\n\tdefer Remove(dir) // even though not quite sure which directory it will execute in\n\tif err != nil {\n\t\tt.Errorf(\"Mkdir(%s, 0755) returned %v\", dir, err)\n\t}\n\terr = Chdir(dir)\n\tif err != nil {\n\t\tt.Fatalf(\"Chdir %s: %s\", dir, err)\n\t\treturn\n\t}\n\t// create a file there\n\tfile := \"_os_test_TestTempDir.dat\"\n\tf, err := OpenFile(file, O_RDWR|O_CREATE, 0644)\n\tif err != nil {\n\t\tt.Errorf(\"OpenFile %s: %s\", file, err)\n\t}\n\tdefer Remove(file) // even though not quite sure which directory it will execute in\n\terr = f.Close()\n\tif err != nil {\n\t\tt.Errorf(\"Close %s: %s\", file, err)\n\t}\n\t// cd back to original directory\n\terr = Chdir(\"..\")\n\tif err != nil {\n\t\tt.Errorf(\"Chdir ..: %s\", err)\n\t}\n\t// clean up file and directory explicitly so we can check for errors\n\tfullname := dir + \"/\" + file\n\terr = Remove(fullname)\n\tif err != nil {\n\t\tt.Errorf(\"Remove %s: %s\", fullname, err)\n\t}\n\terr = Remove(dir)\n\tif err != nil {\n\t\tt.Errorf(\"Remove %s: %s\", dir, err)\n\t}\n}\n\nfunc TestStandardFd(t *testing.T) {\n\tif runtime.GOOS == \"windows\" {\n\t\tt.Log(\"TODO: TestFd fails on Windows, skipping\")\n\t\treturn\n\t}\n\tif fd := Stdin.Fd(); fd != 0 {\n\t\tt.Errorf(\"Stdin.Fd() = %d, want 0\", fd)\n\t}\n\n\tif fd := Stdout.Fd(); fd != 1 {\n\t\tt.Errorf(\"Stdout.Fd() = %d, want 1\", fd)\n\t}\n\n\tif fd := Stderr.Fd(); fd != 2 {\n\t\tt.Errorf(\"Stderr.Fd() = %d, want 2\", fd)\n\t}\n}\n\nfunc TestFd(t *testing.T) {\n\tif runtime.GOOS == \"windows\" {\n\t\tt.Log(\"TODO: TestFd fails on Windows, skipping\")\n\t\treturn\n\t}\n\tf := newFile(\"TestFd.txt\", t)\n\tdefer Remove(f.Name())\n\tdefer f.Close()\n\n\tconst data = \"hello, world\\n\"\n\tio.WriteString(f, data)\n\n\tfd := NewFile(f.Fd(), \"as-fd\")\n\tdefer fd.Close()\n\n\tb := make([]byte, 5)\n\tn, err := fd.ReadAt(b, 0)\n\tif n != 5 && err != nil {\n\t\tt.Errorf(\"Failed to read 5 bytes from file descriptor: %v\", err)\n\t}\n\n\tif string(b) != data[:5] {\n\t\tt.Errorf(\"File descriptor contents not equal to file contents.\")\n\t}\n}\n\n// closeTests is the list of tests used to validate that after calling Close,\n// calling any method of File returns ErrClosed.\nvar closeTests = map[string]func(*File) error{\n\t\"Close\": func(f *File) error {\n\t\treturn f.Close()\n\t},\n\t\"Read\": func(f *File) error {\n\t\t_, err := f.Read(nil)\n\t\treturn err\n\t},\n\t\"ReadAt\": func(f *File) error {\n\t\t_, err := f.ReadAt(nil, 0)\n\t\treturn err\n\t},\n\t\"Seek\": func(f *File) error {\n\t\t_, err := f.Seek(0, 0)\n\t\treturn err\n\t},\n\t\"Sync\": func(f *File) error {\n\t\treturn f.Sync()\n\t},\n\t\"SyscallConn\": func(f *File) error {\n\t\t_, err := f.SyscallConn()\n\t\treturn err\n\t},\n\t\"Truncate\": func(f *File) error {\n\t\treturn f.Truncate(0)\n\t},\n\t\"Write\": func(f *File) error {\n\t\t_, err := f.Write(nil)\n\t\treturn err\n\t},\n\t\"WriteAt\": func(f *File) error {\n\t\t_, err := f.WriteAt(nil, 0)\n\t\treturn err\n\t},\n\t\"WriteString\": func(f *File) error {\n\t\t_, err := f.WriteString(\"\")\n\t\treturn err\n\t},\n}\n\nfunc TestClose(t *testing.T) {\n\tf := newFile(\"TestClose.txt\", t)\n\n\tif err := f.Close(); err != nil {\n\t\tt.Error(\"unexpected error closing the file:\", err)\n\t}\n\tif fd := f.Fd(); fd != ^uintptr(0) {\n\t\tt.Error(\"unexpected file handle after closing the file:\", fd)\n\t}\n\n\tfor name, test := range closeTests {\n\t\tif err := test(f); !errors.Is(err, ErrClosed) {\n\t\t\tt.Errorf(\"unexpected error returned by calling %s on a closed file: %v\", name, err)\n\t\t}\n\t}\n}\n\nfunc TestReadOnDir(t *testing.T) {\n\tname := TempDir() + \"/_os_test_TestReadOnDir\"\n\tdefer Remove(name)\n\tf, err := OpenFile(name, O_RDWR|O_CREATE, 0644)\n\tif err != nil {\n\t\tt.Errorf(\"OpenFile %s: %s\", name, err)\n\t\treturn\n\t}\n\tvar buf [32]byte\n\tn, err := f.Read(buf[:])\n\tif err == nil {\n\t\tt.Errorf(\"Error expected\")\n\t\treturn\n\t}\n\tif n != 0 {\n\t\tt.Errorf(\"Wrong read bytes: %s\", err)\n\t}\n}\n"
  },
  {
    "path": "src/os/file_darwin.go",
    "content": "package os\n\nimport \"syscall\"\n\nfunc pipe(p []int) error {\n\treturn syscall.Pipe(p)\n}\n"
  },
  {
    "path": "src/os/file_notdarwin.go",
    "content": "//go:build (linux && !baremetal && !wasm_unknown) || wasip1 || wasip2\n\npackage os\n\nimport \"syscall\"\n\nfunc pipe(p []int) error {\n\treturn syscall.Pipe2(p, syscall.O_CLOEXEC)\n}\n"
  },
  {
    "path": "src/os/file_other.go",
    "content": "//go:build baremetal || (tinygo.wasm && !wasip1 && !wasip2) || nintendoswitch\n\npackage os\n\nimport (\n\t_ \"unsafe\"\n)\n\n// Stdin, Stdout, and Stderr are open Files pointing to the standard input,\n// standard output, and standard error file descriptors.\nvar (\n\tStdin  = NewFile(0, \"/dev/stdin\")\n\tStdout = NewFile(1, \"/dev/stdout\")\n\tStderr = NewFile(2, \"/dev/stderr\")\n)\n\nconst DevNull = \"/dev/null\"\n\n// isOS indicates whether we're running on a real operating system with\n// filesystem support.\nconst isOS = false\n\n// stdioFileHandle represents one of stdin, stdout, or stderr depending on the\n// number. It implements the FileHandle interface.\ntype stdioFileHandle uint8\n\n// file is the real representation of *File.\n// The extra level of indirection ensures that no clients of os\n// can overwrite this data, which could cause the finalizer\n// to close the wrong file descriptor.\ntype file struct {\n\thandle     FileHandle\n\tname       string\n\tappendMode bool\n}\n\nfunc (f *file) close() error {\n\treturn f.handle.Close()\n}\n\nfunc NewFile(fd uintptr, name string) *File {\n\treturn &File{&file{handle: stdioFileHandle(fd), name: name}}\n}\n\n// Chdir changes the current working directory to the named directory.\n// If there is an error, it will be of type *PathError.\nfunc Chdir(dir string) error {\n\treturn ErrNotImplemented\n}\n\n// Rename renames (moves) oldpath to newpath.\n// If newpath already exists and is not a directory, Rename replaces it.\n// OS-specific restrictions may apply when oldpath and newpath are in different directories.\n// If there is an error, it will be of type *LinkError.\nfunc Rename(oldpath, newpath string) error {\n\treturn ErrNotImplemented\n}\n\n// Read reads up to len(b) bytes from machine.Serial.\n// It returns the number of bytes read and any error encountered.\nfunc (f stdioFileHandle) Read(b []byte) (n int, err error) {\n\tif len(b) == 0 {\n\t\treturn 0, nil\n\t}\n\n\tsize := buffered()\n\tfor size == 0 {\n\t\tgosched()\n\t\tsize = buffered()\n\t}\n\n\tif size > len(b) {\n\t\tsize = len(b)\n\t}\n\tfor i := 0; i < size; i++ {\n\t\tb[i] = getchar()\n\t}\n\treturn size, nil\n}\n\nfunc (f stdioFileHandle) ReadAt(b []byte, off int64) (n int, err error) {\n\treturn 0, ErrNotImplemented\n}\n\nfunc (f stdioFileHandle) WriteAt(b []byte, off int64) (n int, err error) {\n\treturn 0, ErrNotImplemented\n}\n\n// Write writes len(b) bytes to the output. It returns the number of bytes\n// written or an error if this file is not stdout or stderr.\nfunc (f stdioFileHandle) Write(b []byte) (n int, err error) {\n\tswitch f {\n\tcase 1, 2: // stdout, stderr\n\t\tfor _, c := range b {\n\t\t\tputchar(c)\n\t\t}\n\t\treturn len(b), nil\n\tdefault:\n\t\treturn 0, ErrUnsupported\n\t}\n}\n\n// Close is unsupported on this system.\nfunc (f stdioFileHandle) Close() error {\n\treturn ErrUnsupported\n}\n\n// Seek wraps syscall.Seek.\nfunc (f stdioFileHandle) Seek(offset int64, whence int) (int64, error) {\n\treturn -1, ErrUnsupported\n}\n\nfunc (f stdioFileHandle) Sync() error {\n\treturn ErrUnsupported\n}\n\nfunc (f stdioFileHandle) Fd() uintptr {\n\treturn uintptr(f)\n}\n\n//go:linkname putchar runtime.putchar\nfunc putchar(c byte)\n\n//go:linkname getchar runtime.getchar\nfunc getchar() byte\n\n//go:linkname buffered runtime.buffered\nfunc buffered() int\n\n//go:linkname gosched runtime.Gosched\nfunc gosched() int\n\nfunc Pipe() (r *File, w *File, err error) {\n\treturn nil, nil, ErrNotImplemented\n}\n\nfunc Symlink(oldname, newname string) error {\n\treturn ErrNotImplemented\n}\n\nfunc Readlink(name string) (string, error) {\n\treturn \"\", ErrNotImplemented\n}\n\nfunc tempDir() string {\n\treturn \"/tmp\"\n}\n\n// Truncate is unsupported on this system.\nfunc Truncate(filename string, size int64) (err error) {\n\treturn ErrUnsupported\n}\n\n// Truncate is unsupported on this system.\nfunc (f *File) Truncate(size int64) (err error) {\n\tif f.handle == nil {\n\t\treturn ErrClosed\n\t}\n\n\treturn Truncate(f.name, size)\n}\n\nfunc (f *File) chmod(mode FileMode) error {\n\treturn ErrUnsupported\n}\n\nfunc (f *File) chdir() error {\n\treturn ErrNotImplemented\n}\n"
  },
  {
    "path": "src/os/file_posix.go",
    "content": "package os\n\nimport (\n\t\"time\"\n)\n\n//TODO: re-implement the ErrNoDeadline error in the correct code path\n\n// Chtimes is a stub, not yet implemented\nfunc Chtimes(name string, atime time.Time, mtime time.Time) error {\n\treturn ErrNotImplemented\n}\n\n// setDeadline sets the read and write deadline.\nfunc (f *File) setDeadline(t time.Time) error {\n\tif t.IsZero() {\n\t\treturn nil\n\t}\n\treturn ErrNotImplemented\n}\n\n// setReadDeadline sets the read deadline, not yet implemented\n// A zero value for t means Read will not time out.\nfunc (f *File) setReadDeadline(t time.Time) error {\n\tif t.IsZero() {\n\t\treturn nil\n\t}\n\treturn ErrNotImplemented\n}\n\n// setWriteDeadline sets the write deadline, not yet implemented\n// A zero value for t means Read will not time out.\nfunc (f *File) setWriteDeadline(t time.Time) error {\n\tif t.IsZero() {\n\t\treturn nil\n\t}\n\treturn ErrNotImplemented\n}\n"
  },
  {
    "path": "src/os/file_unix.go",
    "content": "//go:build darwin || (linux && !baremetal && !wasm_unknown && !nintendoswitch) || wasip1 || wasip2\n\n// target wasi sets GOOS=linux and thus the +linux build tag,\n// even though it doesn't show up in \"tinygo info target -wasi\"\n\n// Portions copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os\n\nimport (\n\t\"io\"\n\t\"syscall\"\n)\n\nconst DevNull = \"/dev/null\"\n\ntype syscallFd = int\n\n// fixLongPath is a noop on non-Windows platforms.\nfunc fixLongPath(path string) string {\n\treturn path\n}\n\nfunc rename(oldname, newname string) error {\n\t// TODO: import rest of upstream tests, handle fancy cases\n\terr := syscall.Rename(oldname, newname)\n\tif err != nil {\n\t\treturn &LinkError{\"rename\", oldname, newname, err}\n\t}\n\treturn nil\n}\n\n// file is the real representation of *File.\n// The extra level of indirection ensures that no clients of os\n// can overwrite this data, which could cause the finalizer\n// to close the wrong file descriptor.\ntype file struct {\n\thandle     FileHandle\n\tname       string\n\tdirinfo    *dirInfo // nil unless directory being read\n\tappendMode bool\n}\n\nfunc (f *file) close() (err error) {\n\tif f.dirinfo != nil {\n\t\tf.dirinfo.close()\n\t\tf.dirinfo = nil\n\t}\n\treturn f.handle.Close()\n}\n\nfunc NewFile(fd uintptr, name string) *File {\n\treturn &File{&file{handle: unixFileHandle(fd), name: name}}\n}\n\n// Truncate changes the size of the named file.\n// If the file is a symbolic link, it changes the size of the link's target.\n// If there is an error, it will be of type *PathError.\nfunc Truncate(name string, size int64) error {\n\te := ignoringEINTR(func() error {\n\t\treturn syscall.Truncate(name, size)\n\t})\n\tif e != nil {\n\t\treturn &PathError{Op: \"truncate\", Path: name, Err: e}\n\t}\n\treturn nil\n}\n\nfunc Pipe() (r *File, w *File, err error) {\n\tvar p [2]int\n\terr = handleSyscallError(pipe(p[:]))\n\tif err != nil {\n\t\treturn\n\t}\n\tr = NewFile(uintptr(p[0]), \"|0\")\n\tw = NewFile(uintptr(p[1]), \"|1\")\n\treturn\n}\n\nfunc tempDir() string {\n\tdir := Getenv(\"TMPDIR\")\n\tif dir == \"\" {\n\t\tdir = \"/tmp\"\n\t}\n\treturn dir\n}\n\n// Link creates newname as a hard link to the oldname file.\n// If there is an error, it will be of type *LinkError.\nfunc Link(oldname, newname string) error {\n\te := ignoringEINTR(func() error {\n\t\treturn syscall.Link(oldname, newname)\n\t})\n\n\tif e != nil {\n\t\treturn &LinkError{\"link\", oldname, newname, e}\n\t}\n\treturn nil\n}\n\n// Symlink creates newname as a symbolic link to oldname.\n// On Windows, a symlink to a non-existent oldname creates a file symlink;\n// if oldname is later created as a directory the symlink will not work.\n// If there is an error, it will be of type *LinkError.\nfunc Symlink(oldname, newname string) error {\n\te := ignoringEINTR(func() error {\n\t\treturn syscall.Symlink(oldname, newname)\n\t})\n\tif e != nil {\n\t\treturn &LinkError{\"symlink\", oldname, newname, e}\n\t}\n\treturn nil\n}\n\n// Readlink returns the destination of the named symbolic link.\n// If there is an error, it will be of type *PathError.\nfunc Readlink(name string) (string, error) {\n\tfor len := 128; ; len *= 2 {\n\t\tb := make([]byte, len)\n\t\tvar (\n\t\t\tn int\n\t\t\te error\n\t\t)\n\t\tfor {\n\t\t\tn, e = fixCount(syscall.Readlink(name, b))\n\t\t\tif e != syscall.EINTR {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif e != nil {\n\t\t\treturn \"\", &PathError{Op: \"readlink\", Path: name, Err: e}\n\t\t}\n\t\tif n < len {\n\t\t\treturn string(b[0:n]), nil\n\t\t}\n\t}\n}\n\n// Truncate changes the size of the file.\n// It does not change the I/O offset.\n// If there is an error, it will be of type *PathError.\n// Alternatively just use 'raw' syscall by file name\nfunc (f *File) Truncate(size int64) (err error) {\n\tif f.handle == nil {\n\t\treturn ErrClosed\n\t}\n\n\treturn Truncate(f.name, size)\n}\n\nfunc (f *File) chmod(mode FileMode) error {\n\tif f.handle == nil {\n\t\treturn ErrClosed\n\t}\n\n\tlongName := fixLongPath(f.name)\n\te := ignoringEINTR(func() error {\n\t\treturn syscall.Chmod(longName, syscallMode(mode))\n\t})\n\tif e != nil {\n\t\treturn &PathError{Op: \"chmod\", Path: f.name, Err: e}\n\t}\n\treturn nil\n}\n\nfunc (f *File) chdir() error {\n\tif f.handle == nil {\n\t\treturn ErrClosed\n\t}\n\n\t// TODO: use syscall.Fchdir instead\n\tlongName := fixLongPath(f.name)\n\te := ignoringEINTR(func() error {\n\t\treturn syscall.Chdir(longName)\n\t})\n\tif e != nil {\n\t\treturn &PathError{Op: \"chdir\", Path: f.name, Err: e}\n\t}\n\treturn nil\n}\n\n// ReadAt reads up to len(b) bytes from the File starting at the given absolute offset.\n// It returns the number of bytes read and any error encountered, possibly io.EOF.\n// At end of file, Pread returns 0, io.EOF.\n// TODO: move to file_anyos once ReadAt is implemented for windows\nfunc (f unixFileHandle) ReadAt(b []byte, offset int64) (n int, err error) {\n\tn, err = syscall.Pread(syscallFd(f), b, offset)\n\terr = handleSyscallError(err)\n\tif n == 0 && len(b) > 0 && err == nil {\n\t\terr = io.EOF\n\t}\n\treturn\n}\n\n// WriteAt writes len(b) bytes to the File starting at byte offset off.\n// It returns the number of bytes written and an error, if any.\n// WriteAt returns a non-nil error when n != len(b).\n//\n// If file was opened with the O_APPEND flag, WriteAt returns an error.\n//\n// TODO: move to file_anyos once WriteAt is implemented for windows.\nfunc (f unixFileHandle) WriteAt(b []byte, offset int64) (int, error) {\n\tn, err := syscall.Pwrite(syscallFd(f), b, offset)\n\treturn n, handleSyscallError(err)\n}\n\n// Seek wraps syscall.Seek.\nfunc (f unixFileHandle) Seek(offset int64, whence int) (int64, error) {\n\tnewoffset, err := syscall.Seek(syscallFd(f), offset, whence)\n\treturn newoffset, handleSyscallError(err)\n}\n\nfunc (f unixFileHandle) Sync() error {\n\terr := syscall.Fsync(syscallFd(f))\n\treturn handleSyscallError(err)\n}\n\ntype unixDirent struct {\n\tparent string\n\tname   string\n\ttyp    FileMode\n\tinfo   FileInfo\n}\n\nfunc (d *unixDirent) Name() string   { return d.name }\nfunc (d *unixDirent) IsDir() bool    { return d.typ.IsDir() }\nfunc (d *unixDirent) Type() FileMode { return d.typ }\n\nfunc (d *unixDirent) Info() (FileInfo, error) {\n\tif d.info != nil {\n\t\treturn d.info, nil\n\t}\n\treturn lstat(d.parent + \"/\" + d.name)\n}\n\nfunc newUnixDirent(parent, name string, typ FileMode) (DirEntry, error) {\n\tude := &unixDirent{\n\t\tparent: parent,\n\t\tname:   name,\n\t\ttyp:    typ,\n\t}\n\tif typ != ^FileMode(0) && !testingForceReadDirLstat {\n\t\treturn ude, nil\n\t}\n\n\tinfo, err := lstat(parent + \"/\" + name)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tude.typ = info.Mode().Type()\n\tude.info = info\n\treturn ude, nil\n}\n\n// Since internal/poll is not available, we need to stub this out.\n// Big go requires the option to add the fd to the polling system.\n//\n//go:linkname net_newUnixFile net.newUnixFile\nfunc net_newUnixFile(fd int, name string) *File {\n\tif fd < 0 {\n\t\tpanic(\"invalid FD\")\n\t}\n\n\t// see src/os/file_unix.go:162 newFile for the original implementation.\n\t// return newFile(fd, name, kindSock, true)\n\treturn NewFile(uintptr(fd), name)\n}\n"
  },
  {
    "path": "src/os/file_windows.go",
    "content": "//go:build windows\n\n// Portions copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os\n\nimport (\n\t\"internal/syscall/windows\"\n\t\"syscall\"\n\t\"unicode/utf16\"\n)\n\nconst DevNull = \"NUL\"\n\ntype syscallFd = syscall.Handle\n\n// Symlink is a stub, it is not implemented.\nfunc Symlink(oldname, newname string) error {\n\treturn ErrNotImplemented\n}\n\n// Readlink is a stub (for now), always returning the string it was given\nfunc Readlink(name string) (string, error) {\n\treturn name, nil\n}\n\nfunc rename(oldname, newname string) error {\n\te := windows.Rename(fixLongPath(oldname), fixLongPath(newname))\n\tif e != nil {\n\t\treturn &LinkError{\"rename\", oldname, newname, e}\n\t}\n\treturn nil\n}\n\ntype file struct {\n\thandle     FileHandle\n\tname       string\n\tappendMode bool\n}\n\nfunc (f *file) close() error {\n\treturn f.handle.Close()\n}\n\nfunc NewFile(fd uintptr, name string) *File {\n\treturn &File{&file{handle: unixFileHandle(fd), name: name}}\n}\n\nfunc Pipe() (r *File, w *File, err error) {\n\tvar p [2]syscall.Handle\n\te := handleSyscallError(syscall.Pipe(p[:]))\n\tif e != nil {\n\t\treturn nil, nil, err\n\t}\n\tr = NewFile(uintptr(p[0]), \"|0\")\n\tw = NewFile(uintptr(p[1]), \"|1\")\n\treturn\n}\n\nfunc (f *unixFileHandle) Truncate(size int64) error {\n\treturn ErrNotImplemented\n}\n\n// Truncate changes the size of the named file.\n// If the file is a symbolic link, it changes the size of the link's target.\nfunc Truncate(name string, size int64) error {\n\treturn &PathError{Op: \"truncate\", Path: name, Err: ErrNotImplemented}\n}\n\nfunc tempDir() string {\n\tn := uint32(syscall.MAX_PATH)\n\tfor {\n\t\tb := make([]uint16, n)\n\t\tn, _ = syscall.GetTempPath(uint32(len(b)), &b[0])\n\t\tif n > uint32(len(b)) {\n\t\t\tcontinue\n\t\t}\n\t\tif n == 3 && b[1] == ':' && b[2] == '\\\\' {\n\t\t\t// Do nothing for path, like C:\\.\n\t\t} else if n > 0 && b[n-1] == '\\\\' {\n\t\t\t// Otherwise remove terminating \\.\n\t\t\tn--\n\t\t}\n\t\treturn string(utf16.Decode(b[:n]))\n\t}\n}\n\n// ReadAt reads up to len(b) bytes from the File starting at the given absolute offset.\n// It returns the number of bytes read and any error encountered, possibly io.EOF.\n// At end of file, Pread returns 0, io.EOF.\n// TODO: move to file_anyos once ReadAt is implemented for windows\nfunc (f unixFileHandle) ReadAt(b []byte, offset int64) (n int, err error) {\n\treturn -1, ErrNotImplemented\n}\n\n// WriteAt writes len(b) bytes to the File starting at byte offset off.\n// It returns the number of bytes written and an error, if any.\n// WriteAt returns a non-nil error when n != len(b).\n//\n// If file was opened with the O_APPEND flag, WriteAt returns an error.\n//\n// TODO: move to file_anyos once WriteAt is implemented for windows.\nfunc (f unixFileHandle) WriteAt(b []byte, offset int64) (n int, err error) {\n\treturn -1, ErrNotImplemented\n}\n\n// Seek wraps syscall.Seek.\nfunc (f unixFileHandle) Seek(offset int64, whence int) (int64, error) {\n\tnewoffset, err := syscall.Seek(syscallFd(f), offset, whence)\n\treturn newoffset, handleSyscallError(err)\n}\n\nfunc (f unixFileHandle) Sync() error {\n\treturn ErrNotImplemented\n}\n\n// Truncate changes the size of the named file.\n// If the file is a symbolic link, it changes the size of the link's target.\nfunc (f *File) Truncate(size int64) error {\n\tif f.handle == nil {\n\t\treturn &PathError{Op: \"truncate\", Path: f.name, Err: ErrClosed}\n\t}\n\treturn Truncate(f.name, size)\n}\n\n// isWindowsNulName reports whether name is os.DevNull ('NUL') on Windows.\n// True is returned if name is 'NUL' whatever the case.\nfunc isWindowsNulName(name string) bool {\n\tif len(name) != 3 {\n\t\treturn false\n\t}\n\tif name[0] != 'n' && name[0] != 'N' {\n\t\treturn false\n\t}\n\tif name[1] != 'u' && name[1] != 'U' {\n\t\treturn false\n\t}\n\tif name[2] != 'l' && name[2] != 'L' {\n\t\treturn false\n\t}\n\treturn true\n}\n\nfunc (f *File) chmod(mode FileMode) error {\n\treturn ErrNotImplemented\n}\n\nfunc (f *File) chdir() error {\n\treturn ErrNotImplemented\n}\n"
  },
  {
    "path": "src/os/filesystem.go",
    "content": "package os\n\nimport (\n\t\"strings\"\n)\n\n// mounts lists the mount points currently mounted in the filesystem provided by\n// the os package. To resolve a path to a mount point, it is scanned from top to\n// bottom looking for the first prefix match.\nvar mounts []mountPoint\n\ntype mountPoint struct {\n\t// prefix is a filesystem prefix, that always starts and ends with a forward\n\t// slash. To denote the root filesystem, use a single slash: \"/\".\n\t// This allows fast checking whether a path lies within a mount point.\n\tprefix string\n\n\t// filesystem is the Filesystem implementation that is mounted at this mount\n\t// point.\n\tfilesystem Filesystem\n}\n\n// Filesystem provides an interface for generic filesystem drivers mounted in\n// the os package. The errors returned must be one of the os.Err* errors, or a\n// custom error if one doesn't exist. It should not be a *PathError because\n// errors will be wrapped with a *PathError by the filesystem abstraction.\n//\n// WARNING: this interface is not finalized and may change in a future version.\ntype Filesystem interface {\n\t// OpenFile opens the named file.\n\tOpenFile(name string, flag int, perm FileMode) (uintptr, error)\n\n\t// Mkdir creates a new directory with the specified permission (before\n\t// umask). Some filesystems may not support directories or permissions.\n\tMkdir(name string, perm FileMode) error\n\n\t// Remove removes the named file or (empty) directory.\n\tRemove(name string) error\n}\n\n// FileHandle is an interface that should be implemented by filesystems\n// implementing the Filesystem interface.\n//\n// WARNING: this interface is not finalized and may change in a future version.\ntype FileHandle interface {\n\t// Read reads up to len(b) bytes from the file.\n\tRead(b []byte) (n int, err error)\n\n\t// ReadAt reads up to len(b) bytes from the file starting at the given absolute offset\n\tReadAt(b []byte, offset int64) (n int, err error)\n\n\t// Seek resets the file pointer relative to start, current position, or end\n\tSeek(offset int64, whence int) (newoffset int64, err error)\n\n\t// Sync blocks until buffered writes have been written to persistent storage\n\tSync() (err error)\n\n\t// Write writes up to len(b) bytes to the file.\n\tWrite(b []byte) (n int, err error)\n\n\t// WriteAt writes b to the file at the given absolute offset\n\tWriteAt(b []byte, offset int64) (n int, err error)\n\n\t// Close closes the file, making it unusable for further writes.\n\tClose() (err error)\n}\n\n// findMount returns the appropriate (mounted) filesystem to use for a given\n// filename plus the path relative to that filesystem.\nfunc findMount(path string) (Filesystem, string) {\n\tfor i := len(mounts) - 1; i >= 0; i-- {\n\t\tmount := mounts[i]\n\t\tif strings.HasPrefix(path, mount.prefix) {\n\t\t\treturn mount.filesystem, path[len(mount.prefix)-1:]\n\t\t}\n\t}\n\tif isOS {\n\t\t// Assume that the first entry in the mounts slice is the OS filesystem\n\t\t// at the root of the directory tree. Use it as-is, to support relative\n\t\t// paths.\n\t\treturn mounts[0].filesystem, path\n\t}\n\treturn nil, path\n}\n\n// Mount mounts the given filesystem in the filesystem abstraction layer of the\n// os package. It is not possible to unmount filesystems. Filesystems added\n// later will override earlier filesystems.\n//\n// The provided prefix must start and end with a forward slash. This is true for\n// the root directory (\"/\") for example.\nfunc Mount(prefix string, filesystem Filesystem) {\n\tif prefix[0] != '/' || prefix[len(prefix)-1] != '/' {\n\t\tpanic(\"os.Mount: invalid prefix\")\n\t}\n\tmounts = append(mounts, mountPoint{prefix, filesystem})\n}\n"
  },
  {
    "path": "src/os/getpagesize_test.go",
    "content": "//go:build windows || darwin || (linux && !baremetal) || wasip1 || wasip2\n\npackage os_test\n\nimport (\n\t\"os\"\n\t\"testing\"\n)\n\nfunc TestGetpagesize(t *testing.T) {\n\tpagesize := os.Getpagesize()\n\tif pagesize == 0x1000 || pagesize == 0x4000 || pagesize == 0x10000 {\n\t\treturn\n\t}\n\tt.Errorf(\"os.Getpagesize() returns strange value %d\", pagesize)\n}\n"
  },
  {
    "path": "src/os/os_anyos_test.go",
    "content": "//go:build windows || darwin || (linux && !baremetal) || wasip1 || wasip2\n\npackage os_test\n\nimport (\n\t\"io/fs\"\n\t\"os\"\n\t. \"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"strings\"\n\t\"testing\"\n\t\"testing/fstest\"\n\t\"time\"\n)\n\nvar dot = []string{\n\t\"dir.go\",\n\t\"env.go\",\n\t\"errors.go\",\n\t\"file.go\",\n\t\"os_test.go\",\n\t\"types.go\",\n\t\"stat_darwin.go\",\n}\n\nfunc randomName() string {\n\t// fastrand() does not seem available here, so fake it\n\tns := time.Now().Nanosecond()\n\tpid := Getpid()\n\treturn strconv.FormatUint(uint64(ns^pid), 10)\n}\n\nfunc TestMkdir(t *testing.T) {\n\tdir := TempDir() + \"/TestMkdir\" + randomName()\n\tRemove(dir)\n\terr := Mkdir(dir, 0755)\n\tdefer Remove(dir)\n\tif err != nil {\n\t\tt.Errorf(\"Mkdir(%s, 0755) returned %v\", dir, err)\n\t}\n\t// tests the \"directory\" branch of Remove\n\terr = Remove(dir)\n\tif err != nil {\n\t\tt.Errorf(\"Remove(%s) returned %v\", dir, err)\n\t}\n}\n\nfunc TestStatBadDir(t *testing.T) {\n\tif runtime.GOOS == \"windows\" {\n\t\tt.Log(\"TODO: TestStatBadDir: IsNotExist fails on Windows, skipping\")\n\t\treturn\n\t}\n\tdir := TempDir()\n\tbadDir := filepath.Join(dir, \"not-exist/really-not-exist\")\n\t_, err := Stat(badDir)\n\tif pe, ok := err.(*fs.PathError); !ok || !IsNotExist(err) || pe.Path != badDir {\n\t\tt.Errorf(\"Mkdir error = %#v; want PathError for path %q satisfying IsNotExist\", err, badDir)\n\t}\n}\n\nfunc equal(name1, name2 string) (r bool) {\n\tswitch runtime.GOOS {\n\tcase \"windows\":\n\t\tr = strings.ToLower(name1) == strings.ToLower(name2)\n\tdefault:\n\t\tr = name1 == name2\n\t}\n\treturn\n}\n\nfunc TestFstat(t *testing.T) {\n\tif runtime.GOARCH == \"386\" || runtime.GOARCH == \"arm\" {\n\t\tt.Log(\"TODO: implement fstat for 386 and arm\")\n\t\treturn\n\t}\n\tsfname := \"TestFstat\"\n\tpath := TempDir() + \"/\" + sfname\n\tpayload := writeFile(t, path, O_CREATE|O_TRUNC|O_RDWR, \"Hello\")\n\tdefer Remove(path)\n\n\tfile, err1 := Open(path)\n\tif err1 != nil {\n\t\tt.Fatal(\"open failed:\", err1)\n\t}\n\tdefer file.Close()\n\tdir, err2 := file.Stat()\n\tif err2 != nil {\n\t\tt.Fatal(\"fstat failed:\", err2)\n\t}\n\tif !equal(sfname, dir.Name()) {\n\t\tt.Error(\"name should be \", sfname, \"; is\", dir.Name())\n\t}\n\tfilesize := len(payload)\n\tif dir.Size() != int64(filesize) {\n\t\tt.Error(\"size should be\", filesize, \"; is\", dir.Size())\n\t}\n}\n\nfunc writeFile(t *testing.T, fname string, flag int, text string) string {\n\tf, err := OpenFile(fname, flag, 0666)\n\tif err != nil {\n\t\tt.Fatalf(\"Open: %v\", err)\n\t}\n\tn, err := f.WriteString(text)\n\tif err != nil {\n\t\tt.Fatalf(\"WriteString: %d, %v\", n, err)\n\t}\n\tf.Close()\n\tdata, err := ReadFile(f.Name())\n\tif err != nil {\n\t\tt.Fatalf(\"ReadFile: %v\", err)\n\t}\n\treturn string(data)\n}\n\nfunc TestRemove(t *testing.T) {\n\tf := TempDir() + \"/TestRemove\" + randomName()\n\n\terr := Remove(f)\n\tif err == nil {\n\t\tt.Errorf(\"TestRemove: remove of nonexistent file did not fail\")\n\t} else {\n\t\tif pe, ok := err.(*fs.PathError); !ok {\n\t\t\tt.Errorf(\"TestRemove: expected PathError, got err %q\", err.Error())\n\t\t} else {\n\t\t\tif pe.Path != f {\n\t\t\t\tt.Errorf(\"TestRemove: PathError returned path %q, expected %q\", pe.Path, f)\n\t\t\t}\n\t\t}\n\t\tif !IsNotExist(err) {\n\t\t\tt.Errorf(\"TestRemove: expected IsNotExist(err) true, got false; err %q\", err.Error())\n\t\t}\n\t}\n\n\ts := writeFile(t, f, O_CREATE|O_TRUNC|O_RDWR, \"new\")\n\tif s != \"new\" {\n\t\tt.Fatalf(\"writeFile: have %q want %q\", s, \"new\")\n\t}\n\t// tests the \"file\" branch of Remove\n\terr = Remove(f)\n\tif err != nil {\n\t\tt.Fatalf(\"Remove: %v\", err)\n\t}\n}\n\n// chtmpdir changes the working directory to a new temporary directory and\n// provides a cleanup function.\nfunc chtmpdir(t *testing.T) func() {\n\toldwd, err := Getwd()\n\tif err != nil {\n\t\tt.Fatalf(\"chtmpdir: %v\", err)\n\t}\n\td, err := MkdirTemp(\"\", \"test\")\n\tif err != nil {\n\t\tt.Fatalf(\"chtmpdir: %v\", err)\n\t}\n\tif err := Chdir(d); err != nil {\n\t\tt.Fatalf(\"chtmpdir: %v\", err)\n\t}\n\treturn func() {\n\t\tif err := Chdir(oldwd); err != nil {\n\t\t\tt.Fatalf(\"chtmpdir: %v\", err)\n\t\t}\n\t\tRemoveAll(d)\n\t}\n}\n\nfunc TestRename(t *testing.T) {\n\t// TODO: use t.TempDir()\n\tfrom, to := TempDir()+\"/\"+\"TestRename-from\", TempDir()+\"/\"+\"TestRename-to\"\n\n\tfile, err := Create(from)\n\tdefer Remove(from) // TODO: switch to t.Tempdir, remove this line\n\tif err != nil {\n\t\tt.Fatalf(\"open %q failed: %v\", from, err)\n\t}\n\tdefer Remove(to) // TODO: switch to t.Tempdir, remove this line\n\tif err = file.Close(); err != nil {\n\t\tt.Errorf(\"close %q failed: %v\", from, err)\n\t}\n\terr = Rename(from, to)\n\tif err != nil {\n\t\tt.Fatalf(\"rename %q, %q failed: %v\", to, from, err)\n\t}\n\t_, err = Stat(to)\n\tif err != nil {\n\t\tt.Errorf(\"stat %q failed: %v\", to, err)\n\t}\n}\n\nfunc TestRenameOverwriteDest(t *testing.T) {\n\tfrom, to := TempDir()+\"/\"+\"TestRenameOverwrite-from\", TempDir()+\"/\"+\"TestRenameOverwrite-to\"\n\n\ttoData := []byte(\"to\")\n\tfromData := []byte(\"from\")\n\n\terr := os.WriteFile(to, toData, 0777)\n\tdefer Remove(to) // TODO: switch to t.Tempdir, remove this line\n\tif err != nil {\n\t\tt.Fatalf(\"write file %q failed: %v\", to, err)\n\t}\n\n\terr = os.WriteFile(from, fromData, 0777)\n\tdefer Remove(from) // TODO: switch to t.Tempdir, remove this line\n\tif err != nil {\n\t\tt.Fatalf(\"write file %q failed: %v\", from, err)\n\t}\n\terr = Rename(from, to)\n\tif err != nil {\n\t\tt.Fatalf(\"rename %q, %q failed: %v\", to, from, err)\n\t}\n\n\t_, err = Stat(from)\n\tif err == nil {\n\t\tt.Errorf(\"from file %q still exists\", from)\n\t}\n\tif runtime.GOOS == \"windows\" {\n\t\tt.Log(\"TODO: TestRenameOverwriteDest: IsNotExist fails on Windows, skipping\")\n\t} else if err != nil && !IsNotExist(err) {\n\t\tt.Fatalf(\"stat from: %v\", err)\n\t}\n\ttoFi, err := Stat(to)\n\tif err != nil {\n\t\tt.Fatalf(\"stat %q failed: %v\", to, err)\n\t}\n\tif toFi.Size() != int64(len(fromData)) {\n\t\tt.Errorf(`\"to\" size = %d; want %d (old \"from\" size)`, toFi.Size(), len(fromData))\n\t}\n}\n\nfunc TestRenameFailed(t *testing.T) {\n\tfrom, to := TempDir()+\"/\"+\"RenameFailed-from\", TempDir()+\"/\"+\"RenameFailed-to\"\n\n\terr := Rename(from, to)\n\tswitch err := err.(type) {\n\tcase *LinkError:\n\t\tif err.Op != \"rename\" {\n\t\t\tt.Errorf(\"rename %q, %q: err.Op: want %q, got %q\", from, to, \"rename\", err.Op)\n\t\t}\n\t\tif err.Old != from {\n\t\t\tt.Errorf(\"rename %q, %q: err.Old: want %q, got %q\", from, to, from, err.Old)\n\t\t}\n\t\tif err.New != to {\n\t\t\tt.Errorf(\"rename %q, %q: err.New: want %q, got %q\", from, to, to, err.New)\n\t\t}\n\tcase nil:\n\t\tt.Errorf(\"rename %q, %q: expected error, got nil\", from, to)\n\tdefault:\n\t\tt.Errorf(\"rename %q, %q: expected %T, got %T %v\", from, to, new(LinkError), err, err)\n\t}\n}\n\nfunc TestUserHomeDir(t *testing.T) {\n\tdir, err := UserHomeDir()\n\tif dir == \"\" && err == nil {\n\t\tt.Fatal(\"UserHomeDir returned an empty string but no error\")\n\t}\n\tif err != nil {\n\t\tt.Logf(\"UserHomeDir failed: %v\", err)\n\t\treturn\n\t}\n\tfi, err := Stat(dir)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !fi.IsDir() {\n\t\tt.Fatalf(\"dir %s is not directory; type = %v\", dir, fi.Mode())\n\t}\n}\n\nfunc TestDirFS(t *testing.T) {\n\tif runtime.GOOS == \"windows\" {\n\t\tt.Log(\"TODO: implement Readdir for Windows\")\n\t\treturn\n\t}\n\tif runtime.GOOS == \"wasip1\" || runtime.GOOS == \"wasip2\" {\n\t\tt.Log(\"TODO: allow foo/bar/. as synonym for path foo/bar on wasi?\")\n\t\treturn\n\t}\n\tif err := fstest.TestFS(DirFS(\"./testdata/dirfs\"), \"a\", \"b\", \"dir/x\"); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Test that Open does not accept backslash as separator.\n\td := DirFS(\".\")\n\t_, err := d.Open(`testdata\\dirfs`)\n\tif err == nil {\n\t\tt.Fatalf(`Open testdata\\dirfs succeeded`)\n\t}\n}\n\nfunc TestDirFSPathsValid(t *testing.T) {\n\tif runtime.GOOS == \"windows\" {\n\t\tt.Log(\"skipping on Windows\")\n\t\treturn\n\t}\n\tif runtime.GOOS == \"wasip1\" || runtime.GOOS == \"wasip2\" {\n\t\tt.Log(\"skipping on wasi because it fails on wasi on windows\")\n\t\treturn\n\t}\n\n\t// TODO: switch back to t.TempDir once it's implemented\n\td, err := MkdirTemp(\"\", \"TestDirFSPathsValid\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer Remove(d)\n\tif err := WriteFile(filepath.Join(d, \"control.txt\"), []byte(string(\"Hello, world!\")), 0644); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer Remove(filepath.Join(d, \"control.txt\"))\n\tif err := WriteFile(filepath.Join(d, `e:xperi\\ment.txt`), []byte(string(\"Hello, colon and backslash!\")), 0644); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer Remove(filepath.Join(d, `e:xperi\\ment.txt`))\n\n\tfsys := DirFS(d)\n\terr = fs.WalkDir(fsys, \".\", func(path string, e fs.DirEntry, err error) error {\n\t\tif fs.ValidPath(e.Name()) {\n\t\t\tt.Logf(\"%q ok\", e.Name())\n\t\t} else {\n\t\t\tt.Errorf(\"%q INVALID\", e.Name())\n\t\t}\n\t\treturn nil\n\t})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n}\n"
  },
  {
    "path": "src/os/os_chmod_test.go",
    "content": "//go:build !baremetal && !js && !wasip1 && !wasip2\n\n// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// TODO: Move this back into os_test.go (as upstream has it) when wasi supports chmod\n\npackage os_test\n\nimport (\n\t\"errors\"\n\t\"io/fs\"\n\t. \"os\"\n\t\"runtime\"\n\t\"testing\"\n)\n\nfunc TestChmod(t *testing.T) {\n\t// Chmod\n\tf := newFile(\"TestChmod\", t)\n\tdefer Remove(f.Name())\n\tdefer f.Close()\n\t// Creation mode is read write\n\n\tfm := FileMode(0456)\n\tif runtime.GOOS == \"windows\" {\n\t\tfm = FileMode(0444) // read-only file\n\t}\n\tif err := Chmod(f.Name(), fm); err != nil {\n\t\tt.Fatalf(\"chmod %s %#o: %s\", f.Name(), fm, err)\n\t}\n\tcheckMode(t, f.Name(), fm)\n\n}\n\n// Since testing syscalls requires a static, predictable environment that has to be controlled\n// by the CI, we don't test for success but for failures and verify that the error messages are as expected.\n// EACCES is returned when the user does not have the required permissions to change the ownership of the file\n// ENOENT is returned when the file does not exist\n// ENOTDIR is returned when the file is not a directory\nfunc TestChownErr(t *testing.T) {\n\tif runtime.GOOS == \"windows\" || runtime.GOOS == \"plan9\" {\n\t\tt.Log(\"skipping on \" + runtime.GOOS)\n\t\treturn\n\t}\n\n\tvar (\n\t\tTEST_UID_ROOT = 0\n\t\tTEST_GID_ROOT = 0\n\t)\n\n\tf := newFile(\"TestChown\", t)\n\tdefer Remove(f.Name())\n\tdefer f.Close()\n\n\t// EACCES\n\tif err := Chown(f.Name(), TEST_UID_ROOT, TEST_GID_ROOT); err != nil {\n\t\terrCmp := fs.PathError{Op: \"chown\", Path: f.Name(), Err: errors.New(\"operation not permitted\")}\n\t\tif errors.Is(err, &errCmp) {\n\t\t\tt.Fatalf(\"chown(%s, uid=%v, gid=%v): got '%v', want 'operation not permitted'\", f.Name(), TEST_UID_ROOT, TEST_GID_ROOT, err)\n\t\t}\n\t}\n\n\t// ENOENT\n\tif err := Chown(\"invalid\", Geteuid(), Getgid()); err != nil {\n\t\terrCmp := fs.PathError{Op: \"chown\", Path: \"invalid\", Err: errors.New(\"no such file or directory\")}\n\t\tif errors.Is(err, &errCmp) {\n\t\t\tt.Fatalf(\"chown(%s, uid=%v, gid=%v): got '%v', want 'no such file or directory'\", f.Name(), Geteuid(), Getegid(), err)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/os/os_hardlink_test.go",
    "content": "//go:build !windows && !baremetal && !js && !wasip1 && !wasm_unknown\n\n// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os_test\n\nimport (\n\t. \"os\"\n\t\"syscall\"\n\t\"testing\"\n)\n\nfunc TestHardlink(t *testing.T) {\n\tdefer chtmpdir(t)()\n\tfrom, to := \"hardlinktestfrom\", \"hardlinktestto\"\n\n\tfile, err := Create(to)\n\tif err != nil {\n\t\tt.Fatalf(\"Create(%q) failed: %v\", to, err)\n\t}\n\tif err = file.Close(); err != nil {\n\t\tt.Errorf(\"Close(%q) failed: %v\", to, err)\n\t}\n\terr = Link(to, from)\n\tif err != nil {\n\t\tt.Fatalf(\"Link(%q, %q) failed: %v\", to, from, err)\n\t}\n\n\ttostat, err := Lstat(to)\n\tif err != nil {\n\t\tt.Fatalf(\"Lstat(%q) failed: %v\", to, err)\n\t}\n\tfromstat, err := Stat(from)\n\tif err != nil {\n\t\tt.Fatalf(\"Stat(%q) failed: %v\", from, err)\n\t}\n\tif !SameFile(tostat, fromstat) {\n\t\tt.Errorf(\"Symlink(%q, %q) did not create symlink\", to, from)\n\t}\n\n\tfromstat, err = Lstat(from)\n\tif err != nil {\n\t\tt.Fatalf(\"Lstat(%q) failed: %v\", from, err)\n\t}\n\t// if they have the same inode, they are hard links\n\tif fromstat.Sys().(*syscall.Stat_t).Ino != tostat.Sys().(*syscall.Stat_t).Ino {\n\t\tt.Fatalf(\"Lstat(%q).Sys().Ino = %v, Lstat(%q).Sys().Ino = %v, want the same\", to, tostat.Sys().(*syscall.Stat_t).Ino, from, fromstat.Sys().(*syscall.Stat_t).Ino)\n\t}\n\n\tfile.Close()\n}\n"
  },
  {
    "path": "src/os/os_symlink_test.go",
    "content": "//go:build !windows && !baremetal && !js && !wasip1 && !wasip2\n\n// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os_test\n\nimport (\n\t. \"os\"\n\t\"testing\"\n)\n\n// TODO: Move this back into os_anyos_test.go when wasi supports symlink\n\nfunc TestSymlink(t *testing.T) {\n\t//testenv.MustHaveSymlink(t)\n\n\tdefer chtmpdir(t)()\n\tfrom, to := \"symlinktestfrom\", \"symlinktestto\"\n\tfile, err := Create(to)\n\tif err != nil {\n\t\tt.Fatalf(\"Create(%q) failed: %v\", to, err)\n\t}\n\tif err = file.Close(); err != nil {\n\t\tt.Errorf(\"Close(%q) failed: %v\", to, err)\n\t}\n\terr = Symlink(to, from)\n\tif err != nil {\n\t\tt.Fatalf(\"Symlink(%q, %q) failed: %v\", to, from, err)\n\t}\n\ttostat, err := Lstat(to)\n\tif err != nil {\n\t\tt.Fatalf(\"Lstat(%q) failed: %v\", to, err)\n\t}\n\tif tostat.Mode()&ModeSymlink != 0 {\n\t\tt.Fatalf(\"Lstat(%q).Mode()&ModeSymlink = %v, want 0\", to, tostat.Mode()&ModeSymlink)\n\t}\n\tfromstat, err := Stat(from)\n\tif err != nil {\n\t\tt.Fatalf(\"Stat(%q) failed: %v\", from, err)\n\t}\n\tif !SameFile(tostat, fromstat) {\n\t\tt.Errorf(\"Symlink(%q, %q) did not create symlink\", to, from)\n\t}\n\tfromstat, err = Lstat(from)\n\tif err != nil {\n\t\tt.Fatalf(\"Lstat(%q) failed: %v\", from, err)\n\t}\n\tif fromstat.Mode()&ModeSymlink == 0 {\n\t\tt.Fatalf(\"Lstat(%q).Mode()&ModeSymlink = 0, want %v\", from, ModeSymlink)\n\t}\n\tfromstat, err = Stat(from)\n\tif err != nil {\n\t\tt.Fatalf(\"Stat(%q) failed: %v\", from, err)\n\t}\n\tif fromstat.Name() != from {\n\t\tt.Errorf(\"Stat(%q).Name() = %q, want %q\", from, fromstat.Name(), from)\n\t}\n\tif fromstat.Mode()&ModeSymlink != 0 {\n\t\tt.Fatalf(\"Stat(%q).Mode()&ModeSymlink = %v, want 0\", from, fromstat.Mode()&ModeSymlink)\n\t}\n\ts, err := Readlink(from)\n\tif err != nil {\n\t\tt.Fatalf(\"Readlink(%q) failed: %v\", from, err)\n\t}\n\tif s != to {\n\t\tt.Fatalf(\"Readlink(%q) = %q, want %q\", from, s, to)\n\t}\n\tfile, err = Open(from)\n\tif err != nil {\n\t\tt.Fatalf(\"Open(%q) failed: %v\", from, err)\n\t}\n\tfile.Close()\n}\n"
  },
  {
    "path": "src/os/os_test.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os_test\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t. \"os\"\n\t\"runtime\"\n\t\"strings\"\n\t\"syscall\"\n\t\"testing\"\n)\n\n// localTmp returns a local temporary directory not on NFS.\nfunc localTmp() string {\n\treturn TempDir()\n}\n\nfunc newFile(testName string, t *testing.T) (f *File) {\n\tf, err := CreateTemp(\"\", testName)\n\tif err != nil {\n\t\tt.Fatalf(\"newFile %s: CreateTemp fails with %s\", testName, err)\n\t}\n\treturn\n}\n\n// Read with length 0 should not return EOF.\nfunc TestRead0(t *testing.T) {\n\tf := newFile(\"TestRead0\", t)\n\tdefer Remove(f.Name())\n\tdefer f.Close()\n\n\tconst data = \"hello, world\\n\"\n\tio.WriteString(f, data)\n\tf.Close()\n\tf, err := Open(f.Name())\n\tif err != nil {\n\t\tt.Errorf(\"failed to reopen\")\n\t}\n\n\tb := make([]byte, 0)\n\tn, err := f.Read(b)\n\tif n != 0 || err != nil {\n\t\tt.Errorf(\"Read(0) = %d, %v, want 0, nil\", n, err)\n\t}\n\tb = make([]byte, 5)\n\tn, err = f.Read(b)\n\tif n <= 0 || err != nil {\n\t\tt.Errorf(\"Read(5) = %d, %v, want >0, nil\", n, err)\n\t}\n}\n\n// ReadAt with length 0 should not return EOF.\nfunc TestReadAt0(t *testing.T) {\n\tif runtime.GOOS == \"windows\" {\n\t\tt.Log(\"TODO: implement Pread for Windows\")\n\t\treturn\n\t}\n\tf := newFile(\"TestReadAt0\", t)\n\tdefer Remove(f.Name())\n\tdefer f.Close()\n\n\tconst data = \"hello, world\\n\"\n\tio.WriteString(f, data)\n\n\tb := make([]byte, 0)\n\tn, err := f.ReadAt(b, 0)\n\tif n != 0 || err != nil {\n\t\tt.Errorf(\"ReadAt(0,0) = %d, %v, want 0, nil\", n, err)\n\t}\n\tb = make([]byte, 5)\n\tn, err = f.ReadAt(b, 0)\n\tif n <= 0 || err != nil {\n\t\tt.Errorf(\"ReadAt(5,0) = %d, %v, want >0, nil\", n, err)\n\t}\n}\n\nfunc checkMode(t *testing.T, path string, mode FileMode) {\n\tdir, err := Stat(path)\n\tif err != nil {\n\t\tt.Fatalf(\"Stat %q (looking for mode %#o): %s\", path, mode, err)\n\t}\n\tif dir.Mode()&ModePerm != mode {\n\t\tt.Errorf(\"Stat %q: mode %#o want %#o\", path, dir.Mode(), mode)\n\t}\n}\n\nfunc TestSeek(t *testing.T) {\n\tif runtime.GOARCH == \"386\" || runtime.GOARCH == \"arm\" {\n\t\tt.Log(\"TODO: implement seek for 386 and arm\")\n\t\treturn\n\t}\n\tf := newFile(\"TestSeek\", t)\n\tif f == nil {\n\t\tt.Fatalf(\"f is nil\")\n\t\treturn // TODO: remove\n\t}\n\tdefer Remove(f.Name())\n\tdefer f.Close()\n\n\tconst data = \"hello, world\\n\"\n\tio.WriteString(f, data)\n\n\ttype test struct {\n\t\tin     int64\n\t\twhence int\n\t\tout    int64\n\t}\n\tvar tests = []test{\n\t\t{0, io.SeekCurrent, int64(len(data))},\n\t\t{0, io.SeekStart, 0},\n\t\t{5, io.SeekStart, 5},\n\t\t{0, io.SeekEnd, int64(len(data))},\n\t\t{0, io.SeekStart, 0},\n\t\t{-1, io.SeekEnd, int64(len(data)) - 1},\n\t\t{1 << 33, io.SeekStart, 1 << 33},\n\t\t{1 << 33, io.SeekEnd, 1<<33 + int64(len(data))},\n\n\t\t// Issue 21681, Windows 4G-1, etc:\n\t\t{1<<32 - 1, io.SeekStart, 1<<32 - 1},\n\t\t{0, io.SeekCurrent, 1<<32 - 1},\n\t\t{2<<32 - 1, io.SeekStart, 2<<32 - 1},\n\t\t{0, io.SeekCurrent, 2<<32 - 1},\n\t}\n\tfor i, tt := range tests {\n\t\toff, err := f.Seek(tt.in, tt.whence)\n\t\tif off != tt.out || err != nil {\n\t\t\tif e, ok := err.(*PathError); ok && e.Err == syscall.EINVAL && tt.out > 1<<32 && runtime.GOOS == \"linux\" {\n\t\t\t\tmounts, _ := os.ReadFile(\"/proc/mounts\")\n\t\t\t\tif strings.Contains(string(mounts), \"reiserfs\") {\n\t\t\t\t\t// Reiserfs rejects the big seeks.\n\t\t\t\t\tt.Skipf(\"skipping test known to fail on reiserfs; https://golang.org/issue/91\")\n\t\t\t\t}\n\t\t\t}\n\t\t\tt.Errorf(\"#%d: Seek(%v, %v) = %v, %v want %v, nil\", i, tt.in, tt.whence, off, err, tt.out)\n\t\t}\n\t}\n}\n\nfunc TestReadAt(t *testing.T) {\n\tif runtime.GOOS == \"windows\" {\n\t\tt.Log(\"TODO: implement Pread for Windows\")\n\t\treturn\n\t}\n\tf := newFile(\"TestReadAt\", t)\n\tdefer Remove(f.Name())\n\tdefer f.Close()\n\n\tconst data = \"hello, world\\n\"\n\tio.WriteString(f, data)\n\n\tb := make([]byte, 5)\n\tn, err := f.ReadAt(b, 7)\n\tif err != nil || n != len(b) {\n\t\tt.Fatalf(\"ReadAt 7: %d, %v\", n, err)\n\t}\n\tif string(b) != \"world\" {\n\t\tt.Fatalf(\"ReadAt 7: have %q want %q\", string(b), \"world\")\n\t}\n}\n\n// Verify that ReadAt doesn't affect seek offset.\n// In the Plan 9 kernel, there used to be a bug in the implementation of\n// the pread syscall, where the channel offset was erroneously updated after\n// calling pread on a file.\nfunc TestReadAtOffset(t *testing.T) {\n\tif runtime.GOOS == \"windows\" {\n\t\tt.Log(\"TODO: implement Pread for Windows\")\n\t\treturn\n\t}\n\tf := newFile(\"TestReadAtOffset\", t)\n\tdefer Remove(f.Name())\n\tdefer f.Close()\n\n\tconst data = \"hello, world\\n\"\n\tio.WriteString(f, data)\n\tf.Close()\n\tf, err := Open(f.Name())\n\tif err != nil {\n\t\tt.Errorf(\"failed to reopen\")\n\t}\n\n\tb := make([]byte, 5)\n\n\tn, err := f.ReadAt(b, 7)\n\tif err != nil || n != len(b) {\n\t\tt.Fatalf(\"ReadAt 7: %d, %v\", n, err)\n\t}\n\tif string(b) != \"world\" {\n\t\tt.Fatalf(\"ReadAt 7: have %q want %q\", string(b), \"world\")\n\t}\n\n\tn, err = f.Read(b)\n\tif err != nil || n != len(b) {\n\t\tt.Fatalf(\"Read: %d, %v\", n, err)\n\t}\n\tif string(b) != \"hello\" {\n\t\tt.Fatalf(\"Read: have %q want %q\", string(b), \"hello\")\n\t}\n}\n\n// Verify that ReadAt doesn't allow negative offset.\nfunc TestReadAtNegativeOffset(t *testing.T) {\n\tif runtime.GOOS == \"windows\" {\n\t\tt.Log(\"TODO: implement Pread for Windows\")\n\t\treturn\n\t}\n\tf := newFile(\"TestReadAtNegativeOffset\", t)\n\tdefer Remove(f.Name())\n\tdefer f.Close()\n\n\tconst data = \"hello, world\\n\"\n\tio.WriteString(f, data)\n\tf.Close()\n\tf, err := Open(f.Name())\n\tif err != nil {\n\t\tt.Errorf(\"failed to reopen\")\n\t}\n\n\tb := make([]byte, 5)\n\n\tn, err := f.ReadAt(b, -10)\n\n\tconst wantsub = \"negative offset\"\n\tif !strings.Contains(err.Error(), wantsub) || n != 0 {\n\t\tt.Errorf(\"ReadAt(-10) = %v, %v; want 0, ...%q...\", n, err, wantsub)\n\t}\n}\n\nfunc TestReadAtEOF(t *testing.T) {\n\tif runtime.GOOS == \"windows\" {\n\t\tt.Log(\"TODO: implement Pread for Windows\")\n\t\treturn\n\t}\n\tf := newFile(\"TestReadAtEOF\", t)\n\tdefer Remove(f.Name())\n\tdefer f.Close()\n\n\t_, err := f.ReadAt(make([]byte, 10), 0)\n\tswitch err {\n\tcase io.EOF:\n\t\t// all good\n\tcase nil:\n\t\tt.Fatalf(\"ReadAt succeeded\")\n\tdefault:\n\t\tt.Fatalf(\"ReadAt failed: %s\", err)\n\t}\n}\n\nfunc TestWriteAt(t *testing.T) {\n\tif runtime.GOOS == \"windows\" {\n\t\tt.Log(\"TODO: implement Pwrite for Windows\")\n\t\treturn\n\t}\n\tf := newFile(\"TestWriteAt\", t)\n\tdefer Remove(f.Name())\n\tdefer f.Close()\n\n\tconst data = \"hello, world\\n\"\n\tio.WriteString(f, data)\n\n\tn, err := f.WriteAt([]byte(\"WORLD\"), 7)\n\tif err != nil || n != 5 {\n\t\tt.Fatalf(\"WriteAt 7: %d, %v\", n, err)\n\t}\n\n\tb, err := os.ReadFile(f.Name())\n\tif err != nil {\n\t\tt.Fatalf(\"ReadFile %s: %v\", f.Name(), err)\n\t}\n\tif string(b) != \"hello, WORLD\\n\" {\n\t\tt.Fatalf(\"after write: have %q want %q\", string(b), \"hello, WORLD\\n\")\n\t}\n}\n\n// Verify that WriteAt doesn't allow negative offset.\nfunc TestWriteAtNegativeOffset(t *testing.T) {\n\tif runtime.GOOS == \"windows\" {\n\t\tt.Log(\"TODO: implement Pwrite for Windows\")\n\t\treturn\n\t}\n\tf := newFile(\"TestWriteAtNegativeOffset\", t)\n\tdefer Remove(f.Name())\n\tdefer f.Close()\n\n\tn, err := f.WriteAt([]byte(\"WORLD\"), -10)\n\n\tconst wantsub = \"negative offset\"\n\tif !strings.Contains(fmt.Sprint(err), wantsub) || n != 0 {\n\t\tt.Errorf(\"WriteAt(-10) = %v, %v; want 0, ...%q...\", n, err, wantsub)\n\t}\n}\n\n// Verify that WriteAt doesn't work in append mode.\nfunc TestWriteAtInAppendMode(t *testing.T) {\n\tif runtime.GOOS == \"windows\" {\n\t\tt.Log(\"TODO: implement Pwrite for Windows\")\n\t\treturn\n\t}\n\tdefer chtmpdir(t)()\n\tf, err := OpenFile(\"write_at_in_append_mode.txt\", O_APPEND|O_CREATE|O_WRONLY, 0666)\n\tif err != nil {\n\t\tt.Fatalf(\"OpenFile: %v\", err)\n\t}\n\tdefer f.Close()\n\n\t_, err = f.WriteAt([]byte(\"\"), 1)\n\tif err != ErrWriteAtInAppendMode {\n\t\tt.Fatalf(\"f.WriteAt returned %v, expected %v\", err, ErrWriteAtInAppendMode)\n\t}\n}\n"
  },
  {
    "path": "src/os/osexec.go",
    "content": "//go:build linux && !baremetal && !tinygo.wasm && !nintendoswitch\n\npackage os\n\nimport (\n\t\"syscall\"\n\t\"unsafe\"\n)\n\nfunc fork() (pid int32, err error) {\n\tpid = libc_fork()\n\tif pid != 0 {\n\t\tif errno := *libc_errno(); errno != 0 {\n\t\t\terr = syscall.Errno(*libc_errno())\n\t\t}\n\t}\n\treturn\n}\n\n// the golang standard library does not expose interfaces for execve and fork, so we define them here the same way via the libc wrapper\nfunc execve(pathname string, argv []string, envv []string) error {\n\targv0 := cstring(pathname)\n\n\t// transform argv and envv into the format expected by execve\n\targv1 := make([]*byte, len(argv)+1)\n\tfor i, arg := range argv {\n\t\targv1[i] = &cstring(arg)[0]\n\t}\n\targv1[len(argv)] = nil\n\n\tenv1 := make([]*byte, len(envv)+1)\n\tfor i, env := range envv {\n\t\tenv1[i] = &cstring(env)[0]\n\t}\n\tenv1[len(envv)] = nil\n\n\tret, _, err := syscall.Syscall(syscall.SYS_EXECVE, uintptr(unsafe.Pointer(&argv0[0])), uintptr(unsafe.Pointer(&argv1[0])), uintptr(unsafe.Pointer(&env1[0])))\n\tif int(ret) != 0 {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc cstring(s string) []byte {\n\tdata := make([]byte, len(s)+1)\n\tcopy(data, s)\n\t// final byte should be zero from the initial allocation\n\treturn data\n}\n\n//export fork\nfunc libc_fork() int32\n\n// Internal musl function to get the C errno pointer.\n//\n//export __errno_location\nfunc libc_errno() *int32\n"
  },
  {
    "path": "src/os/path.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os\n\nimport (\n\t\"syscall\"\n)\n\n// MkdirAll creates a directory named path,\n// along with any necessary parents, and returns nil,\n// or else returns an error.\n// The permission bits perm (before umask) are used for all\n// directories that MkdirAll creates.\n// If path is already a directory, MkdirAll does nothing\n// and returns nil.\nfunc MkdirAll(path string, perm FileMode) error {\n\t// Fast path: if we can tell whether path is a directory or file, stop with success or error.\n\tdir, err := Stat(path)\n\tif err == nil {\n\t\tif dir.IsDir() {\n\t\t\treturn nil\n\t\t}\n\t\treturn &PathError{Op: \"mkdir\", Path: path, Err: syscall.ENOTDIR}\n\t}\n\n\t// Slow path: make sure parent exists and then call Mkdir for path.\n\ti := len(path)\n\tfor i > 0 && IsPathSeparator(path[i-1]) { // Skip trailing path separator.\n\t\ti--\n\t}\n\n\tj := i\n\tfor j > 0 && !IsPathSeparator(path[j-1]) { // Scan backward over element.\n\t\tj--\n\t}\n\n\tif j > 1 {\n\t\t// Create parent.\n\t\terr = MkdirAll(fixRootDirectory(path[:j-1]), perm)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// Parent now exists; invoke Mkdir and use its result.\n\terr = Mkdir(path, perm)\n\tif err != nil {\n\t\t// Handle arguments like \"foo/.\" by\n\t\t// double-checking that directory doesn't exist.\n\t\tdir, err1 := Lstat(path)\n\t\tif err1 == nil && dir.IsDir() {\n\t\t\treturn nil\n\t\t}\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// RemoveAll removes path and any children it contains.\n// It removes everything it can but returns the first error\n// it encounters. If the path does not exist, RemoveAll\n// returns nil (no error).\n// If there is an error, it will be of type *PathError.\nfunc RemoveAll(path string) error {\n\treturn removeAll(path)\n}\n\n// endsWithDot reports whether the final component of path is \".\".\nfunc endsWithDot(path string) bool {\n\tif path == \".\" {\n\t\treturn true\n\t}\n\tif len(path) >= 2 && path[len(path)-1] == '.' && IsPathSeparator(path[len(path)-2]) {\n\t\treturn true\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "src/os/path_test.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os_test\n\nimport (\n\t. \"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"testing\"\n)\n\nfunc TestMkdirAll(t *testing.T) {\n\ttmpDir := TempDir()\n\tpath := tmpDir + \"/_TestMkdirAll_/dir/./dir2\"\n\terr := MkdirAll(path, 0777)\n\tif err != nil {\n\t\tt.Fatalf(\"MkdirAll %q: %s\", path, err)\n\t}\n\t// TODO: revert to upstream code which uses RemoveAll\n\tdefer Remove(tmpDir + \"/_TestMkdirAll_/dir/dir2\")\n\tdefer Remove(tmpDir + \"/_TestMkdirAll_/dir\")\n\tdefer Remove(tmpDir + \"/_TestMkdirAll_\")\n\n\t// Already exists, should succeed.\n\terr = MkdirAll(path, 0777)\n\tif err != nil {\n\t\tt.Fatalf(\"MkdirAll %q (second time): %s\", path, err)\n\t}\n\n\t// Make file.\n\tfpath := path + \"/file\"\n\tf, err := Create(fpath)\n\tif err != nil {\n\t\tt.Fatalf(\"create %q: %s\", fpath, err)\n\t}\n\tdefer Remove(fpath)\n\tdefer f.Close()\n\n\t// Can't make directory named after file.\n\terr = MkdirAll(fpath, 0777)\n\tif err == nil {\n\t\tt.Fatalf(\"MkdirAll %q: no error\", fpath)\n\t}\n\tperr, ok := err.(*PathError)\n\tif !ok {\n\t\tt.Fatalf(\"MkdirAll %q returned %T, not *PathError\", fpath, err)\n\t}\n\tif filepath.Clean(perr.Path) != filepath.Clean(fpath) {\n\t\tt.Fatalf(\"MkdirAll %q returned wrong error path: %q not %q\", fpath, filepath.Clean(perr.Path), filepath.Clean(fpath))\n\t}\n\n\t// Can't make subdirectory of file.\n\tffpath := fpath + \"/subdir\"\n\terr = MkdirAll(ffpath, 0777)\n\tif err == nil {\n\t\tt.Fatalf(\"MkdirAll %q: no error\", ffpath)\n\t}\n\tperr, ok = err.(*PathError)\n\tif !ok {\n\t\tt.Fatalf(\"MkdirAll %q returned %T, not *PathError\", ffpath, err)\n\t}\n\tif filepath.Clean(perr.Path) != filepath.Clean(fpath) {\n\t\tt.Fatalf(\"MkdirAll %q returned wrong error path: %q not %q\", ffpath, filepath.Clean(perr.Path), filepath.Clean(fpath))\n\t}\n\n\tif runtime.GOOS == \"windows\" {\n\t\tpath := tmpDir + `\\_TestMkdirAll_\\dir\\.\\dir2\\`\n\t\terr := MkdirAll(path, 0777)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"MkdirAll %q: %s\", path, err)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/os/path_unix.go",
    "content": "//go:build !windows\n\n// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os\n\nconst (\n\tPathSeparator     = '/' // PathSeparator is the OS-specific path separator\n\tPathListSeparator = ':' // PathListSeparator is the OS-specific path list separator\n)\n\n// IsPathSeparator reports whether c is a directory separator character.\nfunc IsPathSeparator(c uint8) bool {\n\treturn PathSeparator == c\n}\n\n// basename removes trailing slashes and the leading directory name from path name.\nfunc basename(name string) string {\n\ti := len(name) - 1\n\t// Remove trailing slashes\n\tfor ; i > 0 && name[i] == '/'; i-- {\n\t\tname = name[:i]\n\t}\n\t// Remove leading directory name\n\tfor i--; i >= 0; i-- {\n\t\tif name[i] == '/' {\n\t\t\tname = name[i+1:]\n\t\t\tbreak\n\t\t}\n\t}\n\n\treturn name\n}\n\nfunc fixRootDirectory(p string) string {\n\treturn p\n}\n"
  },
  {
    "path": "src/os/path_windows.go",
    "content": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os\n\nconst (\n\tPathSeparator     = '\\\\' // PathSeparator is the OS-specific path separator\n\tPathListSeparator = ';'  // PathListSeparator is the OS-specific path list separator\n)\n\n// IsPathSeparator reports whether c is a directory separator character.\nfunc IsPathSeparator(c uint8) bool {\n\t// NOTE: Windows accept / as path separator.\n\treturn c == '\\\\' || c == '/'\n}\n\n// basename removes trailing slashes and the leading\n// directory name and drive letter from path name.\nfunc basename(name string) string {\n\t// Remove drive letter\n\tif len(name) == 2 && name[1] == ':' {\n\t\tname = \".\"\n\t} else if len(name) > 2 && name[1] == ':' {\n\t\tname = name[2:]\n\t}\n\ti := len(name) - 1\n\t// Remove trailing slashes\n\tfor ; i > 0 && (name[i] == '/' || name[i] == '\\\\'); i-- {\n\t\tname = name[:i]\n\t}\n\t// Remove leading directory name\n\tfor i--; i >= 0; i-- {\n\t\tif name[i] == '/' || name[i] == '\\\\' {\n\t\t\tname = name[i+1:]\n\t\t\tbreak\n\t\t}\n\t}\n\treturn name\n}\n\nfunc isAbs(path string) (b bool) {\n\tv := volumeName(path)\n\tif v == \"\" {\n\t\treturn false\n\t}\n\tpath = path[len(v):]\n\tif path == \"\" {\n\t\treturn false\n\t}\n\treturn IsPathSeparator(path[0])\n}\n\nfunc volumeName(path string) (v string) {\n\tif len(path) < 2 {\n\t\treturn \"\"\n\t}\n\t// with drive letter\n\tc := path[0]\n\tif path[1] == ':' &&\n\t\t('0' <= c && c <= '9' || 'a' <= c && c <= 'z' ||\n\t\t\t'A' <= c && c <= 'Z') {\n\t\treturn path[:2]\n\t}\n\t// is it UNC\n\tif l := len(path); l >= 5 && IsPathSeparator(path[0]) && IsPathSeparator(path[1]) &&\n\t\t!IsPathSeparator(path[2]) && path[2] != '.' {\n\t\t// first, leading `\\\\` and next shouldn't be `\\`. its server name.\n\t\tfor n := 3; n < l-1; n++ {\n\t\t\t// second, next '\\' shouldn't be repeated.\n\t\t\tif IsPathSeparator(path[n]) {\n\t\t\t\tn++\n\t\t\t\t// third, following something characters. its share name.\n\t\t\t\tif !IsPathSeparator(path[n]) {\n\t\t\t\t\tif path[n] == '.' {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tfor ; n < l; n++ {\n\t\t\t\t\t\tif IsPathSeparator(path[n]) {\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn path[:n]\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\treturn \"\"\n}\n\nfunc fromSlash(path string) string {\n\t// Replace each '/' with '\\\\' if present\n\tvar pathbuf []byte\n\tvar lastSlash int\n\tfor i, b := range path {\n\t\tif b == '/' {\n\t\t\tif pathbuf == nil {\n\t\t\t\tpathbuf = make([]byte, len(path))\n\t\t\t}\n\t\t\tcopy(pathbuf[lastSlash:], path[lastSlash:i])\n\t\t\tpathbuf[i] = '\\\\'\n\t\t\tlastSlash = i + 1\n\t\t}\n\t}\n\tif pathbuf == nil {\n\t\treturn path\n\t}\n\n\tcopy(pathbuf[lastSlash:], path[lastSlash:])\n\treturn string(pathbuf)\n}\n\nfunc dirname(path string) string {\n\tvol := volumeName(path)\n\ti := len(path) - 1\n\tfor i >= len(vol) && !IsPathSeparator(path[i]) {\n\t\ti--\n\t}\n\tdir := path[len(vol) : i+1]\n\tlast := len(dir) - 1\n\tif last > 0 && IsPathSeparator(dir[last]) {\n\t\tdir = dir[:last]\n\t}\n\tif dir == \"\" {\n\t\tdir = \".\"\n\t}\n\treturn vol + dir\n}\n\n// This is set via go:linkname on runtime.canUseLongPaths, and is true when the OS\n// supports opting into proper long path handling without the need for fixups.\nvar canUseLongPaths bool\n\n// fixLongPath returns the extended-length (\\\\?\\-prefixed) form of\n// path when needed, in order to avoid the default 260 character file\n// path limit imposed by Windows. If path is not easily converted to\n// the extended-length form (for example, if path is a relative path\n// or contains .. elements), or is short enough, fixLongPath returns\n// path unmodified.\n//\n// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath\nfunc fixLongPath(path string) string {\n\tif canUseLongPaths {\n\t\treturn path\n\t}\n\t// Do nothing (and don't allocate) if the path is \"short\".\n\t// Empirically (at least on the Windows Server 2013 builder),\n\t// the kernel is arbitrarily okay with < 248 bytes. That\n\t// matches what the docs above say:\n\t// \"When using an API to create a directory, the specified\n\t// path cannot be so long that you cannot append an 8.3 file\n\t// name (that is, the directory name cannot exceed MAX_PATH\n\t// minus 12).\" Since MAX_PATH is 260, 260 - 12 = 248.\n\t//\n\t// The MSDN docs appear to say that a normal path that is 248 bytes long\n\t// will work; empirically the path must be less then 248 bytes long.\n\tif len(path) < 248 {\n\t\t// Don't fix. (This is how Go 1.7 and earlier worked,\n\t\t// not automatically generating the \\\\?\\ form)\n\t\treturn path\n\t}\n\n\t// The extended form begins with \\\\?\\, as in\n\t// \\\\?\\c:\\windows\\foo.txt or \\\\?\\UNC\\server\\share\\foo.txt.\n\t// The extended form disables evaluation of . and .. path\n\t// elements and disables the interpretation of / as equivalent\n\t// to \\. The conversion here rewrites / to \\ and elides\n\t// . elements as well as trailing or duplicate separators. For\n\t// simplicity it avoids the conversion entirely for relative\n\t// paths or paths containing .. elements. For now,\n\t// \\\\server\\share paths are not converted to\n\t// \\\\?\\UNC\\server\\share paths because the rules for doing so\n\t// are less well-specified.\n\tif len(path) >= 2 && path[:2] == `\\\\` {\n\t\t// Don't canonicalize UNC paths.\n\t\treturn path\n\t}\n\tif !isAbs(path) {\n\t\t// Relative path\n\t\treturn path\n\t}\n\n\tconst prefix = `\\\\?`\n\n\tpathbuf := make([]byte, len(prefix)+len(path)+len(`\\`))\n\tcopy(pathbuf, prefix)\n\tn := len(path)\n\tr, w := 0, len(prefix)\n\tfor r < n {\n\t\tswitch {\n\t\tcase IsPathSeparator(path[r]):\n\t\t\t// empty block\n\t\t\tr++\n\t\tcase path[r] == '.' && (r+1 == n || IsPathSeparator(path[r+1])):\n\t\t\t// /./\n\t\t\tr++\n\t\tcase r+1 < n && path[r] == '.' && path[r+1] == '.' && (r+2 == n || IsPathSeparator(path[r+2])):\n\t\t\t// /../ is currently unhandled\n\t\t\treturn path\n\t\tdefault:\n\t\t\tpathbuf[w] = '\\\\'\n\t\t\tw++\n\t\t\tfor ; r < n && !IsPathSeparator(path[r]); r++ {\n\t\t\t\tpathbuf[w] = path[r]\n\t\t\t\tw++\n\t\t\t}\n\t\t}\n\t}\n\t// A drive's root directory needs a trailing \\\n\tif w == len(`\\\\?\\c:`) {\n\t\tpathbuf[w] = '\\\\'\n\t\tw++\n\t}\n\treturn string(pathbuf[:w])\n}\n\n// fixRootDirectory fixes a reference to a drive's root directory to\n// have the required trailing slash.\nfunc fixRootDirectory(p string) string {\n\tif len(p) == len(`\\\\?\\c:`) {\n\t\tif IsPathSeparator(p[0]) && IsPathSeparator(p[1]) && p[2] == '?' && IsPathSeparator(p[3]) && p[5] == ':' {\n\t\t\treturn p + `\\`\n\t\t}\n\t}\n\treturn p\n}\n"
  },
  {
    "path": "src/os/path_windows_test.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os_test\n\nimport (\n\t\"os\"\n\t\"strings\"\n\t\"syscall\"\n\t\"testing\"\n)\n\nfunc TestFixLongPath(t *testing.T) {\n\tif os.CanUseLongPaths {\n\t\treturn\n\t}\n\t// 248 is long enough to trigger the longer-than-248 checks in\n\t// fixLongPath, but short enough not to make a path component\n\t// longer than 255, which is illegal on Windows. (which\n\t// doesn't really matter anyway, since this is purely a string\n\t// function we're testing, and it's not actually being used to\n\t// do a system call)\n\tveryLong := \"l\" + strings.Repeat(\"o\", 248) + \"ng\"\n\tfor _, test := range []struct{ in, want string }{\n\t\t// Short; unchanged:\n\t\t{`C:\\short.txt`, `C:\\short.txt`},\n\t\t{`C:\\`, `C:\\`},\n\t\t{`C:`, `C:`},\n\t\t// The \"long\" substring is replaced by a looooooong\n\t\t// string which triggers the rewriting. Except in the\n\t\t// cases below where it doesn't.\n\t\t{`C:\\long\\foo.txt`, `\\\\?\\C:\\long\\foo.txt`},\n\t\t{`C:/long/foo.txt`, `\\\\?\\C:\\long\\foo.txt`},\n\t\t{`C:\\long\\foo\\\\bar\\.\\baz\\\\`, `\\\\?\\C:\\long\\foo\\bar\\baz`},\n\t\t{`\\\\unc\\path`, `\\\\unc\\path`},\n\t\t{`long.txt`, `long.txt`},\n\t\t{`C:long.txt`, `C:long.txt`},\n\t\t{`c:\\long\\..\\bar\\baz`, `c:\\long\\..\\bar\\baz`},\n\t\t{`\\\\?\\c:\\long\\foo.txt`, `\\\\?\\c:\\long\\foo.txt`},\n\t\t{`\\\\?\\c:\\long/foo.txt`, `\\\\?\\c:\\long/foo.txt`},\n\t} {\n\t\tin := strings.ReplaceAll(test.in, \"long\", veryLong)\n\t\twant := strings.ReplaceAll(test.want, \"long\", veryLong)\n\t\tif got := os.FixLongPath(in); got != want {\n\t\t\tgot = strings.ReplaceAll(got, veryLong, \"long\")\n\t\t\tt.Errorf(\"fixLongPath(%q) = %q; want %q\", test.in, got, test.want)\n\t\t}\n\t}\n}\n\n// TODO: bring back upstream version's TestMkdirAllLongPath once os.RemoveAll and t.TempDir implemented\n\n// isWine returns true if executing on wine (Wine Is Not an Emulator), which\n// is compatible with windows but does not reproduce all its quirks.\nfunc isWine() bool {\n\treturn os.Getenv(\"WINECONFIGDIR\") != \"\"\n}\n\nfunc TestMkdirAllExtendedLength(t *testing.T) {\n\t// TODO: revert to upstream version once os.RemoveAll and t.TempDir implemented\n\ttmpDir := os.TempDir()\n\n\tconst prefix = `\\\\?\\`\n\tif len(tmpDir) < 4 || tmpDir[:4] != prefix {\n\t\tfullPath, err := syscall.FullPath(tmpDir)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"FullPath(%q) fails: %v\", tmpDir, err)\n\t\t}\n\t\ttmpDir = prefix + fullPath\n\t}\n\tpath := tmpDir + `\\dir\\`\n\tif err := os.MkdirAll(path, 0777); err != nil {\n\t\tt.Fatalf(\"MkdirAll(%q) failed: %v\", path, err)\n\t}\n\n\tif isWine() {\n\t\t// TODO: use t.Skip once implemented\n\t\tt.Log(\"wine: Skipping check for no-dots-for-you quirk in windows extended paths\")\n\t\treturn\n\t}\n\tpath = path + `.\\dir2`\n\tif err := os.MkdirAll(path, 0777); err == nil {\n\t\tt.Fatalf(\"MkdirAll(%q) should have failed, but did not\", path)\n\t}\n}\n"
  },
  {
    "path": "src/os/pipe_test.go",
    "content": "//go:build windows || darwin || (linux && !baremetal && !wasip1 && !wasip2)\n\n// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Test pipes on Unix and Windows systems.\n\npackage os_test\n\nimport (\n\t\"bytes\"\n\t\"os\"\n\t\"testing\"\n)\n\n// TestSmokePipe is a simple smoke test for Pipe().\nfunc TestSmokePipe(t *testing.T) {\n\t// Procedure:\n\t// 1. Get the bytes\n\t// 2. Light the bytes on fire\n\t// 3. Smoke the bytes\n\n\tr, w, err := os.Pipe()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t\treturn // TODO: remove once Fatal is fatal\n\t}\n\tdefer r.Close()\n\tdefer w.Close()\n\n\tmsg := []byte(\"Sed nvlla nisi ardva virtvs\")\n\tn, err := w.Write(msg)\n\tif err != nil {\n\t\tt.Errorf(\"Writing to fresh pipe failed, error %v\", err)\n\t}\n\twant := len(msg)\n\tif n != want {\n\t\tt.Errorf(\"Writing to fresh pipe wrote %d bytes, expected %d\", n, want)\n\t}\n\n\tbuf := make([]byte, 2*len(msg))\n\tn, err = r.Read(buf)\n\tif err != nil {\n\t\tt.Errorf(\"Reading from pipe failed, error %v\", err)\n\t}\n\tif n != want {\n\t\tt.Errorf(\"Reading from pipe got %d bytes, expected %d\", n, want)\n\t}\n\t// Read() does not set len(buf), so do it here.\n\tbuf = buf[:n]\n\tif !bytes.Equal(buf, msg) {\n\t\tt.Errorf(\"Reading from fresh pipe got wrong bytes\")\n\t}\n}\n"
  },
  {
    "path": "src/os/proc.go",
    "content": "// Package os implements a subset of the Go \"os\" package. See\n// https://godoc.org/os for details.\n//\n// Note that the current implementation is blocking. This limitation should be\n// removed in a future version.\npackage os\n\nimport (\n\t\"syscall\"\n)\n\n// Args hold the command-line arguments, starting with the program name.\nvar Args []string\n\nfunc init() {\n\tArgs = runtime_args()\n}\n\nfunc runtime_args() []string // in package runtime\n\n// Exit causes the current program to exit with the given status code.\n// Conventionally, code zero indicates success, non-zero an error.\n// The program terminates immediately; deferred functions are not run.\nfunc Exit(code int) {\n\tsyscall.Exit(code)\n}\n\n// Getuid returns the numeric user id of the caller.\n//\n// On non-POSIX systems, it returns -1.\nfunc Getuid() int {\n\treturn syscall.Getuid()\n}\n\n// Geteuid returns the numeric effective user id of the caller.\n//\n// On non-POSIX systems, it returns -1.\nfunc Geteuid() int {\n\treturn syscall.Geteuid()\n}\n\n// Getgid returns the numeric group id of the caller.\n//\n// On non-POSIX systems, it returns -1.\nfunc Getgid() int {\n\treturn syscall.Getgid()\n}\n\n// Getegid returns the numeric effective group id of the caller.\n//\n// On non-POSIX systems, it returns -1.\nfunc Getegid() int {\n\treturn syscall.Getegid()\n}\n"
  },
  {
    "path": "src/os/read_test.go",
    "content": "//go:build !baremetal && !js && !wasip1 && !wasip2\n\n// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os_test\n\nimport (\n\t\"bytes\"\n\t. \"os\"\n\t\"path/filepath\"\n\t\"testing\"\n)\n\nfunc checkNamedSize(t *testing.T, path string, size int64) {\n\t// TODO: this statement fails on wasi, possibly it objects to reading Stat on a symlink\n\tdir, err := Stat(path)\n\tif err != nil {\n\t\tt.Fatalf(\"Stat %q (looking for size %d): %s\", path, size, err)\n\t\treturn\n\t}\n\tif dir.Size() != size {\n\t\tt.Errorf(\"Stat %q: size %d want %d\", path, dir.Size(), size)\n\t}\n}\n\nfunc TestReadFile(t *testing.T) {\n\tfilename := \"rumpelstilzchen\"\n\tcontents, err := ReadFile(filename)\n\tif err == nil {\n\t\tt.Fatalf(\"ReadFile %s: error expected, none found\", filename)\n\t}\n\n\tfilename = \"read_test.go\"\n\tcontents, err = ReadFile(filename)\n\tif err != nil {\n\t\tt.Fatalf(\"ReadFile %s: %v\", filename, err)\n\t}\n\n\tcheckNamedSize(t, filename, int64(len(contents)))\n}\n\nfunc TestWriteFile(t *testing.T) {\n\tf, err := CreateTemp(\"\", \"ioutil-test\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer f.Close()\n\tdefer Remove(f.Name())\n\n\tmsg := \"Programming today is a race between software engineers striving to \" +\n\t\t\"build bigger and better idiot-proof programs, and the Universe trying \" +\n\t\t\"to produce bigger and better idiots. So far, the Universe is winning.\"\n\n\tif err := WriteFile(f.Name(), []byte(msg), 0644); err != nil {\n\t\tt.Fatalf(\"WriteFile %s: %v\", f.Name(), err)\n\t}\n\n\tdata, err := ReadFile(f.Name())\n\tif err != nil {\n\t\tt.Fatalf(\"ReadFile %s: %v\", f.Name(), err)\n\t}\n\n\tif string(data) != msg {\n\t\tt.Fatalf(\"ReadFile: wrong data:\\nhave %q\\nwant %q\", string(data), msg)\n\t}\n}\n\nfunc TestReadOnlyWriteFile(t *testing.T) {\n\t// TODO: also skip on wasi, where file permissions are ignored\n\tif Getuid() == 0 {\n\t\tt.Skipf(\"Root can write to read-only files anyway, so skip the read-only test.\")\n\t}\n\n\t// We don't want to use CreateTemp directly, since that opens a file for us as 0600.\n\ttempDir, err := MkdirTemp(\"\", t.Name())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer RemoveAll(tempDir)\n\tfilename := filepath.Join(tempDir, \"blurp.txt\")\n\n\tshmorp := []byte(\"shmorp\")\n\tflorp := []byte(\"florp\")\n\terr = WriteFile(filename, shmorp, 0444)\n\tif err != nil {\n\t\tt.Fatalf(\"WriteFile %s: %v\", filename, err)\n\t}\n\terr = WriteFile(filename, florp, 0444)\n\tif err == nil {\n\t\tt.Fatalf(\"Expected an error when writing to read-only file %s\", filename)\n\t}\n\tgot, err := ReadFile(filename)\n\tif err != nil {\n\t\tt.Fatalf(\"ReadFile %s: %v\", filename, err)\n\t}\n\tif !bytes.Equal(got, shmorp) {\n\t\tt.Fatalf(\"want %s, got %s\", shmorp, got)\n\t}\n}\n"
  },
  {
    "path": "src/os/removeall_noat.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build !baremetal && !js && !wasip1 && !wasip2 && !wasm_unknown && !nintendoswitch\n\npackage os\n\nimport (\n\t\"io\"\n\t\"runtime\"\n\t\"syscall\"\n)\n\nfunc removeAll(path string) error {\n\tif path == \"\" {\n\t\t// fail silently to retain compatibility with previous behavior\n\t\t// of RemoveAll. See issue 28830.\n\t\treturn nil\n\t}\n\n\t// The rmdir system call permits removing \".\" on Plan 9,\n\t// so we don't permit it to remain consistent with the\n\t// \"at\" implementation of RemoveAll.\n\tif endsWithDot(path) {\n\t\treturn &PathError{Op: \"RemoveAll\", Path: path, Err: syscall.EINVAL}\n\t}\n\n\t// Simple case: if Remove works, we're done.\n\terr := Remove(path)\n\tif err == nil || IsNotExist(err) {\n\t\treturn nil\n\t}\n\n\t// Otherwise, is this a directory we need to recurse into?\n\tdir, serr := Lstat(path)\n\tif serr != nil {\n\t\tif serr, ok := serr.(*PathError); ok && (IsNotExist(serr.Err) || serr.Err == syscall.ENOTDIR) {\n\t\t\treturn nil\n\t\t}\n\t\treturn serr\n\t}\n\tif !dir.IsDir() {\n\t\t// Not a directory; return the error from Remove.\n\t\treturn err\n\t}\n\n\t// Remove contents & return first error.\n\terr = nil\n\tfor {\n\t\tfd, err := Open(path)\n\t\tif err != nil {\n\t\t\tif IsNotExist(err) {\n\t\t\t\t// Already deleted by someone else.\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\treturn err\n\t\t}\n\n\t\tconst reqSize = 1024\n\t\tvar names []string\n\t\tvar readErr error\n\n\t\tfor {\n\t\t\tnumErr := 0\n\t\t\tnames, readErr = fd.Readdirnames(reqSize)\n\n\t\t\tfor _, name := range names {\n\t\t\t\terr1 := RemoveAll(path + string(PathSeparator) + name)\n\t\t\t\tif err == nil {\n\t\t\t\t\terr = err1\n\t\t\t\t}\n\t\t\t\tif err1 != nil {\n\t\t\t\t\tnumErr++\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If we can delete any entry, break to start new iteration.\n\t\t\t// Otherwise, we discard current names, get next entries and try deleting them.\n\t\t\tif numErr != reqSize {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\t// Removing files from the directory may have caused\n\t\t// the OS to reshuffle it. Simply calling Readdirnames\n\t\t// again may skip some entries. The only reliable way\n\t\t// to avoid this is to close and re-open the\n\t\t// directory. See issue 20841.\n\t\tfd.Close()\n\n\t\tif readErr == io.EOF {\n\t\t\tbreak\n\t\t}\n\t\t// If Readdirnames returned an error, use it.\n\t\tif err == nil {\n\t\t\terr = readErr\n\t\t}\n\t\tif len(names) == 0 {\n\t\t\tbreak\n\t\t}\n\n\t\t// We don't want to re-open unnecessarily, so if we\n\t\t// got fewer than request names from Readdirnames, try\n\t\t// simply removing the directory now. If that\n\t\t// succeeds, we are done.\n\t\tif len(names) < reqSize {\n\t\t\terr1 := Remove(path)\n\t\t\tif err1 == nil || IsNotExist(err1) {\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\tif err != nil {\n\t\t\t\t// We got some error removing the\n\t\t\t\t// directory contents, and since we\n\t\t\t\t// read fewer names than we requested\n\t\t\t\t// there probably aren't more files to\n\t\t\t\t// remove. Don't loop around to read\n\t\t\t\t// the directory again. We'll probably\n\t\t\t\t// just get the same error.\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\n\t// Remove directory.\n\terr1 := Remove(path)\n\tif err1 == nil || IsNotExist(err1) {\n\t\treturn nil\n\t}\n\tif runtime.GOOS == \"windows\" && IsPermission(err1) {\n\t\tif fs, err := Stat(path); err == nil {\n\t\t\tif err = Chmod(path, FileMode(0200|int(fs.Mode()))); err == nil {\n\t\t\t\terr1 = Remove(path)\n\t\t\t}\n\t\t}\n\t}\n\tif err == nil {\n\t\terr = err1\n\t}\n\treturn err\n}\n"
  },
  {
    "path": "src/os/removeall_other.go",
    "content": "//go:build baremetal || js || wasip1 || wasip2 || wasm_unknown || nintendoswitch\n\n// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os\n\nimport (\n\t\"syscall\"\n)\n\nfunc removeAll(path string) error {\n\treturn &PathError{Op: \"RemoveAll\", Path: path, Err: syscall.ENOSYS}\n}\n"
  },
  {
    "path": "src/os/removeall_test.go",
    "content": "//go:build darwin || (linux && !baremetal && !js && !wasip1 && !wasip2)\n\n// TODO: implement ReadDir on windows\n\n// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os_test\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t. \"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"testing\"\n)\n\nfunc TestRemoveAll(t *testing.T) {\n\ttmpDir, _ := os.MkdirTemp(\"\", \"TestRemoveAll\")\n\tif err := RemoveAll(\"\"); err != nil {\n\t\tt.Errorf(\"RemoveAll(\\\"\\\"): %v; want nil\", err)\n\t}\n\n\tfile := filepath.Join(tmpDir, \"file\")\n\tpath := filepath.Join(tmpDir, \"_TestRemoveAll_\")\n\tfpath := filepath.Join(path, \"file\")\n\tdpath := filepath.Join(path, \"dir\")\n\n\t// Make a regular file and remove\n\tfd, err := Create(file)\n\tif err != nil {\n\t\tt.Fatalf(\"create %q: %s\", file, err)\n\t}\n\tfd.Close()\n\tif err = RemoveAll(file); err != nil {\n\t\tt.Fatalf(\"RemoveAll %q (first): %s\", file, err)\n\t}\n\tif _, err = Lstat(file); err == nil {\n\t\tt.Fatalf(\"Lstat %q succeeded after RemoveAll (first)\", file)\n\t}\n\n\t// Make directory with 1 file and remove.\n\tif err := MkdirAll(path, 0777); err != nil {\n\t\tt.Fatalf(\"MkdirAll %q: %s\", path, err)\n\t}\n\tfd, err = Create(fpath)\n\tif err != nil {\n\t\tt.Fatalf(\"create %q: %s\", fpath, err)\n\t}\n\tfd.Close()\n\tif err = RemoveAll(path); err != nil {\n\t\tt.Fatalf(\"RemoveAll %q (second): %s\", path, err)\n\t}\n\tif _, err = Lstat(path); err == nil {\n\t\tt.Fatalf(\"Lstat %q succeeded after RemoveAll (second)\", path)\n\t}\n\n\t// Make directory with file and subdirectory and remove.\n\tif err = MkdirAll(dpath, 0777); err != nil {\n\t\tt.Fatalf(\"MkdirAll %q: %s\", dpath, err)\n\t}\n\tfd, err = Create(fpath)\n\tif err != nil {\n\t\tt.Fatalf(\"create %q: %s\", fpath, err)\n\t}\n\tfd.Close()\n\tfd, err = Create(dpath + \"/file\")\n\tif err != nil {\n\t\tt.Fatalf(\"create %q: %s\", fpath, err)\n\t}\n\tfd.Close()\n\tif err = RemoveAll(path); err != nil {\n\t\tt.Fatalf(\"RemoveAll %q (third): %s\", path, err)\n\t}\n\tif _, err := Lstat(path); err == nil {\n\t\tt.Fatalf(\"Lstat %q succeeded after RemoveAll (third)\", path)\n\t}\n\n\t// Chmod is not supported under Windows and test fails as root.\n\tif runtime.GOOS != \"windows\" && Getuid() != 0 {\n\t\t// Make directory with file and subdirectory and trigger error.\n\t\tif err = MkdirAll(dpath, 0777); err != nil {\n\t\t\tt.Fatalf(\"MkdirAll %q: %s\", dpath, err)\n\t\t}\n\n\t\tfor _, s := range []string{fpath, dpath + \"/file1\", path + \"/zzz\"} {\n\t\t\tfd, err = Create(s)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"create %q: %s\", s, err)\n\t\t\t}\n\t\t\tfd.Close()\n\t\t}\n\t\tif err = Chmod(dpath, 0); err != nil {\n\t\t\tt.Fatalf(\"Chmod %q 0: %s\", dpath, err)\n\t\t}\n\n\t\t// No error checking here: either RemoveAll\n\t\t// will or won't be able to remove dpath;\n\t\t// either way we want to see if it removes fpath\n\t\t// and path/zzz. Reasons why RemoveAll might\n\t\t// succeed in removing dpath as well include:\n\t\t//\t* running as root\n\t\t//\t* running on a file system without permissions (FAT)\n\t\tRemoveAll(path)\n\t\tChmod(dpath, 0777)\n\n\t\tfor _, s := range []string{fpath, path + \"/zzz\"} {\n\t\t\tif _, err = Lstat(s); err == nil {\n\t\t\t\tt.Fatalf(\"Lstat %q succeeded after partial RemoveAll\", s)\n\t\t\t}\n\t\t}\n\t}\n\tif err = RemoveAll(path); err != nil {\n\t\tt.Fatalf(\"RemoveAll %q after partial RemoveAll: %s\", path, err)\n\t}\n\tif _, err = Lstat(path); err == nil {\n\t\tt.Fatalf(\"Lstat %q succeeded after RemoveAll (final)\", path)\n\t}\n}\n\n// Test RemoveAll on a large directory.\nfunc TestRemoveAllLarge(t *testing.T) {\n\tif testing.Short() {\n\t\tt.Skip(\"skipping in short mode\")\n\t}\n\n\ttmpDir, _ := os.MkdirTemp(\"\", \"TestRemoveAllLarge\")\n\tpath := filepath.Join(tmpDir, \"_TestRemoveAllLarge_\")\n\n\t// Make directory with 1000 files and remove.\n\tif err := MkdirAll(path, 0777); err != nil {\n\t\tt.Fatalf(\"MkdirAll %q: %s\", path, err)\n\t}\n\tfor i := 0; i < 1000; i++ {\n\t\tfpath := fmt.Sprintf(\"%s/file%d\", path, i)\n\t\tfd, err := Create(fpath)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"create %q: %s\", fpath, err)\n\t\t}\n\t\tfd.Close()\n\t}\n\tif err := RemoveAll(path); err != nil {\n\t\tt.Fatalf(\"RemoveAll %q: %s\", path, err)\n\t}\n\tif _, err := Lstat(path); err == nil {\n\t\tt.Fatalf(\"Lstat %q succeeded after RemoveAll\", path)\n\t}\n}\n\nfunc TestRemoveAllDot(t *testing.T) {\n\tprevDir, err := Getwd()\n\tif err != nil {\n\t\tt.Fatalf(\"Could not get wd: %s\", err)\n\t}\n\ttempDir, err := os.MkdirTemp(\"\", \"TestRemoveAllDot-\")\n\tif err != nil {\n\t\tt.Fatalf(\"Could not create TempDir: %s\", err)\n\t}\n\tdefer RemoveAll(tempDir)\n\n\terr = Chdir(tempDir)\n\tif err != nil {\n\t\tt.Fatalf(\"Could not chdir to tempdir: %s\", err)\n\t}\n\n\terr = RemoveAll(\".\")\n\tif err == nil {\n\t\tt.Errorf(\"RemoveAll succeed to remove .\")\n\t}\n\n\terr = Chdir(prevDir)\n\tif err != nil {\n\t\tt.Fatalf(\"Could not chdir %s: %s\", prevDir, err)\n\t}\n}\n\nfunc TestRemoveAllDotDot(t *testing.T) {\n\tt.Parallel()\n\n\ttempDir, _ := os.MkdirTemp(\"\", \"TestRemoveAllDotDot\")\n\tsubdir := filepath.Join(tempDir, \"x\")\n\tsubsubdir := filepath.Join(subdir, \"y\")\n\tif err := MkdirAll(subsubdir, 0777); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif err := RemoveAll(filepath.Join(subsubdir, \"..\")); err != nil {\n\t\tt.Error(err)\n\t}\n\tfor _, dir := range []string{subsubdir, subdir} {\n\t\tif _, err := Stat(dir); err == nil {\n\t\t\tt.Errorf(\"%s: exists after RemoveAll\", dir)\n\t\t}\n\t}\n}\n\n// Issue #29178.\nfunc TestRemoveReadOnlyDir(t *testing.T) {\n\tt.Parallel()\n\n\ttempDir, _ := os.MkdirTemp(\"\", \"TestRemoveReadOnlyDir\")\n\tsubdir := filepath.Join(tempDir, \"x\")\n\tif err := Mkdir(subdir, 0); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// If an error occurs make it more likely that removing the\n\t// temporary directory will succeed.\n\tdefer Chmod(subdir, 0777)\n\n\tif err := RemoveAll(subdir); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif _, err := Stat(subdir); err == nil {\n\t\tt.Error(\"subdirectory was not removed\")\n\t}\n}\n\n// Issue #29983.\nfunc TestRemoveAllButReadOnlyAndPathError(t *testing.T) {\n\tswitch runtime.GOOS {\n\tcase \"js\", \"windows\":\n\t\tt.Skipf(\"skipping test on %s\", runtime.GOOS)\n\t}\n\n\tif Getuid() == 0 {\n\t\tt.Skip(\"skipping test when running as root\")\n\t}\n\n\tt.Parallel()\n\n\ttempDir, _ := os.MkdirTemp(\"\", \"TestRemoveAllButReadOnlyAndPathError\")\n\tdirs := []string{\n\t\t\"a\",\n\t\t\"a/x\",\n\t\t\"a/x/1\",\n\t\t\"b\",\n\t\t\"b/y\",\n\t\t\"b/y/2\",\n\t\t\"c\",\n\t\t\"c/z\",\n\t\t\"c/z/3\",\n\t}\n\treadonly := []string{\n\t\t\"b\",\n\t}\n\tinReadonly := func(d string) bool {\n\t\tfor _, ro := range readonly {\n\t\t\tif d == ro {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tdd, _ := filepath.Split(d)\n\t\t\tif filepath.Clean(dd) == ro {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\n\tfor _, dir := range dirs {\n\t\tif err := Mkdir(filepath.Join(tempDir, dir), 0777); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\tfor _, dir := range readonly {\n\t\td := filepath.Join(tempDir, dir)\n\t\tif err := Chmod(d, 0555); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\t// Defer changing the mode back so that the deferred\n\t\t// RemoveAll(tempDir) can succeed.\n\t\tdefer Chmod(d, 0777)\n\t}\n\n\terr := RemoveAll(tempDir)\n\tif err == nil {\n\t\tt.Fatal(\"RemoveAll succeeded unexpectedly\")\n\t}\n\n\t// The error should be of type *PathError.\n\t// see issue 30491 for details.\n\tif pathErr, ok := err.(*PathError); ok {\n\t\twant := filepath.Join(tempDir, \"b\", \"y\")\n\t\tif pathErr.Path != want {\n\t\t\tt.Errorf(\"RemoveAll(%q): err.Path=%q, want %q\", tempDir, pathErr.Path, want)\n\t\t}\n\t} else {\n\t\tt.Errorf(\"RemoveAll(%q): error has type %T, want *fs.PathError\", tempDir, err)\n\t}\n\n\tfor _, dir := range dirs {\n\t\t_, err := Stat(filepath.Join(tempDir, dir))\n\t\tif inReadonly(dir) {\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"file %q was deleted but should still exist\", dir)\n\t\t\t}\n\t\t} else {\n\t\t\tif err == nil {\n\t\t\t\tt.Errorf(\"file %q still exists but should have been deleted\", dir)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestRemoveUnreadableDir(t *testing.T) {\n\tswitch runtime.GOOS {\n\tcase \"js\":\n\t\tt.Skipf(\"skipping test on %s\", runtime.GOOS)\n\t}\n\n\tif Getuid() == 0 {\n\t\tt.Skip(\"skipping test when running as root\")\n\t}\n\n\tt.Parallel()\n\n\ttempDir, _ := os.MkdirTemp(\"\", \"TestRemoveUnreadableDir\")\n\ttarget := filepath.Join(tempDir, \"d0\", \"d1\", \"d2\")\n\tif err := MkdirAll(target, 0755); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif err := Chmod(target, 0300); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif err := RemoveAll(filepath.Join(tempDir, \"d0\")); err != nil {\n\t\tt.Fatal(err)\n\t}\n}\n\n// Issue 29921\nfunc TestRemoveAllWithMoreErrorThanReqSize(t *testing.T) {\n\tif testing.Short() {\n\t\tt.Skip(\"skipping in short mode\")\n\t}\n\n\ttmpDir, _ := os.MkdirTemp(\"\", \"TestRemoveAllWithMoreErrorThanReqSize\")\n\tpath := filepath.Join(tmpDir, \"_TestRemoveAllWithMoreErrorThanReqSize_\")\n\n\t// Make directory with 1025 read-only files.\n\tif err := MkdirAll(path, 0777); err != nil {\n\t\tt.Fatalf(\"MkdirAll %q: %s\", path, err)\n\t}\n\tfor i := 0; i < 1025; i++ {\n\t\tfpath := filepath.Join(path, fmt.Sprintf(\"file%d\", i))\n\t\tfd, err := Create(fpath)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"create %q: %s\", fpath, err)\n\t\t}\n\t\tfd.Close()\n\t}\n\n\t// Make the parent directory read-only. On some platforms, this is what\n\t// prevents os.Remove from removing the files within that directory.\n\tif err := Chmod(path, 0555); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer Chmod(path, 0755)\n\n\t// This call should not hang, even on a platform that disallows file deletion\n\t// from read-only directories.\n\terr := RemoveAll(path)\n\n\tif Getuid() == 0 {\n\t\t// On many platforms, root can remove files from read-only directories.\n\t\treturn\n\t}\n\tif err == nil {\n\t\tif runtime.GOOS == \"windows\" {\n\t\t\t// Marking a directory as read-only in Windows does not prevent the RemoveAll\n\t\t\t// from creating or removing files within it.\n\t\t\treturn\n\t\t}\n\t\tt.Fatal(\"RemoveAll(<read-only directory>) = nil; want error\")\n\t}\n\n\tdir, err := Open(path)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer dir.Close()\n\n\tnames, _ := dir.Readdirnames(1025)\n\tif len(names) < 1025 {\n\t\tt.Fatalf(\"RemoveAll(<read-only directory>) unexpectedly removed %d read-only files from that directory\", 1025-len(names))\n\t}\n}\n"
  },
  {
    "path": "src/os/seek_unix_bad.go",
    "content": "//go:build (linux && !baremetal && 386) || (linux && !baremetal && arm && !wasip1 && !wasip2)\n\npackage os\n\nimport (\n\t\"syscall\"\n)\n\n// On linux, we use upstream's syscall package.\n// But we do not yet implement Go Assembly, so we don't see a few functions written in assembly there.\n// In particular, on i386 and arm, the function syscall.seek is missing, breaking syscall.Seek.\n// This in turn causes os.(*File).Seek, time, io/fs, and path/filepath to fail to link.\n//\n// To temporarily let all the above at least link, provide a stub for syscall.seek.\n// This belongs in syscall, but on linux, we use upstream's syscall.\n// Remove once we support Go Assembly.\n// TODO: make this a non-stub, and thus fix the whole problem?\n\n//export syscall.seek\nfunc seek(fd int, offset int64, whence int) (newoffset int64, err syscall.Errno) {\n\treturn 0, syscall.ENOTSUP\n}\n"
  },
  {
    "path": "src/os/stat.go",
    "content": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os\n\n// Stat returns a FileInfo describing the named file.\n// If there is an error, it will be of type *PathError.\nfunc Stat(name string) (FileInfo, error) {\n\treturn statNolog(name)\n}\n\n// Lstat returns a FileInfo describing the named file.\n// If the file is a symbolic link, the returned FileInfo\n// describes the symbolic link. Lstat makes no attempt to follow the link.\n// If there is an error, it will be of type *PathError.\nfunc Lstat(name string) (FileInfo, error) {\n\treturn lstatNolog(name)\n}\n"
  },
  {
    "path": "src/os/stat_darwin.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os\n\nimport (\n\t\"syscall\"\n\t\"time\"\n)\n\nfunc fillFileStatFromSys(fs *fileStat, name string) {\n\tfs.name = basename(name)\n\tfs.size = fs.sys.Size\n\tfs.modTime = timespecToTime(fs.sys.Mtimespec)\n\tfs.mode = FileMode(fs.sys.Mode & 0777)\n\tswitch fs.sys.Mode & syscall.S_IFMT {\n\tcase syscall.S_IFBLK, syscall.S_IFWHT:\n\t\tfs.mode |= ModeDevice\n\tcase syscall.S_IFCHR:\n\t\tfs.mode |= ModeDevice | ModeCharDevice\n\tcase syscall.S_IFDIR:\n\t\tfs.mode |= ModeDir\n\tcase syscall.S_IFIFO:\n\t\tfs.mode |= ModeNamedPipe\n\tcase syscall.S_IFLNK:\n\t\tfs.mode |= ModeSymlink\n\tcase syscall.S_IFREG:\n\t\t// nothing to do\n\tcase syscall.S_IFSOCK:\n\t\tfs.mode |= ModeSocket\n\t}\n\tif fs.sys.Mode&syscall.S_ISGID != 0 {\n\t\tfs.mode |= ModeSetgid\n\t}\n\tif fs.sys.Mode&syscall.S_ISUID != 0 {\n\t\tfs.mode |= ModeSetuid\n\t}\n\tif fs.sys.Mode&syscall.S_ISVTX != 0 {\n\t\tfs.mode |= ModeSticky\n\t}\n}\n\nfunc timespecToTime(ts syscall.Timespec) time.Time {\n\treturn time.Unix(int64(ts.Sec), int64(ts.Nsec))\n}\n\n// For testing.\nfunc atime(fi FileInfo) time.Time {\n\treturn timespecToTime(fi.Sys().(*syscall.Stat_t).Atimespec)\n}\n"
  },
  {
    "path": "src/os/stat_linuxlike.go",
    "content": "//go:build (linux && !baremetal && !wasm_unknown && !nintendoswitch) || wasip1 || wasip2\n\n// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Note: this file is used for both Linux and WASI.\n// Eventually it might be better to spit it up, and make the syscall constants\n// match the typical WASI constants instead of the Linux-equivalents used here.\n\npackage os\n\nimport (\n\t\"syscall\"\n\t\"time\"\n)\n\nfunc fillFileStatFromSys(fs *fileStat, name string) {\n\tfs.name = basename(name)\n\tfs.size = fs.sys.Size\n\tfs.modTime = timespecToTime(fs.sys.Mtim)\n\tfs.mode = FileMode(fs.sys.Mode & 0777)\n\tswitch fs.sys.Mode & syscall.S_IFMT {\n\tcase syscall.S_IFBLK:\n\t\tfs.mode |= ModeDevice\n\tcase syscall.S_IFCHR:\n\t\tfs.mode |= ModeDevice | ModeCharDevice\n\tcase syscall.S_IFDIR:\n\t\tfs.mode |= ModeDir\n\tcase syscall.S_IFIFO:\n\t\tfs.mode |= ModeNamedPipe\n\tcase syscall.S_IFLNK:\n\t\tfs.mode |= ModeSymlink\n\tcase syscall.S_IFREG:\n\t\t// nothing to do\n\tcase syscall.S_IFSOCK:\n\t\tfs.mode |= ModeSocket\n\t}\n\tif fs.sys.Mode&syscall.S_ISGID != 0 {\n\t\tfs.mode |= ModeSetgid\n\t}\n\tif fs.sys.Mode&syscall.S_ISUID != 0 {\n\t\tfs.mode |= ModeSetuid\n\t}\n\tif fs.sys.Mode&syscall.S_ISVTX != 0 {\n\t\tfs.mode |= ModeSticky\n\t}\n}\n\nfunc timespecToTime(ts syscall.Timespec) time.Time {\n\treturn time.Unix(int64(ts.Sec), int64(ts.Nsec))\n}\n\n// For testing.\nfunc atime(fi FileInfo) time.Time {\n\treturn timespecToTime(fi.Sys().(*syscall.Stat_t).Atim)\n}\n"
  },
  {
    "path": "src/os/stat_other.go",
    "content": "//go:build baremetal || (tinygo.wasm && !wasip1 && !wasip2) || nintendoswitch\n\n// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os\n\n// Stat is a stub, not yet implemented\nfunc (f *File) Stat() (FileInfo, error) {\n\treturn nil, ErrNotImplemented\n}\n\n// statNolog stats a file with no test logging.\nfunc statNolog(name string) (FileInfo, error) {\n\treturn nil, &PathError{Op: \"stat\", Path: name, Err: ErrNotImplemented}\n}\n\n// lstatNolog lstats a file with no test logging.\nfunc lstatNolog(name string) (FileInfo, error) {\n\treturn nil, &PathError{Op: \"lstat\", Path: name, Err: ErrNotImplemented}\n}\n"
  },
  {
    "path": "src/os/stat_test.go",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os_test\n\nimport (\n\t\"io/fs\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n)\n\n// testStatAndLstat verifies that all os.Stat, os.Lstat os.File.Stat and os.Readdir work.\nfunc testStatAndLstat(t *testing.T, path string, isLink bool, statCheck, lstatCheck func(*testing.T, string, fs.FileInfo)) {\n\t// TODO: revert to upstream test once fstat and readdir are implemented\n\t// test os.Stat\n\tsfi, err := os.Stat(path)\n\tif err != nil {\n\t\tt.Error(err)\n\t\treturn\n\t}\n\tstatCheck(t, path, sfi)\n\n\t// test os.Lstat\n\tlsfi, err := os.Lstat(path)\n\tif err != nil {\n\t\tt.Error(err)\n\t\treturn\n\t}\n\tlstatCheck(t, path, lsfi)\n\n\tif isLink {\n\t\tif os.SameFile(sfi, lsfi) {\n\t\t\tt.Errorf(\"stat and lstat of %q should not be the same\", path)\n\t\t}\n\t} else {\n\t\tif !os.SameFile(sfi, lsfi) {\n\t\t\tt.Errorf(\"stat and lstat of %q should be the same\", path)\n\t\t}\n\t}\n}\n\n// testIsDir verifies that fi refers to directory.\nfunc testIsDir(t *testing.T, path string, fi fs.FileInfo) {\n\tt.Helper()\n\tif !fi.IsDir() {\n\t\tt.Errorf(\"%q should be a directory\", path)\n\t}\n\tif fi.Mode()&fs.ModeSymlink != 0 {\n\t\tt.Errorf(\"%q should not be a symlink\", path)\n\t}\n}\n\n// testIsFile verifies that fi refers to file.\nfunc testIsFile(t *testing.T, path string, fi fs.FileInfo) {\n\tt.Helper()\n\tif fi.IsDir() {\n\t\tt.Errorf(\"%q should not be a directory\", path)\n\t}\n\tif fi.Mode()&fs.ModeSymlink != 0 {\n\t\tt.Errorf(\"%q should not be a symlink\", path)\n\t}\n}\n\nfunc testDirStats(t *testing.T, path string) {\n\ttestStatAndLstat(t, path, false, testIsDir, testIsDir)\n}\n\nfunc testFileStats(t *testing.T, path string) {\n\ttestStatAndLstat(t, path, false, testIsFile, testIsFile)\n}\n\nfunc TestDirAndSymlinkStats(t *testing.T) {\n\t// TODO: revert to upstream test once symlinks and t.TempDir are implemented\n\ttmpdir := os.TempDir()\n\tdir := filepath.Join(tmpdir, \"dir\")\n\tos.Remove(dir)\n\tif err := os.Mkdir(dir, 0777); err != nil {\n\t\tt.Fatal(err)\n\t\treturn\n\t}\n\ttestDirStats(t, dir)\n\n}\n\nfunc TestFileAndSymlinkStats(t *testing.T) {\n\t// TODO: revert to upstream test once symlinks and t.TempDir are implemented\n\ttmpdir := os.TempDir()\n\tfile := filepath.Join(tmpdir, \"file\")\n\tif err := os.WriteFile(file, []byte(\"abcdefg\"), 0644); err != nil {\n\t\tt.Fatal(err)\n\t\treturn\n\t}\n\ttestFileStats(t, file)\n}\n"
  },
  {
    "path": "src/os/stat_unix.go",
    "content": "//go:build darwin || (linux && !baremetal && !wasm_unknown && !nintendoswitch) || wasip1 || wasip2\n\n// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os\n\nimport (\n\t\"syscall\"\n)\n\n// Stat returns the FileInfo structure describing file.\n// If there is an error, it will be of type *PathError.\nfunc (f *File) Stat() (FileInfo, error) {\n\tvar fs fileStat\n\terr := ignoringEINTR(func() error {\n\t\treturn syscall.Fstat(int(f.handle.(unixFileHandle)), &fs.sys)\n\t})\n\tif err != nil {\n\t\treturn nil, &PathError{Op: \"fstat\", Path: f.name, Err: err}\n\t}\n\tfillFileStatFromSys(&fs, f.name)\n\treturn &fs, nil\n}\n\n// statNolog stats a file with no test logging.\nfunc statNolog(name string) (FileInfo, error) {\n\tvar fs fileStat\n\terr := ignoringEINTR(func() error {\n\t\treturn handleSyscallError(syscall.Stat(name, &fs.sys))\n\t})\n\tif err != nil {\n\t\treturn nil, &PathError{Op: \"stat\", Path: name, Err: err}\n\t}\n\tfillFileStatFromSys(&fs, name)\n\treturn &fs, nil\n}\n\n// lstatNolog lstats a file with no test logging.\nfunc lstatNolog(name string) (FileInfo, error) {\n\tvar fs fileStat\n\terr := ignoringEINTR(func() error {\n\t\treturn handleSyscallError(syscall.Lstat(name, &fs.sys))\n\t})\n\tif err != nil {\n\t\treturn nil, &PathError{Op: \"lstat\", Path: name, Err: err}\n\t}\n\tfillFileStatFromSys(&fs, name)\n\treturn &fs, nil\n}\n"
  },
  {
    "path": "src/os/stat_windows.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os\n\nimport (\n\t\"internal/syscall/windows\"\n\t\"syscall\"\n\t\"unsafe\"\n)\n\n// Stat returns the FileInfo structure describing file.\n// If there is an error, it will be of type *PathError.\nfunc (file *File) Stat() (FileInfo, error) {\n\tif file == nil {\n\t\treturn nil, ErrInvalid\n\t}\n\n\tif isWindowsNulName(file.name) {\n\t\treturn &devNullStat, nil\n\t}\n\n\tft, err := syscall.GetFileType(syscallFd(file.handle.(unixFileHandle)))\n\tif err != nil {\n\t\treturn nil, &PathError{Op: \"GetFileType\", Path: file.name, Err: err}\n\t}\n\tswitch ft {\n\tcase syscall.FILE_TYPE_PIPE, syscall.FILE_TYPE_CHAR:\n\t\treturn &fileStat{name: basename(file.name), filetype: ft}, nil\n\t}\n\n\tfs, err := newFileStatFromGetFileInformationByHandle(file.name, syscallFd(file.handle.(unixFileHandle)))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tfs.filetype = ft\n\treturn fs, err\n}\n\n// stat implements both Stat and Lstat of a file.\nfunc stat(funcname, name string, createFileAttrs uint32) (FileInfo, error) {\n\tif len(name) == 0 {\n\t\treturn nil, &PathError{Op: funcname, Path: name, Err: syscall.Errno(syscall.ERROR_PATH_NOT_FOUND)}\n\t}\n\tif isWindowsNulName(name) {\n\t\treturn &devNullStat, nil\n\t}\n\tnamep, err := syscall.UTF16PtrFromString(fixLongPath(name))\n\tif err != nil {\n\t\treturn nil, &PathError{Op: funcname, Path: name, Err: err}\n\t}\n\n\t// Try GetFileAttributesEx first, because it is faster than CreateFile.\n\t// See https://golang.org/issues/19922#issuecomment-300031421 for details.\n\tvar fa syscall.Win32FileAttributeData\n\terr = syscall.GetFileAttributesEx(namep, syscall.GetFileExInfoStandard, (*byte)(unsafe.Pointer(&fa)))\n\tif err == nil && fa.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 {\n\t\t// Not a symlink.\n\t\tfs := &fileStat{\n\t\t\tFileAttributes: fa.FileAttributes,\n\t\t\tCreationTime:   fa.CreationTime,\n\t\t\tLastAccessTime: fa.LastAccessTime,\n\t\t\tLastWriteTime:  fa.LastWriteTime,\n\t\t\tFileSizeHigh:   fa.FileSizeHigh,\n\t\t\tFileSizeLow:    fa.FileSizeLow,\n\t\t}\n\t\tif err := fs.saveInfoFromPath(name); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn fs, nil\n\t}\n\t// GetFileAttributesEx fails with ERROR_SHARING_VIOLATION error for\n\t// files, like c:\\pagefile.sys. Use FindFirstFile for such files.\n\tif err == windows.ERROR_SHARING_VIOLATION {\n\t\tvar fd syscall.Win32finddata\n\t\tsh, err := syscall.FindFirstFile(namep, &fd)\n\t\tif err != nil {\n\t\t\treturn nil, &PathError{Op: \"FindFirstFile\", Path: name, Err: err}\n\t\t}\n\t\tsyscall.FindClose(sh)\n\t\tfs := newFileStatFromWin32finddata(&fd)\n\t\tif err := fs.saveInfoFromPath(name); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn fs, nil\n\t}\n\n\t// Finally use CreateFile.\n\th, err := syscall.CreateFile(namep, 0, 0, nil,\n\t\tsyscall.OPEN_EXISTING, createFileAttrs, 0)\n\tif err != nil {\n\t\treturn nil, &PathError{Op: \"CreateFile\", Path: name, Err: err}\n\t}\n\tdefer syscall.CloseHandle(h)\n\n\treturn newFileStatFromGetFileInformationByHandle(name, h)\n}\n\n// statNolog implements Stat for Windows.\nfunc statNolog(name string) (FileInfo, error) {\n\treturn stat(\"Stat\", name, syscall.FILE_FLAG_BACKUP_SEMANTICS)\n}\n\n// lstatNolog implements Lstat for Windows.\nfunc lstatNolog(name string) (FileInfo, error) {\n\tattrs := uint32(syscall.FILE_FLAG_BACKUP_SEMANTICS)\n\t// Use FILE_FLAG_OPEN_REPARSE_POINT, otherwise CreateFile will follow symlink.\n\t// See https://docs.microsoft.com/en-us/windows/desktop/FileIO/symbolic-link-effects-on-file-systems-functions#createfile-and-createfiletransacted\n\tattrs |= syscall.FILE_FLAG_OPEN_REPARSE_POINT\n\treturn stat(\"Lstat\", name, attrs)\n}\n"
  },
  {
    "path": "src/os/sys.go",
    "content": "package os\n\nfunc Hostname() (name string, err error) {\n\treturn \"\", ErrNotImplemented\n}\n"
  },
  {
    "path": "src/os/tempfile.go",
    "content": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os\n\nimport (\n\t\"errors\"\n\t\"internal/itoa\"\n\t\"sync\"\n\t\"time\"\n)\n\nvar minrandPreviousValue uint32\nvar minrandMutex sync.Mutex\n\nfunc init() {\n\t// Avoid getting same results on every run\n\tnow := time.Now()\n\tseed := uint32(Getpid()) ^ uint32(now.Nanosecond()) ^ uint32(now.Unix())\n\t// initial state must be odd\n\tminrandPreviousValue = seed | 1\n}\n\n// minrand() is a simple and rather poor placeholder for fastrand()\n// TODO: provide fastrand in runtime, as go does.  It is hard to implement properly elsewhere.\nfunc minrand() uint32 {\n\t// c++11's minstd_rand\n\t// https://en.wikipedia.org/wiki/Linear_congruential_generator\n\t// m=2^32, c=0, a=48271\n\tminrandMutex.Lock()\n\tminrandPreviousValue *= 48271\n\tval := minrandPreviousValue\n\tminrandMutex.Unlock()\n\treturn val\n}\n\n// We generate random temporary file names so that there's a good\n// chance the file doesn't exist yet - keeps the number of tries in\n// TempFile to a minimum.\nfunc nextRandom() string {\n\t// Discard lower four bits of minrand.\n\t// They're not very random, and we don't need the full range here.\n\treturn itoa.Uitoa(uint(minrand() >> 4))\n}\n\n// CreateTemp creates a new temporary file in the directory dir,\n// opens the file for reading and writing, and returns the resulting file.\n// The filename is generated by taking pattern and adding a random string to the end.\n// If pattern includes a \"*\", the random string replaces the last \"*\".\n// If dir is the empty string, CreateTemp uses the default directory for temporary files, as returned by TempDir.\n// Multiple programs or goroutines calling CreateTemp simultaneously will not choose the same file.\n// The caller can use the file's Name method to find the pathname of the file.\n// It is the caller's responsibility to remove the file when it is no longer needed.\nfunc CreateTemp(dir, pattern string) (*File, error) {\n\tif dir == \"\" {\n\t\tdir = TempDir()\n\t}\n\n\tprefix, suffix, err := prefixAndSuffix(pattern)\n\tif err != nil {\n\t\treturn nil, &PathError{Op: \"createtemp\", Path: pattern, Err: err}\n\t}\n\tprefix = joinPath(dir, prefix)\n\n\ttry := 0\n\tfor {\n\t\tname := prefix + nextRandom() + suffix\n\t\tf, err := OpenFile(name, O_RDWR|O_CREATE|O_EXCL, 0600)\n\t\tif IsExist(err) {\n\t\t\tif try++; try < 10000 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn nil, &PathError{Op: \"createtemp\", Path: dir + string(PathSeparator) + prefix + \"*\" + suffix, Err: ErrExist}\n\t\t}\n\t\treturn f, err\n\t}\n}\n\nvar errPatternHasSeparator = errors.New(\"pattern contains path separator\")\n\n// prefixAndSuffix splits pattern by the last wildcard \"*\", if applicable,\n// returning prefix as the part before \"*\" and suffix as the part after \"*\".\nfunc prefixAndSuffix(pattern string) (prefix, suffix string, err error) {\n\tfor i := 0; i < len(pattern); i++ {\n\t\tif IsPathSeparator(pattern[i]) {\n\t\t\treturn \"\", \"\", errPatternHasSeparator\n\t\t}\n\t}\n\tif pos := lastIndex(pattern, '*'); pos != -1 {\n\t\tprefix, suffix = pattern[:pos], pattern[pos+1:]\n\t} else {\n\t\tprefix = pattern\n\t}\n\treturn prefix, suffix, nil\n}\n\n// MkdirTemp creates a new temporary directory in the directory dir\n// and returns the pathname of the new directory.\n// The new directory's name is generated by adding a random string to the end of pattern.\n// If pattern includes a \"*\", the random string replaces the last \"*\" instead.\n// If dir is the empty string, MkdirTemp uses the default directory for temporary files, as returned by TempDir.\n// Multiple programs or goroutines calling MkdirTemp simultaneously will not choose the same directory.\n// It is the caller's responsibility to remove the directory when it is no longer needed.\nfunc MkdirTemp(dir, pattern string) (string, error) {\n\tif dir == \"\" {\n\t\tdir = TempDir()\n\t}\n\n\tprefix, suffix, err := prefixAndSuffix(pattern)\n\tif err != nil {\n\t\treturn \"\", &PathError{Op: \"mkdirtemp\", Path: pattern, Err: err}\n\t}\n\tprefix = joinPath(dir, prefix)\n\n\ttry := 0\n\tfor {\n\t\tname := prefix + nextRandom() + suffix\n\t\terr := Mkdir(name, 0700)\n\t\tif err == nil {\n\t\t\treturn name, nil\n\t\t}\n\t\tif IsExist(err) {\n\t\t\tif try++; try < 10000 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn \"\", &PathError{Op: \"mkdirtemp\", Path: dir + string(PathSeparator) + prefix + \"*\" + suffix, Err: ErrExist}\n\t\t}\n\t\tif IsNotExist(err) {\n\t\t\tif _, err := Stat(dir); IsNotExist(err) {\n\t\t\t\treturn \"\", err\n\t\t\t}\n\t\t}\n\t\treturn \"\", err\n\t}\n}\n\nfunc joinPath(dir, name string) string {\n\tif len(dir) > 0 && IsPathSeparator(dir[len(dir)-1]) {\n\t\treturn dir + name\n\t}\n\treturn dir + string(PathSeparator) + name\n}\n\n// lastIndex from the strings package.\nfunc lastIndex(s string, sep byte) int {\n\tfor i := len(s) - 1; i >= 0; i-- {\n\t\tif s[i] == sep {\n\t\t\treturn i\n\t\t}\n\t}\n\treturn -1\n}\n"
  },
  {
    "path": "src/os/tempfile_test.go",
    "content": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build !baremetal && !js && !wasip1 && !wasip2\n\npackage os_test\n\nimport (\n\t\"errors\"\n\t\"io/fs\"\n\t. \"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"runtime\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestCreateTemp(t *testing.T) {\n\tdir, err := MkdirTemp(\"\", \"TestCreateTempBadDir\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer RemoveAll(dir)\n\n\tnonexistentDir := filepath.Join(dir, \"_not_exists_\")\n\tf, err := CreateTemp(nonexistentDir, \"foo\")\n\tif f != nil || err == nil {\n\t\tt.Errorf(\"CreateTemp(%q, `foo`) = %v, %v\", nonexistentDir, f, err)\n\t}\n}\n\nfunc TestCreateTempPattern(t *testing.T) {\n\ttests := []struct{ pattern, prefix, suffix string }{\n\t\t{\"tempfile_test\", \"tempfile_test\", \"\"},\n\t\t{\"tempfile_test*\", \"tempfile_test\", \"\"},\n\t\t{\"tempfile_test*xyz\", \"tempfile_test\", \"xyz\"},\n\t}\n\tfor _, test := range tests {\n\t\tf, err := CreateTemp(\"\", test.pattern)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"CreateTemp(..., %q) error: %v\", test.pattern, err)\n\t\t\tcontinue\n\t\t}\n\t\tdefer Remove(f.Name())\n\t\tbase := filepath.Base(f.Name())\n\t\tf.Close()\n\t\tif !(strings.HasPrefix(base, test.prefix) && strings.HasSuffix(base, test.suffix)) {\n\t\t\tt.Errorf(\"CreateTemp pattern %q created bad name %q; want prefix %q & suffix %q\",\n\t\t\t\ttest.pattern, base, test.prefix, test.suffix)\n\t\t}\n\t}\n}\n\nfunc TestCreateTempBadPattern(t *testing.T) {\n\ttmpDir, err := MkdirTemp(\"\", t.Name())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer RemoveAll(tmpDir)\n\n\tconst sep = string(PathSeparator)\n\ttests := []struct {\n\t\tpattern string\n\t\twantErr bool\n\t}{\n\t\t{\"ioutil*test\", false},\n\t\t{\"tempfile_test*foo\", false},\n\t\t{\"tempfile_test\" + sep + \"foo\", true},\n\t\t{\"tempfile_test*\" + sep + \"foo\", true},\n\t\t{\"tempfile_test\" + sep + \"*foo\", true},\n\t\t{sep + \"tempfile_test\" + sep + \"*foo\", true},\n\t\t{\"tempfile_test*foo\" + sep, true},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.pattern, func(t *testing.T) {\n\t\t\ttmpfile, err := CreateTemp(tmpDir, tt.pattern)\n\t\t\tif tmpfile != nil {\n\t\t\t\tdefer tmpfile.Close()\n\t\t\t}\n\t\t\tif tt.wantErr {\n\t\t\t\tif err == nil {\n\t\t\t\t\tt.Errorf(\"CreateTemp(..., %#q) succeeded, expected error\", tt.pattern)\n\t\t\t\t}\n\t\t\t\tif !errors.Is(err, ErrPatternHasSeparator) {\n\t\t\t\t\tt.Errorf(\"CreateTemp(..., %#q): %v, expected ErrPatternHasSeparator\", tt.pattern, err)\n\t\t\t\t}\n\t\t\t} else if err != nil {\n\t\t\t\tt.Errorf(\"CreateTemp(..., %#q): %v\", tt.pattern, err)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMkdirTemp(t *testing.T) {\n\tname, err := MkdirTemp(\"/_not_exists_\", \"foo\")\n\tif name != \"\" || err == nil {\n\t\tt.Errorf(\"MkdirTemp(`/_not_exists_`, `foo`) = %v, %v\", name, err)\n\t}\n\n\ttests := []struct {\n\t\tpattern                string\n\t\twantPrefix, wantSuffix string\n\t}{\n\t\t{\"tempfile_test\", \"tempfile_test\", \"\"},\n\t\t{\"tempfile_test*\", \"tempfile_test\", \"\"},\n\t\t{\"tempfile_test*xyz\", \"tempfile_test\", \"xyz\"},\n\t}\n\n\tdir := filepath.Clean(TempDir())\n\n\trunTestMkdirTemp := func(t *testing.T, pattern, wantRePat string) {\n\t\tname, err := MkdirTemp(dir, pattern)\n\t\tif name == \"\" || err != nil {\n\t\t\tt.Fatalf(\"MkdirTemp(dir, `tempfile_test`) = %v, %v\", name, err)\n\t\t}\n\t\tdefer Remove(name)\n\n\t\tre := regexp.MustCompile(wantRePat)\n\t\tif !re.MatchString(name) {\n\t\t\tt.Errorf(\"MkdirTemp(%q, %q) created bad name\\n\\t%q\\ndid not match pattern\\n\\t%q\", dir, pattern, name, wantRePat)\n\t\t}\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.pattern, func(t *testing.T) {\n\t\t\twantRePat := \"^\" + regexp.QuoteMeta(filepath.Join(dir, tt.wantPrefix)) + \"[0-9]+\" + regexp.QuoteMeta(tt.wantSuffix) + \"$\"\n\t\t\trunTestMkdirTemp(t, tt.pattern, wantRePat)\n\t\t})\n\t}\n\n\t// Separately testing \"*xyz\" (which has no prefix). That is when constructing the\n\t// pattern to assert on, as in the previous loop, using filepath.Join for an empty\n\t// prefix filepath.Join(dir, \"\"), produces the pattern:\n\t//     ^<DIR>[0-9]+xyz$\n\t// yet we just want to match\n\t//     \"^<DIR>/[0-9]+xyz\"\n\tt.Run(\"*xyz\", func(t *testing.T) {\n\t\twantRePat := \"^\" + regexp.QuoteMeta(filepath.Join(dir)) + regexp.QuoteMeta(string(filepath.Separator)) + \"[0-9]+xyz$\"\n\t\trunTestMkdirTemp(t, \"*xyz\", wantRePat)\n\t})\n}\n\n// test that we return a nice error message if the dir argument to TempDir doesn't\n// exist (or that it's empty and TempDir doesn't exist)\nfunc TestMkdirTempBadDir(t *testing.T) {\n\tif runtime.GOOS == \"windows\" {\n\t\tt.Log(\"TODO: TestMkdirTempBadDir fails on Windows, skipping\")\n\t\treturn\n\t}\n\tdir, err := MkdirTemp(\"\", \"MkdirTempBadDir\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer RemoveAll(dir)\n\n\tbadDir := filepath.Join(dir, \"not-exist\")\n\t_, err = MkdirTemp(badDir, \"foo\")\n\tif pe, ok := err.(*fs.PathError); !ok || !IsNotExist(err) || pe.Path != badDir {\n\t\tt.Errorf(\"TempDir error = %#v; want PathError for path %q satisfying IsNotExist\", err, badDir)\n\t}\n}\n\nfunc TestMkdirTempBadPattern(t *testing.T) {\n\ttmpDir, err := MkdirTemp(\"\", t.Name())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer RemoveAll(tmpDir)\n\n\tconst sep = string(PathSeparator)\n\ttests := []struct {\n\t\tpattern string\n\t\twantErr bool\n\t}{\n\t\t{\"ioutil*test\", false},\n\t\t{\"tempfile_test*foo\", false},\n\t\t{\"tempfile_test\" + sep + \"foo\", true},\n\t\t{\"tempfile_test*\" + sep + \"foo\", true},\n\t\t{\"tempfile_test\" + sep + \"*foo\", true},\n\t\t{sep + \"tempfile_test\" + sep + \"*foo\", true},\n\t\t{\"tempfile_test*foo\" + sep, true},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.pattern, func(t *testing.T) {\n\t\t\t_, err := MkdirTemp(tmpDir, tt.pattern)\n\t\t\tif tt.wantErr {\n\t\t\t\tif err == nil {\n\t\t\t\t\tt.Errorf(\"MkdirTemp(..., %#q) succeeded, expected error\", tt.pattern)\n\t\t\t\t}\n\t\t\t\tif !errors.Is(err, ErrPatternHasSeparator) {\n\t\t\t\t\tt.Errorf(\"MkdirTemp(..., %#q): %v, expected ErrPatternHasSeparator\", tt.pattern, err)\n\t\t\t\t}\n\t\t\t} else if err != nil {\n\t\t\t\tt.Errorf(\"MkdirTemp(..., %#q): %v\", tt.pattern, err)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "src/os/truncate_test.go",
    "content": "//go:build darwin || (linux && !baremetal && !js && !wasi)\n\n// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os_test\n\nimport (\n\t. \"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"testing\"\n)\n\nfunc TestTruncate(t *testing.T) {\n\t// Truncate is not supported on Windows or wasi at the moment\n\tif runtime.GOOS == \"windows\" || runtime.GOOS == \"wasip1\" || runtime.GOOS == \"wasip2\" {\n\t\tt.Logf(\"skipping test on %s\", runtime.GOOS)\n\t\treturn\n\t}\n\n\ttmpDir := t.TempDir()\n\tfile := filepath.Join(tmpDir, \"truncate_test\")\n\n\tfd, err := Create(file)\n\tif err != nil {\n\t\tt.Fatalf(\"create %q: got %v, want nil\", file, err)\n\t}\n\tdefer fd.Close()\n\n\t// truncate up to 0x100\n\tif err := fd.Truncate(0x100); err != nil {\n\t\tt.Fatalf(\"truncate %q: got %v, want nil\", file, err)\n\t}\n\n\t// check if size is 0x100\n\tfi, err := Stat(file)\n\tif err != nil {\n\t\tt.Fatalf(\"stat %q: got %v, want nil\", file, err)\n\t}\n\n\tif fi.Size() != 0x100 {\n\t\tt.Fatalf(\"size of %q is %d; want 0x100\", file, fi.Size())\n\t}\n\n\t// truncate down to 0x80\n\tif err := fd.Truncate(0x80); err != nil {\n\t\tt.Fatalf(\"truncate %q: got %v, want nil\", file, err)\n\t}\n\n\t// check if size is 0x80\n\tfi, err = Stat(file)\n\tif err != nil {\n\t\tt.Fatalf(\"stat %q: got %v, want nil\", file, err)\n\t}\n\n\tif fi.Size() != 0x80 {\n\t\tt.Fatalf(\"size of %q is %d; want 0x80\", file, fi.Size())\n\t}\n}\n"
  },
  {
    "path": "src/os/types.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os\n\n// File represents an open file descriptor.\ntype File struct {\n\t*file // os specific\n}\n"
  },
  {
    "path": "src/os/types_anyos.go",
    "content": "//go:build !baremetal && !js && !wasm_unknown && !nintendoswitch\n\n// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os\n\nimport \"syscall\"\n\n// Getpagesize returns the underlying system's memory page size.\nfunc Getpagesize() int { return syscall.Getpagesize() }\n\nfunc (fs *fileStat) Name() string { return fs.name }\nfunc (fs *fileStat) IsDir() bool  { return fs.Mode().IsDir() }\n\n// SameFile reports whether fi1 and fi2 describe the same file.\n// For example, on Unix this means that the device and inode fields\n// of the two underlying structures are identical; on other systems\n// the decision may be based on the path names.\n// SameFile only applies to results returned by this package's Stat.\n// It returns false in other cases.\nfunc SameFile(fi1, fi2 FileInfo) bool {\n\tfs1, ok1 := fi1.(*fileStat)\n\tfs2, ok2 := fi2.(*fileStat)\n\tif !ok1 || !ok2 {\n\t\treturn false\n\t}\n\treturn sameFile(fs1, fs2)\n}\n"
  },
  {
    "path": "src/os/types_unix.go",
    "content": "//go:build darwin || (linux && !baremetal && !wasm_unknown && !nintendoswitch) || wasip1 || wasip2\n\n// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os\n\nimport (\n\t\"syscall\"\n\t\"time\"\n)\n\n// A fileStat is the implementation of FileInfo returned by Stat and Lstat.\ntype fileStat struct {\n\tname    string\n\tsize    int64\n\tmode    FileMode\n\tmodTime time.Time\n\tsys     syscall.Stat_t\n}\n\nfunc (fs *fileStat) Size() int64        { return fs.size }\nfunc (fs *fileStat) Mode() FileMode     { return fs.mode }\nfunc (fs *fileStat) ModTime() time.Time { return fs.modTime }\nfunc (fs *fileStat) Sys() interface{}   { return &fs.sys }\n\nfunc sameFile(fs1, fs2 *fileStat) bool {\n\treturn fs1.sys.Dev == fs2.sys.Dev && fs1.sys.Ino == fs2.sys.Ino\n}\n"
  },
  {
    "path": "src/os/types_windows.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage os\n\nimport (\n\t\"internal/syscall/windows\"\n\t\"sync\"\n\t\"syscall\"\n\t\"time\"\n\t\"unsafe\"\n)\n\n// A fileStat is the implementation of FileInfo returned by Stat and Lstat.\ntype fileStat struct {\n\tname string\n\n\t// from ByHandleFileInformation, Win32FileAttributeData and Win32finddata\n\tFileAttributes uint32\n\tCreationTime   syscall.Filetime\n\tLastAccessTime syscall.Filetime\n\tLastWriteTime  syscall.Filetime\n\tFileSizeHigh   uint32\n\tFileSizeLow    uint32\n\n\t// from Win32finddata\n\tReserved0 uint32\n\n\t// what syscall.GetFileType returns\n\tfiletype uint32\n\n\t// used to implement SameFile\n\tsync.Mutex\n\tpath             string\n\tvol              uint32\n\tidxhi            uint32\n\tidxlo            uint32\n\tappendNameToPath bool\n}\n\n// newFileStatFromGetFileInformationByHandle calls GetFileInformationByHandle\n// to gather all required information about the file handle h.\nfunc newFileStatFromGetFileInformationByHandle(path string, h syscall.Handle) (fs *fileStat, err error) {\n\tvar d syscall.ByHandleFileInformation\n\terr = syscall.GetFileInformationByHandle(h, &d)\n\tif err != nil {\n\t\treturn nil, &PathError{Op: \"GetFileInformationByHandle\", Path: path, Err: err}\n\t}\n\n\tvar ti windows.FILE_ATTRIBUTE_TAG_INFO\n\terr = windows.GetFileInformationByHandleEx(h, windows.FileAttributeTagInfo, (*byte)(unsafe.Pointer(&ti)), uint32(unsafe.Sizeof(ti)))\n\tif err != nil {\n\t\tif errno, ok := err.(syscall.Errno); ok && errno == windows.ERROR_INVALID_PARAMETER {\n\t\t\t// It appears calling GetFileInformationByHandleEx with\n\t\t\t// FILE_ATTRIBUTE_TAG_INFO fails on FAT file system with\n\t\t\t// ERROR_INVALID_PARAMETER. Clear ti.ReparseTag in that\n\t\t\t// instance to indicate no symlinks are possible.\n\t\t\tti.ReparseTag = 0\n\t\t} else {\n\t\t\treturn nil, &PathError{Op: \"GetFileInformationByHandleEx\", Path: path, Err: err}\n\t\t}\n\t}\n\n\treturn &fileStat{\n\t\tname:           basename(path),\n\t\tFileAttributes: d.FileAttributes,\n\t\tCreationTime:   d.CreationTime,\n\t\tLastAccessTime: d.LastAccessTime,\n\t\tLastWriteTime:  d.LastWriteTime,\n\t\tFileSizeHigh:   d.FileSizeHigh,\n\t\tFileSizeLow:    d.FileSizeLow,\n\t\tvol:            d.VolumeSerialNumber,\n\t\tidxhi:          d.FileIndexHigh,\n\t\tidxlo:          d.FileIndexLow,\n\t\tReserved0:      ti.ReparseTag,\n\t\t// fileStat.path is used by os.SameFile to decide if it needs\n\t\t// to fetch vol, idxhi and idxlo. But these are already set,\n\t\t// so set fileStat.path to \"\" to prevent os.SameFile doing it again.\n\t}, nil\n}\n\n// newFileStatFromWin32finddata copies all required information\n// from syscall.Win32finddata d into the newly created fileStat.\nfunc newFileStatFromWin32finddata(d *syscall.Win32finddata) *fileStat {\n\treturn &fileStat{\n\t\tFileAttributes: d.FileAttributes,\n\t\tCreationTime:   d.CreationTime,\n\t\tLastAccessTime: d.LastAccessTime,\n\t\tLastWriteTime:  d.LastWriteTime,\n\t\tFileSizeHigh:   d.FileSizeHigh,\n\t\tFileSizeLow:    d.FileSizeLow,\n\t\tReserved0:      d.Reserved0,\n\t}\n}\n\nfunc (fs *fileStat) isSymlink() bool {\n\t// Use instructions described at\n\t// https://blogs.msdn.microsoft.com/oldnewthing/20100212-00/?p=14963/\n\t// to recognize whether it's a symlink.\n\tif fs.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 {\n\t\treturn false\n\t}\n\treturn fs.Reserved0 == syscall.IO_REPARSE_TAG_SYMLINK ||\n\t\tfs.Reserved0 == windows.IO_REPARSE_TAG_MOUNT_POINT\n}\n\nfunc (fs *fileStat) Size() int64 {\n\treturn int64(fs.FileSizeHigh)<<32 + int64(fs.FileSizeLow)\n}\n\nfunc (fs *fileStat) Mode() (m FileMode) {\n\tif fs == &devNullStat {\n\t\treturn ModeDevice | ModeCharDevice | 0666\n\t}\n\tif fs.FileAttributes&syscall.FILE_ATTRIBUTE_READONLY != 0 {\n\t\tm |= 0444\n\t} else {\n\t\tm |= 0666\n\t}\n\tif fs.isSymlink() {\n\t\treturn m | ModeSymlink\n\t}\n\tif fs.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {\n\t\tm |= ModeDir | 0111\n\t}\n\tswitch fs.filetype {\n\tcase syscall.FILE_TYPE_PIPE:\n\t\tm |= ModeNamedPipe\n\tcase syscall.FILE_TYPE_CHAR:\n\t\tm |= ModeDevice | ModeCharDevice\n\t}\n\treturn m\n}\n\nfunc (fs *fileStat) ModTime() time.Time {\n\treturn time.Unix(0, fs.LastWriteTime.Nanoseconds())\n}\n\n// Sys returns syscall.Win32FileAttributeData for file fs.\nfunc (fs *fileStat) Sys() interface{} {\n\treturn &syscall.Win32FileAttributeData{\n\t\tFileAttributes: fs.FileAttributes,\n\t\tCreationTime:   fs.CreationTime,\n\t\tLastAccessTime: fs.LastAccessTime,\n\t\tLastWriteTime:  fs.LastWriteTime,\n\t\tFileSizeHigh:   fs.FileSizeHigh,\n\t\tFileSizeLow:    fs.FileSizeLow,\n\t}\n}\n\nfunc (fs *fileStat) loadFileId() error {\n\tfs.Lock()\n\tdefer fs.Unlock()\n\tif fs.path == \"\" {\n\t\t// already done\n\t\treturn nil\n\t}\n\tvar path string\n\tif fs.appendNameToPath {\n\t\tpath = fs.path + `\\` + fs.name\n\t} else {\n\t\tpath = fs.path\n\t}\n\tpathp, err := syscall.UTF16PtrFromString(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\tattrs := uint32(syscall.FILE_FLAG_BACKUP_SEMANTICS)\n\tif fs.isSymlink() {\n\t\t// Use FILE_FLAG_OPEN_REPARSE_POINT, otherwise CreateFile will follow symlink.\n\t\t// See https://docs.microsoft.com/en-us/windows/desktop/FileIO/symbolic-link-effects-on-file-systems-functions#createfile-and-createfiletransacted\n\t\tattrs |= syscall.FILE_FLAG_OPEN_REPARSE_POINT\n\t}\n\th, err := syscall.CreateFile(pathp, 0, 0, nil, syscall.OPEN_EXISTING, attrs, 0)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer syscall.CloseHandle(h)\n\tvar i syscall.ByHandleFileInformation\n\terr = syscall.GetFileInformationByHandle(h, &i)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfs.path = \"\"\n\tfs.vol = i.VolumeSerialNumber\n\tfs.idxhi = i.FileIndexHigh\n\tfs.idxlo = i.FileIndexLow\n\treturn nil\n}\n\n// saveInfoFromPath saves full path of the file to be used by os.SameFile later,\n// and set name from path.\nfunc (fs *fileStat) saveInfoFromPath(path string) error {\n\tfs.path = path\n\tif !isAbs(fs.path) {\n\t\tvar err error\n\t\tfs.path, err = syscall.FullPath(fs.path)\n\t\tif err != nil {\n\t\t\treturn &PathError{Op: \"FullPath\", Path: path, Err: err}\n\t\t}\n\t}\n\tfs.name = basename(path)\n\treturn nil\n}\n\n// devNullStat is fileStat structure describing DevNull file (\"NUL\").\nvar devNullStat = fileStat{\n\tname: DevNull,\n\t// hopefully this will work for SameFile\n\tvol:   0,\n\tidxhi: 0,\n\tidxlo: 0,\n}\n\nfunc sameFile(fs1, fs2 *fileStat) bool {\n\te := fs1.loadFileId()\n\tif e != nil {\n\t\treturn false\n\t}\n\te = fs2.loadFileId()\n\tif e != nil {\n\t\treturn false\n\t}\n\treturn fs1.vol == fs2.vol && fs1.idxhi == fs2.idxhi && fs1.idxlo == fs2.idxlo\n}\n\n// For testing.\nfunc atime(fi FileInfo) time.Time {\n\treturn time.Unix(0, fi.Sys().(*syscall.Win32FileAttributeData).LastAccessTime.Nanoseconds())\n}\n"
  },
  {
    "path": "src/reflect/all_test.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage reflect_test\n\nimport (\n\t\"bytes\"\n\t\"encoding/base64\"\n\t\"flag\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"io\"\n\t\"math\"\n\t\"math/rand\"\n\t\"net\"\n\t\"os\"\n\t. \"reflect\"\n\t\"reflect/internal/example1\"\n\t\"reflect/internal/example2\"\n\t\"runtime\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"testing\"\n\t\"time\"\n\t\"unsafe\"\n)\n\n// keep imports\nvar (\n\t_ = bytes.MinRead\n\t_ = base64.StdPadding\n\t_ = flag.ErrHelp\n\t_ = fmt.Append\n\t_ = token.LowestPrec\n\t_ = io.EOF\n\t_ = math.E\n\t_ = rand.Int\n\t_ = net.IPv4len\n\t_ = os.PathSeparator\n\t_ = example1.MyStruct{}\n\t_ = example2.MyStruct{}\n\t_ = Invalid // reflect\n\t_ = runtime.Compiler\n\t_ = sort.Find\n\t_ = strconv.IntSize\n\t_ = strings.Clone\n\t_ = sync.NewCond\n\t_ = atomic.AddInt32\n\t_ = testing.T{}\n\t_ = time.Now\n\t_ = unsafe.Add(nil, 0)\n)\n\nvar goarch = struct {\n\tPtrSize uintptr\n}{\n\tPtrSize: unsafe.Sizeof(uintptr(0)),\n}\n\nvar testenv = struct {\n\tOptimizationOff func() bool\n}{\n\tOptimizationOff: func() bool { return false },\n}\n\nvar sink any\n\nfunc TestBool(t *testing.T) {\n\tv := ValueOf(true)\n\tif v.Bool() != true {\n\t\tt.Fatal(\"ValueOf(true).Bool() = false\")\n\t}\n}\n\ntype integer int\ntype T struct {\n\ta int\n\tb float64\n\tc string\n\td *int\n}\n\nvar _ = T{} == T{} // tests depend on T being comparable\n\ntype pair struct {\n\ti any\n\ts string\n}\n\nfunc assert(t *testing.T, s, want string) {\n\tif s != want {\n\t\tt.Errorf(\"have %#q want %#q\", s, want)\n\t}\n}\n\nvar typeTests = []pair{\n\t{struct{ x int }{}, \"int\"},\n\t{struct{ x int8 }{}, \"int8\"},\n\t{struct{ x int16 }{}, \"int16\"},\n\t{struct{ x int32 }{}, \"int32\"},\n\t{struct{ x int64 }{}, \"int64\"},\n\t{struct{ x uint }{}, \"uint\"},\n\t{struct{ x uint8 }{}, \"uint8\"},\n\t{struct{ x uint16 }{}, \"uint16\"},\n\t{struct{ x uint32 }{}, \"uint32\"},\n\t{struct{ x uint64 }{}, \"uint64\"},\n\t{struct{ x float32 }{}, \"float32\"},\n\t{struct{ x float64 }{}, \"float64\"},\n\t{struct{ x int8 }{}, \"int8\"},\n\t{struct{ x (**int8) }{}, \"**int8\"},\n\t{struct{ x (**integer) }{}, \"**reflect_test.integer\"},\n\t{struct{ x ([32]int32) }{}, \"[32]int32\"},\n\t{struct{ x ([]int8) }{}, \"[]int8\"},\n\t{struct{ x (map[string]int32) }{}, \"map[string]int32\"},\n\t{struct{ x (chan<- string) }{}, \"chan<- string\"},\n\t{struct{ x (chan<- chan string) }{}, \"chan<- chan string\"},\n\t{struct{ x (chan<- <-chan string) }{}, \"chan<- <-chan string\"},\n\t{struct{ x (<-chan <-chan string) }{}, \"<-chan <-chan string\"},\n\t{struct{ x (chan (<-chan string)) }{}, \"chan (<-chan string)\"},\n\t{struct {\n\t\tx struct {\n\t\t\tc chan *int32\n\t\t\td float32\n\t\t}\n\t}{},\n\t\t\"struct { c chan *int32; d float32 }\",\n\t},\n\t/* // TODO(tinygo): No function support\n\t{struct{ x (func(a int8, b int32)) }{}, \"func(int8, int32)\"},\n\t{struct {\n\t\tx struct {\n\t\t\tc func(chan *integer, *int8)\n\t\t}\n\t}{},\n\t\t\"struct { c func(chan *reflect_test.integer, *int8) }\",\n\t}, */\n\t{struct {\n\t\tx struct {\n\t\t\ta int8\n\t\t\tb int32\n\t\t}\n\t}{},\n\t\t\"struct { a int8; b int32 }\",\n\t},\n\t{struct {\n\t\tx struct {\n\t\t\ta int8\n\t\t\tb int8\n\t\t\tc int32\n\t\t}\n\t}{},\n\t\t\"struct { a int8; b int8; c int32 }\",\n\t},\n\t{struct {\n\t\tx struct {\n\t\t\ta int8\n\t\t\tb int8\n\t\t\tc int8\n\t\t\td int32\n\t\t}\n\t}{},\n\t\t\"struct { a int8; b int8; c int8; d int32 }\",\n\t},\n\t{struct {\n\t\tx struct {\n\t\t\ta int8\n\t\t\tb int8\n\t\t\tc int8\n\t\t\td int8\n\t\t\te int32\n\t\t}\n\t}{},\n\t\t\"struct { a int8; b int8; c int8; d int8; e int32 }\",\n\t},\n\t{struct {\n\t\tx struct {\n\t\t\ta int8\n\t\t\tb int8\n\t\t\tc int8\n\t\t\td int8\n\t\t\te int8\n\t\t\tf int32\n\t\t}\n\t}{},\n\t\t\"struct { a int8; b int8; c int8; d int8; e int8; f int32 }\",\n\t},\n\t{struct {\n\t\tx struct {\n\t\t\ta int8 `reflect:\"hi there\"`\n\t\t}\n\t}{},\n\t\t`struct { a int8 \"reflect:\\\"hi there\\\"\" }`,\n\t},\n\t{struct {\n\t\tx struct {\n\t\t\ta int8 `reflect:\"hi \\x00there\\t\\n\\\"\\\\\"`\n\t\t}\n\t}{},\n\t\t`struct { a int8 \"reflect:\\\"hi \\\\x00there\\\\t\\\\n\\\\\\\"\\\\\\\\\\\"\" }`,\n\t},\n\t/* // TODO(tinygo):  Functions not supported\n\t{struct {\n\t\tx struct {\n\t\t\tf func(args ...int)\n\t\t}\n\t}{},\n\t\t\"struct { f func(...int) }\",\n\t},\n\t{struct {\n\t\tx (interface {\n\t\t\ta(func(func(int) int) func(func(int)) int)\n\t\t\tb()\n\t\t})\n\t}{},\n\t\t\"interface { reflect_test.a(func(func(int) int) func(func(int)) int); reflect_test.b() }\",\n\t},\n\t{struct {\n\t\tx struct {\n\t\t\tint32\n\t\t\tint64\n\t\t}\n\t}{},\n\t\t\"struct { int32; int64 }\",\n\t},\n\t*/\n}\n\nvar valueTests = []pair{\n\t{new(int), \"132\"},\n\t{new(int8), \"8\"},\n\t{new(int16), \"16\"},\n\t{new(int32), \"32\"},\n\t{new(int64), \"64\"},\n\t{new(uint), \"132\"},\n\t{new(uint8), \"8\"},\n\t{new(uint16), \"16\"},\n\t{new(uint32), \"32\"},\n\t{new(uint64), \"64\"},\n\t{new(float32), \"256.25\"},\n\t{new(float64), \"512.125\"},\n\t{new(complex64), \"532.125+10i\"},\n\t{new(complex128), \"564.25+1i\"},\n\t{new(string), \"stringy cheese\"},\n\t{new(bool), \"true\"},\n\t{new(*int8), \"*int8(0)\"},\n\t{new(**int8), \"**int8(0)\"},\n\t{new([5]int32), \"[5]int32{0, 0, 0, 0, 0}\"},\n\t{new(**integer), \"**reflect_test.integer(0)\"},\n\t{new(map[string]int32), \"map[string]int32{<can't iterate on maps>}\"},\n\t{new(chan<- string), \"chan<- string\"},\n\t//{new(func(a int8, b int32)), \"func(int8, int32)(0)\"}, // TODO(tinygo): No function support\n\t{new(struct {\n\t\tc chan *int32\n\t\td float32\n\t}),\n\t\t\"struct { c chan *int32; d float32 }{chan *int32, 0}\",\n\t},\n\t/* // TODO(tinygo): No function support\n\t{new(struct{ c func(chan *integer, *int8) }),\n\t\t\"struct { c func(chan *reflect_test.integer, *int8) }{func(chan *reflect_test.integer, *int8)(0)}\",\n\t},\n\t*/\n\t{new(struct {\n\t\ta int8\n\t\tb int32\n\t}),\n\t\t\"struct { a int8; b int32 }{0, 0}\",\n\t},\n\t{new(struct {\n\t\ta int8\n\t\tb int8\n\t\tc int32\n\t}),\n\t\t\"struct { a int8; b int8; c int32 }{0, 0, 0}\",\n\t},\n}\n\nfunc testType(t *testing.T, i int, typ Type, want string) {\n\ts := typ.String()\n\tif s != want {\n\t\tt.Errorf(\"#%d: have %#q, want %#q\", i, s, want)\n\t}\n}\n\nfunc TestTypes(t *testing.T) {\n\tfor i, tt := range typeTests {\n\t\ttestType(t, i, ValueOf(tt.i).Field(0).Type(), tt.s)\n\t}\n}\n\nfunc TestSet(t *testing.T) {\n\tfor i, tt := range valueTests {\n\t\tv := ValueOf(tt.i)\n\t\tv = v.Elem()\n\t\tswitch v.Kind() {\n\t\tcase Int:\n\t\t\tv.SetInt(132)\n\t\tcase Int8:\n\t\t\tv.SetInt(8)\n\t\tcase Int16:\n\t\t\tv.SetInt(16)\n\t\tcase Int32:\n\t\t\tv.SetInt(32)\n\t\tcase Int64:\n\t\t\tv.SetInt(64)\n\t\tcase Uint:\n\t\t\tv.SetUint(132)\n\t\tcase Uint8:\n\t\t\tv.SetUint(8)\n\t\tcase Uint16:\n\t\t\tv.SetUint(16)\n\t\tcase Uint32:\n\t\t\tv.SetUint(32)\n\t\tcase Uint64:\n\t\t\tv.SetUint(64)\n\t\tcase Float32:\n\t\t\tv.SetFloat(256.25)\n\t\tcase Float64:\n\t\t\tv.SetFloat(512.125)\n\t\tcase Complex64:\n\t\t\tv.SetComplex(532.125 + 10i)\n\t\tcase Complex128:\n\t\t\tv.SetComplex(564.25 + 1i)\n\t\tcase String:\n\t\t\tv.SetString(\"stringy cheese\")\n\t\tcase Bool:\n\t\t\tv.SetBool(true)\n\t\t}\n\t\ts := valueToString(v)\n\t\tif s != tt.s {\n\t\t\tt.Errorf(\"#%d: have %#q, want %#q\", i, s, tt.s)\n\t\t}\n\t}\n}\n\nfunc TestSetValue(t *testing.T) {\n\tfor i, tt := range valueTests {\n\t\tv := ValueOf(tt.i).Elem()\n\t\tswitch v.Kind() {\n\t\tcase Int:\n\t\t\tv.Set(ValueOf(int(132)))\n\t\tcase Int8:\n\t\t\tv.Set(ValueOf(int8(8)))\n\t\tcase Int16:\n\t\t\tv.Set(ValueOf(int16(16)))\n\t\tcase Int32:\n\t\t\tv.Set(ValueOf(int32(32)))\n\t\tcase Int64:\n\t\t\tv.Set(ValueOf(int64(64)))\n\t\tcase Uint:\n\t\t\tv.Set(ValueOf(uint(132)))\n\t\tcase Uint8:\n\t\t\tv.Set(ValueOf(uint8(8)))\n\t\tcase Uint16:\n\t\t\tv.Set(ValueOf(uint16(16)))\n\t\tcase Uint32:\n\t\t\tv.Set(ValueOf(uint32(32)))\n\t\tcase Uint64:\n\t\t\tv.Set(ValueOf(uint64(64)))\n\t\tcase Float32:\n\t\t\tv.Set(ValueOf(float32(256.25)))\n\t\tcase Float64:\n\t\t\tv.Set(ValueOf(512.125))\n\t\tcase Complex64:\n\t\t\tv.Set(ValueOf(complex64(532.125 + 10i)))\n\t\tcase Complex128:\n\t\t\tv.Set(ValueOf(complex128(564.25 + 1i)))\n\t\tcase String:\n\t\t\tv.Set(ValueOf(\"stringy cheese\"))\n\t\tcase Bool:\n\t\t\tv.Set(ValueOf(true))\n\t\t}\n\t\ts := valueToString(v)\n\t\tif s != tt.s {\n\t\t\tt.Errorf(\"#%d: have %#q, want %#q\", i, s, tt.s)\n\t\t}\n\t}\n}\n\nfunc TestMapIterSet(t *testing.T) {\n\tm := make(map[string]any, len(valueTests))\n\tfor _, tt := range valueTests {\n\t\tm[tt.s] = tt.i\n\t}\n\tv := ValueOf(m)\n\n\tk := New(v.Type().Key()).Elem()\n\te := New(v.Type().Elem()).Elem()\n\n\titer := v.MapRange()\n\tfor iter.Next() {\n\t\tk.SetIterKey(iter)\n\t\te.SetIterValue(iter)\n\t\twant := m[k.String()]\n\t\tgot := e.Interface()\n\t\tif got != want {\n\t\t\tt.Errorf(\"%q: want (%T) %v, got (%T) %v\", k.String(), want, want, got, got)\n\t\t}\n\t\tif setkey, key := valueToString(k), valueToString(iter.Key()); setkey != key {\n\t\t\tt.Errorf(\"MapIter.Key() = %q, MapIter.SetKey() = %q\", key, setkey)\n\t\t}\n\t\tif setval, val := valueToString(e), valueToString(iter.Value()); setval != val {\n\t\t\tt.Errorf(\"MapIter.Value() = %q, MapIter.SetValue() = %q\", val, setval)\n\t\t}\n\t}\n\n\tif testenv.OptimizationOff() {\n\t\treturn // no inlining with the noopt builder\n\t}\n\n\tgot := int(testing.AllocsPerRun(10, func() {\n\t\titer := v.MapRange()\n\t\tfor iter.Next() {\n\t\t\tk.SetIterKey(iter)\n\t\t\te.SetIterValue(iter)\n\t\t}\n\t}))\n\t// Calling MapRange should not allocate even though it returns a *MapIter.\n\t// The function is inlineable, so if the local usage does not escape\n\t// the *MapIter, it can remain stack allocated.\n\twant := 0\n\tif got != want {\n\t\tt.Errorf(\"wanted %d alloc, got %d\", want, got)\n\t}\n}\n\nfunc TestCanIntUintFloatComplex(t *testing.T) {\n\ttype integer int\n\ttype uinteger uint\n\ttype float float64\n\ttype complex complex128\n\n\tvar ops = [...]string{\"CanInt\", \"CanUint\", \"CanFloat\", \"CanComplex\"}\n\n\tvar testCases = []struct {\n\t\ti    any\n\t\twant [4]bool\n\t}{\n\t\t// signed integer\n\t\t{132, [...]bool{true, false, false, false}},\n\t\t{int8(8), [...]bool{true, false, false, false}},\n\t\t{int16(16), [...]bool{true, false, false, false}},\n\t\t{int32(32), [...]bool{true, false, false, false}},\n\t\t{int64(64), [...]bool{true, false, false, false}},\n\t\t// unsigned integer\n\t\t{uint(132), [...]bool{false, true, false, false}},\n\t\t{uint8(8), [...]bool{false, true, false, false}},\n\t\t{uint16(16), [...]bool{false, true, false, false}},\n\t\t{uint32(32), [...]bool{false, true, false, false}},\n\t\t{uint64(64), [...]bool{false, true, false, false}},\n\t\t{uintptr(0xABCD), [...]bool{false, true, false, false}},\n\t\t// floating-point\n\t\t{float32(256.25), [...]bool{false, false, true, false}},\n\t\t{float64(512.125), [...]bool{false, false, true, false}},\n\t\t// complex\n\t\t{complex64(532.125 + 10i), [...]bool{false, false, false, true}},\n\t\t{complex128(564.25 + 1i), [...]bool{false, false, false, true}},\n\t\t// underlying\n\t\t{integer(-132), [...]bool{true, false, false, false}},\n\t\t{uinteger(132), [...]bool{false, true, false, false}},\n\t\t{float(256.25), [...]bool{false, false, true, false}},\n\t\t{complex(532.125 + 10i), [...]bool{false, false, false, true}},\n\t\t// not-acceptable\n\t\t{\"hello world\", [...]bool{false, false, false, false}},\n\t\t{new(int), [...]bool{false, false, false, false}},\n\t\t{new(uint), [...]bool{false, false, false, false}},\n\t\t{new(float64), [...]bool{false, false, false, false}},\n\t\t{new(complex64), [...]bool{false, false, false, false}},\n\t\t{new([5]int), [...]bool{false, false, false, false}},\n\t\t{new(integer), [...]bool{false, false, false, false}},\n\t\t{new(map[int]int), [...]bool{false, false, false, false}},\n\t\t{new(chan<- int), [...]bool{false, false, false, false}},\n\t\t{new(func(a int8)), [...]bool{false, false, false, false}},\n\t\t{new(struct{ i int }), [...]bool{false, false, false, false}},\n\t}\n\n\tfor i, tc := range testCases {\n\t\tv := ValueOf(tc.i)\n\t\tgot := [...]bool{v.CanInt(), v.CanUint(), v.CanFloat(), v.CanComplex()}\n\n\t\tfor j := range tc.want {\n\t\t\tif got[j] != tc.want[j] {\n\t\t\t\tt.Errorf(\n\t\t\t\t\t\"#%d: v.%s() returned %t for type %T, want %t\",\n\t\t\t\t\ti,\n\t\t\t\t\tops[j],\n\t\t\t\t\tgot[j],\n\t\t\t\t\ttc.i,\n\t\t\t\t\ttc.want[j],\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestCanSetField(t *testing.T) {\n\ttype embed struct{ x, X int }\n\ttype Embed struct{ x, X int }\n\ttype S1 struct {\n\t\tembed\n\t\tx, X int\n\t}\n\ttype S2 struct {\n\t\t*embed\n\t\tx, X int\n\t}\n\ttype S3 struct {\n\t\tEmbed\n\t\tx, X int\n\t}\n\ttype S4 struct {\n\t\t*Embed\n\t\tx, X int\n\t}\n\n\ttype testCase struct {\n\t\t// -1 means Addr().Elem() of current value\n\t\tindex  []int\n\t\tcanSet bool\n\t}\n\ttests := []struct {\n\t\tval   Value\n\t\tcases []testCase\n\t}{{\n\t\tval: ValueOf(&S1{}),\n\t\tcases: []testCase{\n\t\t\t{[]int{0}, false},\n\t\t\t{[]int{0, -1}, false},\n\t\t\t{[]int{0, 0}, false},\n\t\t\t{[]int{0, 0, -1}, false},\n\t\t\t{[]int{0, -1, 0}, false},\n\t\t\t{[]int{0, -1, 0, -1}, false},\n\t\t\t{[]int{0, 1}, true},\n\t\t\t{[]int{0, 1, -1}, true},\n\t\t\t{[]int{0, -1, 1}, true},\n\t\t\t{[]int{0, -1, 1, -1}, true},\n\t\t\t{[]int{1}, false},\n\t\t\t{[]int{1, -1}, false},\n\t\t\t{[]int{2}, true},\n\t\t\t{[]int{2, -1}, true},\n\t\t},\n\t}, {\n\t\tval: ValueOf(&S2{embed: &embed{}}),\n\t\tcases: []testCase{\n\t\t\t{[]int{0}, false},\n\t\t\t{[]int{0, -1}, false},\n\t\t\t{[]int{0, 0}, false},\n\t\t\t{[]int{0, 0, -1}, false},\n\t\t\t{[]int{0, -1, 0}, false},\n\t\t\t{[]int{0, -1, 0, -1}, false},\n\t\t\t{[]int{0, 1}, true},\n\t\t\t{[]int{0, 1, -1}, true},\n\t\t\t{[]int{0, -1, 1}, true},\n\t\t\t{[]int{0, -1, 1, -1}, true},\n\t\t\t{[]int{1}, false},\n\t\t\t{[]int{2}, true},\n\t\t},\n\t}, {\n\t\tval: ValueOf(&S3{}),\n\t\tcases: []testCase{\n\t\t\t{[]int{0}, true},\n\t\t\t{[]int{0, -1}, true},\n\t\t\t{[]int{0, 0}, false},\n\t\t\t{[]int{0, 0, -1}, false},\n\t\t\t{[]int{0, -1, 0}, false},\n\t\t\t{[]int{0, -1, 0, -1}, false},\n\t\t\t{[]int{0, 1}, true},\n\t\t\t{[]int{0, 1, -1}, true},\n\t\t\t{[]int{0, -1, 1}, true},\n\t\t\t{[]int{0, -1, 1, -1}, true},\n\t\t\t{[]int{1}, false},\n\t\t\t{[]int{2}, true},\n\t\t},\n\t}, {\n\t\tval: ValueOf(&S4{Embed: &Embed{}}),\n\t\tcases: []testCase{\n\t\t\t{[]int{0}, true},\n\t\t\t{[]int{0, -1}, true},\n\t\t\t{[]int{0, 0}, false},\n\t\t\t{[]int{0, 0, -1}, false},\n\t\t\t{[]int{0, -1, 0}, false},\n\t\t\t{[]int{0, -1, 0, -1}, false},\n\t\t\t{[]int{0, 1}, true},\n\t\t\t{[]int{0, 1, -1}, true},\n\t\t\t{[]int{0, -1, 1}, true},\n\t\t\t{[]int{0, -1, 1, -1}, true},\n\t\t\t{[]int{1}, false},\n\t\t\t{[]int{2}, true},\n\t\t},\n\t}}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.val.Type().Name(), func(t *testing.T) {\n\t\t\tfor _, tc := range tt.cases {\n\t\t\t\tf := tt.val\n\t\t\t\tfor _, i := range tc.index {\n\t\t\t\t\tif f.Kind() == Pointer {\n\t\t\t\t\t\tf = f.Elem()\n\t\t\t\t\t}\n\t\t\t\t\tif i == -1 {\n\t\t\t\t\t\tf = f.Addr().Elem()\n\t\t\t\t\t} else {\n\t\t\t\t\t\tf = f.Field(i)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif got := f.CanSet(); got != tc.canSet {\n\t\t\t\t\tt.Errorf(\"CanSet() = %v, want %v\", got, tc.canSet)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nvar _i = 7\n\nvar valueToStringTests = []pair{\n\t{123, \"123\"},\n\t{123.5, \"123.5\"},\n\t{byte(123), \"123\"},\n\t{\"abc\", \"abc\"},\n\t{T{123, 456.75, \"hello\", &_i}, \"reflect_test.T{123, 456.75, hello, *int(&7)}\"},\n\t{new(chan *T), \"*chan *reflect_test.T(&chan *reflect_test.T)\"},\n\t{[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, \"[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}\"},\n\t{&[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, \"*[10]int(&[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})\"},\n\t{[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, \"[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}\"},\n\t{&[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, \"*[]int(&[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})\"},\n}\n\nfunc TestValueToString(t *testing.T) {\n\tfor i, test := range valueToStringTests {\n\t\ts := valueToString(ValueOf(test.i))\n\t\tif s != test.s {\n\t\t\tt.Errorf(\"#%d: have %#q, want %#q\", i, s, test.s)\n\t\t}\n\t}\n}\n\nfunc TestArrayElemSet(t *testing.T) {\n\tv := ValueOf(&[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}).Elem()\n\tv.Index(4).SetInt(123)\n\ts := valueToString(v)\n\tconst want = \"[10]int{1, 2, 3, 4, 123, 6, 7, 8, 9, 10}\"\n\tif s != want {\n\t\tt.Errorf(\"[10]int: have %#q want %#q\", s, want)\n\t}\n\n\tv = ValueOf([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})\n\tv.Index(4).SetInt(123)\n\ts = valueToString(v)\n\tconst want1 = \"[]int{1, 2, 3, 4, 123, 6, 7, 8, 9, 10}\"\n\tif s != want1 {\n\t\tt.Errorf(\"[]int: have %#q want %#q\", s, want1)\n\t}\n}\n\nfunc TestPtrPointTo(t *testing.T) {\n\tvar ip *int32\n\tvar i int32 = 1234\n\tvip := ValueOf(&ip)\n\tvi := ValueOf(&i).Elem()\n\tvip.Elem().Set(vi.Addr())\n\tif *ip != 1234 {\n\t\tt.Errorf(\"got %d, want 1234\", *ip)\n\t}\n\n\tip = nil\n\tvp := ValueOf(&ip).Elem()\n\tvp.Set(Zero(vp.Type()))\n\tif ip != nil {\n\t\tt.Errorf(\"got non-nil (%p), want nil\", ip)\n\t}\n}\n\nfunc TestPtrSetNil(t *testing.T) {\n\tvar i int32 = 1234\n\tip := &i\n\tvip := ValueOf(&ip)\n\tvip.Elem().Set(Zero(vip.Elem().Type()))\n\tif ip != nil {\n\t\tt.Errorf(\"got non-nil (%d), want nil\", *ip)\n\t}\n}\n\nfunc TestMapSetNil(t *testing.T) {\n\tm := make(map[string]int)\n\tvm := ValueOf(&m)\n\tvm.Elem().Set(Zero(vm.Elem().Type()))\n\tif m != nil {\n\t\tt.Errorf(\"got non-nil (%p), want nil\", m)\n\t}\n}\n\nfunc TestAll(t *testing.T) {\n\ttestType(t, 1, TypeOf((int8)(0)), \"int8\")\n\ttestType(t, 2, TypeOf((*int8)(nil)).Elem(), \"int8\")\n\n\ttyp := TypeOf((*struct {\n\t\tc chan *int32\n\t\td float32\n\t})(nil))\n\ttestType(t, 3, typ, \"*struct { c chan *int32; d float32 }\")\n\tetyp := typ.Elem()\n\ttestType(t, 4, etyp, \"struct { c chan *int32; d float32 }\")\n\tstyp := etyp\n\tf := styp.Field(0)\n\ttestType(t, 5, f.Type, \"chan *int32\")\n\n\tf, present := styp.FieldByName(\"d\")\n\tif !present {\n\t\tt.Errorf(\"FieldByName says present field is absent\")\n\t}\n\ttestType(t, 6, f.Type, \"float32\")\n\n\tf, present = styp.FieldByName(\"absent\")\n\tif present {\n\t\tt.Errorf(\"FieldByName says absent field is present\")\n\t}\n\n\ttyp = TypeOf([32]int32{})\n\ttestType(t, 7, typ, \"[32]int32\")\n\ttestType(t, 8, typ.Elem(), \"int32\")\n\n\ttyp = TypeOf((map[string]*int32)(nil))\n\ttestType(t, 9, typ, \"map[string]*int32\")\n\tmtyp := typ\n\ttestType(t, 10, mtyp.Key(), \"string\")\n\ttestType(t, 11, mtyp.Elem(), \"*int32\")\n\n\ttyp = TypeOf((chan<- string)(nil))\n\ttestType(t, 12, typ, \"chan<- string\")\n\ttestType(t, 13, typ.Elem(), \"string\")\n\n\t// make sure tag strings are not part of element type\n\ttyp = TypeOf(struct {\n\t\td []uint32 `reflect:\"TAG\"`\n\t}{}).Field(0).Type\n\ttestType(t, 14, typ, \"[]uint32\")\n}\n\nfunc TestInterfaceGet(t *testing.T) {\n\tvar inter struct {\n\t\tE any\n\t}\n\tinter.E = 123.456\n\tv1 := ValueOf(&inter)\n\tv2 := v1.Elem().Field(0)\n\tassert(t, v2.Type().String(), \"interface {}\")\n\ti2 := v2.Interface()\n\tv3 := ValueOf(i2)\n\tassert(t, v3.Type().String(), \"float64\")\n}\n\nfunc TestInterfaceValue(t *testing.T) {\n\tvar inter struct {\n\t\tE any\n\t}\n\tinter.E = 123.456\n\tv1 := ValueOf(&inter)\n\tv2 := v1.Elem().Field(0)\n\tassert(t, v2.Type().String(), \"interface {}\")\n\tv3 := v2.Elem()\n\tassert(t, v3.Type().String(), \"float64\")\n\n\ti3 := v2.Interface()\n\tif _, ok := i3.(float64); !ok {\n\t\tt.Error(\"v2.Interface() did not return float64, got \", TypeOf(i3))\n\t}\n}\n\n/*\n\nfunc TestFunctionValue(t *testing.T) {\n\tvar x any = func() {}\n\tv := ValueOf(x)\n\tif fmt.Sprint(v.Interface()) != fmt.Sprint(x) {\n\t\tt.Fatalf(\"TestFunction returned wrong pointer\")\n\t}\n\tassert(t, v.Type().String(), \"func()\")\n}\n\n*/\n\nfunc TestGrow(t *testing.T) {\n\tv := ValueOf([]int(nil))\n\tshouldPanic(\"reflect.Value.Grow using unaddressable value\", func() { v.Grow(0) })\n\tv = ValueOf(new([]int)).Elem()\n\tv.Grow(0)\n\tif !v.IsNil() {\n\t\tt.Errorf(\"v.Grow(0) should still be nil\")\n\t}\n\tv.Grow(1)\n\tif v.Cap() == 0 {\n\t\tt.Errorf(\"v.Cap = %v, want non-zero\", v.Cap())\n\t}\n\twant := v.UnsafePointer()\n\tv.Grow(1)\n\tgot := v.UnsafePointer()\n\tif got != want {\n\t\tt.Errorf(\"noop v.Grow should not change pointers\")\n\t}\n\n\tt.Run(\"Append\", func(t *testing.T) {\n\t\tvar got, want []T\n\t\tv := ValueOf(&got).Elem()\n\t\tappendValue := func(vt T) {\n\t\t\tv.Grow(1)\n\t\t\tv.SetLen(v.Len() + 1)\n\t\t\tv.Index(v.Len() - 1).Set(ValueOf(vt))\n\t\t}\n\t\tfor i := 0; i < 10; i++ {\n\t\t\tvt := T{i, float64(i), strconv.Itoa(i), &i}\n\t\t\tappendValue(vt)\n\t\t\twant = append(want, vt)\n\t\t}\n\t\tif !DeepEqual(got, want) {\n\t\t\tt.Errorf(\"value mismatch:\\ngot  %v\\nwant %v\", got, want)\n\t\t}\n\t})\n\n\tt.Run(\"Rate\", func(t *testing.T) {\n\t\tvar b []byte\n\t\tv := ValueOf(new([]byte)).Elem()\n\t\tfor i := 0; i < 10; i++ {\n\t\t\tb = append(b[:cap(b)], make([]byte, 1)...)\n\t\t\tv.SetLen(v.Cap())\n\t\t\tv.Grow(1)\n\t\t\tif v.Cap() != cap(b) {\n\t\t\t\tt.Errorf(\"v.Cap = %v, want %v\", v.Cap(), cap(b))\n\t\t\t}\n\t\t}\n\t})\n\n\tt.Run(\"ZeroCapacity\", func(t *testing.T) {\n\t\tfor i := 0; i < 10; i++ {\n\t\t\tv := ValueOf(new([]byte)).Elem()\n\t\t\tv.Grow(61)\n\t\t\tb := v.Bytes()\n\t\t\tb = b[:cap(b)]\n\t\t\tfor i, c := range b {\n\t\t\t\tif c != 0 {\n\t\t\t\t\tt.Fatalf(\"Value.Bytes[%d] = 0x%02x, want 0x00\", i, c)\n\t\t\t\t}\n\t\t\t\tb[i] = 0xff\n\t\t\t}\n\t\t\truntime.GC()\n\t\t}\n\t})\n}\n\nvar appendTests = []struct {\n\torig, extra []int\n}{\n\t{nil, nil},\n\t{[]int{}, nil},\n\t{nil, []int{}},\n\t{[]int{}, []int{}},\n\t{nil, []int{22}},\n\t{[]int{}, []int{22}},\n\t{make([]int, 2, 4), nil},\n\t{make([]int, 2, 4), []int{}},\n\t{make([]int, 2, 4), []int{22}},\n\t{make([]int, 2, 4), []int{22, 33, 44}},\n}\n\nfunc TestAppend(t *testing.T) {\n\tfor i, test := range appendTests {\n\t\torigLen, extraLen := len(test.orig), len(test.extra)\n\t\twant := append(test.orig, test.extra...)\n\t\t// Convert extra from []int to []Value.\n\t\te0 := make([]Value, len(test.extra))\n\t\tfor j, e := range test.extra {\n\t\t\te0[j] = ValueOf(e)\n\t\t}\n\t\t// Convert extra from []int to *SliceValue.\n\t\te1 := ValueOf(test.extra)\n\n\t\t// Test Append.\n\t\ta0 := ValueOf(&test.orig).Elem()\n\t\thave0 := Append(a0, e0...)\n\t\tif have0.CanAddr() {\n\t\t\tt.Errorf(\"Append #%d: have slice should not be addressable\", i)\n\t\t}\n\t\tif !DeepEqual(have0.Interface(), want) {\n\t\t\tt.Errorf(\"Append #%d: have %v, want %v (%p %p)\", i, have0, want, test.orig, have0.Interface())\n\t\t}\n\t\t// Check that the orig and extra slices were not modified.\n\t\tif a0.Len() != len(test.orig) {\n\t\t\tt.Errorf(\"Append #%d: a0.Len: have %d, want %d\", i, a0.Len(), origLen)\n\t\t}\n\t\tif len(test.orig) != origLen {\n\t\t\tt.Errorf(\"Append #%d origLen: have %v, want %v\", i, len(test.orig), origLen)\n\t\t}\n\t\tif len(test.extra) != extraLen {\n\t\t\tt.Errorf(\"Append #%d extraLen: have %v, want %v\", i, len(test.extra), extraLen)\n\t\t}\n\n\t\t// Test AppendSlice.\n\t\ta1 := ValueOf(&test.orig).Elem()\n\t\thave1 := AppendSlice(a1, e1)\n\t\tif have1.CanAddr() {\n\t\t\tt.Errorf(\"AppendSlice #%d: have slice should not be addressable\", i)\n\t\t}\n\t\tif !DeepEqual(have1.Interface(), want) {\n\t\t\tt.Errorf(\"AppendSlice #%d: have %v, want %v\", i, have1, want)\n\t\t}\n\t\t// Check that the orig and extra slices were not modified.\n\t\tif a1.Len() != len(test.orig) {\n\t\t\tt.Errorf(\"AppendSlice #%d: a1.Len: have %d, want %d\", i, a0.Len(), origLen)\n\t\t}\n\t\tif len(test.orig) != origLen {\n\t\t\tt.Errorf(\"AppendSlice #%d origLen: have %v, want %v\", i, len(test.orig), origLen)\n\t\t}\n\t\tif len(test.extra) != extraLen {\n\t\t\tt.Errorf(\"AppendSlice #%d extraLen: have %v, want %v\", i, len(test.extra), extraLen)\n\t\t}\n\n\t\t// Test Append and AppendSlice with unexported value.\n\t\tax := ValueOf(struct{ x []int }{test.orig}).Field(0)\n\t\tshouldPanic(\"using unexported field\", func() { Append(ax, e0...) })\n\t\tshouldPanic(\"using unexported field\", func() { AppendSlice(ax, e1) })\n\t}\n}\n\nfunc TestCopy(t *testing.T) {\n\ta := []int{1, 2, 3, 4, 10, 9, 8, 7}\n\tb := []int{11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44}\n\tc := []int{11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44}\n\tfor i := 0; i < len(b); i++ {\n\t\tif b[i] != c[i] {\n\t\t\tt.Fatalf(\"b != c before test\")\n\t\t}\n\t}\n\ta1 := a\n\tb1 := b\n\taa := ValueOf(&a1).Elem()\n\tab := ValueOf(&b1).Elem()\n\tfor tocopy := 1; tocopy <= 7; tocopy++ {\n\t\taa.SetLen(tocopy)\n\t\tCopy(ab, aa)\n\t\taa.SetLen(8)\n\t\tfor i := 0; i < tocopy; i++ {\n\t\t\tif a[i] != b[i] {\n\t\t\t\tt.Errorf(\"(i) tocopy=%d a[%d]=%d, b[%d]=%d\",\n\t\t\t\t\ttocopy, i, a[i], i, b[i])\n\t\t\t}\n\t\t}\n\t\tfor i := tocopy; i < len(b); i++ {\n\t\t\tif b[i] != c[i] {\n\t\t\t\tif i < len(a) {\n\t\t\t\t\tt.Errorf(\"(ii) tocopy=%d a[%d]=%d, b[%d]=%d, c[%d]=%d\",\n\t\t\t\t\t\ttocopy, i, a[i], i, b[i], i, c[i])\n\t\t\t\t} else {\n\t\t\t\t\tt.Errorf(\"(iii) tocopy=%d b[%d]=%d, c[%d]=%d\",\n\t\t\t\t\t\ttocopy, i, b[i], i, c[i])\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tt.Logf(\"tocopy=%d elem %d is okay\\n\", tocopy, i)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestCopyString(t *testing.T) {\n\tt.Run(\"Slice\", func(t *testing.T) {\n\t\ts := bytes.Repeat([]byte{'_'}, 8)\n\t\tval := ValueOf(s)\n\n\t\tn := Copy(val, ValueOf(\"\"))\n\t\tif expecting := []byte(\"________\"); n != 0 || !bytes.Equal(s, expecting) {\n\t\t\tt.Errorf(\"got n = %d, s = %s, expecting n = 0, s = %s\", n, s, expecting)\n\t\t}\n\n\t\tn = Copy(val, ValueOf(\"hello\"))\n\t\tif expecting := []byte(\"hello___\"); n != 5 || !bytes.Equal(s, expecting) {\n\t\t\tt.Errorf(\"got n = %d, s = %s, expecting n = 5, s = %s\", n, s, expecting)\n\t\t}\n\n\t\tn = Copy(val, ValueOf(\"helloworld\"))\n\t\tif expecting := []byte(\"hellowor\"); n != 8 || !bytes.Equal(s, expecting) {\n\t\t\tt.Errorf(\"got n = %d, s = %s, expecting n = 8, s = %s\", n, s, expecting)\n\t\t}\n\t})\n\tt.Run(\"Array\", func(t *testing.T) {\n\t\ts := [...]byte{'_', '_', '_', '_', '_', '_', '_', '_'}\n\t\tval := ValueOf(&s).Elem()\n\n\t\tn := Copy(val, ValueOf(\"\"))\n\t\tif expecting := []byte(\"________\"); n != 0 || !bytes.Equal(s[:], expecting) {\n\t\t\tt.Errorf(\"got n = %d, s = %s, expecting n = 0, s = %s\", n, s[:], expecting)\n\t\t}\n\n\t\tn = Copy(val, ValueOf(\"hello\"))\n\t\tif expecting := []byte(\"hello___\"); n != 5 || !bytes.Equal(s[:], expecting) {\n\t\t\tt.Errorf(\"got n = %d, s = %s, expecting n = 5, s = %s\", n, s[:], expecting)\n\t\t}\n\n\t\tn = Copy(val, ValueOf(\"helloworld\"))\n\t\tif expecting := []byte(\"hellowor\"); n != 8 || !bytes.Equal(s[:], expecting) {\n\t\t\tt.Errorf(\"got n = %d, s = %s, expecting n = 8, s = %s\", n, s[:], expecting)\n\t\t}\n\t})\n}\n\nfunc TestCopyArray(t *testing.T) {\n\ta := [8]int{1, 2, 3, 4, 10, 9, 8, 7}\n\tb := [11]int{11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44}\n\tc := b\n\taa := ValueOf(&a).Elem()\n\tab := ValueOf(&b).Elem()\n\tCopy(ab, aa)\n\tfor i := 0; i < len(a); i++ {\n\t\tif a[i] != b[i] {\n\t\t\tt.Errorf(\"(i) a[%d]=%d, b[%d]=%d\", i, a[i], i, b[i])\n\t\t}\n\t}\n\tfor i := len(a); i < len(b); i++ {\n\t\tif b[i] != c[i] {\n\t\t\tt.Errorf(\"(ii) b[%d]=%d, c[%d]=%d\", i, b[i], i, c[i])\n\t\t} else {\n\t\t\tt.Logf(\"elem %d is okay\\n\", i)\n\t\t}\n\t}\n}\n\nfunc TestBigUnnamedStruct(t *testing.T) {\n\tb := struct{ a, b, c, d int64 }{1, 2, 3, 4}\n\tv := ValueOf(b)\n\tb1 := v.Interface().(struct {\n\t\ta, b, c, d int64\n\t})\n\tif b1.a != b.a || b1.b != b.b || b1.c != b.c || b1.d != b.d {\n\t\tt.Errorf(\"ValueOf(%v).Interface().(*Big) = %v\", b, b1)\n\t}\n}\n\ntype big struct {\n\ta, b, c, d, e int64\n}\n\nfunc TestBigStruct(t *testing.T) {\n\tb := big{1, 2, 3, 4, 5}\n\tv := ValueOf(b)\n\tb1 := v.Interface().(big)\n\tif b1.a != b.a || b1.b != b.b || b1.c != b.c || b1.d != b.d || b1.e != b.e {\n\t\tt.Errorf(\"ValueOf(%v).Interface().(big) = %v\", b, b1)\n\t}\n}\n\ntype Basic struct {\n\tx int\n\ty float32\n}\n\ntype NotBasic Basic\n\ntype DeepEqualTest struct {\n\ta, b any\n\teq   bool\n}\n\n// Simple functions for DeepEqual tests.\nvar (\n\tfn1 func()             // nil.\n\tfn2 func()             // nil.\n\tfn3 = func() { fn1() } // Not nil.\n)\n\ntype self struct{}\n\ntype Loop *Loop\ntype Loopy any\n\nvar loop1, loop2 Loop\nvar loopy1, loopy2 Loopy\nvar cycleMap1, cycleMap2, cycleMap3 map[string]any\n\ntype structWithSelfPtr struct {\n\tp *structWithSelfPtr\n\ts string\n}\n\nfunc init() {\n\tloop1 = &loop2\n\tloop2 = &loop1\n\n\tloopy1 = &loopy2\n\tloopy2 = &loopy1\n\n\tcycleMap1 = map[string]any{}\n\tcycleMap1[\"cycle\"] = cycleMap1\n\tcycleMap2 = map[string]any{}\n\tcycleMap2[\"cycle\"] = cycleMap2\n\tcycleMap3 = map[string]any{}\n\tcycleMap3[\"different\"] = cycleMap3\n}\n\nvar deepEqualTests = []DeepEqualTest{\n\t// Equalities\n\t{nil, nil, true},\n\t{1, 1, true},\n\t{int32(1), int32(1), true},\n\t{0.5, 0.5, true},\n\t{float32(0.5), float32(0.5), true},\n\t{\"hello\", \"hello\", true},\n\t{make([]int, 10), make([]int, 10), true},\n\t{&[3]int{1, 2, 3}, &[3]int{1, 2, 3}, true},\n\t{Basic{1, 0.5}, Basic{1, 0.5}, true},\n\t{error(nil), error(nil), true},\n\t{map[int]string{1: \"one\", 2: \"two\"}, map[int]string{2: \"two\", 1: \"one\"}, true},\n\t{fn1, fn2, true},\n\t{[]byte{1, 2, 3}, []byte{1, 2, 3}, true},\n\t{[]MyByte{1, 2, 3}, []MyByte{1, 2, 3}, true},\n\t{MyBytes{1, 2, 3}, MyBytes{1, 2, 3}, true},\n\n\t// Inequalities\n\t{1, 2, false},\n\t{int32(1), int32(2), false},\n\t{0.5, 0.6, false},\n\t{float32(0.5), float32(0.6), false},\n\t{\"hello\", \"hey\", false},\n\t{make([]int, 10), make([]int, 11), false},\n\t{&[3]int{1, 2, 3}, &[3]int{1, 2, 4}, false},\n\t{Basic{1, 0.5}, Basic{1, 0.6}, false},\n\t{Basic{1, 0}, Basic{2, 0}, false},\n\t{map[int]string{1: \"one\", 3: \"two\"}, map[int]string{2: \"two\", 1: \"one\"}, false},\n\t{map[int]string{1: \"one\", 2: \"txo\"}, map[int]string{2: \"two\", 1: \"one\"}, false},\n\t{map[int]string{1: \"one\"}, map[int]string{2: \"two\", 1: \"one\"}, false},\n\t{map[int]string{2: \"two\", 1: \"one\"}, map[int]string{1: \"one\"}, false},\n\t{nil, 1, false},\n\t{1, nil, false},\n\t{fn1, fn3, false},\n\t{fn3, fn3, false},\n\t{[][]int{{1}}, [][]int{{2}}, false},\n\t{&structWithSelfPtr{p: &structWithSelfPtr{s: \"a\"}}, &structWithSelfPtr{p: &structWithSelfPtr{s: \"b\"}}, false},\n\n\t// Fun with floating point.\n\t{math.NaN(), math.NaN(), false},\n\t{&[1]float64{math.NaN()}, &[1]float64{math.NaN()}, false},\n\t{&[1]float64{math.NaN()}, self{}, true},\n\t{[]float64{math.NaN()}, []float64{math.NaN()}, false},\n\t{[]float64{math.NaN()}, self{}, true},\n\t{map[float64]float64{math.NaN(): 1}, map[float64]float64{1: 2}, false},\n\t{map[float64]float64{math.NaN(): 1}, self{}, true},\n\n\t// Nil vs empty: not the same.\n\t{[]int{}, []int(nil), false},\n\t{[]int{}, []int{}, true},\n\t{[]int(nil), []int(nil), true},\n\t{map[int]int{}, map[int]int(nil), false},\n\t{map[int]int{}, map[int]int{}, true},\n\t{map[int]int(nil), map[int]int(nil), true},\n\n\t// Mismatched types\n\t{1, 1.0, false},\n\t{int32(1), int64(1), false},\n\t{0.5, \"hello\", false},\n\t{[]int{1, 2, 3}, [3]int{1, 2, 3}, false},\n\t{&[3]any{1, 2, 4}, &[3]any{1, 2, \"s\"}, false},\n\t{Basic{1, 0.5}, NotBasic{1, 0.5}, false},\n\t{map[uint]string{1: \"one\", 2: \"two\"}, map[int]string{2: \"two\", 1: \"one\"}, false},\n\t{[]byte{1, 2, 3}, []MyByte{1, 2, 3}, false},\n\t{[]MyByte{1, 2, 3}, MyBytes{1, 2, 3}, false},\n\t{[]byte{1, 2, 3}, MyBytes{1, 2, 3}, false},\n\n\t// Possible loops.\n\t{&loop1, &loop1, true},\n\t{&loop1, &loop2, true},\n\t{&loopy1, &loopy1, true},\n\t{&loopy1, &loopy2, true},\n\t{&cycleMap1, &cycleMap2, true},\n\t{&cycleMap1, &cycleMap3, false},\n}\n\nfunc TestDeepEqual(t *testing.T) {\n\tfor _, test := range deepEqualTests {\n\t\tif test.b == (self{}) {\n\t\t\ttest.b = test.a\n\t\t}\n\t\tif r := DeepEqual(test.a, test.b); r != test.eq {\n\t\t\tt.Errorf(\"DeepEqual(%#v, %#v) = %v, want %v\", test.a, test.b, r, test.eq)\n\t\t}\n\t}\n}\n\nfunc TestTypeOf(t *testing.T) {\n\t// Special case for nil\n\tif typ := TypeOf(nil); typ != nil {\n\t\tt.Errorf(\"expected nil type for nil value; got %v\", typ)\n\t}\n\tfor _, test := range deepEqualTests {\n\t\tv := ValueOf(test.a)\n\t\tif !v.IsValid() {\n\t\t\tcontinue\n\t\t}\n\t\ttyp := TypeOf(test.a)\n\t\tif typ != v.Type() {\n\t\t\tt.Errorf(\"TypeOf(%v) = %v, but ValueOf(%v).Type() = %v\", test.a, typ, test.a, v.Type())\n\t\t}\n\t}\n}\n\ntype Recursive struct {\n\tx int\n\tr *Recursive\n}\n\nfunc TestDeepEqualRecursiveStruct(t *testing.T) {\n\ta, b := new(Recursive), new(Recursive)\n\t*a = Recursive{12, a}\n\t*b = Recursive{12, b}\n\tif !DeepEqual(a, b) {\n\t\tt.Error(\"DeepEqual(recursive same) = false, want true\")\n\t}\n}\n\ntype _Complex struct {\n\ta int\n\tb [3]*_Complex\n\tc *string\n\td map[float64]float64\n}\n\nfunc TestDeepEqualComplexStruct(t *testing.T) {\n\tm := make(map[float64]float64)\n\tstra, strb := \"hello\", \"hello\"\n\ta, b := new(_Complex), new(_Complex)\n\t*a = _Complex{5, [3]*_Complex{a, b, a}, &stra, m}\n\t*b = _Complex{5, [3]*_Complex{b, a, a}, &strb, m}\n\tif !DeepEqual(a, b) {\n\t\tt.Error(\"DeepEqual(complex same) = false, want true\")\n\t}\n}\n\nfunc TestDeepEqualComplexStructInequality(t *testing.T) {\n\tm := make(map[float64]float64)\n\tstra, strb := \"hello\", \"helloo\" // Difference is here\n\ta, b := new(_Complex), new(_Complex)\n\t*a = _Complex{5, [3]*_Complex{a, b, a}, &stra, m}\n\t*b = _Complex{5, [3]*_Complex{b, a, a}, &strb, m}\n\tif DeepEqual(a, b) {\n\t\tt.Error(\"DeepEqual(complex different) = true, want false\")\n\t}\n}\n\ntype UnexpT struct {\n\tm map[int]int\n}\n\nfunc TestDeepEqualUnexportedMap(t *testing.T) {\n\t// Check that DeepEqual can look at unexported fields.\n\tx1 := UnexpT{map[int]int{1: 2}}\n\tx2 := UnexpT{map[int]int{1: 2}}\n\tif !DeepEqual(&x1, &x2) {\n\t\tt.Error(\"DeepEqual(x1, x2) = false, want true\")\n\t}\n\n\ty1 := UnexpT{map[int]int{2: 3}}\n\tif DeepEqual(&x1, &y1) {\n\t\tt.Error(\"DeepEqual(x1, y1) = true, want false\")\n\t}\n}\n\nvar deepEqualPerfTests = []struct {\n\tx, y any\n}{\n\t{x: int8(99), y: int8(99)},\n\t{x: []int8{99}, y: []int8{99}},\n\t{x: int16(99), y: int16(99)},\n\t{x: []int16{99}, y: []int16{99}},\n\t{x: int32(99), y: int32(99)},\n\t{x: []int32{99}, y: []int32{99}},\n\t{x: int64(99), y: int64(99)},\n\t{x: []int64{99}, y: []int64{99}},\n\t{x: int(999999), y: int(999999)},\n\t{x: []int{999999}, y: []int{999999}},\n\n\t{x: uint8(99), y: uint8(99)},\n\t{x: []uint8{99}, y: []uint8{99}},\n\t{x: uint16(99), y: uint16(99)},\n\t{x: []uint16{99}, y: []uint16{99}},\n\t{x: uint32(99), y: uint32(99)},\n\t{x: []uint32{99}, y: []uint32{99}},\n\t{x: uint64(99), y: uint64(99)},\n\t{x: []uint64{99}, y: []uint64{99}},\n\t{x: uint(999999), y: uint(999999)},\n\t{x: []uint{999999}, y: []uint{999999}},\n\t{x: uintptr(999999), y: uintptr(999999)},\n\t{x: []uintptr{999999}, y: []uintptr{999999}},\n\n\t{x: float32(1.414), y: float32(1.414)},\n\t{x: []float32{1.414}, y: []float32{1.414}},\n\t{x: float64(1.414), y: float64(1.414)},\n\t{x: []float64{1.414}, y: []float64{1.414}},\n\n\t{x: complex64(1.414), y: complex64(1.414)},\n\t{x: []complex64{1.414}, y: []complex64{1.414}},\n\t{x: complex128(1.414), y: complex128(1.414)},\n\t{x: []complex128{1.414}, y: []complex128{1.414}},\n\n\t{x: true, y: true},\n\t{x: []bool{true}, y: []bool{true}},\n\n\t{x: \"abcdef\", y: \"abcdef\"},\n\t{x: []string{\"abcdef\"}, y: []string{\"abcdef\"}},\n\n\t{x: []byte(\"abcdef\"), y: []byte(\"abcdef\")},\n\t{x: [][]byte{[]byte(\"abcdef\")}, y: [][]byte{[]byte(\"abcdef\")}},\n\n\t{x: [6]byte{'a', 'b', 'c', 'a', 'b', 'c'}, y: [6]byte{'a', 'b', 'c', 'a', 'b', 'c'}},\n\t{x: [][6]byte{[6]byte{'a', 'b', 'c', 'a', 'b', 'c'}}, y: [][6]byte{[6]byte{'a', 'b', 'c', 'a', 'b', 'c'}}},\n}\n\nfunc TestDeepEqualAllocs(t *testing.T) {\n\tfor _, tt := range deepEqualPerfTests {\n\t\tt.Run(ValueOf(tt.x).Type().String(), func(t *testing.T) {\n\t\t\tgot := testing.AllocsPerRun(100, func() {\n\t\t\t\tif !DeepEqual(tt.x, tt.y) {\n\t\t\t\t\tt.Errorf(\"DeepEqual(%v, %v)=false\", tt.x, tt.y)\n\t\t\t\t}\n\t\t\t})\n\t\t\tif int(got) != 0 {\n\t\t\t\tt.Errorf(\"DeepEqual(%v, %v) allocated %d times\", tt.x, tt.y, int(got))\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc check2ndField(x any, offs uintptr, t *testing.T) {\n\ts := ValueOf(x)\n\tf := s.Type().Field(1)\n\tif f.Offset != offs {\n\t\tt.Error(\"mismatched offsets in structure alignment:\", f.Offset, offs)\n\t}\n}\n\n// Check that structure alignment & offsets viewed through reflect agree with those\n// from the compiler itself.\nfunc TestAlignment(t *testing.T) {\n\ttype T1inner struct {\n\t\ta int\n\t}\n\ttype T1 struct {\n\t\tT1inner\n\t\tf int\n\t}\n\ttype T2inner struct {\n\t\ta, b int\n\t}\n\ttype T2 struct {\n\t\tT2inner\n\t\tf int\n\t}\n\n\tx := T1{T1inner{2}, 17}\n\tcheck2ndField(x, uintptr(unsafe.Pointer(&x.f))-uintptr(unsafe.Pointer(&x)), t)\n\n\tx1 := T2{T2inner{2, 3}, 17}\n\tcheck2ndField(x1, uintptr(unsafe.Pointer(&x1.f))-uintptr(unsafe.Pointer(&x1)), t)\n}\n\nfunc Nil(a any, t *testing.T) {\n\tn := ValueOf(a).Field(0)\n\tif !n.IsNil() {\n\t\tt.Errorf(\"%v should be nil\", a)\n\t}\n}\n\nfunc NotNil(a any, t *testing.T) {\n\tn := ValueOf(a).Field(0)\n\tif n.IsNil() {\n\t\tt.Errorf(\"value of type %v should not be nil\", ValueOf(a).Type().String())\n\t}\n}\n\nfunc TestIsNil(t *testing.T) {\n\t// These implement IsNil.\n\t// Wrap in extra struct to hide interface type.\n\tdoNil := []any{\n\t\tstruct{ x *int }{},\n\t\tstruct{ x any }{},\n\t\tstruct{ x map[string]int }{},\n\t\tstruct{ x func() bool }{},\n\t\tstruct{ x chan int }{},\n\t\tstruct{ x []string }{},\n\t\tstruct{ x unsafe.Pointer }{},\n\t}\n\tfor _, ts := range doNil {\n\t\tty := TypeOf(ts).Field(0).Type\n\t\tv := Zero(ty)\n\t\tv.IsNil() // panics if not okay to call\n\t}\n\n\t// Check the implementations\n\tvar pi struct {\n\t\tx *int\n\t}\n\tNil(pi, t)\n\tpi.x = new(int)\n\tNotNil(pi, t)\n\n\tvar si struct {\n\t\tx []int\n\t}\n\tNil(si, t)\n\tsi.x = make([]int, 10)\n\tNotNil(si, t)\n\n\tvar ci struct {\n\t\tx chan int\n\t}\n\tNil(ci, t)\n\tci.x = make(chan int)\n\tNotNil(ci, t)\n\n\tvar mi struct {\n\t\tx map[int]int\n\t}\n\tNil(mi, t)\n\tmi.x = make(map[int]int)\n\tNotNil(mi, t)\n\n\tvar ii struct {\n\t\tx any\n\t}\n\tNil(ii, t)\n\tii.x = 2\n\tNotNil(ii, t)\n\n\tvar fi struct {\n\t\tx func(t *testing.T)\n\t}\n\tNil(fi, t)\n\tfi.x = TestIsNil\n\tNotNil(fi, t)\n}\n\nfunc setField[S, V any](in S, offset uintptr, value V) (out S) {\n\t*(*V)(unsafe.Add(unsafe.Pointer(&in), offset)) = value\n\treturn in\n}\n\nfunc TestIsZero(t *testing.T) {\n\tfor i, tt := range []struct {\n\t\tx    any\n\t\twant bool\n\t}{\n\t\t// Booleans\n\t\t{true, false},\n\t\t{false, true},\n\t\t// Numeric types\n\t\t{int(0), true},\n\t\t{int(1), false},\n\t\t{int8(0), true},\n\t\t{int8(1), false},\n\t\t{int16(0), true},\n\t\t{int16(1), false},\n\t\t{int32(0), true},\n\t\t{int32(1), false},\n\t\t{int64(0), true},\n\t\t{int64(1), false},\n\t\t{uint(0), true},\n\t\t{uint(1), false},\n\t\t{uint8(0), true},\n\t\t{uint8(1), false},\n\t\t{uint16(0), true},\n\t\t{uint16(1), false},\n\t\t{uint32(0), true},\n\t\t{uint32(1), false},\n\t\t{uint64(0), true},\n\t\t{uint64(1), false},\n\t\t{float32(0), true},\n\t\t{float32(1.2), false},\n\t\t{float64(0), true},\n\t\t{float64(1.2), false},\n\t\t{math.Copysign(0, -1), true},\n\t\t{complex64(0), true},\n\t\t{complex64(1.2), false},\n\t\t{complex128(0), true},\n\t\t{complex128(1.2), false},\n\t\t{complex(math.Copysign(0, -1), 0), true},\n\t\t{complex(0, math.Copysign(0, -1)), true},\n\t\t{complex(math.Copysign(0, -1), math.Copysign(0, -1)), true},\n\t\t{uintptr(0), true},\n\t\t{uintptr(128), false},\n\t\t// Array\n\t\t{Zero(TypeOf([5]string{})).Interface(), true},\n\t\t{[5]string{}, true},                     // comparable array\n\t\t{[5]string{\"\", \"\", \"\", \"a\", \"\"}, false}, // comparable array\n\t\t{[1]*int{}, true},                       // direct pointer array\n\t\t{[1]*int{new(int)}, false},              // direct pointer array\n\t\t{[3][]int{}, true},                      // incomparable array\n\t\t{[3][]int{{1}}, false},                  // incomparable array\n\t\t{[1 << 12]byte{}, true},\n\t\t{[1 << 12]byte{1}, false},\n\t\t{[1]struct{ p *int }{}, true},\n\t\t{[1]struct{ p *int }{{new(int)}}, false},\n\t\t{[3]Value{}, true},\n\t\t{[3]Value{{}, ValueOf(0), {}}, false},\n\t\t// Chan\n\t\t{(chan string)(nil), true},\n\t\t{make(chan string), false},\n\t\t{time.After(1), false},\n\t\t// Func\n\t\t{(func())(nil), true},\n\t\t{New, false},\n\t\t// Interface\n\t\t{New(TypeOf(new(error)).Elem()).Elem(), true},\n\t\t{(io.Reader)(strings.NewReader(\"\")), false},\n\t\t// Map\n\t\t{(map[string]string)(nil), true},\n\t\t{map[string]string{}, false},\n\t\t{make(map[string]string), false},\n\t\t// Pointer\n\t\t{(*func())(nil), true},\n\t\t{(*int)(nil), true},\n\t\t{new(int), false},\n\t\t// Slice\n\t\t{[]string{}, false},\n\t\t{([]string)(nil), true},\n\t\t{make([]string, 0), false},\n\t\t// Strings\n\t\t{\"\", true},\n\t\t{\"not-zero\", false},\n\t\t// Structs\n\t\t{T{}, true},                           // comparable struct\n\t\t{T{123, 456.75, \"hello\", &_i}, false}, // comparable struct\n\t\t{struct{ p *int }{}, true},            // direct pointer struct\n\t\t{struct{ p *int }{new(int)}, false},   // direct pointer struct\n\t\t{struct{ s []int }{}, true},           // incomparable struct\n\t\t{struct{ s []int }{[]int{1}}, false},  // incomparable struct\n\t\t{struct{ Value }{}, true},\n\t\t{struct{ Value }{ValueOf(0)}, false},\n\t\t{struct{ _, a, _ uintptr }{}, true}, // comparable struct with blank fields\n\t\t{setField(struct{ _, a, _ uintptr }{}, 0*unsafe.Sizeof(uintptr(0)), 1), true},\n\t\t{setField(struct{ _, a, _ uintptr }{}, 1*unsafe.Sizeof(uintptr(0)), 1), false},\n\t\t{setField(struct{ _, a, _ uintptr }{}, 2*unsafe.Sizeof(uintptr(0)), 1), true},\n\t\t{struct{ _, a, _ func() }{}, true}, // incomparable struct with blank fields\n\t\t{setField(struct{ _, a, _ func() }{}, 0*unsafe.Sizeof((func())(nil)), func() {}), true},\n\t\t{setField(struct{ _, a, _ func() }{}, 1*unsafe.Sizeof((func())(nil)), func() {}), false},\n\t\t{setField(struct{ _, a, _ func() }{}, 2*unsafe.Sizeof((func())(nil)), func() {}), true},\n\t\t{struct{ a [256]S }{}, true},\n\t\t{struct{ a [256]S }{a: [256]S{2: {i1: 1}}}, false},\n\t\t{struct{ a [256]float32 }{}, true},\n\t\t{struct{ a [256]float32 }{a: [256]float32{2: 1.0}}, false},\n\t\t{struct{ _, a [256]S }{}, true},\n\t\t{setField(struct{ _, a [256]S }{}, 0*unsafe.Sizeof(int64(0)), int64(1)), true},\n\t\t// UnsafePointer\n\t\t{(unsafe.Pointer)(nil), true},\n\t\t{(unsafe.Pointer)(new(int)), false},\n\t} {\n\t\tvar x Value\n\t\tif v, ok := tt.x.(Value); ok {\n\t\t\tx = v\n\t\t} else {\n\t\t\tx = ValueOf(tt.x)\n\t\t}\n\n\t\tb := x.IsZero()\n\t\tif b != tt.want {\n\t\t\tt.Errorf(\"%d: IsZero((%s)(%+v)) = %t, want %t\", i, x.Kind(), tt.x, b, tt.want)\n\t\t}\n\n\t\tif !Zero(TypeOf(tt.x)).IsZero() {\n\t\t\tt.Errorf(\"%d: IsZero(Zero(TypeOf((%s)(%+v)))) is false\", i, x.Kind(), tt.x)\n\t\t}\n\n\t\tp := New(x.Type()).Elem()\n\t\tp.Set(x)\n\t\tp.SetZero()\n\t\tif !p.IsZero() {\n\t\t\tt.Errorf(\"%d: IsZero((%s)(%+v)) is true after SetZero\", i, p.Kind(), tt.x)\n\t\t}\n\t}\n\n\t/* // TODO(tinygo): panic/recover support\n\tfunc() {\n\t\tdefer func() {\n\t\t\tif r := recover(); r == nil {\n\t\t\t\tt.Error(\"should panic for invalid value\")\n\t\t\t}\n\t\t}()\n\t\t(Value{}).IsZero()\n\t}()\n\t*/\n}\n\n// extra comment for gofmt\n\nfunc TestInterfaceExtraction(t *testing.T) {\n\tvar s struct {\n\t\tW io.Writer\n\t}\n\n\ts.W = os.Stdout\n\tv := Indirect(ValueOf(&s)).Field(0).Interface()\n\tif v != s.W.(any) {\n\t\tt.Error(\"Interface() on interface: \", v, s.W)\n\t}\n}\nfunc TestNilPtrValueSub(t *testing.T) {\n\tvar pi *int\n\tif pv := ValueOf(pi); pv.Elem().IsValid() {\n\t\tt.Error(\"ValueOf((*int)(nil)).Elem().IsValid()\")\n\t}\n}\n\nfunc TestMap(t *testing.T) {\n\tm := map[string]int{\"a\": 1, \"b\": 2}\n\tmv := ValueOf(m)\n\tif n := mv.Len(); n != len(m) {\n\t\tt.Errorf(\"Len = %d, want %d\", n, len(m))\n\t}\n\tkeys := mv.MapKeys()\n\tnewmap := MakeMap(mv.Type())\n\tfor k, v := range m {\n\t\t// Check that returned Keys match keys in range.\n\t\t// These aren't required to be in the same order.\n\t\tseen := false\n\t\tfor _, kv := range keys {\n\t\t\tif kv.String() == k {\n\t\t\t\tseen = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif !seen {\n\t\t\tt.Errorf(\"Missing key %q\", k)\n\t\t}\n\n\t\t// Check that value lookup is correct.\n\t\tvv := mv.MapIndex(ValueOf(k))\n\t\tif vi := vv.Int(); vi != int64(v) {\n\t\t\tt.Errorf(\"Key %q: have value %d, want %d\", k, vi, v)\n\t\t}\n\n\t\t// Copy into new map.\n\t\tnewmap.SetMapIndex(ValueOf(k), ValueOf(v))\n\t}\n\tvv := mv.MapIndex(ValueOf(\"not-present\"))\n\tif vv.IsValid() {\n\t\tt.Errorf(\"Invalid key: got non-nil value %s\", valueToString(vv))\n\t}\n\n\tnewm := newmap.Interface().(map[string]int)\n\tif len(newm) != len(m) {\n\t\tt.Errorf(\"length after copy: newm=%d, m=%d\", len(newm), len(m))\n\t}\n\n\tfor k, v := range newm {\n\t\tmv, ok := m[k]\n\t\tif mv != v {\n\t\t\tt.Errorf(\"newm[%q] = %d, but m[%q] = %d, %v\", k, v, k, mv, ok)\n\t\t}\n\t}\n\n\tnewmap.SetMapIndex(ValueOf(\"a\"), Value{})\n\tv, ok := newm[\"a\"]\n\tif ok {\n\t\tt.Errorf(\"newm[\\\"a\\\"] = %d after delete\", v)\n\t}\n\n\tmv = ValueOf(&m).Elem()\n\tmv.Set(Zero(mv.Type()))\n\tif m != nil {\n\t\tt.Errorf(\"mv.Set(nil) failed\")\n\t}\n\n\ttype S string\n\tshouldPanic(\"not assignable\", func() { mv.MapIndex(ValueOf(S(\"key\"))) })\n\tshouldPanic(\"not assignable\", func() { mv.SetMapIndex(ValueOf(S(\"key\")), ValueOf(0)) })\n}\n\nfunc TestNilMap(t *testing.T) {\n\tvar m map[string]int\n\tmv := ValueOf(m)\n\tkeys := mv.MapKeys()\n\tif len(keys) != 0 {\n\t\tt.Errorf(\">0 keys for nil map: %v\", keys)\n\t}\n\n\t// Check that value for missing key is zero.\n\tx := mv.MapIndex(ValueOf(\"hello\"))\n\tif x.Kind() != Invalid {\n\t\tt.Errorf(\"m.MapIndex(\\\"hello\\\") for nil map = %v, want Invalid Value\", x)\n\t}\n\n\t// Check big value too.\n\tvar mbig map[string][10 << 20]byte\n\tx = ValueOf(mbig).MapIndex(ValueOf(\"hello\"))\n\tif x.Kind() != Invalid {\n\t\tt.Errorf(\"mbig.MapIndex(\\\"hello\\\") for nil map = %v, want Invalid Value\", x)\n\t}\n\n\t// Test that deletes from a nil map succeed.\n\tmv.SetMapIndex(ValueOf(\"hi\"), Value{})\n}\n\n/* // TODO(tinygo): missing chan reflect support\n\nfunc TestChan(t *testing.T) {\n\tfor loop := 0; loop < 2; loop++ {\n\t\tvar c chan int\n\t\tvar cv Value\n\n\t\t// check both ways to allocate channels\n\t\tswitch loop {\n\t\tcase 1:\n\t\t\tc = make(chan int, 1)\n\t\t\tcv = ValueOf(c)\n\t\tcase 0:\n\t\t\tcv = MakeChan(TypeOf(c), 1)\n\t\t\tc = cv.Interface().(chan int)\n\t\t}\n\n\t\t// Send\n\t\tcv.Send(ValueOf(2))\n\t\tif i := <-c; i != 2 {\n\t\t\tt.Errorf(\"reflect Send 2, native recv %d\", i)\n\t\t}\n\n\t\t// Recv\n\t\tc <- 3\n\t\tif i, ok := cv.Recv(); i.Int() != 3 || !ok {\n\t\t\tt.Errorf(\"native send 3, reflect Recv %d, %t\", i.Int(), ok)\n\t\t}\n\n\t\t// TryRecv fail\n\t\tval, ok := cv.TryRecv()\n\t\tif val.IsValid() || ok {\n\t\t\tt.Errorf(\"TryRecv on empty chan: %s, %t\", valueToString(val), ok)\n\t\t}\n\n\t\t// TryRecv success\n\t\tc <- 4\n\t\tval, ok = cv.TryRecv()\n\t\tif !val.IsValid() {\n\t\t\tt.Errorf(\"TryRecv on ready chan got nil\")\n\t\t} else if i := val.Int(); i != 4 || !ok {\n\t\t\tt.Errorf(\"native send 4, TryRecv %d, %t\", i, ok)\n\t\t}\n\n\t\t// TrySend fail\n\t\tc <- 100\n\t\tok = cv.TrySend(ValueOf(5))\n\t\ti := <-c\n\t\tif ok {\n\t\t\tt.Errorf(\"TrySend on full chan succeeded: value %d\", i)\n\t\t}\n\n\t\t// TrySend success\n\t\tok = cv.TrySend(ValueOf(6))\n\t\tif !ok {\n\t\t\tt.Errorf(\"TrySend on empty chan failed\")\n\t\t\tselect {\n\t\t\tcase x := <-c:\n\t\t\t\tt.Errorf(\"TrySend failed but it did send %d\", x)\n\t\t\tdefault:\n\t\t\t}\n\t\t} else {\n\t\t\tif i = <-c; i != 6 {\n\t\t\t\tt.Errorf(\"TrySend 6, recv %d\", i)\n\t\t\t}\n\t\t}\n\n\t\t// Close\n\t\tc <- 123\n\t\tcv.Close()\n\t\tif i, ok := cv.Recv(); i.Int() != 123 || !ok {\n\t\t\tt.Errorf(\"send 123 then close; Recv %d, %t\", i.Int(), ok)\n\t\t}\n\t\tif i, ok := cv.Recv(); i.Int() != 0 || ok {\n\t\t\tt.Errorf(\"after close Recv %d, %t\", i.Int(), ok)\n\t\t}\n\t}\n\n\t// check creation of unbuffered channel\n\tvar c chan int\n\tcv := MakeChan(TypeOf(c), 0)\n\tc = cv.Interface().(chan int)\n\tif cv.TrySend(ValueOf(7)) {\n\t\tt.Errorf(\"TrySend on sync chan succeeded\")\n\t}\n\tif v, ok := cv.TryRecv(); v.IsValid() || ok {\n\t\tt.Errorf(\"TryRecv on sync chan succeeded: isvalid=%v ok=%v\", v.IsValid(), ok)\n\t}\n\n\t// len/cap\n\tcv = MakeChan(TypeOf(c), 10)\n\tc = cv.Interface().(chan int)\n\tfor i := 0; i < 3; i++ {\n\t\tc <- i\n\t}\n\tif l, m := cv.Len(), cv.Cap(); l != len(c) || m != cap(c) {\n\t\tt.Errorf(\"Len/Cap = %d/%d want %d/%d\", l, m, len(c), cap(c))\n\t}\n}\n\n// caseInfo describes a single case in a select test.\ntype caseInfo struct {\n\tdesc      string\n\tcanSelect bool\n\trecv      Value\n\tclosed    bool\n\thelper    func()\n\tpanic     bool\n}\n\nvar allselect = flag.Bool(\"allselect\", false, \"exhaustive select test\")\n\nfunc TestSelect(t *testing.T) {\n\tselectWatch.once.Do(func() { go selectWatcher() })\n\n\tvar x exhaustive\n\tnch := 0\n\tnewop := func(n int, cap int) (ch, val Value) {\n\t\tnch++\n\t\tif nch%101%2 == 1 {\n\t\t\tc := make(chan int, cap)\n\t\t\tch = ValueOf(c)\n\t\t\tval = ValueOf(n)\n\t\t} else {\n\t\t\tc := make(chan string, cap)\n\t\t\tch = ValueOf(c)\n\t\t\tval = ValueOf(fmt.Sprint(n))\n\t\t}\n\t\treturn\n\t}\n\n\tfor n := 0; x.Next(); n++ {\n\t\tif testing.Short() && n >= 1000 {\n\t\t\tbreak\n\t\t}\n\t\tif n >= 100000 && !*allselect {\n\t\t\tbreak\n\t\t}\n\t\tif n%100000 == 0 && testing.Verbose() {\n\t\t\tprintln(\"TestSelect\", n)\n\t\t}\n\t\tvar cases []SelectCase\n\t\tvar info []caseInfo\n\n\t\t// Ready send.\n\t\tif x.Maybe() {\n\t\t\tch, val := newop(len(cases), 1)\n\t\t\tcases = append(cases, SelectCase{\n\t\t\t\tDir:  SelectSend,\n\t\t\t\tChan: ch,\n\t\t\t\tSend: val,\n\t\t\t})\n\t\t\tinfo = append(info, caseInfo{desc: \"ready send\", canSelect: true})\n\t\t}\n\n\t\t// Ready recv.\n\t\tif x.Maybe() {\n\t\t\tch, val := newop(len(cases), 1)\n\t\t\tch.Send(val)\n\t\t\tcases = append(cases, SelectCase{\n\t\t\t\tDir:  SelectRecv,\n\t\t\t\tChan: ch,\n\t\t\t})\n\t\t\tinfo = append(info, caseInfo{desc: \"ready recv\", canSelect: true, recv: val})\n\t\t}\n\n\t\t// Blocking send.\n\t\tif x.Maybe() {\n\t\t\tch, val := newop(len(cases), 0)\n\t\t\tcases = append(cases, SelectCase{\n\t\t\t\tDir:  SelectSend,\n\t\t\t\tChan: ch,\n\t\t\t\tSend: val,\n\t\t\t})\n\t\t\t// Let it execute?\n\t\t\tif x.Maybe() {\n\t\t\t\tf := func() { ch.Recv() }\n\t\t\t\tinfo = append(info, caseInfo{desc: \"blocking send\", helper: f})\n\t\t\t} else {\n\t\t\t\tinfo = append(info, caseInfo{desc: \"blocking send\"})\n\t\t\t}\n\t\t}\n\n\t\t// Blocking recv.\n\t\tif x.Maybe() {\n\t\t\tch, val := newop(len(cases), 0)\n\t\t\tcases = append(cases, SelectCase{\n\t\t\t\tDir:  SelectRecv,\n\t\t\t\tChan: ch,\n\t\t\t})\n\t\t\t// Let it execute?\n\t\t\tif x.Maybe() {\n\t\t\t\tf := func() { ch.Send(val) }\n\t\t\t\tinfo = append(info, caseInfo{desc: \"blocking recv\", recv: val, helper: f})\n\t\t\t} else {\n\t\t\t\tinfo = append(info, caseInfo{desc: \"blocking recv\"})\n\t\t\t}\n\t\t}\n\n\t\t// Zero Chan send.\n\t\tif x.Maybe() {\n\t\t\t// Maybe include value to send.\n\t\t\tvar val Value\n\t\t\tif x.Maybe() {\n\t\t\t\tval = ValueOf(100)\n\t\t\t}\n\t\t\tcases = append(cases, SelectCase{\n\t\t\t\tDir:  SelectSend,\n\t\t\t\tSend: val,\n\t\t\t})\n\t\t\tinfo = append(info, caseInfo{desc: \"zero Chan send\"})\n\t\t}\n\n\t\t// Zero Chan receive.\n\t\tif x.Maybe() {\n\t\t\tcases = append(cases, SelectCase{\n\t\t\t\tDir: SelectRecv,\n\t\t\t})\n\t\t\tinfo = append(info, caseInfo{desc: \"zero Chan recv\"})\n\t\t}\n\n\t\t// nil Chan send.\n\t\tif x.Maybe() {\n\t\t\tcases = append(cases, SelectCase{\n\t\t\t\tDir:  SelectSend,\n\t\t\t\tChan: ValueOf((chan int)(nil)),\n\t\t\t\tSend: ValueOf(101),\n\t\t\t})\n\t\t\tinfo = append(info, caseInfo{desc: \"nil Chan send\"})\n\t\t}\n\n\t\t// nil Chan recv.\n\t\tif x.Maybe() {\n\t\t\tcases = append(cases, SelectCase{\n\t\t\t\tDir:  SelectRecv,\n\t\t\t\tChan: ValueOf((chan int)(nil)),\n\t\t\t})\n\t\t\tinfo = append(info, caseInfo{desc: \"nil Chan recv\"})\n\t\t}\n\n\t\t// closed Chan send.\n\t\tif x.Maybe() {\n\t\t\tch := make(chan int)\n\t\t\tclose(ch)\n\t\t\tcases = append(cases, SelectCase{\n\t\t\t\tDir:  SelectSend,\n\t\t\t\tChan: ValueOf(ch),\n\t\t\t\tSend: ValueOf(101),\n\t\t\t})\n\t\t\tinfo = append(info, caseInfo{desc: \"closed Chan send\", canSelect: true, panic: true})\n\t\t}\n\n\t\t// closed Chan recv.\n\t\tif x.Maybe() {\n\t\t\tch, val := newop(len(cases), 0)\n\t\t\tch.Close()\n\t\t\tval = Zero(val.Type())\n\t\t\tcases = append(cases, SelectCase{\n\t\t\t\tDir:  SelectRecv,\n\t\t\t\tChan: ch,\n\t\t\t})\n\t\t\tinfo = append(info, caseInfo{desc: \"closed Chan recv\", canSelect: true, closed: true, recv: val})\n\t\t}\n\n\t\tvar helper func() // goroutine to help the select complete\n\n\t\t// Add default? Must be last case here, but will permute.\n\t\t// Add the default if the select would otherwise\n\t\t// block forever, and maybe add it anyway.\n\t\tnumCanSelect := 0\n\t\tcanProceed := false\n\t\tcanBlock := true\n\t\tcanPanic := false\n\t\thelpers := []int{}\n\t\tfor i, c := range info {\n\t\t\tif c.canSelect {\n\t\t\t\tcanProceed = true\n\t\t\t\tcanBlock = false\n\t\t\t\tnumCanSelect++\n\t\t\t\tif c.panic {\n\t\t\t\t\tcanPanic = true\n\t\t\t\t}\n\t\t\t} else if c.helper != nil {\n\t\t\t\tcanProceed = true\n\t\t\t\thelpers = append(helpers, i)\n\t\t\t}\n\t\t}\n\t\tif !canProceed || x.Maybe() {\n\t\t\tcases = append(cases, SelectCase{\n\t\t\t\tDir: SelectDefault,\n\t\t\t})\n\t\t\tinfo = append(info, caseInfo{desc: \"default\", canSelect: canBlock})\n\t\t\tnumCanSelect++\n\t\t} else if canBlock {\n\t\t\t// Select needs to communicate with another goroutine.\n\t\t\tcas := &info[helpers[x.Choose(len(helpers))]]\n\t\t\thelper = cas.helper\n\t\t\tcas.canSelect = true\n\t\t\tnumCanSelect++\n\t\t}\n\n\t\t// Permute cases and case info.\n\t\t// Doing too much here makes the exhaustive loop\n\t\t// too exhausting, so just do two swaps.\n\t\tfor loop := 0; loop < 2; loop++ {\n\t\t\ti := x.Choose(len(cases))\n\t\t\tj := x.Choose(len(cases))\n\t\t\tcases[i], cases[j] = cases[j], cases[i]\n\t\t\tinfo[i], info[j] = info[j], info[i]\n\t\t}\n\n\t\tif helper != nil {\n\t\t\t// We wait before kicking off a goroutine to satisfy a blocked select.\n\t\t\t// The pause needs to be big enough to let the select block before\n\t\t\t// we run the helper, but if we lose that race once in a while it's okay: the\n\t\t\t// select will just proceed immediately. Not a big deal.\n\t\t\t// For short tests we can grow [sic] the timeout a bit without fear of taking too long\n\t\t\tpause := 10 * time.Microsecond\n\t\t\tif testing.Short() {\n\t\t\t\tpause = 100 * time.Microsecond\n\t\t\t}\n\t\t\ttime.AfterFunc(pause, helper)\n\t\t}\n\n\t\t// Run select.\n\t\ti, recv, recvOK, panicErr := runSelect(cases, info)\n\t\tif panicErr != nil && !canPanic {\n\t\t\tt.Fatalf(\"%s\\npanicked unexpectedly: %v\", fmtSelect(info), panicErr)\n\t\t}\n\t\tif panicErr == nil && canPanic && numCanSelect == 1 {\n\t\t\tt.Fatalf(\"%s\\nselected #%d incorrectly (should panic)\", fmtSelect(info), i)\n\t\t}\n\t\tif panicErr != nil {\n\t\t\tcontinue\n\t\t}\n\n\t\tcas := info[i]\n\t\tif !cas.canSelect {\n\t\t\trecvStr := \"\"\n\t\t\tif recv.IsValid() {\n\t\t\t\trecvStr = fmt.Sprintf(\", received %v, %v\", recv.Interface(), recvOK)\n\t\t\t}\n\t\t\tt.Fatalf(\"%s\\nselected #%d incorrectly%s\", fmtSelect(info), i, recvStr)\n\t\t}\n\t\tif cas.panic {\n\t\t\tt.Fatalf(\"%s\\nselected #%d incorrectly (case should panic)\", fmtSelect(info), i)\n\t\t}\n\n\t\tif cases[i].Dir == SelectRecv {\n\t\t\tif !recv.IsValid() {\n\t\t\t\tt.Fatalf(\"%s\\nselected #%d but got %v, %v, want %v, %v\", fmtSelect(info), i, recv, recvOK, cas.recv.Interface(), !cas.closed)\n\t\t\t}\n\t\t\tif !cas.recv.IsValid() {\n\t\t\t\tt.Fatalf(\"%s\\nselected #%d but internal error: missing recv value\", fmtSelect(info), i)\n\t\t\t}\n\t\t\tif recv.Interface() != cas.recv.Interface() || recvOK != !cas.closed {\n\t\t\t\tif recv.Interface() == cas.recv.Interface() && recvOK == !cas.closed {\n\t\t\t\t\tt.Fatalf(\"%s\\nselected #%d, got %#v, %v, and DeepEqual is broken on %T\", fmtSelect(info), i, recv.Interface(), recvOK, recv.Interface())\n\t\t\t\t}\n\t\t\t\tt.Fatalf(\"%s\\nselected #%d but got %#v, %v, want %#v, %v\", fmtSelect(info), i, recv.Interface(), recvOK, cas.recv.Interface(), !cas.closed)\n\t\t\t}\n\t\t} else {\n\t\t\tif recv.IsValid() || recvOK {\n\t\t\t\tt.Fatalf(\"%s\\nselected #%d but got %v, %v, want %v, %v\", fmtSelect(info), i, recv, recvOK, Value{}, false)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestSelectMaxCases(t *testing.T) {\n\tvar sCases []SelectCase\n\tchannel := make(chan int)\n\tclose(channel)\n\tfor i := 0; i < 65536; i++ {\n\t\tsCases = append(sCases, SelectCase{\n\t\t\tDir:  SelectRecv,\n\t\t\tChan: ValueOf(channel),\n\t\t})\n\t}\n\t// Should not panic\n\t_, _, _ = Select(sCases)\n\tsCases = append(sCases, SelectCase{\n\t\tDir:  SelectRecv,\n\t\tChan: ValueOf(channel),\n\t})\n\tdefer func() {\n\t\tif err := recover(); err != nil {\n\t\t\tif err.(string) != \"reflect.Select: too many cases (max 65536)\" {\n\t\t\t\tt.Fatalf(\"unexpected error from select call with greater than max supported cases\")\n\t\t\t}\n\t\t} else {\n\t\t\tt.Fatalf(\"expected select call to panic with greater than max supported cases\")\n\t\t}\n\t}()\n\t// Should panic\n\t_, _, _ = Select(sCases)\n}\n\nfunc TestSelectNop(t *testing.T) {\n\t// \"select { default: }\" should always return the default case.\n\tchosen, _, _ := Select([]SelectCase{{Dir: SelectDefault}})\n\tif chosen != 0 {\n\t\tt.Fatalf(\"expected Select to return 0, but got %#v\", chosen)\n\t}\n}\n\n// selectWatch and the selectWatcher are a watchdog mechanism for running Select.\n// If the selectWatcher notices that the select has been blocked for >1 second, it prints\n// an error describing the select and panics the entire test binary.\nvar selectWatch struct {\n\tsync.Mutex\n\tonce sync.Once\n\tnow  time.Time\n\tinfo []caseInfo\n}\n\nfunc selectWatcher() {\n\tfor {\n\t\ttime.Sleep(1 * time.Second)\n\t\tselectWatch.Lock()\n\t\tif selectWatch.info != nil && time.Since(selectWatch.now) > 10*time.Second {\n\t\t\tfmt.Fprintf(os.Stderr, \"TestSelect:\\n%s blocked indefinitely\\n\", fmtSelect(selectWatch.info))\n\t\t\tpanic(\"select stuck\")\n\t\t}\n\t\tselectWatch.Unlock()\n\t}\n}\n\n// runSelect runs a single select test.\n// It returns the values returned by Select but also returns\n// a panic value if the Select panics.\nfunc runSelect(cases []SelectCase, info []caseInfo) (chosen int, recv Value, recvOK bool, panicErr any) {\n\tdefer func() {\n\t\tpanicErr = recover()\n\n\t\tselectWatch.Lock()\n\t\tselectWatch.info = nil\n\t\tselectWatch.Unlock()\n\t}()\n\n\tselectWatch.Lock()\n\tselectWatch.now = time.Now()\n\tselectWatch.info = info\n\tselectWatch.Unlock()\n\n\tchosen, recv, recvOK = Select(cases)\n\treturn\n}\n\n// fmtSelect formats the information about a single select test.\nfunc fmtSelect(info []caseInfo) string {\n\tvar buf strings.Builder\n\tfmt.Fprintf(&buf, \"\\nselect {\\n\")\n\tfor i, cas := range info {\n\t\tfmt.Fprintf(&buf, \"%d: %s\", i, cas.desc)\n\t\tif cas.recv.IsValid() {\n\t\t\tfmt.Fprintf(&buf, \" val=%#v\", cas.recv.Interface())\n\t\t}\n\t\tif cas.canSelect {\n\t\t\tfmt.Fprintf(&buf, \" canselect\")\n\t\t}\n\t\tif cas.panic {\n\t\t\tfmt.Fprintf(&buf, \" panic\")\n\t\t}\n\t\tfmt.Fprintf(&buf, \"\\n\")\n\t}\n\tfmt.Fprintf(&buf, \"}\")\n\treturn buf.String()\n}\n\n// TODO(tinygo): missing func/method/call support\n\ntype two [2]uintptr\n\n// Difficult test for function call because of\n// implicit padding between arguments.\nfunc dummy(b byte, c int, d byte, e two, f byte, g float32, h byte) (i byte, j int, k byte, l two, m byte, n float32, o byte) {\n\treturn b, c, d, e, f, g, h\n}\n\nfunc TestFunc(t *testing.T) {\n\tret := ValueOf(dummy).Call([]Value{\n\t\tValueOf(byte(10)),\n\t\tValueOf(20),\n\t\tValueOf(byte(30)),\n\t\tValueOf(two{40, 50}),\n\t\tValueOf(byte(60)),\n\t\tValueOf(float32(70)),\n\t\tValueOf(byte(80)),\n\t})\n\tif len(ret) != 7 {\n\t\tt.Fatalf(\"Call returned %d values, want 7\", len(ret))\n\t}\n\n\ti := byte(ret[0].Uint())\n\tj := int(ret[1].Int())\n\tk := byte(ret[2].Uint())\n\tl := ret[3].Interface().(two)\n\tm := byte(ret[4].Uint())\n\tn := float32(ret[5].Float())\n\to := byte(ret[6].Uint())\n\n\tif i != 10 || j != 20 || k != 30 || l != (two{40, 50}) || m != 60 || n != 70 || o != 80 {\n\t\tt.Errorf(\"Call returned %d, %d, %d, %v, %d, %g, %d; want 10, 20, 30, [40, 50], 60, 70, 80\", i, j, k, l, m, n, o)\n\t}\n\n\tfor i, v := range ret {\n\t\tif v.CanAddr() {\n\t\t\tt.Errorf(\"result %d is addressable\", i)\n\t\t}\n\t}\n}\n\nfunc TestCallConvert(t *testing.T) {\n\tv := ValueOf(new(io.ReadWriter)).Elem()\n\tf := ValueOf(func(r io.Reader) io.Reader { return r })\n\tout := f.Call([]Value{v})\n\tif len(out) != 1 || out[0].Type() != TypeOf(new(io.Reader)).Elem() || !out[0].IsNil() {\n\t\tt.Errorf(\"expected [nil], got %v\", out)\n\t}\n}\n\ntype emptyStruct struct{}\n\ntype nonEmptyStruct struct {\n\tmember int\n}\n\nfunc returnEmpty() emptyStruct {\n\treturn emptyStruct{}\n}\n\nfunc takesEmpty(e emptyStruct) {\n}\n\nfunc returnNonEmpty(i int) nonEmptyStruct {\n\treturn nonEmptyStruct{member: i}\n}\n\nfunc takesNonEmpty(n nonEmptyStruct) int {\n\treturn n.member\n}\n\nfunc TestCallWithStruct(t *testing.T) {\n\tr := ValueOf(returnEmpty).Call(nil)\n\tif len(r) != 1 || r[0].Type() != TypeOf(emptyStruct{}) {\n\t\tt.Errorf(\"returning empty struct returned %#v instead\", r)\n\t}\n\tr = ValueOf(takesEmpty).Call([]Value{ValueOf(emptyStruct{})})\n\tif len(r) != 0 {\n\t\tt.Errorf(\"takesEmpty returned values: %#v\", r)\n\t}\n\tr = ValueOf(returnNonEmpty).Call([]Value{ValueOf(42)})\n\tif len(r) != 1 || r[0].Type() != TypeOf(nonEmptyStruct{}) || r[0].Field(0).Int() != 42 {\n\t\tt.Errorf(\"returnNonEmpty returned %#v\", r)\n\t}\n\tr = ValueOf(takesNonEmpty).Call([]Value{ValueOf(nonEmptyStruct{member: 42})})\n\tif len(r) != 1 || r[0].Type() != TypeOf(1) || r[0].Int() != 42 {\n\t\tt.Errorf(\"takesNonEmpty returned %#v\", r)\n\t}\n}\n\nfunc TestCallReturnsEmpty(t *testing.T) {\n\t// Issue 21717: past-the-end pointer write in Call with\n\t// nonzero-sized frame and zero-sized return value.\n\truntime.GC()\n\tvar finalized uint32\n\tf := func() (emptyStruct, *[2]int64) {\n\t\ti := new([2]int64) // big enough to not be tinyalloc'd, so finalizer always runs when i dies\n\t\truntime.SetFinalizer(i, func(*[2]int64) { atomic.StoreUint32(&finalized, 1) })\n\t\treturn emptyStruct{}, i\n\t}\n\tv := ValueOf(f).Call(nil)[0] // out[0] should not alias out[1]'s memory, so the finalizer should run.\n\ttimeout := time.After(5 * time.Second)\n\tfor atomic.LoadUint32(&finalized) == 0 {\n\t\tselect {\n\t\tcase <-timeout:\n\t\t\tt.Fatal(\"finalizer did not run\")\n\t\tdefault:\n\t\t}\n\t\truntime.Gosched()\n\t\truntime.GC()\n\t}\n\truntime.KeepAlive(v)\n}\n\nfunc TestMakeFunc(t *testing.T) {\n\tf := dummy\n\tfv := MakeFunc(TypeOf(f), func(in []Value) []Value { return in })\n\tValueOf(&f).Elem().Set(fv)\n\n\t// Call g with small arguments so that there is\n\t// something predictable (and different from the\n\t// correct results) in those positions on the stack.\n\tg := dummy\n\tg(1, 2, 3, two{4, 5}, 6, 7, 8)\n\n\t// Call constructed function f.\n\ti, j, k, l, m, n, o := f(10, 20, 30, two{40, 50}, 60, 70, 80)\n\tif i != 10 || j != 20 || k != 30 || l != (two{40, 50}) || m != 60 || n != 70 || o != 80 {\n\t\tt.Errorf(\"Call returned %d, %d, %d, %v, %d, %g, %d; want 10, 20, 30, [40, 50], 60, 70, 80\", i, j, k, l, m, n, o)\n\t}\n}\n\nfunc TestMakeFuncInterface(t *testing.T) {\n\tfn := func(i int) int { return i }\n\tincr := func(in []Value) []Value {\n\t\treturn []Value{ValueOf(int(in[0].Int() + 1))}\n\t}\n\tfv := MakeFunc(TypeOf(fn), incr)\n\tValueOf(&fn).Elem().Set(fv)\n\tif r := fn(2); r != 3 {\n\t\tt.Errorf(\"Call returned %d, want 3\", r)\n\t}\n\tif r := fv.Call([]Value{ValueOf(14)})[0].Int(); r != 15 {\n\t\tt.Errorf(\"Call returned %d, want 15\", r)\n\t}\n\tif r := fv.Interface().(func(int) int)(26); r != 27 {\n\t\tt.Errorf(\"Call returned %d, want 27\", r)\n\t}\n}\n\nfunc TestMakeFuncVariadic(t *testing.T) {\n\t// Test that variadic arguments are packed into a slice and passed as last arg\n\tfn := func(_ int, is ...int) []int { return nil }\n\tfv := MakeFunc(TypeOf(fn), func(in []Value) []Value { return in[1:2] })\n\tValueOf(&fn).Elem().Set(fv)\n\n\tr := fn(1, 2, 3)\n\tif r[0] != 2 || r[1] != 3 {\n\t\tt.Errorf(\"Call returned [%v, %v]; want 2, 3\", r[0], r[1])\n\t}\n\n\tr = fn(1, []int{2, 3}...)\n\tif r[0] != 2 || r[1] != 3 {\n\t\tt.Errorf(\"Call returned [%v, %v]; want 2, 3\", r[0], r[1])\n\t}\n\n\tr = fv.Call([]Value{ValueOf(1), ValueOf(2), ValueOf(3)})[0].Interface().([]int)\n\tif r[0] != 2 || r[1] != 3 {\n\t\tt.Errorf(\"Call returned [%v, %v]; want 2, 3\", r[0], r[1])\n\t}\n\n\tr = fv.CallSlice([]Value{ValueOf(1), ValueOf([]int{2, 3})})[0].Interface().([]int)\n\tif r[0] != 2 || r[1] != 3 {\n\t\tt.Errorf(\"Call returned [%v, %v]; want 2, 3\", r[0], r[1])\n\t}\n\n\tf := fv.Interface().(func(int, ...int) []int)\n\n\tr = f(1, 2, 3)\n\tif r[0] != 2 || r[1] != 3 {\n\t\tt.Errorf(\"Call returned [%v, %v]; want 2, 3\", r[0], r[1])\n\t}\n\tr = f(1, []int{2, 3}...)\n\tif r[0] != 2 || r[1] != 3 {\n\t\tt.Errorf(\"Call returned [%v, %v]; want 2, 3\", r[0], r[1])\n\t}\n}\n\n// Dummy type that implements io.WriteCloser\ntype WC struct {\n}\n\nfunc (w *WC) Write(p []byte) (n int, err error) {\n\treturn 0, nil\n}\nfunc (w *WC) Close() error {\n\treturn nil\n}\n\nfunc TestMakeFuncValidReturnAssignments(t *testing.T) {\n\t// reflect.Values returned from the wrapped function should be assignment-converted\n\t// to the types returned by the result of MakeFunc.\n\n\t// Concrete types should be promotable to interfaces they implement.\n\tvar f func() error\n\tf = MakeFunc(TypeOf(f), func([]Value) []Value {\n\t\treturn []Value{ValueOf(io.EOF)}\n\t}).Interface().(func() error)\n\tf()\n\n\t// Super-interfaces should be promotable to simpler interfaces.\n\tvar g func() io.Writer\n\tg = MakeFunc(TypeOf(g), func([]Value) []Value {\n\t\tvar w io.WriteCloser = &WC{}\n\t\treturn []Value{ValueOf(&w).Elem()}\n\t}).Interface().(func() io.Writer)\n\tg()\n\n\t// Channels should be promotable to directional channels.\n\tvar h func() <-chan int\n\th = MakeFunc(TypeOf(h), func([]Value) []Value {\n\t\treturn []Value{ValueOf(make(chan int))}\n\t}).Interface().(func() <-chan int)\n\th()\n\n\t// Unnamed types should be promotable to named types.\n\ttype T struct{ a, b, c int }\n\tvar i func() T\n\ti = MakeFunc(TypeOf(i), func([]Value) []Value {\n\t\treturn []Value{ValueOf(struct{ a, b, c int }{a: 1, b: 2, c: 3})}\n\t}).Interface().(func() T)\n\ti()\n}\n\nfunc TestMakeFuncInvalidReturnAssignments(t *testing.T) {\n\t// Type doesn't implement the required interface.\n\tshouldPanic(\"\", func() {\n\t\tvar f func() error\n\t\tf = MakeFunc(TypeOf(f), func([]Value) []Value {\n\t\t\treturn []Value{ValueOf(int(7))}\n\t\t}).Interface().(func() error)\n\t\tf()\n\t})\n\t// Assigning to an interface with additional methods.\n\tshouldPanic(\"\", func() {\n\t\tvar f func() io.ReadWriteCloser\n\t\tf = MakeFunc(TypeOf(f), func([]Value) []Value {\n\t\t\tvar w io.WriteCloser = &WC{}\n\t\t\treturn []Value{ValueOf(&w).Elem()}\n\t\t}).Interface().(func() io.ReadWriteCloser)\n\t\tf()\n\t})\n\t// Directional channels can't be assigned to bidirectional ones.\n\tshouldPanic(\"\", func() {\n\t\tvar f func() chan int\n\t\tf = MakeFunc(TypeOf(f), func([]Value) []Value {\n\t\t\tvar c <-chan int = make(chan int)\n\t\t\treturn []Value{ValueOf(c)}\n\t\t}).Interface().(func() chan int)\n\t\tf()\n\t})\n\t// Two named types which are otherwise identical.\n\tshouldPanic(\"\", func() {\n\t\ttype T struct{ a, b, c int }\n\t\ttype U struct{ a, b, c int }\n\t\tvar f func() T\n\t\tf = MakeFunc(TypeOf(f), func([]Value) []Value {\n\t\t\treturn []Value{ValueOf(U{a: 1, b: 2, c: 3})}\n\t\t}).Interface().(func() T)\n\t\tf()\n\t})\n}\n\n*/\n\ntype Point struct {\n\tx, y int\n}\n\n// This will be index 0.\nfunc (p Point) AnotherMethod(scale int) int {\n\treturn -1\n}\n\n// This will be index 1.\nfunc (p Point) Dist(scale int) int {\n\t//println(\"Point.Dist\", p.x, p.y, scale)\n\treturn p.x*p.x*scale + p.y*p.y*scale\n}\n\n// This will be index 2.\nfunc (p Point) GCMethod(k int) int {\n\truntime.GC()\n\treturn k + p.x\n}\n\n// This will be index 3.\nfunc (p Point) NoArgs() {\n\t// Exercise no-argument/no-result paths.\n}\n\n// This will be index 4.\nfunc (p Point) TotalDist(points ...Point) int {\n\ttot := 0\n\tfor _, q := range points {\n\t\tdx := q.x - p.x\n\t\tdy := q.y - p.y\n\t\ttot += dx*dx + dy*dy // Should call Sqrt, but it's just a test.\n\n\t}\n\treturn tot\n}\n\n// This will be index 5.\nfunc (p *Point) Int64Method(x int64) int64 {\n\treturn x\n}\n\n// This will be index 6.\nfunc (p *Point) Int32Method(x int32) int32 {\n\treturn x\n}\n\n/*\n// TODO(tinygo): missing method support\nfunc TestMethod(t *testing.T) {\n\t// Non-curried method of type.\n\tp := Point{3, 4}\n\ti := TypeOf(p).Method(1).Func.Call([]Value{ValueOf(p), ValueOf(10)})[0].Int()\n\tif i != 250 {\n\t\tt.Errorf(\"Type Method returned %d; want 250\", i)\n\t}\n\n\tm, ok := TypeOf(p).MethodByName(\"Dist\")\n\tif !ok {\n\t\tt.Fatalf(\"method by name failed\")\n\t}\n\ti = m.Func.Call([]Value{ValueOf(p), ValueOf(11)})[0].Int()\n\tif i != 275 {\n\t\tt.Errorf(\"Type MethodByName returned %d; want 275\", i)\n\t}\n\n\tm, ok = TypeOf(p).MethodByName(\"NoArgs\")\n\tif !ok {\n\t\tt.Fatalf(\"method by name failed\")\n\t}\n\tn := len(m.Func.Call([]Value{ValueOf(p)}))\n\tif n != 0 {\n\t\tt.Errorf(\"NoArgs returned %d values; want 0\", n)\n\t}\n\n\ti = TypeOf(&p).Method(1).Func.Call([]Value{ValueOf(&p), ValueOf(12)})[0].Int()\n\tif i != 300 {\n\t\tt.Errorf(\"Pointer Type Method returned %d; want 300\", i)\n\t}\n\n\tm, ok = TypeOf(&p).MethodByName(\"Dist\")\n\tif !ok {\n\t\tt.Fatalf(\"ptr method by name failed\")\n\t}\n\ti = m.Func.Call([]Value{ValueOf(&p), ValueOf(13)})[0].Int()\n\tif i != 325 {\n\t\tt.Errorf(\"Pointer Type MethodByName returned %d; want 325\", i)\n\t}\n\n\tm, ok = TypeOf(&p).MethodByName(\"NoArgs\")\n\tif !ok {\n\t\tt.Fatalf(\"method by name failed\")\n\t}\n\tn = len(m.Func.Call([]Value{ValueOf(&p)}))\n\tif n != 0 {\n\t\tt.Errorf(\"NoArgs returned %d values; want 0\", n)\n\t}\n\n\t_, ok = TypeOf(&p).MethodByName(\"AA\")\n\tif ok {\n\t\tt.Errorf(`MethodByName(\"AA\") should have failed`)\n\t}\n\n\t_, ok = TypeOf(&p).MethodByName(\"ZZ\")\n\tif ok {\n\t\tt.Errorf(`MethodByName(\"ZZ\") should have failed`)\n\t}\n\n\t// Curried method of value.\n\ttfunc := TypeOf((func(int) int)(nil))\n\tv := ValueOf(p).Method(1)\n\tif tt := v.Type(); tt != tfunc {\n\t\tt.Errorf(\"Value Method Type is %s; want %s\", tt, tfunc)\n\t}\n\ti = v.Call([]Value{ValueOf(14)})[0].Int()\n\tif i != 350 {\n\t\tt.Errorf(\"Value Method returned %d; want 350\", i)\n\t}\n\tv = ValueOf(p).MethodByName(\"Dist\")\n\tif tt := v.Type(); tt != tfunc {\n\t\tt.Errorf(\"Value MethodByName Type is %s; want %s\", tt, tfunc)\n\t}\n\ti = v.Call([]Value{ValueOf(15)})[0].Int()\n\tif i != 375 {\n\t\tt.Errorf(\"Value MethodByName returned %d; want 375\", i)\n\t}\n\tv = ValueOf(p).MethodByName(\"NoArgs\")\n\tv.Call(nil)\n\n\t// Curried method of pointer.\n\tv = ValueOf(&p).Method(1)\n\tif tt := v.Type(); tt != tfunc {\n\t\tt.Errorf(\"Pointer Value Method Type is %s; want %s\", tt, tfunc)\n\t}\n\ti = v.Call([]Value{ValueOf(16)})[0].Int()\n\tif i != 400 {\n\t\tt.Errorf(\"Pointer Value Method returned %d; want 400\", i)\n\t}\n\tv = ValueOf(&p).MethodByName(\"Dist\")\n\tif tt := v.Type(); tt != tfunc {\n\t\tt.Errorf(\"Pointer Value MethodByName Type is %s; want %s\", tt, tfunc)\n\t}\n\ti = v.Call([]Value{ValueOf(17)})[0].Int()\n\tif i != 425 {\n\t\tt.Errorf(\"Pointer Value MethodByName returned %d; want 425\", i)\n\t}\n\tv = ValueOf(&p).MethodByName(\"NoArgs\")\n\tv.Call(nil)\n\n\t// Curried method of interface value.\n\t// Have to wrap interface value in a struct to get at it.\n\t// Passing it to ValueOf directly would\n\t// access the underlying Point, not the interface.\n\tvar x interface {\n\t\tDist(int) int\n\t} = p\n\tpv := ValueOf(&x).Elem()\n\tv = pv.Method(0)\n\tif tt := v.Type(); tt != tfunc {\n\t\tt.Errorf(\"Interface Method Type is %s; want %s\", tt, tfunc)\n\t}\n\ti = v.Call([]Value{ValueOf(18)})[0].Int()\n\tif i != 450 {\n\t\tt.Errorf(\"Interface Method returned %d; want 450\", i)\n\t}\n\tv = pv.MethodByName(\"Dist\")\n\tif tt := v.Type(); tt != tfunc {\n\t\tt.Errorf(\"Interface MethodByName Type is %s; want %s\", tt, tfunc)\n\t}\n\ti = v.Call([]Value{ValueOf(19)})[0].Int()\n\tif i != 475 {\n\t\tt.Errorf(\"Interface MethodByName returned %d; want 475\", i)\n\t}\n}\n\nfunc TestMethodValue(t *testing.T) {\n\tp := Point{3, 4}\n\tvar i int64\n\n\t// Check that method value have the same underlying code pointers.\n\tif p1, p2 := ValueOf(Point{1, 1}).Method(1), ValueOf(Point{2, 2}).Method(1); p1.Pointer() != p2.Pointer() {\n\t\tt.Errorf(\"methodValueCall mismatched: %v - %v\", p1, p2)\n\t}\n\n\t// Curried method of value.\n\ttfunc := TypeOf((func(int) int)(nil))\n\tv := ValueOf(p).Method(1)\n\tif tt := v.Type(); tt != tfunc {\n\t\tt.Errorf(\"Value Method Type is %s; want %s\", tt, tfunc)\n\t}\n\ti = ValueOf(v.Interface()).Call([]Value{ValueOf(10)})[0].Int()\n\tif i != 250 {\n\t\tt.Errorf(\"Value Method returned %d; want 250\", i)\n\t}\n\tv = ValueOf(p).MethodByName(\"Dist\")\n\tif tt := v.Type(); tt != tfunc {\n\t\tt.Errorf(\"Value MethodByName Type is %s; want %s\", tt, tfunc)\n\t}\n\ti = ValueOf(v.Interface()).Call([]Value{ValueOf(11)})[0].Int()\n\tif i != 275 {\n\t\tt.Errorf(\"Value MethodByName returned %d; want 275\", i)\n\t}\n\tv = ValueOf(p).MethodByName(\"NoArgs\")\n\tValueOf(v.Interface()).Call(nil)\n\tv.Interface().(func())()\n\n\t// Curried method of pointer.\n\tv = ValueOf(&p).Method(1)\n\tif tt := v.Type(); tt != tfunc {\n\t\tt.Errorf(\"Pointer Value Method Type is %s; want %s\", tt, tfunc)\n\t}\n\ti = ValueOf(v.Interface()).Call([]Value{ValueOf(12)})[0].Int()\n\tif i != 300 {\n\t\tt.Errorf(\"Pointer Value Method returned %d; want 300\", i)\n\t}\n\tv = ValueOf(&p).MethodByName(\"Dist\")\n\tif tt := v.Type(); tt != tfunc {\n\t\tt.Errorf(\"Pointer Value MethodByName Type is %s; want %s\", tt, tfunc)\n\t}\n\ti = ValueOf(v.Interface()).Call([]Value{ValueOf(13)})[0].Int()\n\tif i != 325 {\n\t\tt.Errorf(\"Pointer Value MethodByName returned %d; want 325\", i)\n\t}\n\tv = ValueOf(&p).MethodByName(\"NoArgs\")\n\tValueOf(v.Interface()).Call(nil)\n\tv.Interface().(func())()\n\n\t// Curried method of pointer to pointer.\n\tpp := &p\n\tv = ValueOf(&pp).Elem().Method(1)\n\tif tt := v.Type(); tt != tfunc {\n\t\tt.Errorf(\"Pointer Pointer Value Method Type is %s; want %s\", tt, tfunc)\n\t}\n\ti = ValueOf(v.Interface()).Call([]Value{ValueOf(14)})[0].Int()\n\tif i != 350 {\n\t\tt.Errorf(\"Pointer Pointer Value Method returned %d; want 350\", i)\n\t}\n\tv = ValueOf(&pp).Elem().MethodByName(\"Dist\")\n\tif tt := v.Type(); tt != tfunc {\n\t\tt.Errorf(\"Pointer Pointer Value MethodByName Type is %s; want %s\", tt, tfunc)\n\t}\n\ti = ValueOf(v.Interface()).Call([]Value{ValueOf(15)})[0].Int()\n\tif i != 375 {\n\t\tt.Errorf(\"Pointer Pointer Value MethodByName returned %d; want 375\", i)\n\t}\n\n\t// Curried method of interface value.\n\t// Have to wrap interface value in a struct to get at it.\n\t// Passing it to ValueOf directly would\n\t// access the underlying Point, not the interface.\n\tvar s = struct {\n\t\tX interface {\n\t\t\tDist(int) int\n\t\t}\n\t}{p}\n\tpv := ValueOf(s).Field(0)\n\tv = pv.Method(0)\n\tif tt := v.Type(); tt != tfunc {\n\t\tt.Errorf(\"Interface Method Type is %s; want %s\", tt, tfunc)\n\t}\n\ti = ValueOf(v.Interface()).Call([]Value{ValueOf(16)})[0].Int()\n\tif i != 400 {\n\t\tt.Errorf(\"Interface Method returned %d; want 400\", i)\n\t}\n\tv = pv.MethodByName(\"Dist\")\n\tif tt := v.Type(); tt != tfunc {\n\t\tt.Errorf(\"Interface MethodByName Type is %s; want %s\", tt, tfunc)\n\t}\n\ti = ValueOf(v.Interface()).Call([]Value{ValueOf(17)})[0].Int()\n\tif i != 425 {\n\t\tt.Errorf(\"Interface MethodByName returned %d; want 425\", i)\n\t}\n\n\t// For issue #33628: method args are not stored at the right offset\n\t// on amd64p32.\n\tm64 := ValueOf(&p).MethodByName(\"Int64Method\").Interface().(func(int64) int64)\n\tif x := m64(123); x != 123 {\n\t\tt.Errorf(\"Int64Method returned %d; want 123\", x)\n\t}\n\tm32 := ValueOf(&p).MethodByName(\"Int32Method\").Interface().(func(int32) int32)\n\tif x := m32(456); x != 456 {\n\t\tt.Errorf(\"Int32Method returned %d; want 456\", x)\n\t}\n}\n\nfunc TestVariadicMethodValue(t *testing.T) {\n\tp := Point{3, 4}\n\tpoints := []Point{{20, 21}, {22, 23}, {24, 25}}\n\twant := int64(p.TotalDist(points[0], points[1], points[2]))\n\n\t// Variadic method of type.\n\ttfunc := TypeOf((func(Point, ...Point) int)(nil))\n\tif tt := TypeOf(p).Method(4).Type; tt != tfunc {\n\t\tt.Errorf(\"Variadic Method Type from TypeOf is %s; want %s\", tt, tfunc)\n\t}\n\n\t// Curried method of value.\n\ttfunc = TypeOf((func(...Point) int)(nil))\n\tv := ValueOf(p).Method(4)\n\tif tt := v.Type(); tt != tfunc {\n\t\tt.Errorf(\"Variadic Method Type is %s; want %s\", tt, tfunc)\n\t}\n\ti := ValueOf(v.Interface()).Call([]Value{ValueOf(points[0]), ValueOf(points[1]), ValueOf(points[2])})[0].Int()\n\tif i != want {\n\t\tt.Errorf(\"Variadic Method returned %d; want %d\", i, want)\n\t}\n\ti = ValueOf(v.Interface()).CallSlice([]Value{ValueOf(points)})[0].Int()\n\tif i != want {\n\t\tt.Errorf(\"Variadic Method CallSlice returned %d; want %d\", i, want)\n\t}\n\n\tf := v.Interface().(func(...Point) int)\n\ti = int64(f(points[0], points[1], points[2]))\n\tif i != want {\n\t\tt.Errorf(\"Variadic Method Interface returned %d; want %d\", i, want)\n\t}\n\ti = int64(f(points...))\n\tif i != want {\n\t\tt.Errorf(\"Variadic Method Interface Slice returned %d; want %d\", i, want)\n\t}\n}\n\ntype DirectIfaceT struct {\n\tp *int\n}\n\nfunc (d DirectIfaceT) M() int { return *d.p }\n\nfunc TestDirectIfaceMethod(t *testing.T) {\n\tx := 42\n\tv := DirectIfaceT{&x}\n\ttyp := TypeOf(v)\n\tm, ok := typ.MethodByName(\"M\")\n\tif !ok {\n\t\tt.Fatalf(\"cannot find method M\")\n\t}\n\tin := []Value{ValueOf(v)}\n\tout := m.Func.Call(in)\n\tif got := out[0].Int(); got != 42 {\n\t\tt.Errorf(\"Call with value receiver got %d, want 42\", got)\n\t}\n\n\tpv := &v\n\ttyp = TypeOf(pv)\n\tm, ok = typ.MethodByName(\"M\")\n\tif !ok {\n\t\tt.Fatalf(\"cannot find method M\")\n\t}\n\tin = []Value{ValueOf(pv)}\n\tout = m.Func.Call(in)\n\tif got := out[0].Int(); got != 42 {\n\t\tt.Errorf(\"Call with pointer receiver got %d, want 42\", got)\n\t}\n}\n\n// Reflect version of $GOROOT/test/method5.go\n\n// Concrete types implementing M method.\n// Smaller than a word, word-sized, larger than a word.\n// Value and pointer receivers.\n\ntype Tinter interface {\n\tM(int, byte) (byte, int)\n}\n\ntype Tsmallv byte\n\nfunc (v Tsmallv) M(x int, b byte) (byte, int) { return b, x + int(v) }\n\ntype Tsmallp byte\n\nfunc (p *Tsmallp) M(x int, b byte) (byte, int) { return b, x + int(*p) }\n\ntype Twordv uintptr\n\nfunc (v Twordv) M(x int, b byte) (byte, int) { return b, x + int(v) }\n\ntype Twordp uintptr\n\nfunc (p *Twordp) M(x int, b byte) (byte, int) { return b, x + int(*p) }\n\ntype Tbigv [2]uintptr\n\nfunc (v Tbigv) M(x int, b byte) (byte, int) { return b, x + int(v[0]) + int(v[1]) }\n\ntype Tbigp [2]uintptr\n\nfunc (p *Tbigp) M(x int, b byte) (byte, int) { return b, x + int(p[0]) + int(p[1]) }\n\ntype tinter interface {\n\tm(int, byte) (byte, int)\n}\n\n// Embedding via pointer.\n\ntype Tm1 struct {\n\tTm2\n}\n\ntype Tm2 struct {\n\t*Tm3\n}\n\ntype Tm3 struct {\n\t*Tm4\n}\n\ntype Tm4 struct {\n}\n\nfunc (t4 Tm4) M(x int, b byte) (byte, int) { return b, x + 40 }\n\nfunc TestMethod5(t *testing.T) {\n\tCheckF := func(name string, f func(int, byte) (byte, int), inc int) {\n\t\tb, x := f(1000, 99)\n\t\tif b != 99 || x != 1000+inc {\n\t\t\tt.Errorf(\"%s(1000, 99) = %v, %v, want 99, %v\", name, b, x, 1000+inc)\n\t\t}\n\t}\n\n\tCheckV := func(name string, i Value, inc int) {\n\t\tbx := i.Method(0).Call([]Value{ValueOf(1000), ValueOf(byte(99))})\n\t\tb := bx[0].Interface()\n\t\tx := bx[1].Interface()\n\t\tif b != byte(99) || x != 1000+inc {\n\t\t\tt.Errorf(\"direct %s.M(1000, 99) = %v, %v, want 99, %v\", name, b, x, 1000+inc)\n\t\t}\n\n\t\tCheckF(name+\".M\", i.Method(0).Interface().(func(int, byte) (byte, int)), inc)\n\t}\n\n\tvar TinterType = TypeOf(new(Tinter)).Elem()\n\n\tCheckI := func(name string, i any, inc int) {\n\t\tv := ValueOf(i)\n\t\tCheckV(name, v, inc)\n\t\tCheckV(\"(i=\"+name+\")\", v.Convert(TinterType), inc)\n\t}\n\n\tsv := Tsmallv(1)\n\tCheckI(\"sv\", sv, 1)\n\tCheckI(\"&sv\", &sv, 1)\n\n\tsp := Tsmallp(2)\n\tCheckI(\"&sp\", &sp, 2)\n\n\twv := Twordv(3)\n\tCheckI(\"wv\", wv, 3)\n\tCheckI(\"&wv\", &wv, 3)\n\n\twp := Twordp(4)\n\tCheckI(\"&wp\", &wp, 4)\n\n\tbv := Tbigv([2]uintptr{5, 6})\n\tCheckI(\"bv\", bv, 11)\n\tCheckI(\"&bv\", &bv, 11)\n\n\tbp := Tbigp([2]uintptr{7, 8})\n\tCheckI(\"&bp\", &bp, 15)\n\n\tt4 := Tm4{}\n\tt3 := Tm3{&t4}\n\tt2 := Tm2{&t3}\n\tt1 := Tm1{t2}\n\tCheckI(\"t4\", t4, 40)\n\tCheckI(\"&t4\", &t4, 40)\n\tCheckI(\"t3\", t3, 40)\n\tCheckI(\"&t3\", &t3, 40)\n\tCheckI(\"t2\", t2, 40)\n\tCheckI(\"&t2\", &t2, 40)\n\tCheckI(\"t1\", t1, 40)\n\tCheckI(\"&t1\", &t1, 40)\n\n\tvar tnil Tinter\n\tvnil := ValueOf(&tnil).Elem()\n\tshouldPanic(\"Method\", func() { vnil.Method(0) })\n}\n\nfunc TestInterfaceSet(t *testing.T) {\n\tp := &Point{3, 4}\n\n\tvar s struct {\n\t\tI any\n\t\tP interface {\n\t\t\tDist(int) int\n\t\t}\n\t}\n\tsv := ValueOf(&s).Elem()\n\tsv.Field(0).Set(ValueOf(p))\n\tif q := s.I.(*Point); q != p {\n\t\tt.Errorf(\"i: have %p want %p\", q, p)\n\t}\n\n\tpv := sv.Field(1)\n\tpv.Set(ValueOf(p))\n\tif q := s.P.(*Point); q != p {\n\t\tt.Errorf(\"i: have %p want %p\", q, p)\n\t}\n\n\ti := pv.Method(0).Call([]Value{ValueOf(10)})[0].Int()\n\tif i != 250 {\n\t\tt.Errorf(\"Interface Method returned %d; want 250\", i)\n\t}\n}\n\n*/\n\ntype T1 struct {\n\ta string\n\tint\n}\n\nfunc TestAnonymousFields(t *testing.T) {\n\tvar field StructField\n\tvar ok bool\n\tvar t1 T1\n\ttype1 := TypeOf(t1)\n\tif field, ok = type1.FieldByName(\"int\"); !ok {\n\t\tt.Fatal(\"no field 'int'\")\n\t}\n\tif field.Index[0] != 1 {\n\t\tt.Error(\"field index should be 1; is\", field.Index)\n\t}\n}\n\ntype FTest struct {\n\ts     any\n\tname  string\n\tindex []int\n\tvalue int\n}\n\ntype D1 struct {\n\td int\n}\ntype D2 struct {\n\td int\n}\n\ntype S0 struct {\n\tA, B, C int\n\tD1\n\tD2\n}\n\ntype S1 struct {\n\tB int\n\tS0\n}\n\ntype S2 struct {\n\tA int\n\t*S1\n}\n\ntype S1x struct {\n\tS1\n}\n\ntype S1y struct {\n\tS1\n}\n\ntype S3 struct {\n\tS1x\n\tS2\n\tD, E int\n\t*S1y\n}\n\ntype S4 struct {\n\t*S4\n\tA int\n}\n\n// The X in S6 and S7 annihilate, but they also block the X in S8.S9.\ntype S5 struct {\n\tS6\n\tS7\n\tS8\n}\n\ntype S6 struct {\n\tX int\n}\n\ntype S7 S6\n\ntype S8 struct {\n\tS9\n}\n\ntype S9 struct {\n\tX int\n\tY int\n}\n\n// The X in S11.S6 and S12.S6 annihilate, but they also block the X in S13.S8.S9.\ntype S10 struct {\n\tS11\n\tS12\n\tS13\n}\n\ntype S11 struct {\n\tS6\n}\n\ntype S12 struct {\n\tS6\n}\n\ntype S13 struct {\n\tS8\n}\n\n// The X in S15.S11.S1 and S16.S11.S1 annihilate.\ntype S14 struct {\n\tS15\n\tS16\n}\n\ntype S15 struct {\n\tS11\n}\n\ntype S16 struct {\n\tS11\n}\n\nvar fieldTests = []FTest{\n\t{struct{}{}, \"\", nil, 0},\n\t{struct{}{}, \"Foo\", nil, 0},\n\t{S0{A: 'a'}, \"A\", []int{0}, 'a'},\n\t{S0{}, \"D\", nil, 0},\n\t{S1{S0: S0{A: 'a'}}, \"A\", []int{1, 0}, 'a'},\n\t{S1{B: 'b'}, \"B\", []int{0}, 'b'},\n\t{S1{}, \"S0\", []int{1}, 0},\n\t{S1{S0: S0{C: 'c'}}, \"C\", []int{1, 2}, 'c'},\n\t{S2{A: 'a'}, \"A\", []int{0}, 'a'},\n\t{S2{}, \"S1\", []int{1}, 0},\n\t{S2{S1: &S1{B: 'b'}}, \"B\", []int{1, 0}, 'b'},\n\t{S2{S1: &S1{S0: S0{C: 'c'}}}, \"C\", []int{1, 1, 2}, 'c'},\n\t{S2{}, \"D\", nil, 0},\n\t{S3{}, \"S1\", nil, 0},\n\t{S3{S2: S2{A: 'a'}}, \"A\", []int{1, 0}, 'a'},\n\t{S3{}, \"B\", nil, 0},\n\t{S3{D: 'd'}, \"D\", []int{2}, 0},\n\t{S3{E: 'e'}, \"E\", []int{3}, 'e'},\n\t{S4{A: 'a'}, \"A\", []int{1}, 'a'},\n\t{S4{}, \"B\", nil, 0},\n\t{S5{}, \"X\", nil, 0},\n\t{S5{}, \"Y\", []int{2, 0, 1}, 0},\n\t{S10{}, \"X\", nil, 0},\n\t{S10{}, \"Y\", []int{2, 0, 0, 1}, 0},\n\t{S14{}, \"X\", nil, 0},\n}\n\nfunc TestFieldByIndex(t *testing.T) {\n\tfor _, test := range fieldTests {\n\t\ts := TypeOf(test.s)\n\t\tf := s.FieldByIndex(test.index)\n\t\tif f.Name != \"\" {\n\t\t\tif test.index != nil {\n\t\t\t\tif f.Name != test.name {\n\t\t\t\t\tt.Errorf(\"%s.%s found; want %s\", s.Name(), f.Name, test.name)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tt.Errorf(\"%s.%s found\", s.Name(), f.Name)\n\t\t\t}\n\t\t} else if len(test.index) > 0 {\n\t\t\tt.Errorf(\"%s.%s not found\", s.Name(), test.name)\n\t\t}\n\n\t\tif test.value != 0 {\n\t\t\tv := ValueOf(test.s).FieldByIndex(test.index)\n\t\t\tif v.IsValid() {\n\t\t\t\tif x, ok := v.Interface().(int); ok {\n\t\t\t\t\tif x != test.value {\n\t\t\t\t\t\tt.Errorf(\"%s%v is %d; want %d\", s.Name(), test.index, x, test.value)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tt.Errorf(\"%s%v value not an int\", s.Name(), test.index)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tt.Errorf(\"%s%v value not found\", s.Name(), test.index)\n\t\t\t}\n\t\t}\n\t}\n}\n\n/*\n\nfunc TestFieldByName(t *testing.T) {\n\tfor _, test := range fieldTests {\n\t\ts := TypeOf(test.s)\n\t\tf, found := s.FieldByName(test.name)\n\t\tif found {\n\t\t\tif test.index != nil {\n\t\t\t\t// Verify field depth and index.\n\t\t\t\tif len(f.Index) != len(test.index) {\n\t\t\t\t\tt.Errorf(\"%s.%s depth %d; want %d: %v vs %v\", s.Name(), test.name, len(f.Index), len(test.index), f.Index, test.index)\n\t\t\t\t} else {\n\t\t\t\t\tfor i, x := range f.Index {\n\t\t\t\t\t\tif x != test.index[i] {\n\t\t\t\t\t\t\tt.Errorf(\"%s.%s.Index[%d] is %d; want %d\", s.Name(), test.name, i, x, test.index[i])\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tt.Errorf(\"%s.%s found\", s.Name(), f.Name)\n\t\t\t}\n\t\t} else if len(test.index) > 0 {\n\t\t\tt.Errorf(\"%s.%s not found\", s.Name(), test.name)\n\t\t}\n\n\t\tif test.value != 0 {\n\t\t\tv := ValueOf(test.s).FieldByName(test.name)\n\t\t\tif v.IsValid() {\n\t\t\t\tif x, ok := v.Interface().(int); ok {\n\t\t\t\t\tif x != test.value {\n\t\t\t\t\t\tt.Errorf(\"%s.%s is %d; want %d\", s.Name(), test.name, x, test.value)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tt.Errorf(\"%s.%s value not an int\", s.Name(), test.name)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tt.Errorf(\"%s.%s value not found\", s.Name(), test.name)\n\t\t\t}\n\t\t}\n\t}\n}\n\n*/\n\nfunc TestImportPath(t *testing.T) {\n\ttests := []struct {\n\t\tt    Type\n\t\tpath string\n\t}{\n\t\t{TypeOf(&base64.Encoding{}).Elem(), \"encoding/base64\"},\n\t\t{TypeOf(int(0)), \"\"},\n\t\t{TypeOf(int8(0)), \"\"},\n\t\t{TypeOf(int16(0)), \"\"},\n\t\t{TypeOf(int32(0)), \"\"},\n\t\t{TypeOf(int64(0)), \"\"},\n\t\t{TypeOf(uint(0)), \"\"},\n\t\t{TypeOf(uint8(0)), \"\"},\n\t\t{TypeOf(uint16(0)), \"\"},\n\t\t{TypeOf(uint32(0)), \"\"},\n\t\t{TypeOf(uint64(0)), \"\"},\n\t\t{TypeOf(uintptr(0)), \"\"},\n\t\t{TypeOf(float32(0)), \"\"},\n\t\t{TypeOf(float64(0)), \"\"},\n\t\t{TypeOf(complex64(0)), \"\"},\n\t\t{TypeOf(complex128(0)), \"\"},\n\t\t{TypeOf(byte(0)), \"\"},\n\t\t{TypeOf(rune(0)), \"\"},\n\t\t{TypeOf([]byte(nil)), \"\"},\n\t\t{TypeOf([]rune(nil)), \"\"},\n\t\t{TypeOf(string(\"\")), \"\"},\n\t\t{TypeOf((*any)(nil)).Elem(), \"\"},\n\t\t{TypeOf((*byte)(nil)), \"\"},\n\t\t{TypeOf((*rune)(nil)), \"\"},\n\t\t{TypeOf((*int64)(nil)), \"\"},\n\t\t{TypeOf(map[string]int{}), \"\"},\n\t\t{TypeOf((*error)(nil)).Elem(), \"\"},\n\t\t{TypeOf((*Point)(nil)), \"\"},\n\t\t{TypeOf((*Point)(nil)).Elem(), \"reflect_test\"},\n\t}\n\tfor _, test := range tests {\n\t\tif path := test.t.PkgPath(); path != test.path {\n\t\t\tt.Errorf(\"%v.PkgPath() = %q, want %q\", test.t, path, test.path)\n\t\t}\n\t}\n}\n\nfunc TestFieldPkgPath(t *testing.T) {\n\ttype x int\n\ttyp := TypeOf(struct {\n\t\tExported   string\n\t\tunexported string\n\t\tOtherPkgFields\n\t\tint // issue 21702\n\t\t*x  // issue 21122\n\t}{})\n\n\ttype pkgpathTest struct {\n\t\tindex    []int\n\t\tpkgPath  string\n\t\tembedded bool\n\t\texported bool\n\t}\n\n\tcheckPkgPath := func(name string, s []pkgpathTest) {\n\t\tfor _, test := range s {\n\t\t\tf := typ.FieldByIndex(test.index)\n\t\t\tif got, want := f.PkgPath, test.pkgPath; got != want {\n\t\t\t\tt.Errorf(\"%s: Field(%d).PkgPath = %q, want %q\", name, test.index, got, want)\n\t\t\t}\n\t\t\tif got, want := f.Anonymous, test.embedded; got != want {\n\t\t\t\tt.Errorf(\"%s: Field(%d).Anonymous = %v, want %v\", name, test.index, got, want)\n\t\t\t}\n\t\t\tif got, want := f.IsExported(), test.exported; got != want {\n\t\t\t\tt.Errorf(\"%s: Field(%d).IsExported = %v, want %v\", name, test.index, got, want)\n\t\t\t}\n\t\t}\n\t}\n\n\tcheckPkgPath(\"testStruct\", []pkgpathTest{\n\t\t{[]int{0}, \"\", false, true},              // Exported\n\t\t{[]int{1}, \"reflect_test\", false, false}, // unexported\n\t\t{[]int{2}, \"\", true, true},               // OtherPkgFields\n\t\t{[]int{2, 0}, \"\", false, true},           // OtherExported\n\t\t{[]int{2, 1}, \"reflect\", false, false},   // otherUnexported\n\t\t{[]int{3}, \"reflect_test\", true, false},  // int\n\t\t{[]int{4}, \"reflect_test\", true, false},  // *x\n\t})\n\n\ttype localOtherPkgFields OtherPkgFields\n\ttyp = TypeOf(localOtherPkgFields{})\n\tcheckPkgPath(\"localOtherPkgFields\", []pkgpathTest{\n\t\t{[]int{0}, \"\", false, true},         // OtherExported\n\t\t{[]int{1}, \"reflect\", false, false}, // otherUnexported\n\t})\n}\n\n/*\n\nfunc TestMethodPkgPath(t *testing.T) {\n\ttype I interface {\n\t\tx()\n\t\tX()\n\t}\n\ttyp := TypeOf((*interface {\n\t\tI\n\t\ty()\n\t\tY()\n\t})(nil)).Elem()\n\n\ttests := []struct {\n\t\tname     string\n\t\tpkgPath  string\n\t\texported bool\n\t}{\n\t\t{\"X\", \"\", true},\n\t\t{\"Y\", \"\", true},\n\t\t{\"x\", \"reflect_test\", false},\n\t\t{\"y\", \"reflect_test\", false},\n\t}\n\n\tfor _, test := range tests {\n\t\tm, _ := typ.MethodByName(test.name)\n\t\tif got, want := m.PkgPath, test.pkgPath; got != want {\n\t\t\tt.Errorf(\"MethodByName(%q).PkgPath = %q, want %q\", test.name, got, want)\n\t\t}\n\t\tif got, want := m.IsExported(), test.exported; got != want {\n\t\t\tt.Errorf(\"MethodByName(%q).IsExported = %v, want %v\", test.name, got, want)\n\t\t}\n\t}\n}\n\nfunc TestVariadicType(t *testing.T) {\n\t// Test example from Type documentation.\n\tvar f func(x int, y ...float64)\n\ttyp := TypeOf(f)\n\tif typ.NumIn() == 2 && typ.In(0) == TypeOf(int(0)) {\n\t\tsl := typ.In(1)\n\t\tif sl.Kind() == Slice {\n\t\t\tif sl.Elem() == TypeOf(0.0) {\n\t\t\t\t// ok\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\n\t// Failed\n\tt.Errorf(\"want NumIn() = 2, In(0) = int, In(1) = []float64\")\n\ts := fmt.Sprintf(\"have NumIn() = %d\", typ.NumIn())\n\tfor i := 0; i < typ.NumIn(); i++ {\n\t\ts += fmt.Sprintf(\", In(%d) = %s\", i, typ.In(i))\n\t}\n\tt.Error(s)\n}\n\ntype inner struct {\n\tx int\n}\n\ntype outer struct {\n\ty int\n\tinner\n}\n\nfunc (*inner) M() {}\nfunc (*outer) M() {}\n\nfunc TestNestedMethods(t *testing.T) {\n\ttyp := TypeOf((*outer)(nil))\n\tif typ.NumMethod() != 1 || typ.Method(0).Func.UnsafePointer() != ValueOf((*outer).M).UnsafePointer() {\n\t\tt.Errorf(\"Wrong method table for outer: (M=%p)\", (*outer).M)\n\t\tfor i := 0; i < typ.NumMethod(); i++ {\n\t\t\tm := typ.Method(i)\n\t\t\tt.Errorf(\"\\t%d: %s %p\\n\", i, m.Name, m.Func.UnsafePointer())\n\t\t}\n\t}\n}\n\n*/\n\ntype unexp struct{}\n\nfunc (*unexp) f() (int32, int8) { return 7, 7 }\nfunc (*unexp) g() (int64, int8) { return 8, 8 }\n\ntype unexpI interface {\n\tf() (int32, int8)\n}\n\nvar unexpi unexpI = new(unexp)\n\nfunc TestUnexportedMethods(t *testing.T) {\n\ttyp := TypeOf(unexpi)\n\n\tif got := typ.NumMethod(); got != 0 {\n\t\tt.Errorf(\"NumMethod=%d, want 0 satisfied methods\", got)\n\t}\n}\n\ntype InnerInt struct {\n\tX int\n}\n\ntype OuterInt struct {\n\tY int\n\tInnerInt\n}\n\nfunc (i *InnerInt) M() int {\n\treturn i.X\n}\n\n/*\n\nfunc TestEmbeddedMethods(t *testing.T) {\n\ttyp := TypeOf((*OuterInt)(nil))\n\tif typ.NumMethod() != 1 || typ.Method(0).Func.UnsafePointer() != ValueOf((*OuterInt).M).UnsafePointer() {\n\t\tt.Errorf(\"Wrong method table for OuterInt: (m=%p)\", (*OuterInt).M)\n\t\tfor i := 0; i < typ.NumMethod(); i++ {\n\t\t\tm := typ.Method(i)\n\t\t\tt.Errorf(\"\\t%d: %s %p\\n\", i, m.Name, m.Func.UnsafePointer())\n\t\t}\n\t}\n\n\ti := &InnerInt{3}\n\tif v := ValueOf(i).Method(0).Call(nil)[0].Int(); v != 3 {\n\t\tt.Errorf(\"i.M() = %d, want 3\", v)\n\t}\n\n\to := &OuterInt{1, InnerInt{2}}\n\tif v := ValueOf(o).Method(0).Call(nil)[0].Int(); v != 2 {\n\t\tt.Errorf(\"i.M() = %d, want 2\", v)\n\t}\n\n\tf := (*OuterInt).M\n\tif v := f(o); v != 2 {\n\t\tt.Errorf(\"f(o) = %d, want 2\", v)\n\t}\n}\n\n*/\n\ntype FuncDDD func(...any) error\n\nfunc (f FuncDDD) M() {}\n\nfunc TestNumMethodOnDDD(t *testing.T) {\n\trv := ValueOf((FuncDDD)(nil))\n\tif n := rv.NumMethod(); n != 1 {\n\t\tt.Fatalf(\"NumMethod()=%d, want 1\", n)\n\t}\n}\n\n/*\nfunc TestPtrTo(t *testing.T) {\n\t// This block of code means that the ptrToThis field of the\n\t// reflect data for *unsafe.Pointer is non zero, see\n\t// https://golang.org/issue/19003\n\tvar x unsafe.Pointer\n\tvar y = &x\n\tvar z = &y\n\n\tvar i int\n\n\ttyp := TypeOf(z)\n\tfor i = 0; i < 100; i++ {\n\t\ttyp = PointerTo(typ)\n\t}\n\tfor i = 0; i < 100; i++ {\n\t\ttyp = typ.Elem()\n\t}\n\tif typ != TypeOf(z) {\n\t\tt.Errorf(\"after 100 PointerTo and Elem, have %s, want %s\", typ, TypeOf(z))\n\t}\n}\n\nfunc TestPtrToGC(t *testing.T) {\n\ttype T *uintptr\n\ttt := TypeOf(T(nil))\n\tpt := PointerTo(tt)\n\tconst n = 100\n\tvar x []any\n\tfor i := 0; i < n; i++ {\n\t\tv := New(pt)\n\t\tp := new(*uintptr)\n\t\t*p = new(uintptr)\n\t\t**p = uintptr(i)\n\t\tv.Elem().Set(ValueOf(p).Convert(pt))\n\t\tx = append(x, v.Interface())\n\t}\n\truntime.GC()\n\n\tfor i, xi := range x {\n\t\tk := ValueOf(xi).Elem().Elem().Elem().Interface().(uintptr)\n\t\tif k != uintptr(i) {\n\t\t\tt.Errorf(\"lost x[%d] = %d, want %d\", i, k, i)\n\t\t}\n\t}\n}\n\n*/\n\nfunc TestAddr(t *testing.T) {\n\tvar p struct {\n\t\tX, Y int\n\t}\n\n\tv := ValueOf(&p)\n\tv = v.Elem()\n\tv = v.Addr()\n\tv = v.Elem()\n\tv = v.Field(0)\n\tv.SetInt(2)\n\tif p.X != 2 {\n\t\tt.Errorf(\"Addr.Elem.Set failed to set value\")\n\t}\n\n\t// Again but take address of the ValueOf value.\n\t// Exercises generation of PtrTypes not present in the binary.\n\tq := &p\n\tv = ValueOf(&q).Elem()\n\tv = v.Addr()\n\tv = v.Elem()\n\tv = v.Elem()\n\tv = v.Addr()\n\tv = v.Elem()\n\tv = v.Field(0)\n\tv.SetInt(3)\n\tif p.X != 3 {\n\t\tt.Errorf(\"Addr.Elem.Set failed to set value\")\n\t}\n\n\t// Starting without pointer we should get changed value\n\t// in interface.\n\tqq := p\n\tv = ValueOf(&qq).Elem()\n\tv0 := v\n\tv = v.Addr()\n\tv = v.Elem()\n\tv = v.Field(0)\n\tv.SetInt(4)\n\tif p.X != 3 { // should be unchanged from last time\n\t\tt.Errorf(\"somehow value Set changed original p\")\n\t}\n\tp = v0.Interface().(struct {\n\t\tX, Y int\n\t})\n\tif p.X != 4 {\n\t\tt.Errorf(\"Addr.Elem.Set valued to set value in top value\")\n\t}\n\n\t// Verify that taking the address of a type gives us a pointer\n\t// which we can convert back using the usual interface\n\t// notation.\n\tvar s struct {\n\t\tB *bool\n\t}\n\tps := ValueOf(&s).Elem().Field(0).Addr().Interface()\n\t*(ps.(**bool)) = new(bool)\n\tif s.B == nil {\n\t\tt.Errorf(\"Addr.Interface direct assignment failed\")\n\t}\n}\n\nfunc noAlloc(t *testing.T, n int, f func(int)) {\n\tif testing.Short() {\n\t\tt.Skip(\"skipping malloc count in short mode\")\n\t}\n\tif runtime.GOMAXPROCS(0) > 1 {\n\t\tt.Skip(\"skipping; GOMAXPROCS>1\")\n\t}\n\ti := -1\n\tallocs := testing.AllocsPerRun(n, func() {\n\t\tf(i)\n\t\ti++\n\t})\n\tif allocs > 0 {\n\t\tt.Errorf(\"%d iterations: got %v mallocs, want 0\", n, allocs)\n\t}\n}\n\nfunc TestAllocations(t *testing.T) {\n\tnoAlloc(t, 100, func(j int) {\n\t\tvar i any\n\t\tvar v Value\n\n\t\t// We can uncomment this when compiler escape analysis\n\t\t// is good enough to see that the integer assigned to i\n\t\t// does not escape and therefore need not be allocated.\n\t\t//\n\t\t// i = 42 + j\n\t\t// v = ValueOf(i)\n\t\t// if int(v.Int()) != 42+j {\n\t\t// \tpanic(\"wrong int\")\n\t\t// }\n\n\t\ti = func(j int) int { return j }\n\t\tv = ValueOf(i)\n\t\tif v.Interface().(func(int) int)(j) != j {\n\t\t\tpanic(\"wrong result\")\n\t\t}\n\t})\n}\n\nfunc TestSmallNegativeInt(t *testing.T) {\n\ti := int16(-1)\n\tv := ValueOf(i)\n\tif v.Int() != -1 {\n\t\tt.Errorf(\"int16(-1).Int() returned %v\", v.Int())\n\t}\n}\n\nfunc TestIndex(t *testing.T) {\n\txs := []byte{1, 2, 3, 4, 5, 6, 7, 8}\n\tv := ValueOf(xs).Index(3).Interface().(byte)\n\tif v != xs[3] {\n\t\tt.Errorf(\"xs.Index(3) = %v; expected %v\", v, xs[3])\n\t}\n\txa := [8]byte{10, 20, 30, 40, 50, 60, 70, 80}\n\tv = ValueOf(xa).Index(2).Interface().(byte)\n\tif v != xa[2] {\n\t\tt.Errorf(\"xa.Index(2) = %v; expected %v\", v, xa[2])\n\t}\n\ts := \"0123456789\"\n\tv = ValueOf(s).Index(3).Interface().(byte)\n\tif v != s[3] {\n\t\tt.Errorf(\"s.Index(3) = %v; expected %v\", v, s[3])\n\t}\n}\n\n/*\n\nfunc TestSlice(t *testing.T) {\n\txs := []int{1, 2, 3, 4, 5, 6, 7, 8}\n\tv := ValueOf(xs).Slice(3, 5).Interface().([]int)\n\tif len(v) != 2 {\n\t\tt.Errorf(\"len(xs.Slice(3, 5)) = %d\", len(v))\n\t}\n\tif cap(v) != 5 {\n\t\tt.Errorf(\"cap(xs.Slice(3, 5)) = %d\", cap(v))\n\t}\n\tif !DeepEqual(v[0:5], xs[3:]) {\n\t\tt.Errorf(\"xs.Slice(3, 5)[0:5] = %v\", v[0:5])\n\t}\n\txa := [8]int{10, 20, 30, 40, 50, 60, 70, 80}\n\tv = ValueOf(&xa).Elem().Slice(2, 5).Interface().([]int)\n\tif len(v) != 3 {\n\t\tt.Errorf(\"len(xa.Slice(2, 5)) = %d\", len(v))\n\t}\n\tif cap(v) != 6 {\n\t\tt.Errorf(\"cap(xa.Slice(2, 5)) = %d\", cap(v))\n\t}\n\tif !DeepEqual(v[0:6], xa[2:]) {\n\t\tt.Errorf(\"xs.Slice(2, 5)[0:6] = %v\", v[0:6])\n\t}\n\ts := \"0123456789\"\n\tvs := ValueOf(s).Slice(3, 5).Interface().(string)\n\tif vs != s[3:5] {\n\t\tt.Errorf(\"s.Slice(3, 5) = %q; expected %q\", vs, s[3:5])\n\t}\n\n\trv := ValueOf(&xs).Elem()\n\trv = rv.Slice(3, 4)\n\tptr2 := rv.UnsafePointer()\n\trv = rv.Slice(5, 5)\n\tptr3 := rv.UnsafePointer()\n\tif ptr3 != ptr2 {\n\t\tt.Errorf(\"xs.Slice(3,4).Slice3(5,5).UnsafePointer() = %p, want %p\", ptr3, ptr2)\n\t}\n}\n\nfunc TestSlice3(t *testing.T) {\n\txs := []int{1, 2, 3, 4, 5, 6, 7, 8}\n\tv := ValueOf(xs).Slice3(3, 5, 7).Interface().([]int)\n\tif len(v) != 2 {\n\t\tt.Errorf(\"len(xs.Slice3(3, 5, 7)) = %d\", len(v))\n\t}\n\tif cap(v) != 4 {\n\t\tt.Errorf(\"cap(xs.Slice3(3, 5, 7)) = %d\", cap(v))\n\t}\n\tif !DeepEqual(v[0:4], xs[3:7:7]) {\n\t\tt.Errorf(\"xs.Slice3(3, 5, 7)[0:4] = %v\", v[0:4])\n\t}\n\trv := ValueOf(&xs).Elem()\n\tshouldPanic(\"Slice3\", func() { rv.Slice3(1, 2, 1) })\n\tshouldPanic(\"Slice3\", func() { rv.Slice3(1, 1, 11) })\n\tshouldPanic(\"Slice3\", func() { rv.Slice3(2, 2, 1) })\n\n\txa := [8]int{10, 20, 30, 40, 50, 60, 70, 80}\n\tv = ValueOf(&xa).Elem().Slice3(2, 5, 6).Interface().([]int)\n\tif len(v) != 3 {\n\t\tt.Errorf(\"len(xa.Slice(2, 5, 6)) = %d\", len(v))\n\t}\n\tif cap(v) != 4 {\n\t\tt.Errorf(\"cap(xa.Slice(2, 5, 6)) = %d\", cap(v))\n\t}\n\tif !DeepEqual(v[0:4], xa[2:6:6]) {\n\t\tt.Errorf(\"xs.Slice(2, 5, 6)[0:4] = %v\", v[0:4])\n\t}\n\trv = ValueOf(&xa).Elem()\n\tshouldPanic(\"Slice3\", func() { rv.Slice3(1, 2, 1) })\n\tshouldPanic(\"Slice3\", func() { rv.Slice3(1, 1, 11) })\n\tshouldPanic(\"Slice3\", func() { rv.Slice3(2, 2, 1) })\n\n\ts := \"hello world\"\n\trv = ValueOf(&s).Elem()\n\tshouldPanic(\"Slice3\", func() { rv.Slice3(1, 2, 3) })\n\n\trv = ValueOf(&xs).Elem()\n\trv = rv.Slice3(3, 5, 7)\n\tptr2 := rv.UnsafePointer()\n\trv = rv.Slice3(4, 4, 4)\n\tptr3 := rv.UnsafePointer()\n\tif ptr3 != ptr2 {\n\t\tt.Errorf(\"xs.Slice3(3,5,7).Slice3(4,4,4).UnsafePointer() = %p, want %p\", ptr3, ptr2)\n\t}\n}\n\nfunc TestSetLenCap(t *testing.T) {\n\txs := []int{1, 2, 3, 4, 5, 6, 7, 8}\n\txa := [8]int{10, 20, 30, 40, 50, 60, 70, 80}\n\n\tvs := ValueOf(&xs).Elem()\n\tshouldPanic(\"SetLen\", func() { vs.SetLen(10) })\n\tshouldPanic(\"SetCap\", func() { vs.SetCap(10) })\n\tshouldPanic(\"SetLen\", func() { vs.SetLen(-1) })\n\tshouldPanic(\"SetCap\", func() { vs.SetCap(-1) })\n\tshouldPanic(\"SetCap\", func() { vs.SetCap(6) }) // smaller than len\n\tvs.SetLen(5)\n\tif len(xs) != 5 || cap(xs) != 8 {\n\t\tt.Errorf(\"after SetLen(5), len, cap = %d, %d, want 5, 8\", len(xs), cap(xs))\n\t}\n\tvs.SetCap(6)\n\tif len(xs) != 5 || cap(xs) != 6 {\n\t\tt.Errorf(\"after SetCap(6), len, cap = %d, %d, want 5, 6\", len(xs), cap(xs))\n\t}\n\tvs.SetCap(5)\n\tif len(xs) != 5 || cap(xs) != 5 {\n\t\tt.Errorf(\"after SetCap(5), len, cap = %d, %d, want 5, 5\", len(xs), cap(xs))\n\t}\n\tshouldPanic(\"SetCap\", func() { vs.SetCap(4) }) // smaller than len\n\tshouldPanic(\"SetLen\", func() { vs.SetLen(6) }) // bigger than cap\n\n\tva := ValueOf(&xa).Elem()\n\tshouldPanic(\"SetLen\", func() { va.SetLen(8) })\n\tshouldPanic(\"SetCap\", func() { va.SetCap(8) })\n}\n\nfunc TestVariadic(t *testing.T) {\n\tvar b strings.Builder\n\tV := ValueOf\n\n\tb.Reset()\n\tV(fmt.Fprintf).Call([]Value{V(&b), V(\"%s, %d world\"), V(\"hello\"), V(42)})\n\tif b.String() != \"hello, 42 world\" {\n\t\tt.Errorf(\"after Fprintf Call: %q != %q\", b.String(), \"hello 42 world\")\n\t}\n\n\tb.Reset()\n\tV(fmt.Fprintf).CallSlice([]Value{V(&b), V(\"%s, %d world\"), V([]any{\"hello\", 42})})\n\tif b.String() != \"hello, 42 world\" {\n\t\tt.Errorf(\"after Fprintf CallSlice: %q != %q\", b.String(), \"hello 42 world\")\n\t}\n}\n\nfunc TestFuncArg(t *testing.T) {\n\tf1 := func(i int, f func(int) int) int { return f(i) }\n\tf2 := func(i int) int { return i + 1 }\n\tr := ValueOf(f1).Call([]Value{ValueOf(100), ValueOf(f2)})\n\tif r[0].Int() != 101 {\n\t\tt.Errorf(\"function returned %d, want 101\", r[0].Int())\n\t}\n}\n\nfunc TestStructArg(t *testing.T) {\n\ttype padded struct {\n\t\tB string\n\t\tC int32\n\t}\n\tvar (\n\t\tgotA  padded\n\t\tgotB  uint32\n\t\twantA = padded{\"3\", 4}\n\t\twantB = uint32(5)\n\t)\n\tf := func(a padded, b uint32) {\n\t\tgotA, gotB = a, b\n\t}\n\tValueOf(f).Call([]Value{ValueOf(wantA), ValueOf(wantB)})\n\tif gotA != wantA || gotB != wantB {\n\t\tt.Errorf(\"function called with (%v, %v), want (%v, %v)\", gotA, gotB, wantA, wantB)\n\t}\n}\n\n*/\n\nvar tagGetTests = []struct {\n\tTag   StructTag\n\tKey   string\n\tValue string\n}{\n\t{`protobuf:\"PB(1,2)\"`, `protobuf`, `PB(1,2)`},\n\t{`protobuf:\"PB(1,2)\"`, `foo`, ``},\n\t{`protobuf:\"PB(1,2)\"`, `rotobuf`, ``},\n\t{`protobuf:\"PB(1,2)\" json:\"name\"`, `json`, `name`},\n\t{`protobuf:\"PB(1,2)\" json:\"name\"`, `protobuf`, `PB(1,2)`},\n\t{`k0:\"values contain spaces\" k1:\"and\\ttabs\"`, \"k0\", \"values contain spaces\"},\n\t{`k0:\"values contain spaces\" k1:\"and\\ttabs\"`, \"k1\", \"and\\ttabs\"},\n}\n\nfunc TestTagGet(t *testing.T) {\n\tfor _, tt := range tagGetTests {\n\t\tif v := tt.Tag.Get(tt.Key); v != tt.Value {\n\t\t\tt.Errorf(\"StructTag(%#q).Get(%#q) = %#q, want %#q\", tt.Tag, tt.Key, v, tt.Value)\n\t\t}\n\t}\n}\n\nfunc TestBytes(t *testing.T) {\n\tshouldPanic(\"on int Value\", func() { ValueOf(0).Bytes() })\n\tshouldPanic(\"of non-byte slice\", func() { ValueOf([]string{}).Bytes() })\n\n\ttype S []byte\n\tx := S{1, 2, 3, 4}\n\ty := ValueOf(x).Bytes()\n\tif !bytes.Equal(x, y) {\n\t\tt.Fatalf(\"ValueOf(%v).Bytes() = %v\", x, y)\n\t}\n\tif &x[0] != &y[0] {\n\t\tt.Errorf(\"ValueOf(%p).Bytes() = %p\", &x[0], &y[0])\n\t}\n\n\ttype A [4]byte\n\ta := A{1, 2, 3, 4}\n\tshouldPanic(\"unaddressable\", func() { ValueOf(a).Bytes() })\n\tshouldPanic(\"on ptr Value\", func() { ValueOf(&a).Bytes() })\n\tb := ValueOf(&a).Elem().Bytes()\n\tif !bytes.Equal(a[:], y) {\n\t\tt.Fatalf(\"ValueOf(%v).Bytes() = %v\", a, b)\n\t}\n\tif &a[0] != &b[0] {\n\t\tt.Errorf(\"ValueOf(%p).Bytes() = %p\", &a[0], &b[0])\n\t}\n\n\t// Per issue #24746, it was decided that Bytes can be called on byte slices\n\t// that normally cannot be converted from per Go language semantics.\n\ttype B byte\n\ttype SB []B\n\ttype AB [4]B\n\tValueOf([]B{1, 2, 3, 4}).Bytes()  // should not panic\n\tValueOf(new([4]B)).Elem().Bytes() // should not panic\n\tValueOf(SB{1, 2, 3, 4}).Bytes()   // should not panic\n\tValueOf(new(AB)).Elem().Bytes()   // should not panic\n}\n\nfunc TestSetBytes(t *testing.T) {\n\ttype B []byte\n\tvar x B\n\ty := []byte{1, 2, 3, 4}\n\tValueOf(&x).Elem().SetBytes(y)\n\tif !bytes.Equal(x, y) {\n\t\tt.Fatalf(\"ValueOf(%v).Bytes() = %v\", x, y)\n\t}\n\tif &x[0] != &y[0] {\n\t\tt.Errorf(\"ValueOf(%p).Bytes() = %p\", &x[0], &y[0])\n\t}\n}\n\ntype Private struct {\n\tx int\n\ty **int\n\tZ int\n}\n\nfunc (p *Private) m() {\n}\n\ntype private struct {\n\tZ int\n\tz int\n\tS string\n\tA [1]Private\n\tT []Private\n}\n\nfunc (p *private) P() {\n}\n\ntype Public struct {\n\tX int\n\tY **int\n\tprivate\n}\n\nfunc (p *Public) M() {\n}\n\n/*\n\nfunc TestUnexported(t *testing.T) {\n\tvar pub Public\n\tpub.S = \"S\"\n\tpub.T = pub.A[:]\n\tv := ValueOf(&pub)\n\tisValid(v.Elem().Field(0))\n\tisValid(v.Elem().Field(1))\n\tisValid(v.Elem().Field(2))\n\tisValid(v.Elem().FieldByName(\"X\"))\n\tisValid(v.Elem().FieldByName(\"Y\"))\n\tisValid(v.Elem().FieldByName(\"Z\"))\n\tisValid(v.Type().Method(0).Func)\n\tm, _ := v.Type().MethodByName(\"M\")\n\tisValid(m.Func)\n\tm, _ = v.Type().MethodByName(\"P\")\n\tisValid(m.Func)\n\tisNonNil(v.Elem().Field(0).Interface())\n\tisNonNil(v.Elem().Field(1).Interface())\n\tisNonNil(v.Elem().Field(2).Field(2).Index(0))\n\tisNonNil(v.Elem().FieldByName(\"X\").Interface())\n\tisNonNil(v.Elem().FieldByName(\"Y\").Interface())\n\tisNonNil(v.Elem().FieldByName(\"Z\").Interface())\n\tisNonNil(v.Elem().FieldByName(\"S\").Index(0).Interface())\n\tisNonNil(v.Type().Method(0).Func.Interface())\n\tm, _ = v.Type().MethodByName(\"P\")\n\tisNonNil(m.Func.Interface())\n\n\tvar priv Private\n\tv = ValueOf(&priv)\n\tisValid(v.Elem().Field(0))\n\tisValid(v.Elem().Field(1))\n\tisValid(v.Elem().FieldByName(\"x\"))\n\tisValid(v.Elem().FieldByName(\"y\"))\n\tshouldPanic(\"Interface\", func() { v.Elem().Field(0).Interface() })\n\tshouldPanic(\"Interface\", func() { v.Elem().Field(1).Interface() })\n\tshouldPanic(\"Interface\", func() { v.Elem().FieldByName(\"x\").Interface() })\n\tshouldPanic(\"Interface\", func() { v.Elem().FieldByName(\"y\").Interface() })\n\tshouldPanic(\"Method\", func() { v.Type().Method(0) })\n}\n\nfunc TestSetPanic(t *testing.T) {\n\tok := func(f func()) { f() }\n\tbad := func(f func()) { shouldPanic(\"Set\", f) }\n\tclear := func(v Value) { v.Set(Zero(v.Type())) }\n\n\ttype t0 struct {\n\t\tW int\n\t}\n\n\ttype t1 struct {\n\t\tY int\n\t\tt0\n\t}\n\n\ttype T2 struct {\n\t\tZ       int\n\t\tnamedT0 t0\n\t}\n\n\ttype T struct {\n\t\tX int\n\t\tt1\n\t\tT2\n\t\tNamedT1 t1\n\t\tNamedT2 T2\n\t\tnamedT1 t1\n\t\tnamedT2 T2\n\t}\n\n\t// not addressable\n\tv := ValueOf(T{})\n\tbad(func() { clear(v.Field(0)) })                   // .X\n\tbad(func() { clear(v.Field(1)) })                   // .t1\n\tbad(func() { clear(v.Field(1).Field(0)) })          // .t1.Y\n\tbad(func() { clear(v.Field(1).Field(1)) })          // .t1.t0\n\tbad(func() { clear(v.Field(1).Field(1).Field(0)) }) // .t1.t0.W\n\tbad(func() { clear(v.Field(2)) })                   // .T2\n\tbad(func() { clear(v.Field(2).Field(0)) })          // .T2.Z\n\tbad(func() { clear(v.Field(2).Field(1)) })          // .T2.namedT0\n\tbad(func() { clear(v.Field(2).Field(1).Field(0)) }) // .T2.namedT0.W\n\tbad(func() { clear(v.Field(3)) })                   // .NamedT1\n\tbad(func() { clear(v.Field(3).Field(0)) })          // .NamedT1.Y\n\tbad(func() { clear(v.Field(3).Field(1)) })          // .NamedT1.t0\n\tbad(func() { clear(v.Field(3).Field(1).Field(0)) }) // .NamedT1.t0.W\n\tbad(func() { clear(v.Field(4)) })                   // .NamedT2\n\tbad(func() { clear(v.Field(4).Field(0)) })          // .NamedT2.Z\n\tbad(func() { clear(v.Field(4).Field(1)) })          // .NamedT2.namedT0\n\tbad(func() { clear(v.Field(4).Field(1).Field(0)) }) // .NamedT2.namedT0.W\n\tbad(func() { clear(v.Field(5)) })                   // .namedT1\n\tbad(func() { clear(v.Field(5).Field(0)) })          // .namedT1.Y\n\tbad(func() { clear(v.Field(5).Field(1)) })          // .namedT1.t0\n\tbad(func() { clear(v.Field(5).Field(1).Field(0)) }) // .namedT1.t0.W\n\tbad(func() { clear(v.Field(6)) })                   // .namedT2\n\tbad(func() { clear(v.Field(6).Field(0)) })          // .namedT2.Z\n\tbad(func() { clear(v.Field(6).Field(1)) })          // .namedT2.namedT0\n\tbad(func() { clear(v.Field(6).Field(1).Field(0)) }) // .namedT2.namedT0.W\n\n\t// addressable\n\tv = ValueOf(&T{}).Elem()\n\tok(func() { clear(v.Field(0)) })                    // .X\n\tbad(func() { clear(v.Field(1)) })                   // .t1\n\tok(func() { clear(v.Field(1).Field(0)) })           // .t1.Y\n\tbad(func() { clear(v.Field(1).Field(1)) })          // .t1.t0\n\tok(func() { clear(v.Field(1).Field(1).Field(0)) })  // .t1.t0.W\n\tok(func() { clear(v.Field(2)) })                    // .T2\n\tok(func() { clear(v.Field(2).Field(0)) })           // .T2.Z\n\tbad(func() { clear(v.Field(2).Field(1)) })          // .T2.namedT0\n\tbad(func() { clear(v.Field(2).Field(1).Field(0)) }) // .T2.namedT0.W\n\tok(func() { clear(v.Field(3)) })                    // .NamedT1\n\tok(func() { clear(v.Field(3).Field(0)) })           // .NamedT1.Y\n\tbad(func() { clear(v.Field(3).Field(1)) })          // .NamedT1.t0\n\tok(func() { clear(v.Field(3).Field(1).Field(0)) })  // .NamedT1.t0.W\n\tok(func() { clear(v.Field(4)) })                    // .NamedT2\n\tok(func() { clear(v.Field(4).Field(0)) })           // .NamedT2.Z\n\tbad(func() { clear(v.Field(4).Field(1)) })          // .NamedT2.namedT0\n\tbad(func() { clear(v.Field(4).Field(1).Field(0)) }) // .NamedT2.namedT0.W\n\tbad(func() { clear(v.Field(5)) })                   // .namedT1\n\tbad(func() { clear(v.Field(5).Field(0)) })          // .namedT1.Y\n\tbad(func() { clear(v.Field(5).Field(1)) })          // .namedT1.t0\n\tbad(func() { clear(v.Field(5).Field(1).Field(0)) }) // .namedT1.t0.W\n\tbad(func() { clear(v.Field(6)) })                   // .namedT2\n\tbad(func() { clear(v.Field(6).Field(0)) })          // .namedT2.Z\n\tbad(func() { clear(v.Field(6).Field(1)) })          // .namedT2.namedT0\n\tbad(func() { clear(v.Field(6).Field(1).Field(0)) }) // .namedT2.namedT0.W\n}\n\n*/\n\ntype timp int\n\nfunc (t timp) W() {}\nfunc (t timp) Y() {}\nfunc (t timp) w() {}\nfunc (t timp) y() {}\n\n/*\n\nfunc TestCallPanic(t *testing.T) {\n\ttype t0 interface {\n\t\tW()\n\t\tw()\n\t}\n\ttype T1 interface {\n\t\tY()\n\t\ty()\n\t}\n\ttype T2 struct {\n\t\tT1\n\t\tt0\n\t}\n\ttype T struct {\n\t\tt0 // 0\n\t\tT1 // 1\n\n\t\tNamedT0 t0 // 2\n\t\tNamedT1 T1 // 3\n\t\tNamedT2 T2 // 4\n\n\t\tnamedT0 t0 // 5\n\t\tnamedT1 T1 // 6\n\t\tnamedT2 T2 // 7\n\t}\n\tok := func(f func()) { f() }\n\tbadCall := func(f func()) { shouldPanic(\"Call\", f) }\n\tbadMethod := func(f func()) { shouldPanic(\"Method\", f) }\n\tcall := func(v Value) { v.Call(nil) }\n\n\ti := timp(0)\n\tv := ValueOf(T{i, i, i, i, T2{i, i}, i, i, T2{i, i}})\n\tbadCall(func() { call(v.Field(0).Method(0)) })          // .t0.W\n\tbadCall(func() { call(v.Field(0).Elem().Method(0)) })   // .t0.W\n\tbadCall(func() { call(v.Field(0).Method(1)) })          // .t0.w\n\tbadMethod(func() { call(v.Field(0).Elem().Method(2)) }) // .t0.w\n\tok(func() { call(v.Field(1).Method(0)) })               // .T1.Y\n\tok(func() { call(v.Field(1).Elem().Method(0)) })        // .T1.Y\n\tbadCall(func() { call(v.Field(1).Method(1)) })          // .T1.y\n\tbadMethod(func() { call(v.Field(1).Elem().Method(2)) }) // .T1.y\n\n\tok(func() { call(v.Field(2).Method(0)) })               // .NamedT0.W\n\tok(func() { call(v.Field(2).Elem().Method(0)) })        // .NamedT0.W\n\tbadCall(func() { call(v.Field(2).Method(1)) })          // .NamedT0.w\n\tbadMethod(func() { call(v.Field(2).Elem().Method(2)) }) // .NamedT0.w\n\n\tok(func() { call(v.Field(3).Method(0)) })               // .NamedT1.Y\n\tok(func() { call(v.Field(3).Elem().Method(0)) })        // .NamedT1.Y\n\tbadCall(func() { call(v.Field(3).Method(1)) })          // .NamedT1.y\n\tbadMethod(func() { call(v.Field(3).Elem().Method(3)) }) // .NamedT1.y\n\n\tok(func() { call(v.Field(4).Field(0).Method(0)) })             // .NamedT2.T1.Y\n\tok(func() { call(v.Field(4).Field(0).Elem().Method(0)) })      // .NamedT2.T1.W\n\tbadCall(func() { call(v.Field(4).Field(1).Method(0)) })        // .NamedT2.t0.W\n\tbadCall(func() { call(v.Field(4).Field(1).Elem().Method(0)) }) // .NamedT2.t0.W\n\n\tbadCall(func() { call(v.Field(5).Method(0)) })          // .namedT0.W\n\tbadCall(func() { call(v.Field(5).Elem().Method(0)) })   // .namedT0.W\n\tbadCall(func() { call(v.Field(5).Method(1)) })          // .namedT0.w\n\tbadMethod(func() { call(v.Field(5).Elem().Method(2)) }) // .namedT0.w\n\n\tbadCall(func() { call(v.Field(6).Method(0)) })        // .namedT1.Y\n\tbadCall(func() { call(v.Field(6).Elem().Method(0)) }) // .namedT1.Y\n\tbadCall(func() { call(v.Field(6).Method(0)) })        // .namedT1.y\n\tbadCall(func() { call(v.Field(6).Elem().Method(0)) }) // .namedT1.y\n\n\tbadCall(func() { call(v.Field(7).Field(0).Method(0)) })        // .namedT2.T1.Y\n\tbadCall(func() { call(v.Field(7).Field(0).Elem().Method(0)) }) // .namedT2.T1.W\n\tbadCall(func() { call(v.Field(7).Field(1).Method(0)) })        // .namedT2.t0.W\n\tbadCall(func() { call(v.Field(7).Field(1).Elem().Method(0)) }) // .namedT2.t0.W\n}\n\nfunc TestValuePanic(t *testing.T) {\n\tvo := ValueOf\n\tshouldPanic(\"reflect.Value.Addr of unaddressable value\", func() { vo(0).Addr() })\n\tshouldPanic(\"call of reflect.Value.Bool on float64 Value\", func() { vo(0.0).Bool() })\n\tshouldPanic(\"call of reflect.Value.Bytes on string Value\", func() { vo(\"\").Bytes() })\n\tshouldPanic(\"call of reflect.Value.Call on bool Value\", func() { vo(true).Call(nil) })\n\tshouldPanic(\"call of reflect.Value.CallSlice on int Value\", func() { vo(0).CallSlice(nil) })\n\tshouldPanic(\"call of reflect.Value.Close on string Value\", func() { vo(\"\").Close() })\n\tshouldPanic(\"call of reflect.Value.Complex on float64 Value\", func() { vo(0.0).Complex() })\n\tshouldPanic(\"call of reflect.Value.Elem on bool Value\", func() { vo(false).Elem() })\n\tshouldPanic(\"call of reflect.Value.Field on int Value\", func() { vo(0).Field(0) })\n\tshouldPanic(\"call of reflect.Value.Float on string Value\", func() { vo(\"\").Float() })\n\tshouldPanic(\"call of reflect.Value.Index on float64 Value\", func() { vo(0.0).Index(0) })\n\tshouldPanic(\"call of reflect.Value.Int on bool Value\", func() { vo(false).Int() })\n\tshouldPanic(\"call of reflect.Value.IsNil on int Value\", func() { vo(0).IsNil() })\n\tshouldPanic(\"call of reflect.Value.Len on bool Value\", func() { vo(false).Len() })\n\tshouldPanic(\"call of reflect.Value.MapIndex on float64 Value\", func() { vo(0.0).MapIndex(vo(0.0)) })\n\tshouldPanic(\"call of reflect.Value.MapKeys on string Value\", func() { vo(\"\").MapKeys() })\n\tshouldPanic(\"call of reflect.Value.MapRange on int Value\", func() { vo(0).MapRange() })\n\tshouldPanic(\"call of reflect.Value.Method on zero Value\", func() { vo(nil).Method(0) })\n\tshouldPanic(\"call of reflect.Value.NumField on string Value\", func() { vo(\"\").NumField() })\n\tshouldPanic(\"call of reflect.Value.NumMethod on zero Value\", func() { vo(nil).NumMethod() })\n\tshouldPanic(\"call of reflect.Value.OverflowComplex on float64 Value\", func() { vo(float64(0)).OverflowComplex(0) })\n\tshouldPanic(\"call of reflect.Value.OverflowFloat on int64 Value\", func() { vo(int64(0)).OverflowFloat(0) })\n\tshouldPanic(\"call of reflect.Value.OverflowInt on uint64 Value\", func() { vo(uint64(0)).OverflowInt(0) })\n\tshouldPanic(\"call of reflect.Value.OverflowUint on complex64 Value\", func() { vo(complex64(0)).OverflowUint(0) })\n\tshouldPanic(\"call of reflect.Value.Recv on string Value\", func() { vo(\"\").Recv() })\n\tshouldPanic(\"call of reflect.Value.Send on bool Value\", func() { vo(true).Send(vo(true)) })\n\tshouldPanic(\"value of type string is not assignable to type bool\", func() { vo(new(bool)).Elem().Set(vo(\"\")) })\n\tshouldPanic(\"call of reflect.Value.SetBool on string Value\", func() { vo(new(string)).Elem().SetBool(false) })\n\tshouldPanic(\"reflect.Value.SetBytes using unaddressable value\", func() { vo(\"\").SetBytes(nil) })\n\tshouldPanic(\"call of reflect.Value.SetCap on string Value\", func() { vo(new(string)).Elem().SetCap(0) })\n\tshouldPanic(\"call of reflect.Value.SetComplex on string Value\", func() { vo(new(string)).Elem().SetComplex(0) })\n\tshouldPanic(\"call of reflect.Value.SetFloat on string Value\", func() { vo(new(string)).Elem().SetFloat(0) })\n\tshouldPanic(\"call of reflect.Value.SetInt on string Value\", func() { vo(new(string)).Elem().SetInt(0) })\n\tshouldPanic(\"call of reflect.Value.SetLen on string Value\", func() { vo(new(string)).Elem().SetLen(0) })\n\tshouldPanic(\"call of reflect.Value.SetString on int Value\", func() { vo(new(int)).Elem().SetString(\"\") })\n\tshouldPanic(\"reflect.Value.SetUint using unaddressable value\", func() { vo(0.0).SetUint(0) })\n\tshouldPanic(\"call of reflect.Value.Slice on bool Value\", func() { vo(true).Slice(1, 2) })\n\tshouldPanic(\"call of reflect.Value.Slice3 on int Value\", func() { vo(0).Slice3(1, 2, 3) })\n\tshouldPanic(\"call of reflect.Value.TryRecv on bool Value\", func() { vo(true).TryRecv() })\n\tshouldPanic(\"call of reflect.Value.TrySend on string Value\", func() { vo(\"\").TrySend(vo(\"\")) })\n\tshouldPanic(\"call of reflect.Value.Uint on float64 Value\", func() { vo(0.0).Uint() })\n}\n\n*/\n\nfunc shouldPanic(expect string, f func()) {\n\treturn\n\tdefer func() {\n\t\tr := recover()\n\t\tif r == nil {\n\t\t\tpanic(\"did not panic\")\n\t\t}\n\t\tif expect != \"\" {\n\t\t\tvar s string\n\t\t\tswitch r := r.(type) {\n\t\t\tcase string:\n\t\t\t\ts = r\n\t\t\tcase *ValueError:\n\t\t\t\ts = r.Error()\n\t\t\tdefault:\n\t\t\t\tpanic(fmt.Sprintf(\"panicked with unexpected type %T\", r))\n\t\t\t}\n\t\t\tif !strings.HasPrefix(s, \"reflect\") {\n\t\t\t\tpanic(`panic string does not start with \"reflect\": ` + s)\n\t\t\t}\n\t\t\tif !strings.Contains(s, expect) {\n\t\t\t\tpanic(`panic string does not contain \"` + expect + `\": ` + s)\n\t\t\t}\n\t\t}\n\t}()\n\tf()\n}\n\nfunc isNonNil(x any) {\n\tif x == nil {\n\t\tpanic(\"nil interface\")\n\t}\n}\n\nfunc isValid(v Value) {\n\tif !v.IsValid() {\n\t\tpanic(\"zero Value\")\n\t}\n}\n\n/*\n\nfunc TestAlias(t *testing.T) {\n\tx := string(\"hello\")\n\tv := ValueOf(&x).Elem()\n\toldvalue := v.Interface()\n\tv.SetString(\"world\")\n\tnewvalue := v.Interface()\n\n\tif oldvalue != \"hello\" || newvalue != \"world\" {\n\t\tt.Errorf(\"aliasing: old=%q new=%q, want hello, world\", oldvalue, newvalue)\n\t}\n}\n\n*/\n\nvar V = ValueOf\n\nfunc EmptyInterfaceV(x any) Value {\n\treturn ValueOf(&x).Elem()\n}\n\nfunc ReaderV(x io.Reader) Value {\n\treturn ValueOf(&x).Elem()\n}\n\nfunc ReadWriterV(x io.ReadWriter) Value {\n\treturn ValueOf(&x).Elem()\n}\n\ntype Empty struct{}\ntype MyStruct struct {\n\tx int `some:\"tag\"`\n}\ntype MyStruct1 struct {\n\tx struct {\n\t\tint `some:\"bar\"`\n\t}\n}\ntype MyStruct2 struct {\n\tx struct {\n\t\tint `some:\"foo\"`\n\t}\n}\ntype MyString string\ntype MyBytes []byte\ntype MyBytesArrayPtr0 *[0]byte\ntype MyBytesArrayPtr *[4]byte\ntype MyBytesArray0 [0]byte\ntype MyBytesArray [4]byte\ntype MyRunes []int32\ntype MyFunc func()\ntype MyByte byte\n\ntype IntChan chan int\ntype IntChanRecv <-chan int\ntype IntChanSend chan<- int\ntype BytesChan chan []byte\ntype BytesChanRecv <-chan []byte\ntype BytesChanSend chan<- []byte\n\n/*\n\nvar convertTests = []struct {\n\tin  Value\n\tout Value\n}{\n\t// numbers\n\t/*\n\t\tEdit .+1,/\\*\\//-1>cat >/tmp/x.go && go run /tmp/x.go\n\n\t\tpackage main\n\n\t\timport \"fmt\"\n\n\t\tvar numbers = []string{\n\t\t\t\"int8\", \"uint8\", \"int16\", \"uint16\",\n\t\t\t\"int32\", \"uint32\", \"int64\", \"uint64\",\n\t\t\t\"int\", \"uint\", \"uintptr\",\n\t\t\t\"float32\", \"float64\",\n\t\t}\n\n\t\tfunc main() {\n\t\t\t// all pairs but in an unusual order,\n\t\t\t// to emit all the int8, uint8 cases\n\t\t\t// before n grows too big.\n\t\t\tn := 1\n\t\t\tfor i, f := range numbers {\n\t\t\t\tfor _, g := range numbers[i:] {\n\t\t\t\t\tfmt.Printf(\"\\t{V(%s(%d)), V(%s(%d))},\\n\", f, n, g, n)\n\t\t\t\t\tn++\n\t\t\t\t\tif f != g {\n\t\t\t\t\t\tfmt.Printf(\"\\t{V(%s(%d)), V(%s(%d))},\\n\", g, n, f, n)\n\t\t\t\t\t\tn++\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n*/ /*\n\t{V(int8(1)), V(int8(1))},\n\t{V(int8(2)), V(uint8(2))},\n\t{V(uint8(3)), V(int8(3))},\n\t{V(int8(4)), V(int16(4))},\n\t{V(int16(5)), V(int8(5))},\n\t{V(int8(6)), V(uint16(6))},\n\t{V(uint16(7)), V(int8(7))},\n\t{V(int8(8)), V(int32(8))},\n\t{V(int32(9)), V(int8(9))},\n\t{V(int8(10)), V(uint32(10))},\n\t{V(uint32(11)), V(int8(11))},\n\t{V(int8(12)), V(int64(12))},\n\t{V(int64(13)), V(int8(13))},\n\t{V(int8(14)), V(uint64(14))},\n\t{V(uint64(15)), V(int8(15))},\n\t{V(int8(16)), V(int(16))},\n\t{V(int(17)), V(int8(17))},\n\t{V(int8(18)), V(uint(18))},\n\t{V(uint(19)), V(int8(19))},\n\t{V(int8(20)), V(uintptr(20))},\n\t{V(uintptr(21)), V(int8(21))},\n\t{V(int8(22)), V(float32(22))},\n\t{V(float32(23)), V(int8(23))},\n\t{V(int8(24)), V(float64(24))},\n\t{V(float64(25)), V(int8(25))},\n\t{V(uint8(26)), V(uint8(26))},\n\t{V(uint8(27)), V(int16(27))},\n\t{V(int16(28)), V(uint8(28))},\n\t{V(uint8(29)), V(uint16(29))},\n\t{V(uint16(30)), V(uint8(30))},\n\t{V(uint8(31)), V(int32(31))},\n\t{V(int32(32)), V(uint8(32))},\n\t{V(uint8(33)), V(uint32(33))},\n\t{V(uint32(34)), V(uint8(34))},\n\t{V(uint8(35)), V(int64(35))},\n\t{V(int64(36)), V(uint8(36))},\n\t{V(uint8(37)), V(uint64(37))},\n\t{V(uint64(38)), V(uint8(38))},\n\t{V(uint8(39)), V(int(39))},\n\t{V(int(40)), V(uint8(40))},\n\t{V(uint8(41)), V(uint(41))},\n\t{V(uint(42)), V(uint8(42))},\n\t{V(uint8(43)), V(uintptr(43))},\n\t{V(uintptr(44)), V(uint8(44))},\n\t{V(uint8(45)), V(float32(45))},\n\t{V(float32(46)), V(uint8(46))},\n\t{V(uint8(47)), V(float64(47))},\n\t{V(float64(48)), V(uint8(48))},\n\t{V(int16(49)), V(int16(49))},\n\t{V(int16(50)), V(uint16(50))},\n\t{V(uint16(51)), V(int16(51))},\n\t{V(int16(52)), V(int32(52))},\n\t{V(int32(53)), V(int16(53))},\n\t{V(int16(54)), V(uint32(54))},\n\t{V(uint32(55)), V(int16(55))},\n\t{V(int16(56)), V(int64(56))},\n\t{V(int64(57)), V(int16(57))},\n\t{V(int16(58)), V(uint64(58))},\n\t{V(uint64(59)), V(int16(59))},\n\t{V(int16(60)), V(int(60))},\n\t{V(int(61)), V(int16(61))},\n\t{V(int16(62)), V(uint(62))},\n\t{V(uint(63)), V(int16(63))},\n\t{V(int16(64)), V(uintptr(64))},\n\t{V(uintptr(65)), V(int16(65))},\n\t{V(int16(66)), V(float32(66))},\n\t{V(float32(67)), V(int16(67))},\n\t{V(int16(68)), V(float64(68))},\n\t{V(float64(69)), V(int16(69))},\n\t{V(uint16(70)), V(uint16(70))},\n\t{V(uint16(71)), V(int32(71))},\n\t{V(int32(72)), V(uint16(72))},\n\t{V(uint16(73)), V(uint32(73))},\n\t{V(uint32(74)), V(uint16(74))},\n\t{V(uint16(75)), V(int64(75))},\n\t{V(int64(76)), V(uint16(76))},\n\t{V(uint16(77)), V(uint64(77))},\n\t{V(uint64(78)), V(uint16(78))},\n\t{V(uint16(79)), V(int(79))},\n\t{V(int(80)), V(uint16(80))},\n\t{V(uint16(81)), V(uint(81))},\n\t{V(uint(82)), V(uint16(82))},\n\t{V(uint16(83)), V(uintptr(83))},\n\t{V(uintptr(84)), V(uint16(84))},\n\t{V(uint16(85)), V(float32(85))},\n\t{V(float32(86)), V(uint16(86))},\n\t{V(uint16(87)), V(float64(87))},\n\t{V(float64(88)), V(uint16(88))},\n\t{V(int32(89)), V(int32(89))},\n\t{V(int32(90)), V(uint32(90))},\n\t{V(uint32(91)), V(int32(91))},\n\t{V(int32(92)), V(int64(92))},\n\t{V(int64(93)), V(int32(93))},\n\t{V(int32(94)), V(uint64(94))},\n\t{V(uint64(95)), V(int32(95))},\n\t{V(int32(96)), V(int(96))},\n\t{V(int(97)), V(int32(97))},\n\t{V(int32(98)), V(uint(98))},\n\t{V(uint(99)), V(int32(99))},\n\t{V(int32(100)), V(uintptr(100))},\n\t{V(uintptr(101)), V(int32(101))},\n\t{V(int32(102)), V(float32(102))},\n\t{V(float32(103)), V(int32(103))},\n\t{V(int32(104)), V(float64(104))},\n\t{V(float64(105)), V(int32(105))},\n\t{V(uint32(106)), V(uint32(106))},\n\t{V(uint32(107)), V(int64(107))},\n\t{V(int64(108)), V(uint32(108))},\n\t{V(uint32(109)), V(uint64(109))},\n\t{V(uint64(110)), V(uint32(110))},\n\t{V(uint32(111)), V(int(111))},\n\t{V(int(112)), V(uint32(112))},\n\t{V(uint32(113)), V(uint(113))},\n\t{V(uint(114)), V(uint32(114))},\n\t{V(uint32(115)), V(uintptr(115))},\n\t{V(uintptr(116)), V(uint32(116))},\n\t{V(uint32(117)), V(float32(117))},\n\t{V(float32(118)), V(uint32(118))},\n\t{V(uint32(119)), V(float64(119))},\n\t{V(float64(120)), V(uint32(120))},\n\t{V(int64(121)), V(int64(121))},\n\t{V(int64(122)), V(uint64(122))},\n\t{V(uint64(123)), V(int64(123))},\n\t{V(int64(124)), V(int(124))},\n\t{V(int(125)), V(int64(125))},\n\t{V(int64(126)), V(uint(126))},\n\t{V(uint(127)), V(int64(127))},\n\t{V(int64(128)), V(uintptr(128))},\n\t{V(uintptr(129)), V(int64(129))},\n\t{V(int64(130)), V(float32(130))},\n\t{V(float32(131)), V(int64(131))},\n\t{V(int64(132)), V(float64(132))},\n\t{V(float64(133)), V(int64(133))},\n\t{V(uint64(134)), V(uint64(134))},\n\t{V(uint64(135)), V(int(135))},\n\t{V(int(136)), V(uint64(136))},\n\t{V(uint64(137)), V(uint(137))},\n\t{V(uint(138)), V(uint64(138))},\n\t{V(uint64(139)), V(uintptr(139))},\n\t{V(uintptr(140)), V(uint64(140))},\n\t{V(uint64(141)), V(float32(141))},\n\t{V(float32(142)), V(uint64(142))},\n\t{V(uint64(143)), V(float64(143))},\n\t{V(float64(144)), V(uint64(144))},\n\t{V(int(145)), V(int(145))},\n\t{V(int(146)), V(uint(146))},\n\t{V(uint(147)), V(int(147))},\n\t{V(int(148)), V(uintptr(148))},\n\t{V(uintptr(149)), V(int(149))},\n\t{V(int(150)), V(float32(150))},\n\t{V(float32(151)), V(int(151))},\n\t{V(int(152)), V(float64(152))},\n\t{V(float64(153)), V(int(153))},\n\t{V(uint(154)), V(uint(154))},\n\t{V(uint(155)), V(uintptr(155))},\n\t{V(uintptr(156)), V(uint(156))},\n\t{V(uint(157)), V(float32(157))},\n\t{V(float32(158)), V(uint(158))},\n\t{V(uint(159)), V(float64(159))},\n\t{V(float64(160)), V(uint(160))},\n\t{V(uintptr(161)), V(uintptr(161))},\n\t{V(uintptr(162)), V(float32(162))},\n\t{V(float32(163)), V(uintptr(163))},\n\t{V(uintptr(164)), V(float64(164))},\n\t{V(float64(165)), V(uintptr(165))},\n\t{V(float32(166)), V(float32(166))},\n\t{V(float32(167)), V(float64(167))},\n\t{V(float64(168)), V(float32(168))},\n\t{V(float64(169)), V(float64(169))},\n\n\t// truncation\n\t{V(float64(1.5)), V(int(1))},\n\n\t// complex\n\t{V(complex64(1i)), V(complex64(1i))},\n\t{V(complex64(2i)), V(complex128(2i))},\n\t{V(complex128(3i)), V(complex64(3i))},\n\t{V(complex128(4i)), V(complex128(4i))},\n\n\t// string\n\t{V(string(\"hello\")), V(string(\"hello\"))},\n\t{V(string(\"bytes1\")), V([]byte(\"bytes1\"))},\n\t{V([]byte(\"bytes2\")), V(string(\"bytes2\"))},\n\t{V([]byte(\"bytes3\")), V([]byte(\"bytes3\"))},\n\t{V(string(\"runes♝\")), V([]rune(\"runes♝\"))},\n\t{V([]rune(\"runes♕\")), V(string(\"runes♕\"))},\n\t{V([]rune(\"runes🙈🙉🙊\")), V([]rune(\"runes🙈🙉🙊\"))},\n\t{V(int('a')), V(string(\"a\"))},\n\t{V(int8('a')), V(string(\"a\"))},\n\t{V(int16('a')), V(string(\"a\"))},\n\t{V(int32('a')), V(string(\"a\"))},\n\t{V(int64('a')), V(string(\"a\"))},\n\t{V(uint('a')), V(string(\"a\"))},\n\t{V(uint8('a')), V(string(\"a\"))},\n\t{V(uint16('a')), V(string(\"a\"))},\n\t{V(uint32('a')), V(string(\"a\"))},\n\t{V(uint64('a')), V(string(\"a\"))},\n\t{V(uintptr('a')), V(string(\"a\"))},\n\t{V(int(-1)), V(string(\"\\uFFFD\"))},\n\t{V(int8(-2)), V(string(\"\\uFFFD\"))},\n\t{V(int16(-3)), V(string(\"\\uFFFD\"))},\n\t{V(int32(-4)), V(string(\"\\uFFFD\"))},\n\t{V(int64(-5)), V(string(\"\\uFFFD\"))},\n\t{V(int64(-1 << 32)), V(string(\"\\uFFFD\"))},\n\t{V(int64(1 << 32)), V(string(\"\\uFFFD\"))},\n\t{V(uint(0x110001)), V(string(\"\\uFFFD\"))},\n\t{V(uint32(0x110002)), V(string(\"\\uFFFD\"))},\n\t{V(uint64(0x110003)), V(string(\"\\uFFFD\"))},\n\t{V(uint64(1 << 32)), V(string(\"\\uFFFD\"))},\n\t{V(uintptr(0x110004)), V(string(\"\\uFFFD\"))},\n\n\t// named string\n\t{V(MyString(\"hello\")), V(string(\"hello\"))},\n\t{V(string(\"hello\")), V(MyString(\"hello\"))},\n\t{V(string(\"hello\")), V(string(\"hello\"))},\n\t{V(MyString(\"hello\")), V(MyString(\"hello\"))},\n\t{V(MyString(\"bytes1\")), V([]byte(\"bytes1\"))},\n\t{V([]byte(\"bytes2\")), V(MyString(\"bytes2\"))},\n\t{V([]byte(\"bytes3\")), V([]byte(\"bytes3\"))},\n\t{V(MyString(\"runes♝\")), V([]rune(\"runes♝\"))},\n\t{V([]rune(\"runes♕\")), V(MyString(\"runes♕\"))},\n\t{V([]rune(\"runes🙈🙉🙊\")), V([]rune(\"runes🙈🙉🙊\"))},\n\t{V([]rune(\"runes🙈🙉🙊\")), V(MyRunes(\"runes🙈🙉🙊\"))},\n\t{V(MyRunes(\"runes🙈🙉🙊\")), V([]rune(\"runes🙈🙉🙊\"))},\n\t{V(int('a')), V(MyString(\"a\"))},\n\t{V(int8('a')), V(MyString(\"a\"))},\n\t{V(int16('a')), V(MyString(\"a\"))},\n\t{V(int32('a')), V(MyString(\"a\"))},\n\t{V(int64('a')), V(MyString(\"a\"))},\n\t{V(uint('a')), V(MyString(\"a\"))},\n\t{V(uint8('a')), V(MyString(\"a\"))},\n\t{V(uint16('a')), V(MyString(\"a\"))},\n\t{V(uint32('a')), V(MyString(\"a\"))},\n\t{V(uint64('a')), V(MyString(\"a\"))},\n\t{V(uintptr('a')), V(MyString(\"a\"))},\n\t{V(int(-1)), V(MyString(\"\\uFFFD\"))},\n\t{V(int8(-2)), V(MyString(\"\\uFFFD\"))},\n\t{V(int16(-3)), V(MyString(\"\\uFFFD\"))},\n\t{V(int32(-4)), V(MyString(\"\\uFFFD\"))},\n\t{V(int64(-5)), V(MyString(\"\\uFFFD\"))},\n\t{V(uint(0x110001)), V(MyString(\"\\uFFFD\"))},\n\t{V(uint32(0x110002)), V(MyString(\"\\uFFFD\"))},\n\t{V(uint64(0x110003)), V(MyString(\"\\uFFFD\"))},\n\t{V(uintptr(0x110004)), V(MyString(\"\\uFFFD\"))},\n\n\t// named []byte\n\t{V(string(\"bytes1\")), V(MyBytes(\"bytes1\"))},\n\t{V(MyBytes(\"bytes2\")), V(string(\"bytes2\"))},\n\t{V(MyBytes(\"bytes3\")), V(MyBytes(\"bytes3\"))},\n\t{V(MyString(\"bytes1\")), V(MyBytes(\"bytes1\"))},\n\t{V(MyBytes(\"bytes2\")), V(MyString(\"bytes2\"))},\n\n\t// named []rune\n\t{V(string(\"runes♝\")), V(MyRunes(\"runes♝\"))},\n\t{V(MyRunes(\"runes♕\")), V(string(\"runes♕\"))},\n\t{V(MyRunes(\"runes🙈🙉🙊\")), V(MyRunes(\"runes🙈🙉🙊\"))},\n\t{V(MyString(\"runes♝\")), V(MyRunes(\"runes♝\"))},\n\t{V(MyRunes(\"runes♕\")), V(MyString(\"runes♕\"))},\n\n\t// slice to array\n\t{V([]byte(nil)), V([0]byte{})},\n\t{V([]byte{}), V([0]byte{})},\n\t{V([]byte{1}), V([1]byte{1})},\n\t{V([]byte{1, 2}), V([2]byte{1, 2})},\n\t{V([]byte{1, 2, 3}), V([3]byte{1, 2, 3})},\n\t{V(MyBytes([]byte(nil))), V([0]byte{})},\n\t{V(MyBytes{}), V([0]byte{})},\n\t{V(MyBytes{1}), V([1]byte{1})},\n\t{V(MyBytes{1, 2}), V([2]byte{1, 2})},\n\t{V(MyBytes{1, 2, 3}), V([3]byte{1, 2, 3})},\n\t{V([]byte(nil)), V(MyBytesArray0{})},\n\t{V([]byte{}), V(MyBytesArray0([0]byte{}))},\n\t{V([]byte{1, 2, 3, 4}), V(MyBytesArray([4]byte{1, 2, 3, 4}))},\n\t{V(MyBytes{}), V(MyBytesArray0([0]byte{}))},\n\t{V(MyBytes{5, 6, 7, 8}), V(MyBytesArray([4]byte{5, 6, 7, 8}))},\n\t{V([]MyByte{}), V([0]MyByte{})},\n\t{V([]MyByte{1, 2}), V([2]MyByte{1, 2})},\n\n\t// slice to array pointer\n\t{V([]byte(nil)), V((*[0]byte)(nil))},\n\t{V([]byte{}), V(new([0]byte))},\n\t{V([]byte{7}), V(&[1]byte{7})},\n\t{V(MyBytes([]byte(nil))), V((*[0]byte)(nil))},\n\t{V(MyBytes([]byte{})), V(new([0]byte))},\n\t{V(MyBytes([]byte{9})), V(&[1]byte{9})},\n\t{V([]byte(nil)), V(MyBytesArrayPtr0(nil))},\n\t{V([]byte{}), V(MyBytesArrayPtr0(new([0]byte)))},\n\t{V([]byte{1, 2, 3, 4}), V(MyBytesArrayPtr(&[4]byte{1, 2, 3, 4}))},\n\t{V(MyBytes([]byte{})), V(MyBytesArrayPtr0(new([0]byte)))},\n\t{V(MyBytes([]byte{5, 6, 7, 8})), V(MyBytesArrayPtr(&[4]byte{5, 6, 7, 8}))},\n\n\t{V([]byte(nil)), V((*MyBytesArray0)(nil))},\n\t{V([]byte{}), V((*MyBytesArray0)(new([0]byte)))},\n\t{V([]byte{1, 2, 3, 4}), V(&MyBytesArray{1, 2, 3, 4})},\n\t{V(MyBytes([]byte(nil))), V((*MyBytesArray0)(nil))},\n\t{V(MyBytes([]byte{})), V((*MyBytesArray0)(new([0]byte)))},\n\t{V(MyBytes([]byte{5, 6, 7, 8})), V(&MyBytesArray{5, 6, 7, 8})},\n\t{V(new([0]byte)), V(new(MyBytesArray0))},\n\t{V(new(MyBytesArray0)), V(new([0]byte))},\n\t{V(MyBytesArrayPtr0(nil)), V((*[0]byte)(nil))},\n\t{V((*[0]byte)(nil)), V(MyBytesArrayPtr0(nil))},\n\n\t// named types and equal underlying types\n\t{V(new(int)), V(new(integer))},\n\t{V(new(integer)), V(new(int))},\n\t{V(Empty{}), V(struct{}{})},\n\t{V(new(Empty)), V(new(struct{}))},\n\t{V(struct{}{}), V(Empty{})},\n\t{V(new(struct{})), V(new(Empty))},\n\t{V(Empty{}), V(Empty{})},\n\t{V(MyBytes{}), V([]byte{})},\n\t{V([]byte{}), V(MyBytes{})},\n\t{V((func())(nil)), V(MyFunc(nil))},\n\t{V((MyFunc)(nil)), V((func())(nil))},\n\n\t// structs with different tags\n\t{V(struct {\n\t\tx int `some:\"foo\"`\n\t}{}), V(struct {\n\t\tx int `some:\"bar\"`\n\t}{})},\n\n\t{V(struct {\n\t\tx int `some:\"bar\"`\n\t}{}), V(struct {\n\t\tx int `some:\"foo\"`\n\t}{})},\n\n\t{V(MyStruct{}), V(struct {\n\t\tx int `some:\"foo\"`\n\t}{})},\n\n\t{V(struct {\n\t\tx int `some:\"foo\"`\n\t}{}), V(MyStruct{})},\n\n\t{V(MyStruct{}), V(struct {\n\t\tx int `some:\"bar\"`\n\t}{})},\n\n\t{V(struct {\n\t\tx int `some:\"bar\"`\n\t}{}), V(MyStruct{})},\n\n\t{V(MyStruct1{}), V(MyStruct2{})},\n\t{V(MyStruct2{}), V(MyStruct1{})},\n\n\t// can convert *byte and *MyByte\n\t{V((*byte)(nil)), V((*MyByte)(nil))},\n\t{V((*MyByte)(nil)), V((*byte)(nil))},\n\n\t// cannot convert mismatched array sizes\n\t{V([2]byte{}), V([2]byte{})},\n\t{V([3]byte{}), V([3]byte{})},\n\t{V(MyBytesArray0{}), V([0]byte{})},\n\t{V([0]byte{}), V(MyBytesArray0{})},\n\n\t// cannot convert other instances\n\t{V((**byte)(nil)), V((**byte)(nil))},\n\t{V((**MyByte)(nil)), V((**MyByte)(nil))},\n\t{V((chan byte)(nil)), V((chan byte)(nil))},\n\t{V((chan MyByte)(nil)), V((chan MyByte)(nil))},\n\t{V(([]byte)(nil)), V(([]byte)(nil))},\n\t{V(([]MyByte)(nil)), V(([]MyByte)(nil))},\n\t{V((map[int]byte)(nil)), V((map[int]byte)(nil))},\n\t{V((map[int]MyByte)(nil)), V((map[int]MyByte)(nil))},\n\t{V((map[byte]int)(nil)), V((map[byte]int)(nil))},\n\t{V((map[MyByte]int)(nil)), V((map[MyByte]int)(nil))},\n\t{V([2]byte{}), V([2]byte{})},\n\t{V([2]MyByte{}), V([2]MyByte{})},\n\n\t// other\n\t{V((***int)(nil)), V((***int)(nil))},\n\t{V((***byte)(nil)), V((***byte)(nil))},\n\t{V((***int32)(nil)), V((***int32)(nil))},\n\t{V((***int64)(nil)), V((***int64)(nil))},\n\t{V((chan byte)(nil)), V((chan byte)(nil))},\n\t{V((chan MyByte)(nil)), V((chan MyByte)(nil))},\n\t{V((map[int]bool)(nil)), V((map[int]bool)(nil))},\n\t{V((map[int]byte)(nil)), V((map[int]byte)(nil))},\n\t{V((map[uint]bool)(nil)), V((map[uint]bool)(nil))},\n\t{V([]uint(nil)), V([]uint(nil))},\n\t{V([]int(nil)), V([]int(nil))},\n\t{V(new(any)), V(new(any))},\n\t{V(new(io.Reader)), V(new(io.Reader))},\n\t{V(new(io.Writer)), V(new(io.Writer))},\n\n\t// channels\n\t{V(IntChan(nil)), V((chan<- int)(nil))},\n\t{V(IntChan(nil)), V((<-chan int)(nil))},\n\t{V((chan int)(nil)), V(IntChanRecv(nil))},\n\t{V((chan int)(nil)), V(IntChanSend(nil))},\n\t{V(IntChanRecv(nil)), V((<-chan int)(nil))},\n\t{V((<-chan int)(nil)), V(IntChanRecv(nil))},\n\t{V(IntChanSend(nil)), V((chan<- int)(nil))},\n\t{V((chan<- int)(nil)), V(IntChanSend(nil))},\n\t{V(IntChan(nil)), V((chan int)(nil))},\n\t{V((chan int)(nil)), V(IntChan(nil))},\n\t{V((chan int)(nil)), V((<-chan int)(nil))},\n\t{V((chan int)(nil)), V((chan<- int)(nil))},\n\t{V(BytesChan(nil)), V((chan<- []byte)(nil))},\n\t{V(BytesChan(nil)), V((<-chan []byte)(nil))},\n\t{V((chan []byte)(nil)), V(BytesChanRecv(nil))},\n\t{V((chan []byte)(nil)), V(BytesChanSend(nil))},\n\t{V(BytesChanRecv(nil)), V((<-chan []byte)(nil))},\n\t{V((<-chan []byte)(nil)), V(BytesChanRecv(nil))},\n\t{V(BytesChanSend(nil)), V((chan<- []byte)(nil))},\n\t{V((chan<- []byte)(nil)), V(BytesChanSend(nil))},\n\t{V(BytesChan(nil)), V((chan []byte)(nil))},\n\t{V((chan []byte)(nil)), V(BytesChan(nil))},\n\t{V((chan []byte)(nil)), V((<-chan []byte)(nil))},\n\t{V((chan []byte)(nil)), V((chan<- []byte)(nil))},\n\n\t// cannot convert other instances (channels)\n\t{V(IntChan(nil)), V(IntChan(nil))},\n\t{V(IntChanRecv(nil)), V(IntChanRecv(nil))},\n\t{V(IntChanSend(nil)), V(IntChanSend(nil))},\n\t{V(BytesChan(nil)), V(BytesChan(nil))},\n\t{V(BytesChanRecv(nil)), V(BytesChanRecv(nil))},\n\t{V(BytesChanSend(nil)), V(BytesChanSend(nil))},\n\n\t// interfaces\n\t{V(int(1)), EmptyInterfaceV(int(1))},\n\t{V(string(\"hello\")), EmptyInterfaceV(string(\"hello\"))},\n\t{V(new(bytes.Buffer)), ReaderV(new(bytes.Buffer))},\n\t{ReadWriterV(new(bytes.Buffer)), ReaderV(new(bytes.Buffer))},\n\t{V(new(bytes.Buffer)), ReadWriterV(new(bytes.Buffer))},\n}\n\nfunc TestConvert(t *testing.T) {\n\tcanConvert := map[[2]Type]bool{}\n\tall := map[Type]bool{}\n\n\tfor _, tt := range convertTests {\n\t\tt1 := tt.in.Type()\n\t\tif !t1.ConvertibleTo(t1) {\n\t\t\tt.Errorf(\"(%s).ConvertibleTo(%s) = false, want true\", t1, t1)\n\t\t\tcontinue\n\t\t}\n\n\t\tt2 := tt.out.Type()\n\t\tif !t1.ConvertibleTo(t2) {\n\t\t\tt.Errorf(\"(%s).ConvertibleTo(%s) = false, want true\", t1, t2)\n\t\t\tcontinue\n\t\t}\n\n\t\tall[t1] = true\n\t\tall[t2] = true\n\t\tcanConvert[[2]Type{t1, t2}] = true\n\n\t\t// vout1 represents the in value converted to the in type.\n\t\tv1 := tt.in\n\t\tif !v1.CanConvert(t1) {\n\t\t\tt.Errorf(\"ValueOf(%T(%[1]v)).CanConvert(%s) = false, want true\", tt.in.Interface(), t1)\n\t\t}\n\t\tvout1 := v1.Convert(t1)\n\t\tout1 := vout1.Interface()\n\t\tif vout1.Type() != tt.in.Type() || !DeepEqual(out1, tt.in.Interface()) {\n\t\t\tt.Errorf(\"ValueOf(%T(%[1]v)).Convert(%s) = %T(%[3]v), want %T(%[4]v)\", tt.in.Interface(), t1, out1, tt.in.Interface())\n\t\t}\n\n\t\t// vout2 represents the in value converted to the out type.\n\t\tif !v1.CanConvert(t2) {\n\t\t\tt.Errorf(\"ValueOf(%T(%[1]v)).CanConvert(%s) = false, want true\", tt.in.Interface(), t2)\n\t\t}\n\t\tvout2 := v1.Convert(t2)\n\t\tout2 := vout2.Interface()\n\t\tif vout2.Type() != tt.out.Type() || !DeepEqual(out2, tt.out.Interface()) {\n\t\t\tt.Errorf(\"ValueOf(%T(%[1]v)).Convert(%s) = %T(%[3]v), want %T(%[4]v)\", tt.in.Interface(), t2, out2, tt.out.Interface())\n\t\t}\n\t\tif got, want := vout2.Kind(), vout2.Type().Kind(); got != want {\n\t\t\tt.Errorf(\"ValueOf(%T(%[1]v)).Convert(%s) has internal kind %v want %v\", tt.in.Interface(), t1, got, want)\n\t\t}\n\n\t\t// vout3 represents a new value of the out type, set to vout2.  This makes\n\t\t// sure the converted value vout2 is really usable as a regular value.\n\t\tvout3 := New(t2).Elem()\n\t\tvout3.Set(vout2)\n\t\tout3 := vout3.Interface()\n\t\tif vout3.Type() != tt.out.Type() || !DeepEqual(out3, tt.out.Interface()) {\n\t\t\tt.Errorf(\"Set(ValueOf(%T(%[1]v)).Convert(%s)) = %T(%[3]v), want %T(%[4]v)\", tt.in.Interface(), t2, out3, tt.out.Interface())\n\t\t}\n\n\t\tif IsRO(v1) {\n\t\t\tt.Errorf(\"table entry %v is RO, should not be\", v1)\n\t\t}\n\t\tif IsRO(vout1) {\n\t\t\tt.Errorf(\"self-conversion output %v is RO, should not be\", vout1)\n\t\t}\n\t\tif IsRO(vout2) {\n\t\t\tt.Errorf(\"conversion output %v is RO, should not be\", vout2)\n\t\t}\n\t\tif IsRO(vout3) {\n\t\t\tt.Errorf(\"set(conversion output) %v is RO, should not be\", vout3)\n\t\t}\n\t\tif !IsRO(MakeRO(v1).Convert(t1)) {\n\t\t\tt.Errorf(\"RO self-conversion output %v is not RO, should be\", v1)\n\t\t}\n\t\tif !IsRO(MakeRO(v1).Convert(t2)) {\n\t\t\tt.Errorf(\"RO conversion output %v is not RO, should be\", v1)\n\t\t}\n\t}\n\n\t// Assume that of all the types we saw during the tests,\n\t// if there wasn't an explicit entry for a conversion between\n\t// a pair of types, then it's not to be allowed. This checks for\n\t// things like 'int64' converting to '*int'.\n\tfor t1 := range all {\n\t\tfor t2 := range all {\n\t\t\texpectOK := t1 == t2 || canConvert[[2]Type{t1, t2}] || t2.Kind() == Interface && t2.NumMethod() == 0\n\t\t\tif ok := t1.ConvertibleTo(t2); ok != expectOK {\n\t\t\t\tt.Errorf(\"(%s).ConvertibleTo(%s) = %v, want %v\", t1, t2, ok, expectOK)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestConvertPanic(t *testing.T) {\n\ts := make([]byte, 4)\n\tp := new([8]byte)\n\tv := ValueOf(s)\n\tpt := TypeOf(p)\n\tif !v.Type().ConvertibleTo(pt) {\n\t\tt.Errorf(\"[]byte should be convertible to *[8]byte\")\n\t}\n\tif v.CanConvert(pt) {\n\t\tt.Errorf(\"slice with length 4 should not be convertible to *[8]byte\")\n\t}\n\tshouldPanic(\"reflect: cannot convert slice with length 4 to pointer to array with length 8\", func() {\n\t\t_ = v.Convert(pt)\n\t})\n\n\tif v.CanConvert(pt.Elem()) {\n\t\tt.Errorf(\"slice with length 4 should not be convertible to [8]byte\")\n\t}\n\tshouldPanic(\"reflect: cannot convert slice with length 4 to array with length 8\", func() {\n\t\t_ = v.Convert(pt.Elem())\n\t})\n}\n\nfunc TestConvertSlice2Array(t *testing.T) {\n\ts := make([]int, 4)\n\tp := [4]int{}\n\tpt := TypeOf(p)\n\tov := ValueOf(s)\n\tv := ov.Convert(pt)\n\t// Converting a slice to non-empty array needs to return\n\t// a non-addressable copy of the original memory.\n\tif v.CanAddr() {\n\t\tt.Fatalf(\"convert slice to non-empty array returns a addressable copy array\")\n\t}\n\tfor i := range s {\n\t\tov.Index(i).Set(ValueOf(i + 1))\n\t}\n\tfor i := range s {\n\t\tif v.Index(i).Int() != 0 {\n\t\t\tt.Fatalf(\"slice (%v) mutation visible in converted result (%v)\", ov, v)\n\t\t}\n\t}\n}\n\nvar gFloat32 float32\n\nconst snan uint32 = 0x7f800001\n\nfunc TestConvertNaNs(t *testing.T) {\n\t// Test to see if a store followed by a load of a signaling NaN\n\t// maintains the signaling bit. (This used to fail on the 387 port.)\n\tgFloat32 = math.Float32frombits(snan)\n\truntime.Gosched() // make sure we don't optimize the store/load away\n\tif got := math.Float32bits(gFloat32); got != snan {\n\t\tt.Errorf(\"store/load of sNaN not faithful, got %x want %x\", got, snan)\n\t}\n\t// Test reflect's conversion between float32s. See issue 36400.\n\ttype myFloat32 float32\n\tx := V(myFloat32(math.Float32frombits(snan)))\n\ty := x.Convert(TypeOf(float32(0)))\n\tz := y.Interface().(float32)\n\tif got := math.Float32bits(z); got != snan {\n\t\tt.Errorf(\"signaling nan conversion got %x, want %x\", got, snan)\n\t}\n}\n\n*/\n\ntype ComparableStruct struct {\n\tX int\n}\n\ntype NonComparableStruct struct {\n\tX int\n\tY map[string]int\n}\n\nvar comparableTests = []struct {\n\ttyp Type\n\tok  bool\n}{\n\t{TypeOf(1), true},\n\t{TypeOf(\"hello\"), true},\n\t{TypeOf(new(byte)), true},\n\t{TypeOf((func())(nil)), false},\n\t{TypeOf([]byte{}), false},\n\t{TypeOf(map[string]int{}), false},\n\t{TypeOf(make(chan int)), true},\n\t{TypeOf(1.5), true},\n\t{TypeOf(false), true},\n\t{TypeOf(1i), true},\n\t{TypeOf(ComparableStruct{}), true},\n\t{TypeOf(NonComparableStruct{}), false},\n\t{TypeOf([10]map[string]int{}), false},\n\t{TypeOf([10]string{}), true},\n\t{TypeOf(new(any)).Elem(), true},\n}\n\nfunc TestComparable(t *testing.T) {\n\tfor _, tt := range comparableTests {\n\t\tif ok := tt.typ.Comparable(); ok != tt.ok {\n\t\t\tt.Errorf(\"TypeOf(%v).Comparable() = %v, want %v\", tt.typ, ok, tt.ok)\n\t\t}\n\t}\n}\n\nfunc TestValueOverflow(t *testing.T) {\n\tif ovf := V(float64(0)).OverflowFloat(1e300); ovf {\n\t\tt.Errorf(\"%v wrongly overflows float64\", 1e300)\n\t}\n\n\tmaxFloat32 := float64((1<<24 - 1) << (127 - 23))\n\tif ovf := V(float32(0)).OverflowFloat(maxFloat32); ovf {\n\t\tt.Errorf(\"%v wrongly overflows float32\", maxFloat32)\n\t}\n\tovfFloat32 := float64((1<<24-1)<<(127-23) + 1<<(127-52))\n\tif ovf := V(float32(0)).OverflowFloat(ovfFloat32); !ovf {\n\t\tt.Errorf(\"%v should overflow float32\", ovfFloat32)\n\t}\n\tif ovf := V(float32(0)).OverflowFloat(-ovfFloat32); !ovf {\n\t\tt.Errorf(\"%v should overflow float32\", -ovfFloat32)\n\t}\n\n\tmaxInt32 := int64(0x7fffffff)\n\tif ovf := V(int32(0)).OverflowInt(maxInt32); ovf {\n\t\tt.Errorf(\"%v wrongly overflows int32\", maxInt32)\n\t}\n\tif ovf := V(int32(0)).OverflowInt(-1 << 31); ovf {\n\t\tt.Errorf(\"%v wrongly overflows int32\", -int64(1)<<31)\n\t}\n\tovfInt32 := int64(1 << 31)\n\tif ovf := V(int32(0)).OverflowInt(ovfInt32); !ovf {\n\t\tt.Errorf(\"%v should overflow int32\", ovfInt32)\n\t}\n\n\tmaxUint32 := uint64(0xffffffff)\n\tif ovf := V(uint32(0)).OverflowUint(maxUint32); ovf {\n\t\tt.Errorf(\"%v wrongly overflows uint32\", maxUint32)\n\t}\n\tovfUint32 := uint64(1 << 32)\n\tif ovf := V(uint32(0)).OverflowUint(ovfUint32); !ovf {\n\t\tt.Errorf(\"%v should overflow uint32\", ovfUint32)\n\t}\n}\n\nfunc TestTypeOverflow(t *testing.T) {\n\tif ovf := TypeFor[float64]().OverflowFloat(1e300); ovf {\n\t\tt.Errorf(\"%v wrongly overflows float64\", 1e300)\n\t}\n\n\tmaxFloat32 := float64((1<<24 - 1) << (127 - 23))\n\tif ovf := TypeFor[float32]().OverflowFloat(maxFloat32); ovf {\n\t\tt.Errorf(\"%v wrongly overflows float32\", maxFloat32)\n\t}\n\tovfFloat32 := float64((1<<24-1)<<(127-23) + 1<<(127-52))\n\tif ovf := TypeFor[float32]().OverflowFloat(ovfFloat32); !ovf {\n\t\tt.Errorf(\"%v should overflow float32\", ovfFloat32)\n\t}\n\tif ovf := TypeFor[float32]().OverflowFloat(-ovfFloat32); !ovf {\n\t\tt.Errorf(\"%v should overflow float32\", -ovfFloat32)\n\t}\n\n\tmaxInt32 := int64(0x7fffffff)\n\tif ovf := TypeFor[int32]().OverflowInt(maxInt32); ovf {\n\t\tt.Errorf(\"%v wrongly overflows int32\", maxInt32)\n\t}\n\tif ovf := TypeFor[int32]().OverflowInt(-1 << 31); ovf {\n\t\tt.Errorf(\"%v wrongly overflows int32\", -int64(1)<<31)\n\t}\n\tovfInt32 := int64(1 << 31)\n\tif ovf := TypeFor[int32]().OverflowInt(ovfInt32); !ovf {\n\t\tt.Errorf(\"%v should overflow int32\", ovfInt32)\n\t}\n\n\tmaxUint32 := uint64(0xffffffff)\n\tif ovf := TypeFor[uint32]().OverflowUint(maxUint32); ovf {\n\t\tt.Errorf(\"%v wrongly overflows uint32\", maxUint32)\n\t}\n\tovfUint32 := uint64(1 << 32)\n\tif ovf := TypeFor[uint32]().OverflowUint(ovfUint32); !ovf {\n\t\tt.Errorf(\"%v should overflow uint32\", ovfUint32)\n\t}\n}\n\n/*\n\nfunc checkSameType(t *testing.T, x Type, y any) {\n\tif x != TypeOf(y) || TypeOf(Zero(x).Interface()) != TypeOf(y) {\n\t\tt.Errorf(\"did not find preexisting type for %s (vs %s)\", TypeOf(x), TypeOf(y))\n\t}\n}\n\nfunc TestArrayOf(t *testing.T) {\n\t// check construction and use of type not in binary\n\ttests := []struct {\n\t\tn          int\n\t\tvalue      func(i int) any\n\t\tcomparable bool\n\t\twant       string\n\t}{\n\t\t{\n\t\t\tn:          0,\n\t\t\tvalue:      func(i int) any { type Tint int; return Tint(i) },\n\t\t\tcomparable: true,\n\t\t\twant:       \"[]\",\n\t\t},\n\t\t{\n\t\t\tn:          10,\n\t\t\tvalue:      func(i int) any { type Tint int; return Tint(i) },\n\t\t\tcomparable: true,\n\t\t\twant:       \"[0 1 2 3 4 5 6 7 8 9]\",\n\t\t},\n\t\t{\n\t\t\tn:          10,\n\t\t\tvalue:      func(i int) any { type Tfloat float64; return Tfloat(i) },\n\t\t\tcomparable: true,\n\t\t\twant:       \"[0 1 2 3 4 5 6 7 8 9]\",\n\t\t},\n\t\t{\n\t\t\tn:          10,\n\t\t\tvalue:      func(i int) any { type Tstring string; return Tstring(strconv.Itoa(i)) },\n\t\t\tcomparable: true,\n\t\t\twant:       \"[0 1 2 3 4 5 6 7 8 9]\",\n\t\t},\n\t\t{\n\t\t\tn:          10,\n\t\t\tvalue:      func(i int) any { type Tstruct struct{ V int }; return Tstruct{i} },\n\t\t\tcomparable: true,\n\t\t\twant:       \"[{0} {1} {2} {3} {4} {5} {6} {7} {8} {9}]\",\n\t\t},\n\t\t{\n\t\t\tn:          10,\n\t\t\tvalue:      func(i int) any { type Tint int; return []Tint{Tint(i)} },\n\t\t\tcomparable: false,\n\t\t\twant:       \"[[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]]\",\n\t\t},\n\t\t{\n\t\t\tn:          10,\n\t\t\tvalue:      func(i int) any { type Tint int; return [1]Tint{Tint(i)} },\n\t\t\tcomparable: true,\n\t\t\twant:       \"[[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]]\",\n\t\t},\n\t\t{\n\t\t\tn:          10,\n\t\t\tvalue:      func(i int) any { type Tstruct struct{ V [1]int }; return Tstruct{[1]int{i}} },\n\t\t\tcomparable: true,\n\t\t\twant:       \"[{[0]} {[1]} {[2]} {[3]} {[4]} {[5]} {[6]} {[7]} {[8]} {[9]}]\",\n\t\t},\n\t\t{\n\t\t\tn:          10,\n\t\t\tvalue:      func(i int) any { type Tstruct struct{ V []int }; return Tstruct{[]int{i}} },\n\t\t\tcomparable: false,\n\t\t\twant:       \"[{[0]} {[1]} {[2]} {[3]} {[4]} {[5]} {[6]} {[7]} {[8]} {[9]}]\",\n\t\t},\n\t\t{\n\t\t\tn:          10,\n\t\t\tvalue:      func(i int) any { type TstructUV struct{ U, V int }; return TstructUV{i, i} },\n\t\t\tcomparable: true,\n\t\t\twant:       \"[{0 0} {1 1} {2 2} {3 3} {4 4} {5 5} {6 6} {7 7} {8 8} {9 9}]\",\n\t\t},\n\t\t{\n\t\t\tn: 10,\n\t\t\tvalue: func(i int) any {\n\t\t\t\ttype TstructUV struct {\n\t\t\t\t\tU int\n\t\t\t\t\tV float64\n\t\t\t\t}\n\t\t\t\treturn TstructUV{i, float64(i)}\n\t\t\t},\n\t\t\tcomparable: true,\n\t\t\twant:       \"[{0 0} {1 1} {2 2} {3 3} {4 4} {5 5} {6 6} {7 7} {8 8} {9 9}]\",\n\t\t},\n\t}\n\n\tfor _, table := range tests {\n\t\tat := ArrayOf(table.n, TypeOf(table.value(0)))\n\t\tv := New(at).Elem()\n\t\tvok := New(at).Elem()\n\t\tvnot := New(at).Elem()\n\t\tfor i := 0; i < v.Len(); i++ {\n\t\t\tv.Index(i).Set(ValueOf(table.value(i)))\n\t\t\tvok.Index(i).Set(ValueOf(table.value(i)))\n\t\t\tj := i\n\t\t\tif i+1 == v.Len() {\n\t\t\t\tj = i + 1\n\t\t\t}\n\t\t\tvnot.Index(i).Set(ValueOf(table.value(j))) // make it differ only by last element\n\t\t}\n\t\ts := fmt.Sprint(v.Interface())\n\t\tif s != table.want {\n\t\t\tt.Errorf(\"constructed array = %s, want %s\", s, table.want)\n\t\t}\n\n\t\tif table.comparable != at.Comparable() {\n\t\t\tt.Errorf(\"constructed array (%#v) is comparable=%v, want=%v\", v.Interface(), at.Comparable(), table.comparable)\n\t\t}\n\t\tif table.comparable {\n\t\t\tif table.n > 0 {\n\t\t\t\tif DeepEqual(vnot.Interface(), v.Interface()) {\n\t\t\t\t\tt.Errorf(\n\t\t\t\t\t\t\"arrays (%#v) compare ok (but should not)\",\n\t\t\t\t\t\tv.Interface(),\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !DeepEqual(vok.Interface(), v.Interface()) {\n\t\t\t\tt.Errorf(\n\t\t\t\t\t\"arrays (%#v) compare NOT-ok (but should)\",\n\t\t\t\t\tv.Interface(),\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n\n\t// check that type already in binary is found\n\ttype T int\n\tcheckSameType(t, ArrayOf(5, TypeOf(T(1))), [5]T{})\n}\n\nfunc TestArrayOfGC(t *testing.T) {\n\ttype T *uintptr\n\ttt := TypeOf(T(nil))\n\tconst n = 100\n\tvar x []any\n\tfor i := 0; i < n; i++ {\n\t\tv := New(ArrayOf(n, tt)).Elem()\n\t\tfor j := 0; j < v.Len(); j++ {\n\t\t\tp := new(uintptr)\n\t\t\t*p = uintptr(i*n + j)\n\t\t\tv.Index(j).Set(ValueOf(p).Convert(tt))\n\t\t}\n\t\tx = append(x, v.Interface())\n\t}\n\truntime.GC()\n\n\tfor i, xi := range x {\n\t\tv := ValueOf(xi)\n\t\tfor j := 0; j < v.Len(); j++ {\n\t\t\tk := v.Index(j).Elem().Interface()\n\t\t\tif k != uintptr(i*n+j) {\n\t\t\t\tt.Errorf(\"lost x[%d][%d] = %d, want %d\", i, j, k, i*n+j)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestArrayOfAlg(t *testing.T) {\n\tat := ArrayOf(6, TypeOf(byte(0)))\n\tv1 := New(at).Elem()\n\tv2 := New(at).Elem()\n\tif v1.Interface() != v1.Interface() {\n\t\tt.Errorf(\"constructed array %v not equal to itself\", v1.Interface())\n\t}\n\tv1.Index(5).Set(ValueOf(byte(1)))\n\tif i1, i2 := v1.Interface(), v2.Interface(); i1 == i2 {\n\t\tt.Errorf(\"constructed arrays %v and %v should not be equal\", i1, i2)\n\t}\n\n\tat = ArrayOf(6, TypeOf([]int(nil)))\n\tv1 = New(at).Elem()\n\tshouldPanic(\"\", func() { _ = v1.Interface() == v1.Interface() })\n}\n\nfunc TestArrayOfGenericAlg(t *testing.T) {\n\tat1 := ArrayOf(5, TypeOf(string(\"\")))\n\tat := ArrayOf(6, at1)\n\tv1 := New(at).Elem()\n\tv2 := New(at).Elem()\n\tif v1.Interface() != v1.Interface() {\n\t\tt.Errorf(\"constructed array %v not equal to itself\", v1.Interface())\n\t}\n\n\tv1.Index(0).Index(0).Set(ValueOf(\"abc\"))\n\tv2.Index(0).Index(0).Set(ValueOf(\"efg\"))\n\tif i1, i2 := v1.Interface(), v2.Interface(); i1 == i2 {\n\t\tt.Errorf(\"constructed arrays %v and %v should not be equal\", i1, i2)\n\t}\n\n\tv1.Index(0).Index(0).Set(ValueOf(\"abc\"))\n\tv2.Index(0).Index(0).Set(ValueOf((v1.Index(0).Index(0).String() + \" \")[:3]))\n\tif i1, i2 := v1.Interface(), v2.Interface(); i1 != i2 {\n\t\tt.Errorf(\"constructed arrays %v and %v should be equal\", i1, i2)\n\t}\n\n\t// Test hash\n\tm := MakeMap(MapOf(at, TypeOf(int(0))))\n\tm.SetMapIndex(v1, ValueOf(1))\n\tif i1, i2 := v1.Interface(), v2.Interface(); !m.MapIndex(v2).IsValid() {\n\t\tt.Errorf(\"constructed arrays %v and %v have different hashes\", i1, i2)\n\t}\n}\n\nfunc TestArrayOfDirectIface(t *testing.T) {\n\t{\n\t\ttype T [1]*byte\n\t\ti1 := Zero(TypeOf(T{})).Interface()\n\t\tv1 := ValueOf(&i1).Elem()\n\t\tp1 := v1.InterfaceData()[1]\n\n\t\ti2 := Zero(ArrayOf(1, PointerTo(TypeOf(int8(0))))).Interface()\n\t\tv2 := ValueOf(&i2).Elem()\n\t\tp2 := v2.InterfaceData()[1]\n\n\t\tif p1 != 0 {\n\t\t\tt.Errorf(\"got p1=%v. want=%v\", p1, nil)\n\t\t}\n\n\t\tif p2 != 0 {\n\t\t\tt.Errorf(\"got p2=%v. want=%v\", p2, nil)\n\t\t}\n\t}\n\t{\n\t\ttype T [0]*byte\n\t\ti1 := Zero(TypeOf(T{})).Interface()\n\t\tv1 := ValueOf(&i1).Elem()\n\t\tp1 := v1.InterfaceData()[1]\n\n\t\ti2 := Zero(ArrayOf(0, PointerTo(TypeOf(int8(0))))).Interface()\n\t\tv2 := ValueOf(&i2).Elem()\n\t\tp2 := v2.InterfaceData()[1]\n\n\t\tif p1 == 0 {\n\t\t\tt.Errorf(\"got p1=%v. want=not-%v\", p1, nil)\n\t\t}\n\n\t\tif p2 == 0 {\n\t\t\tt.Errorf(\"got p2=%v. want=not-%v\", p2, nil)\n\t\t}\n\t}\n}\n\n// Ensure passing in negative lengths panics.\n// See https://golang.org/issue/43603\nfunc TestArrayOfPanicOnNegativeLength(t *testing.T) {\n\tshouldPanic(\"reflect: negative length passed to ArrayOf\", func() {\n\t\tArrayOf(-1, TypeOf(byte(0)))\n\t})\n}\n\nfunc TestSliceOf(t *testing.T) {\n\t// check construction and use of type not in binary\n\ttype T int\n\tst := SliceOf(TypeOf(T(1)))\n\tif got, want := st.String(), \"[]reflect_test.T\"; got != want {\n\t\tt.Errorf(\"SliceOf(T(1)).String()=%q, want %q\", got, want)\n\t}\n\tv := MakeSlice(st, 10, 10)\n\truntime.GC()\n\tfor i := 0; i < v.Len(); i++ {\n\t\tv.Index(i).Set(ValueOf(T(i)))\n\t\truntime.GC()\n\t}\n\ts := fmt.Sprint(v.Interface())\n\twant := \"[0 1 2 3 4 5 6 7 8 9]\"\n\tif s != want {\n\t\tt.Errorf(\"constructed slice = %s, want %s\", s, want)\n\t}\n\n\t// check that type already in binary is found\n\ttype T1 int\n\tcheckSameType(t, SliceOf(TypeOf(T1(1))), []T1{})\n}\n\nfunc TestSliceOverflow(t *testing.T) {\n\t// check that MakeSlice panics when size of slice overflows uint\n\tconst S = 1e6\n\ts := uint(S)\n\tl := (1<<(unsafe.Sizeof((*byte)(nil))*8)-1)/s + 1\n\tif l*s >= s {\n\t\tt.Fatal(\"slice size does not overflow\")\n\t}\n\tvar x [S]byte\n\tst := SliceOf(TypeOf(x))\n\tdefer func() {\n\t\terr := recover()\n\t\tif err == nil {\n\t\t\tt.Fatal(\"slice overflow does not panic\")\n\t\t}\n\t}()\n\tMakeSlice(st, int(l), int(l))\n}\n\nfunc TestSliceOfGC(t *testing.T) {\n\ttype T *uintptr\n\ttt := TypeOf(T(nil))\n\tst := SliceOf(tt)\n\tconst n = 100\n\tvar x []any\n\tfor i := 0; i < n; i++ {\n\t\tv := MakeSlice(st, n, n)\n\t\tfor j := 0; j < v.Len(); j++ {\n\t\t\tp := new(uintptr)\n\t\t\t*p = uintptr(i*n + j)\n\t\t\tv.Index(j).Set(ValueOf(p).Convert(tt))\n\t\t}\n\t\tx = append(x, v.Interface())\n\t}\n\truntime.GC()\n\n\tfor i, xi := range x {\n\t\tv := ValueOf(xi)\n\t\tfor j := 0; j < v.Len(); j++ {\n\t\t\tk := v.Index(j).Elem().Interface()\n\t\t\tif k != uintptr(i*n+j) {\n\t\t\t\tt.Errorf(\"lost x[%d][%d] = %d, want %d\", i, j, k, i*n+j)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestStructOfFieldName(t *testing.T) {\n\t// invalid field name \"1nvalid\"\n\tshouldPanic(\"has invalid name\", func() {\n\t\tStructOf([]StructField{\n\t\t\t{Name: \"Valid\", Type: TypeOf(\"\")},\n\t\t\t{Name: \"1nvalid\", Type: TypeOf(\"\")},\n\t\t})\n\t})\n\n\t// invalid field name \"+\"\n\tshouldPanic(\"has invalid name\", func() {\n\t\tStructOf([]StructField{\n\t\t\t{Name: \"Val1d\", Type: TypeOf(\"\")},\n\t\t\t{Name: \"+\", Type: TypeOf(\"\")},\n\t\t})\n\t})\n\n\t// no field name\n\tshouldPanic(\"has no name\", func() {\n\t\tStructOf([]StructField{\n\t\t\t{Name: \"\", Type: TypeOf(\"\")},\n\t\t})\n\t})\n\n\t// verify creation of a struct with valid struct fields\n\tvalidFields := []StructField{\n\t\t{\n\t\t\tName: \"φ\",\n\t\t\tType: TypeOf(\"\"),\n\t\t},\n\t\t{\n\t\t\tName: \"ValidName\",\n\t\t\tType: TypeOf(\"\"),\n\t\t},\n\t\t{\n\t\t\tName: \"Val1dNam5\",\n\t\t\tType: TypeOf(\"\"),\n\t\t},\n\t}\n\n\tvalidStruct := StructOf(validFields)\n\n\tconst structStr = `struct { φ string; ValidName string; Val1dNam5 string }`\n\tif got, want := validStruct.String(), structStr; got != want {\n\t\tt.Errorf(\"StructOf(validFields).String()=%q, want %q\", got, want)\n\t}\n}\n\nfunc TestStructOf(t *testing.T) {\n\t// check construction and use of type not in binary\n\tfields := []StructField{\n\t\t{\n\t\t\tName: \"S\",\n\t\t\tTag:  \"s\",\n\t\t\tType: TypeOf(\"\"),\n\t\t},\n\t\t{\n\t\t\tName: \"X\",\n\t\t\tTag:  \"x\",\n\t\t\tType: TypeOf(byte(0)),\n\t\t},\n\t\t{\n\t\t\tName: \"Y\",\n\t\t\tType: TypeOf(uint64(0)),\n\t\t},\n\t\t{\n\t\t\tName: \"Z\",\n\t\t\tType: TypeOf([3]uint16{}),\n\t\t},\n\t}\n\n\tst := StructOf(fields)\n\tv := New(st).Elem()\n\truntime.GC()\n\tv.FieldByName(\"X\").Set(ValueOf(byte(2)))\n\tv.FieldByIndex([]int{1}).Set(ValueOf(byte(1)))\n\truntime.GC()\n\n\ts := fmt.Sprint(v.Interface())\n\twant := `{ 1 0 [0 0 0]}`\n\tif s != want {\n\t\tt.Errorf(\"constructed struct = %s, want %s\", s, want)\n\t}\n\tconst stStr = `struct { S string \"s\"; X uint8 \"x\"; Y uint64; Z [3]uint16 }`\n\tif got, want := st.String(), stStr; got != want {\n\t\tt.Errorf(\"StructOf(fields).String()=%q, want %q\", got, want)\n\t}\n\n\t// check the size, alignment and field offsets\n\tstt := TypeOf(struct {\n\t\tString string\n\t\tX      byte\n\t\tY      uint64\n\t\tZ      [3]uint16\n\t}{})\n\tif st.Size() != stt.Size() {\n\t\tt.Errorf(\"constructed struct size = %v, want %v\", st.Size(), stt.Size())\n\t}\n\tif st.Align() != stt.Align() {\n\t\tt.Errorf(\"constructed struct align = %v, want %v\", st.Align(), stt.Align())\n\t}\n\tif st.FieldAlign() != stt.FieldAlign() {\n\t\tt.Errorf(\"constructed struct field align = %v, want %v\", st.FieldAlign(), stt.FieldAlign())\n\t}\n\tfor i := 0; i < st.NumField(); i++ {\n\t\to1 := st.Field(i).Offset\n\t\to2 := stt.Field(i).Offset\n\t\tif o1 != o2 {\n\t\t\tt.Errorf(\"constructed struct field %v offset = %v, want %v\", i, o1, o2)\n\t\t}\n\t}\n\n\t// Check size and alignment with a trailing zero-sized field.\n\tst = StructOf([]StructField{\n\t\t{\n\t\t\tName: \"F1\",\n\t\t\tType: TypeOf(byte(0)),\n\t\t},\n\t\t{\n\t\t\tName: \"F2\",\n\t\t\tType: TypeOf([0]*byte{}),\n\t\t},\n\t})\n\tstt = TypeOf(struct {\n\t\tG1 byte\n\t\tG2 [0]*byte\n\t}{})\n\tif st.Size() != stt.Size() {\n\t\tt.Errorf(\"constructed zero-padded struct size = %v, want %v\", st.Size(), stt.Size())\n\t}\n\tif st.Align() != stt.Align() {\n\t\tt.Errorf(\"constructed zero-padded struct align = %v, want %v\", st.Align(), stt.Align())\n\t}\n\tif st.FieldAlign() != stt.FieldAlign() {\n\t\tt.Errorf(\"constructed zero-padded struct field align = %v, want %v\", st.FieldAlign(), stt.FieldAlign())\n\t}\n\tfor i := 0; i < st.NumField(); i++ {\n\t\to1 := st.Field(i).Offset\n\t\to2 := stt.Field(i).Offset\n\t\tif o1 != o2 {\n\t\t\tt.Errorf(\"constructed zero-padded struct field %v offset = %v, want %v\", i, o1, o2)\n\t\t}\n\t}\n\n\t// check duplicate names\n\tshouldPanic(\"duplicate field\", func() {\n\t\tStructOf([]StructField{\n\t\t\t{Name: \"string\", PkgPath: \"p\", Type: TypeOf(\"\")},\n\t\t\t{Name: \"string\", PkgPath: \"p\", Type: TypeOf(\"\")},\n\t\t})\n\t})\n\tshouldPanic(\"has no name\", func() {\n\t\tStructOf([]StructField{\n\t\t\t{Type: TypeOf(\"\")},\n\t\t\t{Name: \"string\", PkgPath: \"p\", Type: TypeOf(\"\")},\n\t\t})\n\t})\n\tshouldPanic(\"has no name\", func() {\n\t\tStructOf([]StructField{\n\t\t\t{Type: TypeOf(\"\")},\n\t\t\t{Type: TypeOf(\"\")},\n\t\t})\n\t})\n\t// check that type already in binary is found\n\tcheckSameType(t, StructOf(fields[2:3]), struct{ Y uint64 }{})\n\n\t// gccgo used to fail this test.\n\ttype structFieldType any\n\tcheckSameType(t,\n\t\tStructOf([]StructField{\n\t\t\t{\n\t\t\t\tName: \"F\",\n\t\t\t\tType: TypeOf((*structFieldType)(nil)).Elem(),\n\t\t\t},\n\t\t}),\n\t\tstruct{ F structFieldType }{})\n}\n\nfunc TestStructOfExportRules(t *testing.T) {\n\ttype S1 struct{}\n\ttype s2 struct{}\n\ttype ΦType struct{}\n\ttype φType struct{}\n\n\ttestPanic := func(i int, mustPanic bool, f func()) {\n\t\tdefer func() {\n\t\t\terr := recover()\n\t\t\tif err == nil && mustPanic {\n\t\t\t\tt.Errorf(\"test-%d did not panic\", i)\n\t\t\t}\n\t\t\tif err != nil && !mustPanic {\n\t\t\t\tt.Errorf(\"test-%d panicked: %v\\n\", i, err)\n\t\t\t}\n\t\t}()\n\t\tf()\n\t}\n\n\ttests := []struct {\n\t\tfield     StructField\n\t\tmustPanic bool\n\t\texported  bool\n\t}{\n\t\t{\n\t\t\tfield:    StructField{Name: \"S1\", Anonymous: true, Type: TypeOf(S1{})},\n\t\t\texported: true,\n\t\t},\n\t\t{\n\t\t\tfield:    StructField{Name: \"S1\", Anonymous: true, Type: TypeOf((*S1)(nil))},\n\t\t\texported: true,\n\t\t},\n\t\t{\n\t\t\tfield:     StructField{Name: \"s2\", Anonymous: true, Type: TypeOf(s2{})},\n\t\t\tmustPanic: true,\n\t\t},\n\t\t{\n\t\t\tfield:     StructField{Name: \"s2\", Anonymous: true, Type: TypeOf((*s2)(nil))},\n\t\t\tmustPanic: true,\n\t\t},\n\t\t{\n\t\t\tfield:     StructField{Name: \"Name\", Type: nil, PkgPath: \"\"},\n\t\t\tmustPanic: true,\n\t\t},\n\t\t{\n\t\t\tfield:     StructField{Name: \"\", Type: TypeOf(S1{}), PkgPath: \"\"},\n\t\t\tmustPanic: true,\n\t\t},\n\t\t{\n\t\t\tfield:     StructField{Name: \"S1\", Anonymous: true, Type: TypeOf(S1{}), PkgPath: \"other/pkg\"},\n\t\t\tmustPanic: true,\n\t\t},\n\t\t{\n\t\t\tfield:     StructField{Name: \"S1\", Anonymous: true, Type: TypeOf((*S1)(nil)), PkgPath: \"other/pkg\"},\n\t\t\tmustPanic: true,\n\t\t},\n\t\t{\n\t\t\tfield:     StructField{Name: \"s2\", Anonymous: true, Type: TypeOf(s2{}), PkgPath: \"other/pkg\"},\n\t\t\tmustPanic: true,\n\t\t},\n\t\t{\n\t\t\tfield:     StructField{Name: \"s2\", Anonymous: true, Type: TypeOf((*s2)(nil)), PkgPath: \"other/pkg\"},\n\t\t\tmustPanic: true,\n\t\t},\n\t\t{\n\t\t\tfield: StructField{Name: \"s2\", Type: TypeOf(int(0)), PkgPath: \"other/pkg\"},\n\t\t},\n\t\t{\n\t\t\tfield: StructField{Name: \"s2\", Type: TypeOf(int(0)), PkgPath: \"other/pkg\"},\n\t\t},\n\t\t{\n\t\t\tfield:    StructField{Name: \"S\", Type: TypeOf(S1{})},\n\t\t\texported: true,\n\t\t},\n\t\t{\n\t\t\tfield:    StructField{Name: \"S\", Type: TypeOf((*S1)(nil))},\n\t\t\texported: true,\n\t\t},\n\t\t{\n\t\t\tfield:    StructField{Name: \"S\", Type: TypeOf(s2{})},\n\t\t\texported: true,\n\t\t},\n\t\t{\n\t\t\tfield:    StructField{Name: \"S\", Type: TypeOf((*s2)(nil))},\n\t\t\texported: true,\n\t\t},\n\t\t{\n\t\t\tfield:     StructField{Name: \"s\", Type: TypeOf(S1{})},\n\t\t\tmustPanic: true,\n\t\t},\n\t\t{\n\t\t\tfield:     StructField{Name: \"s\", Type: TypeOf((*S1)(nil))},\n\t\t\tmustPanic: true,\n\t\t},\n\t\t{\n\t\t\tfield:     StructField{Name: \"s\", Type: TypeOf(s2{})},\n\t\t\tmustPanic: true,\n\t\t},\n\t\t{\n\t\t\tfield:     StructField{Name: \"s\", Type: TypeOf((*s2)(nil))},\n\t\t\tmustPanic: true,\n\t\t},\n\t\t{\n\t\t\tfield: StructField{Name: \"s\", Type: TypeOf(S1{}), PkgPath: \"other/pkg\"},\n\t\t},\n\t\t{\n\t\t\tfield: StructField{Name: \"s\", Type: TypeOf((*S1)(nil)), PkgPath: \"other/pkg\"},\n\t\t},\n\t\t{\n\t\t\tfield: StructField{Name: \"s\", Type: TypeOf(s2{}), PkgPath: \"other/pkg\"},\n\t\t},\n\t\t{\n\t\t\tfield: StructField{Name: \"s\", Type: TypeOf((*s2)(nil)), PkgPath: \"other/pkg\"},\n\t\t},\n\t\t{\n\t\t\tfield:     StructField{Name: \"\", Type: TypeOf(ΦType{})},\n\t\t\tmustPanic: true,\n\t\t},\n\t\t{\n\t\t\tfield:     StructField{Name: \"\", Type: TypeOf(φType{})},\n\t\t\tmustPanic: true,\n\t\t},\n\t\t{\n\t\t\tfield:    StructField{Name: \"Φ\", Type: TypeOf(0)},\n\t\t\texported: true,\n\t\t},\n\t\t{\n\t\t\tfield:    StructField{Name: \"φ\", Type: TypeOf(0)},\n\t\t\texported: false,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\ttestPanic(i, test.mustPanic, func() {\n\t\t\ttyp := StructOf([]StructField{test.field})\n\t\t\tif typ == nil {\n\t\t\t\tt.Errorf(\"test-%d: error creating struct type\", i)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tfield := typ.Field(0)\n\t\t\tn := field.Name\n\t\t\tif n == \"\" {\n\t\t\t\tpanic(\"field.Name must not be empty\")\n\t\t\t}\n\t\t\texported := token.IsExported(n)\n\t\t\tif exported != test.exported {\n\t\t\t\tt.Errorf(\"test-%d: got exported=%v want exported=%v\", i, exported, test.exported)\n\t\t\t}\n\t\t\tif field.PkgPath != test.field.PkgPath {\n\t\t\t\tt.Errorf(\"test-%d: got PkgPath=%q want pkgPath=%q\", i, field.PkgPath, test.field.PkgPath)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestStructOfGC(t *testing.T) {\n\ttype T *uintptr\n\ttt := TypeOf(T(nil))\n\tfields := []StructField{\n\t\t{Name: \"X\", Type: tt},\n\t\t{Name: \"Y\", Type: tt},\n\t}\n\tst := StructOf(fields)\n\n\tconst n = 10000\n\tvar x []any\n\tfor i := 0; i < n; i++ {\n\t\tv := New(st).Elem()\n\t\tfor j := 0; j < v.NumField(); j++ {\n\t\t\tp := new(uintptr)\n\t\t\t*p = uintptr(i*n + j)\n\t\t\tv.Field(j).Set(ValueOf(p).Convert(tt))\n\t\t}\n\t\tx = append(x, v.Interface())\n\t}\n\truntime.GC()\n\n\tfor i, xi := range x {\n\t\tv := ValueOf(xi)\n\t\tfor j := 0; j < v.NumField(); j++ {\n\t\t\tk := v.Field(j).Elem().Interface()\n\t\t\tif k != uintptr(i*n+j) {\n\t\t\t\tt.Errorf(\"lost x[%d].%c = %d, want %d\", i, \"XY\"[j], k, i*n+j)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestStructOfAlg(t *testing.T) {\n\tst := StructOf([]StructField{{Name: \"X\", Tag: \"x\", Type: TypeOf(int(0))}})\n\tv1 := New(st).Elem()\n\tv2 := New(st).Elem()\n\tif !DeepEqual(v1.Interface(), v1.Interface()) {\n\t\tt.Errorf(\"constructed struct %v not equal to itself\", v1.Interface())\n\t}\n\tv1.FieldByName(\"X\").Set(ValueOf(int(1)))\n\tif i1, i2 := v1.Interface(), v2.Interface(); DeepEqual(i1, i2) {\n\t\tt.Errorf(\"constructed structs %v and %v should not be equal\", i1, i2)\n\t}\n\n\tst = StructOf([]StructField{{Name: \"X\", Tag: \"x\", Type: TypeOf([]int(nil))}})\n\tv1 = New(st).Elem()\n\tshouldPanic(\"\", func() { _ = v1.Interface() == v1.Interface() })\n}\n\nfunc TestStructOfGenericAlg(t *testing.T) {\n\tst1 := StructOf([]StructField{\n\t\t{Name: \"X\", Tag: \"x\", Type: TypeOf(int64(0))},\n\t\t{Name: \"Y\", Type: TypeOf(string(\"\"))},\n\t})\n\tst := StructOf([]StructField{\n\t\t{Name: \"S0\", Type: st1},\n\t\t{Name: \"S1\", Type: st1},\n\t})\n\n\ttests := []struct {\n\t\trt  Type\n\t\tidx []int\n\t}{\n\t\t{\n\t\t\trt:  st,\n\t\t\tidx: []int{0, 1},\n\t\t},\n\t\t{\n\t\t\trt:  st1,\n\t\t\tidx: []int{1},\n\t\t},\n\t\t{\n\t\t\trt: StructOf(\n\t\t\t\t[]StructField{\n\t\t\t\t\t{Name: \"XX\", Type: TypeOf([0]int{})},\n\t\t\t\t\t{Name: \"YY\", Type: TypeOf(\"\")},\n\t\t\t\t},\n\t\t\t),\n\t\t\tidx: []int{1},\n\t\t},\n\t\t{\n\t\t\trt: StructOf(\n\t\t\t\t[]StructField{\n\t\t\t\t\t{Name: \"XX\", Type: TypeOf([0]int{})},\n\t\t\t\t\t{Name: \"YY\", Type: TypeOf(\"\")},\n\t\t\t\t\t{Name: \"ZZ\", Type: TypeOf([2]int{})},\n\t\t\t\t},\n\t\t\t),\n\t\t\tidx: []int{1},\n\t\t},\n\t\t{\n\t\t\trt: StructOf(\n\t\t\t\t[]StructField{\n\t\t\t\t\t{Name: \"XX\", Type: TypeOf([1]int{})},\n\t\t\t\t\t{Name: \"YY\", Type: TypeOf(\"\")},\n\t\t\t\t},\n\t\t\t),\n\t\t\tidx: []int{1},\n\t\t},\n\t\t{\n\t\t\trt: StructOf(\n\t\t\t\t[]StructField{\n\t\t\t\t\t{Name: \"XX\", Type: TypeOf([1]int{})},\n\t\t\t\t\t{Name: \"YY\", Type: TypeOf(\"\")},\n\t\t\t\t\t{Name: \"ZZ\", Type: TypeOf([1]int{})},\n\t\t\t\t},\n\t\t\t),\n\t\t\tidx: []int{1},\n\t\t},\n\t\t{\n\t\t\trt: StructOf(\n\t\t\t\t[]StructField{\n\t\t\t\t\t{Name: \"XX\", Type: TypeOf([2]int{})},\n\t\t\t\t\t{Name: \"YY\", Type: TypeOf(\"\")},\n\t\t\t\t\t{Name: \"ZZ\", Type: TypeOf([2]int{})},\n\t\t\t\t},\n\t\t\t),\n\t\t\tidx: []int{1},\n\t\t},\n\t\t{\n\t\t\trt: StructOf(\n\t\t\t\t[]StructField{\n\t\t\t\t\t{Name: \"XX\", Type: TypeOf(int64(0))},\n\t\t\t\t\t{Name: \"YY\", Type: TypeOf(byte(0))},\n\t\t\t\t\t{Name: \"ZZ\", Type: TypeOf(\"\")},\n\t\t\t\t},\n\t\t\t),\n\t\t\tidx: []int{2},\n\t\t},\n\t\t{\n\t\t\trt: StructOf(\n\t\t\t\t[]StructField{\n\t\t\t\t\t{Name: \"XX\", Type: TypeOf(int64(0))},\n\t\t\t\t\t{Name: \"YY\", Type: TypeOf(int64(0))},\n\t\t\t\t\t{Name: \"ZZ\", Type: TypeOf(\"\")},\n\t\t\t\t\t{Name: \"AA\", Type: TypeOf([1]int64{})},\n\t\t\t\t},\n\t\t\t),\n\t\t\tidx: []int{2},\n\t\t},\n\t}\n\n\tfor _, table := range tests {\n\t\tv1 := New(table.rt).Elem()\n\t\tv2 := New(table.rt).Elem()\n\n\t\tif !DeepEqual(v1.Interface(), v1.Interface()) {\n\t\t\tt.Errorf(\"constructed struct %v not equal to itself\", v1.Interface())\n\t\t}\n\n\t\tv1.FieldByIndex(table.idx).Set(ValueOf(\"abc\"))\n\t\tv2.FieldByIndex(table.idx).Set(ValueOf(\"def\"))\n\t\tif i1, i2 := v1.Interface(), v2.Interface(); DeepEqual(i1, i2) {\n\t\t\tt.Errorf(\"constructed structs %v and %v should not be equal\", i1, i2)\n\t\t}\n\n\t\tabc := \"abc\"\n\t\tv1.FieldByIndex(table.idx).Set(ValueOf(abc))\n\t\tval := \"+\" + abc + \"-\"\n\t\tv2.FieldByIndex(table.idx).Set(ValueOf(val[1:4]))\n\t\tif i1, i2 := v1.Interface(), v2.Interface(); !DeepEqual(i1, i2) {\n\t\t\tt.Errorf(\"constructed structs %v and %v should be equal\", i1, i2)\n\t\t}\n\n\t\t// Test hash\n\t\tm := MakeMap(MapOf(table.rt, TypeOf(int(0))))\n\t\tm.SetMapIndex(v1, ValueOf(1))\n\t\tif i1, i2 := v1.Interface(), v2.Interface(); !m.MapIndex(v2).IsValid() {\n\t\t\tt.Errorf(\"constructed structs %#v and %#v have different hashes\", i1, i2)\n\t\t}\n\n\t\tv2.FieldByIndex(table.idx).Set(ValueOf(\"abc\"))\n\t\tif i1, i2 := v1.Interface(), v2.Interface(); !DeepEqual(i1, i2) {\n\t\t\tt.Errorf(\"constructed structs %v and %v should be equal\", i1, i2)\n\t\t}\n\n\t\tif i1, i2 := v1.Interface(), v2.Interface(); !m.MapIndex(v2).IsValid() {\n\t\t\tt.Errorf(\"constructed structs %v and %v have different hashes\", i1, i2)\n\t\t}\n\t}\n}\n\nfunc TestStructOfDirectIface(t *testing.T) {\n\t{\n\t\ttype T struct{ X [1]*byte }\n\t\ti1 := Zero(TypeOf(T{})).Interface()\n\t\tv1 := ValueOf(&i1).Elem()\n\t\tp1 := v1.InterfaceData()[1]\n\n\t\ti2 := Zero(StructOf([]StructField{\n\t\t\t{\n\t\t\t\tName: \"X\",\n\t\t\t\tType: ArrayOf(1, TypeOf((*int8)(nil))),\n\t\t\t},\n\t\t})).Interface()\n\t\tv2 := ValueOf(&i2).Elem()\n\t\tp2 := v2.InterfaceData()[1]\n\n\t\tif p1 != 0 {\n\t\t\tt.Errorf(\"got p1=%v. want=%v\", p1, nil)\n\t\t}\n\n\t\tif p2 != 0 {\n\t\t\tt.Errorf(\"got p2=%v. want=%v\", p2, nil)\n\t\t}\n\t}\n\t{\n\t\ttype T struct{ X [0]*byte }\n\t\ti1 := Zero(TypeOf(T{})).Interface()\n\t\tv1 := ValueOf(&i1).Elem()\n\t\tp1 := v1.InterfaceData()[1]\n\n\t\ti2 := Zero(StructOf([]StructField{\n\t\t\t{\n\t\t\t\tName: \"X\",\n\t\t\t\tType: ArrayOf(0, TypeOf((*int8)(nil))),\n\t\t\t},\n\t\t})).Interface()\n\t\tv2 := ValueOf(&i2).Elem()\n\t\tp2 := v2.InterfaceData()[1]\n\n\t\tif p1 == 0 {\n\t\t\tt.Errorf(\"got p1=%v. want=not-%v\", p1, nil)\n\t\t}\n\n\t\tif p2 == 0 {\n\t\t\tt.Errorf(\"got p2=%v. want=not-%v\", p2, nil)\n\t\t}\n\t}\n}\n\ntype StructI int\n\nfunc (i StructI) Get() int { return int(i) }\n\ntype StructIPtr int\n\nfunc (i *StructIPtr) Get() int  { return int(*i) }\nfunc (i *StructIPtr) Set(v int) { *(*int)(i) = v }\n\ntype SettableStruct struct {\n\tSettableField int\n}\n\nfunc (p *SettableStruct) Set(v int) { p.SettableField = v }\n\ntype SettablePointer struct {\n\tSettableField *int\n}\n\nfunc (p *SettablePointer) Set(v int) { *p.SettableField = v }\n\nfunc TestStructOfWithInterface(t *testing.T) {\n\tconst want = 42\n\ttype Iface interface {\n\t\tGet() int\n\t}\n\ttype IfaceSet interface {\n\t\tSet(int)\n\t}\n\ttests := []struct {\n\t\tname string\n\t\ttyp  Type\n\t\tval  Value\n\t\timpl bool\n\t}{\n\t\t{\n\t\t\tname: \"StructI\",\n\t\t\ttyp:  TypeOf(StructI(want)),\n\t\t\tval:  ValueOf(StructI(want)),\n\t\t\timpl: true,\n\t\t},\n\t\t{\n\t\t\tname: \"StructI\",\n\t\t\ttyp:  PointerTo(TypeOf(StructI(want))),\n\t\t\tval: ValueOf(func() any {\n\t\t\t\tv := StructI(want)\n\t\t\t\treturn &v\n\t\t\t}()),\n\t\t\timpl: true,\n\t\t},\n\t\t{\n\t\t\tname: \"StructIPtr\",\n\t\t\ttyp:  PointerTo(TypeOf(StructIPtr(want))),\n\t\t\tval: ValueOf(func() any {\n\t\t\t\tv := StructIPtr(want)\n\t\t\t\treturn &v\n\t\t\t}()),\n\t\t\timpl: true,\n\t\t},\n\t\t{\n\t\t\tname: \"StructIPtr\",\n\t\t\ttyp:  TypeOf(StructIPtr(want)),\n\t\t\tval:  ValueOf(StructIPtr(want)),\n\t\t\timpl: false,\n\t\t},\n\t\t// {\n\t\t//\ttyp:  TypeOf((*Iface)(nil)).Elem(), // FIXME(sbinet): fix method.ifn/tfn\n\t\t//\tval:  ValueOf(StructI(want)),\n\t\t//\timpl: true,\n\t\t// },\n\t}\n\n\tfor i, table := range tests {\n\t\tfor j := 0; j < 2; j++ {\n\t\t\tvar fields []StructField\n\t\t\tif j == 1 {\n\t\t\t\tfields = append(fields, StructField{\n\t\t\t\t\tName:    \"Dummy\",\n\t\t\t\t\tPkgPath: \"\",\n\t\t\t\t\tType:    TypeOf(int(0)),\n\t\t\t\t})\n\t\t\t}\n\t\t\tfields = append(fields, StructField{\n\t\t\t\tName:      table.name,\n\t\t\t\tAnonymous: true,\n\t\t\t\tPkgPath:   \"\",\n\t\t\t\tType:      table.typ,\n\t\t\t})\n\n\t\t\t// We currently do not correctly implement methods\n\t\t\t// for embedded fields other than the first.\n\t\t\t// Therefore, for now, we expect those methods\n\t\t\t// to not exist.  See issues 15924 and 20824.\n\t\t\t// When those issues are fixed, this test of panic\n\t\t\t// should be removed.\n\t\t\tif j == 1 && table.impl {\n\t\t\t\tfunc() {\n\t\t\t\t\tdefer func() {\n\t\t\t\t\t\tif err := recover(); err == nil {\n\t\t\t\t\t\t\tt.Errorf(\"test-%d-%d did not panic\", i, j)\n\t\t\t\t\t\t}\n\t\t\t\t\t}()\n\t\t\t\t\t_ = StructOf(fields)\n\t\t\t\t}()\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\trt := StructOf(fields)\n\t\t\trv := New(rt).Elem()\n\t\t\trv.Field(j).Set(table.val)\n\n\t\t\tif _, ok := rv.Interface().(Iface); ok != table.impl {\n\t\t\t\tif table.impl {\n\t\t\t\t\tt.Errorf(\"test-%d-%d: type=%v fails to implement Iface.\\n\", i, j, table.typ)\n\t\t\t\t} else {\n\t\t\t\t\tt.Errorf(\"test-%d-%d: type=%v should NOT implement Iface\\n\", i, j, table.typ)\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif !table.impl {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tv := rv.Interface().(Iface).Get()\n\t\t\tif v != want {\n\t\t\t\tt.Errorf(\"test-%d-%d: x.Get()=%v. want=%v\\n\", i, j, v, want)\n\t\t\t}\n\n\t\t\tfct := rv.MethodByName(\"Get\")\n\t\t\tout := fct.Call(nil)\n\t\t\tif !DeepEqual(out[0].Interface(), want) {\n\t\t\t\tt.Errorf(\"test-%d-%d: x.Get()=%v. want=%v\\n\", i, j, out[0].Interface(), want)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Test an embedded nil pointer with pointer methods.\n\tfields := []StructField{{\n\t\tName:      \"StructIPtr\",\n\t\tAnonymous: true,\n\t\tType:      PointerTo(TypeOf(StructIPtr(want))),\n\t}}\n\trt := StructOf(fields)\n\trv := New(rt).Elem()\n\t// This should panic since the pointer is nil.\n\tshouldPanic(\"\", func() {\n\t\trv.Interface().(IfaceSet).Set(want)\n\t})\n\n\t// Test an embedded nil pointer to a struct with pointer methods.\n\n\tfields = []StructField{{\n\t\tName:      \"SettableStruct\",\n\t\tAnonymous: true,\n\t\tType:      PointerTo(TypeOf(SettableStruct{})),\n\t}}\n\trt = StructOf(fields)\n\trv = New(rt).Elem()\n\t// This should panic since the pointer is nil.\n\tshouldPanic(\"\", func() {\n\t\trv.Interface().(IfaceSet).Set(want)\n\t})\n\n\t// The behavior is different if there is a second field,\n\t// since now an interface value holds a pointer to the struct\n\t// rather than just holding a copy of the struct.\n\tfields = []StructField{\n\t\t{\n\t\t\tName:      \"SettableStruct\",\n\t\t\tAnonymous: true,\n\t\t\tType:      PointerTo(TypeOf(SettableStruct{})),\n\t\t},\n\t\t{\n\t\t\tName:      \"EmptyStruct\",\n\t\t\tAnonymous: true,\n\t\t\tType:      StructOf(nil),\n\t\t},\n\t}\n\t// With the current implementation this is expected to panic.\n\t// Ideally it should work and we should be able to see a panic\n\t// if we call the Set method.\n\tshouldPanic(\"\", func() {\n\t\tStructOf(fields)\n\t})\n\n\t// Embed a field that can be stored directly in an interface,\n\t// with a second field.\n\tfields = []StructField{\n\t\t{\n\t\t\tName:      \"SettablePointer\",\n\t\t\tAnonymous: true,\n\t\t\tType:      TypeOf(SettablePointer{}),\n\t\t},\n\t\t{\n\t\t\tName:      \"EmptyStruct\",\n\t\t\tAnonymous: true,\n\t\t\tType:      StructOf(nil),\n\t\t},\n\t}\n\t// With the current implementation this is expected to panic.\n\t// Ideally it should work and we should be able to call the\n\t// Set and Get methods.\n\tshouldPanic(\"\", func() {\n\t\tStructOf(fields)\n\t})\n}\n\nfunc TestStructOfTooManyFields(t *testing.T) {\n\t// Bug Fix: #25402 - this should not panic\n\ttt := StructOf([]StructField{\n\t\t{Name: \"Time\", Type: TypeOf(time.Time{}), Anonymous: true},\n\t})\n\n\tif _, present := tt.MethodByName(\"After\"); !present {\n\t\tt.Errorf(\"Expected method `After` to be found\")\n\t}\n}\n\nfunc TestStructOfDifferentPkgPath(t *testing.T) {\n\tfields := []StructField{\n\t\t{\n\t\t\tName:    \"f1\",\n\t\t\tPkgPath: \"p1\",\n\t\t\tType:    TypeOf(int(0)),\n\t\t},\n\t\t{\n\t\t\tName:    \"f2\",\n\t\t\tPkgPath: \"p2\",\n\t\t\tType:    TypeOf(int(0)),\n\t\t},\n\t}\n\tshouldPanic(\"different PkgPath\", func() {\n\t\tStructOf(fields)\n\t})\n}\n\nfunc TestStructOfTooLarge(t *testing.T) {\n\tt1 := TypeOf(byte(0))\n\tt2 := TypeOf(int16(0))\n\tt4 := TypeOf(int32(0))\n\tt0 := ArrayOf(0, t1)\n\n\t// 2^64-3 sized type (or 2^32-3 on 32-bit archs)\n\tbigType := StructOf([]StructField{\n\t\t{Name: \"F1\", Type: ArrayOf(int(^uintptr(0)>>1), t1)},\n\t\t{Name: \"F2\", Type: ArrayOf(int(^uintptr(0)>>1-1), t1)},\n\t})\n\n\ttype test struct {\n\t\tshouldPanic bool\n\t\tfields      []StructField\n\t}\n\n\ttests := [...]test{\n\t\t{\n\t\t\tshouldPanic: false, // 2^64-1, ok\n\t\t\tfields: []StructField{\n\t\t\t\t{Name: \"F1\", Type: bigType},\n\t\t\t\t{Name: \"F2\", Type: ArrayOf(2, t1)},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tshouldPanic: true, // overflow in total size\n\t\t\tfields: []StructField{\n\t\t\t\t{Name: \"F1\", Type: bigType},\n\t\t\t\t{Name: \"F2\", Type: ArrayOf(3, t1)},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tshouldPanic: true, // overflow while aligning F2\n\t\t\tfields: []StructField{\n\t\t\t\t{Name: \"F1\", Type: bigType},\n\t\t\t\t{Name: \"F2\", Type: t4},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tshouldPanic: true, // overflow while adding trailing byte for zero-sized fields\n\t\t\tfields: []StructField{\n\t\t\t\t{Name: \"F1\", Type: bigType},\n\t\t\t\t{Name: \"F2\", Type: ArrayOf(2, t1)},\n\t\t\t\t{Name: \"F3\", Type: t0},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tshouldPanic: true, // overflow while aligning total size\n\t\t\tfields: []StructField{\n\t\t\t\t{Name: \"F1\", Type: t2},\n\t\t\t\t{Name: \"F2\", Type: bigType},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor i, tt := range tests {\n\t\tfunc() {\n\t\t\tdefer func() {\n\t\t\t\terr := recover()\n\t\t\t\tif !tt.shouldPanic {\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tt.Errorf(\"test %d should not panic, got %s\", i, err)\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif err == nil {\n\t\t\t\t\tt.Errorf(\"test %d expected to panic\", i)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\ts := fmt.Sprintf(\"%s\", err)\n\t\t\t\tif s != \"reflect.StructOf: struct size would exceed virtual address space\" {\n\t\t\t\t\tt.Errorf(\"test %d wrong panic message: %s\", i, s)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}()\n\t\t\t_ = StructOf(tt.fields)\n\t\t}()\n\t}\n}\n\nfunc TestChanOf(t *testing.T) {\n\t// check construction and use of type not in binary\n\ttype T string\n\tct := ChanOf(BothDir, TypeOf(T(\"\")))\n\tv := MakeChan(ct, 2)\n\truntime.GC()\n\tv.Send(ValueOf(T(\"hello\")))\n\truntime.GC()\n\tv.Send(ValueOf(T(\"world\")))\n\truntime.GC()\n\n\tsv1, _ := v.Recv()\n\tsv2, _ := v.Recv()\n\ts1 := sv1.String()\n\ts2 := sv2.String()\n\tif s1 != \"hello\" || s2 != \"world\" {\n\t\tt.Errorf(\"constructed chan: have %q, %q, want %q, %q\", s1, s2, \"hello\", \"world\")\n\t}\n\n\t// check that type already in binary is found\n\ttype T1 int\n\tcheckSameType(t, ChanOf(BothDir, TypeOf(T1(1))), (chan T1)(nil))\n\n\t// Check arrow token association in undefined chan types.\n\tvar left chan<- chan T\n\tvar right chan (<-chan T)\n\ttLeft := ChanOf(SendDir, ChanOf(BothDir, TypeOf(T(\"\"))))\n\ttRight := ChanOf(BothDir, ChanOf(RecvDir, TypeOf(T(\"\"))))\n\tif tLeft != TypeOf(left) {\n\t\tt.Errorf(\"chan<-chan: have %s, want %T\", tLeft, left)\n\t}\n\tif tRight != TypeOf(right) {\n\t\tt.Errorf(\"chan<-chan: have %s, want %T\", tRight, right)\n\t}\n}\n\nfunc TestChanOfDir(t *testing.T) {\n\t// check construction and use of type not in binary\n\ttype T string\n\tcrt := ChanOf(RecvDir, TypeOf(T(\"\")))\n\tcst := ChanOf(SendDir, TypeOf(T(\"\")))\n\n\t// check that type already in binary is found\n\ttype T1 int\n\tcheckSameType(t, ChanOf(RecvDir, TypeOf(T1(1))), (<-chan T1)(nil))\n\tcheckSameType(t, ChanOf(SendDir, TypeOf(T1(1))), (chan<- T1)(nil))\n\n\t// check String form of ChanDir\n\tif crt.ChanDir().String() != \"<-chan\" {\n\t\tt.Errorf(\"chan dir: have %q, want %q\", crt.ChanDir().String(), \"<-chan\")\n\t}\n\tif cst.ChanDir().String() != \"chan<-\" {\n\t\tt.Errorf(\"chan dir: have %q, want %q\", cst.ChanDir().String(), \"chan<-\")\n\t}\n}\n\nfunc TestChanOfGC(t *testing.T) {\n\tdone := make(chan bool, 1)\n\tgo func() {\n\t\tselect {\n\t\tcase <-done:\n\t\tcase <-time.After(5 * time.Second):\n\t\t\tpanic(\"deadlock in TestChanOfGC\")\n\t\t}\n\t}()\n\n\tdefer func() {\n\t\tdone <- true\n\t}()\n\n\ttype T *uintptr\n\ttt := TypeOf(T(nil))\n\tct := ChanOf(BothDir, tt)\n\n\t// NOTE: The garbage collector handles allocated channels specially,\n\t// so we have to save pointers to channels in x; the pointer code will\n\t// use the gc info in the newly constructed chan type.\n\tconst n = 100\n\tvar x []any\n\tfor i := 0; i < n; i++ {\n\t\tv := MakeChan(ct, n)\n\t\tfor j := 0; j < n; j++ {\n\t\t\tp := new(uintptr)\n\t\t\t*p = uintptr(i*n + j)\n\t\t\tv.Send(ValueOf(p).Convert(tt))\n\t\t}\n\t\tpv := New(ct)\n\t\tpv.Elem().Set(v)\n\t\tx = append(x, pv.Interface())\n\t}\n\truntime.GC()\n\n\tfor i, xi := range x {\n\t\tv := ValueOf(xi).Elem()\n\t\tfor j := 0; j < n; j++ {\n\t\t\tpv, _ := v.Recv()\n\t\t\tk := pv.Elem().Interface()\n\t\t\tif k != uintptr(i*n+j) {\n\t\t\t\tt.Errorf(\"lost x[%d][%d] = %d, want %d\", i, j, k, i*n+j)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestMapOf(t *testing.T) {\n\t// check construction and use of type not in binary\n\ttype K string\n\ttype V float64\n\n\tv := MakeMap(MapOf(TypeOf(K(\"\")), TypeOf(V(0))))\n\truntime.GC()\n\tv.SetMapIndex(ValueOf(K(\"a\")), ValueOf(V(1)))\n\truntime.GC()\n\n\ts := fmt.Sprint(v.Interface())\n\twant := \"map[a:1]\"\n\tif s != want {\n\t\tt.Errorf(\"constructed map = %s, want %s\", s, want)\n\t}\n\n\t// check that type already in binary is found\n\tcheckSameType(t, MapOf(TypeOf(V(0)), TypeOf(K(\"\"))), map[V]K(nil))\n\n\t// check that invalid key type panics\n\tshouldPanic(\"invalid key type\", func() { MapOf(TypeOf((func())(nil)), TypeOf(false)) })\n}\n\nfunc TestMapOfGCKeys(t *testing.T) {\n\ttype T *uintptr\n\ttt := TypeOf(T(nil))\n\tmt := MapOf(tt, TypeOf(false))\n\n\t// NOTE: The garbage collector handles allocated maps specially,\n\t// so we have to save pointers to maps in x; the pointer code will\n\t// use the gc info in the newly constructed map type.\n\tconst n = 100\n\tvar x []any\n\tfor i := 0; i < n; i++ {\n\t\tv := MakeMap(mt)\n\t\tfor j := 0; j < n; j++ {\n\t\t\tp := new(uintptr)\n\t\t\t*p = uintptr(i*n + j)\n\t\t\tv.SetMapIndex(ValueOf(p).Convert(tt), ValueOf(true))\n\t\t}\n\t\tpv := New(mt)\n\t\tpv.Elem().Set(v)\n\t\tx = append(x, pv.Interface())\n\t}\n\truntime.GC()\n\n\tfor i, xi := range x {\n\t\tv := ValueOf(xi).Elem()\n\t\tvar out []int\n\t\tfor _, kv := range v.MapKeys() {\n\t\t\tout = append(out, int(kv.Elem().Interface().(uintptr)))\n\t\t}\n\t\tsort.Ints(out)\n\t\tfor j, k := range out {\n\t\t\tif k != i*n+j {\n\t\t\t\tt.Errorf(\"lost x[%d][%d] = %d, want %d\", i, j, k, i*n+j)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestMapOfGCValues(t *testing.T) {\n\ttype T *uintptr\n\ttt := TypeOf(T(nil))\n\tmt := MapOf(TypeOf(1), tt)\n\n\t// NOTE: The garbage collector handles allocated maps specially,\n\t// so we have to save pointers to maps in x; the pointer code will\n\t// use the gc info in the newly constructed map type.\n\tconst n = 100\n\tvar x []any\n\tfor i := 0; i < n; i++ {\n\t\tv := MakeMap(mt)\n\t\tfor j := 0; j < n; j++ {\n\t\t\tp := new(uintptr)\n\t\t\t*p = uintptr(i*n + j)\n\t\t\tv.SetMapIndex(ValueOf(j), ValueOf(p).Convert(tt))\n\t\t}\n\t\tpv := New(mt)\n\t\tpv.Elem().Set(v)\n\t\tx = append(x, pv.Interface())\n\t}\n\truntime.GC()\n\n\tfor i, xi := range x {\n\t\tv := ValueOf(xi).Elem()\n\t\tfor j := 0; j < n; j++ {\n\t\t\tk := v.MapIndex(ValueOf(j)).Elem().Interface().(uintptr)\n\t\t\tif k != uintptr(i*n+j) {\n\t\t\t\tt.Errorf(\"lost x[%d][%d] = %d, want %d\", i, j, k, i*n+j)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestTypelinksSorted(t *testing.T) {\n\tvar last string\n\tfor i, n := range TypeLinks() {\n\t\tif n < last {\n\t\t\tt.Errorf(\"typelinks not sorted: %q [%d] > %q [%d]\", last, i-1, n, i)\n\t\t}\n\t\tlast = n\n\t}\n}\n\nfunc TestFuncOf(t *testing.T) {\n\t// check construction and use of type not in binary\n\ttype K string\n\ttype V float64\n\n\tfn := func(args []Value) []Value {\n\t\tif len(args) != 1 {\n\t\t\tt.Errorf(\"args == %v, want exactly one arg\", args)\n\t\t} else if args[0].Type() != TypeOf(K(\"\")) {\n\t\t\tt.Errorf(\"args[0] is type %v, want %v\", args[0].Type(), TypeOf(K(\"\")))\n\t\t} else if args[0].String() != \"gopher\" {\n\t\t\tt.Errorf(\"args[0] = %q, want %q\", args[0].String(), \"gopher\")\n\t\t}\n\t\treturn []Value{ValueOf(V(3.14))}\n\t}\n\tv := MakeFunc(FuncOf([]Type{TypeOf(K(\"\"))}, []Type{TypeOf(V(0))}, false), fn)\n\n\touts := v.Call([]Value{ValueOf(K(\"gopher\"))})\n\tif len(outs) != 1 {\n\t\tt.Fatalf(\"v.Call returned %v, want exactly one result\", outs)\n\t} else if outs[0].Type() != TypeOf(V(0)) {\n\t\tt.Fatalf(\"c.Call[0] is type %v, want %v\", outs[0].Type(), TypeOf(V(0)))\n\t}\n\tf := outs[0].Float()\n\tif f != 3.14 {\n\t\tt.Errorf(\"constructed func returned %f, want %f\", f, 3.14)\n\t}\n\n\t// check that types already in binary are found\n\ttype T1 int\n\ttestCases := []struct {\n\t\tin, out  []Type\n\t\tvariadic bool\n\t\twant     any\n\t}{\n\t\t{in: []Type{TypeOf(T1(0))}, want: (func(T1))(nil)},\n\t\t{in: []Type{TypeOf(int(0))}, want: (func(int))(nil)},\n\t\t{in: []Type{SliceOf(TypeOf(int(0)))}, variadic: true, want: (func(...int))(nil)},\n\t\t{in: []Type{TypeOf(int(0))}, out: []Type{TypeOf(false)}, want: (func(int) bool)(nil)},\n\t\t{in: []Type{TypeOf(int(0))}, out: []Type{TypeOf(false), TypeOf(\"\")}, want: (func(int) (bool, string))(nil)},\n\t}\n\tfor _, tt := range testCases {\n\t\tcheckSameType(t, FuncOf(tt.in, tt.out, tt.variadic), tt.want)\n\t}\n\n\t// check that variadic requires last element be a slice.\n\tFuncOf([]Type{TypeOf(1), TypeOf(\"\"), SliceOf(TypeOf(false))}, nil, true)\n\tshouldPanic(\"must be slice\", func() { FuncOf([]Type{TypeOf(0), TypeOf(\"\"), TypeOf(false)}, nil, true) })\n\tshouldPanic(\"must be slice\", func() { FuncOf(nil, nil, true) })\n\n\t//testcase for  #54669\n\tvar in []Type\n\tfor i := 0; i < 51; i++ {\n\t\tin = append(in, TypeOf(1))\n\t}\n\tFuncOf(in, nil, false)\n}\n\n*/\n\ntype R0 struct {\n\t*R1\n\t*R2\n\t*R3\n\t*R4\n}\n\ntype R1 struct {\n\t*R5\n\t*R6\n\t*R7\n\t*R8\n}\n\ntype R2 R1\ntype R3 R1\ntype R4 R1\n\ntype R5 struct {\n\t*R9\n\t*R10\n\t*R11\n\t*R12\n}\n\ntype R6 R5\ntype R7 R5\ntype R8 R5\n\ntype R9 struct {\n\t*R13\n\t*R14\n\t*R15\n\t*R16\n}\n\ntype R10 R9\ntype R11 R9\ntype R12 R9\n\ntype R13 struct {\n\t*R17\n\t*R18\n\t*R19\n\t*R20\n}\n\ntype R14 R13\ntype R15 R13\ntype R16 R13\n\ntype R17 struct {\n\t*R21\n\t*R22\n\t*R23\n\t*R24\n}\n\ntype R18 R17\ntype R19 R17\ntype R20 R17\n\ntype R21 struct {\n\tX int\n}\n\ntype R22 R21\ntype R23 R21\ntype R24 R21\n\nfunc TestEmbed(t *testing.T) {\n\ttyp := TypeOf(R0{})\n\tf, ok := typ.FieldByName(\"X\")\n\tif ok {\n\t\tt.Fatalf(`FieldByName(\"X\") should fail, returned %v`, f.Index)\n\t}\n}\n\n/*\n\nfunc TestAllocsInterfaceBig(t *testing.T) {\n\tif testing.Short() {\n\t\tt.Skip(\"skipping malloc count in short mode\")\n\t}\n\tv := ValueOf(S{})\n\tif allocs := testing.AllocsPerRun(100, func() { v.Interface() }); allocs > 0 {\n\t\tt.Error(\"allocs:\", allocs)\n\t}\n}\n\nfunc TestAllocsInterfaceSmall(t *testing.T) {\n\tif testing.Short() {\n\t\tt.Skip(\"skipping malloc count in short mode\")\n\t}\n\tv := ValueOf(int64(0))\n\tif allocs := testing.AllocsPerRun(100, func() { v.Interface() }); allocs > 0 {\n\t\tt.Error(\"allocs:\", allocs)\n\t}\n}\n\n// An exhaustive is a mechanism for writing exhaustive or stochastic tests.\n// The basic usage is:\n//\n//\tfor x.Next() {\n//\t\t... code using x.Maybe() or x.Choice(n) to create test cases ...\n//\t}\n//\n// Each iteration of the loop returns a different set of results, until all\n// possible result sets have been explored. It is okay for different code paths\n// to make different method call sequences on x, but there must be no\n// other source of non-determinism in the call sequences.\n//\n// When faced with a new decision, x chooses randomly. Future explorations\n// of that path will choose successive values for the result. Thus, stopping\n// the loop after a fixed number of iterations gives somewhat stochastic\n// testing.\n//\n// Example:\n//\n//\tfor x.Next() {\n//\t\tv := make([]bool, x.Choose(4))\n//\t\tfor i := range v {\n//\t\t\tv[i] = x.Maybe()\n//\t\t}\n//\t\tfmt.Println(v)\n//\t}\n//\n// prints (in some order):\n//\n//\t[]\n//\t[false]\n//\t[true]\n//\t[false false]\n//\t[false true]\n//\t...\n//\t[true true]\n//\t[false false false]\n//\t...\n//\t[true true true]\n//\t[false false false false]\n//\t...\n//\t[true true true true]\ntype exhaustive struct {\n\tr    *rand.Rand\n\tpos  int\n\tlast []choice\n}\n\ntype choice struct {\n\toff int\n\tn   int\n\tmax int\n}\n\nfunc (x *exhaustive) Next() bool {\n\tif x.r == nil {\n\t\tx.r = rand.New(rand.NewSource(time.Now().UnixNano()))\n\t}\n\tx.pos = 0\n\tif x.last == nil {\n\t\tx.last = []choice{}\n\t\treturn true\n\t}\n\tfor i := len(x.last) - 1; i >= 0; i-- {\n\t\tc := &x.last[i]\n\t\tif c.n+1 < c.max {\n\t\t\tc.n++\n\t\t\tx.last = x.last[:i+1]\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc (x *exhaustive) Choose(max int) int {\n\tif x.pos >= len(x.last) {\n\t\tx.last = append(x.last, choice{x.r.Intn(max), 0, max})\n\t}\n\tc := &x.last[x.pos]\n\tx.pos++\n\tif c.max != max {\n\t\tpanic(\"inconsistent use of exhaustive tester\")\n\t}\n\treturn (c.n + c.off) % max\n}\n\nfunc (x *exhaustive) Maybe() bool {\n\treturn x.Choose(2) == 1\n}\n\nfunc GCFunc(args []Value) []Value {\n\truntime.GC()\n\treturn []Value{}\n}\n\nfunc TestReflectFuncTraceback(t *testing.T) {\n\tf := MakeFunc(TypeOf(func() {}), GCFunc)\n\tf.Call([]Value{})\n}\n\nfunc TestReflectMethodTraceback(t *testing.T) {\n\tp := Point{3, 4}\n\tm := ValueOf(p).MethodByName(\"GCMethod\")\n\ti := ValueOf(m.Interface()).Call([]Value{ValueOf(5)})[0].Int()\n\tif i != 8 {\n\t\tt.Errorf(\"Call returned %d; want 8\", i)\n\t}\n}\n\nfunc TestSmallZero(t *testing.T) {\n\ttype T [10]byte\n\ttyp := TypeOf(T{})\n\tif allocs := testing.AllocsPerRun(100, func() { Zero(typ) }); allocs > 0 {\n\t\tt.Errorf(\"Creating small zero values caused %f allocs, want 0\", allocs)\n\t}\n}\n\nfunc TestBigZero(t *testing.T) {\n\tconst size = 1 << 10\n\tvar v [size]byte\n\tz := Zero(ValueOf(v).Type()).Interface().([size]byte)\n\tfor i := 0; i < size; i++ {\n\t\tif z[i] != 0 {\n\t\t\tt.Fatalf(\"Zero object not all zero, index %d\", i)\n\t\t}\n\t}\n}\n\nfunc TestZeroSet(t *testing.T) {\n\ttype T [16]byte\n\ttype S struct {\n\t\ta uint64\n\t\tT T\n\t\tb uint64\n\t}\n\tv := S{\n\t\ta: 0xaaaaaaaaaaaaaaaa,\n\t\tT: T{9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9},\n\t\tb: 0xbbbbbbbbbbbbbbbb,\n\t}\n\tValueOf(&v).Elem().Field(1).Set(Zero(TypeOf(T{})))\n\tif v != (S{\n\t\ta: 0xaaaaaaaaaaaaaaaa,\n\t\tb: 0xbbbbbbbbbbbbbbbb,\n\t}) {\n\t\tt.Fatalf(\"Setting a field to a Zero value didn't work\")\n\t}\n}\n\nfunc TestFieldByIndexNil(t *testing.T) {\n\ttype P struct {\n\t\tF int\n\t}\n\ttype T struct {\n\t\t*P\n\t}\n\tv := ValueOf(T{})\n\n\tv.FieldByName(\"P\") // should be fine\n\n\tdefer func() {\n\t\tif err := recover(); err == nil {\n\t\t\tt.Fatalf(\"no error\")\n\t\t} else if !strings.Contains(fmt.Sprint(err), \"nil pointer to embedded struct\") {\n\t\t\tt.Fatalf(`err=%q, wanted error containing \"nil pointer to embedded struct\"`, err)\n\t\t}\n\t}()\n\tv.FieldByName(\"F\") // should panic\n\n\tt.Fatalf(\"did not panic\")\n}\n\n// Given\n//\ttype Outer struct {\n//\t\t*Inner\n//\t\t...\n//\t}\n// the compiler generates the implementation of (*Outer).M dispatching to the embedded Inner.\n// The implementation is logically:\n//\tfunc (p *Outer) M() {\n//\t\t(p.Inner).M()\n//\t}\n// but since the only change here is the replacement of one pointer receiver with another,\n// the actual generated code overwrites the original receiver with the p.Inner pointer and\n// then jumps to the M method expecting the *Inner receiver.\n//\n// During reflect.Value.Call, we create an argument frame and the associated data structures\n// to describe it to the garbage collector, populate the frame, call reflect.call to\n// run a function call using that frame, and then copy the results back out of the frame.\n// The reflect.call function does a memmove of the frame structure onto the\n// stack (to set up the inputs), runs the call, and the memmoves the stack back to\n// the frame structure (to preserve the outputs).\n//\n// Originally reflect.call did not distinguish inputs from outputs: both memmoves\n// were for the full stack frame. However, in the case where the called function was\n// one of these wrappers, the rewritten receiver is almost certainly a different type\n// than the original receiver. This is not a problem on the stack, where we use the\n// program counter to determine the type information and understand that\n// during (*Outer).M the receiver is an *Outer while during (*Inner).M the receiver in the same\n// memory word is now an *Inner. But in the statically typed argument frame created\n// by reflect, the receiver is always an *Outer. Copying the modified receiver pointer\n// off the stack into the frame will store an *Inner there, and then if a garbage collection\n// happens to scan that argument frame before it is discarded, it will scan the *Inner\n// memory as if it were an *Outer. If the two have different memory layouts, the\n// collection will interpret the memory incorrectly.\n//\n// One such possible incorrect interpretation is to treat two arbitrary memory words\n// (Inner.P1 and Inner.P2 below) as an interface (Outer.R below). Because interpreting\n// an interface requires dereferencing the itab word, the misinterpretation will try to\n// deference Inner.P1, causing a crash during garbage collection.\n//\n// This came up in a real program in issue 7725.\n\ntype Outer struct {\n\t*Inner\n\tR io.Reader\n}\n\ntype Inner struct {\n\tX  *Outer\n\tP1 uintptr\n\tP2 uintptr\n}\n\nfunc (pi *Inner) M() {\n\t// Clear references to pi so that the only way the\n\t// garbage collection will find the pointer is in the\n\t// argument frame, typed as a *Outer.\n\tpi.X.Inner = nil\n\n\t// Set up an interface value that will cause a crash.\n\t// P1 = 1 is a non-zero, so the interface looks non-nil.\n\t// P2 = pi ensures that the data word points into the\n\t// allocated heap; if not the collection skips the interface\n\t// value as irrelevant, without dereferencing P1.\n\tpi.P1 = 1\n\tpi.P2 = uintptr(unsafe.Pointer(pi))\n}\n\nfunc TestCallMethodJump(t *testing.T) {\n\t// In reflect.Value.Call, trigger a garbage collection after reflect.call\n\t// returns but before the args frame has been discarded.\n\t// This is a little clumsy but makes the failure repeatable.\n\t*CallGC = true\n\n\tp := &Outer{Inner: new(Inner)}\n\tp.Inner.X = p\n\tValueOf(p).Method(0).Call(nil)\n\n\t// Stop garbage collecting during reflect.call.\n\t*CallGC = false\n}\n\nfunc TestCallArgLive(t *testing.T) {\n\ttype T struct{ X, Y *string } // pointerful aggregate\n\n\tF := func(t T) { *t.X = \"ok\" }\n\n\t// In reflect.Value.Call, trigger a garbage collection in reflect.call\n\t// between marshaling argument and the actual call.\n\t*CallGC = true\n\n\tx := new(string)\n\truntime.SetFinalizer(x, func(p *string) {\n\t\tif *p != \"ok\" {\n\t\t\tt.Errorf(\"x dead prematurely\")\n\t\t}\n\t})\n\tv := T{x, nil}\n\n\tValueOf(F).Call([]Value{ValueOf(v)})\n\n\t// Stop garbage collecting during reflect.call.\n\t*CallGC = false\n}\n\nfunc TestMakeFuncStackCopy(t *testing.T) {\n\ttarget := func(in []Value) []Value {\n\t\truntime.GC()\n\t\tuseStack(16)\n\t\treturn []Value{ValueOf(9)}\n\t}\n\n\tvar concrete func(*int, int) int\n\tfn := MakeFunc(ValueOf(concrete).Type(), target)\n\tValueOf(&concrete).Elem().Set(fn)\n\tx := concrete(nil, 7)\n\tif x != 9 {\n\t\tt.Errorf(\"have %#q want 9\", x)\n\t}\n}\n\n// use about n KB of stack\nfunc useStack(n int) {\n\tif n == 0 {\n\t\treturn\n\t}\n\tvar b [1024]byte // makes frame about 1KB\n\tuseStack(n - 1 + int(b[99]))\n}\n\ntype Impl struct{}\n\nfunc (Impl) F() {}\n\nfunc TestValueString(t *testing.T) {\n\trv := ValueOf(Impl{})\n\tif rv.String() != \"<reflect_test.Impl Value>\" {\n\t\tt.Errorf(\"ValueOf(Impl{}).String() = %q, want %q\", rv.String(), \"<reflect_test.Impl Value>\")\n\t}\n\n\tmethod := rv.Method(0)\n\tif method.String() != \"<func() Value>\" {\n\t\tt.Errorf(\"ValueOf(Impl{}).Method(0).String() = %q, want %q\", method.String(), \"<func() Value>\")\n\t}\n}\n\n*/\n\nfunc TestInvalid(t *testing.T) {\n\t// Used to have inconsistency between IsValid() and Kind() != Invalid.\n\ttype T struct{ v any }\n\n\tv := ValueOf(T{}).Field(0)\n\tif v.IsValid() != true || v.Kind() != Interface {\n\t\tt.Errorf(\"field: IsValid=%v, Kind=%v, want true, Interface\", v.IsValid(), v.Kind())\n\t}\n\tv = v.Elem()\n\tif v.IsValid() != false || v.Kind() != Invalid {\n\t\tt.Errorf(\"field elem: IsValid=%v, Kind=%v, want false, Invalid\", v.IsValid(), v.Kind())\n\t}\n}\n\n/*\n\n// Issue 8917.\nfunc TestLargeGCProg(t *testing.T) {\n\tfv := ValueOf(func([256]*byte) {})\n\tfv.Call([]Value{ValueOf([256]*byte{})})\n}\n\nfunc fieldIndexRecover(t Type, i int) (recovered any) {\n\tdefer func() {\n\t\trecovered = recover()\n\t}()\n\n\tt.Field(i)\n\treturn\n}\n\n// Issue 15046.\nfunc TestTypeFieldOutOfRangePanic(t *testing.T) {\n\ttyp := TypeOf(struct{ X int }{10})\n\ttestIndices := [...]struct {\n\t\ti         int\n\t\tmustPanic bool\n\t}{\n\t\t0: {-2, true},\n\t\t1: {0, false},\n\t\t2: {1, true},\n\t\t3: {1 << 10, true},\n\t}\n\tfor i, tt := range testIndices {\n\t\trecoveredErr := fieldIndexRecover(typ, tt.i)\n\t\tif tt.mustPanic {\n\t\t\tif recoveredErr == nil {\n\t\t\t\tt.Errorf(\"#%d: fieldIndex %d expected to panic\", i, tt.i)\n\t\t\t}\n\t\t} else {\n\t\t\tif recoveredErr != nil {\n\t\t\t\tt.Errorf(\"#%d: got err=%v, expected no panic\", i, recoveredErr)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Issue 9179.\nfunc TestCallGC(t *testing.T) {\n\tf := func(a, b, c, d, e string) {\n\t}\n\tg := func(in []Value) []Value {\n\t\truntime.GC()\n\t\treturn nil\n\t}\n\ttyp := ValueOf(f).Type()\n\tf2 := MakeFunc(typ, g).Interface().(func(string, string, string, string, string))\n\tf2(\"four\", \"five5\", \"six666\", \"seven77\", \"eight888\")\n}\n\n// Issue 18635 (function version).\nfunc TestKeepFuncLive(t *testing.T) {\n\t// Test that we keep makeFuncImpl live as long as it is\n\t// referenced on the stack.\n\ttyp := TypeOf(func(i int) {})\n\tvar f, g func(in []Value) []Value\n\tf = func(in []Value) []Value {\n\t\tclobber()\n\t\ti := int(in[0].Int())\n\t\tif i > 0 {\n\t\t\t// We can't use Value.Call here because\n\t\t\t// runtime.call* will keep the makeFuncImpl\n\t\t\t// alive. However, by converting it to an\n\t\t\t// interface value and calling that,\n\t\t\t// reflect.callReflect is the only thing that\n\t\t\t// can keep the makeFuncImpl live.\n\t\t\t//\n\t\t\t// Alternate between f and g so that if we do\n\t\t\t// reuse the memory prematurely it's more\n\t\t\t// likely to get obviously corrupted.\n\t\t\tMakeFunc(typ, g).Interface().(func(i int))(i - 1)\n\t\t}\n\t\treturn nil\n\t}\n\tg = func(in []Value) []Value {\n\t\tclobber()\n\t\ti := int(in[0].Int())\n\t\tMakeFunc(typ, f).Interface().(func(i int))(i)\n\t\treturn nil\n\t}\n\tMakeFunc(typ, f).Call([]Value{ValueOf(10)})\n}\n\ntype UnExportedFirst int\n\nfunc (i UnExportedFirst) ΦExported()  {}\nfunc (i UnExportedFirst) unexported() {}\n\n// Issue 21177\nfunc TestMethodByNameUnExportedFirst(t *testing.T) {\n\tdefer func() {\n\t\tif recover() != nil {\n\t\t\tt.Errorf(\"should not panic\")\n\t\t}\n\t}()\n\ttyp := TypeOf(UnExportedFirst(0))\n\tm, _ := typ.MethodByName(\"ΦExported\")\n\tif m.Name != \"ΦExported\" {\n\t\tt.Errorf(\"got %s, expected ΦExported\", m.Name)\n\t}\n}\n\n// Issue 18635 (method version).\ntype KeepMethodLive struct{}\n\nfunc (k KeepMethodLive) Method1(i int) {\n\tclobber()\n\tif i > 0 {\n\t\tValueOf(k).MethodByName(\"Method2\").Interface().(func(i int))(i - 1)\n\t}\n}\n\nfunc (k KeepMethodLive) Method2(i int) {\n\tclobber()\n\tValueOf(k).MethodByName(\"Method1\").Interface().(func(i int))(i)\n}\n\nfunc TestKeepMethodLive(t *testing.T) {\n\t// Test that we keep methodValue live as long as it is\n\t// referenced on the stack.\n\tKeepMethodLive{}.Method1(10)\n}\n\n// clobber tries to clobber unreachable memory.\nfunc clobber() {\n\truntime.GC()\n\tfor i := 1; i < 32; i++ {\n\t\tfor j := 0; j < 10; j++ {\n\t\t\tobj := make([]*byte, i)\n\t\t\tsink = obj\n\t\t}\n\t}\n\truntime.GC()\n}\n\nfunc TestFuncLayout(t *testing.T) {\n\talign := func(x uintptr) uintptr {\n\t\treturn (x + goarch.PtrSize - 1) &^ (goarch.PtrSize - 1)\n\t}\n\tvar r []byte\n\tif goarch.PtrSize == 4 {\n\t\tr = []byte{0, 0, 0, 1}\n\t} else {\n\t\tr = []byte{0, 0, 1}\n\t}\n\n\ttype S struct {\n\t\ta, b uintptr\n\t\tc, d *byte\n\t}\n\n\ttype test struct {\n\t\trcvr, typ                  Type\n\t\tsize, argsize, retOffset   uintptr\n\t\tstack, gc, inRegs, outRegs []byte // pointer bitmap: 1 is pointer, 0 is scalar\n\t\tintRegs, floatRegs         int\n\t\tfloatRegSize               uintptr\n\t}\n\ttests := []test{\n\t\t{\n\t\t\ttyp:       ValueOf(func(a, b string) string { return \"\" }).Type(),\n\t\t\tsize:      6 * goarch.PtrSize,\n\t\t\targsize:   4 * goarch.PtrSize,\n\t\t\tretOffset: 4 * goarch.PtrSize,\n\t\t\tstack:     []byte{1, 0, 1, 0, 1},\n\t\t\tgc:        []byte{1, 0, 1, 0, 1},\n\t\t},\n\t\t{\n\t\t\ttyp:       ValueOf(func(a, b, c uint32, p *byte, d uint16) {}).Type(),\n\t\t\tsize:      align(align(3*4) + goarch.PtrSize + 2),\n\t\t\targsize:   align(3*4) + goarch.PtrSize + 2,\n\t\t\tretOffset: align(align(3*4) + goarch.PtrSize + 2),\n\t\t\tstack:     r,\n\t\t\tgc:        r,\n\t\t},\n\t\t{\n\t\t\ttyp:       ValueOf(func(a map[int]int, b uintptr, c any) {}).Type(),\n\t\t\tsize:      4 * goarch.PtrSize,\n\t\t\targsize:   4 * goarch.PtrSize,\n\t\t\tretOffset: 4 * goarch.PtrSize,\n\t\t\tstack:     []byte{1, 0, 1, 1},\n\t\t\tgc:        []byte{1, 0, 1, 1},\n\t\t},\n\t\t{\n\t\t\ttyp:       ValueOf(func(a S) {}).Type(),\n\t\t\tsize:      4 * goarch.PtrSize,\n\t\t\targsize:   4 * goarch.PtrSize,\n\t\t\tretOffset: 4 * goarch.PtrSize,\n\t\t\tstack:     []byte{0, 0, 1, 1},\n\t\t\tgc:        []byte{0, 0, 1, 1},\n\t\t},\n\t\t{\n\t\t\trcvr:      ValueOf((*byte)(nil)).Type(),\n\t\t\ttyp:       ValueOf(func(a uintptr, b *int) {}).Type(),\n\t\t\tsize:      3 * goarch.PtrSize,\n\t\t\targsize:   3 * goarch.PtrSize,\n\t\t\tretOffset: 3 * goarch.PtrSize,\n\t\t\tstack:     []byte{1, 0, 1},\n\t\t\tgc:        []byte{1, 0, 1},\n\t\t},\n\t\t{\n\t\t\ttyp:       ValueOf(func(a uintptr) {}).Type(),\n\t\t\tsize:      goarch.PtrSize,\n\t\t\targsize:   goarch.PtrSize,\n\t\t\tretOffset: goarch.PtrSize,\n\t\t\tstack:     []byte{},\n\t\t\tgc:        []byte{},\n\t\t},\n\t\t{\n\t\t\ttyp:       ValueOf(func() uintptr { return 0 }).Type(),\n\t\t\tsize:      goarch.PtrSize,\n\t\t\targsize:   0,\n\t\t\tretOffset: 0,\n\t\t\tstack:     []byte{},\n\t\t\tgc:        []byte{},\n\t\t},\n\t\t{\n\t\t\trcvr:      ValueOf(uintptr(0)).Type(),\n\t\t\ttyp:       ValueOf(func(a uintptr) {}).Type(),\n\t\t\tsize:      2 * goarch.PtrSize,\n\t\t\targsize:   2 * goarch.PtrSize,\n\t\t\tretOffset: 2 * goarch.PtrSize,\n\t\t\tstack:     []byte{1},\n\t\t\tgc:        []byte{1},\n\t\t\t// Note: this one is tricky, as the receiver is not a pointer. But we\n\t\t\t// pass the receiver by reference to the autogenerated pointer-receiver\n\t\t\t// version of the function.\n\t\t},\n\t\t// TODO(mknyszek): Add tests for non-zero register count.\n\t}\n\tfor _, lt := range tests {\n\t\tname := lt.typ.String()\n\t\tif lt.rcvr != nil {\n\t\t\tname = lt.rcvr.String() + \".\" + name\n\t\t}\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\tdefer SetArgRegs(SetArgRegs(lt.intRegs, lt.floatRegs, lt.floatRegSize))\n\n\t\t\ttyp, argsize, retOffset, stack, gc, inRegs, outRegs, ptrs := FuncLayout(lt.typ, lt.rcvr)\n\t\t\tif typ.Size() != lt.size {\n\t\t\t\tt.Errorf(\"funcLayout(%v, %v).size=%d, want %d\", lt.typ, lt.rcvr, typ.Size(), lt.size)\n\t\t\t}\n\t\t\tif argsize != lt.argsize {\n\t\t\t\tt.Errorf(\"funcLayout(%v, %v).argsize=%d, want %d\", lt.typ, lt.rcvr, argsize, lt.argsize)\n\t\t\t}\n\t\t\tif retOffset != lt.retOffset {\n\t\t\t\tt.Errorf(\"funcLayout(%v, %v).retOffset=%d, want %d\", lt.typ, lt.rcvr, retOffset, lt.retOffset)\n\t\t\t}\n\t\t\tif !bytes.Equal(stack, lt.stack) {\n\t\t\t\tt.Errorf(\"funcLayout(%v, %v).stack=%v, want %v\", lt.typ, lt.rcvr, stack, lt.stack)\n\t\t\t}\n\t\t\tif !bytes.Equal(gc, lt.gc) {\n\t\t\t\tt.Errorf(\"funcLayout(%v, %v).gc=%v, want %v\", lt.typ, lt.rcvr, gc, lt.gc)\n\t\t\t}\n\t\t\tif !bytes.Equal(inRegs, lt.inRegs) {\n\t\t\t\tt.Errorf(\"funcLayout(%v, %v).inRegs=%v, want %v\", lt.typ, lt.rcvr, inRegs, lt.inRegs)\n\t\t\t}\n\t\t\tif !bytes.Equal(outRegs, lt.outRegs) {\n\t\t\t\tt.Errorf(\"funcLayout(%v, %v).outRegs=%v, want %v\", lt.typ, lt.rcvr, outRegs, lt.outRegs)\n\t\t\t}\n\t\t\tif ptrs && len(stack) == 0 || !ptrs && len(stack) > 0 {\n\t\t\t\tt.Errorf(\"funcLayout(%v, %v) pointers flag=%v, want %v\", lt.typ, lt.rcvr, ptrs, !ptrs)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// trimBitmap removes trailing 0 elements from b and returns the result.\nfunc trimBitmap(b []byte) []byte {\n\tfor len(b) > 0 && b[len(b)-1] == 0 {\n\t\tb = b[:len(b)-1]\n\t}\n\treturn b\n}\n\nfunc verifyGCBits(t *testing.T, typ Type, bits []byte) {\n\theapBits := GCBits(New(typ).Interface())\n\n\t// Trim scalars at the end, as bits might end in zero,\n\t// e.g. with rep(2, lit(1, 0)).\n\tbits = trimBitmap(bits)\n\n\tif !bytes.Equal(heapBits, bits) {\n\t\t_, _, line, _ := runtime.Caller(1)\n\t\tt.Errorf(\"line %d: heapBits incorrect for %v\\nhave %v\\nwant %v\", line, typ, heapBits, bits)\n\t}\n}\n\nfunc verifyGCBitsSlice(t *testing.T, typ Type, cap int, bits []byte) {\n\t// Creating a slice causes the runtime to repeat a bitmap,\n\t// which exercises a different path from making the compiler\n\t// repeat a bitmap for a small array or executing a repeat in\n\t// a GC program.\n\tval := MakeSlice(typ, 0, cap)\n\tdata := NewAt(ArrayOf(cap, typ), val.UnsafePointer())\n\theapBits := GCBits(data.Interface())\n\t// Repeat the bitmap for the slice size, trimming scalars in\n\t// the last element.\n\tbits = trimBitmap(rep(cap, bits))\n\tif !bytes.Equal(heapBits, bits) {\n\t\t_, _, line, _ := runtime.Caller(1)\n\t\tt.Errorf(\"line %d: heapBits incorrect for make(%v, 0, %v)\\nhave %v\\nwant %v\", line, typ, cap, heapBits, bits)\n\t}\n}\n\nfunc TestGCBits(t *testing.T) {\n\tverifyGCBits(t, TypeOf((*byte)(nil)), []byte{1})\n\n\t// Building blocks for types seen by the compiler (like [2]Xscalar).\n\t// The compiler will create the type structures for the derived types,\n\t// including their GC metadata.\n\ttype Xscalar struct{ x uintptr }\n\ttype Xptr struct{ x *byte }\n\ttype Xptrscalar struct {\n\t\t*byte\n\t\tuintptr\n\t}\n\ttype Xscalarptr struct {\n\t\tuintptr\n\t\t*byte\n\t}\n\ttype Xbigptrscalar struct {\n\t\t_ [100]*byte\n\t\t_ [100]uintptr\n\t}\n\n\tvar Tscalar, Tint64, Tptr, Tscalarptr, Tptrscalar, Tbigptrscalar Type\n\t{\n\t\t// Building blocks for types constructed by reflect.\n\t\t// This code is in a separate block so that code below\n\t\t// cannot accidentally refer to these.\n\t\t// The compiler must NOT see types derived from these\n\t\t// (for example, [2]Scalar must NOT appear in the program),\n\t\t// or else reflect will use it instead of having to construct one.\n\t\t// The goal is to test the construction.\n\t\ttype Scalar struct{ x uintptr }\n\t\ttype Ptr struct{ x *byte }\n\t\ttype Ptrscalar struct {\n\t\t\t*byte\n\t\t\tuintptr\n\t\t}\n\t\ttype Scalarptr struct {\n\t\t\tuintptr\n\t\t\t*byte\n\t\t}\n\t\ttype Bigptrscalar struct {\n\t\t\t_ [100]*byte\n\t\t\t_ [100]uintptr\n\t\t}\n\t\ttype Int64 int64\n\t\tTscalar = TypeOf(Scalar{})\n\t\tTint64 = TypeOf(Int64(0))\n\t\tTptr = TypeOf(Ptr{})\n\t\tTscalarptr = TypeOf(Scalarptr{})\n\t\tTptrscalar = TypeOf(Ptrscalar{})\n\t\tTbigptrscalar = TypeOf(Bigptrscalar{})\n\t}\n\n\tempty := []byte{}\n\n\tverifyGCBits(t, TypeOf(Xscalar{}), empty)\n\tverifyGCBits(t, Tscalar, empty)\n\tverifyGCBits(t, TypeOf(Xptr{}), lit(1))\n\tverifyGCBits(t, Tptr, lit(1))\n\tverifyGCBits(t, TypeOf(Xscalarptr{}), lit(0, 1))\n\tverifyGCBits(t, Tscalarptr, lit(0, 1))\n\tverifyGCBits(t, TypeOf(Xptrscalar{}), lit(1))\n\tverifyGCBits(t, Tptrscalar, lit(1))\n\n\tverifyGCBits(t, TypeOf([0]Xptr{}), empty)\n\tverifyGCBits(t, ArrayOf(0, Tptr), empty)\n\tverifyGCBits(t, TypeOf([1]Xptrscalar{}), lit(1))\n\tverifyGCBits(t, ArrayOf(1, Tptrscalar), lit(1))\n\tverifyGCBits(t, TypeOf([2]Xscalar{}), empty)\n\tverifyGCBits(t, ArrayOf(2, Tscalar), empty)\n\tverifyGCBits(t, TypeOf([10000]Xscalar{}), empty)\n\tverifyGCBits(t, ArrayOf(10000, Tscalar), empty)\n\tverifyGCBits(t, TypeOf([2]Xptr{}), lit(1, 1))\n\tverifyGCBits(t, ArrayOf(2, Tptr), lit(1, 1))\n\tverifyGCBits(t, TypeOf([10000]Xptr{}), rep(10000, lit(1)))\n\tverifyGCBits(t, ArrayOf(10000, Tptr), rep(10000, lit(1)))\n\tverifyGCBits(t, TypeOf([2]Xscalarptr{}), lit(0, 1, 0, 1))\n\tverifyGCBits(t, ArrayOf(2, Tscalarptr), lit(0, 1, 0, 1))\n\tverifyGCBits(t, TypeOf([10000]Xscalarptr{}), rep(10000, lit(0, 1)))\n\tverifyGCBits(t, ArrayOf(10000, Tscalarptr), rep(10000, lit(0, 1)))\n\tverifyGCBits(t, TypeOf([2]Xptrscalar{}), lit(1, 0, 1))\n\tverifyGCBits(t, ArrayOf(2, Tptrscalar), lit(1, 0, 1))\n\tverifyGCBits(t, TypeOf([10000]Xptrscalar{}), rep(10000, lit(1, 0)))\n\tverifyGCBits(t, ArrayOf(10000, Tptrscalar), rep(10000, lit(1, 0)))\n\tverifyGCBits(t, TypeOf([1][10000]Xptrscalar{}), rep(10000, lit(1, 0)))\n\tverifyGCBits(t, ArrayOf(1, ArrayOf(10000, Tptrscalar)), rep(10000, lit(1, 0)))\n\tverifyGCBits(t, TypeOf([2][10000]Xptrscalar{}), rep(2*10000, lit(1, 0)))\n\tverifyGCBits(t, ArrayOf(2, ArrayOf(10000, Tptrscalar)), rep(2*10000, lit(1, 0)))\n\tverifyGCBits(t, TypeOf([4]Xbigptrscalar{}), join(rep(3, join(rep(100, lit(1)), rep(100, lit(0)))), rep(100, lit(1))))\n\tverifyGCBits(t, ArrayOf(4, Tbigptrscalar), join(rep(3, join(rep(100, lit(1)), rep(100, lit(0)))), rep(100, lit(1))))\n\n\tverifyGCBitsSlice(t, TypeOf([]Xptr{}), 0, empty)\n\tverifyGCBitsSlice(t, SliceOf(Tptr), 0, empty)\n\tverifyGCBitsSlice(t, TypeOf([]Xptrscalar{}), 1, lit(1))\n\tverifyGCBitsSlice(t, SliceOf(Tptrscalar), 1, lit(1))\n\tverifyGCBitsSlice(t, TypeOf([]Xscalar{}), 2, lit(0))\n\tverifyGCBitsSlice(t, SliceOf(Tscalar), 2, lit(0))\n\tverifyGCBitsSlice(t, TypeOf([]Xscalar{}), 10000, lit(0))\n\tverifyGCBitsSlice(t, SliceOf(Tscalar), 10000, lit(0))\n\tverifyGCBitsSlice(t, TypeOf([]Xptr{}), 2, lit(1))\n\tverifyGCBitsSlice(t, SliceOf(Tptr), 2, lit(1))\n\tverifyGCBitsSlice(t, TypeOf([]Xptr{}), 10000, lit(1))\n\tverifyGCBitsSlice(t, SliceOf(Tptr), 10000, lit(1))\n\tverifyGCBitsSlice(t, TypeOf([]Xscalarptr{}), 2, lit(0, 1))\n\tverifyGCBitsSlice(t, SliceOf(Tscalarptr), 2, lit(0, 1))\n\tverifyGCBitsSlice(t, TypeOf([]Xscalarptr{}), 10000, lit(0, 1))\n\tverifyGCBitsSlice(t, SliceOf(Tscalarptr), 10000, lit(0, 1))\n\tverifyGCBitsSlice(t, TypeOf([]Xptrscalar{}), 2, lit(1, 0))\n\tverifyGCBitsSlice(t, SliceOf(Tptrscalar), 2, lit(1, 0))\n\tverifyGCBitsSlice(t, TypeOf([]Xptrscalar{}), 10000, lit(1, 0))\n\tverifyGCBitsSlice(t, SliceOf(Tptrscalar), 10000, lit(1, 0))\n\tverifyGCBitsSlice(t, TypeOf([][10000]Xptrscalar{}), 1, rep(10000, lit(1, 0)))\n\tverifyGCBitsSlice(t, SliceOf(ArrayOf(10000, Tptrscalar)), 1, rep(10000, lit(1, 0)))\n\tverifyGCBitsSlice(t, TypeOf([][10000]Xptrscalar{}), 2, rep(10000, lit(1, 0)))\n\tverifyGCBitsSlice(t, SliceOf(ArrayOf(10000, Tptrscalar)), 2, rep(10000, lit(1, 0)))\n\tverifyGCBitsSlice(t, TypeOf([]Xbigptrscalar{}), 4, join(rep(100, lit(1)), rep(100, lit(0))))\n\tverifyGCBitsSlice(t, SliceOf(Tbigptrscalar), 4, join(rep(100, lit(1)), rep(100, lit(0))))\n\n\tverifyGCBits(t, TypeOf((chan [100]Xscalar)(nil)), lit(1))\n\tverifyGCBits(t, ChanOf(BothDir, ArrayOf(100, Tscalar)), lit(1))\n\n\tverifyGCBits(t, TypeOf((func([10000]Xscalarptr))(nil)), lit(1))\n\tverifyGCBits(t, FuncOf([]Type{ArrayOf(10000, Tscalarptr)}, nil, false), lit(1))\n\n\tverifyGCBits(t, TypeOf((map[[10000]Xscalarptr]Xscalar)(nil)), lit(1))\n\tverifyGCBits(t, MapOf(ArrayOf(10000, Tscalarptr), Tscalar), lit(1))\n\n\tverifyGCBits(t, TypeOf((*[10000]Xscalar)(nil)), lit(1))\n\tverifyGCBits(t, PointerTo(ArrayOf(10000, Tscalar)), lit(1))\n\n\tverifyGCBits(t, TypeOf(([][10000]Xscalar)(nil)), lit(1))\n\tverifyGCBits(t, SliceOf(ArrayOf(10000, Tscalar)), lit(1))\n\n\thdr := make([]byte, 8/goarch.PtrSize)\n\n\tverifyMapBucket := func(t *testing.T, k, e Type, m any, want []byte) {\n\t\tverifyGCBits(t, MapBucketOf(k, e), want)\n\t\tverifyGCBits(t, CachedBucketOf(TypeOf(m)), want)\n\t}\n\tverifyMapBucket(t,\n\t\tTscalar, Tptr,\n\t\tmap[Xscalar]Xptr(nil),\n\t\tjoin(hdr, rep(8, lit(0)), rep(8, lit(1)), lit(1)))\n\tverifyMapBucket(t,\n\t\tTscalarptr, Tptr,\n\t\tmap[Xscalarptr]Xptr(nil),\n\t\tjoin(hdr, rep(8, lit(0, 1)), rep(8, lit(1)), lit(1)))\n\tverifyMapBucket(t, Tint64, Tptr,\n\t\tmap[int64]Xptr(nil),\n\t\tjoin(hdr, rep(8, rep(8/goarch.PtrSize, lit(0))), rep(8, lit(1)), lit(1)))\n\tverifyMapBucket(t,\n\t\tTscalar, Tscalar,\n\t\tmap[Xscalar]Xscalar(nil),\n\t\tempty)\n\tverifyMapBucket(t,\n\t\tArrayOf(2, Tscalarptr), ArrayOf(3, Tptrscalar),\n\t\tmap[[2]Xscalarptr][3]Xptrscalar(nil),\n\t\tjoin(hdr, rep(8*2, lit(0, 1)), rep(8*3, lit(1, 0)), lit(1)))\n\tverifyMapBucket(t,\n\t\tArrayOf(64/goarch.PtrSize, Tscalarptr), ArrayOf(64/goarch.PtrSize, Tptrscalar),\n\t\tmap[[64 / goarch.PtrSize]Xscalarptr][64 / goarch.PtrSize]Xptrscalar(nil),\n\t\tjoin(hdr, rep(8*64/goarch.PtrSize, lit(0, 1)), rep(8*64/goarch.PtrSize, lit(1, 0)), lit(1)))\n\tverifyMapBucket(t,\n\t\tArrayOf(64/goarch.PtrSize+1, Tscalarptr), ArrayOf(64/goarch.PtrSize, Tptrscalar),\n\t\tmap[[64/goarch.PtrSize + 1]Xscalarptr][64 / goarch.PtrSize]Xptrscalar(nil),\n\t\tjoin(hdr, rep(8, lit(1)), rep(8*64/goarch.PtrSize, lit(1, 0)), lit(1)))\n\tverifyMapBucket(t,\n\t\tArrayOf(64/goarch.PtrSize, Tscalarptr), ArrayOf(64/goarch.PtrSize+1, Tptrscalar),\n\t\tmap[[64 / goarch.PtrSize]Xscalarptr][64/goarch.PtrSize + 1]Xptrscalar(nil),\n\t\tjoin(hdr, rep(8*64/goarch.PtrSize, lit(0, 1)), rep(8, lit(1)), lit(1)))\n\tverifyMapBucket(t,\n\t\tArrayOf(64/goarch.PtrSize+1, Tscalarptr), ArrayOf(64/goarch.PtrSize+1, Tptrscalar),\n\t\tmap[[64/goarch.PtrSize + 1]Xscalarptr][64/goarch.PtrSize + 1]Xptrscalar(nil),\n\t\tjoin(hdr, rep(8, lit(1)), rep(8, lit(1)), lit(1)))\n}\n\nfunc rep(n int, b []byte) []byte { return bytes.Repeat(b, n) }\nfunc join(b ...[]byte) []byte    { return bytes.Join(b, nil) }\nfunc lit(x ...byte) []byte       { return x }\n\nfunc TestTypeOfTypeOf(t *testing.T) {\n\t// Check that all the type constructors return concrete *rtype implementations.\n\t// It's difficult to test directly because the reflect package is only at arm's length.\n\t// The easiest thing to do is just call a function that crashes if it doesn't get an *rtype.\n\tcheck := func(name string, typ Type) {\n\t\tif underlying := TypeOf(typ).String(); underlying != \"*reflect.rtype\" {\n\t\t\tt.Errorf(\"%v returned %v, not *reflect.rtype\", name, underlying)\n\t\t}\n\t}\n\n\ttype T struct{ int }\n\tcheck(\"TypeOf\", TypeOf(T{}))\n\n\tcheck(\"ArrayOf\", ArrayOf(10, TypeOf(T{})))\n\tcheck(\"ChanOf\", ChanOf(BothDir, TypeOf(T{})))\n\tcheck(\"FuncOf\", FuncOf([]Type{TypeOf(T{})}, nil, false))\n\tcheck(\"MapOf\", MapOf(TypeOf(T{}), TypeOf(T{})))\n\tcheck(\"PtrTo\", PointerTo(TypeOf(T{})))\n\tcheck(\"SliceOf\", SliceOf(TypeOf(T{})))\n}\n\ntype XM struct{ _ bool }\n\nfunc (*XM) String() string { return \"\" }\n\nfunc TestPtrToMethods(t *testing.T) {\n\tvar y struct{ XM }\n\typ := New(TypeOf(y)).Interface()\n\t_, ok := yp.(fmt.Stringer)\n\tif !ok {\n\t\tt.Fatal(\"does not implement Stringer, but should\")\n\t}\n}\n\nfunc TestMapAlloc(t *testing.T) {\n\tm := ValueOf(make(map[int]int, 10))\n\tk := ValueOf(5)\n\tv := ValueOf(7)\n\tallocs := testing.AllocsPerRun(100, func() {\n\t\tm.SetMapIndex(k, v)\n\t})\n\tif allocs > 0.5 {\n\t\tt.Errorf(\"allocs per map assignment: want 0 got %f\", allocs)\n\t}\n\n\tconst size = 1000\n\ttmp := 0\n\tval := ValueOf(&tmp).Elem()\n\tallocs = testing.AllocsPerRun(100, func() {\n\t\tmv := MakeMapWithSize(TypeOf(map[int]int{}), size)\n\t\t// Only adding half of the capacity to not trigger re-allocations due too many overloaded buckets.\n\t\tfor i := 0; i < size/2; i++ {\n\t\t\tval.SetInt(int64(i))\n\t\t\tmv.SetMapIndex(val, val)\n\t\t}\n\t})\n\tif allocs > 10 {\n\t\tt.Errorf(\"allocs per map assignment: want at most 10 got %f\", allocs)\n\t}\n\t// Empirical testing shows that with capacity hint single run will trigger 3 allocations and without 91. I set\n\t// the threshold to 10, to not make it overly brittle if something changes in the initial allocation of the\n\t// map, but to still catch a regression where we keep re-allocating in the hashmap as new entries are added.\n}\n\nfunc TestChanAlloc(t *testing.T) {\n\t// Note: for a chan int, the return Value must be allocated, so we\n\t// use a chan *int instead.\n\tc := ValueOf(make(chan *int, 1))\n\tv := ValueOf(new(int))\n\tallocs := testing.AllocsPerRun(100, func() {\n\t\tc.Send(v)\n\t\t_, _ = c.Recv()\n\t})\n\tif allocs < 0.5 || allocs > 1.5 {\n\t\tt.Errorf(\"allocs per chan send/recv: want 1 got %f\", allocs)\n\t}\n\t// Note: there is one allocation in reflect.recv which seems to be\n\t// a limitation of escape analysis. If that is ever fixed the\n\t// allocs < 0.5 condition will trigger and this test should be fixed.\n}\n\n*/\n\ntype TheNameOfThisTypeIsExactly255BytesLongSoWhenTheCompilerPrependsTheReflectTestPackageNameAndExtraStarTheLinkerRuntimeAndReflectPackagesWillHaveToCorrectlyDecodeTheSecondLengthByte0123456789_0123456789_0123456789_0123456789_0123456789_012345678 int\n\ntype nameTest struct {\n\tv    any\n\twant string\n}\n\nvar nameTests = []nameTest{\n\t{(*int32)(nil), \"int32\"},\n\t{(*D1)(nil), \"D1\"},\n\t{(*[]D1)(nil), \"\"},\n\t{(*chan D1)(nil), \"\"},\n\t{(*func() D1)(nil), \"\"},\n\t{(*<-chan D1)(nil), \"\"},\n\t{(*chan<- D1)(nil), \"\"},\n\t{(*any)(nil), \"\"},\n\t{(*interface {\n\t\tF()\n\t})(nil), \"\"},\n\t{(*TheNameOfThisTypeIsExactly255BytesLongSoWhenTheCompilerPrependsTheReflectTestPackageNameAndExtraStarTheLinkerRuntimeAndReflectPackagesWillHaveToCorrectlyDecodeTheSecondLengthByte0123456789_0123456789_0123456789_0123456789_0123456789_012345678)(nil), \"TheNameOfThisTypeIsExactly255BytesLongSoWhenTheCompilerPrependsTheReflectTestPackageNameAndExtraStarTheLinkerRuntimeAndReflectPackagesWillHaveToCorrectlyDecodeTheSecondLengthByte0123456789_0123456789_0123456789_0123456789_0123456789_012345678\"},\n}\n\nfunc TestNames(t *testing.T) {\n\tfor _, test := range nameTests {\n\t\ttyp := TypeOf(test.v).Elem()\n\t\tif got := typ.Name(); got != test.want {\n\t\t\tt.Errorf(\"%v Name()=%q, want %q\", typ, got, test.want)\n\t\t}\n\t}\n}\n\n/*\n\nfunc TestExported(t *testing.T) {\n\ttype ΦExported struct{}\n\ttype φUnexported struct{}\n\ttype BigP *big\n\ttype P int\n\ttype p *P\n\ttype P2 p\n\ttype p3 p\n\n\ttype exportTest struct {\n\t\tv    any\n\t\twant bool\n\t}\n\texportTests := []exportTest{\n\t\t{D1{}, true},\n\t\t{(*D1)(nil), true},\n\t\t{big{}, false},\n\t\t{(*big)(nil), false},\n\t\t{(BigP)(nil), true},\n\t\t{(*BigP)(nil), true},\n\t\t{ΦExported{}, true},\n\t\t{φUnexported{}, false},\n\t\t{P(0), true},\n\t\t{(p)(nil), false},\n\t\t{(P2)(nil), true},\n\t\t{(p3)(nil), false},\n\t}\n\n\tfor i, test := range exportTests {\n\t\ttyp := TypeOf(test.v)\n\t\tif got := IsExported(typ); got != test.want {\n\t\t\tt.Errorf(\"%d: %s exported=%v, want %v\", i, typ.Name(), got, test.want)\n\t\t}\n\t}\n}\n\nfunc TestTypeStrings(t *testing.T) {\n\ttype stringTest struct {\n\t\ttyp  Type\n\t\twant string\n\t}\n\tstringTests := []stringTest{\n\t\t{TypeOf(func(int) {}), \"func(int)\"},\n\t\t{FuncOf([]Type{TypeOf(int(0))}, nil, false), \"func(int)\"},\n\t\t{TypeOf(XM{}), \"reflect_test.XM\"},\n\t\t{TypeOf(new(XM)), \"*reflect_test.XM\"},\n\t\t{TypeOf(new(XM).String), \"func() string\"},\n\t\t{TypeOf(new(XM)).Method(0).Type, \"func(*reflect_test.XM) string\"},\n\t\t{ChanOf(3, TypeOf(XM{})), \"chan reflect_test.XM\"},\n\t\t{MapOf(TypeOf(int(0)), TypeOf(XM{})), \"map[int]reflect_test.XM\"},\n\t\t{ArrayOf(3, TypeOf(XM{})), \"[3]reflect_test.XM\"},\n\t\t{ArrayOf(3, TypeOf(struct{}{})), \"[3]struct {}\"},\n\t}\n\n\tfor i, test := range stringTests {\n\t\tif got, want := test.typ.String(), test.want; got != want {\n\t\t\tt.Errorf(\"type %d String()=%q, want %q\", i, got, want)\n\t\t}\n\t}\n}\n\nfunc TestOffsetLock(t *testing.T) {\n\tvar wg sync.WaitGroup\n\tfor i := 0; i < 4; i++ {\n\t\ti := i\n\t\twg.Add(1)\n\t\tgo func() {\n\t\t\tfor j := 0; j < 50; j++ {\n\t\t\t\tResolveReflectName(fmt.Sprintf(\"OffsetLockName:%d:%d\", i, j))\n\t\t\t}\n\t\t\twg.Done()\n\t\t}()\n\t}\n\twg.Wait()\n}\n\n*/\n\nfunc TestSwapper(t *testing.T) {\n\ttype I int\n\tvar a, b, c I\n\ttype pair struct {\n\t\tx, y int\n\t}\n\ttype pairPtr struct {\n\t\tx, y int\n\t\tp    *I\n\t}\n\ttype S string\n\n\ttests := []struct {\n\t\tin   any\n\t\ti, j int\n\t\twant any\n\t}{\n\t\t{\n\t\t\tin:   []int{1, 20, 300},\n\t\t\ti:    0,\n\t\t\tj:    2,\n\t\t\twant: []int{300, 20, 1},\n\t\t},\n\t\t{\n\t\t\tin:   []uintptr{1, 20, 300},\n\t\t\ti:    0,\n\t\t\tj:    2,\n\t\t\twant: []uintptr{300, 20, 1},\n\t\t},\n\t\t{\n\t\t\tin:   []int16{1, 20, 300},\n\t\t\ti:    0,\n\t\t\tj:    2,\n\t\t\twant: []int16{300, 20, 1},\n\t\t},\n\t\t{\n\t\t\tin:   []int8{1, 20, 100},\n\t\t\ti:    0,\n\t\t\tj:    2,\n\t\t\twant: []int8{100, 20, 1},\n\t\t},\n\t\t{\n\t\t\tin:   []*I{&a, &b, &c},\n\t\t\ti:    0,\n\t\t\tj:    2,\n\t\t\twant: []*I{&c, &b, &a},\n\t\t},\n\t\t{\n\t\t\tin:   []string{\"eric\", \"sergey\", \"larry\"},\n\t\t\ti:    0,\n\t\t\tj:    2,\n\t\t\twant: []string{\"larry\", \"sergey\", \"eric\"},\n\t\t},\n\t\t{\n\t\t\tin:   []S{\"eric\", \"sergey\", \"larry\"},\n\t\t\ti:    0,\n\t\t\tj:    2,\n\t\t\twant: []S{\"larry\", \"sergey\", \"eric\"},\n\t\t},\n\t\t{\n\t\t\tin:   []pair{{1, 2}, {3, 4}, {5, 6}},\n\t\t\ti:    0,\n\t\t\tj:    2,\n\t\t\twant: []pair{{5, 6}, {3, 4}, {1, 2}},\n\t\t},\n\t\t{\n\t\t\tin:   []pairPtr{{1, 2, &a}, {3, 4, &b}, {5, 6, &c}},\n\t\t\ti:    0,\n\t\t\tj:    2,\n\t\t\twant: []pairPtr{{5, 6, &c}, {3, 4, &b}, {1, 2, &a}},\n\t\t},\n\t}\n\n\tfor i, tt := range tests {\n\t\tinStr := fmt.Sprint(tt.in)\n\t\tSwapper(tt.in)(tt.i, tt.j)\n\t\tif !DeepEqual(tt.in, tt.want) {\n\t\t\tt.Errorf(\"%d. swapping %v and %v of %v = %v; want %v\", i, tt.i, tt.j, inStr, tt.in, tt.want)\n\t\t}\n\t}\n}\n\n/*\n\n// TestUnaddressableField tests that the reflect package will not allow\n// a type from another package to be used as a named type with an\n// unexported field.\n//\n// This ensures that unexported fields cannot be modified by other packages.\nfunc TestUnaddressableField(t *testing.T) {\n\tvar b Buffer // type defined in reflect, a different package\n\tvar localBuffer struct {\n\t\tbuf []byte\n\t}\n\tlv := ValueOf(&localBuffer).Elem()\n\trv := ValueOf(b)\n\tshouldPanic(\"Set\", func() {\n\t\tlv.Set(rv)\n\t})\n}\n\n*/\n\ntype Tint int\n\ntype Tint2 = Tint\n\ntype Talias1 struct {\n\tbyte\n\tuint8\n\tint\n\tint32\n\trune\n}\n\ntype Talias2 struct {\n\tTint\n\tTint2\n}\n\nfunc TestAliasNames(t *testing.T) {\n\tt1 := Talias1{byte: 1, uint8: 2, int: 3, int32: 4, rune: 5}\n\tout := fmt.Sprintf(\"%#v\", t1)\n\twant := \"reflect_test.Talias1{byte:0x1, uint8:0x2, int:3, int32:4, rune:5}\"\n\tif out != want {\n\t\tt.Errorf(\"Talias1 print:\\nhave: %s\\nwant: %s\", out, want)\n\t}\n\n\tt2 := Talias2{Tint: 1, Tint2: 2}\n\tout = fmt.Sprintf(\"%#v\", t2)\n\twant = \"reflect_test.Talias2{Tint:1, Tint2:2}\"\n\tif out != want {\n\t\tt.Errorf(\"Talias2 print:\\nhave: %s\\nwant: %s\", out, want)\n\t}\n}\n\nfunc TestIssue22031(t *testing.T) {\n\ttype s []struct{ C int }\n\n\ttype t1 struct{ s }\n\ttype t2 struct{ f s }\n\n\ttests := []Value{\n\t\tValueOf(t1{s{{}}}).Field(0).Index(0).Field(0),\n\t\tValueOf(t2{s{{}}}).Field(0).Index(0).Field(0),\n\t}\n\n\tfor i, test := range tests {\n\t\tif test.CanSet() {\n\t\t\tt.Errorf(\"%d: CanSet: got true, want false\", i)\n\t\t}\n\t}\n}\n\n/*\n\ntype NonExportedFirst int\n\nfunc (i NonExportedFirst) ΦExported()       {}\nfunc (i NonExportedFirst) nonexported() int { panic(\"wrong\") }\n\nfunc TestIssue22073(t *testing.T) {\n\tm := ValueOf(NonExportedFirst(0)).Method(0)\n\n\tif got := m.Type().NumOut(); got != 0 {\n\t\tt.Errorf(\"NumOut: got %v, want 0\", got)\n\t}\n\n\t// Shouldn't panic.\n\tm.Call(nil)\n}\n\n*/\n\nfunc TestMapIterNonEmptyMap(t *testing.T) {\n\tm := map[string]int{\"one\": 1, \"two\": 2, \"three\": 3}\n\titer := ValueOf(m).MapRange()\n\tif got, want := iterateToString(iter), `[one: 1, three: 3, two: 2]`; got != want {\n\t\tt.Errorf(\"iterator returned %s (after sorting), want %s\", got, want)\n\t}\n}\n\nfunc TestMapIterNilMap(t *testing.T) {\n\tvar m map[string]int\n\titer := ValueOf(m).MapRange()\n\tif got, want := iterateToString(iter), `[]`; got != want {\n\t\tt.Errorf(\"non-empty result iteratoring nil map: %s\", got)\n\t}\n}\n\n/*\n\nfunc TestMapIterReset(t *testing.T) {\n\titer := new(MapIter)\n\n\t// Use of zero iterator should panic.\n\tfunc() {\n\t\tdefer func() { recover() }()\n\t\titer.Next()\n\t\tt.Error(\"Next did not panic\")\n\t}()\n\n\t// Reset to new Map should work.\n\tm := map[string]int{\"one\": 1, \"two\": 2, \"three\": 3}\n\titer.Reset(ValueOf(m))\n\tif got, want := iterateToString(iter), `[one: 1, three: 3, two: 2]`; got != want {\n\t\tt.Errorf(\"iterator returned %s (after sorting), want %s\", got, want)\n\t}\n\n\t// Reset to Zero value should work, but iterating over it should panic.\n\titer.Reset(Value{})\n\tfunc() {\n\t\tdefer func() { recover() }()\n\t\titer.Next()\n\t\tt.Error(\"Next did not panic\")\n\t}()\n\n\t// Reset to a different Map with different types should work.\n\tm2 := map[int]string{1: \"one\", 2: \"two\", 3: \"three\"}\n\titer.Reset(ValueOf(m2))\n\tif got, want := iterateToString(iter), `[1: one, 2: two, 3: three]`; got != want {\n\t\tt.Errorf(\"iterator returned %s (after sorting), want %s\", got, want)\n\t}\n\n\t// Check that Reset, Next, and SetKey/SetValue play nicely together.\n\tm3 := map[uint64]uint64{\n\t\t1 << 0: 1 << 1,\n\t\t1 << 1: 1 << 2,\n\t\t1 << 2: 1 << 3,\n\t}\n\tkv := New(TypeOf(uint64(0))).Elem()\n\tfor i := 0; i < 5; i++ {\n\t\tvar seenk, seenv uint64\n\t\titer.Reset(ValueOf(m3))\n\t\tfor iter.Next() {\n\t\t\tkv.SetIterKey(iter)\n\t\t\tseenk ^= kv.Uint()\n\t\t\tkv.SetIterValue(iter)\n\t\t\tseenv ^= kv.Uint()\n\t\t}\n\t\tif seenk != 0b111 {\n\t\t\tt.Errorf(\"iteration yielded keys %b, want %b\", seenk, 0b111)\n\t\t}\n\t\tif seenv != 0b1110 {\n\t\t\tt.Errorf(\"iteration yielded values %b, want %b\", seenv, 0b1110)\n\t\t}\n\t}\n\n\t// Reset should not allocate.\n\tn := int(testing.AllocsPerRun(10, func() {\n\t\titer.Reset(ValueOf(m2))\n\t\titer.Reset(Value{})\n\t}))\n\tif n > 0 {\n\t\tt.Errorf(\"MapIter.Reset allocated %d times\", n)\n\t}\n}\n\nfunc TestMapIterSafety(t *testing.T) {\n\t// Using a zero MapIter causes a panic, but not a crash.\n\tfunc() {\n\t\tdefer func() { recover() }()\n\t\tnew(MapIter).Key()\n\t\tt.Fatal(\"Key did not panic\")\n\t}()\n\tfunc() {\n\t\tdefer func() { recover() }()\n\t\tnew(MapIter).Value()\n\t\tt.Fatal(\"Value did not panic\")\n\t}()\n\tfunc() {\n\t\tdefer func() { recover() }()\n\t\tnew(MapIter).Next()\n\t\tt.Fatal(\"Next did not panic\")\n\t}()\n\n\t// Calling Key/Value on a MapIter before Next\n\t// causes a panic, but not a crash.\n\tvar m map[string]int\n\titer := ValueOf(m).MapRange()\n\n\tfunc() {\n\t\tdefer func() { recover() }()\n\t\titer.Key()\n\t\tt.Fatal(\"Key did not panic\")\n\t}()\n\tfunc() {\n\t\tdefer func() { recover() }()\n\t\titer.Value()\n\t\tt.Fatal(\"Value did not panic\")\n\t}()\n\n\t// Calling Next, Key, or Value on an exhausted iterator\n\t// causes a panic, but not a crash.\n\titer.Next() // -> false\n\tfunc() {\n\t\tdefer func() { recover() }()\n\t\titer.Key()\n\t\tt.Fatal(\"Key did not panic\")\n\t}()\n\tfunc() {\n\t\tdefer func() { recover() }()\n\t\titer.Value()\n\t\tt.Fatal(\"Value did not panic\")\n\t}()\n\tfunc() {\n\t\tdefer func() { recover() }()\n\t\titer.Next()\n\t\tt.Fatal(\"Next did not panic\")\n\t}()\n}\n\n*/\n\nfunc TestMapIterNext(t *testing.T) {\n\t// The first call to Next should reflect any\n\t// insertions to the map since the iterator was created.\n\tm := map[string]int{}\n\titer := ValueOf(m).MapRange()\n\tm[\"one\"] = 1\n\tif got, want := iterateToString(iter), `[one: 1]`; got != want {\n\t\tt.Errorf(\"iterator returned deleted elements: got %s, want %s\", got, want)\n\t}\n}\n\nfunc TestMapIterDelete0(t *testing.T) {\n\t// Delete all elements before first iteration.\n\tm := map[string]int{\"one\": 1, \"two\": 2, \"three\": 3}\n\titer := ValueOf(m).MapRange()\n\tdelete(m, \"one\")\n\tdelete(m, \"two\")\n\tdelete(m, \"three\")\n\tif got, want := iterateToString(iter), `[]`; got != want {\n\t\tt.Errorf(\"iterator returned deleted elements: got %s, want %s\", got, want)\n\t}\n}\n\nfunc TestMapIterDelete1(t *testing.T) {\n\t// Delete all elements after first iteration.\n\tm := map[string]int{\"one\": 1, \"two\": 2, \"three\": 3}\n\titer := ValueOf(m).MapRange()\n\tvar got []string\n\tfor iter.Next() {\n\t\tgot = append(got, fmt.Sprint(iter.Key(), iter.Value()))\n\t\tdelete(m, \"one\")\n\t\tdelete(m, \"two\")\n\t\tdelete(m, \"three\")\n\t}\n\tif len(got) != 1 {\n\t\tt.Errorf(\"iterator returned wrong number of elements: got %d, want 1\", len(got))\n\t}\n}\n\n// iterateToString returns the set of elements\n// returned by an iterator in readable form.\nfunc iterateToString(it *MapIter) string {\n\tvar got []string\n\tfor it.Next() {\n\t\tline := fmt.Sprintf(\"%v: %v\", it.Key(), it.Value())\n\t\tgot = append(got, line)\n\t}\n\tsort.Strings(got)\n\treturn \"[\" + strings.Join(got, \", \") + \"]\"\n}\n\n/*\n\nfunc TestConvertibleTo(t *testing.T) {\n\tt1 := ValueOf(example1.MyStruct{}).Type()\n\tt2 := ValueOf(example2.MyStruct{}).Type()\n\n\t// Shouldn't raise stack overflow\n\tif t1.ConvertibleTo(t2) {\n\t\tt.Fatalf(\"(%s).ConvertibleTo(%s) = true, want false\", t1, t2)\n\t}\n\n\tt3 := ValueOf([]example1.MyStruct{}).Type()\n\tt4 := ValueOf([]example2.MyStruct{}).Type()\n\n\tif t3.ConvertibleTo(t4) {\n\t\tt.Fatalf(\"(%s).ConvertibleTo(%s) = true, want false\", t3, t4)\n\t}\n}\n\n*/\n\nfunc TestSetIter(t *testing.T) {\n\tdata := map[string]int{\n\t\t\"foo\": 1,\n\t\t\"bar\": 2,\n\t\t\"baz\": 3,\n\t}\n\n\tm := ValueOf(data)\n\ti := m.MapRange()\n\tk := New(TypeOf(\"\")).Elem()\n\tv := New(TypeOf(0)).Elem()\n\tshouldPanic(\"Value.SetIterKey called before Next\", func() {\n\t\tk.SetIterKey(i)\n\t})\n\tshouldPanic(\"Value.SetIterValue called before Next\", func() {\n\t\tv.SetIterValue(i)\n\t})\n\tdata2 := map[string]int{}\n\tfor i.Next() {\n\t\tk.SetIterKey(i)\n\t\tv.SetIterValue(i)\n\t\tdata2[k.Interface().(string)] = v.Interface().(int)\n\t}\n\tif !DeepEqual(data, data2) {\n\t\tt.Errorf(\"maps not equal, got %v want %v\", data2, data)\n\t}\n\tshouldPanic(\"Value.SetIterKey called on exhausted iterator\", func() {\n\t\tk.SetIterKey(i)\n\t})\n\tshouldPanic(\"Value.SetIterValue called on exhausted iterator\", func() {\n\t\tv.SetIterValue(i)\n\t})\n\n\ti.Reset(m)\n\ti.Next()\n\tshouldPanic(\"Value.SetIterKey using unaddressable value\", func() {\n\t\tValueOf(\"\").SetIterKey(i)\n\t})\n\tshouldPanic(\"Value.SetIterValue using unaddressable value\", func() {\n\t\tValueOf(0).SetIterValue(i)\n\t})\n\tshouldPanic(\"value of type string is not assignable to type int\", func() {\n\t\tNew(TypeOf(0)).Elem().SetIterKey(i)\n\t})\n\tshouldPanic(\"value of type int is not assignable to type string\", func() {\n\t\tNew(TypeOf(\"\")).Elem().SetIterValue(i)\n\t})\n\n\t// Make sure assignment conversion works.\n\tvar x any\n\ty := ValueOf(&x).Elem()\n\ty.SetIterKey(i)\n\tif _, ok := data[x.(string)]; !ok {\n\t\tt.Errorf(\"got key %s which is not in map\", x)\n\t}\n\ty.SetIterValue(i)\n\tif x.(int) < 1 || x.(int) > 3 {\n\t\tt.Errorf(\"got value %d which is not in map\", x)\n\t}\n\n\t// Try some key/value types which are direct interfaces.\n\ta := 88\n\tb := 99\n\tpp := map[*int]*int{\n\t\t&a: &b,\n\t}\n\ti = ValueOf(pp).MapRange()\n\ti.Next()\n\ty.SetIterKey(i)\n\tif got := *y.Interface().(*int); got != a {\n\t\tt.Errorf(\"pointer incorrect: got %d want %d\", got, a)\n\t}\n\ty.SetIterValue(i)\n\tif got := *y.Interface().(*int); got != b {\n\t\tt.Errorf(\"pointer incorrect: got %d want %d\", got, b)\n\t}\n\n\t// Make sure we panic assigning from an unexported field.\n\tm = ValueOf(struct{ m map[string]int }{data}).Field(0)\n\tfor iter := m.MapRange(); iter.Next(); {\n\t\tshouldPanic(\"using value obtained using unexported field\", func() {\n\t\t\tk.SetIterKey(iter)\n\t\t})\n\t\tshouldPanic(\"using value obtained using unexported field\", func() {\n\t\t\tv.SetIterValue(iter)\n\t\t})\n\t}\n}\n\n/*\n\nfunc TestMethodCallValueCodePtr(t *testing.T) {\n\tm := ValueOf(Point{}).Method(1)\n\twant := MethodValueCallCodePtr()\n\tif got := uintptr(m.UnsafePointer()); got != want {\n\t\tt.Errorf(\"methodValueCall code pointer mismatched, want: %v, got: %v\", want, got)\n\t}\n\tif got := m.Pointer(); got != want {\n\t\tt.Errorf(\"methodValueCall code pointer mismatched, want: %v, got: %v\", want, got)\n\t}\n}\n\ntype A struct{}\ntype B[T any] struct{}\n\nfunc TestIssue50208(t *testing.T) {\n\twant1 := \"B[reflect_test.A]\"\n\tif got := TypeOf(new(B[A])).Elem().Name(); got != want1 {\n\t\tt.Errorf(\"name of type parameter mismatched, want:%s, got:%s\", want1, got)\n\t}\n\twant2 := \"B[reflect_test.B[reflect_test.A]]\"\n\tif got := TypeOf(new(B[B[A]])).Elem().Name(); got != want2 {\n\t\tt.Errorf(\"name of type parameter mismatched, want:%s, got:%s\", want2, got)\n\t}\n}\n\n*/\n\nfunc TestNegativeKindString(t *testing.T) {\n\tx := -1\n\ts := Kind(x).String()\n\twant := \"kind-1\"\n\tif s != want {\n\t\tt.Fatalf(\"Kind(-1).String() = %q, want %q\", s, want)\n\t}\n}\n\ntype (\n\tnamedBool  bool\n\tnamedBytes []byte\n)\n\n/*\n\nfunc TestValue_Cap(t *testing.T) {\n\ta := &[3]int{1, 2, 3}\n\tv := ValueOf(a)\n\tif v.Cap() != cap(a) {\n\t\tt.Errorf(\"Cap = %d want %d\", v.Cap(), cap(a))\n\t}\n\n\ta = nil\n\tv = ValueOf(a)\n\tif v.Cap() != cap(a) {\n\t\tt.Errorf(\"Cap = %d want %d\", v.Cap(), cap(a))\n\t}\n\n\tgetError := func(f func()) (errorStr string) {\n\t\tdefer func() {\n\t\t\te := recover()\n\t\t\tif str, ok := e.(string); ok {\n\t\t\t\terrorStr = str\n\t\t\t}\n\t\t}()\n\t\tf()\n\t\treturn\n\t}\n\te := getError(func() {\n\t\tvar ptr *int\n\t\tValueOf(ptr).Cap()\n\t})\n\twantStr := \"reflect: call of reflect.Value.Cap on ptr to non-array Value\"\n\tif e != wantStr {\n\t\tt.Errorf(\"error is %q, want %q\", e, wantStr)\n\t}\n}\n\nfunc TestValue_Len(t *testing.T) {\n\ta := &[3]int{1, 2, 3}\n\tv := ValueOf(a)\n\tif v.Len() != len(a) {\n\t\tt.Errorf(\"Len = %d want %d\", v.Len(), len(a))\n\t}\n\n\ta = nil\n\tv = ValueOf(a)\n\tif v.Len() != len(a) {\n\t\tt.Errorf(\"Len = %d want %d\", v.Len(), len(a))\n\t}\n\n\tgetError := func(f func()) (errorStr string) {\n\t\tdefer func() {\n\t\t\te := recover()\n\t\t\tif str, ok := e.(string); ok {\n\t\t\t\terrorStr = str\n\t\t\t}\n\t\t}()\n\t\tf()\n\t\treturn\n\t}\n\te := getError(func() {\n\t\tvar ptr *int\n\t\tValueOf(ptr).Len()\n\t})\n\twantStr := \"reflect: call of reflect.Value.Len on ptr to non-array Value\"\n\tif e != wantStr {\n\t\tt.Errorf(\"error is %q, want %q\", e, wantStr)\n\t}\n}\n\n*/\n\nfunc TestValue_Comparable(t *testing.T) {\n\tvar a int\n\tvar s []int\n\tvar i interface{} = a\n\tvar iSlice interface{} = s\n\tvar iArrayFalse interface{} = [2]interface{}{1, map[int]int{}}\n\tvar iArrayTrue interface{} = [2]interface{}{1, struct{ I interface{} }{1}}\n\tvar testcases = []struct {\n\t\tvalue      Value\n\t\tcomparable bool\n\t\tderef      bool\n\t}{\n\t\t{\n\t\t\tValueOf(32),\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValueOf(int8(1)),\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValueOf(int16(1)),\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValueOf(int32(1)),\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValueOf(int64(1)),\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValueOf(uint8(1)),\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValueOf(uint16(1)),\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValueOf(uint32(1)),\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValueOf(uint64(1)),\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValueOf(float32(1)),\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValueOf(float64(1)),\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValueOf(complex(float32(1), float32(1))),\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValueOf(complex(float64(1), float64(1))),\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValueOf(\"abc\"),\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValueOf(true),\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValueOf(map[int]int{}),\n\t\t\tfalse,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValueOf([]int{}),\n\t\t\tfalse,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValue{},\n\t\t\tfalse,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValueOf(&a),\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValueOf(&s),\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValueOf(&i),\n\t\t\ttrue,\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\tValueOf(&iSlice),\n\t\t\tfalse,\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\tValueOf([2]int{}),\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValueOf([2]map[int]int{}),\n\t\t\tfalse,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValueOf([0]func(){}),\n\t\t\tfalse,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValueOf([2]struct{ I interface{} }{{1}, {1}}),\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValueOf([2]struct{ I interface{} }{{[]int{}}, {1}}),\n\t\t\tfalse,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValueOf([2]interface{}{1, struct{ I int }{1}}),\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValueOf([2]interface{}{[1]interface{}{map[int]int{}}, struct{ I int }{1}}),\n\t\t\tfalse,\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\tValueOf(&iArrayFalse),\n\t\t\tfalse,\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\tValueOf(&iArrayTrue),\n\t\t\ttrue,\n\t\t\ttrue,\n\t\t},\n\t}\n\n\tfor _, cas := range testcases {\n\t\tv := cas.value\n\t\tif cas.deref {\n\t\t\tv = v.Elem()\n\t\t}\n\t\tgot := v.Comparable()\n\t\tif got != cas.comparable {\n\t\t\tt.Errorf(\"%T.Comparable = %t, want %t\", v, got, cas.comparable)\n\t\t}\n\t}\n}\n\n/*\n\ntype ValueEqualTest struct {\n\tv, u           any\n\teq             bool\n\tvDeref, uDeref bool\n}\n\nvar equalI interface{} = 1\nvar equalSlice interface{} = []int{1}\nvar nilInterface interface{}\nvar mapInterface interface{} = map[int]int{}\n\nvar valueEqualTests = []ValueEqualTest{\n\t{\n\t\tValue{}, Value{},\n\t\ttrue,\n\t\tfalse, false,\n\t},\n\t{\n\t\ttrue, true,\n\t\ttrue,\n\t\tfalse, false,\n\t},\n\t{\n\t\t1, 1,\n\t\ttrue,\n\t\tfalse, false,\n\t},\n\t{\n\t\tint8(1), int8(1),\n\t\ttrue,\n\t\tfalse, false,\n\t},\n\t{\n\t\tint16(1), int16(1),\n\t\ttrue,\n\t\tfalse, false,\n\t},\n\t{\n\t\tint32(1), int32(1),\n\t\ttrue,\n\t\tfalse, false,\n\t},\n\t{\n\t\tint64(1), int64(1),\n\t\ttrue,\n\t\tfalse, false,\n\t},\n\t{\n\t\tuint(1), uint(1),\n\t\ttrue,\n\t\tfalse, false,\n\t},\n\t{\n\t\tuint8(1), uint8(1),\n\t\ttrue,\n\t\tfalse, false,\n\t},\n\t{\n\t\tuint16(1), uint16(1),\n\t\ttrue,\n\t\tfalse, false,\n\t},\n\t{\n\t\tuint32(1), uint32(1),\n\t\ttrue,\n\t\tfalse, false,\n\t},\n\t{\n\t\tuint64(1), uint64(1),\n\t\ttrue,\n\t\tfalse, false,\n\t},\n\t{\n\t\tfloat32(1), float32(1),\n\t\ttrue,\n\t\tfalse, false,\n\t},\n\t{\n\t\tfloat64(1), float64(1),\n\t\ttrue,\n\t\tfalse, false,\n\t},\n\t{\n\t\tcomplex(1, 1), complex(1, 1),\n\t\ttrue,\n\t\tfalse, false,\n\t},\n\t{\n\t\tcomplex128(1 + 1i), complex128(1 + 1i),\n\t\ttrue,\n\t\tfalse, false,\n\t},\n\t{\n\t\tfunc() {}, nil,\n\t\tfalse,\n\t\tfalse, false,\n\t},\n\t{\n\t\t&equalI, 1,\n\t\ttrue,\n\t\ttrue, false,\n\t},\n\t{\n\t\t(chan int)(nil), nil,\n\t\tfalse,\n\t\tfalse, false,\n\t},\n\t{\n\t\t(chan int)(nil), (chan int)(nil),\n\t\ttrue,\n\t\tfalse, false,\n\t},\n\t{\n\t\t&equalI, &equalI,\n\t\ttrue,\n\t\tfalse, false,\n\t},\n\t{\n\t\tstruct{ i int }{1}, struct{ i int }{1},\n\t\ttrue,\n\t\tfalse, false,\n\t},\n\t{\n\t\tstruct{ i int }{1}, struct{ i int }{2},\n\t\tfalse,\n\t\tfalse, false,\n\t},\n\t{\n\t\t&nilInterface, &nilInterface,\n\t\ttrue,\n\t\ttrue, true,\n\t},\n\t{\n\t\t1, ValueOf(struct{ i int }{1}).Field(0),\n\t\ttrue,\n\t\tfalse, false,\n\t},\n}\n\nfunc TestValue_Equal(t *testing.T) {\n\tfor _, test := range valueEqualTests {\n\t\tvar v, u Value\n\t\tif vv, ok := test.v.(Value); ok {\n\t\t\tv = vv\n\t\t} else {\n\t\t\tv = ValueOf(test.v)\n\t\t}\n\n\t\tif uu, ok := test.u.(Value); ok {\n\t\t\tu = uu\n\t\t} else {\n\t\t\tu = ValueOf(test.u)\n\t\t}\n\t\tif test.vDeref {\n\t\t\tv = v.Elem()\n\t\t}\n\n\t\tif test.uDeref {\n\t\t\tu = u.Elem()\n\t\t}\n\n\t\tif r := v.Equal(u); r != test.eq {\n\t\t\tt.Errorf(\"%s == %s got %t, want %t\", v.Type(), u.Type(), r, test.eq)\n\t\t}\n\t}\n}\n\nfunc TestValue_EqualNonComparable(t *testing.T) {\n\tvar invalid = Value{} // ValueOf(nil)\n\tvar values = []Value{\n\t\t// Value of slice is non-comparable.\n\t\tValueOf([]int(nil)),\n\t\tValueOf(([]int{})),\n\n\t\t// Value of map is non-comparable.\n\t\tValueOf(map[int]int(nil)),\n\t\tValueOf((map[int]int{})),\n\n\t\t// Value of func is non-comparable.\n\t\tValueOf(((func())(nil))),\n\t\tValueOf(func() {}),\n\n\t\t// Value of struct is non-comparable because of non-comparable elements.\n\t\tValueOf((NonComparableStruct{})),\n\n\t\t// Value of array is non-comparable because of non-comparable elements.\n\t\tValueOf([0]map[int]int{}),\n\t\tValueOf([0]func(){}),\n\t\tValueOf(([1]struct{ I interface{} }{{[]int{}}})),\n\t\tValueOf(([1]interface{}{[1]interface{}{map[int]int{}}})),\n\t}\n\tfor _, value := range values {\n\t\t// Panic when reflect.Value.Equal using two valid non-comparable values.\n\t\tshouldPanic(\"are not comparable\", func() { value.Equal(value) })\n\n\t\t// If one is non-comparable and the other is invalid, the expected result is always false.\n\t\tif r := value.Equal(invalid); r != false {\n\t\t\tt.Errorf(\"%s == invalid got %t, want false\", value.Type(), r)\n\t\t}\n\t}\n}\n\nfunc TestInitFuncTypes(t *testing.T) {\n\tn := 100\n\tvar wg sync.WaitGroup\n\n\twg.Add(n)\n\tfor i := 0; i < n; i++ {\n\t\tgo func() {\n\t\t\tdefer wg.Done()\n\t\t\tipT := TypeOf(net.IP{})\n\t\t\tfor i := 0; i < ipT.NumMethod(); i++ {\n\t\t\t\t_ = ipT.Method(i)\n\t\t\t}\n\t\t}()\n\t}\n\twg.Wait()\n}\n\n*/\n"
  },
  {
    "path": "src/reflect/benchmark_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage reflect_test\n\ntype S struct {\n\ti1 int64\n\ti2 int64\n}\n"
  },
  {
    "path": "src/reflect/convert_test.go",
    "content": "package reflect_test\n\nimport (\n\t. \"reflect\"\n\t\"testing\"\n)\n\nfunc TestTinyConvert(t *testing.T) {\n\n\tV := ValueOf\n\n\tvar tests = []struct {\n\t\thave, want Value\n\t}{\n\t\t{V(int8(1)), V(int8(1))},\n\t\t{V(int8(2)), V(uint8(2))},\n\t\t{V(uint8(3)), V(int8(3))},\n\t\t{V(int8(4)), V(int16(4))},\n\t\t{V(int16(5)), V(int8(5))},\n\t\t{V(int8(6)), V(uint16(6))},\n\t\t{V(uint16(7)), V(int8(7))},\n\t\t{V(int8(8)), V(int32(8))},\n\t\t{V(int32(9)), V(int8(9))},\n\t\t{V(int8(10)), V(uint32(10))},\n\t\t{V(uint32(11)), V(int8(11))},\n\t\t{V(int8(12)), V(int64(12))},\n\t\t{V(int64(13)), V(int8(13))},\n\t\t{V(int8(14)), V(uint64(14))},\n\t\t{V(uint64(15)), V(int8(15))},\n\t\t{V(int8(16)), V(int(16))},\n\t\t{V(int(17)), V(int8(17))},\n\t\t{V(int8(18)), V(uint(18))},\n\t\t{V(uint(19)), V(int8(19))},\n\t\t{V(int8(20)), V(uintptr(20))},\n\t\t{V(uintptr(21)), V(int8(21))},\n\t\t{V(int8(22)), V(float32(22))},\n\t\t{V(float32(23)), V(int8(23))},\n\t\t{V(int8(24)), V(float64(24))},\n\t\t{V(float64(25)), V(int8(25))},\n\t\t{V(uint8(26)), V(uint8(26))},\n\t\t{V(uint8(27)), V(int16(27))},\n\t\t{V(int16(28)), V(uint8(28))},\n\t\t{V(uint8(29)), V(uint16(29))},\n\t\t{V(uint16(30)), V(uint8(30))},\n\t\t{V(uint8(31)), V(int32(31))},\n\t\t{V(int32(32)), V(uint8(32))},\n\t\t{V(uint8(33)), V(uint32(33))},\n\t\t{V(uint32(34)), V(uint8(34))},\n\t\t{V(uint8(35)), V(int64(35))},\n\t\t{V(int64(36)), V(uint8(36))},\n\t\t{V(uint8(37)), V(uint64(37))},\n\t\t{V(uint64(38)), V(uint8(38))},\n\t\t{V(uint8(39)), V(int(39))},\n\t\t{V(int(40)), V(uint8(40))},\n\t\t{V(uint8(41)), V(uint(41))},\n\t\t{V(uint(42)), V(uint8(42))},\n\t\t{V(uint8(43)), V(uintptr(43))},\n\t\t{V(uintptr(44)), V(uint8(44))},\n\t\t{V(uint8(45)), V(float32(45))},\n\t\t{V(float32(46)), V(uint8(46))},\n\t\t{V(uint8(47)), V(float64(47))},\n\t\t{V(float64(48)), V(uint8(48))},\n\t\t{V(int16(49)), V(int16(49))},\n\t\t{V(int16(50)), V(uint16(50))},\n\t\t{V(uint16(51)), V(int16(51))},\n\t\t{V(int16(52)), V(int32(52))},\n\t\t{V(int32(53)), V(int16(53))},\n\t\t{V(int16(54)), V(uint32(54))},\n\t\t{V(uint32(55)), V(int16(55))},\n\t\t{V(int16(56)), V(int64(56))},\n\t\t{V(int64(57)), V(int16(57))},\n\t\t{V(int16(58)), V(uint64(58))},\n\t\t{V(uint64(59)), V(int16(59))},\n\t\t{V(int16(60)), V(int(60))},\n\t\t{V(int(61)), V(int16(61))},\n\t\t{V(int16(62)), V(uint(62))},\n\t\t{V(uint(63)), V(int16(63))},\n\t\t{V(int16(64)), V(uintptr(64))},\n\t\t{V(uintptr(65)), V(int16(65))},\n\t\t{V(int16(66)), V(float32(66))},\n\t\t{V(float32(67)), V(int16(67))},\n\t\t{V(int16(68)), V(float64(68))},\n\t\t{V(float64(69)), V(int16(69))},\n\t\t{V(uint16(70)), V(uint16(70))},\n\t\t{V(uint16(71)), V(int32(71))},\n\t\t{V(int32(72)), V(uint16(72))},\n\t\t{V(uint16(73)), V(uint32(73))},\n\t\t{V(uint32(74)), V(uint16(74))},\n\t\t{V(uint16(75)), V(int64(75))},\n\t\t{V(int64(76)), V(uint16(76))},\n\t\t{V(uint16(77)), V(uint64(77))},\n\t\t{V(uint64(78)), V(uint16(78))},\n\t\t{V(uint16(79)), V(int(79))},\n\t\t{V(int(80)), V(uint16(80))},\n\t\t{V(uint16(81)), V(uint(81))},\n\t\t{V(uint(82)), V(uint16(82))},\n\t\t{V(uint16(83)), V(uintptr(83))},\n\t\t{V(uintptr(84)), V(uint16(84))},\n\t\t{V(uint16(85)), V(float32(85))},\n\t\t{V(float32(86)), V(uint16(86))},\n\t\t{V(uint16(87)), V(float64(87))},\n\t\t{V(float64(88)), V(uint16(88))},\n\t\t{V(int32(89)), V(int32(89))},\n\t\t{V(int32(90)), V(uint32(90))},\n\t\t{V(uint32(91)), V(int32(91))},\n\t\t{V(int32(92)), V(int64(92))},\n\t\t{V(int64(93)), V(int32(93))},\n\t\t{V(int32(94)), V(uint64(94))},\n\t\t{V(uint64(95)), V(int32(95))},\n\t\t{V(int32(96)), V(int(96))},\n\t\t{V(int(97)), V(int32(97))},\n\t\t{V(int32(98)), V(uint(98))},\n\t\t{V(uint(99)), V(int32(99))},\n\t\t{V(int32(100)), V(uintptr(100))},\n\t\t{V(uintptr(101)), V(int32(101))},\n\t\t{V(int32(102)), V(float32(102))},\n\t\t{V(float32(103)), V(int32(103))},\n\t\t{V(int32(104)), V(float64(104))},\n\t\t{V(float64(105)), V(int32(105))},\n\t\t{V(uint32(106)), V(uint32(106))},\n\t\t{V(uint32(107)), V(int64(107))},\n\t\t{V(int64(108)), V(uint32(108))},\n\t\t{V(uint32(109)), V(uint64(109))},\n\t\t{V(uint64(110)), V(uint32(110))},\n\t\t{V(uint32(111)), V(int(111))},\n\t\t{V(int(112)), V(uint32(112))},\n\t\t{V(uint32(113)), V(uint(113))},\n\t\t{V(uint(114)), V(uint32(114))},\n\t\t{V(uint32(115)), V(uintptr(115))},\n\t\t{V(uintptr(116)), V(uint32(116))},\n\t\t{V(uint32(117)), V(float32(117))},\n\t\t{V(float32(118)), V(uint32(118))},\n\t\t{V(uint32(119)), V(float64(119))},\n\t\t{V(float64(120)), V(uint32(120))},\n\t\t{V(int64(121)), V(int64(121))},\n\t\t{V(int64(122)), V(uint64(122))},\n\t\t{V(uint64(123)), V(int64(123))},\n\t\t{V(int64(124)), V(int(124))},\n\t\t{V(int(125)), V(int64(125))},\n\t\t{V(int64(126)), V(uint(126))},\n\t\t{V(uint(127)), V(int64(127))},\n\t\t{V(int64(128)), V(uintptr(128))},\n\t\t{V(uintptr(129)), V(int64(129))},\n\t\t{V(int64(130)), V(float32(130))},\n\t\t{V(float32(131)), V(int64(131))},\n\t\t{V(int64(132)), V(float64(132))},\n\t\t{V(float64(133)), V(int64(133))},\n\t\t{V(uint64(134)), V(uint64(134))},\n\t\t{V(uint64(135)), V(int(135))},\n\t\t{V(int(136)), V(uint64(136))},\n\t\t{V(uint64(137)), V(uint(137))},\n\t\t{V(uint(138)), V(uint64(138))},\n\t\t{V(uint64(139)), V(uintptr(139))},\n\t\t{V(uintptr(140)), V(uint64(140))},\n\t\t{V(uint64(141)), V(float32(141))},\n\t\t{V(float32(142)), V(uint64(142))},\n\t\t{V(uint64(143)), V(float64(143))},\n\t\t{V(float64(144)), V(uint64(144))},\n\t\t{V(int(145)), V(int(145))},\n\t\t{V(int(146)), V(uint(146))},\n\t\t{V(uint(147)), V(int(147))},\n\t\t{V(int(148)), V(uintptr(148))},\n\t\t{V(uintptr(149)), V(int(149))},\n\t\t{V(int(150)), V(float32(150))},\n\t\t{V(float32(151)), V(int(151))},\n\t\t{V(int(152)), V(float64(152))},\n\t\t{V(float64(153)), V(int(153))},\n\t\t{V(uint(154)), V(uint(154))},\n\t\t{V(uint(155)), V(uintptr(155))},\n\t\t{V(uintptr(156)), V(uint(156))},\n\t\t{V(uint(157)), V(float32(157))},\n\t\t{V(float32(158)), V(uint(158))},\n\t\t{V(uint(159)), V(float64(159))},\n\t\t{V(float64(160)), V(uint(160))},\n\t\t{V(uintptr(161)), V(uintptr(161))},\n\t\t{V(uintptr(162)), V(float32(162))},\n\t\t{V(float32(163)), V(uintptr(163))},\n\t\t{V(uintptr(164)), V(float64(164))},\n\t\t{V(float64(165)), V(uintptr(165))},\n\t\t{V(float32(166)), V(float32(166))},\n\t\t{V(float32(167)), V(float64(167))},\n\t\t{V(float64(168)), V(float32(168))},\n\t\t{V(float64(169)), V(float64(169))},\n\t}\n\n\tfor _, tt := range tests {\n\t\tgot := tt.have.Convert(tt.want.Type())\n\t\tif !DeepEqual(got.Interface(), tt.want.Interface()) {\n\t\t\tt.Errorf(\"Failed to Convert() %T(%v) -> %T(%v),  got %T(%v)\", tt.have.Interface(), tt.have, tt.want.Interface(), tt.want, got.Interface(), got)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/reflect/deepequal.go",
    "content": "package reflect\n\nimport \"internal/reflectlite\"\n\nfunc DeepEqual(x, y interface{}) bool {\n\treturn reflectlite.DeepEqual(x, y)\n}\n"
  },
  {
    "path": "src/reflect/export_test.go",
    "content": "package reflect\n\ntype OtherPkgFields struct {\n\tOtherExported   int\n\totherUnexported int\n}\n"
  },
  {
    "path": "src/reflect/internal/example1/example.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage example1\n\ntype MyStruct struct {\n\tMyStructs []MyStruct\n\tMyStruct  *MyStruct\n}\n"
  },
  {
    "path": "src/reflect/internal/example2/example.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage example2\n\ntype MyStruct struct {\n\tMyStructs []MyStruct\n\tMyStruct  *MyStruct\n}\n"
  },
  {
    "path": "src/reflect/intw.go",
    "content": "//go:build !avr\n\npackage reflect\n\n// intw is an integer type, used in places where an int is typically required,\n// except architectures where the size of an int != word size.\n// See https://github.com/tinygo-org/tinygo/issues/1284.\ntype intw = int\n"
  },
  {
    "path": "src/reflect/intw_avr.go",
    "content": "//go:build avr\n\npackage reflect\n\n// intw is an integer type, used in places where an int is typically required,\n// except architectures where the size of an int != word size.\n// See https://github.com/tinygo-org/tinygo/issues/1284.\ntype intw = uintptr\n"
  },
  {
    "path": "src/reflect/intw_test.go",
    "content": "//go:build !avr\n\npackage reflect_test\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\t\"unsafe\"\n)\n\n// Verify that SliceHeader is the same size as a slice.\nvar _ [unsafe.Sizeof([]byte{})]byte = [unsafe.Sizeof(reflect.SliceHeader{})]byte{}\n\n// TestSliceHeaderIntegerSize verifies that SliceHeader.Len and Cap are type int on non-AVR platforms.\n// See https://github.com/tinygo-org/tinygo/issues/1284.\nfunc TestSliceHeaderIntegerSize(t *testing.T) {\n\tvar h reflect.SliceHeader\n\th.Len = int(0)\n\th.Cap = int(0)\n}\n\n// Verify that StringHeader is the same size as a string.\nvar _ [unsafe.Sizeof(\"hello\")]byte = [unsafe.Sizeof(reflect.StringHeader{})]byte{}\n\n// TestStringHeaderIntegerSize verifies that StringHeader.Len and Cap are type int on non-AVR platforms.\n// See https://github.com/tinygo-org/tinygo/issues/1284.\nfunc TestStringHeaderIntegerSize(t *testing.T) {\n\tvar h reflect.StringHeader\n\th.Len = int(0)\n}\n"
  },
  {
    "path": "src/reflect/iter.go",
    "content": "//go:build go1.23\n\n// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage reflect\n\nimport (\n\t\"iter\"\n)\n\nfunc rangeNum[T int8 | int16 | int32 | int64 | int |\n\tuint8 | uint16 | uint32 | uint64 | uint |\n\tuintptr, N int64 | uint64](num N, t Type) iter.Seq[Value] {\n\treturn func(yield func(v Value) bool) {\n\t\tconvert := t.PkgPath() != \"\"\n\t\t// cannot use range T(v) because no core type.\n\t\tfor i := T(0); i < T(num); i++ {\n\t\t\ttmp := ValueOf(i)\n\t\t\t// if the iteration value type is define by\n\t\t\t// type T built-in type.\n\t\t\tif convert {\n\t\t\t\ttmp = tmp.Convert(t)\n\t\t\t}\n\t\t\tif !yield(tmp) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Seq returns an iter.Seq[Value] that loops over the elements of v.\n// If v's kind is Func, it must be a function that has no results and\n// that takes a single argument of type func(T) bool for some type T.\n// If v's kind is Pointer, the pointer element type must have kind Array.\n// Otherwise v's kind must be Int, Int8, Int16, Int32, Int64,\n// Uint, Uint8, Uint16, Uint32, Uint64, Uintptr,\n// Array, Chan, Map, Slice, or String.\nfunc (v Value) Seq() iter.Seq[Value] {\n\t// TODO: canRangeFunc\n\t// if canRangeFunc(v.typ()) {\n\t// \treturn func(yield func(Value) bool) {\n\t// \t\trf := MakeFunc(v.Type().In(0), func(in []Value) []Value {\n\t// \t\t\treturn []Value{ValueOf(yield(in[0]))}\n\t// \t\t})\n\t// \t\tv.Call([]Value{rf})\n\t// \t}\n\t// }\n\tswitch v.Kind() {\n\tcase Int:\n\t\treturn rangeNum[int](v.Int(), v.Type())\n\tcase Int8:\n\t\treturn rangeNum[int8](v.Int(), v.Type())\n\tcase Int16:\n\t\treturn rangeNum[int16](v.Int(), v.Type())\n\tcase Int32:\n\t\treturn rangeNum[int32](v.Int(), v.Type())\n\tcase Int64:\n\t\treturn rangeNum[int64](v.Int(), v.Type())\n\tcase Uint:\n\t\treturn rangeNum[uint](v.Uint(), v.Type())\n\tcase Uint8:\n\t\treturn rangeNum[uint8](v.Uint(), v.Type())\n\tcase Uint16:\n\t\treturn rangeNum[uint16](v.Uint(), v.Type())\n\tcase Uint32:\n\t\treturn rangeNum[uint32](v.Uint(), v.Type())\n\tcase Uint64:\n\t\treturn rangeNum[uint64](v.Uint(), v.Type())\n\tcase Uintptr:\n\t\treturn rangeNum[uintptr](v.Uint(), v.Type())\n\tcase Pointer:\n\t\tif v.Elem().Kind() != Array {\n\t\t\tbreak\n\t\t}\n\t\treturn func(yield func(Value) bool) {\n\t\t\tv = v.Elem()\n\t\t\tfor i := 0; i < v.Len(); i++ {\n\t\t\t\tif !yield(ValueOf(i)) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tcase Array, Slice:\n\t\treturn func(yield func(Value) bool) {\n\t\t\tfor i := 0; i < v.Len(); i++ {\n\t\t\t\tif !yield(ValueOf(i)) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tcase String:\n\t\treturn func(yield func(Value) bool) {\n\t\t\tfor i := range v.String() {\n\t\t\t\tif !yield(ValueOf(i)) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tcase Map:\n\t\treturn func(yield func(Value) bool) {\n\t\t\ti := v.MapRange()\n\t\t\tfor i.Next() {\n\t\t\t\tif !yield(i.Key()) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tcase Chan:\n\t\treturn func(yield func(Value) bool) {\n\t\t\tfor value, ok := v.Recv(); ok; value, ok = v.Recv() {\n\t\t\t\tif !yield(value) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tpanic(\"reflect: \" + v.Type().String() + \" cannot produce iter.Seq[Value]\")\n}\n\n// Seq2 returns an iter.Seq2[Value, Value] that loops over the elements of v.\n// If v's kind is Func, it must be a function that has no results and\n// that takes a single argument of type func(K, V) bool for some type K, V.\n// If v's kind is Pointer, the pointer element type must have kind Array.\n// Otherwise v's kind must be Array, Map, Slice, or String.\nfunc (v Value) Seq2() iter.Seq2[Value, Value] {\n\t// TODO: canRangeFunc2\n\t// if canRangeFunc2(v.typ()) {\n\t// \treturn func(yield func(Value, Value) bool) {\n\t// \t\trf := MakeFunc(v.Type().In(0), func(in []Value) []Value {\n\t// \t\t\treturn []Value{ValueOf(yield(in[0], in[1]))}\n\t// \t\t})\n\t// \t\tv.Call([]Value{rf})\n\t// \t}\n\t// }\n\tswitch v.Kind() {\n\tcase Pointer:\n\t\tif v.Elem().Kind() != Array {\n\t\t\tbreak\n\t\t}\n\t\treturn func(yield func(Value, Value) bool) {\n\t\t\tv = v.Elem()\n\t\t\tfor i := 0; i < v.Len(); i++ {\n\t\t\t\tif !yield(ValueOf(i), v.Index(i)) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tcase Array, Slice:\n\t\treturn func(yield func(Value, Value) bool) {\n\t\t\tfor i := 0; i < v.Len(); i++ {\n\t\t\t\tif !yield(ValueOf(i), v.Index(i)) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tcase String:\n\t\treturn func(yield func(Value, Value) bool) {\n\t\t\tfor i, v := range v.String() {\n\t\t\t\tif !yield(ValueOf(i), ValueOf(v)) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tcase Map:\n\t\treturn func(yield func(Value, Value) bool) {\n\t\t\ti := v.MapRange()\n\t\t\tfor i.Next() {\n\t\t\t\tif !yield(i.Key(), i.Value()) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tpanic(\"reflect: \" + v.Type().String() + \" cannot produce iter.Seq2[Value, Value]\")\n}\n"
  },
  {
    "path": "src/reflect/iter_test.go",
    "content": "//go:build go1.23\n\n// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage reflect_test\n\nimport (\n\t\"iter\"\n\t\"maps\"\n\t\"reflect\"\n\t. \"reflect\"\n\t\"testing\"\n)\n\ntype N int8\n\nfunc TestValueSeq(t *testing.T) {\n\tm := map[string]int{\n\t\t\"1\": 1,\n\t\t\"2\": 2,\n\t\t\"3\": 3,\n\t\t\"4\": 4,\n\t}\n\tc := make(chan int, 3)\n\tfor i := range 3 {\n\t\tc <- i\n\t}\n\tclose(c)\n\ttests := []struct {\n\t\tname  string\n\t\tval   Value\n\t\tcheck func(*testing.T, iter.Seq[Value])\n\t}{\n\t\t{\"int\", ValueOf(4), func(t *testing.T, s iter.Seq[Value]) {\n\t\t\ti := int64(0)\n\t\t\tfor v := range s {\n\t\t\t\tif v.Int() != i {\n\t\t\t\t\tt.Fatalf(\"got %d, want %d\", v.Int(), i)\n\t\t\t\t}\n\t\t\t\ti++\n\t\t\t}\n\t\t\tif i != 4 {\n\t\t\t\tt.Fatalf(\"should loop four times\")\n\t\t\t}\n\t\t}},\n\t\t{\"int8\", ValueOf(int8(4)), func(t *testing.T, s iter.Seq[Value]) {\n\t\t\ti := int8(0)\n\t\t\tfor v := range s {\n\t\t\t\tif v.Interface().(int8) != i {\n\t\t\t\t\tt.Fatalf(\"got %d, want %d\", v.Int(), i)\n\t\t\t\t}\n\t\t\t\ti++\n\t\t\t}\n\t\t\tif i != 4 {\n\t\t\t\tt.Fatalf(\"should loop four times\")\n\t\t\t}\n\t\t}},\n\t\t{\"uint\", ValueOf(uint64(4)), func(t *testing.T, s iter.Seq[Value]) {\n\t\t\ti := uint64(0)\n\t\t\tfor v := range s {\n\t\t\t\tif v.Uint() != i {\n\t\t\t\t\tt.Fatalf(\"got %d, want %d\", v.Uint(), i)\n\t\t\t\t}\n\t\t\t\ti++\n\t\t\t}\n\t\t\tif i != 4 {\n\t\t\t\tt.Fatalf(\"should loop four times\")\n\t\t\t}\n\t\t}},\n\t\t{\"uint8\", ValueOf(uint8(4)), func(t *testing.T, s iter.Seq[Value]) {\n\t\t\ti := uint8(0)\n\t\t\tfor v := range s {\n\t\t\t\tif v.Interface().(uint8) != i {\n\t\t\t\t\tt.Fatalf(\"got %d, want %d\", v.Int(), i)\n\t\t\t\t}\n\t\t\t\ti++\n\t\t\t}\n\t\t\tif i != 4 {\n\t\t\t\tt.Fatalf(\"should loop four times\")\n\t\t\t}\n\t\t}},\n\t\t{\"*[4]int\", ValueOf(&[4]int{1, 2, 3, 4}), func(t *testing.T, s iter.Seq[Value]) {\n\t\t\ti := int64(0)\n\t\t\tfor v := range s {\n\t\t\t\tif v.Int() != i {\n\t\t\t\t\tt.Fatalf(\"got %d, want %d\", v.Int(), i)\n\t\t\t\t}\n\t\t\t\ti++\n\t\t\t}\n\t\t\tif i != 4 {\n\t\t\t\tt.Fatalf(\"should loop four times\")\n\t\t\t}\n\t\t}},\n\t\t{\"[4]int\", ValueOf([4]int{1, 2, 3, 4}), func(t *testing.T, s iter.Seq[Value]) {\n\t\t\ti := int64(0)\n\t\t\tfor v := range s {\n\t\t\t\tif v.Int() != i {\n\t\t\t\t\tt.Fatalf(\"got %d, want %d\", v.Int(), i)\n\t\t\t\t}\n\t\t\t\ti++\n\t\t\t}\n\t\t\tif i != 4 {\n\t\t\t\tt.Fatalf(\"should loop four times\")\n\t\t\t}\n\t\t}},\n\t\t{\"[]int\", ValueOf([]int{1, 2, 3, 4}), func(t *testing.T, s iter.Seq[Value]) {\n\t\t\ti := int64(0)\n\t\t\tfor v := range s {\n\t\t\t\tif v.Int() != i {\n\t\t\t\t\tt.Fatalf(\"got %d, want %d\", v.Int(), i)\n\t\t\t\t}\n\t\t\t\ti++\n\t\t\t}\n\t\t\tif i != 4 {\n\t\t\t\tt.Fatalf(\"should loop four times\")\n\t\t\t}\n\t\t}},\n\t\t{\"string\", ValueOf(\"12语言\"), func(t *testing.T, s iter.Seq[Value]) {\n\t\t\ti := int64(0)\n\t\t\tindexes := []int64{0, 1, 2, 5}\n\t\t\tfor v := range s {\n\t\t\t\tif v.Int() != indexes[i] {\n\t\t\t\t\tt.Fatalf(\"got %d, want %d\", v.Int(), indexes[i])\n\t\t\t\t}\n\t\t\t\ti++\n\t\t\t}\n\t\t\tif i != 4 {\n\t\t\t\tt.Fatalf(\"should loop four times\")\n\t\t\t}\n\t\t}},\n\t\t{\"map[string]int\", ValueOf(m), func(t *testing.T, s iter.Seq[Value]) {\n\t\t\tcopy := maps.Clone(m)\n\t\t\tfor v := range s {\n\t\t\t\tif _, ok := copy[v.String()]; !ok {\n\t\t\t\t\tt.Fatalf(\"unexpected %v\", v.Interface())\n\t\t\t\t}\n\t\t\t\tdelete(copy, v.String())\n\t\t\t}\n\t\t\tif len(copy) != 0 {\n\t\t\t\tt.Fatalf(\"should loop four times\")\n\t\t\t}\n\t\t}},\n\t\t// {\"chan int\", ValueOf(c), func(t *testing.T, s iter.Seq[Value]) {\n\t\t// \ti := 0\n\t\t// \tm := map[int64]bool{\n\t\t// \t\t0: false,\n\t\t// \t\t1: false,\n\t\t// \t\t2: false,\n\t\t// \t}\n\t\t// \tfor v := range s {\n\t\t// \t\tif b, ok := m[v.Int()]; !ok || b {\n\t\t// \t\t\tt.Fatalf(\"unexpected %v\", v.Interface())\n\t\t// \t\t}\n\t\t// \t\tm[v.Int()] = true\n\t\t// \t\ti++\n\t\t// \t}\n\t\t// \tif i != 3 {\n\t\t// \t\tt.Fatalf(\"should loop three times\")\n\t\t// \t}\n\t\t// }},\n\t\t// {\"func\", ValueOf(func(yield func(int) bool) {\n\t\t// \tfor i := range 4 {\n\t\t// \t\tif !yield(i) {\n\t\t// \t\t\treturn\n\t\t// \t\t}\n\t\t// \t}\n\t\t// }), func(t *testing.T, s iter.Seq[Value]) {\n\t\t// \ti := int64(0)\n\t\t// \tfor v := range s {\n\t\t// \t\tif v.Int() != i {\n\t\t// \t\t\tt.Fatalf(\"got %d, want %d\", v.Int(), i)\n\t\t// \t\t}\n\t\t// \t\ti++\n\t\t// \t}\n\t\t// \tif i != 4 {\n\t\t// \t\tt.Fatalf(\"should loop four times\")\n\t\t// \t}\n\t\t// }},\n\t\t// {\"method\", ValueOf(methodIter{}).MethodByName(\"Seq\"), func(t *testing.T, s iter.Seq[Value]) {\n\t\t// \ti := int64(0)\n\t\t// \tfor v := range s {\n\t\t// \t\tif v.Int() != i {\n\t\t// \t\t\tt.Fatalf(\"got %d, want %d\", v.Int(), i)\n\t\t// \t\t}\n\t\t// \t\ti++\n\t\t// \t}\n\t\t// \tif i != 4 {\n\t\t// \t\tt.Fatalf(\"should loop four times\")\n\t\t// \t}\n\t\t// }},\n\t\t{\"type N int8\", ValueOf(N(4)), func(t *testing.T, s iter.Seq[Value]) {\n\t\t\ti := N(0)\n\t\t\tfor v := range s {\n\t\t\t\tif v.Int() != int64(i) {\n\t\t\t\t\tt.Fatalf(\"got %d, want %d\", v.Int(), i)\n\t\t\t\t}\n\t\t\t\ti++\n\t\t\t\tif v.Type() != reflect.TypeOf(i) {\n\t\t\t\t\tj := ValueOf(i)\n\t\t\t\t\tt.Logf(\"ValueOf(j): %s\", j.Type())\n\t\t\t\t\tt.Fatalf(\"got %s, want %s\", v.Type(), reflect.TypeOf(i))\n\t\t\t\t}\n\t\t\t}\n\t\t\tif i != 4 {\n\t\t\t\tt.Fatalf(\"should loop four times\")\n\t\t\t}\n\t\t}},\n\t}\n\tfor _, tc := range tests {\n\t\tseq := tc.val.Seq()\n\t\ttc.check(t, seq)\n\t}\n}\n\nfunc TestValueSeq2(t *testing.T) {\n\tm := map[string]int{\n\t\t\"1\": 1,\n\t\t\"2\": 2,\n\t\t\"3\": 3,\n\t\t\"4\": 4,\n\t}\n\ttests := []struct {\n\t\tname  string\n\t\tval   Value\n\t\tcheck func(*testing.T, iter.Seq2[Value, Value])\n\t}{\n\t\t{\"*[4]int\", ValueOf(&[4]int{1, 2, 3, 4}), func(t *testing.T, s iter.Seq2[Value, Value]) {\n\t\t\ti := int64(0)\n\t\t\tfor v1, v2 := range s {\n\t\t\t\tif v1.Int() != i {\n\t\t\t\t\tt.Fatalf(\"got %d, want %d\", v1.Int(), i)\n\t\t\t\t}\n\t\t\t\ti++\n\t\t\t\tif v2.Int() != i {\n\t\t\t\t\tt.Fatalf(\"got %d, want %d\", v2.Int(), i)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif i != 4 {\n\t\t\t\tt.Fatalf(\"should loop four times\")\n\t\t\t}\n\t\t}},\n\t\t{\"[4]int\", ValueOf([4]int{1, 2, 3, 4}), func(t *testing.T, s iter.Seq2[Value, Value]) {\n\t\t\ti := int64(0)\n\t\t\tfor v1, v2 := range s {\n\t\t\t\tif v1.Int() != i {\n\t\t\t\t\tt.Fatalf(\"got %d, want %d\", v1.Int(), i)\n\t\t\t\t}\n\t\t\t\ti++\n\t\t\t\tif v2.Int() != i {\n\t\t\t\t\tt.Fatalf(\"got %d, want %d\", v2.Int(), i)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif i != 4 {\n\t\t\t\tt.Fatalf(\"should loop four times\")\n\t\t\t}\n\t\t}},\n\t\t{\"[]int\", ValueOf([]int{1, 2, 3, 4}), func(t *testing.T, s iter.Seq2[Value, Value]) {\n\t\t\ti := int64(0)\n\t\t\tfor v1, v2 := range s {\n\t\t\t\tif v1.Int() != i {\n\t\t\t\t\tt.Fatalf(\"got %d, want %d\", v1.Int(), i)\n\t\t\t\t}\n\t\t\t\ti++\n\t\t\t\tif v2.Int() != i {\n\t\t\t\t\tt.Fatalf(\"got %d, want %d\", v2.Int(), i)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif i != 4 {\n\t\t\t\tt.Fatalf(\"should loop four times\")\n\t\t\t}\n\t\t}},\n\t\t{\"string\", ValueOf(\"12语言\"), func(t *testing.T, s iter.Seq2[Value, Value]) {\n\t\t\tnext, stop := iter.Pull2(s)\n\t\t\tdefer stop()\n\t\t\ti := int64(0)\n\t\t\tfor j, s := range \"12语言\" {\n\t\t\t\tv1, v2, ok := next()\n\t\t\t\tif !ok {\n\t\t\t\t\tt.Fatalf(\"should loop four times\")\n\t\t\t\t}\n\t\t\t\tif v1.Int() != int64(j) {\n\t\t\t\t\tt.Fatalf(\"got %d, want %d\", v1.Int(), j)\n\t\t\t\t}\n\t\t\t\tif v2.Interface() != s {\n\t\t\t\t\tt.Fatalf(\"got %v, want %v\", v2.Interface(), s)\n\t\t\t\t}\n\t\t\t\ti++\n\t\t\t}\n\t\t\tif i != 4 {\n\t\t\t\tt.Fatalf(\"should loop four times\")\n\t\t\t}\n\t\t}},\n\t\t{\"map[string]int\", ValueOf(m), func(t *testing.T, s iter.Seq2[Value, Value]) {\n\t\t\tcopy := maps.Clone(m)\n\t\t\tfor v1, v2 := range s {\n\t\t\t\tv, ok := copy[v1.String()]\n\t\t\t\tif !ok {\n\t\t\t\t\tt.Fatalf(\"unexpected %v\", v1.String())\n\t\t\t\t}\n\t\t\t\tif v != v2.Interface() {\n\t\t\t\t\tt.Fatalf(\"got %v, want %d\", v2.Interface(), v)\n\t\t\t\t}\n\t\t\t\tdelete(copy, v1.String())\n\t\t\t}\n\t\t\tif len(copy) != 0 {\n\t\t\t\tt.Fatalf(\"should loop four times\")\n\t\t\t}\n\t\t}},\n\t\t// {\"func\", ValueOf(func(f func(int, int) bool) {\n\t\t// \tfor i := range 4 {\n\t\t// \t\tf(i, i+1)\n\t\t// \t}\n\t\t// }), func(t *testing.T, s iter.Seq2[Value, Value]) {\n\t\t// \ti := int64(0)\n\t\t// \tfor v1, v2 := range s {\n\t\t// \t\tif v1.Int() != i {\n\t\t// \t\t\tt.Fatalf(\"got %d, want %d\", v1.Int(), i)\n\t\t// \t\t}\n\t\t// \t\ti++\n\t\t// \t\tif v2.Int() != i {\n\t\t// \t\t\tt.Fatalf(\"got %d, want %d\", v2.Int(), i)\n\t\t// \t\t}\n\t\t// \t}\n\t\t// \tif i != 4 {\n\t\t// \t\tt.Fatalf(\"should loop four times\")\n\t\t// \t}\n\t\t// }},\n\t\t// {\"method\", ValueOf(methodIter2{}).MethodByName(\"Seq2\"), func(t *testing.T, s iter.Seq2[Value, Value]) {\n\t\t// \ti := int64(0)\n\t\t// \tfor v1, v2 := range s {\n\t\t// \t\tif v1.Int() != i {\n\t\t// \t\t\tt.Fatalf(\"got %d, want %d\", v1.Int(), i)\n\t\t// \t\t}\n\t\t// \t\ti++\n\t\t// \t\tif v2.Int() != i {\n\t\t// \t\t\tt.Fatalf(\"got %d, want %d\", v2.Int(), i)\n\t\t// \t\t}\n\t\t// \t}\n\t\t// \tif i != 4 {\n\t\t// \t\tt.Fatalf(\"should loop four times\")\n\t\t// \t}\n\t\t// }},\n\t\t{\"[4]N\", ValueOf([4]N{0, 1, 2, 3}), func(t *testing.T, s iter.Seq2[Value, Value]) {\n\t\t\ti := N(0)\n\t\t\tfor v1, v2 := range s {\n\t\t\t\tif v1.Int() != int64(i) {\n\t\t\t\t\tt.Fatalf(\"got %d, want %d\", v1.Int(), i)\n\t\t\t\t}\n\t\t\t\tif v2.Int() != int64(i) {\n\t\t\t\t\tt.Fatalf(\"got %d, want %d\", v2.Int(), i)\n\t\t\t\t}\n\t\t\t\ti++\n\t\t\t\tif v2.Type() != reflect.TypeOf(i) {\n\t\t\t\t\tt.Fatalf(\"got %s, want %s\", v2.Type(), reflect.TypeOf(i))\n\t\t\t\t}\n\t\t\t}\n\t\t\tif i != 4 {\n\t\t\t\tt.Fatalf(\"should loop four times\")\n\t\t\t}\n\t\t}},\n\t\t{\"[]N\", ValueOf([]N{1, 2, 3, 4}), func(t *testing.T, s iter.Seq2[Value, Value]) {\n\t\t\ti := N(0)\n\t\t\tfor v1, v2 := range s {\n\t\t\t\tif v1.Int() != int64(i) {\n\t\t\t\t\tt.Fatalf(\"got %d, want %d\", v1.Int(), i)\n\t\t\t\t}\n\t\t\t\ti++\n\t\t\t\tif v2.Int() != int64(i) {\n\t\t\t\t\tt.Fatalf(\"got %d, want %d\", v2.Int(), i)\n\t\t\t\t}\n\t\t\t\tif v2.Type() != reflect.TypeOf(i) {\n\t\t\t\t\tt.Fatalf(\"got %s, want %s\", v2.Type(), reflect.TypeOf(i))\n\t\t\t\t}\n\t\t\t}\n\t\t\tif i != 4 {\n\t\t\t\tt.Fatalf(\"should loop four times\")\n\t\t\t}\n\t\t}},\n\t}\n\tfor _, tc := range tests {\n\t\tseq := tc.val.Seq2()\n\t\ttc.check(t, seq)\n\t}\n}\n\n// methodIter is a type from which we can derive a method\n// value that is an iter.Seq.\ntype methodIter struct{}\n\nfunc (methodIter) Seq(yield func(int) bool) {\n\tfor i := range 4 {\n\t\tif !yield(i) {\n\t\t\treturn\n\t\t}\n\t}\n}\n\n// For Type.CanSeq test.\nfunc (methodIter) NonSeq(yield func(int)) {}\n\n// methodIter2 is a type from which we can derive a method\n// value that is an iter.Seq2.\ntype methodIter2 struct{}\n\nfunc (methodIter2) Seq2(yield func(int, int) bool) {\n\tfor i := range 4 {\n\t\tif !yield(i, i+1) {\n\t\t\treturn\n\t\t}\n\t}\n}\n\n// For Type.CanSeq2 test.\nfunc (methodIter2) NonSeq2(yield func(int, int)) {}\n"
  },
  {
    "path": "src/reflect/makefunc.go",
    "content": "package reflect\n\nfunc MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value {\n\tpanic(\"unimplemented: reflect.MakeFunc()\")\n}\n"
  },
  {
    "path": "src/reflect/swapper.go",
    "content": "package reflect\n\nimport \"internal/reflectlite\"\n\nfunc Swapper(slice interface{}) func(i, j int) {\n\treturn reflectlite.Swapper(slice)\n}\n"
  },
  {
    "path": "src/reflect/tostring_test.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Formatting of reflection types and values for debugging.\n// Not defined as methods so they do not need to be linked into most binaries;\n// the functions are not used by the library itself, only in tests.\n\npackage reflect_test\n\nimport (\n\t. \"reflect\"\n\t\"strconv\"\n)\n\n// valueToString returns a textual representation of the reflection value val.\n// For debugging only.\nfunc valueToString(val Value) string {\n\tvar str string\n\tif !val.IsValid() {\n\t\treturn \"<zero Value>\"\n\t}\n\ttyp := val.Type()\n\tswitch val.Kind() {\n\tcase Int, Int8, Int16, Int32, Int64:\n\t\treturn strconv.FormatInt(val.Int(), 10)\n\tcase Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:\n\t\treturn strconv.FormatUint(val.Uint(), 10)\n\tcase Float32, Float64:\n\t\treturn strconv.FormatFloat(val.Float(), 'g', -1, 64)\n\tcase Complex64, Complex128:\n\t\tc := val.Complex()\n\t\treturn strconv.FormatFloat(real(c), 'g', -1, 64) + \"+\" + strconv.FormatFloat(imag(c), 'g', -1, 64) + \"i\"\n\tcase String:\n\t\treturn val.String()\n\tcase Bool:\n\t\tif val.Bool() {\n\t\t\treturn \"true\"\n\t\t} else {\n\t\t\treturn \"false\"\n\t\t}\n\tcase Pointer:\n\t\tv := val\n\t\tstr = typ.String() + \"(\"\n\t\tif v.IsNil() {\n\t\t\tstr += \"0\"\n\t\t} else {\n\t\t\tstr += \"&\" + valueToString(v.Elem())\n\t\t}\n\t\tstr += \")\"\n\t\treturn str\n\tcase Array, Slice:\n\t\tv := val\n\t\tstr += typ.String()\n\t\tstr += \"{\"\n\t\tfor i := 0; i < v.Len(); i++ {\n\t\t\tif i > 0 {\n\t\t\t\tstr += \", \"\n\t\t\t}\n\t\t\tstr += valueToString(v.Index(i))\n\t\t}\n\t\tstr += \"}\"\n\t\treturn str\n\tcase Map:\n\t\tt := typ\n\t\tstr = t.String()\n\t\tstr += \"{\"\n\t\tstr += \"<can't iterate on maps>\"\n\t\tstr += \"}\"\n\t\treturn str\n\tcase Chan:\n\t\tstr = typ.String()\n\t\treturn str\n\tcase Struct:\n\t\tt := typ\n\t\tv := val\n\t\tstr += t.String()\n\t\tstr += \"{\"\n\t\tfor i, n := 0, v.NumField(); i < n; i++ {\n\t\t\tif i > 0 {\n\t\t\t\tstr += \", \"\n\t\t\t}\n\t\t\tstr += valueToString(v.Field(i))\n\t\t}\n\t\tstr += \"}\"\n\t\treturn str\n\tcase Interface:\n\t\treturn typ.String() + \"(\" + valueToString(val.Elem()) + \")\"\n\tcase Func:\n\t\tv := val\n\t\treturn typ.String() + \"(\" + strconv.FormatUint(uint64(v.Pointer()), 10) + \")\"\n\tdefault:\n\t\tpanic(\"valueToString: can't print type \" + typ.String())\n\t}\n}\n"
  },
  {
    "path": "src/reflect/type.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Type information of an interface is stored as a pointer to a global in the\n// interface type (runtime._interface). This is called a type struct.\n// It always starts with a byte that contains both the type kind and a few\n// flags. In most cases it also contains a pointer to another type struct\n// (ptrTo), that is the pointer type of the current type (for example, type int\n// also has a pointer to the type *int). The exception is pointer types, to\n// avoid infinite recursion.\n//\n// The layouts specifically look like this:\n// - basic types (Bool..UnsafePointer):\n//     meta         uint8 // actually: kind + flags\n//     ptrTo        *typeStruct\n// - channels and slices (see elemType):\n//     meta          uint8\n//     nmethods     uint16 (0)\n//     ptrTo        *typeStruct\n//     elementType  *typeStruct // the type that you get with .Elem()\n// - pointer types (see ptrType, this doesn't include chan, map, etc):\n//     meta         uint8\n//     nmethods     uint16\n//     elementType  *typeStruct\n// - array types (see arrayType)\n//     meta         uint8\n//     nmethods     uint16 (0)\n//     ptrTo        *typeStruct\n//     elem         *typeStruct // element type of the array\n//     arrayLen     uintptr     // length of the array (this is part of the type)\n//     slicePtr     *typeStruct // pointer to []T type\n// - map types (this is still missing the key and element types)\n//     meta         uint8\n//     nmethods     uint16 (0)\n//     ptrTo        *typeStruct\n//     elem         *typeStruct\n//     key          *typeStruct\n// - struct types (see structType):\n//     meta         uint8\n//     nmethods     uint16\n//     ptrTo        *typeStruct\n//     size         uint32\n//     pkgpath      *byte       // package path; null terminated\n//     numField     uint16\n//     fields       [...]structField // the remaining fields are all of type structField\n// - interface types (this is missing the interface methods):\n//     meta         uint8\n//     ptrTo        *typeStruct\n// - signature types (this is missing input and output parameters):\n//     meta         uint8\n//     ptrTo        *typeStruct\n// - named types\n//     meta         uint8\n//     nmethods     uint16      // number of methods\n//     ptrTo        *typeStruct\n//     elem         *typeStruct // underlying type\n//     pkgpath      *byte       // pkgpath; null terminated\n//     name         [1]byte     // actual name; null terminated\n//\n// The type struct is essentially a union of all the above types. Which it is,\n// can be determined by looking at the meta byte.\n\npackage reflect\n\nimport (\n\t\"internal/reflectlite\"\n\t\"unsafe\"\n)\n\ntype Kind = reflectlite.Kind\n\nconst (\n\tInvalid       Kind = reflectlite.Invalid\n\tBool          Kind = reflectlite.Bool\n\tInt           Kind = reflectlite.Int\n\tInt8          Kind = reflectlite.Int8\n\tInt16         Kind = reflectlite.Int16\n\tInt32         Kind = reflectlite.Int32\n\tInt64         Kind = reflectlite.Int64\n\tUint          Kind = reflectlite.Uint\n\tUint8         Kind = reflectlite.Uint8\n\tUint16        Kind = reflectlite.Uint16\n\tUint32        Kind = reflectlite.Uint32\n\tUint64        Kind = reflectlite.Uint64\n\tUintptr       Kind = reflectlite.Uintptr\n\tFloat32       Kind = reflectlite.Float32\n\tFloat64       Kind = reflectlite.Float64\n\tComplex64     Kind = reflectlite.Complex64\n\tComplex128    Kind = reflectlite.Complex128\n\tArray         Kind = reflectlite.Array\n\tChan          Kind = reflectlite.Chan\n\tFunc          Kind = reflectlite.Func\n\tInterface     Kind = reflectlite.Interface\n\tMap           Kind = reflectlite.Map\n\tPointer       Kind = reflectlite.Pointer\n\tSlice         Kind = reflectlite.Slice\n\tString        Kind = reflectlite.String\n\tStruct        Kind = reflectlite.Struct\n\tUnsafePointer Kind = reflectlite.UnsafePointer\n)\n\nconst Ptr = reflectlite.Ptr\n\ntype ChanDir = reflectlite.ChanDir\n\nconst (\n\tRecvDir = reflectlite.RecvDir\n\tSendDir = reflectlite.SendDir\n\tBothDir = reflectlite.BothDir\n)\n\n// Method represents a single method.\ntype Method struct {\n\t// Name is the method name.\n\tName string\n\n\t// PkgPath is the package path that qualifies a lower case (unexported)\n\t// method name. It is empty for upper case (exported) method names.\n\t// The combination of PkgPath and Name uniquely identifies a method\n\t// in a method set.\n\t// See https://golang.org/ref/spec#Uniqueness_of_identifiers\n\tPkgPath string\n\n\tType  Type  // method type\n\tFunc  Value // func with receiver as first argument\n\tIndex int   // index for Type.Method\n}\n\n// IsExported reports whether the method is exported.\nfunc (m Method) IsExported() bool {\n\treturn m.PkgPath == \"\"\n}\n\n// The following Type type has been copied almost entirely from\n// https://github.com/golang/go/blob/go1.15/src/reflect/type.go#L27-L212.\n// Some methods have been commented out as they haven't yet been implemented.\n\n// Type is the representation of a Go type.\n//\n// Not all methods apply to all kinds of types. Restrictions,\n// if any, are noted in the documentation for each method.\n// Use the Kind method to find out the kind of type before\n// calling kind-specific methods. Calling a method\n// inappropriate to the kind of type causes a run-time panic.\n//\n// Type values are comparable, such as with the == operator,\n// so they can be used as map keys.\n// Two Type values are equal if they represent identical types.\ntype Type interface {\n\t// Methods applicable to all types.\n\n\t// Align returns the alignment in bytes of a value of\n\t// this type when allocated in memory.\n\tAlign() int\n\n\t// FieldAlign returns the alignment in bytes of a value of\n\t// this type when used as a field in a struct.\n\tFieldAlign() int\n\n\t// Method returns the i'th method in the type's method set.\n\t// It panics if i is not in the range [0, NumMethod()).\n\t//\n\t// For a non-interface type T or *T, the returned Method's Type and Func\n\t// fields describe a function whose first argument is the receiver.\n\t//\n\t// For an interface type, the returned Method's Type field gives the\n\t// method signature, without a receiver, and the Func field is nil.\n\t//\n\t// Only exported methods are accessible and they are sorted in\n\t// lexicographic order.\n\tMethod(int) Method\n\n\t// MethodByName returns the method with that name in the type's\n\t// method set and a boolean indicating if the method was found.\n\t//\n\t// For a non-interface type T or *T, the returned Method's Type and Func\n\t// fields describe a function whose first argument is the receiver.\n\t//\n\t// For an interface type, the returned Method's Type field gives the\n\t// method signature, without a receiver, and the Func field is nil.\n\tMethodByName(string) (Method, bool)\n\n\t// NumMethod returns the number of exported methods in the type's method set.\n\tNumMethod() int\n\n\t// Name returns the type's name within its package for a defined type.\n\t// For other (non-defined) types it returns the empty string.\n\tName() string\n\n\t// PkgPath returns a defined type's package path, that is, the import path\n\t// that uniquely identifies the package, such as \"encoding/base64\".\n\t// If the type was predeclared (string, error) or not defined (*T, struct{},\n\t// []int, or A where A is an alias for a non-defined type), the package path\n\t// will be the empty string.\n\tPkgPath() string\n\n\t// Size returns the number of bytes needed to store\n\t// a value of the given type; it is analogous to unsafe.Sizeof.\n\tSize() uintptr\n\n\t// String returns a string representation of the type.\n\t// The string representation may use shortened package names\n\t// (e.g., base64 instead of \"encoding/base64\") and is not\n\t// guaranteed to be unique among types. To test for type identity,\n\t// compare the Types directly.\n\tString() string\n\n\t// Kind returns the specific kind of this type.\n\tKind() Kind\n\n\t// Implements reports whether the type implements the interface type u.\n\tImplements(u Type) bool\n\n\t// AssignableTo reports whether a value of the type is assignable to type u.\n\tAssignableTo(u Type) bool\n\n\t// ConvertibleTo reports whether a value of the type is convertible to type u.\n\tConvertibleTo(u Type) bool\n\n\t// Comparable reports whether values of this type are comparable.\n\tComparable() bool\n\n\t// Methods applicable only to some types, depending on Kind.\n\t// The methods allowed for each kind are:\n\t//\n\t//\tInt*, Uint*, Float*, Complex*: Bits\n\t//\tArray: Elem, Len\n\t//\tChan: ChanDir, Elem\n\t//\tFunc: In, NumIn, Out, NumOut, IsVariadic.\n\t//\tMap: Key, Elem\n\t//\tPointer: Elem\n\t//\tSlice: Elem\n\t//\tStruct: Field, FieldByIndex, FieldByName, FieldByNameFunc, NumField\n\n\t// Bits returns the size of the type in bits.\n\t// It panics if the type's Kind is not one of the\n\t// sized or unsized Int, Uint, Float, or Complex kinds.\n\tBits() int\n\n\t// ChanDir returns a channel type's direction.\n\t// It panics if the type's Kind is not Chan.\n\tChanDir() ChanDir\n\n\t// IsVariadic reports whether a function type's final input parameter\n\t// is a \"...\" parameter. If so, t.In(t.NumIn() - 1) returns the parameter's\n\t// implicit actual type []T.\n\t//\n\t// For concreteness, if t represents func(x int, y ... float64), then\n\t//\n\t//\tt.NumIn() == 2\n\t//\tt.In(0) is the reflect.Type for \"int\"\n\t//\tt.In(1) is the reflect.Type for \"[]float64\"\n\t//\tt.IsVariadic() == true\n\t//\n\t// IsVariadic panics if the type's Kind is not Func.\n\tIsVariadic() bool\n\n\t// Elem returns a type's element type.\n\t// It panics if the type's Kind is not Array, Chan, Map, Pointer, or Slice.\n\tElem() Type\n\n\t// Field returns a struct type's i'th field.\n\t// It panics if the type's Kind is not Struct.\n\t// It panics if i is not in the range [0, NumField()).\n\tField(i int) StructField\n\n\t// FieldByIndex returns the nested field corresponding\n\t// to the index sequence. It is equivalent to calling Field\n\t// successively for each index i.\n\t// It panics if the type's Kind is not Struct.\n\tFieldByIndex(index []int) StructField\n\n\t// FieldByName returns the struct field with the given name\n\t// and a boolean indicating if the field was found.\n\tFieldByName(name string) (StructField, bool)\n\n\t// FieldByNameFunc returns the struct field with a name\n\t// that satisfies the match function and a boolean indicating if\n\t// the field was found.\n\t//\n\t// FieldByNameFunc considers the fields in the struct itself\n\t// and then the fields in any embedded structs, in breadth first order,\n\t// stopping at the shallowest nesting depth containing one or more\n\t// fields satisfying the match function. If multiple fields at that depth\n\t// satisfy the match function, they cancel each other\n\t// and FieldByNameFunc returns no match.\n\t// This behavior mirrors Go's handling of name lookup in\n\t// structs containing embedded fields.\n\tFieldByNameFunc(match func(string) bool) (StructField, bool)\n\n\t// In returns the type of a function type's i'th input parameter.\n\t// It panics if the type's Kind is not Func.\n\t// It panics if i is not in the range [0, NumIn()).\n\tIn(i int) Type\n\n\t// Key returns a map type's key type.\n\t// It panics if the type's Kind is not Map.\n\tKey() Type\n\n\t// Len returns an array type's length.\n\t// It panics if the type's Kind is not Array.\n\tLen() int\n\n\t// NumField returns a struct type's field count.\n\t// It panics if the type's Kind is not Struct.\n\tNumField() int\n\n\t// NumIn returns a function type's input parameter count.\n\t// It panics if the type's Kind is not Func.\n\tNumIn() int\n\n\t// NumOut returns a function type's output parameter count.\n\t// It panics if the type's Kind is not Func.\n\tNumOut() int\n\n\t// Out returns the type of a function type's i'th output parameter.\n\t// It panics if the type's Kind is not Func.\n\t// It panics if i is not in the range [0, NumOut()).\n\tOut(i int) Type\n\n\t// OverflowComplex reports whether the complex128 x cannot be represented by type t.\n\t// It panics if t's Kind is not Complex64 or Complex128.\n\tOverflowComplex(x complex128) bool\n\n\t// OverflowFloat reports whether the float64 x cannot be represented by type t.\n\t// It panics if t's Kind is not Float32 or Float64.\n\tOverflowFloat(x float64) bool\n\n\t// OverflowInt reports whether the int64 x cannot be represented by type t.\n\t// It panics if t's Kind is not Int, Int8, Int16, Int32, or Int64.\n\tOverflowInt(x int64) bool\n\n\t// OverflowUint reports whether the uint64 x cannot be represented by type t.\n\t// It panics if t's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64.\n\tOverflowUint(x uint64) bool\n\n\t// CanSeq reports whether a [Value] with this type can be iterated over using [Value.Seq].\n\tCanSeq() bool\n\n\t// CanSeq2 reports whether a [Value] with this type can be iterated over using [Value.Seq2].\n\tCanSeq2() bool\n}\n\ntype rawType struct {\n\treflectlite.RawType\n}\n\nfunc toType(t reflectlite.Type) Type {\n\tif t == nil {\n\t\treturn nil\n\t}\n\treturn (*rawType)(unsafe.Pointer(t.(*reflectlite.RawType)))\n}\n\nfunc toRawType(t Type) *reflectlite.RawType {\n\treturn (*reflectlite.RawType)(unsafe.Pointer(t.(*rawType)))\n}\n\nfunc TypeOf(i interface{}) Type {\n\treturn toType(reflectlite.TypeOf(i))\n}\n\nfunc PtrTo(t Type) Type {\n\treturn PointerTo(t)\n}\n\nfunc PointerTo(t Type) Type {\n\treturn toType(reflectlite.PointerTo(toRawType(t)))\n}\n\nfunc (t *rawType) AssignableTo(u Type) bool {\n\treturn t.RawType.AssignableTo(&(u.(*rawType).RawType))\n}\n\nfunc (t *rawType) CanSeq() bool {\n\tswitch t.Kind() {\n\tcase Int8, Int16, Int32, Int64, Int, Uint8, Uint16, Uint32, Uint64, Uint, Uintptr, Array, Slice, Chan, String, Map:\n\t\treturn true\n\tcase Func:\n\t\t// TODO: implement canRangeFunc\n\t\t// return canRangeFunc(t)\n\t\tpanic(\"unimplemented: (reflect.Type).CanSeq() for functions\")\n\tcase Pointer:\n\t\treturn t.Elem().Kind() == Array\n\t}\n\treturn false\n}\n\nfunc (t *rawType) CanSeq2() bool {\n\tswitch t.Kind() {\n\tcase Array, Slice, String, Map:\n\t\treturn true\n\tcase Func:\n\t\t// TODO: implement canRangeFunc2\n\t\t// return canRangeFunc2(t)\n\t\tpanic(\"unimplemented: (reflect.Type).CanSeq2() for functions\")\n\tcase Pointer:\n\t\treturn t.Elem().Kind() == Array\n\t}\n\treturn false\n}\n\nfunc (t *rawType) ConvertibleTo(u Type) bool {\n\tpanic(\"unimplemented: (reflect.Type).ConvertibleTo()\")\n}\n\nfunc (t *rawType) Elem() Type {\n\treturn toType(t.RawType.Elem())\n}\n\nfunc (t *rawType) Field(i int) StructField {\n\tf := t.RawType.Field(i)\n\treturn toStructField(f)\n}\n\nfunc (t *rawType) FieldByIndex(index []int) StructField {\n\tf := t.RawType.FieldByIndex(index)\n\treturn toStructField(f)\n}\n\nfunc (t *rawType) FieldByName(name string) (StructField, bool) {\n\tf, ok := t.RawType.FieldByName(name)\n\treturn toStructField(f), ok\n}\n\nfunc (t *rawType) FieldByNameFunc(match func(string) bool) (StructField, bool) {\n\tf, ok := t.RawType.FieldByNameFunc(match)\n\treturn toStructField(f), ok\n}\n\nfunc (t *rawType) Implements(u Type) bool {\n\treturn t.RawType.Implements(&(u.(*rawType).RawType))\n}\n\nfunc (t *rawType) In(i int) Type {\n\tpanic(\"unimplemented: (reflect.Type).In()\")\n}\n\nfunc (t *rawType) IsVariadic() bool {\n\tpanic(\"unimplemented: (reflect.Type).IsVariadic()\")\n}\n\nfunc (t *rawType) Key() Type {\n\treturn toType(t.RawType.Key())\n}\n\nfunc (t *rawType) Method(i int) Method {\n\tpanic(\"unimplemented: (reflect.Type).Method()\")\n}\n\nfunc (t *rawType) MethodByName(name string) (Method, bool) {\n\tpanic(\"unimplemented: (reflect.Type).MethodByName()\")\n}\n\nfunc (t *rawType) NumIn() int {\n\tpanic(\"unimplemented: (reflect.Type).NumIn()\")\n}\n\nfunc (t *rawType) NumOut() int {\n\tpanic(\"unimplemented: (reflect.Type).NumOut()\")\n}\n\nfunc (t *rawType) Out(i int) Type {\n\tpanic(\"unimplemented: (reflect.Type).Out()\")\n}\n\n// A StructField describes a single field in a struct.\n// This must be kept in sync with [reflectlite.StructField].\ntype StructField struct {\n\t// Name indicates the field name.\n\tName string\n\n\t// PkgPath is the package path where the struct containing this field is\n\t// declared for unexported fields, or the empty string for exported fields.\n\tPkgPath string\n\n\tType      Type\n\tTag       StructTag // field tag string\n\tOffset    uintptr\n\tIndex     []int // index sequence for Type.FieldByIndex\n\tAnonymous bool\n}\n\nfunc toStructField(f reflectlite.StructField) StructField {\n\treturn StructField{\n\t\tName:      f.Name,\n\t\tPkgPath:   f.PkgPath,\n\t\tType:      toType(f.Type),\n\t\tTag:       f.Tag,\n\t\tOffset:    f.Offset,\n\t\tIndex:     f.Index,\n\t\tAnonymous: f.Anonymous,\n\t}\n}\n\n// IsExported reports whether the field is exported.\nfunc (f StructField) IsExported() bool {\n\treturn f.PkgPath == \"\"\n}\n\ntype StructTag = reflectlite.StructTag\n\nfunc TypeFor[T any]() Type {\n\treturn toType(reflectlite.TypeFor[T]())\n}\n\nfunc SliceOf(t Type) Type {\n\treturn toType(reflectlite.SliceOf(toRawType(t)))\n}\n\nfunc ArrayOf(n int, t Type) Type {\n\treturn toType(reflectlite.ArrayOf(n, toRawType(t)))\n}\n\nfunc StructOf([]StructField) Type {\n\treturn toType(reflectlite.StructOf([]reflectlite.StructField{}))\n}\n\nfunc MapOf(key, value Type) Type {\n\treturn toType(reflectlite.MapOf(toRawType(key), toRawType(value)))\n}\n\nfunc FuncOf(in, out []Type, variadic bool) Type {\n\trawIn := make([]reflectlite.Type, len(in))\n\tfor i, t := range in {\n\t\trawIn[i] = toRawType(t)\n\t}\n\n\trawOut := make([]reflectlite.Type, len(out))\n\tfor i, t := range out {\n\t\trawOut[i] = toRawType(t)\n\t}\n\n\treturn toType(reflectlite.FuncOf(rawIn, rawOut, variadic))\n}\n\nfunc ChanOf(dir ChanDir, t Type) Type {\n\tpanic(\"unimplemented: reflect.ChanOf\")\n}\n"
  },
  {
    "path": "src/reflect/type_test.go",
    "content": "// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage reflect_test\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n)\n\nfunc TestTypeFor(t *testing.T) {\n\ttype (\n\t\tmystring string\n\t\tmyiface  interface{}\n\t)\n\n\ttestcases := []struct {\n\t\twantFrom any\n\t\tgot      reflect.Type\n\t}{\n\t\t{new(int), reflect.TypeFor[int]()},\n\t\t{new(int64), reflect.TypeFor[int64]()},\n\t\t{new(string), reflect.TypeFor[string]()},\n\t\t{new(mystring), reflect.TypeFor[mystring]()},\n\t\t{new(any), reflect.TypeFor[any]()},\n\t\t{new(myiface), reflect.TypeFor[myiface]()},\n\t}\n\tfor _, tc := range testcases {\n\t\twant := reflect.ValueOf(tc.wantFrom).Elem().Type()\n\t\tif want != tc.got {\n\t\t\tt.Errorf(\"unexpected reflect.Type: got %v; want %v\", tc.got, want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/reflect/value.go",
    "content": "package reflect\n\nimport (\n\t\"internal/reflectlite\"\n\t\"unsafe\"\n)\n\ntype Value struct {\n\treflectlite.Value\n}\n\nfunc Indirect(v Value) Value {\n\treturn Value{reflectlite.Indirect(v.Value)}\n}\n\nfunc ValueOf(i interface{}) Value {\n\treturn Value{reflectlite.ValueOf(i)}\n}\n\nfunc (v Value) Type() Type {\n\treturn toType(v.Value.Type())\n}\n\nfunc (v Value) Addr() Value {\n\treturn Value{v.Value.Addr()}\n}\n\nfunc (v Value) Slice(i, j int) Value {\n\treturn Value{v.Value.Slice(i, j)}\n}\n\nfunc (v Value) Slice3(i, j, k int) Value {\n\treturn Value{v.Value.Slice3(i, j, k)}\n}\n\nfunc (v Value) Elem() Value {\n\treturn Value{v.Value.Elem()}\n}\n\n// Field returns the value of the i'th field of this struct.\nfunc (v Value) Field(i int) Value {\n\treturn Value{v.Value.Field(i)}\n}\n\nfunc (v Value) Index(i int) Value {\n\treturn Value{v.Value.Index(i)}\n}\n\nfunc (v Value) MapKeys() []Value {\n\tkeys := v.Value.MapKeys()\n\treturn *(*[]Value)(unsafe.Pointer(&keys))\n}\n\nfunc (v Value) MapIndex(key Value) Value {\n\treturn Value{v.Value.MapIndex(key.Value)}\n}\n\nfunc (v Value) MapRange() *MapIter {\n\treturn (*MapIter)(v.Value.MapRange())\n}\n\ntype MapIter reflectlite.MapIter\n\nfunc (it *MapIter) Key() Value {\n\treturn Value{((*reflectlite.MapIter)(it)).Key()}\n}\n\nfunc (v Value) SetIterKey(iter *MapIter) {\n\tv.Value.SetIterKey((*reflectlite.MapIter)(iter))\n}\n\nfunc (it *MapIter) Value() Value {\n\treturn Value{((*reflectlite.MapIter)(it)).Value()}\n}\n\nfunc (v Value) SetIterValue(iter *MapIter) {\n\tv.Value.SetIterValue((*reflectlite.MapIter)(iter))\n}\n\nfunc (it *MapIter) Next() bool {\n\treturn ((*reflectlite.MapIter)(it)).Next()\n}\n\nfunc (it *MapIter) Reset(v Value) {\n\t(*reflectlite.MapIter)(it).Reset(v.Value)\n}\n\nfunc (v Value) Set(x Value) {\n\tv.Value.Set(x.Value)\n}\n\nfunc (v Value) CanConvert(t Type) bool {\n\treturn v.Value.CanConvert(toRawType(t))\n}\n\nfunc (v Value) Convert(t Type) Value {\n\treturn Value{v.Value.Convert(toRawType(t))}\n}\n\nfunc MakeSlice(typ Type, len, cap int) Value {\n\treturn Value{reflectlite.MakeSlice(toRawType(typ), len, cap)}\n}\n\nfunc Zero(typ Type) Value {\n\treturn Value{reflectlite.Zero(toRawType(typ))}\n}\n\n// New is the reflect equivalent of the new(T) keyword, returning a pointer to a\n// new value of the given type.\nfunc New(typ Type) Value {\n\treturn Value{reflectlite.New(toRawType(typ))}\n}\n\ntype ValueError = reflectlite.ValueError\n\n// Copy copies the contents of src into dst until either\n// dst has been filled or src has been exhausted.\nfunc Copy(dst, src Value) int {\n\treturn reflectlite.Copy(dst.Value, src.Value)\n}\n\n// Append appends the values x to a slice s and returns the resulting slice.\n// As in Go, each x's value must be assignable to the slice's element type.\nfunc Append(v Value, x ...Value) Value {\n\ty := *(*[]reflectlite.Value)(unsafe.Pointer(&x))\n\treturn Value{reflectlite.Append(v.Value, y...)}\n}\n\n// AppendSlice appends a slice t to a slice s and returns the resulting slice.\n// The slices s and t must have the same element type.\nfunc AppendSlice(s, t Value) Value {\n\treturn Value{reflectlite.AppendSlice(s.Value, t.Value)}\n}\n\nfunc (v Value) SetMapIndex(key, elem Value) {\n\tv.Value.SetMapIndex(key.Value, elem.Value)\n}\n\n// FieldByIndex returns the nested field corresponding to index.\nfunc (v Value) FieldByIndex(index []int) Value {\n\treturn Value{v.Value.FieldByIndex(index)}\n}\n\n// FieldByIndexErr returns the nested field corresponding to index.\nfunc (v Value) FieldByIndexErr(index []int) (Value, error) {\n\tout, err := v.Value.FieldByIndexErr(index)\n\treturn Value{out}, err\n}\n\nfunc (v Value) FieldByName(name string) Value {\n\treturn Value{v.Value.FieldByName(name)}\n}\n\nfunc (v Value) FieldByNameFunc(match func(string) bool) Value {\n\treturn Value{v.Value.FieldByNameFunc(match)}\n}\n\ntype SelectDir int\n\nconst (\n\t_             SelectDir = iota\n\tSelectSend              // case Chan <- Send\n\tSelectRecv              // case <-Chan:\n\tSelectDefault           // default\n)\n\ntype SelectCase struct {\n\tDir  SelectDir // direction of case\n\tChan Value     // channel to use (for send or receive)\n\tSend Value     // value to send (for send)\n}\n\nfunc Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) {\n\tpanic(\"unimplemented: reflect.Select\")\n}\n\nfunc (v Value) Send(x Value) {\n\tpanic(\"unimplemented: reflect.Value.Send()\")\n}\n\nfunc (v Value) TrySend(x Value) bool {\n\tpanic(\"unimplemented: reflect.Value.TrySend()\")\n}\n\nfunc (v Value) Close() {\n\tpanic(\"unimplemented: reflect.Value.Close()\")\n}\n\n// MakeMap creates a new map with the specified type.\nfunc MakeMap(typ Type) Value {\n\treturn Value{reflectlite.MakeMap(toRawType(typ))}\n}\n\n// MakeMapWithSize creates a new map with the specified type and initial space\n// for approximately n elements.\nfunc MakeMapWithSize(typ Type, n int) Value {\n\treturn Value{reflectlite.MakeMapWithSize(toRawType(typ), n)}\n}\n\nfunc (v Value) Call(in []Value) []Value {\n\tpanic(\"unimplemented: (reflect.Value).Call()\")\n}\n\nfunc (v Value) CallSlice(in []Value) []Value {\n\tpanic(\"unimplemented: (reflect.Value).CallSlice()\")\n}\n\nfunc (v Value) Equal(u Value) bool {\n\treturn v.Value.Equal(u.Value)\n}\n\nfunc (v Value) Method(i int) Value {\n\tpanic(\"unimplemented: (reflect.Value).Method()\")\n}\n\nfunc (v Value) MethodByName(name string) Value {\n\tpanic(\"unimplemented: (reflect.Value).MethodByName()\")\n}\n\nfunc (v Value) Recv() (x Value, ok bool) {\n\tpanic(\"unimplemented: (reflect.Value).Recv()\")\n}\n\nfunc (v Value) TryRecv() (x Value, ok bool) {\n\tpanic(\"unimplemented: (reflect.Value).TryRecv()\")\n}\n\nfunc NewAt(typ Type, p unsafe.Pointer) Value {\n\tpanic(\"unimplemented: reflect.New()\")\n}\n\n// Deprecated: Use unsafe.Slice or unsafe.SliceData instead.\ntype SliceHeader struct {\n\tData uintptr\n\tLen  intw\n\tCap  intw\n}\n\n// Deprecated: Use unsafe.String or unsafe.StringData instead.\ntype StringHeader struct {\n\tData uintptr\n\tLen  intw\n}\n\n// Verify SliceHeader and StringHeader sizes.\n// See https://github.com/tinygo-org/tinygo/pull/4156\n// and https://github.com/tinygo-org/tinygo/issues/1284.\nvar (\n\t_ [unsafe.Sizeof([]byte{})]byte = [unsafe.Sizeof(SliceHeader{})]byte{}\n\t_ [unsafe.Sizeof(\"\")]byte       = [unsafe.Sizeof(StringHeader{})]byte{}\n)\n"
  },
  {
    "path": "src/reflect/value_test.go",
    "content": "package reflect_test\n\nimport (\n\t\"bytes\"\n\t\"encoding/base64\"\n\t. \"reflect\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestTinyIndirectPointers(t *testing.T) {\n\tvar m = map[string]int{}\n\tm[\"x\"] = 1\n\n\tvar a = &m\n\n\tif ValueOf(a).Elem().Len() != 1 {\n\t\tt.Errorf(\"bad map length via reflect\")\n\t}\n\n\tvar b struct {\n\t\tDecoded *[3]byte\n\t}\n\n\tv1 := New(TypeOf(b.Decoded).Elem())\n\n\tvar bb [3]byte\n\tbb[0] = 0xaa\n\n\tv1.Elem().Set(ValueOf(bb))\n\n\tif v1.Elem().Index(0).Uint() != 0xaa {\n\t\tt.Errorf(\"bad indirect array index via reflect\")\n\t}\n}\n\nfunc TestTinyMap(t *testing.T) {\n\n\tm := make(map[string]int)\n\n\tmtyp := TypeOf(m)\n\n\tif got, want := mtyp.Key().Kind().String(), \"string\"; got != want {\n\t\tt.Errorf(\"m.Type().Key().String()=%q, want %q\", got, want)\n\t}\n\n\tif got, want := mtyp.Elem().Kind().String(), \"int\"; got != want {\n\t\tt.Errorf(\"m.Elem().String()=%q, want %q\", got, want)\n\t}\n\n\tm[\"foo\"] = 2\n\n\tmref := ValueOf(m)\n\ttwo := mref.MapIndex(ValueOf(\"foo\"))\n\n\tif got, want := two.Interface().(int), 2; got != want {\n\t\tt.Errorf(\"MapIndex(`foo`)=%v, want %v\", got, want)\n\t}\n\n\tm[\"bar\"] = 3\n\tm[\"baz\"] = 4\n\tm[\"qux\"] = 5\n\n\tit := mref.MapRange()\n\n\tvar gotKeys []string\n\tfor it.Next() {\n\t\tk := it.Key()\n\t\tv := it.Value()\n\n\t\tkstr := k.Interface().(string)\n\t\tvint := v.Interface().(int)\n\n\t\tgotKeys = append(gotKeys, kstr)\n\n\t\tif m[kstr] != vint {\n\t\t\tt.Errorf(\"m[%v]=%v, want %v\", kstr, vint, m[kstr])\n\t\t}\n\t}\n\tvar wantKeys []string\n\tfor k := range m {\n\t\twantKeys = append(wantKeys, k)\n\t}\n\tsort.Strings(gotKeys)\n\tsort.Strings(wantKeys)\n\n\tif !equal(gotKeys, wantKeys) {\n\t\tt.Errorf(\"MapRange return unexpected keys: got %v, want %v\", gotKeys, wantKeys)\n\t}\n\n\trefMapKeys := mref.MapKeys()\n\tgotKeys = gotKeys[:0]\n\tfor _, v := range refMapKeys {\n\t\tgotKeys = append(gotKeys, v.Interface().(string))\n\t}\n\n\tsort.Strings(gotKeys)\n\tif !equal(gotKeys, wantKeys) {\n\t\tt.Errorf(\"MapKeys return unexpected keys: got %v, want %v\", gotKeys, wantKeys)\n\t}\n\n\tmref.SetMapIndex(ValueOf(\"bar\"), Value{})\n\tif _, ok := m[\"bar\"]; ok {\n\t\tt.Errorf(\"SetMapIndex failed to delete `bar`\")\n\t}\n\n\tmref.SetMapIndex(ValueOf(\"baz\"), ValueOf(6))\n\tif got, want := m[\"baz\"], 6; got != want {\n\t\tt.Errorf(\"SetMapIndex(bar, 6) got %v, want %v\", got, want)\n\t}\n\n\tm2ref := MakeMap(mref.Type())\n\tm2ref.SetMapIndex(ValueOf(\"foo\"), ValueOf(2))\n\n\tm2 := m2ref.Interface().(map[string]int)\n\n\tif m2[\"foo\"] != 2 {\n\t\tt.Errorf(\"MakeMap failed to create map\")\n\t}\n\n\ttype stringint struct {\n\t\ts string\n\t\ti int\n\t}\n\n\tsimap := make(map[stringint]int)\n\n\trefsimap := MakeMap(TypeOf(simap))\n\n\trefsimap.SetMapIndex(ValueOf(stringint{\"hello\", 4}), ValueOf(6))\n\n\tsix := refsimap.MapIndex(ValueOf(stringint{\"hello\", 4}))\n\n\tif six.Interface().(int) != 6 {\n\t\tt.Errorf(\"m[hello, 4]=%v, want 6\", six)\n\t}\n\n\tkeys := refsimap.MapKeys()\n\tif len(keys) != 1 {\n\t\tt.Errorf(\"refsimap: MapKeys()=%v, want 1\", len(keys))\n\t}\n\tif keys[0].Type() != TypeOf(stringint{}) {\n\t\tt.Errorf(\"keys[0] has wrong type: %v\", keys[0].Type().String())\n\t}\n\n\tsikey := keys[0].Interface().(stringint)\n\n\tif sikey != (stringint{\"hello\", 4}) {\n\t\tt.Errorf(\"sikey has unexpected value: %#v\", sikey)\n\t}\n\n\t// make sure we can look up interface keys with reflection\n\ttype unmarshalerText struct {\n\t\tA, B string\n\t}\n\n\tut := make(map[unmarshalerText]bool)\n\n\trefut := ValueOf(ut)\n\n\t// put in a key with the compiler\n\tut[unmarshalerText{\"x\", \"y\"}] = true\n\n\t// make sure we can get it out\n\tv2 := refut.MapIndex(ValueOf(unmarshalerText{\"x\", \"y\"}))\n\tif !v2.IsValid() || !v2.Bool() {\n\t\tt.Errorf(\"Failed to look up map struct key with reflection\")\n\t}\n\n\t// put in a key with reflection\n\trefut.SetMapIndex(ValueOf(unmarshalerText{\"y\", \"z\"}), ValueOf(true))\n\n\t// make sure we can get it out with the compiler\n\tif !ut[unmarshalerText{\"y\", \"z\"}] {\n\t\tt.Errorf(\"Failed to look up up reflect-set map key with compiler\")\n\t}\n\n\tutKeys := refut.MapKeys()\n\n\t// make sure keys extracted via reflection have the correct type\n\tif _, ok := utKeys[0].Interface().(unmarshalerText); !ok {\n\t\tt.Errorf(\"Map keys via MapKeys() have wrong type: %v\", utKeys[0].Type().String())\n\t}\n\n\t// and via iteration\n\n\tutIter := refut.MapRange()\n\tutIter.Next()\n\tutIterKey := utIter.Key()\n\n\tif _, ok := utIterKey.Interface().(unmarshalerText); !ok {\n\t\tt.Errorf(\"Map keys via MapIter() have wrong type: %v\", utIterKey.Type().String())\n\t}\n\n\t{\n\t\tm := map[any]any{1: 2}\n\t\trv := ValueOf(m)\n\t\titer := rv.MapRange()\n\n\t\titer.Next()\n\t\tk := iter.Key()\n\t\tif k.Kind().String() != \"interface\" {\n\t\t\tt.Errorf(\"map[any]any MapRange has wrong key type: %v\", k.Kind().String())\n\t\t}\n\n\t\tkeys := rv.MapKeys()\n\t\tif k := keys[0]; k.Kind().String() != \"interface\" {\n\t\t\tt.Errorf(\"map[any]any MapRange has wrong key type: %v\", k.Kind().String())\n\t\t}\n\n\t}\n}\n\n// For an interface type, it returns the number of exported and unexported methods.\n\ntype counter interface {\n\tcount() int\n}\n\ntype count struct {\n\ti int\n}\n\nfunc (c *count) count() int {\n\treturn c.i\n}\n\nfunc TestMapInterfaceKeys(t *testing.T) {\n\tm := make(map[interface{}]int)\n\tfor i := 0; i < 20; i++ {\n\t\tc := &count{i}\n\t\tm[c] = i\n\t}\n\n\tfor k, v := range m {\n\t\tif got := m[k]; got != v {\n\t\t\tt.Error(\"lookup failure got\", got, \"want\", v)\n\t\t}\n\t}\n\n\trefm := ValueOf(m)\n\n\tkeys := refm.MapKeys()\n\tif len(keys) != 20 {\n\t\tt.Error(\"failed to look up 20 keys\")\n\t}\n\tfor _, k := range keys {\n\t\tc := k.Interface().(*count)\n\t\te := refm.MapIndex(k)\n\t\tif e.Interface().(int) != c.i {\n\t\t\tt.Error(\"reflect lookup failure:\", c.i)\n\t\t}\n\t}\n\n\tit := refm.MapRange()\n\tvar totalKeys int\n\tfor it.Next() {\n\t\ttotalKeys++\n\t\tk := it.Key()\n\t\tv := it.Value().Interface().(int)\n\n\t\tc := k.Interface().(*count)\n\t\tif v != c.i || refm.MapIndex(k).Interface().(int) != c.i {\n\t\t\tt.Error(\"reflect iter lookup failure:\", c.i)\n\t\t}\n\t}\n\n\tif totalKeys != 20 {\n\t\tt.Errorf(\"failed to get 20 keys\")\n\t}\n}\n\nfunc TestMapInterfaceElem(t *testing.T) {\n\tm := make(map[string]interface{})\n\trefm := ValueOf(m)\n\n\tfour := ValueOf(4)\n\thello := ValueOf(\"hello\")\n\n\trefm.SetMapIndex(hello, four)\n\n\tif v := refm.MapIndex(hello).Interface().(int); v != 4 {\n\t\tt.Errorf(\"failed to get value assigned to interface via MapIndex\")\n\t}\n\n\tif v := m[\"hello\"].(int); v != 4 {\n\t\tt.Errorf(\"failed to get value assigned to interface via direct lookup\")\n\t}\n}\n\nfunc TestTinySlice(t *testing.T) {\n\ts := []int{0, 10, 20}\n\trefs := ValueOf(s)\n\n\tfor i := 3; i < 10; i++ {\n\t\trefs = Append(refs, ValueOf(i*10))\n\t}\n\n\ts = refs.Interface().([]int)\n\n\tfor i := 0; i < 10; i++ {\n\t\tif s[i] != i*10 {\n\t\t\tt.Errorf(\"s[%d]=%d, want %d\", i, s[i], i*10)\n\t\t}\n\t}\n\n\ts28 := s[2:8]\n\ts28ref := refs.Slice(2, 8)\n\n\tif len(s28) != s28ref.Len() || cap(s28) != s28ref.Cap() {\n\t\tt.Errorf(\"Slice: len(s28)=%d s28ref.Len()=%d cap(s28)=%d s28ref.Cap()=%d\\n\", len(s28), s28ref.Len(), cap(s28), s28ref.Cap())\n\t}\n\n\tfor i, got := range s28 {\n\t\twant := int(s28ref.Index(i).Int())\n\t\tif got != want {\n\t\t\tt.Errorf(\"s28[%d]=%d, want %d\", i, got, want)\n\t\t}\n\t}\n\n\ts268 := s[2:6:8]\n\ts268ref := refs.Slice3(2, 6, 8)\n\n\tif len(s268) != s268ref.Len() || cap(s268) != s268ref.Cap() {\n\t\tt.Errorf(\"Slice3: len(s268)=%d s268ref.Len()=%d cap(s268)=%d s268ref.Cap()=%d\\n\", len(s268), s268ref.Len(), cap(s268), s268ref.Cap())\n\t}\n\n\tfor i, got := range s268 {\n\t\twant := int(s268ref.Index(i).Int())\n\t\tif got != want {\n\t\t\tt.Errorf(\"s268[%d]=%d, want %d\", i, got, want)\n\t\t}\n\t}\n\n\t// should be equivalent to s28 now, except for the capacity which doesn't change\n\n\ts268ref = ValueOf(&s268).Elem()\n\ts268ref.SetLen(6)\n\tif len(s28) != s268ref.Len() || cap(s268) != s268ref.Cap() {\n\t\tt.Errorf(\"SetLen: len(s268)=%d s268ref.Len()=%d cap(s268)=%d s268ref.Cap()=%d\\n\", len(s28), s268ref.Len(), cap(s268), s268ref.Cap())\n\t}\n\n\tfor i, got := range s28 {\n\t\twant := int(s268ref.Index(i).Int())\n\t\tif got != want {\n\t\t\tt.Errorf(\"s28[%d]=%d, want %d\", i, got, want)\n\t\t}\n\t}\n\n\trefs = MakeSlice(TypeOf(s), 5, 10)\n\ts = refs.Interface().([]int)\n\n\tif len(s) != refs.Len() || cap(s) != refs.Cap() {\n\t\tt.Errorf(\"len(s)=%v refs.Len()=%v cap(s)=%v refs.Cap()=%v\", len(s), refs.Len(), cap(s), refs.Cap())\n\t}\n}\n\nfunc TestTinyBytes(t *testing.T) {\n\ts := []byte(\"abcde\")\n\trefs := ValueOf(s)\n\n\ts2 := refs.Bytes()\n\n\tif !equal(s, s2) {\n\t\tt.Errorf(\"Failed to get Bytes(): %v != %v\", s, s2)\n\t}\n\n\tCopy(refs, ValueOf(\"12345\"))\n\n\tif string(s) != \"12345\" {\n\t\tt.Errorf(\"Copy()=%q, want `12345`\", string(s))\n\t}\n\n\t// test small arrays that fit in a pointer\n\ta := [3]byte{10, 20, 30}\n\tv := ValueOf(&a)\n\tvslice := v.Elem().Bytes()\n\tif len(vslice) != 3 || cap(vslice) != 3 {\n\t\tt.Errorf(\"len(vslice)=%v, cap(vslice)=%v\", len(vslice), cap(vslice))\n\t}\n\n\tfor i, got := range vslice {\n\t\tif want := (byte(i) + 1) * 10; got != want {\n\t\t\tt.Errorf(\"vslice[%d]=%d, want %d\", i, got, want)\n\t\t}\n\t}\n}\n\nfunc TestTinyNamedTypes(t *testing.T) {\n\ttype namedString string\n\n\tnamed := namedString(\"foo\")\n\tif got, want := TypeOf(named).Name(), \"namedString\"; got != want {\n\t\tt.Errorf(\"TypeOf.Name()=%v, want %v\", got, want)\n\t}\n\n\tif got, want := TypeOf(named).String(), \"reflect_test.namedString\"; got != want {\n\t\tt.Errorf(\"TypeOf.String()=%v, want %v\", got, want)\n\t}\n\n\terrorType := TypeOf((*error)(nil)).Elem()\n\tif s := errorType.String(); s != \"error\" {\n\t\tt.Errorf(\"error type = %v, want error\", s)\n\t}\n\n\tm := make(map[[4]uint16]string)\n\n\tif got, want := TypeOf(m).String(), \"map[[4]uint16]string\"; got != want {\n\t\tt.Errorf(\"Type.String()=%v, want %v\", got, want)\n\t}\n\n\ts := struct {\n\t\ta int8\n\t\tb int8\n\t\tc int8\n\t\td int8\n\t\te int8\n\t\tf int32\n\t}{}\n\n\tif got, want := TypeOf(s).String(), \"struct { a int8; b int8; c int8; d int8; e int8; f int32 }\"; got != want {\n\t\tt.Errorf(\"Type.String()=%v, want %v\", got, want)\n\t}\n\n\tif got, want := ValueOf(m).String(), \"<map[[4]uint16]string Value>\"; got != want {\n\t\tt.Errorf(\"Value.String()=%v, want %v\", got, want)\n\t}\n\n\tif got, want := TypeOf(base64.Encoding{}).String(), \"base64.Encoding\"; got != want {\n\t\tt.Errorf(\"Type.String(base64.Encoding{})=%v, want %v\", got, want)\n\t}\n\n\ttype Repository struct {\n\t\tRoleName *string `json:\"role_name,omitempty\"`\n\t}\n\n\tvar repo *Repository\n\tv := ValueOf(&repo).Elem()\n\tn := New(v.Type().Elem())\n\tv.Set(n)\n}\n\nfunc TestTinyStruct(t *testing.T) {\n\ttype barStruct struct {\n\t\tQuxString string\n\t\tBazInt    int\n\t}\n\n\ttype foobar struct {\n\t\tFoo string `foo:\"struct tag\"`\n\t\tBar barStruct\n\t}\n\n\tvar fb foobar\n\tfb.Bar.QuxString = \"qux\"\n\n\treffb := TypeOf(fb)\n\n\tq := reffb.FieldByIndex([]int{1, 0})\n\tif want := \"QuxString\"; q.Name != want {\n\t\tt.Errorf(\"FieldByIndex=%v, want %v\", q.Name, want)\n\t}\n\n\tvar ok bool\n\tq, ok = reffb.FieldByName(\"Foo\")\n\tif q.Name != \"Foo\" || !ok {\n\t\tt.Errorf(\"FieldByName(Foo)=%v,%v, want Foo, true\", q.Name, ok)\n\t}\n\n\tif got, want := q.Tag, `foo:\"struct tag\"`; string(got) != want {\n\t\tt.Errorf(\"StrucTag for Foo=%v, want %v\", got, want)\n\t}\n\n\tq, ok = reffb.FieldByNameFunc(func(s string) bool { return strings.ToLower(s) == \"bar\" })\n\tif q.Name != \"Bar\" || !ok {\n\t\tt.Errorf(\"FieldByNameFunc(bar)=%v,%v, want Bar, true\", q.Name, ok)\n\t}\n\n\tq, ok = reffb.FieldByName(\"Snorble\")\n\tif q.Name != \"\" || ok {\n\t\tt.Errorf(\"FieldByName(Snorble)=%v,%v, want ``, false\", q.Name, ok)\n\t}\n\n\tq, ok = reffb.FieldByNameFunc(func(s string) bool { return strings.ToLower(s) == \"snorble\" })\n\tif q.Name != \"\" || ok {\n\t\tt.Errorf(\"FieldByName(snorble)=%v,%v, want ``, false\", q.Name, ok)\n\t}\n}\n\nfunc TestTinyZero(t *testing.T) {\n\ts := \"hello, world\"\n\tsptr := &s\n\tv := ValueOf(&sptr).Elem()\n\tv.Set(Zero(v.Type()))\n\n\tsptr = v.Interface().(*string)\n\n\tif sptr != nil {\n\t\tt.Errorf(\"failed to set a nil string pointer\")\n\t}\n\n\tsl := []int{1, 2, 3}\n\tv = ValueOf(&sl).Elem()\n\tv.Set(Zero(v.Type()))\n\tsl = v.Interface().([]int)\n\n\tif sl != nil {\n\t\tt.Errorf(\"failed to set a nil slice\")\n\t}\n}\n\nfunc addrDecode(body interface{}) {\n\tvbody := ValueOf(body)\n\tptr := vbody.Elem()\n\tpptr := ptr.Addr()\n\taddrSetInt(pptr.Interface())\n}\n\nfunc addrSetInt(intf interface{}) {\n\tptr := intf.(*uint64)\n\t*ptr = 112358\n}\n\nfunc TestTinyAddr(t *testing.T) {\n\tvar n uint64\n\taddrDecode(&n)\n\tif n != 112358 {\n\t\tt.Errorf(\"Failed to set t=112358, got %v\", n)\n\t}\n\n\tv := ValueOf(&n)\n\tif got, want := v.Elem().Addr().CanAddr(), false; got != want {\n\t\tt.Errorf(\"Elem.Addr.CanAddr=%v, want %v\", got, want)\n\t}\n}\n\nfunc TestTinyNilType(t *testing.T) {\n\tvar a any\n\ttyp := TypeOf(a)\n\tif typ != nil {\n\t\tt.Errorf(\"Type of any{nil} is not nil\")\n\t}\n}\n\nfunc TestTinySetBytes(t *testing.T) {\n\tvar b []byte\n\trefb := ValueOf(&b).Elem()\n\ts := []byte(\"hello\")\n\trefb.SetBytes(s)\n\ts[0] = 'b'\n\n\trefbSlice := refb.Interface().([]byte)\n\n\tif len(refbSlice) != len(s) || b[0] != s[0] || refbSlice[0] != s[0] {\n\t\tt.Errorf(\"SetBytes(): reflection slice mismatch\")\n\t}\n}\n\ntype methodStruct struct {\n\ti int\n}\n\nfunc (m methodStruct) ValueMethod1() int {\n\treturn m.i\n}\n\nfunc (m methodStruct) valueMethod2() int {\n\treturn m.i\n}\n\nfunc (m *methodStruct) PointerMethod1() int {\n\treturn m.i\n}\n\nfunc (m *methodStruct) PointerMethod2() int {\n\treturn m.i\n}\n\nfunc (m *methodStruct) pointerMethod3() int {\n\treturn m.i\n}\n\nfunc TestTinyNumMethods(t *testing.T) {\n\trefptrt := TypeOf(&methodStruct{})\n\tif got, want := refptrt.NumMethod(), 1+2; got != want {\n\t\tt.Errorf(\"Pointer Methods=%v, want %v\", got, want)\n\t}\n\n\treft := refptrt.Elem()\n\tif got, want := reft.NumMethod(), 1; got != want {\n\t\tt.Errorf(\"Value Methods=%v, want %v\", got, want)\n\t}\n}\n\nfunc TestAssignableTo(t *testing.T) {\n\tvar a any\n\trefa := ValueOf(&a).Elem()\n\trefa.Set(ValueOf(4))\n\tif got, want := refa.Interface().(int), 4; got != want {\n\t\tt.Errorf(\"AssignableTo / Set failed, got %v, want %v\", got, want)\n\t}\n\n\tb := []byte{0x01, 0x02}\n\trefb := ValueOf(&b).Elem()\n\trefb.Set(ValueOf([]byte{0x02, 0x03}))\n\tif got, want := refb.Interface().([]byte), []byte{0x02, 0x03}; !bytes.Equal(got, want) {\n\t\tt.Errorf(\"AssignableTo / Set failed, got %v, want %v\", got, want)\n\t}\n\n\ttype bstr []byte\n\n\tc := bstr{0x01, 0x02}\n\trefc := ValueOf(&c).Elem()\n\trefc.Set(ValueOf([]byte{0x02, 0x03}))\n\tif got, want := refb.Interface().([]byte), []byte{0x02, 0x03}; !bytes.Equal(got, want) {\n\t\tt.Errorf(\"AssignableTo / Set failed, got %v, want %v\", got, want)\n\t}\n\n\td := []byte{0x01, 0x02}\n\trefd := ValueOf(&d).Elem()\n\trefd.Set(ValueOf(bstr{0x02, 0x03}))\n\tif got, want := refb.Interface().([]byte), []byte{0x02, 0x03}; !bytes.Equal(got, want) {\n\t\tt.Errorf(\"AssignableTo / Set failed, got %v, want %v\", got, want)\n\t}\n}\n\nfunc TestConvert(t *testing.T) {\n\tv := ValueOf(int64(3))\n\tc := v.Convert(TypeOf(byte(0)))\n\n\tif c.Type().Kind() != Uint8 || c.Uint() != 3 {\n\t\tt.Errorf(\"Convert(uint64 -> byte failed: kind=%v, value=%d\", c.Type().Kind().String(), c.Uint())\n\t}\n\n\tv = ValueOf(\"hello\")\n\tc = v.Convert(TypeOf([]byte(\"\")))\n\n\tif c.Type().Kind() != Slice || c.Type().Elem().Kind() != Uint8 && c.Len() != 5 && string(c.Bytes()) != \"hello\" {\n\t\tt.Errorf(\"Convert(string -> []byte\")\n\t}\n\n\ttype namedString string\n\n\tc = v.Convert(TypeOf(namedString(\"\")))\n\tif c.Type().Kind() != String || c.Type().Name() != \"namedString\" {\n\t\tt.Errorf(\"Convert(string -> namedString\")\n\t}\n}\n\nfunc TestConvertSliceToArrayOrArrayPointer(t *testing.T) {\n\ts := make([]byte, 2, 4)\n\t// a0 := [0]byte(s)\n\t// a1 := [1]byte(s[1:])     // a1[0] == s[1]\n\t// a2 := [2]byte(s)         // a2[0] == s[0]\n\t// a4 := [4]byte(s)         // panics: len([4]byte) > len(s)\n\n\tv := ValueOf(s).Convert(TypeFor[[0]byte]())\n\tif v.Kind() != Array || v.Type().Len() != 0 {\n\t\tt.Error(\"Convert([]byte -> [0]byte)\")\n\t}\n\tv = ValueOf(s[1:]).Convert(TypeFor[[1]byte]())\n\tif v.Kind() != Array || v.Type().Len() != 1 {\n\t\tt.Error(\"Convert([]byte -> [1]byte)\")\n\t}\n\tv = ValueOf(s).Convert(TypeFor[[2]byte]())\n\tif v.Kind() != Array || v.Type().Len() != 2 {\n\t\tt.Error(\"Convert([]byte -> [2]byte)\")\n\t}\n\tif ValueOf(s).CanConvert(TypeFor[[4]byte]()) {\n\t\tt.Error(\"Converting a slice with len smaller than array to array should fail\")\n\t}\n\n\t// s0 := (*[0]byte)(s)      // s0 != nil\n\t// s1 := (*[1]byte)(s[1:])  // &s1[0] == &s[1]\n\t// s2 := (*[2]byte)(s)      // &s2[0] == &s[0]\n\t// s4 := (*[4]byte)(s)      // panics: len([4]byte) > len(s)\n\tv = ValueOf(s).Convert(TypeFor[*[0]byte]())\n\tif v.Kind() != Pointer || v.Elem().Kind() != Array || v.Elem().Type().Len() != 0 {\n\t\tt.Error(\"Convert([]byte -> *[0]byte)\")\n\t}\n\tv = ValueOf(s[1:]).Convert(TypeFor[*[1]byte]())\n\tif v.Kind() != Pointer || v.Elem().Kind() != Array || v.Elem().Type().Len() != 1 {\n\t\tt.Error(\"Convert([]byte -> *[1]byte)\")\n\t}\n\tv = ValueOf(s).Convert(TypeFor[*[2]byte]())\n\tif v.Kind() != Pointer || v.Elem().Kind() != Array || v.Elem().Type().Len() != 2 {\n\t\tt.Error(\"Convert([]byte -> *[2]byte)\")\n\t}\n\tif ValueOf(s).CanConvert(TypeFor[*[4]byte]()) {\n\t\tt.Error(\"Converting a slice with len smaller than array to array pointer should fail\")\n\t}\n\n\t// Test converting slices with backing arrays <= and >64bits\n\tslice64 := []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}\n\tarray64 := ValueOf(slice64).Convert(TypeFor[[8]byte]()).Interface().([8]byte)\n\tif !bytes.Equal(slice64, array64[:]) {\n\t\tt.Errorf(\"converted array %x does not match backing array of slice %x\", array64, slice64)\n\t}\n\n\tslice72 := []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09}\n\tarray72 := ValueOf(slice72).Convert(TypeFor[[9]byte]()).Interface().([9]byte)\n\tif !bytes.Equal(slice72, array72[:]) {\n\t\tt.Errorf(\"converted array %x does not match backing array of slice %x\", array72, slice72)\n\t}\n}\n\nfunc TestConvertToEmptyInterface(t *testing.T) {\n\tanyType := TypeFor[interface{}]()\n\n\tv := ValueOf(false).Convert(anyType)\n\tif v.Kind() != Interface || v.NumMethod() > 0 {\n\t\tt.Error(\"Convert(bool -> interface{})\")\n\t}\n\t_ = v.Interface().(interface{}).(bool)\n\n\tv = ValueOf(int64(3)).Convert(anyType)\n\tif v.Kind() != Interface || v.NumMethod() > 0 {\n\t\tt.Error(\"Convert(int64 -> interface{})\")\n\t}\n\t_ = v.Interface().(interface{}).(int64)\n\n\tv = ValueOf(struct{}{}).Convert(anyType)\n\tif v.Kind() != Interface || v.NumMethod() > 0 {\n\t\tt.Error(\"Convert(struct -> interface{})\")\n\t}\n\t_ = v.Interface().(interface{}).(struct{})\n\n\tv = ValueOf([]struct{}{}).Convert(anyType)\n\tif v.Kind() != Interface || v.NumMethod() > 0 {\n\t\tt.Error(\"Convert(slice -> interface{})\")\n\t}\n\t_ = v.Interface().(interface{}).([]struct{})\n\n\tv = ValueOf(map[string]string{\"A\": \"B\"}).Convert(anyType)\n\tif v.Kind() != Interface || v.NumMethod() > 0 {\n\t\tt.Error(\"Convert(map -> interface{})\")\n\t}\n\t_ = v.Interface().(interface{}).(map[string]string)\n}\n\nfunc TestClearSlice(t *testing.T) {\n\ttype stringSlice []string\n\tfor _, test := range []struct {\n\t\tslice  any\n\t\texpect any\n\t}{\n\t\t{\n\t\t\tslice:  []bool{true, false, true},\n\t\t\texpect: []bool{false, false, false},\n\t\t},\n\t\t{\n\t\t\tslice:  []byte{0x00, 0x01, 0x02, 0x03},\n\t\t\texpect: []byte{0x00, 0x00, 0x00, 0x00},\n\t\t},\n\t\t{\n\t\t\tslice:  [][]int{[]int{2, 1}, []int{3}, []int{}},\n\t\t\texpect: [][]int{nil, nil, nil},\n\t\t},\n\t\t{\n\t\t\tslice:  []stringSlice{stringSlice{\"hello\", \"world\"}, stringSlice{}, stringSlice{\"goodbye\"}},\n\t\t\texpect: []stringSlice{nil, nil, nil},\n\t\t},\n\t} {\n\t\tv := ValueOf(test.slice)\n\t\texpectLen, expectCap := v.Len(), v.Cap()\n\n\t\tv.Clear()\n\t\tif len := v.Len(); len != expectLen {\n\t\t\tt.Errorf(\"Clear(slice) altered len, got %d, expected %d\", len, expectLen)\n\t\t}\n\t\tif cap := v.Cap(); cap != expectCap {\n\t\t\tt.Errorf(\"Clear(slice) altered cap, got %d, expected %d\", cap, expectCap)\n\t\t}\n\t\tif !DeepEqual(test.slice, test.expect) {\n\t\t\tt.Errorf(\"Clear(slice) got %v, expected %v\", test.slice, test.expect)\n\t\t}\n\t}\n}\n\nfunc TestClearMap(t *testing.T) {\n\tfor _, test := range []struct {\n\t\tm      any\n\t\texpect any\n\t}{\n\t\t{\n\t\t\tm:      map[int]bool{1: true, 2: false, 3: true},\n\t\t\texpect: map[int]bool{},\n\t\t},\n\t\t{\n\t\t\tm:      map[string][]byte{\"hello\": []byte(\"world\")},\n\t\t\texpect: map[string][]byte{},\n\t\t},\n\t} {\n\t\tv := ValueOf(test.m)\n\n\t\tv.Clear()\n\t\tif len := v.Len(); len != 0 {\n\t\t\tt.Errorf(\"Clear(map) should set len to 0, got %d\", len)\n\t\t}\n\t\tif !DeepEqual(test.m, test.expect) {\n\t\t\tt.Errorf(\"Clear(map) got %v, expected %v\", test.m, test.expect)\n\t\t}\n\t}\n}\n\nfunc TestCopyArrayToSlice(t *testing.T) {\n\t// Test copying array <=64 bits and >64bits\n\t// See issue #4554\n\ta1 := [1]int64{1}\n\ts1 := make([]int64, 1)\n\ta2 := [2]int64{1, 2}\n\ts2 := make([]int64, 2)\n\ta8 := [8]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}\n\ts8 := make([]byte, 8)\n\ta9 := [9]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09}\n\ts9 := make([]byte, 9)\n\n\tCopy(ValueOf(s1), ValueOf(a1))\n\tif !slices.Equal(s1, a1[:]) {\n\t\tt.Errorf(\"copied slice %x does not match input array %x\", s1, a1[:])\n\t}\n\tCopy(ValueOf(s2), ValueOf(a2))\n\tif !slices.Equal(s2, a2[:]) {\n\t\tt.Errorf(\"copied slice %x does not match input array %x\", s2, a2[:])\n\t}\n\tCopy(ValueOf(s8), ValueOf(a8))\n\tif !bytes.Equal(s8, a8[:]) {\n\t\tt.Errorf(\"copied slice %x does not match input array %x\", s8, a8[:])\n\t}\n\tCopy(ValueOf(s9), ValueOf(a9))\n\tif !bytes.Equal(s9, a9[:]) {\n\t\tt.Errorf(\"copied slice %x does not match input array %x\", s9, a9[:])\n\t}\n}\n\nfunc TestIssue4040(t *testing.T) {\n\tvar value interface{} = uint16(0)\n\n\t// get the pointer to the interface value\n\tinPtr := ValueOf(&value)\n\n\t// dereference to get the actual value (an interface)\n\tinElem := inPtr.Elem()\n\n\t// create a new value of the same concrete type\n\tuint16Type := TypeOf(uint16(0))\n\tnewUint16Value := New(uint16Type).Elem()\n\tnewUint16Value.Set(ValueOf(uint16(13)))\n\n\t// set the new value to the interface\n\tinElem.Set(newUint16Value)\n\n\tif value.(uint16) != 13 {\n\t\tt.Errorf(\"Failed to set interface value from uint16\")\n\t}\n}\n\nfunc equal[T comparable](a, b []T) bool {\n\tif len(a) != len(b) {\n\t\treturn false\n\t}\n\n\tfor i, aa := range a {\n\t\tif b[i] != aa {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n"
  },
  {
    "path": "src/reflect/visiblefields.go",
    "content": "package reflect\n\nimport (\n\t\"internal/reflectlite\"\n\t\"unsafe\"\n)\n\nfunc VisibleFields(t Type) []StructField {\n\tfields := reflectlite.VisibleFields(toRawType(t))\n\treturn *(*[]StructField)(unsafe.Pointer(&fields))\n}\n"
  },
  {
    "path": "src/reflect/visiblefields_test.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage reflect_test\n\nimport (\n\t. \"reflect\"\n\t\"strings\"\n\t\"testing\"\n)\n\ntype structField struct {\n\tname  string\n\tindex []int\n}\n\nvar fieldsTests = []struct {\n\ttestName string\n\tval      any\n\texpect   []structField\n}{{\n\ttestName: \"SimpleStruct\",\n\tval: struct {\n\t\tA int\n\t\tB string\n\t\tC bool\n\t}{},\n\texpect: []structField{{\n\t\tname:  \"A\",\n\t\tindex: []int{0},\n\t}, {\n\t\tname:  \"B\",\n\t\tindex: []int{1},\n\t}, {\n\t\tname:  \"C\",\n\t\tindex: []int{2},\n\t}},\n}, {\n\ttestName: \"NonEmbeddedStructMember\",\n\tval: struct {\n\t\tA struct {\n\t\t\tX int\n\t\t}\n\t}{},\n\texpect: []structField{{\n\t\tname:  \"A\",\n\t\tindex: []int{0},\n\t}},\n}, {\n\ttestName: \"EmbeddedExportedStruct\",\n\tval: struct {\n\t\tSFG\n\t}{},\n\texpect: []structField{{\n\t\tname:  \"SFG\",\n\t\tindex: []int{0},\n\t}, {\n\t\tname:  \"F\",\n\t\tindex: []int{0, 0},\n\t}, {\n\t\tname:  \"G\",\n\t\tindex: []int{0, 1},\n\t}},\n}, {\n\ttestName: \"EmbeddedUnexportedStruct\",\n\tval: struct {\n\t\tsFG\n\t}{},\n\texpect: []structField{{\n\t\tname:  \"sFG\",\n\t\tindex: []int{0},\n\t}, {\n\t\tname:  \"F\",\n\t\tindex: []int{0, 0},\n\t}, {\n\t\tname:  \"G\",\n\t\tindex: []int{0, 1},\n\t}},\n}, {\n\ttestName: \"TwoEmbeddedStructsWithCancelingMembers\",\n\tval: struct {\n\t\tSFG\n\t\tSF\n\t}{},\n\texpect: []structField{{\n\t\tname:  \"SFG\",\n\t\tindex: []int{0},\n\t}, {\n\t\tname:  \"G\",\n\t\tindex: []int{0, 1},\n\t}, {\n\t\tname:  \"SF\",\n\t\tindex: []int{1},\n\t}},\n}, {\n\ttestName: \"EmbeddedStructsWithSameFieldsAtDifferentDepths\",\n\tval: struct {\n\t\tSFGH3\n\t\tSG1\n\t\tSFG2\n\t\tSF2\n\t\tL int\n\t}{},\n\texpect: []structField{{\n\t\tname:  \"SFGH3\",\n\t\tindex: []int{0},\n\t}, {\n\t\tname:  \"SFGH2\",\n\t\tindex: []int{0, 0},\n\t}, {\n\t\tname:  \"SFGH1\",\n\t\tindex: []int{0, 0, 0},\n\t}, {\n\t\tname:  \"SFGH\",\n\t\tindex: []int{0, 0, 0, 0},\n\t}, {\n\t\tname:  \"H\",\n\t\tindex: []int{0, 0, 0, 0, 2},\n\t}, {\n\t\tname:  \"SG1\",\n\t\tindex: []int{1},\n\t}, {\n\t\tname:  \"SG\",\n\t\tindex: []int{1, 0},\n\t}, {\n\t\tname:  \"G\",\n\t\tindex: []int{1, 0, 0},\n\t}, {\n\t\tname:  \"SFG2\",\n\t\tindex: []int{2},\n\t}, {\n\t\tname:  \"SFG1\",\n\t\tindex: []int{2, 0},\n\t}, {\n\t\tname:  \"SFG\",\n\t\tindex: []int{2, 0, 0},\n\t}, {\n\t\tname:  \"SF2\",\n\t\tindex: []int{3},\n\t}, {\n\t\tname:  \"SF1\",\n\t\tindex: []int{3, 0},\n\t}, {\n\t\tname:  \"SF\",\n\t\tindex: []int{3, 0, 0},\n\t}, {\n\t\tname:  \"L\",\n\t\tindex: []int{4},\n\t}},\n}, {\n\ttestName: \"EmbeddedPointerStruct\",\n\tval: struct {\n\t\t*SF\n\t}{},\n\texpect: []structField{{\n\t\tname:  \"SF\",\n\t\tindex: []int{0},\n\t}, {\n\t\tname:  \"F\",\n\t\tindex: []int{0, 0},\n\t}},\n}, {\n\ttestName: \"EmbeddedNotAPointer\",\n\tval: struct {\n\t\tM\n\t}{},\n\texpect: []structField{{\n\t\tname:  \"M\",\n\t\tindex: []int{0},\n\t}},\n}, {\n\ttestName: \"RecursiveEmbedding\",\n\tval:      Rec1{},\n\texpect: []structField{{\n\t\tname:  \"Rec2\",\n\t\tindex: []int{0},\n\t}, {\n\t\tname:  \"F\",\n\t\tindex: []int{0, 0},\n\t}, {\n\t\tname:  \"Rec1\",\n\t\tindex: []int{0, 1},\n\t}},\n}, {\n\ttestName: \"RecursiveEmbedding2\",\n\tval:      Rec2{},\n\texpect: []structField{{\n\t\tname:  \"F\",\n\t\tindex: []int{0},\n\t}, {\n\t\tname:  \"Rec1\",\n\t\tindex: []int{1},\n\t}, {\n\t\tname:  \"Rec2\",\n\t\tindex: []int{1, 0},\n\t}},\n}, {\n\ttestName: \"RecursiveEmbedding3\",\n\tval:      RS3{},\n\texpect: []structField{{\n\t\tname:  \"RS2\",\n\t\tindex: []int{0},\n\t}, {\n\t\tname:  \"RS1\",\n\t\tindex: []int{1},\n\t}, {\n\t\tname:  \"i\",\n\t\tindex: []int{1, 0},\n\t}},\n}}\n\ntype SFG struct {\n\tF int\n\tG int\n}\n\ntype SFG1 struct {\n\tSFG\n}\n\ntype SFG2 struct {\n\tSFG1\n}\n\ntype SFGH struct {\n\tF int\n\tG int\n\tH int\n}\n\ntype SFGH1 struct {\n\tSFGH\n}\n\ntype SFGH2 struct {\n\tSFGH1\n}\n\ntype SFGH3 struct {\n\tSFGH2\n}\n\ntype SF struct {\n\tF int\n}\n\ntype SF1 struct {\n\tSF\n}\n\ntype SF2 struct {\n\tSF1\n}\n\ntype SG struct {\n\tG int\n}\n\ntype SG1 struct {\n\tSG\n}\n\ntype sFG struct {\n\tF int\n\tG int\n}\n\ntype RS1 struct {\n\ti int\n}\n\ntype RS2 struct {\n\tRS1\n}\n\ntype RS3 struct {\n\tRS2\n\tRS1\n}\n\ntype M map[string]any\n\ntype Rec1 struct {\n\t*Rec2\n}\n\ntype Rec2 struct {\n\tF string\n\t*Rec1\n}\n\nfunc TestFields(t *testing.T) {\n\tfor _, test := range fieldsTests {\n\t\ttest := test\n\t\tt.Run(test.testName, func(t *testing.T) {\n\t\t\ttyp := TypeOf(test.val)\n\t\t\tfields := VisibleFields(typ)\n\t\t\tif got, want := len(fields), len(test.expect); got != want {\n\t\t\t\tt.Fatalf(\"unexpected field count; got %d want %d\", got, want)\n\t\t\t}\n\n\t\t\tfor j, field := range fields {\n\t\t\t\texpect := test.expect[j]\n\t\t\t\tt.Logf(\"field %d: %s\", j, expect.name)\n\t\t\t\tgotField := typ.FieldByIndex(field.Index)\n\t\t\t\t// Unfortunately, FieldByIndex does not return\n\t\t\t\t// a field with the same index that we passed in,\n\t\t\t\t// so we set it to the expected value so that\n\t\t\t\t// it can be compared later with the result of FieldByName.\n\t\t\t\tgotField.Index = field.Index\n\t\t\t\texpectField := typ.FieldByIndex(expect.index)\n\t\t\t\t// ditto.\n\t\t\t\texpectField.Index = expect.index\n\t\t\t\tif !DeepEqual(gotField, expectField) {\n\t\t\t\t\tt.Fatalf(\"unexpected field result\\ngot %#v\\nwant %#v\", gotField, expectField)\n\t\t\t\t}\n\n\t\t\t\t// Sanity check that we can actually access the field by the\n\t\t\t\t// expected name.\n\t\t\t\tgotField1, ok := typ.FieldByName(expect.name)\n\t\t\t\tif !ok {\n\t\t\t\t\tt.Fatalf(\"field %q not accessible by name\", expect.name)\n\t\t\t\t}\n\t\t\t\tif !DeepEqual(gotField1, expectField) {\n\t\t\t\t\tt.Fatalf(\"unexpected FieldByName result; got %#v want %#v\", gotField1, expectField)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Must not panic with nil embedded pointer.\nfunc TestFieldByIndexErr(t *testing.T) {\n\t// TODO(dgryski): FieldByIndexErr not implemented yet -- skip\n\treturn\n\n\ttype A struct {\n\t\tS string\n\t}\n\ttype B struct {\n\t\t*A\n\t}\n\tv := ValueOf(B{})\n\t_, err := v.FieldByIndexErr([]int{0, 0})\n\tif err == nil {\n\t\tt.Fatal(\"expected error\")\n\t}\n\tif !strings.Contains(err.Error(), \"embedded struct field A\") {\n\t\tt.Fatal(err)\n\t}\n}\n"
  },
  {
    "path": "src/runtime/algorithm.go",
    "content": "package runtime\n\n// This file implements various core algorithms used in the runtime package and\n// standard library.\n\nimport (\n\t\"unsafe\"\n)\n\n// This function is needed by math/rand since Go 1.20.\n// See: https://github.com/golang/go/issues/54880\n//\n//go:linkname rand_fastrand64 math/rand.fastrand64\nfunc rand_fastrand64() uint64 {\n\treturn fastrand64()\n}\n\n// This function is used by hash/maphash.\n// This function isn't required anymore since Go 1.22, so should be removed once\n// that becomes the minimum requirement.\nfunc fastrand() uint32 {\n\txorshift32State = xorshift32(xorshift32State)\n\treturn xorshift32State\n}\n\nfunc initRand() {\n\tr, _ := hardwareRand()\n\txorshift64State = uint64(r | 1) // protect against 0\n\txorshift32State = uint32(xorshift64State)\n}\n\nvar xorshift32State uint32 = 1\n\nfunc xorshift32(x uint32) uint32 {\n\t// Algorithm \"xor\" from p. 4 of Marsaglia, \"Xorshift RNGs\".\n\t// Improved sequence based on\n\t// http://www.iro.umontreal.ca/~lecuyer/myftp/papers/xorshift.pdf\n\tx ^= x << 7\n\tx ^= x >> 1\n\tx ^= x << 9\n\treturn x\n}\n\n// This function is used by hash/maphash.\n// This function isn't required anymore since Go 1.22, so should be removed once\n// that becomes the minimum requirement.\nfunc fastrand64() uint64 {\n\txorshift64State = xorshiftMult64(xorshift64State)\n\treturn xorshift64State\n}\n\nvar xorshift64State uint64 = 1\n\n// 64-bit xorshift multiply rng from http://vigna.di.unimi.it/ftp/papers/xorshift.pdf\nfunc xorshiftMult64(x uint64) uint64 {\n\tx ^= x >> 12 // a\n\tx ^= x << 25 // b\n\tx ^= x >> 27 // c\n\treturn x * 2685821657736338717\n}\n\n// This function is used by hash/maphash.\nfunc memhash(p unsafe.Pointer, seed, s uintptr) uintptr {\n\tif unsafe.Sizeof(uintptr(0)) > 4 {\n\t\treturn uintptr(hash64(p, s, seed))\n\t}\n\treturn uintptr(hash32(p, s, seed))\n}\n\n// Function that's called from various packages starting with Go 1.22.\nfunc rand() uint64 {\n\t// Return a random number from hardware, falling back to software if\n\t// unavailable.\n\tn, ok := hardwareRand()\n\tif !ok {\n\t\t// Fallback to static random number.\n\t\t// Not great, but we can't do much better than this.\n\t\tn = fastrand64()\n\t}\n\treturn n\n}\n"
  },
  {
    "path": "src/runtime/arch-has-returnaddr.go",
    "content": "//go:build !(avr || tinygo.wasm)\n\npackage runtime\n\nimport \"unsafe\"\n\nconst hasReturnAddr = true\n\n//export llvm.returnaddress\nfunc returnAddress(level uint32) unsafe.Pointer\n"
  },
  {
    "path": "src/runtime/arch-no-returnaddr.go",
    "content": "//go:build avr || tinygo.wasm\n\npackage runtime\n\nimport \"unsafe\"\n\nconst hasReturnAddr = false\n\nfunc returnAddress(level uint32) unsafe.Pointer {\n\treturn nil\n}\n"
  },
  {
    "path": "src/runtime/arch_386.go",
    "content": "package runtime\n\nconst GOARCH = \"386\"\n\n// The bitness of the CPU (e.g. 8, 32, 64).\nconst TargetBits = 32\n\nconst deferExtraRegs = 0\n\nconst callInstSize = 5 // \"call someFunction\" is 5 bytes\n\nconst (\n\tlinux_MAP_ANONYMOUS = 0x20\n\tlinux_SIGBUS        = 7\n\tlinux_SIGILL        = 4\n\tlinux_SIGSEGV       = 11\n)\n\n// Align on word boundary.\nfunc align(ptr uintptr) uintptr {\n\treturn (ptr + 15) &^ 15\n}\n\nfunc getCurrentStackPointer() uintptr {\n\treturn uintptr(stacksave())\n}\n"
  },
  {
    "path": "src/runtime/arch_amd64.go",
    "content": "package runtime\n\nconst GOARCH = \"amd64\"\n\n// The bitness of the CPU (e.g. 8, 32, 64).\nconst TargetBits = 64\n\nconst deferExtraRegs = 0\n\nconst callInstSize = 5 // \"call someFunction\" is 5 bytes\n\nconst (\n\tlinux_MAP_ANONYMOUS = 0x20\n\tlinux_SIGBUS        = 7\n\tlinux_SIGILL        = 4\n\tlinux_SIGSEGV       = 11\n)\n\n// Align a pointer.\n// Note that some amd64 instructions (like movaps) expect 16-byte aligned\n// memory, thus the result must be 16-byte aligned.\nfunc align(ptr uintptr) uintptr {\n\treturn (ptr + 15) &^ 15\n}\n\nfunc getCurrentStackPointer() uintptr {\n\treturn uintptr(stacksave())\n}\n"
  },
  {
    "path": "src/runtime/arch_arm.go",
    "content": "//go:build (arm && !baremetal && !tinygo.wasm) || (arm && arm7tdmi)\n\npackage runtime\n\nconst GOARCH = \"arm\"\n\n// The bitness of the CPU (e.g. 8, 32, 64).\nconst TargetBits = 32\n\nconst deferExtraRegs = 0\n\nconst callInstSize = 4 // \"bl someFunction\" is 4 bytes\n\nconst (\n\tlinux_MAP_ANONYMOUS = 0x20\n\tlinux_SIGBUS        = 7\n\tlinux_SIGILL        = 4\n\tlinux_SIGSEGV       = 11\n)\n\n// Align on the maximum alignment for this platform (double).\nfunc align(ptr uintptr) uintptr {\n\treturn (ptr + 7) &^ 7\n}\n\nfunc getCurrentStackPointer() uintptr {\n\treturn uintptr(stacksave())\n}\n"
  },
  {
    "path": "src/runtime/arch_arm64.go",
    "content": "package runtime\n\nconst GOARCH = \"arm64\"\n\n// The bitness of the CPU (e.g. 8, 32, 64).\nconst TargetBits = 64\n\nconst deferExtraRegs = 0\n\nconst callInstSize = 4 // \"bl someFunction\" is 4 bytes\n\nconst (\n\tlinux_MAP_ANONYMOUS = 0x20\n\tlinux_SIGBUS        = 7\n\tlinux_SIGILL        = 4\n\tlinux_SIGSEGV       = 11\n)\n\n// Align on word boundary.\nfunc align(ptr uintptr) uintptr {\n\treturn (ptr + 15) &^ 15\n}\n\nfunc getCurrentStackPointer() uintptr {\n\treturn uintptr(stacksave())\n}\n"
  },
  {
    "path": "src/runtime/arch_avr.go",
    "content": "//go:build avr\n\npackage runtime\n\nimport \"runtime/interrupt\"\n\nconst GOARCH = \"arm\" // avr pretends to be arm\n\n// The bitness of the CPU (e.g. 8, 32, 64).\nconst TargetBits = 8\n\nconst deferExtraRegs = 1 // the frame pointer (Y register) also needs to be stored\n\nconst callInstSize = 2 // \"call\" is 4 bytes, \"rcall\" is 2 bytes\n\n// Align on a word boundary.\nfunc align(ptr uintptr) uintptr {\n\t// No alignment necessary on the AVR.\n\treturn ptr\n}\n\nfunc getCurrentStackPointer() uintptr {\n\treturn uintptr(stacksave())\n}\n\n// The safest thing to do here would just be to disable interrupts for\n// procPin/procUnpin. Note that a global variable is safe in this case, as any\n// access to procPinnedMask will happen with interrupts disabled.\n\nvar procPinnedMask interrupt.State\n\n//go:linkname procPin sync/atomic.runtime_procPin\nfunc procPin() {\n\tprocPinnedMask = interrupt.Disable()\n}\n\n//go:linkname procUnpin sync/atomic.runtime_procUnpin\nfunc procUnpin() {\n\tinterrupt.Restore(procPinnedMask)\n}\n\n// The following functions are workarounds for things missing in compiler-rt.\n// They will likely need special assembly implementations.\n// They are treated specially: they're added to @llvm.compiler.used so that the\n// linker won't eliminate them.\n\n//export __mulsi3\nfunc __mulsi3(a, b uint32) uint32 {\n\tvar r uint32\n\tfor a != 0 {\n\t\tif a&1 != 0 {\n\t\t\tr += b\n\t\t}\n\t\ta >>= 1\n\t\tb <<= 1\n\t}\n\treturn r\n}\n\n//export __divsi3\nfunc __divsi3(a, b int32) int32\n\n//export __udivsi3\nfunc __udivsi3(a, b uint32) uint32\n\n//export __divmodsi4\nfunc __divmodsi4(a, b int32) uint64 {\n\td := __divsi3(a, b)\n\trem := a - (d * b)\n\treturn uint64(uint32(d)) | uint64(uint32(rem))<<32\n}\n\n//export __udivmodsi4\nfunc __udivmodsi4(a, b uint32) uint64 {\n\td := __udivsi3(a, b)\n\trem := a - (d * b)\n\treturn uint64(d) | uint64(rem)<<32\n}\n"
  },
  {
    "path": "src/runtime/arch_cortexm.go",
    "content": "//go:build cortexm\n\npackage runtime\n\nimport (\n\t\"device/arm\"\n)\n\nconst GOARCH = \"arm\"\n\n// The bitness of the CPU (e.g. 8, 32, 64).\nconst TargetBits = 32\n\nconst deferExtraRegs = 0\n\nconst callInstSize = 4 // \"bl someFunction\" is 4 bytes\n\n// Align on word boundary.\nfunc align(ptr uintptr) uintptr {\n\treturn (ptr + 7) &^ 7\n}\n\nfunc getCurrentStackPointer() uintptr {\n\treturn uintptr(stacksave())\n}\n\n// The safest thing to do here would just be to disable interrupts for\n// procPin/procUnpin. Note that a global variable is safe in this case, as any\n// access to procPinnedMask will happen with interrupts disabled.\n\nvar procPinnedMask uintptr\n\n//go:linkname procPin sync/atomic.runtime_procPin\nfunc procPin() {\n\tprocPinnedMask = arm.DisableInterrupts()\n}\n\n//go:linkname procUnpin sync/atomic.runtime_procUnpin\nfunc procUnpin() {\n\tarm.EnableInterrupts(procPinnedMask)\n}\n"
  },
  {
    "path": "src/runtime/arch_mips.go",
    "content": "package runtime\n\nconst GOARCH = \"mips\"\n\n// The bitness of the CPU (e.g. 8, 32, 64).\nconst TargetBits = 32\n\nconst deferExtraRegs = 0\n\nconst callInstSize = 8 // \"jal someFunc\" is 4 bytes, plus a MIPS delay slot\n\nconst (\n\tlinux_MAP_ANONYMOUS = 0x800\n\tlinux_SIGBUS        = 10\n\tlinux_SIGILL        = 4\n\tlinux_SIGSEGV       = 11\n)\n\n// It appears that MIPS has a maximum alignment of 8 bytes.\nfunc align(ptr uintptr) uintptr {\n\treturn (ptr + 7) &^ 7\n}\n\nfunc getCurrentStackPointer() uintptr {\n\treturn uintptr(stacksave())\n}\n"
  },
  {
    "path": "src/runtime/arch_mipsle.go",
    "content": "package runtime\n\nconst GOARCH = \"mipsle\"\n\n// The bitness of the CPU (e.g. 8, 32, 64).\nconst TargetBits = 32\n\nconst deferExtraRegs = 0\n\nconst callInstSize = 8 // \"jal someFunc\" is 4 bytes, plus a MIPS delay slot\n\nconst (\n\tlinux_MAP_ANONYMOUS = 0x800\n\tlinux_SIGBUS        = 10\n\tlinux_SIGILL        = 4\n\tlinux_SIGSEGV       = 11\n)\n\n// It appears that MIPS has a maximum alignment of 8 bytes.\nfunc align(ptr uintptr) uintptr {\n\treturn (ptr + 7) &^ 7\n}\n\nfunc getCurrentStackPointer() uintptr {\n\treturn uintptr(stacksave())\n}\n"
  },
  {
    "path": "src/runtime/arch_tinygoriscv.go",
    "content": "//go:build tinygo.riscv\n\npackage runtime\n\nimport \"device/riscv\"\n\nconst deferExtraRegs = 0\n\nconst callInstSize = 4 // 8 without relaxation, maybe 4 with relaxation\n\n// RISC-V has a maximum alignment of 16 bytes (both for RV32 and for RV64).\n// Source: https://riscv.org/wp-content/uploads/2015/01/riscv-calling.pdf\nfunc align(ptr uintptr) uintptr {\n\treturn (ptr + 15) &^ 15\n}\n\nfunc getCurrentStackPointer() uintptr {\n\treturn uintptr(stacksave())\n}\n\n// The safest thing to do here would just be to disable interrupts for\n// procPin/procUnpin. Note that a global variable is safe in this case, as any\n// access to procPinnedMask will happen with interrupts disabled.\n\nvar procPinnedMask uintptr\n\n//go:linkname procPin sync/atomic.runtime_procPin\nfunc procPin() {\n\tprocPinnedMask = riscv.DisableInterrupts()\n}\n\n//go:linkname procUnpin sync/atomic.runtime_procUnpin\nfunc procUnpin() {\n\triscv.EnableInterrupts(procPinnedMask)\n}\n\nfunc waitForEvents() {\n\tmask := riscv.DisableInterrupts()\n\tif runqueue := schedulerRunQueue(); runqueue == nil || !runqueue.Empty() {\n\t\triscv.Asm(\"wfi\")\n\t}\n\triscv.EnableInterrupts(mask)\n}\n"
  },
  {
    "path": "src/runtime/arch_tinygoriscv32.go",
    "content": "//go:build tinygo.riscv32\n\npackage runtime\n\nconst GOARCH = \"arm\" // riscv pretends to be arm\n\n// The bitness of the CPU (e.g. 8, 32, 64).\nconst TargetBits = 32\n"
  },
  {
    "path": "src/runtime/arch_tinygoriscv64.go",
    "content": "//go:build tinygo.riscv64\n\npackage runtime\n\nconst GOARCH = \"arm64\" // riscv pretends to be arm\n\n// The bitness of the CPU (e.g. 8, 32, 64).\nconst TargetBits = 64\n"
  },
  {
    "path": "src/runtime/arch_tinygowasm.go",
    "content": "//go:build tinygo.wasm\n\npackage runtime\n\nimport (\n\t\"unsafe\"\n)\n\nconst GOARCH = \"wasm\"\n\n// The bitness of the CPU (e.g. 8, 32, 64).\nconst TargetBits = 32\n\nconst deferExtraRegs = 0\n\nconst callInstSize = 1 // unknown and irrelevant (llvm.returnaddress doesn't work), so make something up\n\n//go:extern __heap_base\nvar heapStartSymbol [0]byte\n\n//go:extern __global_base\nvar globalsStartSymbol [0]byte\n\nconst (\n\t// wasmMemoryIndex is always zero until the multi-memory feature is used.\n\t//\n\t// See https://github.com/WebAssembly/multi-memory\n\twasmMemoryIndex = 0\n\n\t// wasmPageSize is the size of a page in WebAssembly's 32-bit memory. This\n\t// is also its only unit of change.\n\t//\n\t// See https://www.w3.org/TR/wasm-core-1/#page-size\n\twasmPageSize = 64 * 1024\n)\n\n// wasm_memory_size invokes the \"memory.size\" instruction, which returns the\n// current size to the memory at the given index (always wasmMemoryIndex), in\n// pages.\n//\n//export llvm.wasm.memory.size.i32\nfunc wasm_memory_size(index int32) int32\n\n// wasm_memory_grow invokes the \"memory.grow\" instruction, which attempts to\n// increase the size of the memory at the given index (always wasmMemoryIndex),\n// by the delta (in pages). This returns the previous size on success of -1 on\n// failure.\n//\n//export llvm.wasm.memory.grow.i32\nfunc wasm_memory_grow(index int32, delta int32) int32\n\nvar (\n\t// heapStart is the current memory offset which starts the heap. The heap\n\t// extends from this offset until heapEnd (exclusive).\n\theapStart = uintptr(unsafe.Pointer(&heapStartSymbol))\n\n\t// heapEnd is the current memory length in bytes.\n\theapEnd = uintptr(wasm_memory_size(wasmMemoryIndex) * wasmPageSize)\n\n\tglobalsStart = uintptr(unsafe.Pointer(&globalsStartSymbol))\n\tglobalsEnd   = uintptr(unsafe.Pointer(&heapStartSymbol))\n\n\tstackTop = uintptr(unsafe.Pointer(&globalsStartSymbol))\n)\n\nfunc align(ptr uintptr) uintptr {\n\t// Align to 16, which is the alignment of max_align_t:\n\t// https://godbolt.org/z/dYqTsWrGq\n\tconst heapAlign = 16\n\treturn (ptr + heapAlign - 1) &^ (heapAlign - 1)\n}\n\n//export tinygo_getCurrentStackPointer\nfunc getCurrentStackPointer() uintptr\n\n// savedStackPointer is used to save the system stack pointer while in a goroutine.\nvar savedStackPointer uintptr\n\n// saveStackPointer is called by internal/task.state.Resume() to save the stack pointer before entering a goroutine from the system stack.\nfunc saveStackPointer() {\n\tsavedStackPointer = getCurrentStackPointer()\n}\n\n// growHeap tries to grow the heap size. It returns true if it succeeds, false\n// otherwise.\nfunc growHeap() bool {\n\t// Grow memory by the available size, which means the heap size is doubled.\n\tmemorySize := wasm_memory_size(wasmMemoryIndex)\n\tresult := wasm_memory_grow(wasmMemoryIndex, memorySize)\n\tif result == -1 {\n\t\t// Grow failed.\n\t\treturn false\n\t}\n\n\tsetHeapEnd(uintptr(wasm_memory_size(wasmMemoryIndex) * wasmPageSize))\n\n\t// Heap has grown successfully.\n\treturn true\n}\n"
  },
  {
    "path": "src/runtime/arch_tinygowasm_malloc.go",
    "content": "//go:build tinygo.wasm && !(custommalloc || wasm_unknown || gc.boehm)\n\npackage runtime\n\nimport \"unsafe\"\n\n// The below functions override the default allocator of wasi-libc. This ensures\n// code linked from other languages can allocate memory without colliding with\n// our GC allocations.\n\n// Map of allocations, where the key is the allocated pointer and the value is\n// the size of the allocation.\n// TODO: make this a map[unsafe.Pointer]uintptr, since that results in slightly\n// smaller binaries. But for that to work, unsafe.Pointer needs to be seen as a\n// binary key (which it is not at the moment).\n// See https://github.com/tinygo-org/tinygo/pull/4898 for details.\nvar allocs = make(map[*byte]uintptr)\n\n//export malloc\nfunc libc_malloc(size uintptr) unsafe.Pointer {\n\tif size == 0 {\n\t\treturn nil\n\t}\n\tptr := alloc(size, nil)\n\tallocs[(*byte)(ptr)] = size\n\treturn ptr\n}\n\n//export free\nfunc libc_free(ptr unsafe.Pointer) {\n\tif ptr == nil {\n\t\treturn\n\t}\n\tif _, ok := allocs[(*byte)(ptr)]; ok {\n\t\tdelete(allocs, (*byte)(ptr))\n\t} else {\n\t\tpanic(\"free: invalid pointer\")\n\t}\n}\n\n//export calloc\nfunc libc_calloc(nmemb, size uintptr) unsafe.Pointer {\n\t// No difference between calloc and malloc.\n\treturn libc_malloc(nmemb * size)\n}\n\n//export realloc\nfunc libc_realloc(oldPtr unsafe.Pointer, size uintptr) unsafe.Pointer {\n\tif size == 0 {\n\t\tlibc_free(oldPtr)\n\t\treturn nil\n\t}\n\n\t// It's hard to optimize this to expand the current buffer with our GC, but\n\t// it is theoretically possible. For now, just always allocate fresh.\n\t// TODO: we could skip this if the new allocation is smaller than the old.\n\tptr := alloc(size, nil)\n\n\tif oldPtr != nil {\n\t\tif oldSize, ok := allocs[(*byte)(oldPtr)]; ok {\n\t\t\toldBuf := unsafe.Slice((*byte)(oldPtr), oldSize)\n\t\t\tnewBuf := unsafe.Slice((*byte)(ptr), size)\n\t\t\tcopy(newBuf, oldBuf)\n\t\t\tdelete(allocs, (*byte)(oldPtr))\n\t\t} else {\n\t\t\tpanic(\"realloc: invalid pointer\")\n\t\t}\n\t}\n\n\tallocs[(*byte)(ptr)] = size\n\treturn ptr\n}\n"
  },
  {
    "path": "src/runtime/arch_xtensa.go",
    "content": "//go:build xtensa\n\npackage runtime\n\nconst GOARCH = \"arm\" // xtensa pretends to be arm\n\n// The bitness of the CPU (e.g. 8, 32, 64).\nconst TargetBits = 32\n\nconst deferExtraRegs = 0\n\nconst callInstSize = 3 // \"callx0 someFunction\" (and similar) is 3 bytes\n\n// The largest alignment according to the Xtensa ABI is 8 (long long, double).\nfunc align(ptr uintptr) uintptr {\n\treturn (ptr + 7) &^ 7\n}\n\nfunc getCurrentStackPointer() uintptr {\n\treturn uintptr(stacksave())\n}\n"
  },
  {
    "path": "src/runtime/asm_386.S",
    "content": "#ifdef _WIN32\n.global _tinygo_scanCurrentStack\n_tinygo_scanCurrentStack:\n#else\n.section .text.tinygo_scanCurrentStack\n.global tinygo_scanCurrentStack\n.type tinygo_scanCurrentStack, %function\ntinygo_scanCurrentStack:\n#endif\n    // Sources:\n    //   * https://stackoverflow.com/questions/18024672/what-registers-are-preserved-through-a-linux-x86-64-function-call\n    //   * https://godbolt.org/z/q7e8dn\n\n    // Save callee-saved registers.\n    pushl %ebx\n    pushl %esi\n    pushl %edi\n    pushl %ebp\n\n    // Scan the stack.\n    subl $8, %esp // adjust the stack before the call to maintain 16-byte alignment\n    pushl %esp\n    #ifdef _WIN32\n    calll _tinygo_scanstack\n    #else\n    calll tinygo_scanstack\n    #endif\n\n    // Restore the stack pointer. Registers do not need to be restored as they\n    // were only pushed to be discoverable by the GC.\n    addl $28, %esp\n    retl\n\n\n#ifdef _WIN32\n.global _tinygo_longjmp\n_tinygo_longjmp:\n#else\n.section .text.tinygo_longjmp\n.global tinygo_longjmp\ntinygo_longjmp:\n#endif\n    // Note: the code we jump to assumes eax is set to a non-zero value if we\n    // jump from here.\n    movl 4(%esp), %eax\n    movl 0(%eax), %esp // jumpSP\n    movl 4(%eax), %eax // jumpPC (stash in volatile register)\n    jmpl *%eax\n"
  },
  {
    "path": "src/runtime/asm_amd64.S",
    "content": "#ifdef __ELF__\n.section .text.tinygo_scanCurrentStack\n.global tinygo_scanCurrentStack\ntinygo_scanCurrentStack:\n#else // Darwin\n.global _tinygo_scanCurrentStack\n_tinygo_scanCurrentStack:\n#endif\n    // Save callee-saved registers.\n    pushq %rbx\n    pushq %rbp\n    pushq %r12\n    pushq %r13\n    pushq %r14\n    pushq %r15\n\n    // Scan the stack.\n    subq $8, %rsp // adjust the stack before the call to maintain 16-byte alignment\n    movq %rsp, %rdi\n#ifdef __ELF__\n    callq tinygo_scanstack\n#else\n    callq _tinygo_scanstack // Darwin\n#endif\n\n    // Restore the stack pointer. Registers do not need to be restored as they\n    // were only pushed to be discoverable by the GC.\n    addq $56, %rsp\n    retq\n\n\n#ifdef __ELF__\n.section .text.tinygo_longjmp\n.global tinygo_longjmp\ntinygo_longjmp:\n#else // Darwin\n.global _tinygo_longjmp\n_tinygo_longjmp:\n#endif\n    // Note: the code we jump to assumes rax is set to a non-zero value if we\n    // jump from here, so we use rax as the temporary value for jumpPC.\n    movq 0(%rdi), %rsp // jumpSP\n    movq 8(%rdi), %rax // jumpPC\n    jmpq *%rax\n\n\n#ifdef __MACH__ // Darwin\n// allow these symbols to stripped as dead code\n.subsections_via_symbols\n#endif\n"
  },
  {
    "path": "src/runtime/asm_amd64_windows.S",
    "content": ".section .text.tinygo_scanCurrentStack,\"ax\"\n.global tinygo_scanCurrentStack\ntinygo_scanCurrentStack:\n    // Save callee-saved registers.\n    pushq %rbx\n    pushq %rbp\n    pushq %rdi\n    pushq %rsi\n    pushq %r12\n    pushq %r13\n    pushq %r14\n    pushq %r15\n\n    // Scan the stack.\n    subq $8, %rsp   // adjust the stack before the call to maintain 16-byte alignment\n    movq %rsp, %rcx // pass the stack pointer as the first parameter\n    callq tinygo_scanstack\n\n    // Restore the stack pointer. Registers do not need to be restored as they\n    // were only pushed to be discoverable by the GC.\n    addq $72, %rsp\n    retq\n\n.section .text.tinygo_longjmp,\"ax\"\n.global tinygo_longjmp\ntinygo_longjmp:\n    // Note: the code we jump to assumes rax is set to a non-zero value if we\n    // jump from here, so we use rax as the temporary value for jumpPC.\n    movq 0(%rcx), %rsp // jumpSP\n    movq 8(%rcx), %rax // jumpPC\n    jmpq *%rax\n"
  },
  {
    "path": "src/runtime/asm_arm.S",
    "content": "// Only generate .debug_frame, don't generate .eh_frame.\n.cfi_sections .debug_frame\n\n.section .text.tinygo_scanCurrentStack\n.global  tinygo_scanCurrentStack\n.type    tinygo_scanCurrentStack, %function\ntinygo_scanCurrentStack:\n    .cfi_startproc\n    // Save callee-saved registers onto the stack.\n    #if defined(__thumb2__)\n    push {r4-r11, lr}\n    .cfi_def_cfa_offset 9*4\n    #else\n    mov r0, r8\n    mov r1, r9\n    mov r2, r10\n    mov r3, r11\n    push {r0-r3, lr}\n    .cfi_def_cfa_offset 5*4\n    push {r4-r7}\n    .cfi_def_cfa_offset 4*4\n    #endif\n\n    // Scan the stack.\n    mov r0, sp\n    bl tinygo_scanstack\n\n    // Restore stack state and return.\n    add sp, #32\n    .cfi_def_cfa_offset 1*4\n    pop {pc}\n    .cfi_endproc\n.size tinygo_scanCurrentStack, .-tinygo_scanCurrentStack\n\n\n.section .text.tinygo_longjmp\n.global tinygo_longjmp\n.type   tinygo_longjmp, %function\ntinygo_longjmp:\n    .cfi_startproc\n    // Note: the code we jump to assumes r0 is set to a non-zero value if we\n    // jump from here (which is conveniently already the case).\n\n    ldm r0, {r0, r1}\n    mov sp, r0 // jumpSP\n    mov pc, r1 // jumpPC\n    .cfi_endproc\n.size tinygo_longjmp, .-tinygo_longjmp\n"
  },
  {
    "path": "src/runtime/asm_arm64.S",
    "content": "#ifdef __MACH__\n.global _tinygo_scanCurrentStack\n_tinygo_scanCurrentStack:\n#else\n.global tinygo_scanCurrentStack\ntinygo_scanCurrentStack:\n#endif\n    // Sources:\n    //   * https://developer.arm.com/architectures/learn-the-architecture/armv8-a-instruction-set-architecture/procedure-call-standard\n    //   * https://godbolt.org/z/qrvrEh\n\n    // Save callee-saved registers.\n    stp     x29, x30, [sp, #-160]!\n    stp     x28, x27, [sp, #16]\n    stp     x26, x25, [sp, #32]\n    stp     x24, x23, [sp, #48]\n    stp     x22, x21, [sp, #64]\n    stp     x20, x19, [sp, #80]\n    stp     d8,  d9,  [sp, #96]\n    stp     d10, d11, [sp, #112]\n    stp     d12, d13, [sp, #128]\n    stp     d14, d15, [sp, #144]\n\n    // Scan the stack.\n    mov     x0, sp\n#ifdef __MACH__\n    bl      _tinygo_scanstack\n#else\n    bl      tinygo_scanstack\n#endif\n\n    // Restore stack state and return.\n    ldp     x29, x30, [sp], #160\n    ret\n\n\n#ifdef __MACH__\n.global _tinygo_longjmp\n_tinygo_longjmp:\n#else\n.global tinygo_longjmp\ntinygo_longjmp:\n#endif\n    // Note: the code we jump to assumes x0 is set to a non-zero value if we\n    // jump from here (which is conveniently already the case).\n    ldp x1, x2, [x0] // jumpSP, jumpPC\n    mov sp, x1\n    br  x2\n"
  },
  {
    "path": "src/runtime/asm_avr.S",
    "content": ".section .text.tinygo_scanCurrentStack\n.global tinygo_scanCurrentStack\n.type tinygo_scanCurrentStack, %function\ntinygo_scanCurrentStack:\n    // Save callee-saved registers.\n    push r29 // Y\n    push r28 // Y\n    push r17\n    push r16\n    push r15\n    push r14\n    push r13\n    push r12\n    push r11\n    push r10\n    push r9\n    push r8\n    push r7\n    push r6\n    push r5\n    push r4\n    push r3\n    push r2\n\n    // Scan the stack.\n    in  r24, 0x3d; SPL\n    in  r25, 0x3e; SPH\n#if __AVR_ARCH__ == 2 || __AVR_ARCH__ == 25\n    rcall tinygo_scanstack\n#else\n    call tinygo_scanstack\n#endif\n\n    // Restore callee-saved registers.\n    pop r2\n    pop r3\n    pop r4\n    pop r5\n    pop r6\n    pop r7\n    pop r8\n    pop r9\n    pop r10\n    pop r11\n    pop r12\n    pop r13\n    pop r14\n    pop r15\n    pop r16\n    pop r17\n    pop r28 // Y\n    pop r29 // Y\n\n\n.section .text.tinygo_longjmp\n.global tinygo_longjmp\ntinygo_longjmp:\n    ; Move the *DeferFrame pointer to the X register.\n    mov r26, r24\n    mov r27, r25\n\n    ; Load the stack pointer\n    ld r24, X+\n    ld r25, X+\n\n    ; Switch to the given stack pointer.\n    in r0, 0x3f   ; SREG\n    cli           ; disable interrupts\n    out 0x3d, r24 ; SPL\n    out 0x3f, r0  ; re-enable interrupts (with one instruction delay)\n    out 0x3e, r25 ; SPH\n\n    ; Load the new PC\n    ld r30, X+\n    ld r31, X+\n\n    ; Load the new Y register\n    ld r28, X+\n    ld r29, X+\n\n\t; Mark that we returned from a longjmp.\n\tldi r24, 1\n\n    ; Jump to the PC (stored in the Z register)\n    icall\n"
  },
  {
    "path": "src/runtime/asm_mipsx.S",
    "content": "// Do not reorder instructions to insert a branch delay slot.\n// We know what we're doing, and will manually fill the branch delay slot.\n.set noreorder\n\n.section .text.tinygo_scanCurrentStack\n.global  tinygo_scanCurrentStack\n.type    tinygo_scanCurrentStack, %function\ntinygo_scanCurrentStack:\n    // Push callee-saved registers onto the stack.\n    addiu $sp, $sp, -40\n    sw $ra, 36($sp)\n    sw $s8, 32($sp)\n    sw $s7, 28($sp)\n    sw $s6, 24($sp)\n    sw $s5, 20($sp)\n    sw $s4, 16($sp)\n    sw $s3, 12($sp)\n    sw $s2,  8($sp)\n    sw $s1,  4($sp)\n    sw $s0,   ($sp)\n\n    // Scan the stack.\n    jal tinygo_scanstack\n    move $a0, $sp // in the branch delay slot\n\n    // Restore return address.\n    lw $ra, 36($sp)\n\n    // Restore stack state.\n    addiu $sp, $sp, 40\n\n    // Return to the caller.\n    jalr $ra\n    nop\n\n.section .text.tinygo_longjmp\n.global tinygo_longjmp\ntinygo_longjmp:\n    // Note: the code we jump to assumes a0 is non-zero, which is already the\n    // case because that's the defer frame pointer.\n    lw $sp, 0($a0) // jumpSP\n    lw $a1, 4($a0) // jumpPC\n    jr $a1\n    nop\n"
  },
  {
    "path": "src/runtime/asm_riscv.S",
    "content": "#if __riscv_xlen==64\n#define REGSIZE 8\n#define SREG sd\n#define LREG ld\n#else\n#define REGSIZE 4\n#define SREG sw\n#define LREG lw\n#endif\n\n.section .text.tinygo_scanCurrentStack\n.global  tinygo_scanCurrentStack\n.type    tinygo_scanCurrentStack, %function\ntinygo_scanCurrentStack:\n   // Push callee-saved registers onto the stack.\n   addi sp, sp, -13*REGSIZE\n   SREG ra,  0*REGSIZE(sp)\n   SREG s11, 1*REGSIZE(sp)\n   SREG s10, 2*REGSIZE(sp)\n   SREG s9,  3*REGSIZE(sp)\n   SREG s8,  4*REGSIZE(sp)\n   SREG s7,  5*REGSIZE(sp)\n   SREG s6,  6*REGSIZE(sp)\n   SREG s5,  7*REGSIZE(sp)\n   SREG s4,  8*REGSIZE(sp)\n   SREG s3,  9*REGSIZE(sp)\n   SREG s2,  10*REGSIZE(sp)\n   SREG s1,  11*REGSIZE(sp)\n   SREG s0,  12*REGSIZE(sp)\n\n   // Scan the stack.\n   mv a0, sp\n   call tinygo_scanstack\n\n   // Restore return address.\n   LREG ra, 0(sp)\n\n   // Restore stack state.\n   addi sp, sp, 13*REGSIZE\n\n   // Return to the caller.\n   ret\n\n\n.section .text.tinygo_longjmp\n.global tinygo_longjmp\ntinygo_longjmp:\n    // Note: the code we jump to assumes a0 is non-zero, which is already the\n    // case because that's the defer frame pointer.\n    lw sp, 0(a0)       // jumpSP\n    lw a1, REGSIZE(a0) // jumpPC\n    jr a1\n\n.section .text.tinygo_checkpointJump\n.global tinygo_checkpointJump\ntinygo_checkpointJump:\n    // Note: the code we jump to assumes a0 is non-zero, which is already the\n    // case because that's the stack pointer.\n    mv sp, a0          // jumpSP\n    csrw mepc, a1      // update MEPC value, so we resume there after the mret\n    mret               // jump to jumpPC\n"
  },
  {
    "path": "src/runtime/asm_tinygowasm.S",
    "content": ".globaltype __stack_pointer, i32\n\n.global  tinygo_getCurrentStackPointer\n.hidden  tinygo_getCurrentStackPointer\n.type    tinygo_getCurrentStackPointer,@function\ntinygo_getCurrentStackPointer: // func getCurrentStackPointer() uintptr\n    .functype tinygo_getCurrentStackPointer() -> (i32)\n    global.get __stack_pointer\n    return\n    end_function\n"
  },
  {
    "path": "src/runtime/atomics_critical.go",
    "content": "//go:build baremetal && !tinygo.wasm\n\n// Automatically generated file. DO NOT EDIT.\n// This file implements standins for non-native atomics using critical sections.\n\npackage runtime\n\nimport (\n\t_ \"unsafe\"\n)\n\n// Documentation:\n// * https://llvm.org/docs/Atomics.html\n// * https://gcc.gnu.org/onlinedocs/gcc/_005f_005fsync-Builtins.html\n//\n// Some atomic operations are emitted inline while others are emitted as libcalls.\n// How many are emitted as libcalls depends on the MCU arch and core variant.\n\n// 16-bit atomics.\n\n//export __atomic_load_2\nfunc __atomic_load_2(ptr *uint16, ordering uintptr) uint16 {\n\t// The LLVM docs for this say that there is a val argument after the pointer.\n\t// That is a typo, and the GCC docs omit it.\n\tmask := lockAtomics()\n\tval := *ptr\n\tunlockAtomics(mask)\n\treturn val\n}\n\n//export __atomic_store_2\nfunc __atomic_store_2(ptr *uint16, val uint16, ordering uintptr) {\n\tmask := lockAtomics()\n\t*ptr = val\n\tunlockAtomics(mask)\n}\n\n//go:inline\nfunc doAtomicCAS16(ptr *uint16, expected, desired uint16) uint16 {\n\tmask := lockAtomics()\n\told := *ptr\n\tif old == expected {\n\t\t*ptr = desired\n\t}\n\tunlockAtomics(mask)\n\treturn old\n}\n\n//export __sync_val_compare_and_swap_2\nfunc __sync_val_compare_and_swap_2(ptr *uint16, expected, desired uint16) uint16 {\n\treturn doAtomicCAS16(ptr, expected, desired)\n}\n\n//export __atomic_compare_exchange_2\nfunc __atomic_compare_exchange_2(ptr, expected *uint16, desired uint16, successOrder, failureOrder uintptr) bool {\n\texp := *expected\n\told := doAtomicCAS16(ptr, exp, desired)\n\treturn old == exp\n}\n\n//go:inline\nfunc doAtomicSwap16(ptr *uint16, new uint16) uint16 {\n\tmask := lockAtomics()\n\told := *ptr\n\t*ptr = new\n\tunlockAtomics(mask)\n\treturn old\n}\n\n//export __sync_lock_test_and_set_2\nfunc __sync_lock_test_and_set_2(ptr *uint16, new uint16) uint16 {\n\treturn doAtomicSwap16(ptr, new)\n}\n\n//export __atomic_exchange_2\nfunc __atomic_exchange_2(ptr *uint16, new uint16, ordering uintptr) uint16 {\n\treturn doAtomicSwap16(ptr, new)\n}\n\n//go:inline\nfunc doAtomicAdd16(ptr *uint16, value uint16) (old, new uint16) {\n\tmask := lockAtomics()\n\told = *ptr\n\tnew = old + value\n\t*ptr = new\n\tunlockAtomics(mask)\n\treturn old, new\n}\n\n//export __atomic_fetch_add_2\nfunc __atomic_fetch_add_2(ptr *uint16, value uint16, ordering uintptr) uint16 {\n\told, _ := doAtomicAdd16(ptr, value)\n\treturn old\n}\n\n//export __sync_fetch_and_add_2\nfunc __sync_fetch_and_add_2(ptr *uint16, value uint16) uint16 {\n\told, _ := doAtomicAdd16(ptr, value)\n\treturn old\n}\n\n//export __atomic_add_fetch_2\nfunc __atomic_add_fetch_2(ptr *uint16, value uint16, ordering uintptr) uint16 {\n\t_, new := doAtomicAdd16(ptr, value)\n\treturn new\n}\n\n// 32-bit atomics.\n\n//export __atomic_load_4\nfunc __atomic_load_4(ptr *uint32, ordering uintptr) uint32 {\n\t// The LLVM docs for this say that there is a val argument after the pointer.\n\t// That is a typo, and the GCC docs omit it.\n\tmask := lockAtomics()\n\tval := *ptr\n\tunlockAtomics(mask)\n\treturn val\n}\n\n//export __atomic_store_4\nfunc __atomic_store_4(ptr *uint32, val uint32, ordering uintptr) {\n\tmask := lockAtomics()\n\t*ptr = val\n\tunlockAtomics(mask)\n}\n\n//go:inline\nfunc doAtomicCAS32(ptr *uint32, expected, desired uint32) uint32 {\n\tmask := lockAtomics()\n\told := *ptr\n\tif old == expected {\n\t\t*ptr = desired\n\t}\n\tunlockAtomics(mask)\n\treturn old\n}\n\n//export __sync_val_compare_and_swap_4\nfunc __sync_val_compare_and_swap_4(ptr *uint32, expected, desired uint32) uint32 {\n\treturn doAtomicCAS32(ptr, expected, desired)\n}\n\n//export __atomic_compare_exchange_4\nfunc __atomic_compare_exchange_4(ptr, expected *uint32, desired uint32, successOrder, failureOrder uintptr) bool {\n\texp := *expected\n\told := doAtomicCAS32(ptr, exp, desired)\n\treturn old == exp\n}\n\n//go:inline\nfunc doAtomicSwap32(ptr *uint32, new uint32) uint32 {\n\tmask := lockAtomics()\n\told := *ptr\n\t*ptr = new\n\tunlockAtomics(mask)\n\treturn old\n}\n\n//export __sync_lock_test_and_set_4\nfunc __sync_lock_test_and_set_4(ptr *uint32, new uint32) uint32 {\n\treturn doAtomicSwap32(ptr, new)\n}\n\n//export __atomic_exchange_4\nfunc __atomic_exchange_4(ptr *uint32, new uint32, ordering uintptr) uint32 {\n\treturn doAtomicSwap32(ptr, new)\n}\n\n//go:inline\nfunc doAtomicAdd32(ptr *uint32, value uint32) (old, new uint32) {\n\tmask := lockAtomics()\n\told = *ptr\n\tnew = old + value\n\t*ptr = new\n\tunlockAtomics(mask)\n\treturn old, new\n}\n\n//export __atomic_fetch_add_4\nfunc __atomic_fetch_add_4(ptr *uint32, value uint32, ordering uintptr) uint32 {\n\told, _ := doAtomicAdd32(ptr, value)\n\treturn old\n}\n\n//export __sync_fetch_and_add_4\nfunc __sync_fetch_and_add_4(ptr *uint32, value uint32) uint32 {\n\told, _ := doAtomicAdd32(ptr, value)\n\treturn old\n}\n\n//export __atomic_add_fetch_4\nfunc __atomic_add_fetch_4(ptr *uint32, value uint32, ordering uintptr) uint32 {\n\t_, new := doAtomicAdd32(ptr, value)\n\treturn new\n}\n\n// 64-bit atomics.\n\n//export __atomic_load_8\nfunc __atomic_load_8(ptr *uint64, ordering uintptr) uint64 {\n\t// The LLVM docs for this say that there is a val argument after the pointer.\n\t// That is a typo, and the GCC docs omit it.\n\tmask := lockAtomics()\n\tval := *ptr\n\tunlockAtomics(mask)\n\treturn val\n}\n\n//export __atomic_store_8\nfunc __atomic_store_8(ptr *uint64, val uint64, ordering uintptr) {\n\tmask := lockAtomics()\n\t*ptr = val\n\tunlockAtomics(mask)\n}\n\n//go:inline\nfunc doAtomicCAS64(ptr *uint64, expected, desired uint64) uint64 {\n\tmask := lockAtomics()\n\told := *ptr\n\tif old == expected {\n\t\t*ptr = desired\n\t}\n\tunlockAtomics(mask)\n\treturn old\n}\n\n//export __sync_val_compare_and_swap_8\nfunc __sync_val_compare_and_swap_8(ptr *uint64, expected, desired uint64) uint64 {\n\treturn doAtomicCAS64(ptr, expected, desired)\n}\n\n//export __atomic_compare_exchange_8\nfunc __atomic_compare_exchange_8(ptr, expected *uint64, desired uint64, successOrder, failureOrder uintptr) bool {\n\texp := *expected\n\told := doAtomicCAS64(ptr, exp, desired)\n\treturn old == exp\n}\n\n//go:inline\nfunc doAtomicSwap64(ptr *uint64, new uint64) uint64 {\n\tmask := lockAtomics()\n\told := *ptr\n\t*ptr = new\n\tunlockAtomics(mask)\n\treturn old\n}\n\n//export __sync_lock_test_and_set_8\nfunc __sync_lock_test_and_set_8(ptr *uint64, new uint64) uint64 {\n\treturn doAtomicSwap64(ptr, new)\n}\n\n//export __atomic_exchange_8\nfunc __atomic_exchange_8(ptr *uint64, new uint64, ordering uintptr) uint64 {\n\treturn doAtomicSwap64(ptr, new)\n}\n\n//go:inline\nfunc doAtomicAdd64(ptr *uint64, value uint64) (old, new uint64) {\n\tmask := lockAtomics()\n\told = *ptr\n\tnew = old + value\n\t*ptr = new\n\tunlockAtomics(mask)\n\treturn old, new\n}\n\n//export __atomic_fetch_add_8\nfunc __atomic_fetch_add_8(ptr *uint64, value uint64, ordering uintptr) uint64 {\n\told, _ := doAtomicAdd64(ptr, value)\n\treturn old\n}\n\n//export __sync_fetch_and_add_8\nfunc __sync_fetch_and_add_8(ptr *uint64, value uint64) uint64 {\n\told, _ := doAtomicAdd64(ptr, value)\n\treturn old\n}\n\n//export __atomic_add_fetch_8\nfunc __atomic_add_fetch_8(ptr *uint64, value uint64, ordering uintptr) uint64 {\n\t_, new := doAtomicAdd64(ptr, value)\n\treturn new\n}\n"
  },
  {
    "path": "src/runtime/baremetal.go",
    "content": "//go:build baremetal\n\npackage runtime\n\nimport (\n\t\"unsafe\"\n)\n\n//go:extern _heap_start\nvar heapStartSymbol [0]byte\n\n//go:extern _heap_end\nvar heapEndSymbol [0]byte\n\n//go:extern _globals_start\nvar globalsStartSymbol [0]byte\n\n//go:extern _globals_end\nvar globalsEndSymbol [0]byte\n\n//go:extern _stack_top\nvar stackTopSymbol [0]byte\n\nvar (\n\theapStart    = uintptr(unsafe.Pointer(&heapStartSymbol))\n\theapEnd      = uintptr(unsafe.Pointer(&heapEndSymbol))\n\tglobalsStart = uintptr(unsafe.Pointer(&globalsStartSymbol))\n\tglobalsEnd   = uintptr(unsafe.Pointer(&globalsEndSymbol))\n\tstackTop     = uintptr(unsafe.Pointer(&stackTopSymbol))\n)\n\n// growHeap tries to grow the heap size. It returns true if it succeeds, false\n// otherwise.\nfunc growHeap() bool {\n\t// On baremetal, there is no way the heap can be grown.\n\treturn false\n}\n\n//export malloc\nfunc libc_malloc(size uintptr) unsafe.Pointer {\n\t// Note: this zeroes the returned buffer which is not necessary.\n\t// The same goes for bytealg.MakeNoZero.\n\treturn alloc(size, nil)\n}\n\n//export calloc\nfunc libc_calloc(nmemb, size uintptr) unsafe.Pointer {\n\t// No difference between calloc and malloc.\n\treturn libc_malloc(nmemb * size)\n}\n\n//export free\nfunc libc_free(ptr unsafe.Pointer) {\n\tfree(ptr)\n}\n\n//export runtime_putchar\nfunc runtime_putchar(c byte) {\n\tputchar(c)\n}\n\n//go:linkname syscall_Exit syscall.Exit\nfunc syscall_Exit(code int) {\n\texit(code)\n}\n\nconst baremetal = true\n\n// timeOffset is how long the monotonic clock started after the Unix epoch. It\n// should be a positive integer under normal operation or zero when it has not\n// been set.\nvar timeOffset int64\n\n//go:linkname now time.now\nfunc now() (sec int64, nsec int32, mono int64) {\n\tmono = nanotime()\n\tsec = (mono + timeOffset) / (1000 * 1000 * 1000)\n\tnsec = int32((mono + timeOffset) - sec*(1000*1000*1000))\n\treturn\n}\n\n// AdjustTimeOffset adds the given offset to the built-in time offset. A\n// positive value adds to the time (skipping some time), a negative value moves\n// the clock into the past.\nfunc AdjustTimeOffset(offset int64) {\n\t// TODO: do this atomically?\n\ttimeOffset += offset\n}\n\n// Picolibc is not configured to define its own errno value, instead it calls\n// __errno_location.\n// TODO: a global works well enough for now (same as errno on Linux with\n// -scheduler=tasks), but this should ideally be a thread-local variable stored\n// in task.Task.\n// Especially when we add multicore support for microcontrollers.\nvar errno int32\n\n//export __errno_location\nfunc libc_errno_location() *int32 {\n\treturn &errno\n}\n"
  },
  {
    "path": "src/runtime/build_asserts.go",
    "content": "//go:build runtime_asserts\n\npackage runtime\n\n// enable assertions for the garbage collector\nconst gcAsserts = true\n\n// enable asserts for the scheduler\nconst schedulerAsserts = true\n"
  },
  {
    "path": "src/runtime/build_noasserts.go",
    "content": "//go:build !runtime_asserts\n\npackage runtime\n\n// disable assertions for the garbage collector\nconst gcAsserts = false\n\n// disable assertions for the scheduler\nconst schedulerAsserts = false\n"
  },
  {
    "path": "src/runtime/cgo/cgo.go",
    "content": "package cgo\n\n// dummy\n"
  },
  {
    "path": "src/runtime/chan.go",
    "content": "package runtime\n\n// This file implements the 'chan' type and send/receive/select operations.\n//\n// Every channel has a list of senders and a list of receivers, and possibly a\n// queue. There is no 'channel state', the state is inferred from the available\n// senders/receivers and values in the buffer.\n//\n// - A sender will first try to send the value to a waiting receiver if there is\n//   one, but only if there is nothing in the queue (to keep the values flowing\n//   in the correct order). If it can't, it will add the value in the queue and\n//   possibly wait as a sender if there's no space available.\n// - A receiver will first try to read a value from the queue, but if there is\n//   none it will try to read from a sender in the list. It will block if it\n//   can't proceed.\n//\n// State is kept in various ways:\n//\n// - The sender value is stored in the sender 'channelOp', which is really a\n//   queue entry. This works for both senders and select operations: a select\n//   operation has a separate value to send for each case.\n// - The receiver value is stored inside Task.Ptr. This works for receivers, and\n//   importantly also works for select which has a single buffer for every\n//   receive operation.\n// - The `Task.Data` value stores how the channel operation proceeded. For\n//   normal send/receive operations, it starts at chanOperationWaiting and then\n//   is changed to chanOperationOk or chanOperationClosed depending on whether\n//   the send/receive proceeded normally or because it was closed. For a select\n//   operation, it also stores the 'case' index in the upper bits (zero for\n//   non-select operations) so that the select operation knows which case did\n//   proceed.\n//   The value is at the same time also a way that goroutines can be the first\n//   (and only) goroutine to 'take' a channel operation using an atomic CAS\n//   operation to change it from 'waiting' to any other value. This is important\n//   for the select statement because multiple goroutines could try to let\n//   different channels in the select statement proceed at the same time. By\n//   using Task.Data, only a single channel operation in the select statement\n//   can proceed.\n// - It is possible for the channel queues to contain already-processed senders\n//   or receivers. This can happen when the select statement managed to proceed\n//   but the goroutine doing the select has not yet cleaned up the stale queue\n//   entries before returning. This should therefore only happen for a short\n//   period.\n\nimport (\n\t\"internal/task\"\n\t\"runtime/interrupt\"\n\t\"unsafe\"\n)\n\n// The runtime implementation of the Go 'chan' type.\ntype channel struct {\n\tclosed       bool\n\tselectLocked bool\n\telementSize  uintptr\n\tbufCap       uintptr // 'cap'\n\tbufLen       uintptr // 'len'\n\tbufHead      uintptr\n\tbufTail      uintptr\n\tsenders      chanQueue\n\treceivers    chanQueue\n\tlock         task.PMutex\n\tbuf          unsafe.Pointer\n}\n\nconst (\n\tchanOperationWaiting = 0b00 // waiting for a send/receive operation to continue\n\tchanOperationOk      = 0b01 // successfully sent or received (not closed)\n\tchanOperationClosed  = 0b10 // channel was closed, the value has been zeroed\n\tchanOperationMask    = 0b11\n)\n\ntype chanQueue struct {\n\tfirst *channelOp\n}\n\n// Pus the next channel operation to the queue. All appropriate fields must have\n// been initialized already.\n// This function must be called with interrupts disabled and the channel lock\n// held.\nfunc (q *chanQueue) push(node *channelOp) {\n\tnode.next = q.first\n\tq.first = node\n}\n\n// Pop the next waiting channel from the queue. Channels that are no longer\n// waiting (for example, when they're part of a select operation) will be\n// skipped.\n// This function must be called with interrupts disabled.\nfunc (q *chanQueue) pop(chanOp uint32) *channelOp {\n\tfor {\n\t\tif q.first == nil {\n\t\t\treturn nil\n\t\t}\n\n\t\t// Pop next from the queue.\n\t\tpopped := q.first\n\t\tq.first = q.first.next\n\n\t\t// The new value for the 'data' field will be a combination of the\n\t\t// channel operation and the select index. (The select index is 0 for\n\t\t// non-select channel operations).\n\t\tnewDataValue := chanOp | popped.index<<2\n\n\t\t// Try to be the first to proceed with this goroutine.\n\t\tswapped := popped.task.DataAtomicUint32().CompareAndSwap(0, newDataValue)\n\t\tif swapped {\n\t\t\treturn popped\n\t\t}\n\t}\n}\n\n// Remove the given to-be-removed node from the queue if it is part of the\n// queue. If there are multiple, only one will be removed.\n// This function must be called with interrupts disabled and the channel lock\n// held.\nfunc (q *chanQueue) remove(remove *channelOp) {\n\tn := &q.first\n\tfor *n != nil {\n\t\tif *n == remove {\n\t\t\t*n = (*n).next\n\t\t\treturn\n\t\t}\n\t\tn = &((*n).next)\n\t}\n}\n\ntype channelOp struct {\n\tnext  *channelOp\n\ttask  *task.Task\n\tindex uint32         // select index, 0 for non-select operation\n\tvalue unsafe.Pointer // if this is a sender, this is the value to send\n}\n\ntype chanSelectState struct {\n\tch    *channel\n\tvalue unsafe.Pointer\n}\n\nfunc chanMake(elementSize uintptr, bufSize uintptr) *channel {\n\treturn &channel{\n\t\telementSize: elementSize,\n\t\tbufCap:      bufSize,\n\t\tbuf:         alloc(elementSize*bufSize, nil),\n\t}\n}\n\n// Return the number of entries in this chan, called from the len builtin.\n// A nil chan is defined as having length 0.\nfunc chanLen(c *channel) int {\n\tif c == nil {\n\t\treturn 0\n\t}\n\treturn int(c.bufLen)\n}\n\n// Return the capacity of this chan, called from the cap builtin.\n// A nil chan is defined as having capacity 0.\nfunc chanCap(c *channel) int {\n\tif c == nil {\n\t\treturn 0\n\t}\n\treturn int(c.bufCap)\n}\n\n// Push the value to the channel buffer array, for a send operation.\n// This function may only be called when interrupts are disabled, the channel is\n// locked and it is known there is space available in the buffer.\nfunc (ch *channel) bufferPush(value unsafe.Pointer) {\n\telemAddr := unsafe.Add(ch.buf, ch.bufHead*ch.elementSize)\n\tch.bufLen++\n\tch.bufHead++\n\tif ch.bufHead == ch.bufCap {\n\t\tch.bufHead = 0\n\t}\n\n\tmemcpy(elemAddr, value, ch.elementSize)\n}\n\n// Pop a value from the channel buffer and store it in the 'value' pointer, for\n// a receive operation.\n// This function may only be called when interrupts are disabled, the channel is\n// locked and it is known there is at least one value available in the buffer.\nfunc (ch *channel) bufferPop(value unsafe.Pointer) {\n\telemAddr := unsafe.Add(ch.buf, ch.bufTail*ch.elementSize)\n\tch.bufLen--\n\tch.bufTail++\n\tif ch.bufTail == ch.bufCap {\n\t\tch.bufTail = 0\n\t}\n\n\tmemcpy(value, elemAddr, ch.elementSize)\n\n\t// Zero the value to allow the GC to collect it.\n\tmemzero(elemAddr, ch.elementSize)\n}\n\n// Try to proceed with this send operation without blocking, and return whether\n// the send succeeded. Interrupts must be disabled and the lock must be held\n// when calling this function.\nfunc (ch *channel) trySend(value unsafe.Pointer) bool {\n\t// To make sure we send values in the correct order, we can only send\n\t// directly to a receiver when there are no values in the buffer.\n\n\t// Do not allow sending on a closed channel.\n\tif ch.closed {\n\t\t// Note: we cannot currently recover from this panic.\n\t\t// There's some state in the select statement especially that would be\n\t\t// corrupted if we allowed recovering from this panic.\n\t\truntimePanic(\"send on closed channel\")\n\t}\n\n\t// There is no value in the buffer and we have a receiver available. Copy\n\t// the value directly into the receiver.\n\tif ch.bufLen == 0 {\n\t\tif receiver := ch.receivers.pop(chanOperationOk); receiver != nil {\n\t\t\tmemcpy(receiver.task.Ptr, value, ch.elementSize)\n\t\t\tscheduleTask(receiver.task)\n\t\t\treturn true\n\t\t}\n\t}\n\n\t// If there is space in the buffer (if this is a buffered channel), we can\n\t// store the value in the buffer and continue.\n\tif ch.bufLen < ch.bufCap {\n\t\tch.bufferPush(value)\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunc chanSend(ch *channel, value unsafe.Pointer, op *channelOp) {\n\tif ch == nil {\n\t\t// A nil channel blocks forever. Do not schedule this goroutine again.\n\t\tdeadlock()\n\t}\n\n\tmask := interrupt.Disable()\n\tch.lock.Lock()\n\n\t// See whether we can proceed immediately, and if so, return early.\n\tif ch.trySend(value) {\n\t\tch.lock.Unlock()\n\t\tinterrupt.Restore(mask)\n\t\treturn\n\t}\n\n\t// Can't proceed. Add us to the list of senders and wait until we're awoken.\n\tt := task.Current()\n\tt.SetDataUint32(chanOperationWaiting)\n\top.task = t\n\top.index = 0\n\top.value = value\n\tch.senders.push(op)\n\tch.lock.Unlock()\n\tinterrupt.Restore(mask)\n\n\t// Wait until this goroutine is resumed.\n\t// It might be resumed after Unlock() and before Pause(). In that case,\n\t// because we use semaphores, the Pause() will continue immediately.\n\ttask.Pause()\n\n\t// Check whether the sent happened normally (not because the channel was\n\t// closed while sending).\n\tif t.DataUint32() == chanOperationClosed {\n\t\t// Oops, this channel was closed while sending!\n\t\truntimePanic(\"send on closed channel\")\n\t}\n}\n\n// Try to proceed with this receive operation without blocking, and return\n// whether the receive operation succeeded. Interrupts must be disabled and the\n// lock must be held when calling this function.\nfunc (ch *channel) tryRecv(value unsafe.Pointer) (received, ok bool) {\n\t// To make sure we keep the values in the channel in the correct order, we\n\t// first have to read values from the buffer before we can look at the\n\t// senders.\n\n\t// If there is a value available in the buffer, we can pull it out and\n\t// proceed immediately.\n\tif ch.bufLen > 0 {\n\t\tch.bufferPop(value)\n\n\t\t// Check for the next sender available and push it to the buffer.\n\t\tif sender := ch.senders.pop(chanOperationOk); sender != nil {\n\t\t\tch.bufferPush(sender.value)\n\t\t\tscheduleTask(sender.task)\n\t\t}\n\n\t\treturn true, true\n\t}\n\n\tif ch.closed {\n\t\t// Channel is closed, so proceed immediately.\n\t\tmemzero(value, ch.elementSize)\n\t\treturn true, false\n\t}\n\n\t// If there is a sender, we can proceed with the channel operation\n\t// immediately.\n\tif sender := ch.senders.pop(chanOperationOk); sender != nil {\n\t\tmemcpy(value, sender.value, ch.elementSize)\n\t\tscheduleTask(sender.task)\n\t\treturn true, true\n\t}\n\n\treturn false, false\n}\n\nfunc chanRecv(ch *channel, value unsafe.Pointer, op *channelOp) bool {\n\tif ch == nil {\n\t\t// A nil channel blocks forever. Do not schedule this goroutine again.\n\t\tdeadlock()\n\t}\n\n\tmask := interrupt.Disable()\n\tch.lock.Lock()\n\n\tif received, ok := ch.tryRecv(value); received {\n\t\tch.lock.Unlock()\n\t\tinterrupt.Restore(mask)\n\t\treturn ok\n\t}\n\n\t// We can't proceed, so we add ourselves to the list of receivers and wait\n\t// until we're awoken.\n\tt := task.Current()\n\tt.Ptr = value\n\tt.SetDataUint32(chanOperationWaiting)\n\top.task = t\n\top.index = 0\n\tch.receivers.push(op)\n\tch.lock.Unlock()\n\tinterrupt.Restore(mask)\n\n\t// Wait until the goroutine is resumed.\n\ttask.Pause()\n\n\t// Return whether the receive happened from a closed channel.\n\treturn t.DataUint32() != chanOperationClosed\n}\n\n// chanClose closes the given channel. If this channel has a receiver or is\n// empty, it closes the channel. Else, it panics.\nfunc chanClose(ch *channel) {\n\tif ch == nil {\n\t\t// Not allowed by the language spec.\n\t\truntimePanic(\"close of nil channel\")\n\t}\n\n\tmask := interrupt.Disable()\n\tch.lock.Lock()\n\n\tif ch.closed {\n\t\t// Not allowed by the language spec.\n\t\tch.lock.Unlock()\n\t\tinterrupt.Restore(mask)\n\t\truntimePanic(\"close of closed channel\")\n\t}\n\n\t// Proceed all receiving operations that are blocked.\n\tfor {\n\t\treceiver := ch.receivers.pop(chanOperationClosed)\n\t\tif receiver == nil {\n\t\t\t// Processed all receivers.\n\t\t\tbreak\n\t\t}\n\n\t\t// Zero the value that the receiver is getting.\n\t\tmemzero(receiver.task.Ptr, ch.elementSize)\n\n\t\t// Wake up the receiving goroutine.\n\t\tscheduleTask(receiver.task)\n\t}\n\n\t// Let all senders panic.\n\tfor {\n\t\tsender := ch.senders.pop(chanOperationClosed)\n\t\tif sender == nil {\n\t\t\tbreak // processed all senders\n\t\t}\n\n\t\t// Wake up the sender.\n\t\tscheduleTask(sender.task)\n\t}\n\n\tch.closed = true\n\n\tch.lock.Unlock()\n\tinterrupt.Restore(mask)\n}\n\n// We currently use a global select lock to avoid deadlocks while locking each\n// individual channel in the select. Without this global lock, two select\n// operations that have a different order of the same channels could end up in a\n// deadlock. This global lock is inefficient if there are many select operations\n// happening in parallel, but gets the job done.\n//\n// If this becomes a performance issue, we can see how the Go runtime does this.\n// I think it does this by sorting all states by channel address and then\n// locking them in that order to avoid this deadlock.\nvar chanSelectLock task.PMutex\n\n// Lock all channels (taking care to skip duplicate channels).\nfunc lockAllStates(states []chanSelectState) {\n\tif !hasParallelism {\n\t\treturn\n\t}\n\tfor _, state := range states {\n\t\tif state.ch != nil && !state.ch.selectLocked {\n\t\t\tstate.ch.lock.Lock()\n\t\t\tstate.ch.selectLocked = true\n\t\t}\n\t}\n}\n\n// Unlock all channels (taking care to skip duplicate channels).\nfunc unlockAllStates(states []chanSelectState) {\n\tif !hasParallelism {\n\t\treturn\n\t}\n\tfor _, state := range states {\n\t\tif state.ch != nil && state.ch.selectLocked {\n\t\t\tstate.ch.lock.Unlock()\n\t\t\tstate.ch.selectLocked = false\n\t\t}\n\t}\n}\n\n// chanSelect implements blocking or non-blocking select operations.\n// The 'ops' slice must be set if (and only if) this is a blocking select.\nfunc chanSelect(recvbuf unsafe.Pointer, states []chanSelectState, ops []channelOp) (uint32, bool) {\n\tmask := interrupt.Disable()\n\n\t// Lock everything.\n\tchanSelectLock.Lock()\n\tlockAllStates(states)\n\n\tconst selectNoIndex = ^uint32(0)\n\tselectIndex := selectNoIndex\n\tselectOk := true\n\n\t// Iterate over each state, and see if it can proceed.\n\t// TODO: start from a random index.\n\tfor i, state := range states {\n\t\tif state.ch == nil {\n\t\t\t// A nil channel blocks forever, so it won't take part of the select\n\t\t\t// operation.\n\t\t\tcontinue\n\t\t}\n\n\t\tif state.value == nil { // chan receive\n\t\t\tif received, ok := state.ch.tryRecv(recvbuf); received {\n\t\t\t\tselectIndex = uint32(i)\n\t\t\t\tselectOk = ok\n\t\t\t\tbreak\n\t\t\t}\n\t\t} else { // chan send\n\t\t\tif state.ch.trySend(state.value) {\n\t\t\t\tselectIndex = uint32(i)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\t// If this select can immediately proceed, or is a non-blocking select,\n\t// return early.\n\tblocking := len(ops) != 0\n\tif selectIndex != selectNoIndex || !blocking {\n\t\tunlockAllStates(states)\n\t\tchanSelectLock.Unlock()\n\t\tinterrupt.Restore(mask)\n\t\treturn selectIndex, selectOk\n\t}\n\n\t// The select is blocking and no channel operation can proceed, so things\n\t// become more complicated.\n\t// We add ourselves as a sender/receiver to every channel, and wait for the\n\t// first one to complete. Only one will successfully complete, because\n\t// senders and receivers use a compare-and-exchange atomic operation on\n\t// t.Data so that only one will be able to \"take\" this select operation.\n\tt := task.Current()\n\tt.Ptr = recvbuf\n\tt.SetDataUint32(chanOperationWaiting)\n\tfor i, state := range states {\n\t\tif state.ch == nil {\n\t\t\tcontinue\n\t\t}\n\t\top := &ops[i]\n\t\top.task = t\n\t\top.index = uint32(i)\n\t\tif state.value == nil { // chan receive\n\t\t\tstate.ch.receivers.push(op)\n\t\t} else { // chan send\n\t\t\top.value = state.value\n\t\t\tstate.ch.senders.push(op)\n\t\t}\n\t}\n\n\t// Now we wait until one of the send/receive operations can proceed.\n\tunlockAllStates(states)\n\tchanSelectLock.Unlock()\n\tinterrupt.Restore(mask)\n\ttask.Pause()\n\n\t// Resumed, so one channel operation must have progressed.\n\n\t// Make sure all channel ops are removed from the senders/receivers\n\t// queue before we return and the memory of them becomes invalid.\n\tchanSelectLock.Lock()\n\tlockAllStates(states)\n\tfor i, state := range states {\n\t\tif state.ch == nil {\n\t\t\tcontinue\n\t\t}\n\t\top := &ops[i]\n\t\tmask := interrupt.Disable()\n\t\tif state.value == nil {\n\t\t\tstate.ch.receivers.remove(op)\n\t\t} else {\n\t\t\tstate.ch.senders.remove(op)\n\t\t}\n\t\tinterrupt.Restore(mask)\n\t}\n\tunlockAllStates(states)\n\tchanSelectLock.Unlock()\n\n\t// Pull the return values out of t.Data (which contains two bitfields).\n\tselectIndex = t.DataUint32() >> 2\n\tselectOk = t.DataUint32()&chanOperationMask != chanOperationClosed\n\n\treturn selectIndex, selectOk\n}\n"
  },
  {
    "path": "src/runtime/complex.go",
    "content": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage runtime\n\n// inf2one returns a signed 1 if f is an infinity and a signed 0 otherwise.\n// The sign of the result is the sign of f.\nfunc inf2one(f float64) float64 {\n\tg := 0.0\n\tif isInf(f) {\n\t\tg = 1.0\n\t}\n\treturn copysign(g, f)\n}\n\nfunc complex64div(n complex64, m complex64) complex64 {\n\treturn complex64(complex128div(complex128(n), complex128(m)))\n}\n\nfunc complex128div(n complex128, m complex128) complex128 {\n\tvar e, f float64 // complex(e, f) = n/m\n\n\t// Algorithm for robust complex division as described in\n\t// Robert L. Smith: Algorithm 116: Complex division. Commun. ACM 5(8): 435 (1962).\n\tif abs(real(m)) >= abs(imag(m)) {\n\t\tratio := imag(m) / real(m)\n\t\tdenom := real(m) + ratio*imag(m)\n\t\te = (real(n) + imag(n)*ratio) / denom\n\t\tf = (imag(n) - real(n)*ratio) / denom\n\t} else {\n\t\tratio := real(m) / imag(m)\n\t\tdenom := imag(m) + ratio*real(m)\n\t\te = (real(n)*ratio + imag(n)) / denom\n\t\tf = (imag(n)*ratio - real(n)) / denom\n\t}\n\n\tif isNaN(e) && isNaN(f) {\n\t\t// Correct final result to infinities and zeros if applicable.\n\t\t// Matches C99: ISO/IEC 9899:1999 - G.5.1  Multiplicative operators.\n\n\t\ta, b := real(n), imag(n)\n\t\tc, d := real(m), imag(m)\n\n\t\tswitch {\n\t\tcase m == 0 && (!isNaN(a) || !isNaN(b)):\n\t\t\te = copysign(inf, c) * a\n\t\t\tf = copysign(inf, c) * b\n\n\t\tcase (isInf(a) || isInf(b)) && isFinite(c) && isFinite(d):\n\t\t\ta = inf2one(a)\n\t\t\tb = inf2one(b)\n\t\t\te = inf * (a*c + b*d)\n\t\t\tf = inf * (b*c - a*d)\n\n\t\tcase (isInf(c) || isInf(d)) && isFinite(a) && isFinite(b):\n\t\t\tc = inf2one(c)\n\t\t\td = inf2one(d)\n\t\t\te = 0 * (a*c + b*d)\n\t\t\tf = 0 * (b*c - a*d)\n\t\t}\n\t}\n\n\treturn complex(e, f)\n}\n"
  },
  {
    "path": "src/runtime/coro.go",
    "content": "package runtime\n\n// A naive implementation of coroutines that supports\n// package iter.\n\ntype coro struct {\n\tf  func(*coro)\n\tch chan struct{}\n}\n\n//go:linkname newcoro\n\nfunc newcoro(f func(*coro)) *coro {\n\tc := &coro{\n\t\tch: make(chan struct{}),\n\t\tf:  f,\n\t}\n\tgo func() {\n\t\tdefer close(c.ch)\n\t\t<-c.ch\n\t\tf(c)\n\t}()\n\treturn c\n}\n\n//go:linkname coroswitch\n\nfunc coroswitch(c *coro) {\n\tc.ch <- struct{}{}\n\t<-c.ch\n}\n"
  },
  {
    "path": "src/runtime/debug/debug.go",
    "content": "// Portions copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package debug is a very partially implemented package to allow compilation.\npackage debug\n\nimport (\n\t\"fmt\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// SetMaxStack sets the maximum amount of memory that can be used by a single\n// goroutine stack.\n//\n// Not implemented.\nfunc SetMaxStack(n int) int {\n\treturn n\n}\n\n// PrintStack prints to standard error the stack trace returned by runtime.Stack.\n//\n// Not implemented.\nfunc PrintStack() {}\n\n// Stack returns a formatted stack trace of the goroutine that calls it.\n//\n// Not implemented.\nfunc Stack() []byte {\n\treturn nil\n}\n\n// ReadBuildInfo returns the build information embedded\n// in the running binary. The information is available only\n// in binaries built with module support.\n//\n// Not implemented.\nfunc ReadBuildInfo() (info *BuildInfo, ok bool) {\n\treturn &BuildInfo{GoVersion: runtime.Compiler + runtime.Version()}, true\n}\n\n// BuildInfo represents the build information read from\n// the running binary.\ntype BuildInfo struct {\n\tGoVersion string    // version of the Go toolchain that built the binary, e.g. \"go1.19.2\"\n\tPath      string    // The main package path\n\tMain      Module    // The module containing the main package\n\tDeps      []*Module // Module dependencies\n\tSettings  []BuildSetting\n}\n\ntype BuildSetting struct {\n\t// Key and Value describe the build setting.\n\t// Key must not contain an equals sign, space, tab, or newline.\n\t// Value must not contain newlines ('\\n').\n\tKey, Value string\n}\n\n// Module represents a module.\ntype Module struct {\n\tPath    string  // module path\n\tVersion string  // module version\n\tSum     string  // checksum\n\tReplace *Module // replaced by this module\n}\n\n// Not implemented.\nfunc SetGCPercent(n int) int {\n\treturn n\n}\n\n// Start of stolen from big go. TODO: import/reuse without copy pasta.\n\n// quoteKey reports whether key is required to be quoted.\nfunc quoteKey(key string) bool {\n\treturn len(key) == 0 || strings.ContainsAny(key, \"= \\t\\r\\n\\\"`\")\n}\n\n// quoteValue reports whether value is required to be quoted.\nfunc quoteValue(value string) bool {\n\treturn strings.ContainsAny(value, \" \\t\\r\\n\\\"`\")\n}\n\nfunc (bi *BuildInfo) String() string {\n\tbuf := new(strings.Builder)\n\tif bi.GoVersion != \"\" {\n\t\tfmt.Fprintf(buf, \"go\\t%s\\n\", bi.GoVersion)\n\t}\n\tif bi.Path != \"\" {\n\t\tfmt.Fprintf(buf, \"path\\t%s\\n\", bi.Path)\n\t}\n\tvar formatMod func(string, Module)\n\tformatMod = func(word string, m Module) {\n\t\tbuf.WriteString(word)\n\t\tbuf.WriteByte('\\t')\n\t\tbuf.WriteString(m.Path)\n\t\tbuf.WriteByte('\\t')\n\t\tbuf.WriteString(m.Version)\n\t\tif m.Replace == nil {\n\t\t\tbuf.WriteByte('\\t')\n\t\t\tbuf.WriteString(m.Sum)\n\t\t} else {\n\t\t\tbuf.WriteByte('\\n')\n\t\t\tformatMod(\"=>\", *m.Replace)\n\t\t}\n\t\tbuf.WriteByte('\\n')\n\t}\n\tif bi.Main != (Module{}) {\n\t\tformatMod(\"mod\", bi.Main)\n\t}\n\tfor _, dep := range bi.Deps {\n\t\tformatMod(\"dep\", *dep)\n\t}\n\tfor _, s := range bi.Settings {\n\t\tkey := s.Key\n\t\tif quoteKey(key) {\n\t\t\tkey = strconv.Quote(key)\n\t\t}\n\t\tvalue := s.Value\n\t\tif quoteValue(value) {\n\t\t\tvalue = strconv.Quote(value)\n\t\t}\n\t\tfmt.Fprintf(buf, \"build\\t%s=%s\\n\", key, value)\n\t}\n\n\treturn buf.String()\n}\n"
  },
  {
    "path": "src/runtime/debug/garbage.go",
    "content": "// Package debug is a very partially implemented package to allow compilation.\npackage debug\n\nimport (\n\t\"time\"\n)\n\ntype GCStats struct {\n\tLastGC         time.Time\n\tNumGC          int64\n\tPauseTotal     time.Duration\n\tPause          []time.Duration\n\tPauseEnd       []time.Time\n\tPauseQuantiles []time.Duration\n}\n\nfunc ReadGCStats(stats *GCStats) {\n}\n\nfunc FreeOSMemory() {\n}\n\nfunc SetMaxThreads(threads int) int {\n\treturn threads\n}\n\nfunc SetPanicOnFault(enabled bool) bool {\n\treturn enabled\n}\n\nfunc WriteHeapDump(fd uintptr)\n\nfunc SetTraceback(level string)\n\nfunc SetMemoryLimit(limit int64) int64 {\n\treturn limit\n}\n"
  },
  {
    "path": "src/runtime/debug.go",
    "content": "package runtime\n\n// Stub for NumCgoCall, does not return the real value\nfunc NumCgoCall() int {\n\treturn 0\n}\n\n// Stub for NumGoroutine, does not return the real value\nfunc NumGoroutine() int {\n\treturn 1\n}\n\n// Stub for Breakpoint, does not do anything.\nfunc Breakpoint() {\n\tpanic(\"Breakpoint not supported\")\n}\n"
  },
  {
    "path": "src/runtime/defer.go",
    "content": "package runtime\n\n// Some helper types for the defer statement.\n// See compiler/defer.go for details.\n\ntype _defer struct {\n\tcallback uintptr // callback number\n\tnext     *_defer\n}\n"
  },
  {
    "path": "src/runtime/dynamic_arm64.go",
    "content": "package runtime\n\nimport (\n\t\"unsafe\"\n)\n\nconst debugLoader = false\n\nconst (\n\trAARCH64_RELATIVE = 1027\n\tdtNULL            = 0 /* Terminating entry. */\n\tdtRELA            = 7 /* Address of ElfNN_Rela relocations. */\n\tdtRELASZ          = 8 /* Total size of ElfNN_Rela relocations. */\n)\n\n/* ELF64 relocations that need an addend field. */\ntype rela64 struct {\n\tOff    uint64 /* Location to be relocated. */\n\tInfo   uint64 /* Relocation type and symbol index. */\n\tAddend int64  /* Addend. */\n}\n\n// ELF64 Dynamic structure. The \".dynamic\" section contains an array of them.\ntype dyn64 struct {\n\tTag int64  /* Entry type. */\n\tVal uint64 /* Integer/address value */\n}\n\n//export __dynamic_loader\nfunc dynamicLoader(base uintptr, dyn *dyn64) {\n\tvar rela *rela64\n\trelasz := uint64(0)\n\n\tif debugLoader {\n\t\tprintln(\"ASLR Base: \", base)\n\t}\n\n\tfor dyn.Tag != dtNULL {\n\t\tswitch dyn.Tag {\n\t\tcase dtRELA:\n\t\t\trela = (*rela64)(unsafe.Pointer(base + uintptr(dyn.Val)))\n\t\tcase dtRELASZ:\n\t\t\trelasz = uint64(dyn.Val) / uint64(unsafe.Sizeof(rela64{}))\n\t\t}\n\n\t\tptr := unsafe.Pointer(dyn)\n\t\tptr = unsafe.Add(ptr, unsafe.Sizeof(dyn64{}))\n\t\tdyn = (*dyn64)(ptr)\n\t}\n\n\tif rela == nil {\n\t\truntimePanic(\"bad reloc\")\n\t}\n\n\tif debugLoader {\n\t\tprintln(\"Sections to load: \", relasz)\n\t}\n\n\tfor relasz > 0 && rela != nil {\n\t\tswitch rela.Info {\n\t\tcase rAARCH64_RELATIVE:\n\t\t\tif debugLoader {\n\t\t\t\tprintln(\"relocating \", uintptr(rela.Addend), \" to \", base+uintptr(rela.Addend))\n\t\t\t}\n\t\t\tptr := (*uint64)(unsafe.Pointer(base + uintptr(rela.Off)))\n\t\t\t*ptr = uint64(base + uintptr(rela.Addend))\n\t\tdefault:\n\t\t\tif debugLoader {\n\t\t\t\tprintln(\"unknown section to load:\", rela.Info)\n\t\t\t}\n\t\t}\n\n\t\trptr := unsafe.Pointer(rela)\n\t\trptr = unsafe.Add(rptr, unsafe.Sizeof(rela64{}))\n\t\trela = (*rela64)(rptr)\n\t\trelasz--\n\t}\n}\n"
  },
  {
    "path": "src/runtime/env.go",
    "content": "//go:build linux || darwin || windows || wasip1\n\npackage runtime\n\n// Update the C environment if cgo is loaded.\n// Called from Go 1.20 and above.\n//\n//go:linkname syscallSetenv syscall.runtimeSetenv\nfunc syscallSetenv(key, value string) {\n\tkeydata := cstring(key)\n\tvaldata := cstring(value)\n\tsetenv(&keydata[0], &valdata[0])\n\tif key == \"GODEBUG\" && godebugUpdate != nil {\n\t\t// Starting with Go 1.20, we need to call a callback (set by\n\t\t// internal/godebug) to notify the GODEBUG environment variable has\n\t\t// changed. This is necessary to get archive/zip to pass tests.\n\t\tgodebugUpdate(key, value)\n\t}\n}\n\n// Update the C environment if cgo is loaded.\n// Called from Go 1.20 and above.\n//\n//go:linkname syscallUnsetenv syscall.runtimeUnsetenv\nfunc syscallUnsetenv(key string) {\n\tkeydata := cstring(key)\n\tunsetenv(&keydata[0])\n}\n\n// Compatibility with Go 1.19 and below.\n//\n//go:linkname syscall_setenv_c syscall.setenv_c\nfunc syscall_setenv_c(key string, val string) {\n\tsyscallSetenv(key, val)\n}\n\n// Compatibility with Go 1.19 and below.\n//\n//go:linkname syscall_unsetenv_c syscall.unsetenv_c\nfunc syscall_unsetenv_c(key string) {\n\tsyscallUnsetenv(key)\n}\n\n// cstring converts a Go string to a C string.\n// borrowed from syscall\nfunc cstring(s string) []byte {\n\tdata := make([]byte, len(s)+1)\n\tcopy(data, s)\n\t// final byte should be zero from the initial allocation\n\treturn data\n}\n"
  },
  {
    "path": "src/runtime/env_unix.go",
    "content": "//go:build linux || darwin || wasip1\n\npackage runtime\n\n// int setenv(const char *name, const char *val, int replace);\n//\n//export setenv\nfunc libc_setenv(name *byte, val *byte, replace int32) int32\n\n// int unsetenv(const char *name);\n//\n//export unsetenv\nfunc libc_unsetenv(name *byte) int32\n\nfunc setenv(key, val *byte) {\n\t// ignore any errors\n\tlibc_setenv(key, val, 1)\n}\n\nfunc unsetenv(key *byte) {\n\t// ignore any errors\n\tlibc_unsetenv(key)\n}\n"
  },
  {
    "path": "src/runtime/env_windows.go",
    "content": "//go:build windows\n\npackage runtime\n\n// Set environment variable in Windows:\n//\n//\tBOOL SetEnvironmentVariableA(\n//\t    [in]           LPCSTR lpName,\n//\t    [in, optional] LPCSTR lpValue\n//\t);\n//\n//export SetEnvironmentVariableA\nfunc _SetEnvironmentVariableA(key, val *byte) bool\n\nfunc setenv(key, val *byte) {\n\t// ignore any errors\n\t_SetEnvironmentVariableA(key, val)\n}\n\nfunc unsetenv(key *byte) {\n\t// ignore any errors\n\t_SetEnvironmentVariableA(key, nil)\n}\n"
  },
  {
    "path": "src/runtime/error.go",
    "content": "package runtime\n\n// The Error interface identifies a run time error.\ntype Error interface {\n\terror\n\n\tRuntimeError()\n}\n"
  },
  {
    "path": "src/runtime/extern.go",
    "content": "package runtime\n\nfunc Callers(skip int, pc []uintptr) int {\n\treturn 0\n}\n\n// buildVersion is the Tinygo tree's version string at build time.\n//\n// This is set by the linker.\nvar buildVersion string\n\n// Version returns the Tinygo tree's version string.\n// It is the same as goenv.Version().\nfunc Version() string {\n\treturn buildVersion\n}\n"
  },
  {
    "path": "src/runtime/float.go",
    "content": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage runtime\n\nimport \"unsafe\"\n\nvar inf = float64frombits(0x7FF0000000000000)\n\n// isNaN reports whether f is an IEEE 754 “not-a-number” value.\nfunc isNaN(f float64) (is bool) {\n\t// IEEE 754 says that only NaNs satisfy f != f.\n\treturn f != f\n}\n\n// isFinite reports whether f is neither NaN nor an infinity.\nfunc isFinite(f float64) bool {\n\treturn !isNaN(f - f)\n}\n\n// isInf reports whether f is an infinity.\nfunc isInf(f float64) bool {\n\treturn !isNaN(f) && !isFinite(f)\n}\n\n// Abs returns the absolute value of x.\n//\n// Special cases are:\n//\n//\tAbs(±Inf) = +Inf\n//\tAbs(NaN) = NaN\nfunc abs(x float64) float64 {\n\tconst sign = 1 << 63\n\treturn float64frombits(float64bits(x) &^ sign)\n}\n\n// copysign returns a value with the magnitude\n// of x and the sign of y.\nfunc copysign(x, y float64) float64 {\n\tconst sign = 1 << 63\n\treturn float64frombits(float64bits(x)&^sign | float64bits(y)&sign)\n}\n\n// Float64bits returns the IEEE 754 binary representation of f.\nfunc float64bits(f float64) uint64 {\n\treturn *(*uint64)(unsafe.Pointer(&f))\n}\n\n// Float64frombits returns the floating point number corresponding\n// the IEEE 754 binary representation b.\nfunc float64frombits(b uint64) float64 {\n\treturn *(*float64)(unsafe.Pointer(&b))\n}\n"
  },
  {
    "path": "src/runtime/gc_blocks.go",
    "content": "//go:build gc.conservative || gc.precise\n\npackage runtime\n\n// This memory manager is a textbook mark/sweep implementation, heavily inspired\n// by the MicroPython garbage collector.\n//\n// The memory manager internally uses blocks of 4 pointers big (see\n// bytesPerBlock). Every allocation first rounds up to this size to align every\n// block. It will first try to find a chain of blocks that is big enough to\n// satisfy the allocation. If it finds one, it marks the first one as the \"head\"\n// and the following ones (if any) as the \"tail\" (see below). If it cannot find\n// any free space, it will perform a garbage collection cycle and try again. If\n// it still cannot find any free space, it gives up.\n//\n// Every block has some metadata, which is stored at the end of the heap.\n// The four states are \"free\", \"head\", \"tail\", and \"mark\". During normal\n// operation, there are no marked blocks. Every allocated object starts with a\n// \"head\" and is followed by \"tail\" blocks. The reason for this distinction is\n// that this way, the start and end of every object can be found easily.\n//\n// Metadata is stored in a special area at the end of the heap, in the area\n// metadataStart..heapEnd. The actual blocks are stored in\n// heapStart..metadataStart.\n//\n// More information:\n// https://aykevl.nl/2020/09/gc-tinygo\n// https://github.com/micropython/micropython/wiki/Memory-Manager\n// https://github.com/micropython/micropython/blob/master/py/gc.c\n// \"The Garbage Collection Handbook\" by Richard Jones, Antony Hosking, Eliot\n// Moss.\n\nimport (\n\t\"internal/task\"\n\t\"runtime/interrupt\"\n\t\"unsafe\"\n)\n\nconst gcDebug = false\nconst needsStaticHeap = true\n\n// Some globals + constants for the entire GC.\n\nconst (\n\twordsPerBlock      = 4 // number of pointers in an allocated block\n\tbytesPerBlock      = wordsPerBlock * unsafe.Sizeof(heapStart)\n\tstateBits          = 2 // how many bits a block state takes (see blockState type)\n\tblocksPerStateByte = 8 / stateBits\n)\n\nvar (\n\tmetadataStart unsafe.Pointer // pointer to the start of the heap metadata\n\tscanList      *objHeader     // scanList is a singly linked list of heap objects that have been marked but not scanned\n\tfreeRanges    *freeRange     // freeRanges is a linked list of free block ranges\n\tendBlock      gcBlock        // the block just past the end of the available space\n\tgcTotalAlloc  uint64         // total number of bytes allocated\n\tgcMallocs     uint64         // total number of allocations\n\tgcLock        task.PMutex    // lock to avoid race conditions on multicore systems\n)\n\n// zeroSizedAlloc is just a sentinel that gets returned when allocating 0 bytes.\nvar zeroSizedAlloc uint8\n\n// Provide some abstraction over heap blocks.\n\n// blockState stores the four states in which a block can be.\n// It holds 1 bit in each nibble.\n// When stored into a state byte, each bit in a nibble corresponds to a different block.\n// For blocks A-D, a state byte would be laid out as 0bDCBA_DCBA.\ntype blockState uint8\n\nconst (\n\tblockStateLow  blockState = 1\n\tblockStateHigh blockState = 1 << blocksPerStateByte\n\n\tblockStateFree blockState = 0\n\tblockStateHead blockState = blockStateLow\n\tblockStateTail blockState = blockStateHigh\n\tblockStateMark blockState = blockStateLow | blockStateHigh\n\tblockStateMask blockState = blockStateLow | blockStateHigh\n)\n\n// blockStateEach is a mask that can be used to extract a nibble from the block state.\nconst blockStateEach = 1<<blocksPerStateByte - 1\n\n// The byte value of a block where every block is a 'tail' block.\nconst blockStateByteAllTails = byte(blockStateTail) * blockStateEach\n\n// String returns a human-readable version of the block state, for debugging.\nfunc (s blockState) String() string {\n\tswitch s {\n\tcase blockStateFree:\n\t\treturn \"free\"\n\tcase blockStateHead:\n\t\treturn \"head\"\n\tcase blockStateTail:\n\t\treturn \"tail\"\n\tcase blockStateMark:\n\t\treturn \"mark\"\n\tdefault:\n\t\t// must never happen\n\t\treturn \"!err\"\n\t}\n}\n\n// The block number in the pool.\ntype gcBlock uintptr\n\n// blockFromAddr returns a block given an address somewhere in the heap (which\n// might not be heap-aligned).\nfunc blockFromAddr(addr uintptr) gcBlock {\n\tif gcAsserts && (addr < heapStart || addr >= uintptr(metadataStart)) {\n\t\truntimePanic(\"gc: trying to get block from invalid address\")\n\t}\n\treturn gcBlock((addr - heapStart) / bytesPerBlock)\n}\n\n// Return a pointer to the start of the allocated object.\nfunc (b gcBlock) pointer() unsafe.Pointer {\n\treturn unsafe.Pointer(b.address())\n}\n\n// Return the address of the start of the allocated object.\nfunc (b gcBlock) address() uintptr {\n\taddr := heapStart + uintptr(b)*bytesPerBlock\n\tif gcAsserts && addr > uintptr(metadataStart) {\n\t\truntimePanic(\"gc: block pointing inside metadata\")\n\t}\n\treturn addr\n}\n\n// findHead returns the head (first block) of an object, assuming the block\n// points to an allocated object. It returns the same block if this block\n// already points to the head.\nfunc (b gcBlock) findHead() gcBlock {\n\tfor {\n\t\t// Optimization: check whether the current block state byte (which\n\t\t// contains the state of multiple blocks) is composed entirely of tail\n\t\t// blocks. If so, we can skip back to the last block in the previous\n\t\t// state byte.\n\t\t// This optimization speeds up findHead for pointers that point into a\n\t\t// large allocation.\n\t\tstateByte := b.stateByte()\n\t\tif stateByte == blockStateByteAllTails {\n\t\t\tb -= (b % blocksPerStateByte) + 1\n\t\t\tcontinue\n\t\t}\n\n\t\t// Check whether we've found a non-tail block, which means we found the\n\t\t// head.\n\t\tstate := b.stateFromByte(stateByte)\n\t\tif state != blockStateTail {\n\t\t\tbreak\n\t\t}\n\t\tb--\n\t}\n\tif gcAsserts {\n\t\tif b.state() != blockStateHead && b.state() != blockStateMark {\n\t\t\truntimePanic(\"gc: found tail without head\")\n\t\t}\n\t}\n\treturn b\n}\n\n// findNext returns the first block just past the end of the tail. This may or\n// may not be the head of an object.\nfunc (b gcBlock) findNext() gcBlock {\n\tif b.state() == blockStateHead || b.state() == blockStateMark {\n\t\tb++\n\t}\n\tfor b.address() < uintptr(metadataStart) && b.state() == blockStateTail {\n\t\tb++\n\t}\n\treturn b\n}\n\nfunc (b gcBlock) stateByte() byte {\n\treturn *(*uint8)(unsafe.Add(metadataStart, b/blocksPerStateByte))\n}\n\n// Return the block state given a state byte. The state byte must have been\n// obtained using b.stateByte(), otherwise the result is incorrect.\nfunc (b gcBlock) stateFromByte(stateByte byte) blockState {\n\treturn blockState(stateByte>>(b%blocksPerStateByte)) & blockStateMask\n}\n\n// State returns the current block state.\nfunc (b gcBlock) state() blockState {\n\treturn b.stateFromByte(b.stateByte())\n}\n\n// setState sets the current block to the given state, which must contain more\n// bits than the current state. Allowed transitions: from free to any state and\n// from head to mark.\nfunc (b gcBlock) setState(newState blockState) {\n\tstateBytePtr := (*uint8)(unsafe.Add(metadataStart, b/blocksPerStateByte))\n\t*stateBytePtr |= uint8(newState << (b % blocksPerStateByte))\n\tif gcAsserts && b.state() != newState {\n\t\truntimePanic(\"gc: setState() was not successful\")\n\t}\n}\n\n// objHeader is a structure prepended to every heap object to hold metadata.\ntype objHeader struct {\n\t// next is the next object to scan after this.\n\tnext *objHeader\n\n\t// layout holds the layout bitmap used to find pointers in the object.\n\tlayout gcLayout\n}\n\n// freeRange is a node on the outer list of range lengths.\n// The free ranges are structured as two nested singly-linked lists:\n// - The outer level (freeRange) has one entry for each unique range length.\n// - The inner level (freeRangeMore) has one entry for each additional range of the same length.\n// This two-level structure ensures that insertion/removal times are proportional to the requested length.\ntype freeRange struct {\n\t// len is the length of this free range.\n\tlen uintptr\n\n\t// nextLen is the next longer free range.\n\tnextLen *freeRange\n\n\t// nextWithLen is the next free range with this length.\n\tnextWithLen *freeRangeMore\n}\n\n// freeRangeMore is a node on the inner list of equal-length ranges.\ntype freeRangeMore struct {\n\tnext *freeRangeMore\n}\n\n// insertFreeRange inserts a range of len blocks starting at ptr into the free list.\nfunc insertFreeRange(ptr unsafe.Pointer, len uintptr) {\n\tif gcAsserts && len == 0 {\n\t\truntimePanic(\"gc: insert 0-length free range\")\n\t}\n\n\t// Find the insertion point by length.\n\t// Skip until the next range is at least the target length.\n\tinsDst := &freeRanges\n\tfor *insDst != nil && (*insDst).len < len {\n\t\tinsDst = &(*insDst).nextLen\n\t}\n\n\t// Create the new free range.\n\tnext := *insDst\n\tif next != nil && next.len == len {\n\t\t// Insert into the list with this length.\n\t\tnewRange := (*freeRangeMore)(ptr)\n\t\tnewRange.next = next.nextWithLen\n\t\tnext.nextWithLen = newRange\n\t} else {\n\t\t// Insert into the list of lengths.\n\t\tnewRange := (*freeRange)(ptr)\n\t\t*newRange = freeRange{\n\t\t\tlen:         len,\n\t\t\tnextLen:     next,\n\t\t\tnextWithLen: nil,\n\t\t}\n\t\t*insDst = newRange\n\t}\n}\n\n// popFreeRange removes a range of len blocks from the freeRanges list.\n// It returns nil if there are no sufficiently long ranges.\nfunc popFreeRange(len uintptr) unsafe.Pointer {\n\tif gcAsserts && len == 0 {\n\t\truntimePanic(\"gc: pop 0-length free range\")\n\t}\n\n\t// Find the removal point by length.\n\t// Skip until the next range is at least the target length.\n\tremDst := &freeRanges\n\tfor *remDst != nil && (*remDst).len < len {\n\t\tremDst = &(*remDst).nextLen\n\t}\n\n\trangeWithLength := *remDst\n\tif rangeWithLength == nil {\n\t\t// No ranges are long enough.\n\t\treturn nil\n\t}\n\tremovedLen := rangeWithLength.len\n\n\t// Remove the range.\n\tvar ptr unsafe.Pointer\n\tif nextWithLen := rangeWithLength.nextWithLen; nextWithLen != nil {\n\t\t// Remove from the list with this length.\n\t\trangeWithLength.nextWithLen = nextWithLen.next\n\t\tptr = unsafe.Pointer(nextWithLen)\n\t} else {\n\t\t// Remove from the list of lengths.\n\t\t*remDst = rangeWithLength.nextLen\n\t\tptr = unsafe.Pointer(rangeWithLength)\n\t}\n\n\tif removedLen > len {\n\t\t// Insert the leftover range.\n\t\tinsertFreeRange(unsafe.Add(ptr, len*bytesPerBlock), removedLen-len)\n\t}\n\treturn ptr\n}\n\nfunc isOnHeap(ptr uintptr) bool {\n\treturn ptr >= heapStart && ptr < uintptr(metadataStart)\n}\n\n// Initialize the memory allocator.\n// No memory may be allocated before this is called. That means the runtime and\n// any packages the runtime depends upon may not allocate memory during package\n// initialization.\nfunc initHeap() {\n\tcalculateHeapAddresses()\n\n\t// Set all block states to 'free'.\n\tmetadataSize := heapEnd - uintptr(metadataStart)\n\tmemzero(unsafe.Pointer(metadataStart), metadataSize)\n\n\t// Rebuild the free ranges list.\n\tbuildFreeRanges()\n}\n\n// setHeapEnd is called to expand the heap. The heap can only grow, not shrink.\n// Also, the heap should grow substantially each time otherwise growing the heap\n// will be expensive.\nfunc setHeapEnd(newHeapEnd uintptr) {\n\tif gcAsserts && newHeapEnd <= heapEnd {\n\t\truntimePanic(\"gc: setHeapEnd didn't grow the heap\")\n\t}\n\n\t// Save some old variables we need later.\n\toldMetadataStart := metadataStart\n\toldMetadataSize := heapEnd - uintptr(metadataStart)\n\n\t// Increase the heap. After setting the new heapEnd, calculateHeapAddresses\n\t// will update metadataStart and the memcpy will copy the metadata to the\n\t// new location.\n\t// The new metadata will be bigger than the old metadata, but a simple\n\t// memcpy is fine as it only copies the old metadata and the new memory will\n\t// have been zero initialized.\n\theapEnd = newHeapEnd\n\tcalculateHeapAddresses()\n\tmemcpy(metadataStart, oldMetadataStart, oldMetadataSize)\n\n\t// Note: the memcpy above assumes the heap grows enough so that the new\n\t// metadata does not overlap the old metadata. If that isn't true, memmove\n\t// should be used to avoid corruption.\n\t// This assert checks whether that's true.\n\tif gcAsserts && uintptr(metadataStart) < uintptr(oldMetadataStart)+oldMetadataSize {\n\t\truntimePanic(\"gc: heap did not grow enough at once\")\n\t}\n\n\t// Rebuild the free ranges list.\n\tbuildFreeRanges()\n}\n\n// calculateHeapAddresses initializes variables such as metadataStart and\n// numBlock based on heapStart and heapEnd.\n//\n// This function can be called again when the heap size increases. The caller is\n// responsible for copying the metadata to the new location.\nfunc calculateHeapAddresses() {\n\ttotalSize := heapEnd - heapStart\n\n\t// Allocate some memory to keep 2 bits of information about every block.\n\tmetadataSize := (totalSize + blocksPerStateByte*bytesPerBlock) / (1 + blocksPerStateByte*bytesPerBlock)\n\tmetadataStart = unsafe.Pointer(heapEnd - metadataSize)\n\n\t// Use the rest of the available memory as heap.\n\tnumBlocks := (uintptr(metadataStart) - heapStart) / bytesPerBlock\n\tendBlock = gcBlock(numBlocks)\n\tif gcDebug {\n\t\tprintln(\"heapStart:        \", heapStart)\n\t\tprintln(\"heapEnd:          \", heapEnd)\n\t\tprintln(\"total size:       \", totalSize)\n\t\tprintln(\"metadata size:    \", metadataSize)\n\t\tprintln(\"metadataStart:    \", metadataStart)\n\t\tprintln(\"# of blocks:      \", numBlocks)\n\t\tprintln(\"# of block states:\", metadataSize*blocksPerStateByte)\n\t}\n\tif gcAsserts && metadataSize*blocksPerStateByte < numBlocks {\n\t\t// sanity check\n\t\truntimePanic(\"gc: metadata array is too small\")\n\t}\n}\n\n// alloc tries to find some free space on the heap, possibly doing a garbage\n// collection cycle if needed. If no space is free, it panics.\n//\n//go:noinline\nfunc alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {\n\tif size == 0 {\n\t\treturn unsafe.Pointer(&zeroSizedAlloc)\n\t}\n\n\tif interrupt.In() {\n\t\truntimePanicAt(returnAddress(0), \"heap alloc in interrupt\")\n\t}\n\n\t// Round the size up to a multiple of blocks, adding space for the header.\n\trawSize := size\n\tsize += align(unsafe.Sizeof(objHeader{}))\n\tsize += bytesPerBlock - 1\n\tif size < rawSize {\n\t\t// The size overflowed.\n\t\truntimePanicAt(returnAddress(0), \"out of memory\")\n\t}\n\tneededBlocks := size / bytesPerBlock\n\tsize = neededBlocks * bytesPerBlock\n\n\t// Make sure there are no concurrent allocations. The heap is not currently\n\t// designed for concurrent alloc/GC.\n\tgcLock.Lock()\n\n\t// Update the total allocation counters.\n\tgcTotalAlloc += uint64(rawSize)\n\tgcMallocs++\n\n\t// Acquire a range of free blocks.\n\tvar ranGC bool\n\tvar grewHeap bool\n\tvar pointer unsafe.Pointer\n\tfor {\n\t\tpointer = popFreeRange(neededBlocks)\n\t\tif pointer != nil {\n\t\t\tbreak\n\t\t}\n\n\t\tif !ranGC {\n\t\t\t// Run the collector and try again.\n\t\t\tfreeBytes := runGC()\n\t\t\tranGC = true\n\t\t\theapSize := uintptr(metadataStart) - heapStart\n\t\t\tif freeBytes < heapSize/3 {\n\t\t\t\t// Ensure there is at least 33% headroom.\n\t\t\t\t// This percentage was arbitrarily chosen, and may need to\n\t\t\t\t// be tuned in the future.\n\t\t\t\tgrowHeap()\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\tif gcDebug && !grewHeap {\n\t\t\tprintln(\"grow heap for request:\", uint(neededBlocks))\n\t\t\tdumpFreeRangeCounts()\n\t\t}\n\t\tif growHeap() {\n\t\t\tgrewHeap = true\n\t\t\tcontinue\n\t\t}\n\n\t\t// Unfortunately the heap could not be increased. This\n\t\t// happens on baremetal systems for example (where all\n\t\t// available RAM has already been dedicated to the heap).\n\t\truntimePanicAt(returnAddress(0), \"out of memory\")\n\t}\n\n\t// Set the backing blocks as being allocated.\n\tblock := blockFromAddr(uintptr(pointer))\n\tblock.setState(blockStateHead)\n\tfor i := block + 1; i != block+gcBlock(neededBlocks); i++ {\n\t\ti.setState(blockStateTail)\n\t}\n\n\t// Create the object header.\n\theader := (*objHeader)(pointer)\n\theader.layout = parseGCLayout(layout)\n\n\t// We've claimed this allocation, now we can unlock the heap.\n\tgcLock.Unlock()\n\n\t// Return a pointer to this allocation.\n\tadd := align(unsafe.Sizeof(objHeader{}))\n\tpointer = unsafe.Add(pointer, add)\n\tsize -= add\n\tmemzero(pointer, size)\n\treturn pointer\n}\n\nfunc realloc(ptr unsafe.Pointer, size uintptr) unsafe.Pointer {\n\tif ptr == nil {\n\t\treturn alloc(size, nil)\n\t}\n\n\tptrAddress := uintptr(ptr)\n\tendOfTailAddress := blockFromAddr(ptrAddress).findNext().address()\n\n\t// this might be a few bytes longer than the original size of\n\t// ptr, because we align to full blocks of size bytesPerBlock\n\toldSize := endOfTailAddress - ptrAddress\n\tif size <= oldSize {\n\t\treturn ptr\n\t}\n\n\tnewAlloc := alloc(size, nil)\n\tmemcpy(newAlloc, ptr, oldSize)\n\tfree(ptr)\n\n\treturn newAlloc\n}\n\nfunc free(ptr unsafe.Pointer) {\n\t// TODO: free blocks on request, when the compiler knows they're unused.\n}\n\n// GC performs a garbage collection cycle.\nfunc GC() {\n\tgcLock.Lock()\n\trunGC()\n\tgcLock.Unlock()\n}\n\n// runGC performs a garbage collection cycle. It is the internal implementation\n// of the runtime.GC() function. The difference is that it returns the number of\n// free bytes in the heap after the GC is finished.\nfunc runGC() (freeBytes uintptr) {\n\tif gcDebug {\n\t\tprintln(\"running collection cycle...\")\n\t}\n\n\t// Mark phase: mark all reachable objects, recursively.\n\tgcMarkReachable()\n\n\tif baremetal && hasScheduler {\n\t\t// Channel operations in interrupts may move task pointers around while we are marking.\n\t\t// Therefore we need to scan the runqueue separately.\n\t\tvar markedTaskQueue task.Queue\n\trunqueueScan:\n\t\trunqueue := schedulerRunQueue()\n\t\tfor !runqueue.Empty() {\n\t\t\t// Pop the next task off of the runqueue.\n\t\t\tt := runqueue.Pop()\n\n\t\t\t// Mark the task if it has not already been marked.\n\t\t\tmarkRoot(uintptr(unsafe.Pointer(runqueue)), uintptr(unsafe.Pointer(t)))\n\n\t\t\t// Push the task onto our temporary queue.\n\t\t\tmarkedTaskQueue.Push(t)\n\t\t}\n\n\t\tfinishMark()\n\n\t\t// Restore the runqueue.\n\t\ti := interrupt.Disable()\n\t\tif !runqueue.Empty() {\n\t\t\t// Something new came in while finishing the mark.\n\t\t\tinterrupt.Restore(i)\n\t\t\tgoto runqueueScan\n\t\t}\n\t\t*runqueue = markedTaskQueue\n\t\tinterrupt.Restore(i)\n\t} else {\n\t\tfinishMark()\n\t}\n\n\t// If we're using threads, resume all other threads before starting the\n\t// sweep.\n\tgcResumeWorld()\n\n\t// Sweep phase: free all non-marked objects and unmark marked objects for\n\t// the next collection cycle.\n\tsweep()\n\n\t// Rebuild the free ranges list.\n\tfreeBytes = buildFreeRanges()\n\n\t// Show how much has been sweeped, for debugging.\n\tif gcDebug {\n\t\tdumpHeap()\n\t}\n\n\treturn\n}\n\n// markRoots reads all pointers from start to end (exclusive) and if they look\n// like a heap pointer and are unmarked, marks them and scans that object as\n// well (recursively). The starting address must be valid and aligned.\nfunc markRoots(start, end uintptr) {\n\tif gcDebug {\n\t\tprintln(\"mark from\", start, \"to\", end, int(end-start))\n\t}\n\tif gcAsserts {\n\t\tif start >= end {\n\t\t\truntimePanic(\"gc: unexpected range to mark\")\n\t\t}\n\t\tif start%unsafe.Alignof(start) != 0 {\n\t\t\truntimePanic(\"gc: unaligned start pointer\")\n\t\t}\n\t}\n\n\t// Scan the range conservatively.\n\tscanConservative(start, end-start)\n}\n\n// scanConservative scans all possible pointer locations in a range and marks referenced heap allocations.\n// The starting address must be valid and pointer-aligned.\nfunc scanConservative(addr, len uintptr) {\n\tfor len >= unsafe.Sizeof(addr) {\n\t\troot := *(*uintptr)(unsafe.Pointer(addr))\n\t\tmarkRoot(addr, root)\n\n\t\taddr += unsafe.Alignof(addr)\n\t\tlen -= unsafe.Alignof(addr)\n\t}\n}\n\nfunc markCurrentGoroutineStack(sp uintptr) {\n\t// This could be optimized by only marking the stack area that's currently\n\t// in use.\n\tmarkRoot(0, sp)\n}\n\n// finishMark finishes the marking process by scanning all heap objects on scanList.\nfunc finishMark() {\n\tfor {\n\t\t// Remove an object from the scan list.\n\t\tobj := scanList\n\t\tif obj == nil {\n\t\t\treturn\n\t\t}\n\t\tscanList = obj.next\n\n\t\t// Check if the object may contain pointers.\n\t\tif obj.layout.pointerFree() {\n\t\t\t// This object doesn't contain any pointers.\n\t\t\t// This is a fast path for objects like make([]int, 4096).\n\t\t\t// It skips the length calculation.\n\t\t\tcontinue\n\t\t}\n\n\t\t// Compute the scan bounds.\n\t\tobjAddr := uintptr(unsafe.Pointer(obj))\n\t\tstart := objAddr + align(unsafe.Sizeof(objHeader{}))\n\t\tend := blockFromAddr(objAddr).findNext().address()\n\n\t\t// Scan the object.\n\t\tobj.layout.scan(start, end-start)\n\t}\n}\n\n// mark a GC root at the address addr.\nfunc markRoot(addr, root uintptr) {\n\t// Find the heap block corresponding to the root.\n\tif !isOnHeap(root) {\n\t\t// This is not a heap pointer.\n\t\treturn\n\t}\n\tblock := blockFromAddr(root)\n\n\t// Find the head of the corresponding object.\n\tif block.state() == blockStateFree {\n\t\t// The to-be-marked object doesn't actually exist.\n\t\t// This could either be a dangling pointer (oops!) but most likely\n\t\t// just a false positive.\n\t\treturn\n\t}\n\thead := block.findHead()\n\n\t// Mark the object.\n\tif head.state() == blockStateMark {\n\t\t// This object is already marked.\n\t\treturn\n\t}\n\tif gcDebug {\n\t\tprintln(\"found unmarked pointer\", root, \"at address\", addr)\n\t}\n\thead.setState(blockStateMark)\n\n\t// Add the object to the scan list.\n\theader := (*objHeader)(head.pointer())\n\theader.next = scanList\n\tscanList = header\n}\n\n// Sweep goes through all memory and frees unmarked memory.\nfunc sweep() {\n\tmetadataEnd := unsafe.Add(metadataStart, (endBlock+(blocksPerStateByte-1))/blocksPerStateByte)\n\tvar carry byte\n\tfor meta := metadataStart; meta != metadataEnd; meta = unsafe.Add(meta, 1) {\n\t\t// Fetch the state byte.\n\t\tstateBytePtr := (*byte)(unsafe.Pointer(meta))\n\t\tstateByte := *stateBytePtr\n\n\t\t// Separate blocks by type.\n\t\t// Split the nibbles.\n\t\t// Each nibble is a mask of blocks.\n\t\thigh := stateByte >> blocksPerStateByte\n\t\tlow := stateByte & blockStateEach\n\t\t// Marked heads are in both nibbles.\n\t\tmarkedHeads := low & high\n\t\t// Unmarked heads are in the low nibble but not the high nibble.\n\t\tunmarkedHeads := low &^ high\n\t\t// Tails are in the high nibble but not the low nibble.\n\t\ttails := high &^ low\n\n\t\t// Clear all tail runs after unmarked (freed) heads.\n\t\t//\n\t\t// Adding 1 to the start of a bit run will clear the run and set the next bit:\n\t\t//   (2^k - 1) + 1 = 2^k\n\t\t//   e.g. 0b0011 + 1 = 0b0100\n\t\t// Bitwise-and with the original mask to clear the newly set bit.\n\t\t//   e.g. (0b0011 + 1) & 0b0011 = 0b0100 & 0b0011 = 0b0000\n\t\t// This will not clear bits after the run because the gap stops the carry:\n\t\t//   e.g. (0b1011 + 1) & 0b1011 = 0b1100 & 0b1011 = 0b1000\n\t\t// This can clear multiple runs in a single addition:\n\t\t//   e.g. (0b1101 + 0b0101) & 0b1101 = 0b10010 & 0b1101 = 0b0000\n\t\t//\n\t\t// In order to find tail run starts after unmarked heads we could use tails & (unmarkedHeads << 1).\n\t\t// It is possible omit the bitwise-and because the clear still works if the next block is not a tail.\n\t\t// A head is not a tail, so corresponding missing tail bit will stop the carry from a previous tail run.\n\t\t// As such it will set the next bit which will be cleared back away later.\n\t\t// e.g. HHTH: (0b0010 + (0b1101 << 1)) & 0b0010 = 0b11100 & 0b0010 = 0b0000\n\t\t//\n\t\t// Treat the whole heap as a single pair of integer masks.\n\t\t// This is accomplished for addition by carrying the overflow to the next state byte.\n\t\t// The unmarkedHeads << 1 is equivalent to unmarkedHeads + unmarkedHeads, so it can be merged with the sum.\n\t\t// This does not require any special work for the bitwise-and because it operates bitwise.\n\t\ttailClear := tails + (unmarkedHeads << 1) + carry\n\t\tcarry = tailClear >> blocksPerStateByte\n\t\ttails &= tailClear\n\n\t\t// Construct the new state byte.\n\t\t*stateBytePtr = markedHeads | (tails << blocksPerStateByte)\n\t}\n}\n\n// buildFreeRanges rebuilds the freeRanges list.\n// This must be called after a GC sweep or heap grow.\n// It returns how many bytes are free in the heap.\nfunc buildFreeRanges() uintptr {\n\tfreeRanges = nil\n\tblock := endBlock\n\tvar totalBlocks uintptr\n\tfor {\n\t\t// Skip backwards over occupied blocks.\n\t\tfor block > 0 && (block-1).state() != blockStateFree {\n\t\t\tblock--\n\t\t}\n\t\tif block == 0 {\n\t\t\tbreak\n\t\t}\n\n\t\t// Find the start of the free range.\n\t\tend := block\n\t\tfor block > 0 && (block-1).state() == blockStateFree {\n\t\t\tblock--\n\t\t}\n\n\t\t// Insert the free range.\n\t\tlen := uintptr(end - block)\n\t\ttotalBlocks += len\n\t\tinsertFreeRange(block.pointer(), len)\n\t}\n\n\tif gcDebug {\n\t\tprintln(\"free ranges after rebuild:\")\n\t\tdumpFreeRangeCounts()\n\t}\n\n\treturn totalBlocks * bytesPerBlock\n}\n\nfunc dumpFreeRangeCounts() {\n\tfor rangeWithLength := freeRanges; rangeWithLength != nil; rangeWithLength = rangeWithLength.nextLen {\n\t\ttotalRanges := uintptr(1)\n\t\tfor nextWithLen := rangeWithLength.nextWithLen; nextWithLen != nil; nextWithLen = nextWithLen.next {\n\t\t\ttotalRanges++\n\t\t}\n\t\tprintln(\"-\", uint(rangeWithLength.len), \"x\", uint(totalRanges))\n\t}\n}\n\n// dumpHeap can be used for debugging purposes. It dumps the state of each heap\n// block to standard output.\nfunc dumpHeap() {\n\tprintln(\"heap:\")\n\tfor block := gcBlock(0); block < endBlock; block++ {\n\t\tswitch block.state() {\n\t\tcase blockStateHead:\n\t\t\tprint(\"*\")\n\t\tcase blockStateTail:\n\t\t\tprint(\"-\")\n\t\tcase blockStateMark:\n\t\t\tprint(\"#\")\n\t\tdefault: // free\n\t\t\tprint(\"·\")\n\t\t}\n\t\tif block%64 == 63 || block+1 == endBlock {\n\t\t\tprintln()\n\t\t}\n\t}\n}\n\n// ReadMemStats populates m with memory statistics.\n//\n// The returned memory statistics are up to date as of the\n// call to ReadMemStats. This would not do GC implicitly for you.\nfunc ReadMemStats(m *MemStats) {\n\tgcLock.Lock()\n\n\t// Calculate the raw size of the heap.\n\theapEnd := heapEnd\n\theapStart := heapStart\n\tm.Sys = uint64(heapEnd - heapStart)\n\tm.HeapSys = uint64(uintptr(metadataStart) - heapStart)\n\tmetadataStart := metadataStart\n\t// TODO: should GCSys include objHeaders?\n\tm.GCSys = uint64(heapEnd - uintptr(metadataStart))\n\tm.HeapReleased = 0 // always 0, we don't currently release memory back to the OS.\n\n\t// Count live heads and tails.\n\tvar liveHeads, liveTails uintptr\n\tendBlock := endBlock\n\tmetadataEnd := unsafe.Add(metadataStart, (endBlock+(blocksPerStateByte-1))/blocksPerStateByte)\n\tfor meta := metadataStart; meta != metadataEnd; meta = unsafe.Add(meta, 1) {\n\t\t// Since we are outside of a GC, nothing is marked.\n\t\t// A bit in the low nibble implies a head.\n\t\t// A bit in the high nibble implies a tail.\n\t\tstateByte := *(*byte)(unsafe.Pointer(meta))\n\t\tliveHeads += uintptr(count4LUT[stateByte&blockStateEach])\n\t\tliveTails += uintptr(count4LUT[stateByte>>blocksPerStateByte])\n\t}\n\n\t// Add heads and tails to count live blocks.\n\tliveBlocks := liveHeads + liveTails\n\tliveBytes := uint64(liveBlocks * bytesPerBlock)\n\tm.HeapInuse = liveBytes\n\tm.HeapAlloc = liveBytes\n\tm.Alloc = liveBytes\n\n\t// Subtract live blocks from total blocks to count free blocks.\n\tfreeBlocks := uintptr(endBlock) - liveBlocks\n\tm.HeapIdle = uint64(freeBlocks * bytesPerBlock)\n\n\t// Record the number of allocated objects.\n\tgcMallocs := gcMallocs\n\tm.Mallocs = gcMallocs\n\n\t// Subtract live objects from allocated objects to count freed objects.\n\tm.Frees = gcMallocs - uint64(liveHeads)\n\n\t// Record the total allocated bytes.\n\tm.TotalAlloc = gcTotalAlloc\n\n\tgcLock.Unlock()\n}\n\n// count4LUT is a lookup table used to count set bits in a 4-bit mask.\n// TODO: replace with popcnt when available\nvar count4LUT = [16]uint8{\n\t0b0000: 0,\n\t0b0001: 1,\n\t0b0010: 1,\n\t0b0011: 2,\n\t0b0100: 1,\n\t0b0101: 2,\n\t0b0110: 2,\n\t0b0111: 3,\n\t0b1000: 1,\n\t0b1001: 2,\n\t0b1010: 2,\n\t0b1011: 3,\n\t0b1100: 2,\n\t0b1101: 3,\n\t0b1110: 3,\n\t0b1111: 4,\n}\n\nfunc SetFinalizer(obj interface{}, finalizer interface{}) {\n\t// Unimplemented.\n}\n"
  },
  {
    "path": "src/runtime/gc_boehm.c",
    "content": "//go:build none\n\n// This file is included in the build on systems that support the Boehm GC,\n// despite the //go:build line above.\n\n#include <stdint.h>\n\ntypedef void (* GC_push_other_roots_proc)(void);\nvoid GC_set_push_other_roots(GC_push_other_roots_proc);\n\ntypedef void(* GC_warn_proc)(const char *msg, uintptr_t arg);\nvoid GC_set_warn_proc(GC_warn_proc p);\n\nvoid tinygo_runtime_bdwgc_callback(void);\n\nstatic void callback(void) {\n    tinygo_runtime_bdwgc_callback();\n}\n\nstatic void warn_proc(const char *msg, uintptr_t arg) {\n}\n\nvoid tinygo_runtime_bdwgc_init(void) {\n    GC_set_push_other_roots(callback);\n#if defined(__wasm__)\n    // There are a lot of warnings on WebAssembly in the form:\n    //\n    //     GC Warning: Repeated allocation of very large block (appr. size 68 KiB):\n    //         May lead to memory leak and poor performance\n    //\n    // The usual advice is to use something like GC_malloc_ignore_off_page but\n    // unfortunately for most allocations that's not allowed: Go allocations can\n    // legitimately hold pointers further than one page in the allocation. So\n    // instead we just disable the warning.\n    GC_set_warn_proc(warn_proc);\n#endif\n}\n"
  },
  {
    "path": "src/runtime/gc_boehm.go",
    "content": "//go:build gc.boehm\n\n// This is the Boehm-Demers-Weiser conservative garbage collector, integrated\n// into TinyGo.\n//\n// Note that we use a special way of dealing with threads:\n//   * All calls to the bdwgc library are serialized using locks.\n//   * When the bdwgc library wants to push GC roots, all other threads that are\n//     running are stopped.\n//   * After returning from a bdwgc library call, the caller checks whether\n//     other threads were stopped (meaning a GC cycle happened) and resumes the\n//     world.\n// This is not exactly the most efficient way to do this. We can likely speed\n// things up by using bdwgc-native wrappers for starting/stopping threads (and\n// also to resume the world while sweeping). Also, thread local allocation might\n// help. But we don't do any of these right now, it is left as a possible future\n// improvement.\n\npackage runtime\n\nimport (\n\t\"internal/gclayout\"\n\t\"internal/task\"\n\t\"unsafe\"\n)\n\nconst needsStaticHeap = false\n\n// zeroSizedAlloc is just a sentinel that gets returned when allocating 0 bytes.\nvar zeroSizedAlloc uint8\n\nvar gcLock task.PMutex\n\nfunc initHeap() {\n\tlibgc_init()\n\n\t// Call GC_set_push_other_roots(gcCallback) in C because of function\n\t// signature differences that do matter in WebAssembly.\n\tgcInit()\n}\n\n//export tinygo_runtime_bdwgc_init\nfunc gcInit()\n\n//export tinygo_runtime_bdwgc_callback\nfunc gcCallback() {\n\t// Mark globals and all stacks, and stop the world if we're using threading.\n\tgcMarkReachable()\n}\n\nfunc markRoots(start, end uintptr) {\n\tlibgc_push_all(start, end)\n}\n\nfunc markCurrentGoroutineStack(sp uintptr) {\n\t// Only mark the area of the stack that is currently in use.\n\t// (This doesn't work for other goroutines, but at least it doesn't keep\n\t// more pointers alive than needed on the current stack).\n\tbase := libgc_base(sp)\n\tif base == 0 { // && asserts\n\t\truntimePanic(\"goroutine stack not in a heap allocation?\")\n\t}\n\tstackBottom := base + libgc_size(base)\n\tlibgc_push_all_stack(sp, stackBottom)\n}\n\n//go:noinline\nfunc alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {\n\tif size == 0 {\n\t\treturn unsafe.Pointer(&zeroSizedAlloc)\n\t}\n\n\tgcLock.Lock()\n\tvar ptr unsafe.Pointer\n\tif layout == gclayout.NoPtrs.AsPtr() {\n\t\t// This object is entirely pointer free, for example make([]int, ...).\n\t\t// Make sure the GC knows this so it doesn't scan the object\n\t\t// unnecessarily to improve performance.\n\t\tptr = libgc_malloc_atomic(size)\n\t\t// Memory returned from libgc_malloc_atomic has not been zeroed so we\n\t\t// have to do that manually.\n\t\tmemzero(ptr, size)\n\t} else {\n\t\t// TODO: bdwgc supports typed allocations, which could be useful to\n\t\t// implement a mostly-precise GC.\n\t\tptr = libgc_malloc(size)\n\t\t// Memory returned from libgc_malloc has already been zeroed, so nothing\n\t\t// to do here.\n\t}\n\tgcResumeWorld()\n\tgcLock.Unlock()\n\tif ptr == nil {\n\t\truntimePanic(\"gc: out of memory\")\n\t}\n\n\treturn ptr\n}\n\nfunc free(ptr unsafe.Pointer) {\n\tlibgc_free(ptr)\n}\n\nfunc GC() {\n\tgcLock.Lock()\n\tlibgc_gcollect()\n\tgcResumeWorld()\n\tgcLock.Unlock()\n}\n\n// This should be stack-allocated, but we don't currently have a good way of\n// ensuring that happens.\nvar gcMemStats libgc_prof_stats\n\nfunc ReadMemStats(m *MemStats) {\n\tgcLock.Lock()\n\n\tlibgc_get_prof_stats(&gcMemStats, unsafe.Sizeof(gcMemStats))\n\n\t// Fill in MemStats as well as we can, given the information that bdwgc\n\t// provides to us.\n\tm.HeapIdle = uint64(gcMemStats.free_bytes_full - gcMemStats.unmapped_bytes)\n\tm.HeapInuse = uint64(gcMemStats.heapsize_full - gcMemStats.unmapped_bytes)\n\tm.HeapReleased = uint64(gcMemStats.unmapped_bytes)\n\tm.HeapSys = uint64(m.HeapInuse + m.HeapIdle)\n\tm.GCSys = 0 // not provided by bdwgc\n\tm.TotalAlloc = uint64(gcMemStats.allocd_bytes_before_gc + gcMemStats.bytes_allocd_since_gc)\n\tm.Mallocs = 0 // not provided by bdwgc\n\tm.Frees = 0   // not provided by bdwgc\n\tm.Sys = uint64(gcMemStats.obtained_from_os_bytes)\n\n\tgcLock.Unlock()\n}\n\nfunc setHeapEnd(newHeapEnd uintptr) {\n\truntimePanic(\"gc: did not expect setHeapEnd call\")\n}\n\nfunc SetFinalizer(obj interface{}, finalizer interface{}) {\n\t// Unimplemented.\n\t// The GC *does* support finalization, so this could be added relatively\n\t// easily I think.\n}\n\n//export GC_init\nfunc libgc_init()\n\n//export GC_malloc\nfunc libgc_malloc(uintptr) unsafe.Pointer\n\n//export GC_malloc_atomic\nfunc libgc_malloc_atomic(uintptr) unsafe.Pointer\n\n//export GC_free\nfunc libgc_free(unsafe.Pointer)\n\n//export GC_base\nfunc libgc_base(ptr uintptr) uintptr\n\n//export GC_size\nfunc libgc_size(ptr uintptr) uintptr\n\n//export GC_push_all\nfunc libgc_push_all(bottom, top uintptr)\n\n//export GC_push_all_stack\nfunc libgc_push_all_stack(bottom, top uintptr)\n\n//export GC_gcollect\nfunc libgc_gcollect()\n\n//export GC_get_prof_stats\nfunc libgc_get_prof_stats(*libgc_prof_stats, uintptr) uintptr\n\n//export GC_set_push_other_roots\nfunc libgc_set_push_other_roots(unsafe.Pointer)\n\ntype libgc_prof_stats struct {\n\theapsize_full             uintptr\n\tfree_bytes_full           uintptr\n\tunmapped_bytes            uintptr\n\tbytes_allocd_since_gc     uintptr\n\tallocd_bytes_before_gc    uintptr\n\tnon_gc_bytes              uintptr\n\tgc_no                     uintptr\n\tmarkers_m1                uintptr\n\tbytes_reclaimed_since_gc  uintptr\n\treclaimed_bytes_before_gc uintptr\n\texpl_freed_bytes_since_gc uintptr\n\tobtained_from_os_bytes    uintptr\n}\n"
  },
  {
    "path": "src/runtime/gc_conservative.go",
    "content": "//go:build gc.conservative\n\n// This implements the block-based heap as a fully conservative GC. No tracking\n// of pointers is done, every word in an object is considered live if it looks\n// like a pointer.\n\npackage runtime\n\nimport \"unsafe\"\n\n// parseGCLayout stores the layout information passed to alloc into a gcLayout value.\n// The conservative GC discards this information.\nfunc parseGCLayout(layout unsafe.Pointer) gcLayout {\n\treturn gcLayout{}\n}\n\n// gcLayout tracks pointer locations in a heap object.\n// The conservative GC treats all locations as potential pointers, so this doesn't need to store anything.\ntype gcLayout struct {\n}\n\nfunc (l gcLayout) pointerFree() bool {\n\t// We don't know whether this object contains pointers, so conservatively\n\t// return false.\n\treturn false\n}\n\nfunc (l gcLayout) scan(start, len uintptr) {\n\tscanConservative(start, len)\n}\n"
  },
  {
    "path": "src/runtime/gc_custom.go",
    "content": "//go:build gc.custom\n// +build gc.custom\n\npackage runtime\n\n// This GC strategy allows an external GC to be plugged in instead of the builtin\n// implementations.\n//\n// The interface defined in this file is not stable and can be broken at anytime, even\n// across minor versions.\n//\n// runtime.markStack() must be called at the beginning of any GC cycle. //go:linkname\n// on a function without a body can be used to access this internal function.\n//\n// The custom implementation must provide the following functions in the runtime package\n// using the go:linkname directive:\n//\n// - func initHeap()\n// - func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer\n// - func free(ptr unsafe.Pointer)\n// - func markRoots(start, end uintptr)\n// - func GC()\n// - func SetFinalizer(obj interface{}, finalizer interface{})\n// - func ReadMemStats(ms *runtime.MemStats)\n//\n//\n// In addition, if targeting wasi, the following functions should be exported for interoperability\n// with wasi libraries that use them. Note, this requires the export directive, not go:linkname.\n//\n// - func malloc(size uintptr) unsafe.Pointer\n// - func free(ptr unsafe.Pointer)\n// - func calloc(nmemb, size uintptr) unsafe.Pointer\n// - func realloc(oldPtr unsafe.Pointer, size uintptr) unsafe.Pointer\n\nimport (\n\t\"unsafe\"\n)\n\nconst needsStaticHeap = false\n\n// initHeap is called when the heap is first initialized at program start.\nfunc initHeap()\n\n// alloc is called to allocate memory. layout is currently not used.\nfunc alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer\n\n// free is called to explicitly free a previously allocated pointer.\nfunc free(ptr unsafe.Pointer)\n\n// markRoots is called with the start and end addresses to scan for references.\n// It is currently only called with the top and bottom of the stack.\nfunc markRoots(start, end uintptr)\n\n// GC is called to explicitly run garbage collection.\nfunc GC()\n\n// SetFinalizer registers a finalizer.\nfunc SetFinalizer(obj interface{}, finalizer interface{})\n\n// ReadMemStats populates m with memory statistics.\nfunc ReadMemStats(ms *MemStats)\n\nfunc setHeapEnd(newHeapEnd uintptr) {\n\t// Heap is in custom GC so ignore for when called from wasm initialization.\n}\n"
  },
  {
    "path": "src/runtime/gc_globals.go",
    "content": "//go:build baremetal || tinygo.wasm\n\npackage runtime\n\n// This file implements findGlobals for all systems where the start and end of\n// the globals section can be found through linker-defined symbols.\n\n// findGlobals finds all globals (which are reachable by definition) and calls\n// the callback for them.\n//\n// This implementation marks all globals conservatively and assumes it can use\n// linker-defined symbols for the start and end of the .data section.\nfunc findGlobals(found func(start, end uintptr)) {\n\tfound(globalsStart, globalsEnd)\n}\n"
  },
  {
    "path": "src/runtime/gc_leaking.go",
    "content": "//go:build gc.leaking\n\npackage runtime\n\n// This GC implementation is the simplest useful memory allocator possible: it\n// only allocates memory and never frees it. For some constrained systems, it\n// may be the only memory allocator possible.\n\nimport (\n\t\"internal/task\"\n\t\"unsafe\"\n)\n\nconst needsStaticHeap = true\n\n// Ever-incrementing pointer: no memory is freed.\nvar heapptr uintptr\n\n// Total amount allocated for runtime.MemStats\nvar gcTotalAlloc uint64\n\n// Total number of calls to alloc()\nvar gcMallocs uint64\n\n// Heap lock for parallel goroutines. No-op when single threaded.\nvar gcLock task.PMutex\n\n// Total number of objected freed; for leaking collector this stays 0\nconst gcFrees = 0\n\n// Inlining alloc() speeds things up slightly but bloats the executable by 50%,\n// see https://github.com/tinygo-org/tinygo/issues/2674.  So don't.\n//\n//go:noinline\nfunc alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {\n\t// TODO: this can be optimized by not casting between pointers and ints so\n\t// much. And by using platform-native data types (e.g. *uint8 for 8-bit\n\t// systems).\n\tgcLock.Lock()\n\tsize = align(size)\n\taddr := heapptr\n\tgcTotalAlloc += uint64(size)\n\tgcMallocs++\n\theapptr += size\n\tfor heapptr >= heapEnd {\n\t\t// Try to increase the heap and check again.\n\t\tif growHeap() {\n\t\t\tcontinue\n\t\t}\n\t\t// Failed to make the heap bigger, so we must really be out of memory.\n\t\truntimePanic(\"out of memory\")\n\t}\n\tgcLock.Unlock()\n\n\tpointer := unsafe.Pointer(addr)\n\tzero_new_alloc(pointer, size)\n\treturn pointer\n}\n\nfunc realloc(ptr unsafe.Pointer, size uintptr) unsafe.Pointer {\n\tnewAlloc := alloc(size, nil)\n\tif ptr == nil {\n\t\treturn newAlloc\n\t}\n\t// according to POSIX everything beyond the previous pointer's\n\t// size will have indeterminate values so we can just copy garbage\n\tmemcpy(newAlloc, ptr, size)\n\n\treturn newAlloc\n}\n\nfunc free(ptr unsafe.Pointer) {\n\t// Memory is never freed.\n}\n\nfunc markRoots(start, end uintptr) {\n\truntimePanic(\"unreachable: markRoots\")\n}\n\n// ReadMemStats populates m with memory statistics.\n//\n// The returned memory statistics are up to date as of the\n// call to ReadMemStats. This would not do GC implicitly for you.\nfunc ReadMemStats(m *MemStats) {\n\tgcLock.Lock()\n\n\tm.HeapIdle = 0\n\tm.HeapInuse = gcTotalAlloc\n\tm.HeapReleased = 0 // always 0, we don't currently release memory back to the OS.\n\n\tm.HeapSys = m.HeapInuse + m.HeapIdle\n\tm.GCSys = 0\n\tm.TotalAlloc = gcTotalAlloc\n\tm.Mallocs = gcMallocs\n\tm.Frees = gcFrees\n\tm.Sys = uint64(heapEnd - heapStart)\n\t// no free -- current in use heap is the total allocated\n\tm.HeapAlloc = gcTotalAlloc\n\tm.Alloc = m.HeapAlloc\n\n\tgcLock.Unlock()\n}\n\nfunc GC() {\n\t// No-op.\n}\n\nfunc SetFinalizer(obj interface{}, finalizer interface{}) {\n\t// No-op.\n}\n\nfunc initHeap() {\n\t// Initialize this bump-pointer allocator to the start of the heap.\n\t// Needed here because heapStart may not be a compile-time constant.\n\theapptr = heapStart\n}\n\n// setHeapEnd sets a new (larger) heapEnd pointer.\nfunc setHeapEnd(newHeapEnd uintptr) {\n\t// This \"heap\" is so simple that simply assigning a new value is good\n\t// enough.\n\theapEnd = newHeapEnd\n}\n"
  },
  {
    "path": "src/runtime/gc_none.go",
    "content": "//go:build gc.none\n\npackage runtime\n\n// This GC strategy provides no memory allocation at all. It can be useful to\n// detect where in a program memory is allocated (via linker errors) or for\n// targets that have far too little RAM even for the leaking memory allocator.\n\nimport (\n\t\"unsafe\"\n)\n\nconst needsStaticHeap = false\n\nvar gcTotalAlloc uint64 // for runtime.MemStats\nvar gcMallocs uint64\nvar gcFrees uint64\n\nfunc alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer\n\nfunc realloc(ptr unsafe.Pointer, size uintptr) unsafe.Pointer\n\nfunc free(ptr unsafe.Pointer) {\n\t// Nothing to free when nothing gets allocated.\n}\n\nfunc GC() {\n\t// Unimplemented.\n}\n\nfunc markRoots(start, end uintptr) {\n\truntimePanic(\"unreachable: markRoots\")\n}\n\nfunc SetFinalizer(obj interface{}, finalizer interface{}) {\n\t// Unimplemented.\n}\n\nfunc initHeap() {\n\t// Nothing to initialize.\n}\n\nfunc setHeapEnd(newHeapEnd uintptr) {\n\t// Nothing to do here, this function is never actually called.\n}\n"
  },
  {
    "path": "src/runtime/gc_precise.go",
    "content": "//go:build gc.precise\n\n// This implements the block-based GC as a partially precise GC. This means that\n// for most heap allocations it is known which words contain a pointer and which\n// don't. This should in theory make the GC faster (because it can skip\n// non-pointer object) and have fewer false positives in a GC cycle. It does\n// however use a bit more RAM to store the layout of each object.\n//\n// The pointer/non-pointer information for objects is stored in the first word\n// of the object. It is described below but in essence it contains a bitstring\n// of a particular size. This size does not indicate the size of the object:\n// instead the allocated object is a multiple of the bitstring size. This is so\n// that arrays and slices can store the size of the object efficiently. The\n// bitstring indicates where the pointers are in the object (the bit is set when\n// the value may be a pointer, and cleared when it certainly isn't a pointer).\n// Some examples (assuming a 32-bit system for the moment):\n//\n// | object type | size | bitstring | note\n// |-------------|------|-----------|------\n// | int         | 1    |   0       | no pointers in this object\n// | string      | 2    |  01       | {pointer, len} pair so there is one pointer\n// | []int       | 3    | 001       | {pointer, len, cap}\n// | [4]*int     | 1    |   1       | even though it contains 4 pointers, an array repeats so it can be stored with size=1\n// | [30]byte    | 1    |   0       | there are no pointers so the layout is very simple\n//\n// The garbage collector scans objects by starting at the first word value in\n// the object. If the least significant bit of the bitstring is clear, it is\n// skipped (it's not a pointer). If the bit is set, it is treated as if it could\n// be a pointer. The garbage collector continues by scanning further words in\n// the object and checking them against the corresponding bit in the bitstring.\n// Once it reaches the end of the bitstring, it wraps around (for arrays,\n// slices, strings, etc).\n//\n// The layout as passed to the runtime.alloc function and stored in the object\n// is a pointer-sized value. If the least significant bit of the value is set,\n// the bitstring is contained directly inside the value, of the form\n// pppp_pppp_ppps_sss1.\n//   * The 'p' bits indicate which parts of the object are a pointer.\n//   * The 's' bits indicate the size of the object. In this case, there are 11\n//     pointer bits so four bits are enough for the size (0-15).\n//   * The lowest bit is always set to distinguish this value from a pointer.\n// This example is for a 16-bit architecture. For example, 32-bit architectures\n// use a layout format of pppppppp_pppppppp_pppppppp_ppsssss1 (26 bits for\n// pointer/non-pointer information, 5 size bits, and one bit that's always set).\n//\n// For larger objects that don't fit in an uintptr, the layout value is a\n// pointer to a global with a format as follows:\n//     struct {\n//         size uintptr\n//         bits [...]uint8\n//     }\n// The 'size' field is the number of bits in the bitstring. The 'bits' field is\n// a byte array that contains the bitstring itself, in little endian form. The\n// length of the bits array is ceil(size/8).\n\npackage runtime\n\nimport \"unsafe\"\n\nconst sizeFieldBits = 4 + (unsafe.Sizeof(uintptr(0)) / 4)\n\n// parseGCLayout stores the layout information passed to alloc into a gcLayout value.\nfunc parseGCLayout(layout unsafe.Pointer) gcLayout {\n\treturn gcLayout(layout)\n}\n\n// gcLayout tracks pointer locations in a heap object.\ntype gcLayout uintptr\n\nfunc (layout gcLayout) pointerFree() bool {\n\treturn layout&1 != 0 && layout>>(sizeFieldBits+1) == 0\n}\n\n// scan an object with this element layout.\n// The starting address must be valid and pointer-aligned.\n// The length is rounded down to a multiple of the element size.\nfunc (layout gcLayout) scan(start, len uintptr) {\n\tswitch {\n\tcase layout == 0:\n\t\t// This is an unknown layout.\n\t\t// Scan conservatively.\n\t\t// NOTE: This is *NOT* equivalent to a slice of pointers on AVR.\n\t\tscanConservative(start, len)\n\n\tcase layout&1 != 0:\n\t\t// The layout is stored directly in the integer value.\n\t\t// Extract the bitfields.\n\t\tsize := uintptr(layout>>1) & (1<<sizeFieldBits - 1)\n\t\tmask := uintptr(layout) >> (1 + sizeFieldBits)\n\n\t\t// Scan with the extracted mask.\n\t\tscanSimple(start, len, size*unsafe.Alignof(start), mask)\n\n\tdefault:\n\t\t// The layout is stored seperately in a global object.\n\t\t// Extract the size and bitmap.\n\t\tlayoutAddr := unsafe.Pointer(layout)\n\t\tsize := *(*uintptr)(layoutAddr)\n\t\tbitmapPtr := unsafe.Add(layoutAddr, unsafe.Sizeof(uintptr(0)))\n\t\tbitmapLen := (size + 7) / 8\n\t\tbitmap := unsafe.Slice((*byte)(bitmapPtr), bitmapLen)\n\n\t\t// Scan with the bitmap.\n\t\tscanComplex(start, len, size*unsafe.Alignof(start), bitmap)\n\t}\n}\n\n// scanSimple scans an object with an integer bitmask of pointer locations.\n// The starting address must be valid and pointer-aligned.\nfunc scanSimple(start, len, size, mask uintptr) {\n\tfor len >= size {\n\t\t// Scan this element.\n\t\tscanWithMask(start, mask)\n\n\t\t// Move to the next element.\n\t\tstart += size\n\t\tlen -= size\n\t}\n}\n\n// scanComplex scans an object with a bitmap of pointer locations.\n// The starting address must be valid and pointer-aligned.\nfunc scanComplex(start, len, size uintptr, bitmap []byte) {\n\tfor len >= size {\n\t\t// Scan this element.\n\t\tfor i, mask := range bitmap {\n\t\t\taddr := start + 8*unsafe.Alignof(start)*uintptr(i)\n\t\t\tscanWithMask(addr, uintptr(mask))\n\t\t}\n\n\t\t// Move to the next element.\n\t\tstart += size\n\t\tlen -= size\n\t}\n}\n\n// scanWithMask scans a portion of an object with a mask of pointer locations.\n// The address must be valid and pointer-aligned.\nfunc scanWithMask(addr, mask uintptr) {\n\t// TODO: use ctz when available\n\tfor mask != 0 {\n\t\tif mask&1 != 0 {\n\t\t\t// Load and mark this pointer.\n\t\t\troot := *(*uintptr)(unsafe.Pointer(addr))\n\t\t\tmarkRoot(addr, root)\n\t\t}\n\n\t\t// Move to the next offset.\n\t\tmask >>= 1\n\t\taddr += unsafe.Alignof(addr)\n\t}\n}\n"
  },
  {
    "path": "src/runtime/gc_stack_cores.go",
    "content": "//go:build scheduler.cores\n\npackage runtime\n\nimport (\n\t\"internal/task\"\n\t\"sync/atomic\"\n)\n\n// Normally 0. During a GC scan it has various purposes for signalling between\n// the core running the GC and the other cores in the system.\nvar gcScanState atomic.Uint32\n\n// Start GC scan by pausing the world (all other cores) and scanning their\n// stacks. It doesn't resume the world.\nfunc gcMarkReachable() {\n\t// If the other cores haven't started yet (for example, when a GC cycle\n\t// happens during init()), we only need to scan the stack of the current\n\t// core.\n\tif !secondaryCoresStarted {\n\t\t// Scan the stack(s) of the current core.\n\t\tscanCurrentStack()\n\t\tif !task.OnSystemStack() {\n\t\t\t// Mark system stack.\n\t\t\tmarkRoots(task.SystemStack(), stackTop)\n\t\t}\n\n\t\t// Scan globals.\n\t\tfindGlobals(markRoots)\n\n\t\t// Nothing more to do: the other cores haven't started yet.\n\t\treturn\n\t}\n\n\tcore := currentCPU()\n\n\t// Interrupt all other cores.\n\tgcScanState.Store(1)\n\tfor i := uint32(0); i < numCPU; i++ {\n\t\tif i == core {\n\t\t\tcontinue\n\t\t}\n\t\tgcPauseCore(i)\n\t}\n\n\t// Scan the stack(s) of the current core.\n\tscanCurrentStack()\n\tif !task.OnSystemStack() {\n\t\t// Mark system stack.\n\t\tmarkRoots(task.SystemStack(), coreStackTop(core))\n\t}\n\n\t// Scan globals.\n\tfindGlobals(markRoots)\n\n\t// Busy-wait until all the other cores are ready. They certainly should be,\n\t// after the scanning we did above.\n\tfor gcScanState.Load() != numCPU {\n\t\tspinLoopWait()\n\t}\n\tgcScanState.Store(0)\n\n\t// Signal each core in turn that they can scan the stack.\n\tfor i := uint32(0); i < numCPU; i++ {\n\t\tif i == core {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Wake up the core to scan the stack.\n\t\tgcSignalCore(i)\n\n\t\t// Busy-wait until this core finished scanning.\n\t\tfor gcScanState.Load() == 0 {\n\t\t\tspinLoopWait()\n\t\t}\n\t\tgcScanState.Store(0)\n\t}\n\n\t// All the stack are now scanned.\n}\n\n//go:export tinygo_scanCurrentStack\nfunc scanCurrentStack()\n\n//go:export tinygo_scanstack\nfunc scanstack(sp uintptr) {\n\t// Mark the current stack.\n\t// This function is called by scanCurrentStack, after pushing all registers\n\t// onto the stack.\n\tif task.OnSystemStack() {\n\t\t// This is the system stack.\n\t\t// Scan all words on the stack.\n\t\tmarkRoots(sp, coreStackTop(currentCPU()))\n\t} else {\n\t\t// This is a goroutine stack.\n\t\tmarkCurrentGoroutineStack(sp)\n\t}\n}\n\n// Resume the world after a call to gcMarkReachable.\nfunc gcResumeWorld() {\n\tif !secondaryCoresStarted {\n\t\t// Nothing to do: the world wasn't stopped in gcMarkReachable.\n\t\treturn\n\t}\n\n\t// Signal each core that they can resume.\n\thartID := currentCPU()\n\tfor i := uint32(0); i < numCPU; i++ {\n\t\tif i == hartID {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Signal the core.\n\t\tgcSignalCore(i)\n\t}\n\n\t// Busy-wait until the core acknowledges the signal (and is going to return\n\t// from the interrupt handler).\n\tfor gcScanState.Load() != numCPU-1 {\n\t\tspinLoopWait()\n\t}\n\tgcScanState.Store(0)\n}\n"
  },
  {
    "path": "src/runtime/gc_stack_portable.go",
    "content": "//go:build (gc.conservative || gc.custom || gc.precise || gc.boehm) && tinygo.wasm\n\npackage runtime\n\nimport (\n\t\"internal/task\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nfunc gcMarkReachable() {\n\tmarkStack()\n\tfindGlobals(markRoots)\n}\n\n//go:extern runtime.stackChainStart\nvar stackChainStart *stackChainObject\n\ntype stackChainObject struct {\n\tparent   *stackChainObject\n\tnumSlots uintptr\n}\n\n// markStack marks all root pointers found on the stack.\n//\n//   - Goroutine stacks are heap allocated and always reachable in some way\n//     (for example through internal/task.currentTask) so they will always be\n//     scanned.\n//   - The system stack (aka startup stack) is not heap allocated, so even\n//     though it may be referenced it will not be scanned by default.\n//\n// The compiler also inserts code to store all globals in a chain via\n// stackChainStart. Luckily we don't need to scan these, as these globals are\n// stored on the goroutine stack and are therefore already getting scanned.\nfunc markStack() {\n\t// Hack to force LLVM to consider stackChainStart to be live.\n\t// Without this hack, loads and stores may be considered dead and objects on\n\t// the stack might not be correctly tracked. With this volatile load, LLVM\n\t// is forced to consider stackChainStart (and everything it points to) as\n\t// live.\n\tvolatile.LoadUint32((*uint32)(unsafe.Pointer(&stackChainStart)))\n\n\t// Scan the system stack.\n\tvar sysSP uintptr\n\tif task.OnSystemStack() {\n\t\t// We are on the system stack.\n\t\t// Use the current stack pointer.\n\t\tsysSP = getCurrentStackPointer()\n\t} else {\n\t\t// We are in a goroutine.\n\t\t// Use the saved stack pointer.\n\t\tsysSP = savedStackPointer\n\t}\n\tmarkRoots(sysSP, stackTop)\n}\n\n// trackPointer is a stub function call inserted by the compiler during IR\n// construction. Calls to it are later replaced with regular stack bookkeeping\n// code.\nfunc trackPointer(ptr, alloca unsafe.Pointer)\n\n// swapStackChain swaps the stack chain.\n// This is called from internal/task when switching goroutines.\nfunc swapStackChain(dst **stackChainObject) {\n\t*dst, stackChainStart = stackChainStart, *dst\n}\n\nfunc gcResumeWorld() {\n\t// Nothing to do here (single threaded).\n}\n"
  },
  {
    "path": "src/runtime/gc_stack_raw.go",
    "content": "//go:build (gc.conservative || gc.precise || gc.boehm) && !tinygo.wasm && !scheduler.threads && !scheduler.cores\n\npackage runtime\n\nimport (\n\t\"internal/task\"\n\t\"sync/atomic\"\n)\n\n// Unused.\nvar gcScanState atomic.Uint32\n\nfunc gcMarkReachable() {\n\tmarkStack()\n\tfindGlobals(markRoots)\n}\n\n// markStack marks all root pointers found on the stack.\n//\n// This implementation is conservative and relies on the stack top (provided by\n// the linker) and getting the current stack pointer from a register. Also, it\n// assumes a descending stack. Thus, it is not very portable.\nfunc markStack() {\n\t// Scan the current stack, and all current registers.\n\tscanCurrentStack()\n\n\tif !task.OnSystemStack() {\n\t\t// Mark system stack.\n\t\tmarkRoots(task.SystemStack(), stackTop)\n\t}\n}\n\n//go:export tinygo_scanCurrentStack\nfunc scanCurrentStack()\n\n//go:export tinygo_scanstack\nfunc scanstack(sp uintptr) {\n\t// Mark current stack.\n\t// This function is called by scanCurrentStack, after pushing all registers onto the stack.\n\t// Callee-saved registers have been pushed onto stack by tinygo_localscan, so this will scan them too.\n\tif task.OnSystemStack() {\n\t\t// This is the system stack.\n\t\t// Scan all words on the stack.\n\t\tmarkRoots(sp, stackTop)\n\t} else {\n\t\t// This is a goroutine stack.\n\t\tmarkCurrentGoroutineStack(sp)\n\t}\n}\n\nfunc gcResumeWorld() {\n\t// Nothing to do here (single threaded).\n}\n"
  },
  {
    "path": "src/runtime/gc_stack_threads.go",
    "content": "//go:build scheduler.threads\n\npackage runtime\n\nimport \"internal/task\"\n\nfunc gcMarkReachable() {\n\ttask.GCStopWorldAndScan()\n}\n\n// Scan globals inside the stop-the-world phase. Called from the STW\n// implementation in the internal/task package.\n//\n//go:linkname gcScanGlobals internal/task.gcScanGlobals\nfunc gcScanGlobals() {\n\tfindGlobals(markRoots)\n}\n\n// Function called from assembly with all registers pushed, to actually scan the\n// stack.\n//\n//go:export tinygo_scanstack\nfunc scanstack(sp uintptr) {\n\tmarkRoots(sp, task.StackTop())\n}\n\nfunc gcResumeWorld() {\n\ttask.GCResumeWorld()\n}\n"
  },
  {
    "path": "src/runtime/hashmap.go",
    "content": "package runtime\n\n// This is a hashmap implementation for the map[T]T type.\n// It is very roughly based on the implementation of the Go hashmap:\n//\n//     https://golang.org/src/runtime/map.go\n\nimport (\n\t\"internal/reflectlite\"\n\t\"tinygo\"\n\t\"unsafe\"\n)\n\n// The underlying hashmap structure for Go.\ntype hashmap struct {\n\tbuckets    unsafe.Pointer // pointer to array of buckets\n\tseed       uintptr\n\tcount      uintptr\n\tkeySize    uintptr // maybe this can store the key type as well? E.g. keysize == 5 means string?\n\tvalueSize  uintptr\n\tbucketBits uint8\n\tkeyEqual   func(x, y unsafe.Pointer, n uintptr) bool\n\tkeyHash    func(key unsafe.Pointer, size, seed uintptr) uint32\n}\n\n// A hashmap bucket. A bucket is a container of 8 key/value pairs: first the\n// following two entries, then the 8 keys, then the 8 values. This somewhat odd\n// ordering is to make sure the keys and values are well aligned when one of\n// them is smaller than the system word size.\ntype hashmapBucket struct {\n\ttophash [8]uint8\n\tnext    *hashmapBucket // next bucket (if there are more than 8 in a chain)\n\t// Followed by the actual keys, and then the actual values. These are\n\t// allocated but as they're of variable size they can't be shown here.\n}\n\ntype hashmapIterator struct {\n\tbuckets      unsafe.Pointer // pointer to array of hashapBuckets\n\tnumBuckets   uintptr        // length of buckets array\n\tbucketNumber uintptr        // current index into buckets array\n\tstartBucket  uintptr        // starting location for iterator\n\tbucket       *hashmapBucket // current bucket in chain\n\tbucketIndex  uint8          // current index into bucket\n\tstartIndex   uint8          // starting bucket index for iterator\n\twrapped      bool           // true if the iterator has wrapped\n}\n\nfunc hashmapNewIterator() unsafe.Pointer {\n\treturn unsafe.Pointer(new(hashmapIterator))\n}\n\n// Get the topmost 8 bits of the hash, without using a special value (like 0).\nfunc hashmapTopHash(hash uint32) uint8 {\n\ttophash := uint8(hash >> 24)\n\tif tophash < 1 {\n\t\t// 0 means empty slot, so make it bigger.\n\t\ttophash += 1\n\t}\n\treturn tophash\n}\n\n// Create a new hashmap with the given keySize and valueSize.\nfunc hashmapMake(keySize, valueSize uintptr, sizeHint uintptr, alg uint8) *hashmap {\n\tbucketBits := uint8(0)\n\tfor hashmapHasSpaceToGrow(bucketBits) && hashmapOverLoadFactor(sizeHint, bucketBits) {\n\t\tbucketBits++\n\t}\n\n\tbucketBufSize := unsafe.Sizeof(hashmapBucket{}) + keySize*8 + valueSize*8\n\tbuckets := alloc(bucketBufSize*(1<<bucketBits), nil)\n\n\tkeyHash := hashmapKeyHashAlg(tinygo.HashmapAlgorithm(alg))\n\tkeyEqual := hashmapKeyEqualAlg(tinygo.HashmapAlgorithm(alg))\n\n\treturn &hashmap{\n\t\tbuckets:    buckets,\n\t\tseed:       uintptr(fastrand()),\n\t\tkeySize:    keySize,\n\t\tvalueSize:  valueSize,\n\t\tbucketBits: bucketBits,\n\t\tkeyEqual:   keyEqual,\n\t\tkeyHash:    keyHash,\n\t}\n}\n\n// Remove all entries from the map, without actually deallocating the space for\n// it. This is used for the clear builtin, and can be used to reuse a map (to\n// avoid extra heap allocations).\nfunc hashmapClear(m *hashmap) {\n\tif m == nil {\n\t\t// Nothing to do. According to the spec:\n\t\t// > If the map or slice is nil, clear is a no-op.\n\t\treturn\n\t}\n\n\tm.count = 0\n\tnumBuckets := uintptr(1) << m.bucketBits\n\tbucketSize := hashmapBucketSize(m)\n\tfor i := uintptr(0); i < numBuckets; i++ {\n\t\tbucket := hashmapBucketAddr(m, m.buckets, i)\n\t\tfor bucket != nil {\n\t\t\t// Clear the tophash, to mark these keys/values as removed.\n\t\t\tbucket.tophash = [8]uint8{}\n\n\t\t\t// Clear the keys and values in the bucket so that the GC won't pin\n\t\t\t// these allocations.\n\t\t\tmemzero(unsafe.Add(unsafe.Pointer(bucket), unsafe.Sizeof(hashmapBucket{})), bucketSize-unsafe.Sizeof(hashmapBucket{}))\n\n\t\t\t// Move on to the next bucket in the chain.\n\t\t\tbucket = bucket.next\n\t\t}\n\t}\n}\n\nfunc hashmapKeyEqualAlg(alg tinygo.HashmapAlgorithm) func(x, y unsafe.Pointer, n uintptr) bool {\n\tswitch alg {\n\tcase tinygo.HashmapAlgorithmBinary:\n\t\treturn memequal\n\tcase tinygo.HashmapAlgorithmString:\n\t\treturn hashmapStringEqual\n\tcase tinygo.HashmapAlgorithmInterface:\n\t\treturn hashmapInterfaceEqual\n\tdefault:\n\t\t// compiler bug :(\n\t\treturn nil\n\t}\n}\n\nfunc hashmapKeyHashAlg(alg tinygo.HashmapAlgorithm) func(key unsafe.Pointer, n, seed uintptr) uint32 {\n\tswitch alg {\n\tcase tinygo.HashmapAlgorithmBinary:\n\t\treturn hash32\n\tcase tinygo.HashmapAlgorithmString:\n\t\treturn hashmapStringPtrHash\n\tcase tinygo.HashmapAlgorithmInterface:\n\t\treturn hashmapInterfacePtrHash\n\tdefault:\n\t\t// compiler bug :(\n\t\treturn nil\n\t}\n}\n\nfunc hashmapHasSpaceToGrow(bucketBits uint8) bool {\n\t// Over this limit, we're likely to overflow uintptrs during calculations\n\t// or numbers of hash elements.   Don't allow any more growth.\n\t// With 29 bits, this is 2^32 elements anyway.\n\treturn bucketBits <= uint8((unsafe.Sizeof(uintptr(0))*8)-3)\n}\n\nfunc hashmapOverLoadFactor(n uintptr, bucketBits uint8) bool {\n\t// \"maximum\" number of elements is 0.75 * buckets * elements per bucket\n\t// to avoid overflow, this is calculated as\n\t// max = 3 * (1/4 * buckets * elements per bucket)\n\t//     = 3 * (buckets * (elements per bucket)/4)\n\t//     = 3 * (buckets * (8/4)\n\t//     = 3 * (buckets * 2)\n\t//     = 6 * buckets\n\tmax := (uintptr(6) << bucketBits)\n\treturn n > max\n}\n\n// Return the number of entries in this hashmap, called from the len builtin.\n// A nil hashmap is defined as having length 0.\n//\n//go:inline\nfunc hashmapLen(m *hashmap) int {\n\tif m == nil {\n\t\treturn 0\n\t}\n\treturn int(m.count)\n}\n\n//go:inline\nfunc hashmapBucketSize(m *hashmap) uintptr {\n\treturn unsafe.Sizeof(hashmapBucket{}) + uintptr(m.keySize)*8 + uintptr(m.valueSize)*8\n}\n\n//go:inline\nfunc hashmapBucketAddr(m *hashmap, buckets unsafe.Pointer, n uintptr) *hashmapBucket {\n\tbucketSize := hashmapBucketSize(m)\n\tbucket := (*hashmapBucket)(unsafe.Add(buckets, bucketSize*n))\n\treturn bucket\n}\n\n//go:inline\nfunc hashmapBucketAddrForHash(m *hashmap, hash uint32) *hashmapBucket {\n\tnumBuckets := uintptr(1) << m.bucketBits\n\tbucketNumber := (uintptr(hash) & (numBuckets - 1))\n\treturn hashmapBucketAddr(m, m.buckets, bucketNumber)\n}\n\n//go:inline\nfunc hashmapSlotKey(m *hashmap, bucket *hashmapBucket, slot uint8) unsafe.Pointer {\n\tslotKeyOffset := unsafe.Sizeof(hashmapBucket{}) + uintptr(m.keySize)*uintptr(slot)\n\tslotKey := unsafe.Add(unsafe.Pointer(bucket), slotKeyOffset)\n\treturn slotKey\n}\n\n//go:inline\nfunc hashmapSlotValue(m *hashmap, bucket *hashmapBucket, slot uint8) unsafe.Pointer {\n\tslotValueOffset := unsafe.Sizeof(hashmapBucket{}) + uintptr(m.keySize)*8 + uintptr(m.valueSize)*uintptr(slot)\n\tslotValue := unsafe.Add(unsafe.Pointer(bucket), slotValueOffset)\n\treturn slotValue\n}\n\n// Set a specified key to a given value. Grow the map if necessary.\n//\n//go:nobounds\nfunc hashmapSet(m *hashmap, key unsafe.Pointer, value unsafe.Pointer, hash uint32) {\n\tif hashmapHasSpaceToGrow(m.bucketBits) && hashmapOverLoadFactor(m.count, m.bucketBits) {\n\t\thashmapGrow(m)\n\t\t// seed changed when we grew; rehash key with new seed\n\t\thash = m.keyHash(key, m.keySize, m.seed)\n\t}\n\n\ttophash := hashmapTopHash(hash)\n\tbucket := hashmapBucketAddrForHash(m, hash)\n\tvar lastBucket *hashmapBucket\n\n\t// See whether the key already exists somewhere.\n\tvar emptySlotKey unsafe.Pointer\n\tvar emptySlotValue unsafe.Pointer\n\tvar emptySlotTophash *byte\n\tfor bucket != nil {\n\t\tfor i := uint8(0); i < 8; i++ {\n\t\t\tslotKey := hashmapSlotKey(m, bucket, i)\n\t\t\tslotValue := hashmapSlotValue(m, bucket, i)\n\t\t\tif bucket.tophash[i] == 0 && emptySlotKey == nil {\n\t\t\t\t// Found an empty slot, store it for if we couldn't find an\n\t\t\t\t// existing slot.\n\t\t\t\temptySlotKey = slotKey\n\t\t\t\temptySlotValue = slotValue\n\t\t\t\temptySlotTophash = &bucket.tophash[i]\n\t\t\t}\n\t\t\tif bucket.tophash[i] == tophash {\n\t\t\t\t// Could be an existing key that's the same.\n\t\t\t\tif m.keyEqual(key, slotKey, m.keySize) {\n\t\t\t\t\t// found same key, replace it\n\t\t\t\t\tmemcpy(slotValue, value, m.valueSize)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tlastBucket = bucket\n\t\tbucket = bucket.next\n\t}\n\tif emptySlotKey == nil {\n\t\t// Add a new bucket to the bucket chain.\n\t\t// TODO: rebalance if necessary to avoid O(n) insert and lookup time.\n\t\tlastBucket.next = (*hashmapBucket)(hashmapInsertIntoNewBucket(m, key, value, tophash))\n\t\treturn\n\t}\n\tm.count++\n\tmemcpy(emptySlotKey, key, m.keySize)\n\tmemcpy(emptySlotValue, value, m.valueSize)\n\t*emptySlotTophash = tophash\n}\n\n// hashmapInsertIntoNewBucket creates a new bucket, inserts the given key and\n// value into the bucket, and returns a pointer to this bucket.\nfunc hashmapInsertIntoNewBucket(m *hashmap, key, value unsafe.Pointer, tophash uint8) *hashmapBucket {\n\tbucketBufSize := hashmapBucketSize(m)\n\tbucketBuf := alloc(bucketBufSize, nil)\n\tbucket := (*hashmapBucket)(bucketBuf)\n\n\t// Insert into the first slot, which is empty as it has just been allocated.\n\tslotKey := hashmapSlotKey(m, bucket, 0)\n\tslotValue := hashmapSlotValue(m, bucket, 0)\n\tm.count++\n\tmemcpy(slotKey, key, m.keySize)\n\tmemcpy(slotValue, value, m.valueSize)\n\tbucket.tophash[0] = tophash\n\treturn bucket\n}\n\nfunc hashmapGrow(m *hashmap) {\n\t// allocate our new buckets twice as big\n\tn := hashmapCopy(m, m.bucketBits+1)\n\t*m = n\n}\n\n//go:linkname hashmapClone maps.clone\nfunc hashmapClone(intf _interface) _interface {\n\ttyp, val := decomposeInterface(intf)\n\tm := (*hashmap)(val)\n\tn := hashmapCopy(m, m.bucketBits)\n\treturn composeInterface(typ, unsafe.Pointer(&n))\n}\n\nfunc hashmapCopy(m *hashmap, sizeBits uint8) hashmap {\n\t// clone map as empty\n\tn := *m\n\tn.count = 0\n\tn.seed = uintptr(fastrand())\n\n\tn.bucketBits = sizeBits\n\tnumBuckets := uintptr(1) << n.bucketBits\n\tbucketBufSize := hashmapBucketSize(m)\n\tn.buckets = alloc(bucketBufSize*numBuckets, nil)\n\n\t// use a hashmap iterator to go through the old map\n\tvar it hashmapIterator\n\n\tvar key = alloc(m.keySize, nil)\n\tvar value = alloc(m.valueSize, nil)\n\n\tfor hashmapNext(m, &it, key, value) {\n\t\th := n.keyHash(key, uintptr(n.keySize), n.seed)\n\t\thashmapSet(&n, key, value, h)\n\t}\n\n\treturn n\n}\n\n// Get the value of a specified key, or zero the value if not found.\n//\n//go:nobounds\nfunc hashmapGet(m *hashmap, key, value unsafe.Pointer, valueSize uintptr, hash uint32) bool {\n\tif m == nil {\n\t\t// Getting a value out of a nil map is valid. From the spec:\n\t\t// > if the map is nil or does not contain such an entry, a[x] is the\n\t\t// > zero value for the element type of M\n\t\tmemzero(value, uintptr(valueSize))\n\t\treturn false\n\t}\n\n\ttophash := hashmapTopHash(hash)\n\tbucket := hashmapBucketAddrForHash(m, hash)\n\n\t// Try to find the key.\n\tfor bucket != nil {\n\t\tfor i := uint8(0); i < 8; i++ {\n\t\t\tslotKey := hashmapSlotKey(m, bucket, i)\n\t\t\tslotValue := hashmapSlotValue(m, bucket, i)\n\t\t\tif bucket.tophash[i] == tophash {\n\t\t\t\t// This could be the key we're looking for.\n\t\t\t\tif m.keyEqual(key, slotKey, m.keySize) {\n\t\t\t\t\t// Found the key, copy it.\n\t\t\t\t\tmemcpy(value, slotValue, m.valueSize)\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tbucket = bucket.next\n\t}\n\n\t// Did not find the key.\n\tmemzero(value, m.valueSize)\n\treturn false\n}\n\n// Delete a given key from the map. No-op when the key does not exist in the\n// map.\n//\n//go:nobounds\nfunc hashmapDelete(m *hashmap, key unsafe.Pointer, hash uint32) {\n\tif m == nil {\n\t\t// The delete builtin is defined even when the map is nil. From the spec:\n\t\t// > If the map m is nil or the element m[k] does not exist, delete is a\n\t\t// > no-op.\n\t\treturn\n\t}\n\n\ttophash := hashmapTopHash(hash)\n\tbucket := hashmapBucketAddrForHash(m, hash)\n\n\t// Try to find the key.\n\tfor bucket != nil {\n\t\tfor i := uint8(0); i < 8; i++ {\n\t\t\tslotKey := hashmapSlotKey(m, bucket, i)\n\t\t\tif bucket.tophash[i] == tophash {\n\t\t\t\t// This could be the key we're looking for.\n\t\t\t\tif m.keyEqual(key, slotKey, m.keySize) {\n\t\t\t\t\t// Found the key, delete it.\n\t\t\t\t\tbucket.tophash[i] = 0\n\t\t\t\t\t// Zero out the key and value so garbage collector doesn't pin the allocations.\n\t\t\t\t\tmemzero(slotKey, m.keySize)\n\t\t\t\t\tslotValue := hashmapSlotValue(m, bucket, i)\n\t\t\t\t\tmemzero(slotValue, m.valueSize)\n\t\t\t\t\tm.count--\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tbucket = bucket.next\n\t}\n}\n\n// Iterate over a hashmap.\n//\n//go:nobounds\nfunc hashmapNext(m *hashmap, it *hashmapIterator, key, value unsafe.Pointer) bool {\n\tif m == nil {\n\t\t// From the spec: If the map is nil, the number of iterations is 0.\n\t\treturn false\n\t}\n\n\tif it.buckets == nil {\n\t\t// initialize iterator\n\t\tit.buckets = m.buckets\n\t\tit.numBuckets = uintptr(1) << m.bucketBits\n\t\tit.startBucket = uintptr(fastrand()) & (it.numBuckets - 1)\n\t\tit.startIndex = uint8(fastrand() & 7)\n\n\t\tit.bucketNumber = it.startBucket\n\t\tit.bucket = hashmapBucketAddr(m, it.buckets, it.bucketNumber)\n\t\tit.bucketIndex = it.startIndex\n\t}\n\n\tfor {\n\t\t// If we've wrapped and we're back at our starting location, terminate the iteration.\n\t\tif it.wrapped && it.bucketNumber == it.startBucket && it.bucketIndex == it.startIndex {\n\t\t\treturn false\n\t\t}\n\n\t\tif it.bucketIndex >= 8 {\n\t\t\t// end of bucket, move to the next in the chain\n\t\t\tit.bucketIndex = 0\n\t\t\tit.bucket = it.bucket.next\n\t\t}\n\n\t\tif it.bucket == nil {\n\t\t\tit.bucketNumber++ // next bucket\n\t\t\tif it.bucketNumber >= it.numBuckets {\n\t\t\t\t// went through all buckets -- wrap around\n\t\t\t\tit.bucketNumber = 0\n\t\t\t\tit.wrapped = true\n\t\t\t}\n\t\t\tit.bucket = hashmapBucketAddr(m, it.buckets, it.bucketNumber)\n\t\t\tcontinue\n\t\t}\n\n\t\tif it.bucket.tophash[it.bucketIndex] == 0 {\n\t\t\t// slot is empty - move on\n\t\t\tit.bucketIndex++\n\t\t\tcontinue\n\t\t}\n\n\t\t// Found a key.\n\t\tslotKey := hashmapSlotKey(m, it.bucket, it.bucketIndex)\n\t\tmemcpy(key, slotKey, m.keySize)\n\n\t\tif it.buckets == m.buckets {\n\t\t\t// Our view of the buckets is the same as the parent map.\n\t\t\t// Just copy the value we have\n\t\t\tslotValue := hashmapSlotValue(m, it.bucket, it.bucketIndex)\n\t\t\tmemcpy(value, slotValue, m.valueSize)\n\t\t\tit.bucketIndex++\n\t\t} else {\n\t\t\tit.bucketIndex++\n\n\t\t\t// Our view of the buckets doesn't match the parent map.\n\t\t\t// Look up the key in the new buckets and return that value if it exists\n\t\t\thash := m.keyHash(key, m.keySize, m.seed)\n\t\t\tok := hashmapGet(m, key, value, m.valueSize, hash)\n\t\t\tif !ok {\n\t\t\t\t// doesn't exist in parent map; try next key\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// All good.\n\t\t}\n\n\t\treturn true\n\t}\n}\n\n// Hashmap with plain binary data keys (not containing strings etc.).\nfunc hashmapBinarySet(m *hashmap, key, value unsafe.Pointer) {\n\tif m == nil {\n\t\tnilMapPanic()\n\t}\n\thash := hash32(key, m.keySize, m.seed)\n\thashmapSet(m, key, value, hash)\n}\n\nfunc hashmapBinaryGet(m *hashmap, key, value unsafe.Pointer, valueSize uintptr) bool {\n\tif m == nil {\n\t\tmemzero(value, uintptr(valueSize))\n\t\treturn false\n\t}\n\thash := hash32(key, m.keySize, m.seed)\n\treturn hashmapGet(m, key, value, valueSize, hash)\n}\n\nfunc hashmapBinaryDelete(m *hashmap, key unsafe.Pointer) {\n\tif m == nil {\n\t\treturn\n\t}\n\thash := hash32(key, m.keySize, m.seed)\n\thashmapDelete(m, key, hash)\n}\n\n// Hashmap with string keys (a common case).\n\nfunc hashmapStringEqual(x, y unsafe.Pointer, n uintptr) bool {\n\treturn *(*string)(x) == *(*string)(y)\n}\n\nfunc hashmapStringHash(s string, seed uintptr) uint32 {\n\t_s := (*_string)(unsafe.Pointer(&s))\n\treturn hash32(unsafe.Pointer(_s.ptr), uintptr(_s.length), seed)\n}\n\nfunc hashmapStringPtrHash(sptr unsafe.Pointer, size uintptr, seed uintptr) uint32 {\n\t_s := *(*_string)(sptr)\n\treturn hash32(unsafe.Pointer(_s.ptr), uintptr(_s.length), seed)\n}\n\nfunc hashmapStringSet(m *hashmap, key string, value unsafe.Pointer) {\n\tif m == nil {\n\t\tnilMapPanic()\n\t}\n\thash := hashmapStringHash(key, m.seed)\n\thashmapSet(m, unsafe.Pointer(&key), value, hash)\n}\n\nfunc hashmapStringGet(m *hashmap, key string, value unsafe.Pointer, valueSize uintptr) bool {\n\tif m == nil {\n\t\tmemzero(value, uintptr(valueSize))\n\t\treturn false\n\t}\n\thash := hashmapStringHash(key, m.seed)\n\treturn hashmapGet(m, unsafe.Pointer(&key), value, valueSize, hash)\n}\n\nfunc hashmapStringDelete(m *hashmap, key string) {\n\tif m == nil {\n\t\treturn\n\t}\n\thash := hashmapStringHash(key, m.seed)\n\thashmapDelete(m, unsafe.Pointer(&key), hash)\n}\n\n// Hashmap with interface keys (for everything else).\n\n// This is a method that is intentionally unexported in the reflect package. It\n// is identical to the Interface() method call, except it doesn't check whether\n// a field is exported and thus allows circumventing the type system.\n// The hash function needs it as it also needs to hash unexported struct fields.\n//\n//go:linkname valueInterfaceUnsafe internal/reflectlite.valueInterfaceUnsafe\nfunc valueInterfaceUnsafe(v reflectlite.Value) interface{}\n\nfunc hashmapFloat32Hash(ptr unsafe.Pointer, seed uintptr) uint32 {\n\tf := *(*uint32)(ptr)\n\tif f == 0x80000000 {\n\t\t// convert -0 to 0 for hashing\n\t\tf = 0\n\t}\n\treturn hash32(unsafe.Pointer(&f), 4, seed)\n}\n\nfunc hashmapFloat64Hash(ptr unsafe.Pointer, seed uintptr) uint32 {\n\tf := *(*uint64)(ptr)\n\tif f == 0x8000000000000000 {\n\t\t// convert -0 to 0 for hashing\n\t\tf = 0\n\t}\n\treturn hash32(unsafe.Pointer(&f), 8, seed)\n}\n\nfunc hashmapInterfaceHash(itf interface{}, seed uintptr) uint32 {\n\tx := reflectlite.ValueOf(itf)\n\tif x.RawType() == nil {\n\t\treturn 0 // nil interface\n\t}\n\n\tvalue := (*_interface)(unsafe.Pointer(&itf)).value\n\tptr := value\n\tif x.RawType().Size() <= unsafe.Sizeof(uintptr(0)) {\n\t\t// Value fits in pointer, so it's directly stored in the pointer.\n\t\tptr = unsafe.Pointer(&value)\n\t}\n\n\tswitch x.RawType().Kind() {\n\tcase reflectlite.Int, reflectlite.Int8, reflectlite.Int16, reflectlite.Int32, reflectlite.Int64:\n\t\treturn hash32(ptr, x.RawType().Size(), seed)\n\tcase reflectlite.Bool, reflectlite.Uint, reflectlite.Uint8, reflectlite.Uint16, reflectlite.Uint32, reflectlite.Uint64, reflectlite.Uintptr:\n\t\treturn hash32(ptr, x.RawType().Size(), seed)\n\tcase reflectlite.Float32:\n\t\t// It should be possible to just has the contents. However, NaN != NaN\n\t\t// so if you're using lots of NaNs as map keys (you shouldn't) then hash\n\t\t// time may become exponential. To fix that, it would be better to\n\t\t// return a random number instead:\n\t\t// https://research.swtch.com/randhash\n\t\treturn hashmapFloat32Hash(ptr, seed)\n\tcase reflectlite.Float64:\n\t\treturn hashmapFloat64Hash(ptr, seed)\n\tcase reflectlite.Complex64:\n\t\trptr, iptr := ptr, unsafe.Add(ptr, 4)\n\t\treturn hashmapFloat32Hash(rptr, seed) ^ hashmapFloat32Hash(iptr, seed)\n\tcase reflectlite.Complex128:\n\t\trptr, iptr := ptr, unsafe.Add(ptr, 8)\n\t\treturn hashmapFloat64Hash(rptr, seed) ^ hashmapFloat64Hash(iptr, seed)\n\tcase reflectlite.String:\n\t\treturn hashmapStringHash(x.String(), seed)\n\tcase reflectlite.Chan, reflectlite.Ptr, reflectlite.UnsafePointer:\n\t\t// It might seem better to just return the pointer, but that won't\n\t\t// result in an evenly distributed hashmap. Instead, hash the pointer\n\t\t// like most other types.\n\t\treturn hash32(ptr, x.RawType().Size(), seed)\n\tcase reflectlite.Array:\n\t\tvar hash uint32\n\t\tfor i := 0; i < x.Len(); i++ {\n\t\t\thash ^= hashmapInterfaceHash(valueInterfaceUnsafe(x.Index(i)), seed)\n\t\t}\n\t\treturn hash\n\tcase reflectlite.Struct:\n\t\tvar hash uint32\n\t\tfor i := 0; i < x.NumField(); i++ {\n\t\t\thash ^= hashmapInterfaceHash(valueInterfaceUnsafe(x.Field(i)), seed)\n\t\t}\n\t\treturn hash\n\tdefault:\n\t\truntimePanic(\"comparing un-comparable type\")\n\t\treturn 0 // unreachable\n\t}\n}\n\nfunc hashmapInterfacePtrHash(iptr unsafe.Pointer, size uintptr, seed uintptr) uint32 {\n\t_i := *(*interface{})(iptr)\n\treturn hashmapInterfaceHash(_i, seed)\n}\n\nfunc hashmapInterfaceEqual(x, y unsafe.Pointer, n uintptr) bool {\n\treturn *(*interface{})(x) == *(*interface{})(y)\n}\n\nfunc hashmapInterfaceSet(m *hashmap, key interface{}, value unsafe.Pointer) {\n\tif m == nil {\n\t\tnilMapPanic()\n\t}\n\thash := hashmapInterfaceHash(key, m.seed)\n\thashmapSet(m, unsafe.Pointer(&key), value, hash)\n}\n\nfunc hashmapInterfaceGet(m *hashmap, key interface{}, value unsafe.Pointer, valueSize uintptr) bool {\n\tif m == nil {\n\t\tmemzero(value, uintptr(valueSize))\n\t\treturn false\n\t}\n\thash := hashmapInterfaceHash(key, m.seed)\n\treturn hashmapGet(m, unsafe.Pointer(&key), value, valueSize, hash)\n}\n\nfunc hashmapInterfaceDelete(m *hashmap, key interface{}) {\n\tif m == nil {\n\t\treturn\n\t}\n\thash := hashmapInterfaceHash(key, m.seed)\n\thashmapDelete(m, unsafe.Pointer(&key), hash)\n}\n"
  },
  {
    "path": "src/runtime/hosted.go",
    "content": "//go:build !baremetal\n\npackage runtime\n\nconst baremetal = false\n"
  },
  {
    "path": "src/runtime/interface.go",
    "content": "package runtime\n\n// This file implements Go interfaces.\n//\n// Interfaces are represented as a pair of {typecode, value}, where value can be\n// anything (including non-pointers).\n\nimport (\n\t\"internal/reflectlite\"\n\t\"unsafe\"\n)\n\ntype _interface struct {\n\ttypecode unsafe.Pointer\n\tvalue    unsafe.Pointer\n}\n\n//go:inline\nfunc composeInterface(typecode, value unsafe.Pointer) _interface {\n\treturn _interface{typecode, value}\n}\n\n//go:inline\nfunc decomposeInterface(i _interface) (unsafe.Pointer, unsafe.Pointer) {\n\treturn i.typecode, i.value\n}\n\n// Return true iff both interfaces are equal.\nfunc interfaceEqual(x, y interface{}) bool {\n\treturn reflectValueEqual(reflectlite.ValueOf(x), reflectlite.ValueOf(y))\n}\n\nfunc reflectValueEqual(x, y reflectlite.Value) bool {\n\t// Note: doing a x.Type() == y.Type() comparison would not work here as that\n\t// would introduce an infinite recursion: comparing two reflectlite.Type values\n\t// is done with this reflectValueEqual runtime call.\n\tif x.RawType() == nil || y.RawType() == nil {\n\t\t// One of them is nil.\n\t\treturn x.RawType() == y.RawType()\n\t}\n\n\tif x.RawType() != y.RawType() {\n\t\t// The type is not the same, which means the interfaces are definitely\n\t\t// not the same.\n\t\treturn false\n\t}\n\n\tswitch x.RawType().Kind() {\n\tcase reflectlite.Bool:\n\t\treturn x.Bool() == y.Bool()\n\tcase reflectlite.Int, reflectlite.Int8, reflectlite.Int16, reflectlite.Int32, reflectlite.Int64:\n\t\treturn x.Int() == y.Int()\n\tcase reflectlite.Uint, reflectlite.Uint8, reflectlite.Uint16, reflectlite.Uint32, reflectlite.Uint64, reflectlite.Uintptr:\n\t\treturn x.Uint() == y.Uint()\n\tcase reflectlite.Float32, reflectlite.Float64:\n\t\treturn x.Float() == y.Float()\n\tcase reflectlite.Complex64, reflectlite.Complex128:\n\t\treturn x.Complex() == y.Complex()\n\tcase reflectlite.String:\n\t\treturn x.String() == y.String()\n\tcase reflectlite.Chan, reflectlite.Ptr, reflectlite.UnsafePointer:\n\t\treturn x.UnsafePointer() == y.UnsafePointer()\n\tcase reflectlite.Array:\n\t\tfor i := 0; i < x.Len(); i++ {\n\t\t\tif !reflectValueEqual(x.Index(i), y.Index(i)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\tcase reflectlite.Struct:\n\t\tfor i := 0; i < x.NumField(); i++ {\n\t\t\tif !reflectValueEqual(x.Field(i), y.Field(i)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\tcase reflectlite.Interface:\n\t\treturn reflectValueEqual(x.Elem(), y.Elem())\n\tdefault:\n\t\truntimePanic(\"comparing un-comparable type\")\n\t\treturn false // unreachable\n\t}\n}\n\n// interfaceTypeAssert is called when a type assert without comma-ok still\n// returns false.\nfunc interfaceTypeAssert(ok bool) {\n\tif !ok {\n\t\truntimePanic(\"type assert failed\")\n\t}\n}\n\n// The following declarations are only used during IR construction. They are\n// lowered to inline IR in the interface lowering pass.\n// See compiler/interface-lowering.go for details.\n\ntype structField struct {\n\ttypecode unsafe.Pointer // type of this struct field\n\tdata     *uint8         // pointer to byte array containing name, tag, varint-encoded offset, and some flags\n}\n\n// Pseudo function call used during a type assert. It is used during interface\n// lowering, to assign the lowest type numbers to the types with the most type\n// asserts. Also, it is replaced with const false if this type assert can never\n// happen.\nfunc typeAssert(actualType unsafe.Pointer, assertedType *uint8) bool\n"
  },
  {
    "path": "src/runtime/internal/sys/zversion.go",
    "content": "package sys\n\nconst TheVersion = `go0.1.0`\n"
  },
  {
    "path": "src/runtime/interrupt/checkpoint.go",
    "content": "package interrupt\n\n// A checkpoint is a setjmp like buffer, that can be used as a flag for\n// interrupts.\n//\n// It can be used as follows:\n//\n//\t// global var\n//\tvar c Checkpoint\n//\n//\t// to set up the checkpoint and wait for it\n//\tif c.Save() {\n//\t\tsetupInterrupt()\n//\t\tfor {\n//\t\t\twaitForInterrupt()\n//\t\t}\n//\t}\n//\n//\t// Inside the interrupt handler:\n//\tif c.Saved() {\n//\t\tc.Jump()\n//\t}\ntype Checkpoint struct {\n\tjumpSP uintptr\n\tjumpPC uintptr\n}\n\n// Save the execution state in the given checkpoint, overwriting a previous\n// saved checkpoint.\n//\n// This function returns twice: once the normal way after saving (returning\n// true) and once after jumping (returning false).\n//\n// This function is a compiler intrinsic, it is not implemented in Go.\nfunc (c *Checkpoint) Save() bool\n\n// Returns whether a jump point was saved (and not erased due to a jump).\nfunc (c *Checkpoint) Saved() bool {\n\treturn c.jumpPC != 0\n}\n\n// Jump to the point where the execution state was saved, and erase the saved\n// jump point. This must *only* be called from inside an interrupt.\n//\n// This method does not return in the conventional way, it resumes execution at\n// the last point a checkpoint was saved.\nfunc (c *Checkpoint) Jump() {\n\tif !c.Saved() {\n\t\tpanic(\"runtime/interrupt: no checkpoint was saved\")\n\t}\n\tjumpPC := c.jumpPC\n\tjumpSP := c.jumpSP\n\tc.jumpPC = 0\n\tc.jumpSP = 0\n\tif jumpPC == 0 {\n\t\tpanic(\"jumping to 0\")\n\t}\n\tcheckpointJump(jumpSP, jumpPC)\n}\n\n//export tinygo_checkpointJump\nfunc checkpointJump(jumpSP, jumpPC uintptr)\n"
  },
  {
    "path": "src/runtime/interrupt/interrupt.go",
    "content": "// Package interrupt provides access to hardware interrupts. It provides a way\n// to define interrupts and to enable/disable them.\npackage interrupt\n\nimport \"unsafe\"\n\n// Interrupt provides direct access to hardware interrupts. You can configure\n// this interrupt through this interface.\n//\n// Do not use the zero value of an Interrupt object. Instead, call New to obtain\n// an interrupt handle.\ntype Interrupt struct {\n\t// Make this number unexported so it cannot be set directly. This provides\n\t// some encapsulation.\n\tnum int\n}\n\n// New is a compiler intrinsic that creates a new Interrupt object. You may call\n// it only once, and must pass constant parameters to it. That means that the\n// interrupt ID must be a Go constant and that the handler must be a simple\n// function: closures are not supported.\nfunc New(id int, handler func(Interrupt)) Interrupt\n\n// handle is used internally, between IR generation and interrupt lowering. The\n// frontend will create runtime/interrupt.handle objects, cast them to an int,\n// and use that in an Interrupt object. That way the compiler will be able to\n// optimize away all interrupt handles that are never used in a program.\n// This system only works when interrupts need to be enabled before use and this\n// is done only through calling Enable() on this object. If interrupts cannot\n// individually be enabled/disabled, the compiler should create a pseudo-call\n// (like runtime/interrupt.use()) that keeps the interrupt alive.\ntype handle struct {\n\tcontext unsafe.Pointer\n\tfuncPtr uintptr\n\tInterrupt\n}\n"
  },
  {
    "path": "src/runtime/interrupt/interrupt_avr.go",
    "content": "//go:build avr\n\npackage interrupt\n\nimport \"device\"\n\n// State represents the previous global interrupt state.\ntype State uint8\n\n// Disable disables all interrupts and returns the previous interrupt state. It\n// can be used in a critical section like this:\n//\n//\tstate := interrupt.Disable()\n//\t// critical section\n//\tinterrupt.Restore(state)\n//\n// Critical sections can be nested. Make sure to call Restore in the same order\n// as you called Disable (this happens naturally with the pattern above).\nfunc Disable() (state State) {\n\t// SREG is at I/O address 0x3f.\n\treturn State(device.AsmFull(`\n\t\tin {}, 0x3f\n\t\tcli\n\t`, nil))\n}\n\n// Restore restores interrupts to what they were before. Give the previous state\n// returned by Disable as a parameter. If interrupts were disabled before\n// calling Disable, this will not re-enable interrupts, allowing for nested\n// critical sections.\nfunc Restore(state State) {\n\t// SREG is at I/O address 0x3f.\n\tdevice.AsmFull(\"out 0x3f, {state}\", map[string]interface{}{\n\t\t\"state\": state,\n\t})\n}\n\n// In returns whether the system is currently in an interrupt.\n//\n// Warning: this always returns false on AVR, as there does not appear to be a\n// reliable way to determine whether we're currently running inside an interrupt\n// handler.\nfunc In() bool {\n\treturn false\n}\n"
  },
  {
    "path": "src/runtime/interrupt/interrupt_cortexm.go",
    "content": "//go:build cortexm\n\npackage interrupt\n\nimport (\n\t\"device/arm\"\n)\n\n// Enable enables this interrupt. Right after calling this function, the\n// interrupt may be invoked if it was already pending.\nfunc (irq Interrupt) Enable() {\n\t// Clear the ARM pending bit, an asserting device may still\n\t// trigger the interrupt once enabled.\n\tarm.ClearPendingIRQ(uint32(irq.num))\n\tarm.EnableIRQ(uint32(irq.num))\n}\n\n// Disable disables this interrupt.\nfunc (irq Interrupt) Disable() {\n\tarm.DisableIRQ(uint32(irq.num))\n}\n\n// SetPriority sets the interrupt priority for this interrupt. A lower number\n// means a higher priority. Additionally, most hardware doesn't implement all\n// priority bits (only the uppoer bits).\n//\n// Examples: 0xff (lowest priority), 0xc0 (low priority), 0x00 (highest possible\n// priority).\nfunc (irq Interrupt) SetPriority(priority uint8) {\n\tarm.SetPriority(uint32(irq.num), uint32(priority))\n}\n\n// State represents the previous global interrupt state.\ntype State uintptr\n\n// Disable disables all interrupts and returns the previous interrupt state. It\n// can be used in a critical section like this:\n//\n//\tstate := interrupt.Disable()\n//\t// critical section\n//\tinterrupt.Restore(state)\n//\n// Critical sections can be nested. Make sure to call Restore in the same order\n// as you called Disable (this happens naturally with the pattern above).\nfunc Disable() (state State) {\n\treturn State(arm.DisableInterrupts())\n}\n\n// Restore restores interrupts to what they were before. Give the previous state\n// returned by Disable as a parameter. If interrupts were disabled before\n// calling Disable, this will not re-enable interrupts, allowing for nested\n// critical sections.\nfunc Restore(state State) {\n\tarm.EnableInterrupts(uintptr(state))\n}\n\n// In returns whether the system is currently in an interrupt.\nfunc In() bool {\n\t// The VECTACTIVE field gives the instruction vector that is currently\n\t// active (in handler mode), or 0 if not in an interrupt.\n\t// Documentation:\n\t// https://developer.arm.com/documentation/dui0497/a/cortex-m0-peripherals/system-control-block/interrupt-control-and-state-register\n\tvectactive := uint8(arm.SCB.ICSR.Get())\n\treturn vectactive != 0\n}\n"
  },
  {
    "path": "src/runtime/interrupt/interrupt_esp32c3.go",
    "content": "//go:build esp32c3\n\npackage interrupt\n\nimport (\n\t\"device/esp\"\n\t\"device/riscv\"\n\t\"errors\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\n// Enable register CPU interrupt with interrupt.Interrupt.\n// The ESP32-C3 has 31 CPU independent interrupts.\n// The Interrupt.New(x, f) (x = [1..31]) attaches CPU interrupt to function f.\n// Caller must map the selected interrupt using following sequence (for example using id 5):\n//\n//\t// map interrupt 5 to my XXXX module\n//\tesp.INTERRUPT_CORE0.XXXX_INTERRUPT_PRO_MAP.Set( 5 )\n//\t_ = Interrupt.New(5, func(interrupt.Interrupt) {\n//\t    ...\n//\t}).Enable()\nfunc (i Interrupt) Enable() error {\n\tif i.num < 1 && i.num > 31 {\n\t\treturn errors.New(\"interrupt for ESP32-C3 must be in range of 1 through 31\")\n\t}\n\tmask := riscv.DisableInterrupts()\n\tdefer riscv.EnableInterrupts(mask)\n\n\t// enable CPU interrupt number i.num\n\tesp.INTERRUPT_CORE0.CPU_INT_ENABLE.SetBits(1 << i.num)\n\n\t// Set pulse interrupt type (rising edge detection)\n\tesp.INTERRUPT_CORE0.CPU_INT_TYPE.SetBits(1 << i.num)\n\n\t// Set default threshold to defaultThreshold\n\treg := (*volatile.Register32)(unsafe.Add(unsafe.Pointer(&esp.INTERRUPT_CORE0.CPU_INT_PRI_0), i.num*4))\n\treg.Set(defaultThreshold)\n\n\t// Reset interrupt before reenabling\n\tesp.INTERRUPT_CORE0.CPU_INT_CLEAR.SetBits(1 << i.num)\n\tesp.INTERRUPT_CORE0.CPU_INT_CLEAR.ClearBits(1 << i.num)\n\n\t// we must wait for any pending write operations to complete\n\triscv.Asm(\"fence\")\n\treturn nil\n}\n\n// Adding pseudo function calls that is replaced by the compiler with the actual\n// functions registered through interrupt.New.\n//\n//go:linkname callHandlers runtime/interrupt.callHandlers\nfunc callHandlers(num int)\n\nconst (\n\tIRQNUM_1 = 1 + iota\n\tIRQNUM_2\n\tIRQNUM_3\n\tIRQNUM_4\n\tIRQNUM_5\n\tIRQNUM_6\n\tIRQNUM_7\n\tIRQNUM_8\n\tIRQNUM_9\n\tIRQNUM_10\n\tIRQNUM_11\n\tIRQNUM_12\n\tIRQNUM_13\n\tIRQNUM_14\n\tIRQNUM_15\n\tIRQNUM_16\n\tIRQNUM_17\n\tIRQNUM_18\n\tIRQNUM_19\n\tIRQNUM_20\n\tIRQNUM_21\n\tIRQNUM_22\n\tIRQNUM_23\n\tIRQNUM_24\n\tIRQNUM_25\n\tIRQNUM_26\n\tIRQNUM_27\n\tIRQNUM_28\n\tIRQNUM_29\n\tIRQNUM_30\n\tIRQNUM_31\n)\n\nconst (\n\tdefaultThreshold = 5\n\tdisableThreshold = 10\n)\n\n//go:inline\nfunc callHandler(n int) {\n\tswitch n {\n\tcase IRQNUM_1:\n\t\tcallHandlers(IRQNUM_1)\n\tcase IRQNUM_2:\n\t\tcallHandlers(IRQNUM_2)\n\tcase IRQNUM_3:\n\t\tcallHandlers(IRQNUM_3)\n\tcase IRQNUM_4:\n\t\tcallHandlers(IRQNUM_4)\n\tcase IRQNUM_5:\n\t\tcallHandlers(IRQNUM_5)\n\tcase IRQNUM_6:\n\t\tcallHandlers(IRQNUM_6)\n\tcase IRQNUM_7:\n\t\tcallHandlers(IRQNUM_7)\n\tcase IRQNUM_8:\n\t\tcallHandlers(IRQNUM_8)\n\tcase IRQNUM_9:\n\t\tcallHandlers(IRQNUM_9)\n\tcase IRQNUM_10:\n\t\tcallHandlers(IRQNUM_10)\n\tcase IRQNUM_11:\n\t\tcallHandlers(IRQNUM_11)\n\tcase IRQNUM_12:\n\t\tcallHandlers(IRQNUM_12)\n\tcase IRQNUM_13:\n\t\tcallHandlers(IRQNUM_13)\n\tcase IRQNUM_14:\n\t\tcallHandlers(IRQNUM_14)\n\tcase IRQNUM_15:\n\t\tcallHandlers(IRQNUM_15)\n\tcase IRQNUM_16:\n\t\tcallHandlers(IRQNUM_16)\n\tcase IRQNUM_17:\n\t\tcallHandlers(IRQNUM_17)\n\tcase IRQNUM_18:\n\t\tcallHandlers(IRQNUM_18)\n\tcase IRQNUM_19:\n\t\tcallHandlers(IRQNUM_19)\n\tcase IRQNUM_20:\n\t\tcallHandlers(IRQNUM_20)\n\tcase IRQNUM_21:\n\t\tcallHandlers(IRQNUM_21)\n\tcase IRQNUM_22:\n\t\tcallHandlers(IRQNUM_22)\n\tcase IRQNUM_23:\n\t\tcallHandlers(IRQNUM_23)\n\tcase IRQNUM_24:\n\t\tcallHandlers(IRQNUM_24)\n\tcase IRQNUM_25:\n\t\tcallHandlers(IRQNUM_25)\n\tcase IRQNUM_26:\n\t\tcallHandlers(IRQNUM_26)\n\tcase IRQNUM_27:\n\t\tcallHandlers(IRQNUM_27)\n\tcase IRQNUM_28:\n\t\tcallHandlers(IRQNUM_28)\n\tcase IRQNUM_29:\n\t\tcallHandlers(IRQNUM_29)\n\tcase IRQNUM_30:\n\t\tcallHandlers(IRQNUM_30)\n\tcase IRQNUM_31:\n\t\tcallHandlers(IRQNUM_31)\n\t}\n}\n\n//export handleInterrupt\nfunc handleInterrupt() {\n\tmcause := riscv.MCAUSE.Get()\n\texception := mcause&(1<<31) == 0\n\tinterruptNumber := uint32(mcause & 0x1f)\n\n\tif !exception && interruptNumber > 0 {\n\t\t// save MSTATUS & MEPC, which could be overwritten by another CPU interrupt\n\t\tmstatus := riscv.MSTATUS.Get()\n\t\tmepc := riscv.MEPC.Get()\n\t\t// Using threshold to temporary disable this interrupts.\n\t\t// FYI: using CPU interrupt enable bit make runtime to loose interrupts.\n\t\treg := (*volatile.Register32)(unsafe.Add(unsafe.Pointer(&esp.INTERRUPT_CORE0.CPU_INT_PRI_0), interruptNumber*4))\n\t\tthresholdSave := reg.Get()\n\t\treg.Set(disableThreshold)\n\t\triscv.Asm(\"fence\")\n\n\t\tinterruptBit := uint32(1 << interruptNumber)\n\n\t\t// reset pending status interrupt\n\t\tif esp.INTERRUPT_CORE0.CPU_INT_TYPE.Get()&interruptBit != 0 {\n\t\t\t// this is edge type interrupt\n\t\t\tesp.INTERRUPT_CORE0.CPU_INT_CLEAR.SetBits(interruptBit)\n\t\t\tesp.INTERRUPT_CORE0.CPU_INT_CLEAR.ClearBits(interruptBit)\n\t\t} else {\n\t\t\t// this is level type interrupt\n\t\t\tesp.INTERRUPT_CORE0.CPU_INT_CLEAR.ClearBits(interruptBit)\n\t\t}\n\n\t\t// enable CPU interrupts\n\t\triscv.MSTATUS.SetBits(riscv.MSTATUS_MIE)\n\n\t\t// Call registered interrupt handler(s)\n\t\tcallHandler(int(interruptNumber))\n\n\t\t// disable CPU interrupts\n\t\triscv.MSTATUS.ClearBits(riscv.MSTATUS_MIE)\n\n\t\t// restore interrupt threshold to enable interrupt again\n\t\treg.Set(thresholdSave)\n\t\triscv.Asm(\"fence\")\n\n\t\t// restore MSTATUS & MEPC\n\t\triscv.MSTATUS.Set(mstatus)\n\t\triscv.MEPC.Set(mepc)\n\n\t\t// do not enable CPU interrupts now\n\t\t// the 'MRET' in src/device/riscv/handleinterrupt.S will copies the state of MPIE back into MIE, and subsequently clears MPIE.\n\t\t// riscv.MSTATUS.SetBits(riscv.MSTATUS_MIE)\n\t} else {\n\t\t// Topmost bit is clear, so it is an exception of some sort.\n\t\t// We could implement support for unsupported instructions here (such as\n\t\t// misaligned loads). However, for now we'll just print a fatal error.\n\t\thandleException(mcause)\n\t}\n}\n\nfunc handleException(mcause uintptr) {\n\tprintln(\"*** Exception:     pc:\", riscv.MEPC.Get())\n\tprintln(\"*** Exception:   code:\", uint32(mcause&0x1f))\n\tprintln(\"*** Exception: mcause:\", mcause)\n\tswitch uint32(mcause & 0x1f) {\n\tcase riscv.InstructionAccessFault:\n\t\tprintln(\"***    virtual address:\", riscv.MTVAL.Get())\n\tcase riscv.IllegalInstruction:\n\t\tprintln(\"***            opcode:\", riscv.MTVAL.Get())\n\tcase riscv.LoadAccessFault:\n\t\tprintln(\"***      read address:\", riscv.MTVAL.Get())\n\tcase riscv.StoreOrAMOAccessFault:\n\t\tprintln(\"***     write address:\", riscv.MTVAL.Get())\n\t}\n\tfor {\n\t\triscv.Asm(\"wfi\")\n\t}\n}\n"
  },
  {
    "path": "src/runtime/interrupt/interrupt_gameboyadvance.go",
    "content": "//go:build gameboyadvance\n\npackage interrupt\n\n// This is good documentation of the GBA: https://www.akkit.org/info/gbatek.htm\n\nimport (\n\t\"device/gba\"\n)\n\n// Enable enables this interrupt. Right after calling this function, the\n// interrupt may be invoked if it was already pending.\nfunc (irq Interrupt) Enable() {\n\tgba.INTERRUPT.IE.SetBits(1 << uint(irq.num))\n}\n\nvar inInterrupt bool\n\n//export handleInterrupt\nfunc handleInterrupt() {\n\tinInterrupt = true\n\tflags := gba.INTERRUPT.IF.Get()\n\tfor i := 0; i < 14; i++ {\n\t\tif flags&(1<<uint(i)) != 0 {\n\t\t\tgba.INTERRUPT.IF.Set(1 << uint(i)) // acknowledge interrupt\n\t\t\tcallInterruptHandler(i)\n\t\t}\n\t}\n\tinInterrupt = false\n}\n\n// Pseudo function call that is replaced by the compiler with the actual\n// functions registered through interrupt.New. If there are none, calls will be\n// replaced with 'unreachablecalls will be replaced with 'unreachable'.\n//\n//go:linkname callHandlers runtime/interrupt.callHandlers\nfunc callHandlers(num int)\n\nfunc callInterruptHandler(id int) {\n\tswitch id {\n\tcase gba.IRQ_VBLANK:\n\t\tcallHandlers(gba.IRQ_VBLANK)\n\tcase gba.IRQ_HBLANK:\n\t\tcallHandlers(gba.IRQ_HBLANK)\n\tcase gba.IRQ_VCOUNT:\n\t\tcallHandlers(gba.IRQ_VCOUNT)\n\tcase gba.IRQ_TIMER0:\n\t\tcallHandlers(gba.IRQ_TIMER0)\n\tcase gba.IRQ_TIMER1:\n\t\tcallHandlers(gba.IRQ_TIMER1)\n\tcase gba.IRQ_TIMER2:\n\t\tcallHandlers(gba.IRQ_TIMER2)\n\tcase gba.IRQ_TIMER3:\n\t\tcallHandlers(gba.IRQ_TIMER3)\n\tcase gba.IRQ_COM:\n\t\tcallHandlers(gba.IRQ_COM)\n\tcase gba.IRQ_DMA0:\n\t\tcallHandlers(gba.IRQ_DMA0)\n\tcase gba.IRQ_DMA1:\n\t\tcallHandlers(gba.IRQ_DMA1)\n\tcase gba.IRQ_DMA2:\n\t\tcallHandlers(gba.IRQ_DMA2)\n\tcase gba.IRQ_DMA3:\n\t\tcallHandlers(gba.IRQ_DMA3)\n\tcase gba.IRQ_KEYPAD:\n\t\tcallHandlers(gba.IRQ_KEYPAD)\n\tcase gba.IRQ_GAMEPAK:\n\t\tcallHandlers(gba.IRQ_GAMEPAK)\n\t}\n}\n\n// State represents the previous global interrupt state.\ntype State uint8\n\n// Disable disables all interrupts and returns the previous interrupt state. It\n// can be used in a critical section like this:\n//\n//\tstate := interrupt.Disable()\n//\t// critical section\n//\tinterrupt.Restore(state)\n//\n// Critical sections can be nested. Make sure to call Restore in the same order\n// as you called Disable (this happens naturally with the pattern above).\nfunc Disable() (state State) {\n\t// Save the previous interrupt state.\n\tstate = State(gba.INTERRUPT.PAUSE.Get())\n\t// Disable all interrupts.\n\tgba.INTERRUPT.PAUSE.Set(0)\n\treturn\n}\n\n// Restore restores interrupts to what they were before. Give the previous state\n// returned by Disable as a parameter. If interrupts were disabled before\n// calling Disable, this will not re-enable interrupts, allowing for nested\n// critical sections.\nfunc Restore(state State) {\n\t// Restore interrupts to the previous state.\n\tgba.INTERRUPT.PAUSE.Set(uint16(state))\n}\n\n// In returns whether the system is currently in an interrupt.\nfunc In() bool {\n\treturn inInterrupt\n}\n"
  },
  {
    "path": "src/runtime/interrupt/interrupt_k210.go",
    "content": "//go:build k210\n\npackage interrupt\n\nimport (\n\t\"device/kendryte\"\n\t\"device/riscv\"\n)\n\n// Enable enables this interrupt. Right after calling this function, the\n// interrupt may be invoked if it was already pending.\nfunc (irq Interrupt) Enable() {\n\thartId := riscv.MHARTID.Get()\n\tkendryte.PLIC.TARGET_ENABLES[hartId].ENABLE[irq.num/32].SetBits(1 << (uint(irq.num) % 32))\n}\n\n// SetPriority sets the interrupt priority for this interrupt. A higher priority\n// number means a higher priority (unlike Cortex-M). Priority 0 effectively\n// disables the interrupt.\nfunc (irq Interrupt) SetPriority(priority uint8) {\n\tkendryte.PLIC.PRIORITY[irq.num].Set(uint32(priority))\n}\n\n// GetNumber returns the interrupt number for this interrupt.\nfunc (irq Interrupt) GetNumber() int {\n\treturn irq.num\n}\n"
  },
  {
    "path": "src/runtime/interrupt/interrupt_none.go",
    "content": "//go:build !baremetal || tkey\n\npackage interrupt\n\n// State represents the previous global interrupt state.\ntype State uintptr\n\n// Disable disables all interrupts and returns the previous interrupt state. It\n// can be used in a critical section like this:\n//\n//\tstate := interrupt.Disable()\n//\t// critical section\n//\tinterrupt.Restore(state)\n//\n// Critical sections can be nested. Make sure to call Restore in the same order\n// as you called Disable (this happens naturally with the pattern above).\nfunc Disable() (state State) {\n\treturn 0\n}\n\n// Restore restores interrupts to what they were before. Give the previous state\n// returned by Disable as a parameter. If interrupts were disabled before\n// calling Disable, this will not re-enable interrupts, allowing for nested\n// critical sections.\nfunc Restore(state State) {}\n\n// In returns whether the system is currently in an interrupt.\nfunc In() bool {\n\t// There are no interrupts, so it can't be in one.\n\treturn false\n}\n"
  },
  {
    "path": "src/runtime/interrupt/interrupt_sifive.go",
    "content": "//go:build sifive\n\npackage interrupt\n\nimport \"device/sifive\"\n\n// Enable enables this interrupt. Right after calling this function, the\n// interrupt may be invoked if it was already pending.\nfunc (irq Interrupt) Enable() {\n\tsifive.PLIC.ENABLE[irq.num/32].SetBits(1 << (uint(irq.num) % 32))\n}\n\n// SetPriority sets the interrupt priority for this interrupt. A higher priority\n// number means a higher priority (unlike Cortex-M). Priority 0 effectively\n// disables the interrupt.\nfunc (irq Interrupt) SetPriority(priority uint8) {\n\tsifive.PLIC.PRIORITY[irq.num].Set(uint32(priority))\n}\n"
  },
  {
    "path": "src/runtime/interrupt/interrupt_tinygoriscv.go",
    "content": "//go:build tinygo.riscv && !tkey\n\npackage interrupt\n\nimport \"device/riscv\"\n\n// State represents the previous global interrupt state.\ntype State uintptr\n\n// Disable disables all interrupts and returns the previous interrupt state. It\n// can be used in a critical section like this:\n//\n//\tstate := interrupt.Disable()\n//\t// critical section\n//\tinterrupt.Restore(state)\n//\n// Critical sections can be nested. Make sure to call Restore in the same order\n// as you called Disable (this happens naturally with the pattern above).\nfunc Disable() (state State) {\n\treturn State(riscv.DisableInterrupts())\n}\n\n// Restore restores interrupts to what they were before. Give the previous state\n// returned by Disable as a parameter. If interrupts were disabled before\n// calling Disable, this will not re-enable interrupts, allowing for nested\n// critical sections.\nfunc Restore(state State) {\n\triscv.EnableInterrupts(uintptr(state))\n}\n\n// In returns whether the system is currently in an interrupt.\nfunc In() bool {\n\t// There is one exception that has the value 0 (instruction address\n\t// misaligned), but it's not very likely and even if it happens, it's not\n\t// really something that can be recovered from. Therefore I think it's safe\n\t// to ignore it. It's handled specially (in handleException).\n\treturn riscv.MCAUSE.Get() != 0\n}\n"
  },
  {
    "path": "src/runtime/interrupt/interrupt_xtensa.go",
    "content": "//go:build xtensa\n\npackage interrupt\n\nimport \"device\"\n\n// State represents the previous global interrupt state.\ntype State uintptr\n\n// Disable disables all interrupts and returns the previous interrupt state. It\n// can be used in a critical section like this:\n//\n//\tstate := interrupt.Disable()\n//\t// critical section\n//\tinterrupt.Restore(state)\n//\n// Critical sections can be nested. Make sure to call Restore in the same order\n// as you called Disable (this happens naturally with the pattern above).\nfunc Disable() (state State) {\n\treturn State(device.AsmFull(\"rsil {}, 15\", nil))\n}\n\n// Restore restores interrupts to what they were before. Give the previous state\n// returned by Disable as a parameter. If interrupts were disabled before\n// calling Disable, this will not re-enable interrupts, allowing for nested\n// critical sections.\nfunc Restore(state State) {\n\tdevice.AsmFull(\"wsr {state}, PS\", map[string]interface{}{\n\t\t\"state\": state,\n\t})\n}\n\n// In returns whether the system is currently in an interrupt.\n//\n// Warning: interrupts have not been implemented for Xtensa yet so this always\n// returns false.\nfunc In() bool {\n\treturn false\n}\n"
  },
  {
    "path": "src/runtime/memhash_fnv.go",
    "content": "//go:build (!wasip1 && !runtime_memhash_tsip && !runtime_memhash_leveldb) || (wasip1 && runtime_memhash_fnv)\n\n// This is the default for all targets except WASI, unless a more specific build\n// tag is set.\n\npackage runtime\n\nimport \"unsafe\"\n\n// Get FNV-1a hash of the given memory buffer.\n//\n// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash\nfunc hash32(ptr unsafe.Pointer, n, seed uintptr) uint32 {\n\tvar result uint32 = 2166136261 // FNV offset basis\n\tresult *= uint32(seed)\n\tfor i := uintptr(0); i < n; i++ {\n\t\tc := *(*uint8)(unsafe.Add(ptr, i))\n\t\tresult ^= uint32(c) // XOR with byte\n\t\tresult *= 16777619  // FNV prime\n\t}\n\treturn result\n}\n\n// Also a FNV-1a hash.\nfunc hash64(ptr unsafe.Pointer, n, seed uintptr) uint64 {\n\tvar result uint64 = 14695981039346656037 // FNV offset basis\n\tresult *= uint64(seed)\n\tfor i := uintptr(0); i < n; i++ {\n\t\tc := *(*uint8)(unsafe.Add(ptr, i))\n\t\tresult ^= uint64(c)     // XOR with byte\n\t\tresult *= 1099511628211 // FNV prime\n\t}\n\treturn result\n}\n"
  },
  {
    "path": "src/runtime/memhash_leveldb.go",
    "content": "//go:build runtime_memhash_leveldb || (wasip1 && !runtime_memhash_fnv && !runtime_memhash_tsip)\n\n// This is the default for WASI, but can also be used on other targets with the\n// right build tag.\n\n// This is the hash function from Google's leveldb key-value storage system. It\n// processes 4 bytes at a time making it faster than the FNV hash for buffer\n// lengths > 16 bytes.\n\n// https://github.com/google/leveldb\n// https://en.wikipedia.org/wiki/LevelDB\n\npackage runtime\n\nimport (\n\t\"unsafe\"\n)\n\n// leveldb hash\nfunc hash32(ptr unsafe.Pointer, n, seed uintptr) uint32 {\n\n\tconst (\n\t\tlseed = 0xbc9f1d34\n\t\tm     = 0xc6a4a793\n\t)\n\n\tb := unsafe.Slice((*byte)(ptr), n)\n\n\th := uint32(lseed^seed) ^ uint32(uint(len(b))*uint(m))\n\n\tfor ; len(b) >= 4; b = b[4:] {\n\t\th += uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24\n\t\th *= m\n\t\th ^= h >> 16\n\t}\n\tswitch len(b) {\n\tcase 3:\n\t\th += uint32(b[2]) << 16\n\t\tfallthrough\n\tcase 2:\n\t\th += uint32(b[1]) << 8\n\t\tfallthrough\n\tcase 1:\n\t\th += uint32(b[0])\n\t\th *= m\n\t\th ^= h >> 24\n\t}\n\n\treturn h\n}\n\n// hash64finalizer is a 64-bit integer mixing function from\n// https://web.archive.org/web/20120720045250/http://www.cris.com/~Ttwang/tech/inthash.htm\nfunc hash64finalizer(key uint64) uint64 {\n\tkey = ^key + (key << 21) // key = (key << 21) - key - 1;\n\tkey = key ^ (key >> 24)\n\tkey = (key + (key << 3)) + (key << 8) // key * 265\n\tkey = key ^ (key >> 14)\n\tkey = (key + (key << 2)) + (key << 4) // key * 21\n\tkey = key ^ (key >> 28)\n\tkey = key + (key << 31)\n\treturn key\n}\n\n// hash64 turns hash32 into a 64-bit hash, by use hash64finalizer to\n// mix the result of hash32 function combined with an xorshifted version of\n// the seed.\nfunc hash64(ptr unsafe.Pointer, n, seed uintptr) uint64 {\n\th32 := hash32(ptr, n, seed)\n\treturn hash64finalizer((uint64(h32^xorshift32(uint32(seed))) << 32) | uint64(h32))\n}\n"
  },
  {
    "path": "src/runtime/memhash_tsip.go",
    "content": "//go:build runtime_memhash_tsip\n\n// This is the tsip hash developed by Damian Gryski, based on ideas from SipHash.\n// It is slower than leveldb's hash, but should be \"stronger\".\n\n// https://en.wikipedia.org/wiki/SipHash\n// https://github.com/veorq/SipHash\n// https://github.com/dgryski/tsip\n\npackage runtime\n\nimport (\n\t\"internal/binary\"\n\t\"math/bits\"\n\t\"unsafe\"\n)\n\ntype sip struct {\n\tv0, v1 uint64\n}\n\nfunc (s *sip) round() {\n\ts.v0 += s.v1\n\ts.v1 = bits.RotateLeft64(s.v1, 13) ^ s.v0\n\ts.v0 = bits.RotateLeft64(s.v0, 35) + s.v1\n\ts.v1 = bits.RotateLeft64(s.v1, 17) ^ s.v0\n\ts.v0 = bits.RotateLeft64(s.v0, 21)\n}\n\nfunc hash64(ptr unsafe.Pointer, n uintptr, seed uintptr) uint64 {\n\tp := unsafe.Slice((*byte)(ptr), n)\n\n\tk0 := uint64(seed)\n\tk1 := uint64(0)\n\n\ts := sip{\n\t\tv0: k0 ^ 0x736f6d6570736575,\n\t\tv1: k1 ^ 0x646f72616e646f6d,\n\t}\n\n\tb := uint64(len(p)) << 56\n\n\tfor len(p) >= 8 {\n\t\tm := binary.LittleEndian.Uint64(p[:8])\n\t\ts.v1 ^= m\n\t\ts.round()\n\t\ts.v0 ^= m\n\t\tp = p[8:]\n\t}\n\n\tswitch len(p) {\n\tcase 7:\n\t\tb |= uint64(p[6]) << 48\n\t\tfallthrough\n\tcase 6:\n\t\tb |= uint64(p[5]) << 40\n\t\tfallthrough\n\tcase 5:\n\t\tb |= uint64(p[4]) << 32\n\t\tfallthrough\n\tcase 4:\n\t\tb |= uint64(p[3]) << 24\n\t\tfallthrough\n\tcase 3:\n\t\tb |= uint64(p[2]) << 16\n\t\tfallthrough\n\tcase 2:\n\t\tb |= uint64(p[1]) << 8\n\t\tfallthrough\n\tcase 1:\n\t\tb |= uint64(p[0])\n\t}\n\n\t// last block\n\ts.v1 ^= b\n\ts.round()\n\ts.v0 ^= b\n\n\t// finalization\n\ts.v1 ^= 0xff\n\ts.round()\n\ts.v1 = bits.RotateLeft64(s.v1, 32)\n\ts.round()\n\ts.v1 = bits.RotateLeft64(s.v1, 32)\n\n\treturn s.v0 ^ s.v1\n}\n\ntype sip32 struct {\n\tv0, v1 uint32\n}\n\nfunc (s *sip32) round() {\n\ts.v0 += s.v1\n\ts.v1 = bits.RotateLeft32(s.v1, 5) ^ s.v0\n\ts.v0 = bits.RotateLeft32(s.v0, 8) + s.v1\n\ts.v1 = bits.RotateLeft32(s.v1, 13) ^ s.v0\n\ts.v0 = bits.RotateLeft32(s.v0, 7)\n}\n\nfunc hash32(ptr unsafe.Pointer, n uintptr, seed uintptr) uint32 {\n\tp := unsafe.Slice((*byte)(ptr), n)\n\n\tk0 := uint32(seed)\n\tk1 := uint32(seed >> 32)\n\n\ts := sip32{\n\t\tv0: k0 ^ 0x74656462,\n\t\tv1: k1 ^ 0x6c796765,\n\t}\n\tb := uint32(len(p)) << 24\n\n\tfor len(p) >= 4 {\n\t\tm := binary.LittleEndian.Uint32(p[:4])\n\t\ts.v1 ^= m\n\t\ts.round()\n\t\ts.v0 ^= m\n\t\tp = p[4:]\n\t}\n\n\tswitch len(p) {\n\tcase 3:\n\t\tb |= uint32(p[2]) << 16\n\t\tfallthrough\n\tcase 2:\n\t\tb |= uint32(p[1]) << 8\n\t\tfallthrough\n\tcase 1:\n\t\tb |= uint32(p[0])\n\t}\n\n\t// last block\n\ts.v1 ^= b\n\ts.round()\n\ts.v0 ^= b\n\n\t// finalization\n\ts.v1 ^= 0xff\n\ts.round()\n\ts.v1 = bits.RotateLeft32(s.v1, 16)\n\ts.round()\n\ts.v1 = bits.RotateLeft32(s.v1, 16)\n\n\treturn s.v0 ^ s.v1\n}\n"
  },
  {
    "path": "src/runtime/metrics/metrics.go",
    "content": "// Package metrics is a dummy package that is not yet implemented.\n\npackage metrics\n\ntype Description struct {\n\tName        string\n\tDescription string\n\tKind        ValueKind\n\tCumulative  bool\n}\n\nfunc All() []Description {\n\treturn nil\n}\n\ntype Float64Histogram struct {\n\tCounts  []uint64\n\tBuckets []float64\n}\n\ntype Sample struct {\n\tName  string\n\tValue Value\n}\n\nfunc Read(m []Sample) {}\n\ntype Value struct{}\n\nfunc (v Value) Float64() float64 {\n\treturn 0\n}\nfunc (v Value) Float64Histogram() *Float64Histogram {\n\treturn nil\n}\nfunc (v Value) Kind() ValueKind {\n\treturn KindBad\n}\nfunc (v Value) Uint64() uint64 {\n\treturn 0\n}\n\ntype ValueKind int\n\nconst (\n\tKindBad ValueKind = iota\n\tKindUint64\n\tKindFloat64\n\tKindFloat64Histogram\n)\n"
  },
  {
    "path": "src/runtime/metrics.go",
    "content": "package runtime\n\n// Implementation of functions needed by runtime/metrics.\n// Mostly just dummy implementations: we don't currently use any of these\n// metrics.\n\n//go:linkname godebug_registerMetric internal/godebug.registerMetric\nfunc godebug_registerMetric(name string, read func() uint64) {\n\t// Dummy function for compatibility with Go 1.21.\n}\n"
  },
  {
    "path": "src/runtime/mstats.go",
    "content": "package runtime\n\n// Memory statistics\n\n// Subset of memory statistics from upstream Go.\n// Works with conservative gc only.\n\n// A MemStats records statistics about the memory allocator.\ntype MemStats struct {\n\t// General statistics.\n\n\t// Alloc is bytes of allocated heap objects.\n\t//\n\t// This is the same as HeapAlloc (see below).\n\tAlloc uint64\n\n\t// Sys is the total bytes of memory obtained from the OS.\n\t//\n\t// Sys is the sum of the XSys fields below. Sys measures the\n\t// address space reserved by the runtime for the\n\t// heap, stacks, and other internal data structures.\n\tSys uint64\n\n\t// Heap memory statistics.\n\n\t// HeapAlloc is bytes of allocated heap objects.\n\t//\n\t// \"Allocated\" heap objects include all reachable objects, as\n\t// well as unreachable objects that the garbage collector has\n\t// not yet freed. Specifically, HeapAlloc increases as heap\n\t// objects are allocated and decreases as the heap is swept\n\t// and unreachable objects are freed. Sweeping occurs\n\t// incrementally between GC cycles, so these two processes\n\t// occur simultaneously, and as a result HeapAlloc tends to\n\t// change smoothly (in contrast with the sawtooth that is\n\t// typical of stop-the-world garbage collectors).\n\tHeapAlloc uint64\n\n\t// HeapSys is bytes of heap memory, total.\n\t//\n\t// In TinyGo unlike upstream Go, we make no distinction between\n\t// regular heap blocks used by escaped-to-the-heap variables and\n\t// blocks occupied by goroutine stacks,\n\t// all such blocks are marked as in-use, see HeapInuse below.\n\tHeapSys uint64\n\n\t// HeapIdle is bytes in idle (unused) blocks.\n\tHeapIdle uint64\n\n\t// HeapInuse is bytes in in-use blocks.\n\tHeapInuse uint64\n\n\t// HeapReleased is bytes of physical memory returned to the OS.\n\tHeapReleased uint64\n\n\t// TotalAlloc is cumulative bytes allocated for heap objects.\n\t//\n\t// TotalAlloc increases as heap objects are allocated, but\n\t// unlike Alloc and HeapAlloc, it does not decrease when\n\t// objects are freed.\n\tTotalAlloc uint64\n\n\t// Mallocs is the cumulative count of heap objects allocated.\n\t// The number of live objects is Mallocs - Frees.\n\tMallocs uint64\n\n\t// Frees is the cumulative count of heap objects freed.\n\tFrees uint64\n\n\t// Off-heap memory statistics.\n\t//\n\t// The following statistics measure runtime-internal\n\t// structures that are not allocated from heap memory (usually\n\t// because they are part of implementing the heap).\n\n\t// GCSys is bytes of memory in garbage collection metadata.\n\tGCSys uint64\n}\n"
  },
  {
    "path": "src/runtime/nonhosted.go",
    "content": "//go:build baremetal || js || wasm_unknown || nintendoswitch\n\npackage runtime\n\n// This file is for non-hosted environments, that don't support command line\n// parameters or environment variables. To still be able to run certain tests,\n// command line parameters and environment variables can be passed to the binary\n// by setting the variables `runtime.osArgs` and `runtime.osEnv`, both of which\n// are strings separated by newlines.\n//\n// The primary use case is `tinygo test`, which takes some parameters (such as\n// -test.v).\n\n// This is the default set of arguments, if nothing else has been set.\nvar args = []string{\"/proc/self/exe\"}\n\n//go:linkname os_runtime_args os.runtime_args\nfunc os_runtime_args() []string {\n\treturn args\n}\n\nvar env []string\n\n//go:linkname syscall_runtime_envs syscall.runtime_envs\nfunc syscall_runtime_envs() []string {\n\treturn env\n}\n\nvar osArgs string\nvar osEnv string\n\nfunc init() {\n\tif osArgs != \"\" {\n\t\ts := osArgs\n\t\tstart := 0\n\t\tfor i := 0; i < len(s); i++ {\n\t\t\tif s[i] == 0 {\n\t\t\t\targs = append(args, s[start:i])\n\t\t\t\tstart = i + 1\n\t\t\t}\n\t\t}\n\t\targs = append(args, s[start:])\n\t}\n\n\tif osEnv != \"\" {\n\t\ts := osEnv\n\t\tstart := 0\n\t\tfor i := 0; i < len(s); i++ {\n\t\t\tif s[i] == 0 {\n\t\t\t\tenv = append(env, s[start:i])\n\t\t\t\tstart = i + 1\n\t\t\t}\n\t\t}\n\t\tenv = append(env, s[start:])\n\t}\n}\n"
  },
  {
    "path": "src/runtime/os_darwin.c",
    "content": "//go:build none\n\n// This file is included in the build, despite the //go:build line above.\n\n#include <fcntl.h>\n\n// Wrapper function because 'open' is a variadic function and variadic functions\n// use a different (incompatible) calling convention on darwin/arm64.\n// This function is referenced from the compiler, when it sees a\n// syscall.libc_open_trampoline function.\nint syscall_libc_open(const char *pathname, int flags, mode_t mode) {\n    return open(pathname, flags, mode);\n}\n\n// The following functions are called by the runtime because Go can't call\n// function pointers directly.\n\nint tinygo_syscall(int (*fn)(uintptr_t a1, uintptr_t a2, uintptr_t a3), uintptr_t a1, uintptr_t a2, uintptr_t a3) {\n    return fn(a1, a2, a3);\n}\n\nuintptr_t tinygo_syscallX(uintptr_t (*fn)(uintptr_t a1, uintptr_t a2, uintptr_t a3), uintptr_t a1, uintptr_t a2, uintptr_t a3) {\n    return fn(a1, a2, a3);\n}\n\nint tinygo_syscall6(int (*fn)(uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6), uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6) {\n    return fn(a1, a2, a3, a4, a5, a6);\n}\n\nuintptr_t tinygo_syscall6X(uintptr_t (*fn)(uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6), uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6) {\n    return fn(a1, a2, a3, a4, a5, a6);\n}\n"
  },
  {
    "path": "src/runtime/os_darwin.go",
    "content": "//go:build darwin\n\npackage runtime\n\nimport \"unsafe\"\n\nconst GOOS = \"darwin\"\n\nconst (\n\t// See https://github.com/golang/go/blob/master/src/syscall/zerrors_darwin_amd64.go\n\tflag_PROT_READ     = 0x1\n\tflag_PROT_WRITE    = 0x2\n\tflag_MAP_PRIVATE   = 0x2\n\tflag_MAP_ANONYMOUS = 0x1000 // MAP_ANON\n)\n\n// Source: https://opensource.apple.com/source/Libc/Libc-1439.100.3/include/time.h.auto.html\nconst (\n\tclock_REALTIME      = 0\n\tclock_MONOTONIC_RAW = 4\n)\n\n// Source:\n// https://opensource.apple.com/source/xnu/xnu-7195.141.2/bsd/sys/signal.h.auto.html\nconst (\n\tsig_SIGBUS  = 10\n\tsig_SIGILL  = 4\n\tsig_SIGSEGV = 11\n)\n\n// https://opensource.apple.com/source/xnu/xnu-7195.141.2/EXTERNAL_HEADERS/mach-o/loader.h.auto.html\ntype machHeader struct {\n\tmagic      uint32\n\tcputype    uint32\n\tcpusubtype uint32\n\tfiletype   uint32\n\tncmds      uint32\n\tsizeofcmds uint32\n\tflags      uint32\n\treserved   uint32\n}\n\n// Struct for the LC_SEGMENT_64 load command.\ntype segmentLoadCommand struct {\n\tcmd      uint32 // LC_SEGMENT_64\n\tcmdsize  uint32\n\tsegname  [16]byte\n\tvmaddr   uintptr\n\tvmsize   uintptr\n\tfileoff  uintptr\n\tfilesize uintptr\n\tmaxprot  uint32\n\tinitprot uint32\n\tnsects   uint32\n\tflags    uint32\n}\n\n// MachO header of the currently running process.\n//\n//go:extern _mh_execute_header\nvar libc_mh_execute_header machHeader\n\n// Find global variables in .data/.bss sections.\n// The MachO linker doesn't seem to provide symbols for the start and end of the\n// data section. There is get_etext, get_edata, and get_end, but these are\n// undocumented and don't work with ASLR (which is enabled by default).\n// Therefore, read the MachO header directly.\nfunc findGlobals(found func(start, end uintptr)) {\n\t// Here is a useful blog post to understand the MachO file format:\n\t// https://h3adsh0tzz.com/2020/01/macho-file-format/\n\n\tconst (\n\t\tMH_MAGIC_64   = 0xfeedfacf\n\t\tLC_SEGMENT_64 = 0x19\n\t\tVM_PROT_WRITE = 0x02\n\t)\n\n\t// Sanity check that we're actually looking at a MachO header.\n\tif gcAsserts && libc_mh_execute_header.magic != MH_MAGIC_64 {\n\t\truntimePanic(\"gc: unexpected MachO header\")\n\t}\n\n\t// Iterate through the load commands.\n\t// Because we're only interested in LC_SEGMENT_64 load commands, cast the\n\t// pointer to that struct in advance.\n\tvar offset uintptr\n\tvar hasOffset bool\n\tcmd := (*segmentLoadCommand)(unsafe.Pointer(uintptr(unsafe.Pointer(&libc_mh_execute_header)) + unsafe.Sizeof(machHeader{})))\n\tfor i := libc_mh_execute_header.ncmds; i != 0; i-- {\n\t\tif cmd.cmd == LC_SEGMENT_64 {\n\t\t\tif cmd.fileoff == 0 && cmd.nsects != 0 {\n\t\t\t\t// Detect ASLR offset by checking fileoff and nsects. This\n\t\t\t\t// locates the __TEXT segment. This matches getsectiondata:\n\t\t\t\t// https://opensource.apple.com/source/cctools/cctools-973.0.1/libmacho/getsecbyname.c.auto.html\n\t\t\t\toffset = uintptr(unsafe.Pointer(&libc_mh_execute_header)) - cmd.vmaddr\n\t\t\t\thasOffset = true\n\t\t\t}\n\t\t\tif cmd.maxprot&VM_PROT_WRITE != 0 {\n\t\t\t\t// Found a writable segment, which may contain Go globals.\n\t\t\t\tif gcAsserts && !hasOffset {\n\t\t\t\t\t// No ASLR offset detected. Did the __TEXT segment come\n\t\t\t\t\t// after the __DATA segment?\n\t\t\t\t\t// Note that when ASLR is disabled (for example, when\n\t\t\t\t\t// running inside lldb), the offset is zero. That's why we\n\t\t\t\t\t// need a separate hasOffset for this assert.\n\t\t\t\t\truntimePanic(\"gc: did not detect ASLR offset\")\n\t\t\t\t}\n\t\t\t\t// Scan this segment for GC roots.\n\t\t\t\t// This could be improved by only reading the memory areas\n\t\t\t\t// covered by sections. That would reduce the amount of memory\n\t\t\t\t// scanned a little bit (up to a single VM page).\n\t\t\t\tfound(offset+cmd.vmaddr, offset+cmd.vmaddr+cmd.vmsize)\n\t\t\t}\n\t\t}\n\n\t\t// Move on to the next load command (which may or may not be a\n\t\t// LC_SEGMENT_64).\n\t\tcmd = (*segmentLoadCommand)(unsafe.Add(unsafe.Pointer(cmd), cmd.cmdsize))\n\t}\n}\n\nfunc hardwareRand() (n uint64, ok bool) {\n\tn |= uint64(libc_arc4random())\n\tn |= uint64(libc_arc4random()) << 32\n\treturn n, true\n}\n\n//go:linkname syscall_Getpagesize syscall.Getpagesize\nfunc syscall_Getpagesize() int {\n\treturn int(libc_getpagesize())\n}\n\n// Call \"system calls\" (actually: libc functions) in a special way.\n//   - Most calls calls return a C int (which is 32-bits), and -1 on failure.\n//   - syscallX* is for functions that return a 64-bit integer (and also return\n//     -1 on failure).\n//   - syscallPtr is for functions that return a pointer on success or NULL on\n//     failure.\n//   - rawSyscall seems to avoid some stack modifications, which isn't relevant\n//     to TinyGo.\n\n//go:linkname syscall_syscall syscall.syscall\nfunc syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {\n\t// For TinyGo we don't need to do anything special to call C functions.\n\treturn syscall_rawSyscall(fn, a1, a2, a3)\n}\n\n//go:linkname syscall_rawSyscall syscall.rawSyscall\nfunc syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {\n\tresult := call_syscall(fn, a1, a2, a3)\n\tr1 = uintptr(result)\n\tif result == -1 {\n\t\t// Syscall returns -1 on failure.\n\t\terr = uintptr(*libc_errno_location())\n\t}\n\treturn\n}\n\n//go:linkname syscall_syscallX syscall.syscallX\nfunc syscall_syscallX(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {\n\tr1 = call_syscallX(fn, a1, a2, a3)\n\tif int64(r1) == -1 {\n\t\t// Syscall returns -1 on failure.\n\t\terr = uintptr(*libc_errno_location())\n\t}\n\treturn\n}\n\n//go:linkname syscall_syscallPtr syscall.syscallPtr\nfunc syscall_syscallPtr(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {\n\tr1 = call_syscallX(fn, a1, a2, a3)\n\tif r1 == 0 {\n\t\t// Syscall returns a pointer on success, or NULL on failure.\n\t\terr = uintptr(*libc_errno_location())\n\t}\n\treturn\n}\n\n//go:linkname syscall_syscall6 syscall.syscall6\nfunc syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {\n\tresult := call_syscall6(fn, a1, a2, a3, a4, a5, a6)\n\tr1 = uintptr(result)\n\tif result == -1 {\n\t\t// Syscall returns -1 on failure.\n\t\terr = uintptr(*libc_errno_location())\n\t}\n\treturn\n}\n\n//go:linkname syscall_syscall6X syscall.syscall6X\nfunc syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {\n\tr1 = call_syscall6X(fn, a1, a2, a3, a4, a5, a6)\n\tif int64(r1) == -1 {\n\t\t// Syscall returns -1 on failure.\n\t\terr = uintptr(*libc_errno_location())\n\t}\n\treturn\n}\n\n// uint32_t arc4random(void);\n//\n//export arc4random\nfunc libc_arc4random() uint32\n\n// int getpagesize(void);\n//\n//export getpagesize\nfunc libc_getpagesize() int32\n\n// This function returns the error location in the darwin ABI.\n// Discovered by compiling the following code using Clang:\n//\n//\t#include <errno.h>\n//\tint getErrno() {\n//\t    return errno;\n//\t}\n//\n//export __error\nfunc libc_errno_location() *int32\n\n//export tinygo_syscall\nfunc call_syscall(fn, a1, a2, a3 uintptr) int32\n\n//export tinygo_syscallX\nfunc call_syscallX(fn, a1, a2, a3 uintptr) uintptr\n\n//export tinygo_syscall6\nfunc call_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) int32\n\n//export tinygo_syscall6X\nfunc call_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) uintptr\n\n//go:linkname os_runtime_executable_path os.runtime_executable_path\nfunc os_runtime_executable_path() string {\n\targv := (*unsafe.Pointer)(unsafe.Pointer(main_argv))\n\n\t// skip over argv\n\targv = (*unsafe.Pointer)(unsafe.Add(unsafe.Pointer(argv), (uintptr(main_argc)+1)*unsafe.Sizeof(argv)))\n\n\t// skip over envv\n\tfor (*argv) != nil {\n\t\targv = (*unsafe.Pointer)(unsafe.Add(unsafe.Pointer(argv), unsafe.Sizeof(argv)))\n\t}\n\n\t// next string is exe path\n\targv = (*unsafe.Pointer)(unsafe.Add(unsafe.Pointer(argv), unsafe.Sizeof(argv)))\n\n\tcstr := unsafe.Pointer(*argv)\n\tlength := strlen(cstr)\n\targString := _string{\n\t\tlength: length,\n\t\tptr:    (*byte)(cstr),\n\t}\n\texecutablePath := *(*string)(unsafe.Pointer(&argString))\n\n\t// strip \"executable_path=\" prefix if available, it's added after OS X 10.11.\n\texecutablePath = stringsTrimPrefix(executablePath, \"executable_path=\")\n\treturn executablePath\n}\n\nfunc stringsTrimPrefix(s, prefix string) string {\n\tif len(s) >= len(prefix) && s[:len(prefix)] == prefix {\n\t\treturn s[len(prefix):]\n\t}\n\treturn s\n}\n"
  },
  {
    "path": "src/runtime/os_js.go",
    "content": "//go:build js\n\npackage runtime\n\nconst GOOS = \"js\"\n"
  },
  {
    "path": "src/runtime/os_linux.go",
    "content": "//go:build linux && !baremetal && !nintendoswitch && !wasip1 && !wasm_unknown && !wasip2\n\npackage runtime\n\n// This file is for systems that are _actually_ Linux (not systems that pretend\n// to be Linux, like baremetal systems).\n\nimport (\n\t\"unsafe\"\n)\n\nconst GOOS = \"linux\"\n\nconst (\n\t// See https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/mman-common.h\n\tflag_PROT_READ     = 0x1\n\tflag_PROT_WRITE    = 0x2\n\tflag_MAP_PRIVATE   = 0x2\n\tflag_MAP_ANONYMOUS = linux_MAP_ANONYMOUS // different on alpha, hppa, mips, xtensa\n)\n\n// Source: https://github.com/torvalds/linux/blob/master/include/uapi/linux/time.h\nconst (\n\tclock_REALTIME      = 0\n\tclock_MONOTONIC_RAW = 4\n)\n\nconst (\n\tsig_SIGBUS  = linux_SIGBUS\n\tsig_SIGILL  = linux_SIGILL\n\tsig_SIGSEGV = linux_SIGSEGV\n)\n\n// For the definition of the various header structs, see:\n// https://refspecs.linuxfoundation.org/elf/elf.pdf\n// Also useful:\n// https://en.wikipedia.org/wiki/Executable_and_Linkable_Format\ntype elfHeader struct {\n\tident_magic      uint32\n\tident_class      uint8\n\tident_data       uint8\n\tident_version    uint8\n\tident_osabi      uint8\n\tident_abiversion uint8\n\t_                [7]byte // reserved\n\tfiletype         uint16\n\tmachine          uint16\n\tversion          uint32\n\tentry            uintptr\n\tphoff            uintptr\n\tshoff            uintptr\n\tflags            uint32\n\tehsize           uint16\n\tphentsize        uint16\n\tphnum            uint16\n\tshentsize        uint16\n\tshnum            uint16\n\tshstrndx         uint16\n}\n\ntype elfProgramHeader64 struct {\n\t_type  uint32\n\tflags  uint32\n\toffset uintptr\n\tvaddr  uintptr\n\tpaddr  uintptr\n\tfilesz uintptr\n\tmemsz  uintptr\n\talign  uintptr\n}\n\ntype elfProgramHeader32 struct {\n\t_type  uint32\n\toffset uintptr\n\tvaddr  uintptr\n\tpaddr  uintptr\n\tfilesz uintptr\n\tmemsz  uintptr\n\tflags  uint32\n\talign  uintptr\n}\n\n// ELF header of the currently running process.\n//\n//go:extern __ehdr_start\nvar ehdr_start elfHeader\n\n// int *__errno_location(void);\n//\n//export __errno_location\nfunc libc_errno_location() *int32\n\n// findGlobals finds globals in the .data/.bss sections.\n// It parses the ELF program header to find writable segments.\nfunc findGlobals(found func(start, end uintptr)) {\n\t// Relevant constants from the ELF specification.\n\t// See: https://refspecs.linuxfoundation.org/elf/elf.pdf\n\tconst (\n\t\tPT_LOAD = 1\n\t\tPF_W    = 0x2 // program flag: write access\n\t)\n\n\theaderPtr := unsafe.Pointer(uintptr(unsafe.Pointer(&ehdr_start)) + ehdr_start.phoff)\n\tfor i := 0; i < int(ehdr_start.phnum); i++ {\n\t\t// Look for a writable segment and scan its contents.\n\t\t// There is a little bit of duplication here, which is unfortunate. But\n\t\t// the alternative would be to put elfProgramHeader in separate files\n\t\t// which is IMHO a lot uglier. If only the ELF spec was consistent\n\t\t// between 32-bit and 64-bit...\n\t\tif TargetBits == 64 {\n\t\t\theader := (*elfProgramHeader64)(headerPtr)\n\t\t\tif header._type == PT_LOAD && header.flags&PF_W != 0 {\n\t\t\t\tstart := header.vaddr\n\t\t\t\tend := start + header.memsz\n\t\t\t\tfound(start, end)\n\t\t\t}\n\t\t} else {\n\t\t\theader := (*elfProgramHeader32)(headerPtr)\n\t\t\tif header._type == PT_LOAD && header.flags&PF_W != 0 {\n\t\t\t\tstart := header.vaddr\n\t\t\t\tend := start + header.memsz\n\t\t\t\tfound(start, end)\n\t\t\t}\n\t\t}\n\t\theaderPtr = unsafe.Add(headerPtr, ehdr_start.phentsize)\n\t}\n}\n\n//export getpagesize\nfunc libc_getpagesize() int\n\n//go:linkname syscall_Getpagesize syscall.Getpagesize\nfunc syscall_Getpagesize() int {\n\treturn libc_getpagesize()\n}\n\nfunc hardwareRand() (n uint64, ok bool) {\n\tread := libc_getrandom(unsafe.Pointer(&n), 8, 0)\n\tif read != 8 {\n\t\treturn 0, false\n\t}\n\treturn n, true\n}\n\n// ssize_t getrandom(void buf[.buflen], size_t buflen, unsigned int flags);\n//\n//export getrandom\nfunc libc_getrandom(buf unsafe.Pointer, buflen uintptr, flags uint32) uint32\n\n// int fcntl(int fd, int cmd, int arg);\n//\n//export fcntl\nfunc libc_fcntl(fd int, cmd int, arg int) (ret int)\n\nfunc fcntl(fd int32, cmd int32, arg int32) (ret int32, errno int32) {\n\tret = int32(libc_fcntl(int(fd), int(cmd), int(arg)))\n\terrno = *libc_errno_location()\n\treturn\n}\n"
  },
  {
    "path": "src/runtime/os_other.go",
    "content": "//go:build linux && (baremetal || nintendoswitch || wasm_unknown)\n\n// Other systems that aren't operating systems supported by the Go toolchain\n// need to pretend to be an existing operating system. Linux seems like a good\n// choice for this for its wide hardware support.\n\npackage runtime\n\nconst GOOS = \"linux\"\n"
  },
  {
    "path": "src/runtime/os_wasip1.go",
    "content": "//go:build wasip1\n\npackage runtime\n\n// The actual GOOS=wasip1, as newly added in the Go 1.21 toolchain.\n// Previously we supported -target=wasi, but that was essentially faked by using\n// linux/arm instead because that was the closest thing that was already\n// supported in the Go standard library.\n\nconst GOOS = \"wasip1\"\n"
  },
  {
    "path": "src/runtime/os_wasip2.go",
    "content": "//go:build wasip2\n\npackage runtime\n\nconst GOOS = \"wasip2\"\n"
  },
  {
    "path": "src/runtime/os_windows.go",
    "content": "package runtime\n\nimport \"unsafe\"\n\nconst GOOS = \"windows\"\n\n//export GetModuleHandleExA\nfunc _GetModuleHandleExA(dwFlags uint32, lpModuleName unsafe.Pointer, phModule **exeHeader) bool\n\n// MS-DOS stub with PE header offset:\n// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#ms-dos-stub-image-only\ntype exeHeader struct {\n\tsignature uint16\n\t_         [58]byte // skip DOS header\n\tpeHeader  uint32   // at offset 0x3C\n}\n\n// COFF file header:\n// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#file-headers\ntype peHeader struct {\n\tmagic                uint32\n\tmachine              uint16\n\tnumberOfSections     uint16\n\ttimeDateStamp        uint32\n\tpointerToSymbolTable uint32\n\tnumberOfSymbols      uint32\n\tsizeOfOptionalHeader uint16\n\tcharacteristics      uint16\n}\n\n// COFF section header:\n// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#section-table-section-headers\ntype peSection struct {\n\tname                 [8]byte\n\tvirtualSize          uint32\n\tvirtualAddress       uint32\n\tsizeOfRawData        uint32\n\tpointerToRawData     uint32\n\tpointerToRelocations uint32\n\tpointerToLinenumbers uint32\n\tnumberOfRelocations  uint16\n\tnumberOfLinenumbers  uint16\n\tcharacteristics      uint32\n}\n\nvar module *exeHeader\n\n// Mark global variables.\n// Unfortunately, the linker doesn't provide symbols for the start and end of\n// the data/bss sections. Therefore these addresses need to be determined at\n// runtime. This might seem complex and it kind of is, but it only compiles to\n// around 160 bytes of amd64 instructions.\n// Most of this function is based on the documentation in\n// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format.\nfunc findGlobals(found func(start, end uintptr)) {\n\t// Constants used in this function.\n\tconst (\n\t\t// https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandleexa\n\t\tGET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT = 0x00000002\n\n\t\t// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format\n\t\tIMAGE_SCN_MEM_WRITE = 0x80000000\n\t)\n\n\tif module == nil {\n\t\t// Obtain a handle to the currently executing image. What we're getting\n\t\t// here is really just __ImageBase, but it's probably better to obtain\n\t\t// it using GetModuleHandle to account for ASLR etc.\n\t\tresult := _GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, nil, &module)\n\t\tif gcAsserts && (!result || module.signature != 0x5A4D) { // 0x4D5A is \"MZ\"\n\t\t\truntimePanic(\"cannot get module handle\")\n\t\t}\n\t}\n\n\t// Find the PE header at offset 0x3C.\n\tpe := (*peHeader)(unsafe.Add(unsafe.Pointer(module), module.peHeader))\n\tif gcAsserts && pe.magic != 0x00004550 { // 0x4550 is \"PE\"\n\t\truntimePanic(\"cannot find PE header\")\n\t}\n\n\t// Iterate through sections.\n\tsection := (*peSection)(unsafe.Pointer(uintptr(unsafe.Pointer(pe)) + uintptr(pe.sizeOfOptionalHeader) + unsafe.Sizeof(peHeader{})))\n\tfor i := 0; i < int(pe.numberOfSections); i++ {\n\t\tif section.characteristics&IMAGE_SCN_MEM_WRITE != 0 {\n\t\t\t// Found a writable section. Scan the entire section for roots.\n\t\t\tstart := uintptr(unsafe.Pointer(module)) + uintptr(section.virtualAddress)\n\t\t\tend := uintptr(unsafe.Pointer(module)) + uintptr(section.virtualAddress) + uintptr(section.virtualSize)\n\t\t\tfound(start, end)\n\t\t}\n\t\tsection = (*peSection)(unsafe.Add(unsafe.Pointer(section), unsafe.Sizeof(peSection{})))\n\t}\n}\n\ntype systeminfo struct {\n\tanon0                       [4]byte\n\tdwpagesize                  uint32\n\tlpminimumapplicationaddress *byte\n\tlpmaximumapplicationaddress *byte\n\tdwactiveprocessormask       uintptr\n\tdwnumberofprocessors        uint32\n\tdwprocessortype             uint32\n\tdwallocationgranularity     uint32\n\twprocessorlevel             uint16\n\twprocessorrevision          uint16\n}\n\n//export GetSystemInfo\nfunc _GetSystemInfo(lpSystemInfo unsafe.Pointer)\n\n//go:linkname syscall_Getpagesize syscall.Getpagesize\nfunc syscall_Getpagesize() int {\n\tvar info systeminfo\n\t_GetSystemInfo(unsafe.Pointer(&info))\n\treturn int(info.dwpagesize)\n}\n\n//export _errno\nfunc libc_errno_location() *int32\n"
  },
  {
    "path": "src/runtime/panic.go",
    "content": "package runtime\n\nimport (\n\t\"internal/task\"\n\t\"runtime/interrupt\"\n\t\"tinygo\"\n\t\"unsafe\"\n)\n\n// trap is a compiler hint that this function cannot be executed. It is\n// translated into either a trap instruction or a call to abort().\n//\n//export llvm.trap\nfunc trap()\n\n// Inline assembly stub. It is essentially C longjmp but modified a bit for the\n// purposes of TinyGo. It restores the stack pointer and jumps to the given pc.\n//\n//export tinygo_longjmp\nfunc tinygo_longjmp(frame *deferFrame)\n\n// Compiler intrinsic.\n// Returns whether recover is supported on the current architecture.\nfunc supportsRecover() bool\n\n// Compile intrinsic.\n// Returns which strategy is used. This is usually \"print\" but can be changed\n// using the -panic= compiler flag.\nfunc panicStrategy() uint8\n\n// DeferFrame is a stack allocated object that stores information for the\n// current \"defer frame\", which is used in functions that use the `defer`\n// keyword.\n// The compiler knows about the JumpPC struct offset, so it should not be moved\n// without also updating compiler/defer.go.\ntype deferFrame struct {\n\tJumpSP     unsafe.Pointer                 // stack pointer to return to\n\tJumpPC     unsafe.Pointer                 // pc to return to\n\tExtraRegs  [deferExtraRegs]unsafe.Pointer // extra registers (depending on the architecture)\n\tPrevious   *deferFrame                    // previous recover buffer pointer\n\tPanicking  panicState                     // not panicking, panicking, or in Goexit\n\tPanicValue interface{}                    // panic value, might be nil for panic(nil) for example\n}\n\ntype panicState uint8\n\nconst (\n\tpanicFalse panicState = iota\n\tpanicTrue\n\tpanicGoexit\n)\n\n// Builtin function panic(msg), used as a compiler intrinsic.\nfunc _panic(message interface{}) {\n\tpanicOrGoexit(message, panicTrue)\n}\n\nfunc panicOrGoexit(message interface{}, panicking panicState) {\n\tif panicStrategy() == tinygo.PanicStrategyTrap {\n\t\ttrap()\n\t}\n\t// Note: recover is not supported inside interrupts.\n\t// (This could be supported, like defer, but we currently don't).\n\tif supportsRecover() && !interrupt.In() {\n\t\tframe := (*deferFrame)(task.Current().DeferFrame)\n\t\tif frame != nil {\n\t\t\tframe.PanicValue = message\n\t\t\tframe.Panicking = panicking\n\t\t\ttinygo_longjmp(frame)\n\t\t\t// unreachable\n\t\t}\n\t}\n\tif panicking == panicGoexit {\n\t\t// Call to Goexit() instead of a panic.\n\t\t// Exit the goroutine instead of printing a panic message.\n\t\tdeadlock()\n\t}\n\tprintstring(\"panic: \")\n\tprintitf(message)\n\tprintnl()\n\tabort()\n}\n\n// Cause a runtime panic, which is (currently) always a string.\nfunc runtimePanic(msg string) {\n\t// As long as this function is inined, llvm.returnaddress(0) will return\n\t// something sensible.\n\truntimePanicAt(returnAddress(0), msg)\n}\n\nfunc runtimePanicAt(addr unsafe.Pointer, msg string) {\n\tif panicStrategy() == tinygo.PanicStrategyTrap {\n\t\ttrap()\n\t}\n\tif hasReturnAddr {\n\t\t// Note: the string \"panic: runtime error at \" is also used in\n\t\t// runtime_cortexm_hardfault.go. It is kept the same so that the string\n\t\t// can be deduplicated by the compiler.\n\t\tprintstring(\"panic: runtime error at \")\n\t\tprintptr(uintptr(addr) - callInstSize)\n\t\tprintstring(\": \")\n\t} else {\n\t\tprintstring(\"panic: runtime error: \")\n\t}\n\tprintstring(msg)\n\tprintnl()\n\tabort()\n}\n\n// Called at the start of a function that includes a deferred call.\n// It gets passed in the stack-allocated defer frame and configures it.\n// Note that the frame is not zeroed yet, so we need to initialize all values\n// that will be used.\n//\n//go:inline\n//go:nobounds\nfunc setupDeferFrame(frame *deferFrame, jumpSP unsafe.Pointer) {\n\tif interrupt.In() {\n\t\t// Defer is not currently allowed in interrupts.\n\t\t// We could add support for this, but since defer might also allocate\n\t\t// (especially in loops) it might not be a good idea anyway.\n\t\truntimePanicAt(returnAddress(0), \"defer in interrupt\")\n\t}\n\tcurrentTask := task.Current()\n\tframe.Previous = (*deferFrame)(currentTask.DeferFrame)\n\tframe.JumpSP = jumpSP\n\tframe.Panicking = panicFalse\n\tcurrentTask.DeferFrame = unsafe.Pointer(frame)\n}\n\n// Called right before the return instruction. It pops the defer frame from the\n// linked list of defer frames. It also re-raises a panic if the goroutine is\n// still panicking.\n//\n//go:inline\n//go:nobounds\nfunc destroyDeferFrame(frame *deferFrame) {\n\ttask.Current().DeferFrame = unsafe.Pointer(frame.Previous)\n\tif frame.Panicking != panicFalse {\n\t\t// We're still panicking!\n\t\t// Re-raise the panic now.\n\t\tpanicOrGoexit(frame.PanicValue, frame.Panicking)\n\t}\n}\n\n// _recover is the built-in recover() function. It tries to recover a currently\n// panicking goroutine.\n// useParentFrame is set when the caller of runtime._recover has a defer frame\n// itself. In that case, recover() shouldn't check that frame but one frame up.\nfunc _recover(useParentFrame bool) interface{} {\n\tif !supportsRecover() || interrupt.In() {\n\t\t// Either we're compiling without stack unwinding support, or we're\n\t\t// inside an interrupt where panic/recover is not supported. Either way,\n\t\t// make this a no-op since panic() won't do any long jumps to a deferred\n\t\t// function.\n\t\treturn nil\n\t}\n\t// TODO: somehow check that recover() is called directly by a deferred\n\t// function in a panicking goroutine. Maybe this can be done by comparing\n\t// the frame pointer?\n\tframe := (*deferFrame)(task.Current().DeferFrame)\n\tif useParentFrame {\n\t\t// Don't recover panic from the current frame (which can't be panicking\n\t\t// already), but instead from the previous frame.\n\t\tframe = frame.Previous\n\t}\n\tif frame != nil && frame.Panicking != panicFalse {\n\t\tif frame.Panicking == panicGoexit {\n\t\t\t// Special value that indicates we're exiting the goroutine using\n\t\t\t// Goexit(). Therefore, make this recover call a no-op.\n\t\t\treturn nil\n\t\t}\n\t\t// Only the first call to recover returns the panic value. It also stops\n\t\t// the panicking sequence, hence setting panicking to false.\n\t\tframe.Panicking = panicFalse\n\t\treturn frame.PanicValue\n\t}\n\t// Not panicking, so return a nil interface.\n\treturn nil\n}\n\n// Panic when trying to dereference a nil pointer.\nfunc nilPanic() {\n\truntimePanicAt(returnAddress(0), \"nil pointer dereference\")\n}\n\n// Panic when trying to add an entry to a nil map\nfunc nilMapPanic() {\n\truntimePanicAt(returnAddress(0), \"assignment to entry in nil map\")\n}\n\n// Panic when trying to access an array or slice out of bounds.\nfunc lookupPanic() {\n\truntimePanicAt(returnAddress(0), \"index out of range\")\n}\n\n// Panic when trying to slice a slice out of bounds.\nfunc slicePanic() {\n\truntimePanicAt(returnAddress(0), \"slice out of range\")\n}\n\n// Panic when trying to convert a slice to an array pointer (Go 1.17+) and the\n// slice is shorter than the array.\nfunc sliceToArrayPointerPanic() {\n\truntimePanicAt(returnAddress(0), \"slice smaller than array\")\n}\n\n// Panic when calling unsafe.Slice() (Go 1.17+) or unsafe.String() (Go 1.20+)\n// with a len that's too large (which includes if the ptr is nil and len is\n// nonzero).\nfunc unsafeSlicePanic() {\n\truntimePanicAt(returnAddress(0), \"unsafe.Slice/String: len out of range\")\n}\n\n// Panic when trying to create a new channel that is too big.\nfunc chanMakePanic() {\n\truntimePanicAt(returnAddress(0), \"new channel is too big\")\n}\n\n// Panic when a shift value is negative.\nfunc negativeShiftPanic() {\n\truntimePanicAt(returnAddress(0), \"negative shift\")\n}\n\n// Panic when there is a divide by zero.\nfunc divideByZeroPanic() {\n\truntimePanicAt(returnAddress(0), \"divide by zero\")\n}\n\nfunc blockingPanic() {\n\truntimePanicAt(returnAddress(0), \"trying to do blocking operation in exported function\")\n}\n\n//go:linkname fips_fatal crypto/internal/fips140.fatal\nfunc fips_fatal(msg string) {\n\truntimePanic(msg)\n}\n"
  },
  {
    "path": "src/runtime/poll.go",
    "content": "package runtime\n\n// This file implements stub functions for internal/poll.\n\n//go:linkname poll_runtime_pollServerInit internal/poll.runtime_pollServerInit\nfunc poll_runtime_pollServerInit() {\n\tpanic(\"todo: runtime_pollServerInit\")\n}\n\n//go:linkname poll_runtime_pollOpen internal/poll.runtime_pollOpen\nfunc poll_runtime_pollOpen(fd uintptr) (uintptr, int) {\n\tpanic(\"todo: runtime_pollOpen\")\n}\n\n//go:linkname poll_runtime_pollClose internal/poll.runtime_pollClose\nfunc poll_runtime_pollClose(ctx uintptr) {\n\tpanic(\"todo: runtime_pollClose\")\n}\n\n//go:linkname poll_runtime_pollUnblock internal/poll.runtime_pollUnblock\nfunc poll_runtime_pollUnblock(ctx uintptr) {\n\tpanic(\"todo: runtime_pollUnblock\")\n}\n"
  },
  {
    "path": "src/runtime/pprof/pprof.go",
    "content": "package pprof\n\n// TinyGo does not implement pprof. However, a dummy shell is needed for the\n// testing package (and testing/internal/pprof).\n\nimport (\n\t\"errors\"\n\t\"io\"\n)\n\nvar ErrUnimplemented = errors.New(\"runtime/pprof: unimplemented\")\n\ntype Profile struct{}\n\nfunc StartCPUProfile(w io.Writer) error {\n\treturn nil\n}\n\nfunc StopCPUProfile() {\n}\n\nfunc WriteHeapProfile(w io.Writer) error {\n\treturn nil\n}\n\nfunc Lookup(name string) *Profile {\n\treturn nil\n}\n\nfunc (p *Profile) Name() string {\n\treturn \"\"\n}\n\nfunc (p *Profile) Count() int {\n\treturn 0\n}\n\nfunc (p *Profile) WriteTo(w io.Writer, debug int) error {\n\treturn ErrUnimplemented\n}\n\nfunc Profiles() []*Profile {\n\treturn nil\n}\n"
  },
  {
    "path": "src/runtime/print.go",
    "content": "package runtime\n\nimport (\n\t\"unsafe\"\n)\n\ntype stringer interface {\n\tString() string\n}\n\n//go:nobounds\nfunc printstring(s string) {\n\tfor i := 0; i < len(s); i++ {\n\t\tputchar(s[i])\n\t}\n}\n\nfunc printuint8(n uint8) {\n\tif TargetBits >= 32 {\n\t\tprintuint32(uint32(n))\n\t} else {\n\t\tprevdigits := n / 10\n\t\tif prevdigits != 0 {\n\t\t\tprintuint8(prevdigits)\n\t\t}\n\t\tputchar(byte((n % 10) + '0'))\n\t}\n}\n\nfunc printint8(n int8) {\n\tif TargetBits >= 32 {\n\t\tprintint32(int32(n))\n\t} else {\n\t\tif n < 0 {\n\t\t\tputchar('-')\n\t\t\tn = -n\n\t\t}\n\t\tprintuint8(uint8(n))\n\t}\n}\n\nfunc printuintptr(n uintptr) {\n\tswitch unsafe.Sizeof(n) {\n\tcase 2:\n\t\tprintuint16(uint16(n))\n\tcase 4:\n\t\tprintuint32(uint32(n))\n\tcase 8:\n\t\tprintuint64(uint64(n))\n\t}\n}\n\nfunc printuint16(n uint16) {\n\tprintuint32(uint32(n))\n}\n\nfunc printint16(n int16) {\n\tprintint32(int32(n))\n}\n\nfunc printuint32(n uint32) {\n\tprintuint64(uint64(n))\n}\n\nfunc printint32(n int32) {\n\t// Print integer in signed big-endian base-10 notation, for humans to\n\t// read.\n\tif n < 0 {\n\t\tputchar('-')\n\t\tn = -n\n\t}\n\tprintuint32(uint32(n))\n}\n\n//go:nobounds\nfunc printuint64(n uint64) {\n\tdigits := [20]byte{} // enough to hold (2^64)-1\n\t// Fill in all 10 digits.\n\tfirstdigit := 19 // digit index that isn't zero (by default, the last to handle '0' correctly)\n\tfor i := 19; i >= 0; i-- {\n\t\tdigit := byte(n%10 + '0')\n\t\tdigits[i] = digit\n\t\tif digit != '0' {\n\t\t\tfirstdigit = i\n\t\t}\n\t\tn /= 10\n\t}\n\t// Print digits without the leading zeroes.\n\tfor i := firstdigit; i < 20; i++ {\n\t\tputchar(digits[i])\n\t}\n}\n\nfunc printint64(n int64) {\n\tif n < 0 {\n\t\tputchar('-')\n\t\tn = -n\n\t}\n\tprintuint64(uint64(n))\n}\n\n// printfloat32() was copied from the relevant source in the original Go\n// implementation and modified to work with float32 instead of float64. It is\n// copyright by the Go authors, licensed under the same BSD 3-clause license.\n// See https://golang.org/LICENSE for details.\n//\n// It is a near-duplicate of printfloat64. This is done so that printing a\n// float32 value doesn't involve float64 routines, which can be unexpected and a\n// problem sometimes. It comes with a possible code size reduction if both\n// printfloat32 and printfloat64 are used, which seems uncommon.\n//\n// Source:\n// https://github.com/golang/go/blob/master/src/runtime/print.go\nfunc printfloat32(v float32) {\n\tswitch {\n\tcase v != v:\n\t\tprintstring(\"NaN\")\n\t\treturn\n\tcase v+v == v && v > 0:\n\t\tprintstring(\"+Inf\")\n\t\treturn\n\tcase v+v == v && v < 0:\n\t\tprintstring(\"-Inf\")\n\t\treturn\n\t}\n\n\tconst n = 7 // digits printed\n\tvar buf [n + 7]byte\n\tbuf[0] = '+'\n\te := 0 // exp\n\tif v == 0 {\n\t\tif 1/v < 0 {\n\t\t\tbuf[0] = '-'\n\t\t}\n\t} else {\n\t\tif v < 0 {\n\t\t\tv = -v\n\t\t\tbuf[0] = '-'\n\t\t}\n\n\t\t// normalize\n\t\tfor v >= 10 {\n\t\t\te++\n\t\t\tv /= 10\n\t\t}\n\t\tfor v < 1 {\n\t\t\te--\n\t\t\tv *= 10\n\t\t}\n\n\t\t// round\n\t\th := float32(5.0)\n\t\tfor i := 0; i < n; i++ {\n\t\t\th /= 10\n\t\t}\n\t\tv += h\n\t\tif v >= 10 {\n\t\t\te++\n\t\t\tv /= 10\n\t\t}\n\t}\n\n\t// format +d.dddd+edd\n\tfor i := 0; i < n; i++ {\n\t\ts := int(v)\n\t\tbuf[i+2] = byte(s + '0')\n\t\tv -= float32(s)\n\t\tv *= 10\n\t}\n\tbuf[1] = buf[2]\n\tbuf[2] = '.'\n\n\tbuf[n+2] = 'e'\n\tbuf[n+3] = '+'\n\tif e < 0 {\n\t\te = -e\n\t\tbuf[n+3] = '-'\n\t}\n\n\tbuf[n+4] = byte(e/100) + '0'\n\tbuf[n+5] = byte(e/10)%10 + '0'\n\tbuf[n+6] = byte(e%10) + '0'\n\tfor _, c := range buf {\n\t\tputchar(c)\n\t}\n}\n\n// printfloat64() was copied from the relevant source in the original Go\n// implementation. It is copyright by the Go authors, licensed under the same\n// BSD 3-clause license. See https://golang.org/LICENSE for details.\n//\n// Source:\n// https://github.com/golang/go/blob/master/src/runtime/print.go\nfunc printfloat64(v float64) {\n\tswitch {\n\tcase v != v:\n\t\tprintstring(\"NaN\")\n\t\treturn\n\tcase v+v == v && v > 0:\n\t\tprintstring(\"+Inf\")\n\t\treturn\n\tcase v+v == v && v < 0:\n\t\tprintstring(\"-Inf\")\n\t\treturn\n\t}\n\n\tconst n = 7 // digits printed\n\tvar buf [n + 7]byte\n\tbuf[0] = '+'\n\te := 0 // exp\n\tif v == 0 {\n\t\tif 1/v < 0 {\n\t\t\tbuf[0] = '-'\n\t\t}\n\t} else {\n\t\tif v < 0 {\n\t\t\tv = -v\n\t\t\tbuf[0] = '-'\n\t\t}\n\n\t\t// normalize\n\t\tfor v >= 10 {\n\t\t\te++\n\t\t\tv /= 10\n\t\t}\n\t\tfor v < 1 {\n\t\t\te--\n\t\t\tv *= 10\n\t\t}\n\n\t\t// round\n\t\th := 5.0\n\t\tfor i := 0; i < n; i++ {\n\t\t\th /= 10\n\t\t}\n\t\tv += h\n\t\tif v >= 10 {\n\t\t\te++\n\t\t\tv /= 10\n\t\t}\n\t}\n\n\t// format +d.dddd+edd\n\tfor i := 0; i < n; i++ {\n\t\ts := int(v)\n\t\tbuf[i+2] = byte(s + '0')\n\t\tv -= float64(s)\n\t\tv *= 10\n\t}\n\tbuf[1] = buf[2]\n\tbuf[2] = '.'\n\n\tbuf[n+2] = 'e'\n\tbuf[n+3] = '+'\n\tif e < 0 {\n\t\te = -e\n\t\tbuf[n+3] = '-'\n\t}\n\n\tbuf[n+4] = byte(e/100) + '0'\n\tbuf[n+5] = byte(e/10)%10 + '0'\n\tbuf[n+6] = byte(e%10) + '0'\n\tfor _, c := range buf {\n\t\tputchar(c)\n\t}\n}\n\nfunc printcomplex64(c complex64) {\n\tputchar('(')\n\tprintfloat32(real(c))\n\tprintfloat32(imag(c))\n\tprintstring(\"i)\")\n}\n\nfunc printcomplex128(c complex128) {\n\tputchar('(')\n\tprintfloat64(real(c))\n\tprintfloat64(imag(c))\n\tprintstring(\"i)\")\n}\n\nfunc printspace() {\n\tputchar(' ')\n}\n\nfunc printnl() {\n\tif baremetal {\n\t\tputchar('\\r')\n\t}\n\tputchar('\\n')\n}\n\nfunc printitf(msg interface{}) {\n\tswitch msg := msg.(type) {\n\tcase bool:\n\t\tprintbool(msg)\n\tcase int:\n\t\tswitch unsafe.Sizeof(msg) {\n\t\tcase 8:\n\t\t\tprintint64(int64(msg))\n\t\tcase 4:\n\t\t\tprintint32(int32(msg))\n\t\t}\n\tcase int8:\n\t\tprintint8(msg)\n\tcase int16:\n\t\tprintint16(msg)\n\tcase int32:\n\t\tprintint32(msg)\n\tcase int64:\n\t\tprintint64(msg)\n\tcase uint:\n\t\tswitch unsafe.Sizeof(msg) {\n\t\tcase 8:\n\t\t\tprintuint64(uint64(msg))\n\t\tcase 4:\n\t\t\tprintuint32(uint32(msg))\n\t\t}\n\tcase uint8:\n\t\tprintuint8(msg)\n\tcase uint16:\n\t\tprintuint16(msg)\n\tcase uint32:\n\t\tprintuint32(msg)\n\tcase uint64:\n\t\tprintuint64(msg)\n\tcase uintptr:\n\t\tprintuintptr(msg)\n\tcase float32:\n\t\tprintfloat32(msg)\n\tcase float64:\n\t\tprintfloat64(msg)\n\tcase complex64:\n\t\tprintcomplex64(msg)\n\tcase complex128:\n\t\tprintcomplex128(msg)\n\tcase string:\n\t\tprintstring(msg)\n\tcase error:\n\t\tprintstring(msg.Error())\n\tcase stringer:\n\t\tprintstring(msg.String())\n\tdefault:\n\t\t// cast to underlying type\n\t\titf := *(*_interface)(unsafe.Pointer(&msg))\n\t\tputchar('(')\n\t\tprintuintptr(uintptr(itf.typecode))\n\t\tputchar(':')\n\t\tprintptr(uintptr(itf.value))\n\t\tputchar(')')\n\t}\n}\n\nfunc printmap(m *hashmap) {\n\tprintstring(\"map[\")\n\tif m == nil {\n\t\tprintstring(\"nil\")\n\t} else {\n\t\tswitch unsafe.Sizeof(m.count) {\n\t\tcase 8:\n\t\t\tprintuint64(uint64(m.count))\n\t\tcase 4:\n\t\t\tprintuint32(uint32(m.count))\n\t\tcase 2:\n\t\t\tprintuint16(uint16(m.count))\n\t\t}\n\t}\n\tputchar(']')\n}\n\nfunc printptr(ptr uintptr) {\n\tif ptr == 0 {\n\t\tprintstring(\"nil\")\n\t\treturn\n\t}\n\tputchar('0')\n\tputchar('x')\n\tfor i := 0; i < int(unsafe.Sizeof(ptr))*2; i++ {\n\t\tnibble := byte(ptr >> (unsafe.Sizeof(ptr)*8 - 4))\n\t\tif nibble < 10 {\n\t\t\tputchar(nibble + '0')\n\t\t} else {\n\t\t\tputchar(nibble - 10 + 'a')\n\t\t}\n\t\tptr <<= 4\n\t}\n}\n\nfunc printbool(b bool) {\n\tif b {\n\t\tprintstring(\"true\")\n\t} else {\n\t\tprintstring(\"false\")\n\t}\n}\n\nfunc printslice(ptr, len_, cap_ uintptr) {\n\tputchar('[')\n\tprintuintptr(len_)\n\tputchar('/')\n\tprintuintptr(cap_)\n\tputchar(']')\n\tprintptr(ptr)\n}\n"
  },
  {
    "path": "src/runtime/proc.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage runtime\n\n// Called from syscall package before Exec.\n//\n//go:linkname syscall_runtime_BeforeExec syscall.runtime_BeforeExec\nfunc syscall_runtime_BeforeExec() {\n\t// Used in BigGo to serialize exec / thread creation. Stubbing to\n\t// satisfy link.\n}\n\n// Called from syscall package after Exec.\n//\n//go:linkname syscall_runtime_AfterExec syscall.runtime_AfterExec\nfunc syscall_runtime_AfterExec() {\n}\n"
  },
  {
    "path": "src/runtime/rand.go",
    "content": "package runtime\n\nimport _ \"unsafe\"\n\n// TODO: Use hardware when available\n//\n//go:linkname vgetrandom\nfunc vgetrandom(p []byte, flags uint32) (ret int, supported bool) { return 0, false }\n\n//go:linkname fatal crypto/internal/sysrand.fatal\nfunc fatal(msg string) { runtimePanic(msg) }\n"
  },
  {
    "path": "src/runtime/rand_hwrng.go",
    "content": "//go:build baremetal && (nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3 || tkey || (tinygo.riscv32 && virt) || rp2040 || rp2350)\n\n// If you update the above build constraint, you'll probably also need to update\n// src/crypto/rand/rand_baremetal.go.\n//\n// The rp2040 and rp2350 implementations are not included in src/crypto/rand/rand_baremetal.go\n// due to not being sufficiently random for the Go crypto libs.\n// However since the randomness here does not provide those same guarantees,\n// they are included in the list for hardwareRand() implementations.\n\npackage runtime\n\nimport \"machine\"\n\nfunc hardwareRand() (n uint64, ok bool) {\n\tn1, err1 := machine.GetRNG()\n\tn2, err2 := machine.GetRNG()\n\tn = uint64(n1)<<32 | uint64(n2)\n\tok = err1 == nil && err2 == nil\n\treturn\n}\n"
  },
  {
    "path": "src/runtime/rand_norng.go",
    "content": "//go:build baremetal && !(nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3 || tkey || (tinygo.riscv32 && virt) || rp2040 || rp2350)\n\npackage runtime\n\nfunc hardwareRand() (n uint64, ok bool) {\n\treturn 0, false // no RNG available\n}\n"
  },
  {
    "path": "src/runtime/runtime.go",
    "content": "package runtime\n\nimport (\n\t\"unsafe\"\n)\n\n//go:generate go run ../../tools/gen-critical-atomics -out ./atomics_critical.go\n\nconst Compiler = \"tinygo\"\n\n// Unit for the 'ticks' and 'sleepTicks' functions.\n//\n// This is the native time unit for the given system. One timeUnit tick might be\n// 1ns or 100ns on a desktop system, or 1/32768s on baremetal systems with a\n// low-power RTC. Many other tick durations are possible.\n//\n// Conversion from time units to nanoseconds and back is done using\n// ticksToNanoseconds and nanosecondsToTicks, which need to be implemented for\n// each system as needed.\ntype timeUnit int64\n\n// The compiler will fill this with calls to the initialization function of each\n// package.\nfunc initAll()\n\n//go:linkname callMain main.main\nfunc callMain()\n\nfunc GOMAXPROCS(n int) int {\n\t// Note: setting GOMAXPROCS is ignored.\n\treturn 1\n}\n\nfunc GOROOT() string {\n\t// TODO: don't hardcode but take the one at compile time.\n\treturn \"/usr/local/go\"\n}\n\n// Copy size bytes from src to dst. The memory areas must not overlap.\n// This function is implemented by the compiler as a call to a LLVM intrinsic\n// like llvm.memcpy.p0.p0.i32(dst, src, size, false).\nfunc memcpy(dst, src unsafe.Pointer, size uintptr)\n\n// Copy size bytes from src to dst. The memory areas may overlap and will do the\n// correct thing.\n// This function is implemented by the compiler as a call to a LLVM intrinsic\n// like llvm.memmove.p0.p0.i32(dst, src, size, false).\nfunc memmove(dst, src unsafe.Pointer, size uintptr)\n\n// Set the given number of bytes to zero.\n// This function is implemented by the compiler as a call to a LLVM intrinsic\n// like llvm.memset.p0.i32(ptr, 0, size, false).\nfunc memzero(ptr unsafe.Pointer, size uintptr)\n\n// Return the current stack pointer using the llvm.stacksave.p0 intrinsic.\n// It is normally used together with llvm.stackrestore.p0 but also works to get\n// the current stack pointer in a platform-independent way.\nfunc stacksave() unsafe.Pointer\n\n// Special LLVM intrinsic that returns the SP register on entry to the calling\n// function.\n//\n//export llvm.sponentry.p0\nfunc llvm_sponentry() unsafe.Pointer\n\n//export strlen\nfunc strlen(ptr unsafe.Pointer) uintptr\n\n//export malloc\nfunc malloc(size uintptr) unsafe.Pointer\n\n// Return the address of an exported function.\n// This is mainly useful to pass a function pointer without extra context\n// parameter to C, for example.\nfunc exportedFuncPtr(fn func()) uintptr\n\n// Compare two same-size buffers for equality.\nfunc memequal(x, y unsafe.Pointer, n uintptr) bool {\n\tfor i := uintptr(0); i < n; i++ {\n\t\tcx := *(*uint8)(unsafe.Add(x, i))\n\t\tcy := *(*uint8)(unsafe.Add(y, i))\n\t\tif cx != cy {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\nfunc nanotime() int64 {\n\treturn ticksToNanoseconds(ticks())\n}\n\n// Copied from the Go runtime source code.\n//\n//go:linkname os_sigpipe os.sigpipe\nfunc os_sigpipe() {\n\truntimePanic(\"too many writes on closed pipe\")\n}\n\n// LockOSThread wires the calling goroutine to its current operating system thread.\n// Stub for now\n// Called by go1.18 standard library on windows, see https://github.com/golang/go/issues/49320\nfunc LockOSThread() {\n}\n\n// UnlockOSThread undoes an earlier call to LockOSThread.\n// Stub for now\nfunc UnlockOSThread() {\n}\n\n// KeepAlive makes sure the value in the interface is alive until at least the\n// point of the call.\nfunc KeepAlive(x interface{})\n\n// AddCleanup is a dummy cleanup implementation. It doesn't do any cleaning up.\n//\n// We base this on the following loophole in the official runtime.AddCleanup\n// documentation:\n//\n// > The cleanup(arg) call is not always guaranteed to run; in particular it is\n// > not guaranteed to run before program exit.\n//\n// So it's technically correct (the best kind of correct) to not run any\n// cleanups. But of course, this can lead to resource leaks so cleanups may need\n// to be implemented eventually.\nfunc AddCleanup[T, S any](ptr *T, cleanup func(S), arg S) Cleanup {\n\treturn Cleanup{}\n}\n\ntype Cleanup struct{}\n\nfunc (c Cleanup) Stop() {}\n\n//go:linkname registerWeakPointer weak.runtime_registerWeakPointer\nfunc registerWeakPointer(ptr unsafe.Pointer) unsafe.Pointer {\n\t// TODO: unimplemented.\n\t// I hope not implementing this won't break anything, like packages that\n\t// expect weak pointers to be GC'd before they actually are.\n\treturn ptr\n}\n\nvar godebugUpdate func(string, string)\n\n//go:linkname godebug_setUpdate internal/godebug.setUpdate\nfunc godebug_setUpdate(update func(string, string)) {\n\t// The 'update' function needs to be called whenever the GODEBUG environment\n\t// variable changes (for example, via os.Setenv).\n\tgodebugUpdate = update\n}\n\n//go:linkname godebug_setNewIncNonDefault internal/godebug.setNewIncNonDefault\nfunc godebug_setNewIncNonDefault(newIncNonDefault func(string) func()) {\n\t// Dummy function necessary in Go 1.21.\n}\n\n// Write to the given file descriptor.\n// This is called from internal/godebug starting with Go 1.21, and only seems to\n// be called with the stderr file descriptor.\nfunc write(fd uintptr, p unsafe.Pointer, n int32) int32 {\n\tif fd == 2 { // stderr\n\t\t// Convert to a string, because we know that p won't change during the\n\t\t// call to printstring.\n\t\t// TODO: use unsafe.String instead once we require Go 1.20.\n\t\ts := _string{\n\t\t\tptr:    (*byte)(p),\n\t\t\tlength: uintptr(n),\n\t\t}\n\t\tstr := *(*string)(unsafe.Pointer(&s))\n\t\tprintstring(str)\n\t\treturn n\n\t}\n\treturn 0\n}\n\n// getAuxv is linknamed from golang.org/x/sys/cpu.\nfunc getAuxv() []uintptr {\n\treturn nil\n}\n\n// Called from cgo to obtain the errno value.\nfunc cgo_errno() uintptr {\n\treturn uintptr(*libc_errno_location())\n}\n"
  },
  {
    "path": "src/runtime/runtime_arm7tdmi.go",
    "content": "//go:build arm7tdmi\n\npackage runtime\n\nimport (\n\t_ \"runtime/interrupt\" // make sure the interrupt handler is defined\n\t\"unsafe\"\n)\n\nfunc putchar(c byte) {\n\t// dummy, TODO\n}\n\nfunc getchar() byte {\n\t// dummy, TODO\n\treturn 0\n}\n\nfunc buffered() int {\n\t// dummy, TODO\n\treturn 0\n}\n\n//go:extern _sbss\nvar _sbss [0]byte\n\n//go:extern _ebss\nvar _ebss [0]byte\n\n//go:extern _sdata\nvar _sdata [0]byte\n\n//go:extern _sidata\nvar _sidata [0]byte\n\n//go:extern _edata\nvar _edata [0]byte\n\n// Entry point for Go. Initialize all packages and call main.main().\n//\n//export main\nfunc main() {\n\t// Initialize .data and .bss sections.\n\tpreinit()\n\n\t// Run program.\n\trun()\n}\n\nfunc preinit() {\n\t// Initialize .bss: zero-initialized global variables.\n\tptr := unsafe.Pointer(&_sbss)\n\tfor ptr != unsafe.Pointer(&_ebss) {\n\t\t*(*uint32)(ptr) = 0\n\t\tptr = unsafe.Add(ptr, 4)\n\t}\n\n\t// Initialize .data: global variables initialized from flash.\n\tsrc := unsafe.Pointer(&_sidata)\n\tdst := unsafe.Pointer(&_sdata)\n\tfor dst != unsafe.Pointer(&_edata) {\n\t\t*(*uint32)(dst) = *(*uint32)(src)\n\t\tdst = unsafe.Add(dst, 4)\n\t\tsrc = unsafe.Add(src, 4)\n\t}\n}\n\nfunc ticksToNanoseconds(ticks timeUnit) int64 {\n\treturn int64(ticks)\n}\n\nfunc nanosecondsToTicks(ns int64) timeUnit {\n\treturn timeUnit(ns)\n}\n\nfunc ticks() timeUnit {\n\t// TODO\n\treturn 0\n}\n\nfunc sleepTicks(d timeUnit) {\n\t// TODO\n}\n\nfunc exit(code int) {\n\tabort()\n}\n\nfunc abort() {\n\t// TODO\n\tfor {\n\t}\n}\n"
  },
  {
    "path": "src/runtime/runtime_atmega.go",
    "content": "//go:build avr && (atmega || atmega32u4)\n\npackage runtime\n\nimport (\n\t\"device/avr\"\n\t\"machine\"\n)\n\nfunc initUART() {\n\tmachine.InitSerial()\n}\n\nfunc putchar(c byte) {\n\tmachine.Serial.WriteByte(c)\n}\n\nfunc getchar() byte {\n\tfor machine.Serial.Buffered() == 0 {\n\t\tGosched()\n\t}\n\tv, _ := machine.Serial.ReadByte()\n\treturn v\n}\n\nfunc buffered() int {\n\treturn machine.Serial.Buffered()\n}\n\n// Sleep for a given period. The period is defined by the WDT peripheral, and is\n// on most chips (at least) 3 bits wide, in powers of two from 16ms to 2s\n// (0=16ms, 1=32ms, 2=64ms...). Note that the WDT is not very accurate: it can\n// be off by a large margin depending on temperature and supply voltage.\n//\n// TODO: disable more peripherals etc. to reduce sleep current.\nfunc sleepWDT(period uint8) {\n\t// Configure WDT\n\tavr.Asm(\"cli\")\n\tavr.Asm(\"wdr\")\n\t// Start timed sequence.\n\tavr.WDTCSR.SetBits(avr.WDTCSR_WDCE | avr.WDTCSR_WDE)\n\t// Enable WDT and set new timeout\n\tavr.WDTCSR.SetBits(avr.WDTCSR_WDIE | period)\n\tavr.Asm(\"sei\")\n\n\t// Set sleep mode to idle and enable sleep mode.\n\t// Note: when using something other than idle, the UART won't work\n\t// correctly. This needs to be fixed, though, so we can truly sleep.\n\tavr.SMCR.Set((0 << 1) | avr.SMCR_SE)\n\n\t// go to sleep\n\tavr.Asm(\"sleep\")\n\n\t// disable sleep\n\tavr.SMCR.Set(0)\n}\n"
  },
  {
    "path": "src/runtime/runtime_atsamd21.go",
    "content": "//go:build sam && atsamd21\n\npackage runtime\n\nimport (\n\t\"device/arm\"\n\t\"device/sam\"\n\t\"machine\"\n\t_ \"machine/usb/cdc\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\n//export Reset_Handler\nfunc main() {\n\tpreinit()\n\trun()\n\texit(0)\n}\n\nfunc init() {\n\tinitClocks()\n\tinitRTC()\n\tinitSERCOMClocks()\n\tinitUSBClock()\n\tinitADCClock()\n\n\tmachine.InitSerial()\n}\n\nfunc putchar(c byte) {\n\tmachine.Serial.WriteByte(c)\n}\n\nfunc getchar() byte {\n\tfor machine.Serial.Buffered() == 0 {\n\t\tGosched()\n\t}\n\tv, _ := machine.Serial.ReadByte()\n\treturn v\n}\n\nfunc buffered() int {\n\treturn machine.Serial.Buffered()\n}\n\nfunc initClocks() {\n\t// Set 1 Flash Wait State for 48MHz, required for 3.3V operation according to SAMD21 Datasheet\n\tsam.NVMCTRL.CTRLB.SetBits(sam.NVMCTRL_CTRLB_RWS_HALF << sam.NVMCTRL_CTRLB_RWS_Pos)\n\n\t// Turn on the digital interface clock\n\tsam.PM.APBAMASK.SetBits(sam.PM_APBAMASK_GCLK_)\n\t// turn off RTC\n\tsam.PM.APBAMASK.ClearBits(sam.PM_APBAMASK_RTC_)\n\n\t// Enable OSC32K clock (Internal 32.768Hz oscillator).\n\t// This requires registers that are not included in the SVD file.\n\t// This is from samd21g18a.h and nvmctrl.h:\n\t//\n\t// #define NVMCTRL_OTP4 0x00806020\n\t//\n\t// #define SYSCTRL_FUSES_OSC32K_CAL_ADDR (NVMCTRL_OTP4 + 4)\n\t// #define SYSCTRL_FUSES_OSC32K_CAL_Pos 6 /** (NVMCTRL_OTP4) OSC32K Calibration */\n\t// #define SYSCTRL_FUSES_OSC32K_CAL_Msk (0x7Fu << SYSCTRL_FUSES_OSC32K_CAL_Pos)\n\t// #define SYSCTRL_FUSES_OSC32K_CAL(value) ((SYSCTRL_FUSES_OSC32K_CAL_Msk & ((value) << SYSCTRL_FUSES_OSC32K_CAL_Pos)))\n\t// u32_t fuse = *(u32_t *)FUSES_OSC32K_CAL_ADDR;\n\t// u32_t calib = (fuse & FUSES_OSC32K_CAL_Msk) >> FUSES_OSC32K_CAL_Pos;\n\tfuse := *(*uint32)(unsafe.Pointer(uintptr(0x00806020) + 4))\n\tcalib := (fuse & uint32(0x7f<<6)) >> 6\n\n\t// SYSCTRL_OSC32K_CALIB(calib) |\n\t//  SYSCTRL_OSC32K_STARTUP(0x6u) |\n\t//  SYSCTRL_OSC32K_EN32K | SYSCTRL_OSC32K_ENABLE;\n\tsam.SYSCTRL.OSC32K.Set((calib << sam.SYSCTRL_OSC32K_CALIB_Pos) |\n\t\t(0x6 << sam.SYSCTRL_OSC32K_STARTUP_Pos) |\n\t\tsam.SYSCTRL_OSC32K_EN32K |\n\t\tsam.SYSCTRL_OSC32K_EN1K |\n\t\tsam.SYSCTRL_OSC32K_ENABLE)\n\t// Wait for oscillator stabilization\n\tfor !sam.SYSCTRL.PCLKSR.HasBits(sam.SYSCTRL_PCLKSR_OSC32KRDY) {\n\t}\n\n\t// Software reset the module to ensure it is re-initialized correctly\n\tsam.GCLK.CTRL.Set(sam.GCLK_CTRL_SWRST)\n\t// Wait for reset to complete\n\tfor sam.GCLK.CTRL.HasBits(sam.GCLK_CTRL_SWRST) && sam.GCLK.STATUS.HasBits(sam.GCLK_STATUS_SYNCBUSY) {\n\t}\n\n\t// Put OSC32K as source of Generic Clock Generator 1\n\tsam.GCLK.GENDIV.Set((1 << sam.GCLK_GENDIV_ID_Pos) |\n\t\t(0 << sam.GCLK_GENDIV_DIV_Pos))\n\twaitForSync()\n\n\t// GCLK_GENCTRL_ID(1) | GCLK_GENCTRL_SRC_OSC32K | GCLK_GENCTRL_GENEN;\n\tsam.GCLK.GENCTRL.Set((1 << sam.GCLK_GENCTRL_ID_Pos) |\n\t\t(sam.GCLK_GENCTRL_SRC_OSC32K << sam.GCLK_GENCTRL_SRC_Pos) |\n\t\tsam.GCLK_GENCTRL_GENEN)\n\twaitForSync()\n\n\t// Use Generic Clock Generator 1 as source for Generic Clock Multiplexer 0 (DFLL48M reference)\n\tsam.GCLK.CLKCTRL.Set((sam.GCLK_CLKCTRL_ID_DFLL48 << sam.GCLK_CLKCTRL_ID_Pos) |\n\t\t(sam.GCLK_CLKCTRL_GEN_GCLK1 << sam.GCLK_CLKCTRL_GEN_Pos) |\n\t\tsam.GCLK_CLKCTRL_CLKEN)\n\twaitForSync()\n\n\t// Remove the OnDemand mode, Bug http://avr32.icgroup.norway.atmel.com/bugzilla/show_bug.cgi?id=9905\n\tsam.SYSCTRL.DFLLCTRL.Set(sam.SYSCTRL_DFLLCTRL_ENABLE)\n\t// Wait for ready\n\tfor !sam.SYSCTRL.PCLKSR.HasBits(sam.SYSCTRL_PCLKSR_DFLLRDY) {\n\t}\n\n\t// Handle DFLL calibration based on info learned from Arduino SAMD implementation,\n\t// using value stored in fuse.\n\t// #define SYSCTRL_FUSES_DFLL48M_COARSE_CAL_ADDR (NVMCTRL_OTP4 + 4)\n\t// #define SYSCTRL_FUSES_DFLL48M_COARSE_CAL_Pos 26           /**< \\brief (NVMCTRL_OTP4) DFLL48M Coarse Calibration */\n\t// #define SYSCTRL_FUSES_DFLL48M_COARSE_CAL_Msk (0x3Fu << SYSCTRL_FUSES_DFLL48M_COARSE_CAL_Pos)\n\t// #define SYSCTRL_FUSES_DFLL48M_COARSE_CAL(value) ((SYSCTRL_FUSES_DFLL48M_COARSE_CAL_Msk & ((value) << SYSCTRL_FUSES_DFLL48M_COARSE_CAL_Pos)))\n\tcoarse := (fuse >> 26) & 0x3F\n\tif coarse == 0x3f {\n\t\tcoarse = 0x1f\n\t}\n\n\tsam.SYSCTRL.DFLLVAL.SetBits(coarse << sam.SYSCTRL_DFLLVAL_COARSE_Pos)\n\tsam.SYSCTRL.DFLLVAL.SetBits(0x1ff << sam.SYSCTRL_DFLLVAL_FINE_Pos)\n\n\t// Write full configuration to DFLL control register\n\t// SYSCTRL_DFLLMUL_CSTEP( 0x1f / 4 ) | // Coarse step is 31, half of the max value\n\t// SYSCTRL_DFLLMUL_FSTEP( 10 ) |\n\t// SYSCTRL_DFLLMUL_MUL( (48000) ) ;\n\tsam.SYSCTRL.DFLLMUL.Set(((31 / 4) << sam.SYSCTRL_DFLLMUL_CSTEP_Pos) |\n\t\t(10 << sam.SYSCTRL_DFLLMUL_FSTEP_Pos) |\n\t\t(48000 << sam.SYSCTRL_DFLLMUL_MUL_Pos))\n\n\t// disable DFLL\n\tsam.SYSCTRL.DFLLCTRL.Set(0)\n\twaitForSync()\n\n\tsam.SYSCTRL.DFLLCTRL.SetBits(sam.SYSCTRL_DFLLCTRL_MODE |\n\t\tsam.SYSCTRL_DFLLCTRL_CCDIS |\n\t\tsam.SYSCTRL_DFLLCTRL_USBCRM |\n\t\tsam.SYSCTRL_DFLLCTRL_BPLCKC)\n\t// Wait for ready\n\tfor !sam.SYSCTRL.PCLKSR.HasBits(sam.SYSCTRL_PCLKSR_DFLLRDY) {\n\t}\n\n\t// Re-enable the DFLL\n\tsam.SYSCTRL.DFLLCTRL.SetBits(sam.SYSCTRL_DFLLCTRL_ENABLE)\n\t// Wait for ready\n\tfor !sam.SYSCTRL.PCLKSR.HasBits(sam.SYSCTRL_PCLKSR_DFLLRDY) {\n\t}\n\n\t// Switch Generic Clock Generator 0 to DFLL48M. CPU will run at 48MHz.\n\tsam.GCLK.GENDIV.Set((0 << sam.GCLK_GENDIV_ID_Pos) |\n\t\t(0 << sam.GCLK_GENDIV_DIV_Pos))\n\twaitForSync()\n\n\tsam.GCLK.GENCTRL.Set((0 << sam.GCLK_GENCTRL_ID_Pos) |\n\t\t(sam.GCLK_GENCTRL_SRC_DFLL48M << sam.GCLK_GENCTRL_SRC_Pos) |\n\t\tsam.GCLK_GENCTRL_IDC |\n\t\tsam.GCLK_GENCTRL_GENEN)\n\twaitForSync()\n\n\t// Modify PRESCaler value of OSC8M to have 8MHz\n\tsam.SYSCTRL.OSC8M.SetBits(sam.SYSCTRL_OSC8M_PRESC_0 << sam.SYSCTRL_OSC8M_PRESC_Pos)\n\tsam.SYSCTRL.OSC8M.ClearBits(1 << sam.SYSCTRL_OSC8M_ONDEMAND_Pos)\n\t// Wait for oscillator stabilization\n\tfor !sam.SYSCTRL.PCLKSR.HasBits(sam.SYSCTRL_PCLKSR_OSC8MRDY) {\n\t}\n\n\t// Use OSC8M as source for Generic Clock Generator 3\n\tsam.GCLK.GENDIV.Set((3 << sam.GCLK_GENDIV_ID_Pos))\n\twaitForSync()\n\n\tsam.GCLK.GENCTRL.Set((3 << sam.GCLK_GENCTRL_ID_Pos) |\n\t\t(sam.GCLK_GENCTRL_SRC_OSC8M << sam.GCLK_GENCTRL_SRC_Pos) |\n\t\tsam.GCLK_GENCTRL_GENEN)\n\twaitForSync()\n\n\t// Use OSC32K as source for Generic Clock Generator 2\n\t// OSC32K/1 -> GCLK2 at 32KHz\n\tsam.GCLK.GENDIV.Set(2 << sam.GCLK_GENDIV_ID_Pos)\n\twaitForSync()\n\n\tsam.GCLK.GENCTRL.Set((2 << sam.GCLK_GENCTRL_ID_Pos) |\n\t\t(sam.GCLK_GENCTRL_SRC_OSC32K << sam.GCLK_GENCTRL_SRC_Pos) |\n\t\tsam.GCLK_GENCTRL_GENEN)\n\twaitForSync()\n\n\t// Use GCLK2 for RTC\n\tsam.GCLK.CLKCTRL.Set((sam.GCLK_CLKCTRL_ID_RTC << sam.GCLK_CLKCTRL_ID_Pos) |\n\t\t(sam.GCLK_CLKCTRL_GEN_GCLK2 << sam.GCLK_CLKCTRL_GEN_Pos) |\n\t\tsam.GCLK_CLKCTRL_CLKEN)\n\twaitForSync()\n\n\t// Set the CPU, APBA, B, and C dividers\n\tsam.PM.CPUSEL.Set(sam.PM_CPUSEL_CPUDIV_DIV1)\n\tsam.PM.APBASEL.Set(sam.PM_APBASEL_APBADIV_DIV1)\n\tsam.PM.APBBSEL.Set(sam.PM_APBBSEL_APBBDIV_DIV1)\n\tsam.PM.APBCSEL.Set(sam.PM_APBCSEL_APBCDIV_DIV1)\n\n\t// Disable automatic NVM write operations\n\tsam.NVMCTRL.CTRLB.SetBits(sam.NVMCTRL_CTRLB_MANW)\n}\n\nfunc initRTC() {\n\t// turn on digital interface clock\n\tsam.PM.APBAMASK.SetBits(sam.PM_APBAMASK_RTC_)\n\n\t// disable RTC\n\tsam.RTC_MODE0.CTRL.Set(0)\n\twaitForSync()\n\n\t// reset RTC\n\tsam.RTC_MODE0.CTRL.SetBits(sam.RTC_MODE0_CTRL_SWRST)\n\twaitForSync()\n\n\t// set Mode0 to 32-bit counter (mode 0) with prescaler 1 and GCLK2 is 32KHz/1\n\tsam.RTC_MODE0.CTRL.Set((sam.RTC_MODE0_CTRL_MODE_COUNT32 << sam.RTC_MODE0_CTRL_MODE_Pos) |\n\t\t(sam.RTC_MODE0_CTRL_PRESCALER_DIV1 << sam.RTC_MODE0_CTRL_PRESCALER_Pos))\n\twaitForSync()\n\n\t// re-enable RTC\n\tsam.RTC_MODE0.CTRL.SetBits(sam.RTC_MODE0_CTRL_ENABLE)\n\twaitForSync()\n\n\trtcInterrupt := interrupt.New(sam.IRQ_RTC, func(intr interrupt.Interrupt) {\n\t\tflags := sam.RTC_MODE0.INTFLAG.Get()\n\t\tif flags&sam.RTC_MODE0_INTENSET_CMP0 != 0 {\n\t\t\t// The timer (for a sleep) has expired.\n\t\t\ttimerWakeup.Set(1)\n\t\t}\n\t\tif flags&sam.RTC_MODE0_INTENSET_OVF != 0 {\n\t\t\t// The 32-bit RTC timer has overflowed.\n\t\t\trtcOverflows.Set(rtcOverflows.Get() + 1)\n\t\t}\n\t\t// Mark this interrupt has handled for CMP0 and OVF.\n\t\tsam.RTC_MODE0.INTFLAG.Set(sam.RTC_MODE0_INTENSET_CMP0 | sam.RTC_MODE0_INTENSET_OVF)\n\t})\n\tsam.RTC_MODE0.INTENSET.Set(sam.RTC_MODE0_INTENSET_OVF)\n\trtcInterrupt.SetPriority(0xc0)\n\trtcInterrupt.Enable()\n}\n\nfunc waitForSync() {\n\tfor sam.GCLK.STATUS.HasBits(sam.GCLK_STATUS_SYNCBUSY) {\n\t}\n}\n\nvar rtcOverflows volatile.Register32 // number of times the RTC wrapped around\n\nvar timerWakeup volatile.Register8\n\n// ticksToNanoseconds converts RTC ticks (at 32768Hz) to nanoseconds.\nfunc ticksToNanoseconds(ticks timeUnit) int64 {\n\t// The following calculation is actually the following, but with both sides\n\t// reduced to reduce the risk of overflow:\n\t//     ticks * 1e9 / 32768\n\treturn int64(ticks) * 1953125 / 64\n}\n\n// nanosecondsToTicks converts nanoseconds to RTC ticks (running at 32768Hz).\nfunc nanosecondsToTicks(ns int64) timeUnit {\n\t// The following calculation is actually the following, but with both sides\n\t// reduced to reduce the risk of overflow:\n\t//     ns * 32768 / 1e9\n\treturn timeUnit(ns * 64 / 1953125)\n}\n\n// sleepTicks should sleep for d number of microseconds.\nfunc sleepTicks(d timeUnit) {\n\tfor d != 0 {\n\t\tticks := uint32(d)\n\t\tif d > 0xffff_ffff {\n\t\t\tticks = 0xffff_ffff\n\t\t}\n\t\tif !timerSleep(ticks) {\n\t\t\t// Bail out early to handle a non-time interrupt.\n\t\t\treturn\n\t\t}\n\t\td -= timeUnit(ticks)\n\t}\n}\n\n// ticks returns the elapsed time since reset.\nfunc ticks() timeUnit {\n\t// For some ways of capturing the time atomically, see this thread:\n\t// https://www.eevblog.com/forum/microcontrollers/correct-timing-by-timer-overflow-count/msg749617/#msg749617\n\t// Here, instead of re-reading the counter register if an overflow has been\n\t// detected, we simply try again because that results in smaller code.\n\tfor {\n\t\tmask := interrupt.Disable()\n\t\tcounter := readRTC()\n\t\toverflows := rtcOverflows.Get()\n\t\thasOverflow := sam.RTC_MODE0.INTFLAG.Get()&sam.RTC_MODE0_INTENSET_OVF != 0\n\t\tinterrupt.Restore(mask)\n\n\t\tif hasOverflow {\n\t\t\t// There was an overflow while trying to capture the timer.\n\t\t\t// Try again.\n\t\t\tcontinue\n\t\t}\n\n\t\t// This is a 32-bit timer, so the number of timer overflows forms the\n\t\t// upper 32 bits of this timer.\n\t\treturn timeUnit(overflows)<<32 + timeUnit(counter)\n\t}\n}\n\nfunc readRTC() uint32 {\n\t// request read of count\n\tsam.RTC_MODE0.READREQ.Set(sam.RTC_MODE0_READREQ_RREQ)\n\twaitForSync()\n\n\treturn sam.RTC_MODE0.COUNT.Get()\n}\n\n// ticks are in microseconds\n// Returns true if the timer completed.\n// Returns false if another interrupt occurred which requires an early return to scheduler.\nfunc timerSleep(ticks uint32) bool {\n\ttimerWakeup.Set(0)\n\tif ticks < 7 {\n\t\t// Due to around 6 clock ticks delay waiting for the register value to\n\t\t// sync, the minimum sleep value for the SAMD21 is 214us.\n\t\t// For related info, see:\n\t\t// https://community.atmel.com/comment/2507091#comment-2507091\n\t\tticks = 7\n\t}\n\n\t// request read of count\n\tsam.RTC_MODE0.READREQ.Set(sam.RTC_MODE0_READREQ_RREQ)\n\twaitForSync()\n\n\t// set compare value\n\tcnt := sam.RTC_MODE0.COUNT.Get()\n\tsam.RTC_MODE0.COMP0.Set(uint32(cnt) + ticks)\n\twaitForSync()\n\n\t// enable IRQ for CMP0 compare\n\tsam.RTC_MODE0.INTENSET.Set(sam.RTC_MODE0_INTENSET_CMP0)\n\nwait:\n\twaitForEvents()\n\tif timerWakeup.Get() != 0 {\n\t\treturn true\n\t}\n\tif hasScheduler {\n\t\t// The interurpt may have awoken a goroutine, so bail out early.\n\t\t// Disable IRQ for CMP0 compare.\n\t\tsam.RTC_MODE0.INTENCLR.Set(sam.RTC_MODE0_INTENSET_CMP0)\n\t\treturn false\n\t} else {\n\t\t// This is running without a scheduler.\n\t\t// The application expects this to sleep the whole time.\n\t\tgoto wait\n\t}\n}\n\nfunc initUSBClock() {\n\t// Turn on clock for USB\n\tsam.PM.APBBMASK.SetBits(sam.PM_APBBMASK_USB_)\n\n\t// Put Generic Clock Generator 0 as source for Generic Clock Multiplexer 6 (USB reference)\n\tsam.GCLK.CLKCTRL.Set((sam.GCLK_CLKCTRL_ID_USB << sam.GCLK_CLKCTRL_ID_Pos) |\n\t\t(sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |\n\t\tsam.GCLK_CLKCTRL_CLKEN)\n\twaitForSync()\n}\n\nfunc initADCClock() {\n\t// Turn on clock for ADC\n\tsam.PM.APBCMASK.SetBits(sam.PM_APBCMASK_ADC_)\n\n\t// Put Generic Clock Generator 0 as source for Generic Clock Multiplexer for ADC.\n\tsam.GCLK.CLKCTRL.Set((sam.GCLK_CLKCTRL_ID_ADC << sam.GCLK_CLKCTRL_ID_Pos) |\n\t\t(sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |\n\t\tsam.GCLK_CLKCTRL_CLKEN)\n\twaitForSync()\n}\n\nfunc waitForEvents() {\n\tarm.Asm(\"wfe\")\n}\n"
  },
  {
    "path": "src/runtime/runtime_atsamd21e18.go",
    "content": "//go:build sam && atsamd21 && atsamd21e18\n\npackage runtime\n\nimport (\n\t\"device/sam\"\n)\n\nfunc initSERCOMClocks() {\n\t// Turn on clock to SERCOM0 for UART0\n\tsam.PM.APBCMASK.SetBits(sam.PM_APBCMASK_SERCOM0_)\n\n\t// Use GCLK0 for SERCOM0 aka UART0\n\t// GCLK_CLKCTRL_ID( clockId ) | // Generic Clock 0 (SERCOMx)\n\t// GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source\n\t// GCLK_CLKCTRL_CLKEN ;\n\tsam.GCLK.CLKCTRL.Set((sam.GCLK_CLKCTRL_ID_SERCOM0_CORE << sam.GCLK_CLKCTRL_ID_Pos) |\n\t\t(sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |\n\t\tsam.GCLK_CLKCTRL_CLKEN)\n\twaitForSync()\n\n\t// Turn on clock to SERCOM1\n\tsam.PM.APBCMASK.SetBits(sam.PM_APBCMASK_SERCOM1_)\n\tsam.GCLK.CLKCTRL.Set((sam.GCLK_CLKCTRL_ID_SERCOM1_CORE << sam.GCLK_CLKCTRL_ID_Pos) |\n\t\t(sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |\n\t\tsam.GCLK_CLKCTRL_CLKEN)\n\twaitForSync()\n\n\t// Turn on clock to SERCOM2\n\tsam.PM.APBCMASK.SetBits(sam.PM_APBCMASK_SERCOM2_)\n\tsam.GCLK.CLKCTRL.Set((sam.GCLK_CLKCTRL_ID_SERCOM2_CORE << sam.GCLK_CLKCTRL_ID_Pos) |\n\t\t(sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |\n\t\tsam.GCLK_CLKCTRL_CLKEN)\n\twaitForSync()\n\n\t// Turn on clock to SERCOM3\n\tsam.PM.APBCMASK.SetBits(sam.PM_APBCMASK_SERCOM3_)\n\tsam.GCLK.CLKCTRL.Set((sam.GCLK_CLKCTRL_ID_SERCOM3_CORE << sam.GCLK_CLKCTRL_ID_Pos) |\n\t\t(sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |\n\t\tsam.GCLK_CLKCTRL_CLKEN)\n\twaitForSync()\n}\n"
  },
  {
    "path": "src/runtime/runtime_atsamd21g18.go",
    "content": "//go:build sam && atsamd21 && atsamd21g18\n\npackage runtime\n\nimport (\n\t\"device/sam\"\n)\n\nfunc initSERCOMClocks() {\n\t// Turn on clock to SERCOM0 for UART0\n\tsam.PM.APBCMASK.SetBits(sam.PM_APBCMASK_SERCOM0_)\n\n\t// Use GCLK0 for SERCOM0 aka UART0\n\t// GCLK_CLKCTRL_ID( clockId ) | // Generic Clock 0 (SERCOMx)\n\t// GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source\n\t// GCLK_CLKCTRL_CLKEN ;\n\tsam.GCLK.CLKCTRL.Set((sam.GCLK_CLKCTRL_ID_SERCOM0_CORE << sam.GCLK_CLKCTRL_ID_Pos) |\n\t\t(sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |\n\t\tsam.GCLK_CLKCTRL_CLKEN)\n\twaitForSync()\n\n\t// Turn on clock to SERCOM1\n\tsam.PM.APBCMASK.SetBits(sam.PM_APBCMASK_SERCOM1_)\n\tsam.GCLK.CLKCTRL.Set((sam.GCLK_CLKCTRL_ID_SERCOM1_CORE << sam.GCLK_CLKCTRL_ID_Pos) |\n\t\t(sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |\n\t\tsam.GCLK_CLKCTRL_CLKEN)\n\twaitForSync()\n\n\t// Turn on clock to SERCOM2\n\tsam.PM.APBCMASK.SetBits(sam.PM_APBCMASK_SERCOM2_)\n\tsam.GCLK.CLKCTRL.Set((sam.GCLK_CLKCTRL_ID_SERCOM2_CORE << sam.GCLK_CLKCTRL_ID_Pos) |\n\t\t(sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |\n\t\tsam.GCLK_CLKCTRL_CLKEN)\n\twaitForSync()\n\n\t// Turn on clock to SERCOM3\n\tsam.PM.APBCMASK.SetBits(sam.PM_APBCMASK_SERCOM3_)\n\tsam.GCLK.CLKCTRL.Set((sam.GCLK_CLKCTRL_ID_SERCOM3_CORE << sam.GCLK_CLKCTRL_ID_Pos) |\n\t\t(sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |\n\t\tsam.GCLK_CLKCTRL_CLKEN)\n\twaitForSync()\n\n\t// Turn on clock to SERCOM4\n\tsam.PM.APBCMASK.SetBits(sam.PM_APBCMASK_SERCOM4_)\n\n\t// Use GCLK0 for SERCOM4\n\tsam.GCLK.CLKCTRL.Set((sam.GCLK_CLKCTRL_ID_SERCOM4_CORE << sam.GCLK_CLKCTRL_ID_Pos) |\n\t\t(sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |\n\t\tsam.GCLK_CLKCTRL_CLKEN)\n\twaitForSync()\n\n\t// Turn on clock to SERCOM5\n\tsam.PM.APBCMASK.SetBits(sam.PM_APBCMASK_SERCOM5_)\n\n\t// Use GCLK0 for SERCOM5\n\tsam.GCLK.CLKCTRL.Set((sam.GCLK_CLKCTRL_ID_SERCOM5_CORE << sam.GCLK_CLKCTRL_ID_Pos) |\n\t\t(sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) |\n\t\tsam.GCLK_CLKCTRL_CLKEN)\n\twaitForSync()\n}\n"
  },
  {
    "path": "src/runtime/runtime_atsamd51.go",
    "content": "//go:build (sam && atsamd51) || (sam && atsame5x)\n\npackage runtime\n\nimport (\n\t\"device/arm\"\n\t\"device/sam\"\n\t\"machine\"\n\t_ \"machine/usb/cdc\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n)\n\n//export Reset_Handler\nfunc main() {\n\tarm.SCB.CPACR.Set(0) // disable FPU if it is enabled\n\tpreinit()\n\trun()\n\texit(0)\n}\n\nfunc init() {\n\tinitClocks()\n\tinitRTC()\n\tinitSERCOMClocks()\n\tinitUSBClock()\n\tinitADCClock()\n\tenableCache()\n\n\tmachine.InitSerial()\n}\n\nfunc putchar(c byte) {\n\tmachine.Serial.WriteByte(c)\n}\n\nfunc getchar() byte {\n\tfor machine.Serial.Buffered() == 0 {\n\t\tGosched()\n\t}\n\tv, _ := machine.Serial.ReadByte()\n\treturn v\n}\n\nfunc buffered() int {\n\treturn machine.Serial.Buffered()\n}\n\nfunc initClocks() {\n\t// set flash wait state\n\tsam.NVMCTRL.CTRLA.SetBits(0 << sam.NVMCTRL_CTRLA_RWS_Pos)\n\n\t// software reset\n\tsam.GCLK.CTRLA.SetBits(sam.GCLK_CTRLA_SWRST)\n\tfor sam.GCLK.SYNCBUSY.HasBits(sam.GCLK_SYNCBUSY_SWRST) {\n\t}\n\n\t// Set OSCULP32K as source of Generic Clock Generator 3\n\t// GCLK->GENCTRL[GENERIC_CLOCK_GENERATOR_XOSC32K].reg = GCLK_GENCTRL_SRC(GCLK_GENCTRL_SRC_OSCULP32K) | GCLK_GENCTRL_GENEN; //generic clock gen 3\n\tsam.GCLK.GENCTRL[3].Set((sam.GCLK_GENCTRL_SRC_OSCULP32K << sam.GCLK_GENCTRL_SRC_Pos) |\n\t\tsam.GCLK_GENCTRL_GENEN)\n\tfor sam.GCLK.SYNCBUSY.HasBits(sam.GCLK_SYNCBUSY_GENCTRL_GCLK3) {\n\t}\n\n\t// Set OSCULP32K as source of Generic Clock Generator 0\n\tsam.GCLK.GENCTRL[0].Set((sam.GCLK_GENCTRL_SRC_OSCULP32K << sam.GCLK_GENCTRL_SRC_Pos) |\n\t\tsam.GCLK_GENCTRL_GENEN)\n\tfor sam.GCLK.SYNCBUSY.HasBits(sam.GCLK_SYNCBUSY_GENCTRL_GCLK0) {\n\t}\n\n\t// Enable DFLL48M clock\n\tsam.OSCCTRL.DFLLCTRLA.Set(0)\n\tsam.OSCCTRL.DFLLMUL.Set((0x1 << sam.OSCCTRL_DFLLMUL_CSTEP_Pos) |\n\t\t(0x1 << sam.OSCCTRL_DFLLMUL_FSTEP_Pos) |\n\t\t(0x0 << sam.OSCCTRL_DFLLMUL_MUL_Pos))\n\tfor sam.OSCCTRL.DFLLSYNC.HasBits(sam.OSCCTRL_DFLLSYNC_DFLLMUL) {\n\t}\n\n\tsam.OSCCTRL.DFLLCTRLB.Set(0)\n\tfor sam.OSCCTRL.DFLLSYNC.HasBits(sam.OSCCTRL_DFLLSYNC_DFLLCTRLB) {\n\t}\n\n\tsam.OSCCTRL.DFLLCTRLA.SetBits(sam.OSCCTRL_DFLLCTRLA_ENABLE)\n\tfor sam.OSCCTRL.DFLLSYNC.HasBits(sam.OSCCTRL_DFLLSYNC_ENABLE) {\n\t}\n\n\tsam.OSCCTRL.DFLLVAL.Set(sam.OSCCTRL.DFLLVAL.Get())\n\tfor sam.OSCCTRL.DFLLSYNC.HasBits(sam.OSCCTRL_DFLLSYNC_DFLLVAL) {\n\t}\n\n\tsam.OSCCTRL.DFLLCTRLB.Set(sam.OSCCTRL_DFLLCTRLB_WAITLOCK |\n\t\tsam.OSCCTRL_DFLLCTRLB_CCDIS |\n\t\tsam.OSCCTRL_DFLLCTRLB_USBCRM)\n\tfor !sam.OSCCTRL.STATUS.HasBits(sam.OSCCTRL_STATUS_DFLLRDY) {\n\t}\n\n\t// set GCLK7 to run at 2MHz, using DFLL48M as clock source\n\t// GCLK7 = 48MHz / 24 = 2MHz\n\tsam.GCLK.GENCTRL[7].Set((sam.GCLK_GENCTRL_SRC_DFLL << sam.GCLK_GENCTRL_SRC_Pos) |\n\t\t(24 << sam.GCLK_GENCTRL_DIV_Pos) |\n\t\tsam.GCLK_GENCTRL_GENEN)\n\tfor sam.GCLK.SYNCBUSY.HasBits(sam.GCLK_SYNCBUSY_GENCTRL_GCLK7) {\n\t}\n\n\t// Set up the PLLs\n\n\t// Set PLL0 to run at 120MHz, using GCLK7 as clock source\n\tsam.GCLK.PCHCTRL[1].Set(sam.GCLK_PCHCTRL_CHEN |\n\t\t(sam.GCLK_PCHCTRL_GEN_GCLK7 << sam.GCLK_PCHCTRL_GEN_Pos))\n\n\t// multiplier = 59 + 1 + (0/32) = 60\n\t// PLL0 = 2MHz * 60 = 120MHz\n\tsam.OSCCTRL.DPLL[0].DPLLRATIO.Set((0x0 << sam.OSCCTRL_DPLL_DPLLRATIO_LDRFRAC_Pos) |\n\t\t(59 << sam.OSCCTRL_DPLL_DPLLRATIO_LDR_Pos))\n\tfor sam.OSCCTRL.DPLL[0].DPLLSYNCBUSY.HasBits(sam.OSCCTRL_DPLL_DPLLSYNCBUSY_DPLLRATIO) {\n\t}\n\n\t// MUST USE LBYPASS DUE TO BUG IN REV A OF SAMD51, via Adafruit lib.\n\tsam.OSCCTRL.DPLL[0].DPLLCTRLB.Set((sam.OSCCTRL_DPLL_DPLLCTRLB_REFCLK_GCLK << sam.OSCCTRL_DPLL_DPLLCTRLB_REFCLK_Pos) |\n\t\tsam.OSCCTRL_DPLL_DPLLCTRLB_LBYPASS)\n\n\tsam.OSCCTRL.DPLL[0].DPLLCTRLA.Set(sam.OSCCTRL_DPLL_DPLLCTRLA_ENABLE)\n\tfor !sam.OSCCTRL.DPLL[0].DPLLSTATUS.HasBits(sam.OSCCTRL_DPLL_DPLLSTATUS_CLKRDY) ||\n\t\t!sam.OSCCTRL.DPLL[0].DPLLSTATUS.HasBits(sam.OSCCTRL_DPLL_DPLLSTATUS_LOCK) {\n\t}\n\n\t// Set PLL1 to run at 100MHz, using GCLK7 as clock source\n\tsam.GCLK.PCHCTRL[2].Set(sam.GCLK_PCHCTRL_CHEN |\n\t\t(sam.GCLK_PCHCTRL_GEN_GCLK7 << sam.GCLK_PCHCTRL_GEN_Pos))\n\n\t// multiplier = 49 + 1 + (0/32) = 50\n\t// PLL1 = 2MHz * 50 = 100MHz\n\tsam.OSCCTRL.DPLL[1].DPLLRATIO.Set((0x0 << sam.OSCCTRL_DPLL_DPLLRATIO_LDRFRAC_Pos) |\n\t\t(49 << sam.OSCCTRL_DPLL_DPLLRATIO_LDR_Pos))\n\tfor sam.OSCCTRL.DPLL[1].DPLLSYNCBUSY.HasBits(sam.OSCCTRL_DPLL_DPLLSYNCBUSY_DPLLRATIO) {\n\t}\n\n\t// // MUST USE LBYPASS DUE TO BUG IN REV A OF SAMD51\n\tsam.OSCCTRL.DPLL[1].DPLLCTRLB.Set((sam.OSCCTRL_DPLL_DPLLCTRLB_REFCLK_GCLK << sam.OSCCTRL_DPLL_DPLLCTRLB_REFCLK_Pos) |\n\t\tsam.OSCCTRL_DPLL_DPLLCTRLB_LBYPASS)\n\n\tsam.OSCCTRL.DPLL[1].DPLLCTRLA.Set(sam.OSCCTRL_DPLL_DPLLCTRLA_ENABLE)\n\t// for !sam.OSCCTRL.DPLLSTATUS1.HasBits(sam.OSCCTRL_DPLLSTATUS_CLKRDY) ||\n\t// \t!sam.OSCCTRL.DPLLSTATUS1.HasBits(sam.OSCCTRL_DPLLSTATUS_LOCK) {\n\t// }\n\n\t// Set up the peripheral clocks\n\t// Set 48MHZ CLOCK FOR USB\n\tsam.GCLK.GENCTRL[1].Set((sam.GCLK_GENCTRL_SRC_DFLL << sam.GCLK_GENCTRL_SRC_Pos) |\n\t\tsam.GCLK_GENCTRL_IDC |\n\t\tsam.GCLK_GENCTRL_GENEN)\n\tfor sam.GCLK.SYNCBUSY.HasBits(sam.GCLK_SYNCBUSY_GENCTRL_GCLK1) {\n\t}\n\n\t// // Set 100MHZ CLOCK FOR OTHER PERIPHERALS\n\t// sam.GCLK.GENCTRL2.Set((sam.GCLK_GENCTRL_SRC_DPLL1 << sam.GCLK_GENCTRL_SRC_Pos) |\n\t// \tsam.GCLK_GENCTRL_IDC |\n\t// \tsam.GCLK_GENCTRL_GENEN)\n\t// for sam.GCLK.SYNCBUSY.HasBits(sam.GCLK_SYNCBUSY_GENCTRL2) {\n\t// }\n\n\t// // Set 12MHZ CLOCK FOR DAC\n\tsam.GCLK.GENCTRL[4].Set((sam.GCLK_GENCTRL_SRC_DFLL << sam.GCLK_GENCTRL_SRC_Pos) |\n\t\tsam.GCLK_GENCTRL_IDC |\n\t\t(4 << sam.GCLK_GENCTRL_DIVSEL_Pos) |\n\t\tsam.GCLK_GENCTRL_GENEN)\n\tfor sam.GCLK.SYNCBUSY.HasBits(sam.GCLK_SYNCBUSY_GENCTRL_GCLK4) {\n\t}\n\n\t// // Set up main clock\n\tsam.GCLK.GENCTRL[0].Set((sam.GCLK_GENCTRL_SRC_DPLL0 << sam.GCLK_GENCTRL_SRC_Pos) |\n\t\tsam.GCLK_GENCTRL_IDC |\n\t\tsam.GCLK_GENCTRL_GENEN)\n\tfor sam.GCLK.SYNCBUSY.HasBits(sam.GCLK_SYNCBUSY_GENCTRL_GCLK0) {\n\t}\n\n\tsam.MCLK.CPUDIV.Set(sam.MCLK_CPUDIV_DIV_DIV1)\n\n\t// Use the LDO regulator by default\n\tsam.SUPC.VREG.ClearBits(sam.SUPC_VREG_SEL)\n\n\t// Start up the \"Debug Watchpoint and Trace\" unit, so that we can use\n\t// it's 32bit cycle counter for timing.\n\t//CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;\n\t//DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;\n\n\t// Disable automatic NVM write operations\n\tsam.NVMCTRL.SetCTRLA_WMODE(sam.NVMCTRL_CTRLA_WMODE_MAN)\n}\n\nfunc initRTC() {\n\t// turn on digital interface clock\n\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_RTC_)\n\n\t// disable RTC\n\tsam.RTC_MODE0.CTRLA.ClearBits(sam.RTC_MODE0_CTRLA_ENABLE)\n\t//sam.RTC_MODE0.CTRLA.Set(0)\n\tfor sam.RTC_MODE0.SYNCBUSY.HasBits(sam.RTC_MODE0_SYNCBUSY_ENABLE) {\n\t}\n\n\t// reset RTC\n\tsam.RTC_MODE0.CTRLA.SetBits(sam.RTC_MODE0_CTRLA_SWRST)\n\tfor sam.RTC_MODE0.SYNCBUSY.HasBits(sam.RTC_MODE0_SYNCBUSY_SWRST) {\n\t}\n\n\t// set to use ulp 32k oscillator\n\tsam.OSC32KCTRL.OSCULP32K.SetBits(sam.OSC32KCTRL_OSCULP32K_EN32K)\n\tsam.OSC32KCTRL.RTCCTRL.Set(sam.OSC32KCTRL_RTCCTRL_RTCSEL_ULP32K)\n\n\t// set Mode0 to 32-bit counter (mode 0) with prescaler 1 and GCLK2 is 32KHz/1\n\tsam.RTC_MODE0.CTRLA.Set((sam.RTC_MODE0_CTRLA_MODE_COUNT32 << sam.RTC_MODE0_CTRLA_MODE_Pos) |\n\t\t(sam.RTC_MODE0_CTRLA_PRESCALER_DIV1 << sam.RTC_MODE0_CTRLA_PRESCALER_Pos) |\n\t\t(sam.RTC_MODE0_CTRLA_COUNTSYNC))\n\n\t// re-enable RTC\n\tsam.RTC_MODE0.CTRLA.SetBits(sam.RTC_MODE0_CTRLA_ENABLE)\n\tfor sam.RTC_MODE0.SYNCBUSY.HasBits(sam.RTC_MODE0_SYNCBUSY_ENABLE) {\n\t}\n\n\tirq := interrupt.New(sam.IRQ_RTC, func(interrupt.Interrupt) {\n\t\tflags := sam.RTC_MODE0.INTFLAG.Get()\n\t\tif flags&sam.RTC_MODE0_INTENSET_CMP0 != 0 {\n\t\t\t// The timer (for a sleep) has expired.\n\t\t\ttimerWakeup.Set(1)\n\t\t}\n\t\tif flags&sam.RTC_MODE0_INTENSET_OVF != 0 {\n\t\t\t// The 32-bit RTC timer has overflowed.\n\t\t\trtcOverflows.Set(rtcOverflows.Get() + 1)\n\t\t}\n\t\t// Mark this interrupt has handled for CMP0 and OVF.\n\t\tsam.RTC_MODE0.INTFLAG.Set(sam.RTC_MODE0_INTENSET_CMP0 | sam.RTC_MODE0_INTENSET_OVF)\n\t})\n\tsam.RTC_MODE0.INTENSET.Set(sam.RTC_MODE0_INTENSET_OVF)\n\tirq.SetPriority(0xc0)\n\tirq.Enable()\n}\n\nfunc waitForSync() {\n\tfor sam.RTC_MODE0.SYNCBUSY.HasBits(sam.RTC_MODE0_SYNCBUSY_COUNT) {\n\t}\n}\n\nvar rtcOverflows volatile.Register32 // number of times the RTC wrapped around\n\nvar timerWakeup volatile.Register8\n\n// ticksToNanoseconds converts RTC ticks (at 32768Hz) to nanoseconds.\nfunc ticksToNanoseconds(ticks timeUnit) int64 {\n\t// The following calculation is actually the following, but with both sides\n\t// reduced to reduce the risk of overflow:\n\t//     ticks * 1e9 / 32768\n\treturn int64(ticks) * 1953125 / 64\n}\n\n// nanosecondsToTicks converts nanoseconds to RTC ticks (running at 32768Hz).\nfunc nanosecondsToTicks(ns int64) timeUnit {\n\t// The following calculation is actually the following, but with both sides\n\t// reduced to reduce the risk of overflow:\n\t//     ns * 32768 / 1e9\n\treturn timeUnit(ns * 64 / 1953125)\n}\n\n// sleepTicks should sleep for d number of microseconds.\nfunc sleepTicks(d timeUnit) {\n\tfor d != 0 {\n\t\tticks := uint32(d)\n\t\tif d > 0xffff_ffff {\n\t\t\tticks = 0xffff_ffff\n\t\t}\n\t\tif !timerSleep(ticks) {\n\t\t\treturn\n\t\t}\n\t\td -= timeUnit(ticks)\n\t}\n}\n\n// ticks returns the elapsed time since reset.\nfunc ticks() timeUnit {\n\t// For some ways of capturing the time atomically, see this thread:\n\t// https://www.eevblog.com/forum/microcontrollers/correct-timing-by-timer-overflow-count/msg749617/#msg749617\n\t// Here, instead of re-reading the counter register if an overflow has been\n\t// detected, we simply try again because that results in smaller code.\n\tfor {\n\t\tmask := interrupt.Disable()\n\t\tcounter := readRTC()\n\t\toverflows := rtcOverflows.Get()\n\t\thasOverflow := sam.RTC_MODE0.INTFLAG.Get()&sam.RTC_MODE0_INTENSET_OVF != 0\n\t\tinterrupt.Restore(mask)\n\n\t\tif hasOverflow {\n\t\t\t// There was an overflow while trying to capture the timer.\n\t\t\t// Try again.\n\t\t\tcontinue\n\t\t}\n\n\t\t// This is a 32-bit timer, so the number of timer overflows forms the\n\t\t// upper 32 bits of this timer.\n\t\treturn timeUnit(overflows)<<32 + timeUnit(counter)\n\t}\n}\n\nfunc readRTC() uint32 {\n\twaitForSync()\n\treturn sam.RTC_MODE0.COUNT.Get()\n}\n\n// ticks are in microseconds\n// Returns true if the timer completed.\n// Returns false if another interrupt occurred which requires an early return to scheduler.\nfunc timerSleep(ticks uint32) bool {\n\ttimerWakeup.Set(0)\n\tif ticks < 8 {\n\t\t// due to delay waiting for the register value to sync, the minimum sleep value\n\t\t// for the SAMD51 is 260us.\n\t\t// For related info for SAMD21, see:\n\t\t// https://community.atmel.com/comment/2507091#comment-2507091\n\t\tticks = 8\n\t}\n\n\t// request read of count\n\twaitForSync()\n\n\t// set compare value\n\tcnt := sam.RTC_MODE0.COUNT.Get()\n\n\tsam.RTC_MODE0.COMP[0].Set(uint32(cnt) + ticks)\n\n\t// enable IRQ for CMP0 compare\n\tsam.RTC_MODE0.INTENSET.Set(sam.RTC_MODE0_INTENSET_CMP0)\n\nwait:\n\twaitForEvents()\n\tif timerWakeup.Get() != 0 {\n\t\treturn true\n\t}\n\tif hasScheduler {\n\t\t// The interurpt may have awoken a goroutine, so bail out early.\n\t\t// Disable IRQ for CMP0 compare.\n\t\tsam.RTC_MODE0.INTENCLR.Set(sam.RTC_MODE0_INTENSET_CMP0)\n\t\treturn false\n\t} else {\n\t\t// This is running without a scheduler.\n\t\t// The application expects this to sleep the whole time.\n\t\tgoto wait\n\t}\n}\n\nfunc initUSBClock() {\n\t// Turn on clock(s) for USB\n\t//MCLK->APBBMASK.reg |= MCLK_APBBMASK_USB;\n\t//MCLK->AHBMASK.reg |= MCLK_AHBMASK_USB;\n\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_USB_)\n\tsam.MCLK.AHBMASK.SetBits(sam.MCLK_AHBMASK_USB_)\n\n\t// Put Generic Clock Generator 1 as source for USB\n\t//GCLK->PCHCTRL[USB_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_USB].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n}\n\nfunc initADCClock() {\n\t// Turn on clocks for ADC0/ADC1.\n\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_ADC0_)\n\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_ADC1_)\n\n\t// Put Generic Clock Generator 1 as source for ADC0 and ADC1.\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_ADC0].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_ADC1].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n}\n\nfunc enableCache() {\n\tsam.CMCC.CTRL.SetBits(sam.CMCC_CTRL_CEN)\n}\n\nfunc waitForEvents() {\n\tarm.Asm(\"wfe\")\n}\n"
  },
  {
    "path": "src/runtime/runtime_atsamd51g19.go",
    "content": "//go:build sam && atsamd51 && atsamd51g19\n\npackage runtime\n\nimport (\n\t\"device/sam\"\n)\n\nfunc initSERCOMClocks() {\n\t// Turn on clock to SERCOM0 for UART0\n\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM0_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM0_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// sets the \"slow\" clock shared by all SERCOM\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOMX_SLOW].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM1\n\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM1_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM1_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM2\n\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM2_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM2_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM3\n\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM3_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM3_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM4\n\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM4_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM4_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM5\n\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM5_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM5_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n}\n"
  },
  {
    "path": "src/runtime/runtime_atsamd51j19.go",
    "content": "//go:build sam && atsamd51 && atsamd51j19\n\npackage runtime\n\nimport (\n\t\"device/sam\"\n)\n\nfunc initSERCOMClocks() {\n\t// Turn on clock to SERCOM0 for UART0\n\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM0_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM0_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// sets the \"slow\" clock shared by all SERCOM\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOMX_SLOW].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM1\n\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM1_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM1_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM2\n\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM2_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM2_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM3\n\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM3_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM3_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM4\n\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM4_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM4_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM5\n\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM5_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM5_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n}\n"
  },
  {
    "path": "src/runtime/runtime_atsamd51j20.go",
    "content": "//go:build sam && atsamd51 && atsamd51j20\n\npackage runtime\n\nimport (\n\t\"device/sam\"\n)\n\nfunc initSERCOMClocks() {\n\t// Turn on clock to SERCOM0 for UART0\n\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM0_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM0_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// sets the \"slow\" clock shared by all SERCOM\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOMX_SLOW].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM1\n\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM1_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM1_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM2\n\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM2_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM2_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM3\n\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM3_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM3_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM4\n\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM4_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM4_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM5\n\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM5_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM5_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n}\n"
  },
  {
    "path": "src/runtime/runtime_atsamd51p19.go",
    "content": "//go:build sam && atsamd51 && atsamd51p19\n\npackage runtime\n\nimport (\n\t\"device/sam\"\n)\n\nfunc initSERCOMClocks() {\n\t// Turn on clock to SERCOM0 for UART0\n\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM0_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM0_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// sets the \"slow\" clock shared by all SERCOM\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOMX_SLOW].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM1\n\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM1_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM1_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM2\n\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM2_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM2_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM3\n\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM3_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM3_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM4\n\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM4_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM4_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM5\n\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM5_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM5_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM6\n\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM6_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM6_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM7\n\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM7_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM7_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n}\n"
  },
  {
    "path": "src/runtime/runtime_atsamd51p20.go",
    "content": "//go:build sam && atsamd51 && atsamd51p20\n\npackage runtime\n\nimport (\n\t\"device/sam\"\n)\n\nfunc initSERCOMClocks() {\n\t// Turn on clock to SERCOM0 for UART0\n\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM0_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM0_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// sets the \"slow\" clock shared by all SERCOM\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOMX_SLOW].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM1\n\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM1_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM1_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM2\n\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM2_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM2_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM3\n\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM3_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM3_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM4\n\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM4_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM4_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM5\n\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM5_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM5_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM6\n\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM6_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM6_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM7\n\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM7_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM7_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n}\n"
  },
  {
    "path": "src/runtime/runtime_atsame51j19.go",
    "content": "//go:build sam && atsame51 && atsame51j19\n\npackage runtime\n\nimport (\n\t\"device/sam\"\n)\n\nfunc initSERCOMClocks() {\n\t// Turn on clock to SERCOM0 for UART0\n\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM0_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM0_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// sets the \"slow\" clock shared by all SERCOM\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOMX_SLOW].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM1\n\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM1_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM1_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM2\n\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM2_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM2_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM3\n\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM3_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM3_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM4\n\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM4_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM4_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM5\n\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM5_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM5_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n}\n"
  },
  {
    "path": "src/runtime/runtime_atsame54p20.go",
    "content": "//go:build sam && atsame5x && atsame54p20\n\npackage runtime\n\nimport (\n\t\"device/sam\"\n)\n\nfunc initSERCOMClocks() {\n\t// Turn on clock to SERCOM0 for UART0\n\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM0_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM0_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// sets the \"slow\" clock shared by all SERCOM\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOMX_SLOW].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM1\n\tsam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM1_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM1_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM2\n\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM2_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM2_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM3\n\tsam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM3_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM3_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM4\n\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM4_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM4_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM5\n\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM5_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM5_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM6\n\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM6_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM6_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\n\t// Turn on clock to SERCOM7\n\tsam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM7_)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_SERCOM7_CORE].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n}\n"
  },
  {
    "path": "src/runtime/runtime_atsame5x_can.go",
    "content": "//go:build (sam && atsame51) || (sam && atsame54)\n\npackage runtime\n\nimport (\n\t\"device/sam\"\n)\n\nfunc init() {\n\tinitCANClock()\n}\n\nfunc initCANClock() {\n\t// Turn on clocks for CAN0/CAN1.\n\tsam.MCLK.AHBMASK.SetBits(sam.MCLK_AHBMASK_CAN0_)\n\tsam.MCLK.AHBMASK.SetBits(sam.MCLK_AHBMASK_CAN1_)\n\n\t// Put Generic Clock Generator 1 as source for USB\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_CAN0].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n\tsam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_CAN1].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) |\n\t\tsam.GCLK_PCHCTRL_CHEN)\n}\n"
  },
  {
    "path": "src/runtime/runtime_attiny.go",
    "content": "//go:build avr && attiny\n\npackage runtime\n\nimport (\n\t\"device/avr\"\n)\n\nfunc initUART() {\n}\n\nfunc putchar(c byte) {\n\t// UART is not supported.\n}\n\nfunc getchar() byte {\n\t// UART is not supported.\n\treturn 0\n}\n\nfunc buffered() int {\n\t// UART is not supported.\n\treturn 0\n}\n\nfunc sleepWDT(period uint8) {\n\t// TODO: use the watchdog timer instead of a busy loop.\n\tfor i := 0x45; i != 0; i-- {\n\t\tfor i := 0xff; i != 0; i-- {\n\t\t\tavr.Asm(\"nop\")\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/runtime/runtime_avr.go",
    "content": "//go:build avr && !avrtiny\n\npackage runtime\n\nimport (\n\t\"device/avr\"\n\t\"machine\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nconst BOARD = \"arduino\"\n\n// Watchdog timer periods. These can be off by a large margin (hence the jump\n// between 64ms and 125ms which is not an exact double), so don't rely on this\n// for accurate time keeping.\nconst (\n\tWDT_PERIOD_16MS = iota\n\tWDT_PERIOD_32MS\n\tWDT_PERIOD_64MS\n\tWDT_PERIOD_125MS\n\tWDT_PERIOD_250MS\n\tWDT_PERIOD_500MS\n\tWDT_PERIOD_1S\n\tWDT_PERIOD_2S\n)\n\nconst timerRecalibrateInterval = 6e7 // 1 minute\n\nvar nextTimerRecalibrate timeUnit\n\n//go:extern _sbss\nvar _sbss [0]byte\n\n//go:extern _ebss\nvar _ebss [0]byte\n\n//export main\nfunc main() {\n\tpreinit()\n\tinitHardware()\n\trun()\n\texit(0)\n}\n\nfunc preinit() {\n\t// Initialize .bss: zero-initialized global variables.\n\tptr := unsafe.Pointer(&_sbss)\n\tfor ptr != unsafe.Pointer(&_ebss) {\n\t\t*(*uint8)(ptr) = 0\n\t\tptr = unsafe.Add(ptr, 1)\n\t}\n}\n\nfunc initHardware() {\n\tinitUART()\n\tinitMonotonicTimer()\n\tnextTimerRecalibrate = ticks() + timerRecalibrateInterval\n\n\t// Enable interrupts after initialization.\n\tavr.Asm(\"sei\")\n}\n\nfunc ticksToNanoseconds(ticks timeUnit) int64 {\n\treturn int64(ticks)\n}\n\nfunc nanosecondsToTicks(ns int64) timeUnit {\n\treturn timeUnit(ns)\n}\n\n// Sleep this number of ticks of nanoseconds.\nfunc sleepTicks(d timeUnit) {\n\twaitTill := ticks() + d\n\tfor {\n\t\t// wait for interrupt\n\t\tavr.Asm(\"sleep\")\n\t\tif waitTill <= ticks() {\n\t\t\t// done waiting\n\t\t\treturn\n\t\t}\n\t\tif hasScheduler {\n\t\t\t// The interrupt may have awoken a goroutine, so bail out early.\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc ticks() (ticksReturn timeUnit) {\n\tstate := interrupt.Disable()\n\t// use volatile since ticksCount can be changed when running on multi-core boards.\n\tticksReturn = timeUnit(volatile.LoadUint64((*uint64)(unsafe.Pointer(&ticksCount))))\n\tinterrupt.Restore(state)\n\treturn\n}\n\nfunc exit(code int) {\n\tabort()\n}\n\nfunc abort() {\n\t// Disable interrupts and go to sleep.\n\t// This can never be awoken except for reset, and is recognized as termination by simavr.\n\tavr.Asm(\"cli\")\n\tfor {\n\t\tavr.Asm(\"sleep\")\n\t}\n}\n\nvar ticksCount int64                // nanoseconds since start\nvar nanosecondsInTick int64 = 16000 // nanoseconds per each tick\n\nfunc initMonotonicTimer() {\n\tticksCount = 0\n\n\tinterrupt.New(avr.IRQ_TIMER0_OVF, func(i interrupt.Interrupt) {\n\t\t// use volatile\n\t\tticks := volatile.LoadUint64((*uint64)(unsafe.Pointer(&ticksCount)))\n\t\tticks += uint64(nanosecondsInTick)\n\t\tvolatile.StoreUint64((*uint64)(unsafe.Pointer(&ticksCount)), ticks)\n\t})\n\n\t// initial initialization of the Timer0\n\t// - Mask interrupt\n\tavr.TIMSK0.ClearBits(avr.TIMSK0_TOIE0 | avr.TIMSK0_OCIE0A | avr.TIMSK0_OCIE0B)\n\n\t// - Write new values to TCNT2, OCR2x, and TCCR2x.\n\tavr.TCNT0.Set(0)\n\tavr.OCR0A.Set(0xff)\n\t// - Set mode 3\n\tavr.TCCR0A.Set(avr.TCCR0A_WGM00 | avr.TCCR0A_WGM01)\n\t// - Set prescaler 1\n\tavr.TCCR0B.Set(avr.TCCR0B_CS00)\n\n\t// - Unmask interrupt\n\tavr.TIMSK0.SetBits(avr.TIMSK0_TOIE0)\n}\n\n//go:linkname adjustMonotonicTimer machine.adjustMonotonicTimer\nfunc adjustMonotonicTimer() {\n\t// adjust the nanosecondsInTick using volatile\n\tmask := interrupt.Disable()\n\tvolatile.StoreUint64((*uint64)(unsafe.Pointer(&nanosecondsInTick)), uint64(currentNanosecondsInTick()))\n\tinterrupt.Restore(mask)\n}\n\nfunc currentNanosecondsInTick() int64 {\n\t// this time depends on clk_IO, prescale, mode and OCR0A\n\t// assuming the clock source is CPU clock\n\tprescaler := int64(avr.TCCR0B.Get() & 0x7)\n\tclock := (int64(1e12) / prescaler) / int64(machine.CPUFrequency())\n\tmode := avr.TCCR0A.Get() & 0x7\n\n\t/*\n\t Mode WGM02 WGM01 WGM00 Timer/Counter       TOP  Update of  TOV Flag\n\t                        Mode of Operation        OCRx at    Set on\n\t 0    0     0     0     Normal              0xFF Immediate  MAX\n\t 1    0     0     1     PWM, Phase Correct  0xFF TOP        BOTTOM\n\t 2    0     1     0     CTC                 OCRA Immediate  MAX\n\t 3    0     1     1     Fast PWM            0xFF BOTTOM     MAX\n\t 5    1     0     1     PWM, Phase Correct  OCRA TOP        BOTTOM\n\t 7    1     1     1     Fast PWM            OCRA BOTTOM     TOP\n\t*/\n\tswitch mode {\n\tcase 0, 3:\n\t\t// normal & fast PWM\n\t\t// TOV0 Interrupt when moving from MAX (0xff) to 0x00\n\t\treturn clock * 256 / 1000\n\tcase 1:\n\t\t// Phase Correct PWM\n\t\t// TOV0 Interrupt when moving from MAX (0xff) to 0x00\n\t\treturn clock * 256 * 2 / 1000\n\tcase 2, 7:\n\t\t// CTC & fast PWM\n\t\t// TOV0 Interrupt when moving from MAX (OCRA) to 0x00\n\t\treturn clock * int64(avr.OCR0A.Get()) / 1000\n\tcase 5:\n\t\t// Phase Correct PWM\n\t\t// TOV0 Interrupt when moving from MAX (OCRA) to 0x00\n\t\treturn clock * int64(avr.OCR0A.Get()) * 2 / 1000\n\t}\n\n\treturn clock / 1000 // for unknown\n}\n"
  },
  {
    "path": "src/runtime/runtime_avrtiny.go",
    "content": "//go:build avrtiny\n\n// Runtime for the newer AVRs introduced since around 2016 that work quite\n// different from older AVRs like the atmega328p or even the attiny85.\n// Because of these large differences, a new runtime and machine implementation\n// is needed.\n// Some key differences:\n//   * Peripherals are now logically separated, instead of all mixed together as\n//     one big bag of registers. No PORTA/DDRA etc registers anymore, instead a\n//     real PORT peripheral type with multiple instances.\n//   * There is a real RTC now! No need for using one of the timers as a time\n//     source, which then conflicts with using it as a PWM.\n//   * Flash and RAM are now in the same address space! This avoids the need for\n//     PROGMEM which couldn't (easily) be supported in Go anyway. Constant\n//     globals just get stored in flash, like on Cortex-M chips.\n\npackage runtime\n\nimport (\n\t\"device/avr\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n)\n\n//export main\nfunc main() {\n\t// Initialize RTC.\n\tfor avr.RTC.STATUS.Get() != 0 {\n\t}\n\tavr.RTC.CTRLA.Set(avr.RTC_CTRLA_RTCEN | avr.RTC_CTRLA_RUNSTDBY)\n\tavr.RTC.INTCTRL.Set(avr.RTC_INTCTRL_OVF) // enable overflow interrupt\n\tinterrupt.New(avr.IRQ_RTC_CNT, rtcInterrupt)\n\n\t// Configure sleep:\n\t// - enable sleep mode\n\t// - set sleep mode to STANDBY (mode 0x1)\n\tavr.SLPCTRL.CTRLA.Set(avr.SLPCTRL_CTRLA_SEN | 0x1<<1)\n\n\t// Enable interrupts after initialization.\n\tavr.Asm(\"sei\")\n\n\trun()\n\texit(0)\n}\n\nfunc initUART() {\n\t// no UART configured\n}\n\nfunc putchar(b byte) {\n\t// no-op\n}\n\n// ticksToNanoseconds converts RTC ticks (at 32768Hz) to nanoseconds.\nfunc ticksToNanoseconds(ticks timeUnit) int64 {\n\t// The following calculation is actually the following, but with both sides\n\t// reduced to reduce the risk of overflow:\n\t//     ticks * 1e9 / 32768\n\treturn int64(ticks) * 1953125 / 64\n}\n\n// nanosecondsToTicks converts nanoseconds to RTC ticks (running at 32768Hz).\nfunc nanosecondsToTicks(ns int64) timeUnit {\n\t// The following calculation is actually the following, but with both sides\n\t// reduced to reduce the risk of overflow:\n\t//     ns * 32768 / 1e9\n\treturn timeUnit(ns * 64 / 1953125)\n}\n\n// Sleep for the given number of timer ticks.\nfunc sleepTicks(d timeUnit) {\n\tticksStart := ticks()\n\tsleepUntil := ticksStart + d\n\n\t// Sleep until we're in the right 2-second interval.\n\tfor {\n\t\tavr.Asm(\"cli\")\n\t\toverflows := rtcOverflows.Get()\n\t\tif overflows >= uint32(sleepUntil>>16) {\n\t\t\t// We're in the right 2-second interval.\n\t\t\t// At this point we know that the difference between ticks() and\n\t\t\t// sleepUntil is ≤0xffff.\n\t\t\tavr.Asm(\"sei\")\n\t\t\tbreak\n\t\t}\n\t\t// Sleep some more, because we're not there yet.\n\t\tavr.Asm(\"sei\\nsleep\")\n\t}\n\n\t// Now we know the sleep duration is small enough to fit in rtc.CNT.\n\n\t// Update rtc.CMP (atomically).\n\tcnt := uint16(sleepUntil)\n\tlow := uint8(cnt)\n\thigh := uint8(cnt >> 8)\n\tavr.RTC.CMPH.Set(high)\n\tavr.RTC.CMPL.Set(low)\n\n\t// Disable interrupts, so we can change interrupt settings without racing.\n\tavr.Asm(\"cli\")\n\n\t// Enable the CMP interrupt.\n\tavr.RTC.INTCTRL.Set(avr.RTC_INTCTRL_OVF | avr.RTC_INTCTRL_CMP)\n\n\t// Check whether we already reached CNT, in which case the interrupt may\n\t// have triggered already (but maybe not, it's a race condition).\n\tlow2 := avr.RTC.CNTL.Get()\n\thigh2 := avr.RTC.CNTH.Get()\n\tcnt2 := uint16(high2)<<8 | uint16(low2)\n\tif cnt2 < cnt {\n\t\t// We have not, so wait until the interrupt happens.\n\t\tfor {\n\t\t\t// Sleep until the next interrupt happens.\n\t\t\tavr.Asm(\"sei\\nsleep\\ncli\")\n\t\t\tif cmpMatch.Get() != 0 {\n\t\t\t\t// The CMP interrupt occurred, so we have slept long enough.\n\t\t\t\tcmpMatch.Set(0)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\t// Disable the CMP interrupt, and restore things like they were before.\n\tavr.RTC.INTCTRL.Set(avr.RTC_INTCTRL_OVF)\n\tavr.Asm(\"sei\")\n}\n\n// Number of RTC overflows, updated in the RTC interrupt handler.\n// The RTC is running at 32768Hz so an overflow happens every 2 seconds. A\n// 32-bit integer is large enough to run for about 279 years.\nvar rtcOverflows volatile.Register32\n\n// Set to one in the RTC CMP interrupt, to signal the expected number of ticks\n// have passed.\nvar cmpMatch volatile.Register8\n\n// Return the number of RTC ticks that happened since reset.\nfunc ticks() timeUnit {\n\tvar ovf uint32\n\tvar count uint16\n\tfor {\n\t\t// Get the tick count and overflow value, in a 4-step process to avoid a\n\t\t// race with the overflow interrupt.\n\t\tmask := interrupt.Disable()\n\n\t\t// 1. Get the overflow value.\n\t\tovf = rtcOverflows.Get()\n\n\t\t// 2. Read the RTC counter.\n\t\t// This way of reading is atomic (due to the TEMP register).\n\t\tlow := avr.RTC.CNTL.Get()\n\t\thigh := avr.RTC.CNTH.Get()\n\n\t\t// 3. Get the interrupt flags.\n\t\tintflags := avr.RTC.INTFLAGS.Get()\n\n\t\tinterrupt.Restore(mask)\n\n\t\t// 4. Check whether an overflow happened somewhere in the last three\n\t\t// steps. If so, just repeat the loop.\n\t\tif intflags&avr.RTC_INTFLAGS_OVF == 0 {\n\t\t\tcount = uint16(high)<<8 | uint16(low)\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// Create the 64-bit tick count, combining the two.\n\treturn timeUnit(ovf)<<16 | timeUnit(count)\n}\n\n// Interrupt handler for the RTC.\n// It happens every two seconds, and while sleeping using the CMP interrupt.\nfunc rtcInterrupt(interrupt.Interrupt) {\n\tflags := avr.RTC.INTFLAGS.Get()\n\tif flags&avr.RTC_INTFLAGS_OVF != 0 {\n\t\trtcOverflows.Set(rtcOverflows.Get() + 1)\n\t}\n\tif flags&avr.RTC_INTFLAGS_CMP != 0 {\n\t\tcmpMatch.Set(1)\n\t}\n\tavr.RTC.INTFLAGS.Set(flags) // clear interrupts\n}\n\nfunc exit(code int) {\n\tabort()\n}\n\n//export __vector_default\nfunc abort()\n"
  },
  {
    "path": "src/runtime/runtime_cortexm.go",
    "content": "//go:build cortexm\n\npackage runtime\n\nimport (\n\t\"unsafe\"\n)\n\n//go:extern _sbss\nvar _sbss [0]byte\n\n//go:extern _ebss\nvar _ebss [0]byte\n\n//go:extern _sdata\nvar _sdata [0]byte\n\n//go:extern _sidata\nvar _sidata [0]byte\n\n//go:extern _edata\nvar _edata [0]byte\n\nfunc preinit() {\n\t// Initialize .bss: zero-initialized global variables.\n\tptr := unsafe.Pointer(&_sbss)\n\tfor ptr != unsafe.Pointer(&_ebss) {\n\t\t*(*uint32)(ptr) = 0\n\t\tptr = unsafe.Add(ptr, 4)\n\t}\n\n\t// Initialize .data: global variables initialized from flash.\n\tsrc := unsafe.Pointer(&_sidata)\n\tdst := unsafe.Pointer(&_sdata)\n\tfor dst != unsafe.Pointer(&_edata) {\n\t\t*(*uint32)(dst) = *(*uint32)(src)\n\t\tdst = unsafe.Add(dst, 4)\n\t\tsrc = unsafe.Add(src, 4)\n\t}\n}\n\n// The stack layout at the moment an interrupt occurs.\n// Registers can be accessed if the stack pointer is cast to a pointer to this\n// struct.\ntype interruptStack struct {\n\tR0  uintptr\n\tR1  uintptr\n\tR2  uintptr\n\tR3  uintptr\n\tR12 uintptr\n\tLR  uintptr\n\tPC  uintptr\n\tPSR uintptr\n}\n"
  },
  {
    "path": "src/runtime/runtime_cortexm_abort.go",
    "content": "//go:build cortexm && !nxp && !qemu\n\npackage runtime\n\nimport (\n\t\"device/arm\"\n)\n\nfunc exit(code int) {\n\tabort()\n}\n\nfunc abort() {\n\t// lock up forever\n\tfor {\n\t\tarm.Asm(\"wfi\")\n\t}\n}\n"
  },
  {
    "path": "src/runtime/runtime_cortexm_hardfault.go",
    "content": "//go:build atsamd21 || nrf51\n\npackage runtime\n\n// This function is called at HardFault.\n//\n// For details, see:\n// https://community.arm.com/developer/ip-products/system/f/embedded-forum/3257/debugging-a-cortex-m0-hard-fault\n// https://blog.feabhas.com/2013/02/developing-a-generic-hard-fault-handler-for-arm-cortex-m3cortex-m4/\n//\n//export HardFault_Handler\nfunc HardFault_Handler() {\n\t// Obtain the stack pointer as it was on entry to the HardFault. It contains\n\t// the registers that were pushed by the NVIC and that we can now read back\n\t// to print the PC value at the time of the hard fault, for example.\n\tsp := (*interruptStack)(llvm_sponentry())\n\n\t// Note: by reusing the string \"panic: runtime error at \" we save a little\n\t// bit in terms of code size as the string can be deduplicated.\n\tprint(\"panic: runtime error at \", sp.PC, \": HardFault with sp=\", sp)\n\t// TODO: try to find the cause of the hard fault. Especially on Cortex-M3\n\t// and higher it is possible to find more detailed information in special\n\t// status registers.\n\tprintln()\n\tabort()\n}\n"
  },
  {
    "path": "src/runtime/runtime_cortexm_hardfault_debug.go",
    "content": "//go:build cortexm && !atsamd21 && !nrf51\n\npackage runtime\n\nimport (\n\t\"device/arm\"\n\t\"unsafe\"\n)\n\nconst (\n\tSCB_CFSR_KnownFault = arm.SCB_CFSR_IACCVIOL | arm.SCB_CFSR_DACCVIOL |\n\t\tarm.SCB_CFSR_MUNSTKERR | arm.SCB_CFSR_MSTKERR | arm.SCB_CFSR_MLSPERR |\n\t\tarm.SCB_CFSR_IBUSERR | arm.SCB_CFSR_PRECISERR | arm.SCB_CFSR_IMPRECISERR |\n\t\tarm.SCB_CFSR_UNSTKERR | arm.SCB_CFSR_STKERR | arm.SCB_CFSR_LSPERR |\n\t\tarm.SCB_CFSR_UNDEFINSTR | arm.SCB_CFSR_INVSTATE | arm.SCB_CFSR_INVPC |\n\t\tarm.SCB_CFSR_NOCP | arm.SCB_CFSR_UNALIGNED | arm.SCB_CFSR_DIVBYZERO\n)\n\n// See runtime_cortexm_hardfault.go\n//\n//export HardFault_Handler\nfunc HardFault_Handler() {\n\t// Obtain the stack pointer as it was on entry to the HardFault. It contains\n\t// the registers that were pushed by the NVIC and that we can now read back\n\t// to print the PC value at the time of the hard fault, for example.\n\tsp := (*interruptStack)(llvm_sponentry())\n\n\tfault := GetFaultStatus()\n\tspValid := !fault.Bus().ImpreciseDataBusError()\n\n\tprint(\"fatal error: \")\n\tif spValid && uintptr(unsafe.Pointer(sp)) < 0x20000000 {\n\t\tprint(\"stack overflow? \")\n\t}\n\tif fault.Mem().InstructionAccessViolation() {\n\t\tprint(\"instruction access violation\")\n\t}\n\tif fault.Mem().DataAccessViolation() {\n\t\tprint(\"data access violation\")\n\t}\n\tif fault.Mem().WhileUnstackingException() {\n\t\tprint(\" while unstacking exception\")\n\t}\n\tif fault.Mem().WileStackingException() {\n\t\tprint(\" while stacking exception\")\n\t}\n\tif fault.Mem().DuringFPLazyStatePres() {\n\t\tprint(\" during floating-point lazy state preservation\")\n\t}\n\n\tif fault.Bus().InstructionBusError() {\n\t\tprint(\"instruction bus error\")\n\t}\n\tif fault.Bus().PreciseDataBusError() {\n\t\tprint(\"data bus error (precise)\")\n\t}\n\tif fault.Bus().ImpreciseDataBusError() {\n\t\tprint(\"data bus error (imprecise)\")\n\t}\n\tif fault.Bus().WhileUnstackingException() {\n\t\tprint(\" while unstacking exception\")\n\t}\n\tif fault.Bus().WhileStackingException() {\n\t\tprint(\" while stacking exception\")\n\t}\n\tif fault.Bus().DuringFPLazyStatePres() {\n\t\tprint(\" during floating-point lazy state preservation\")\n\t}\n\n\tif fault.Usage().UndefinedInstruction() {\n\t\tprint(\"undefined instruction\")\n\t}\n\tif fault.Usage().IllegalUseOfEPSR() {\n\t\tprint(\"illegal use of the EPSR\")\n\t}\n\tif fault.Usage().IllegalExceptionReturn() {\n\t\tprint(\"illegal load of EXC_RETURN to the PC\")\n\t}\n\tif fault.Usage().AttemptedToAccessCoprocessor() {\n\t\tprint(\"coprocessor access violation\")\n\t}\n\tif fault.Usage().UnalignedMemoryAccess() {\n\t\tprint(\"unaligned memory access\")\n\t}\n\tif fault.Usage().DivideByZero() {\n\t\tprint(\"divide by zero\")\n\t}\n\n\tif fault.Unknown() {\n\t\tprint(\"unknown hard fault\")\n\t}\n\n\tif addr, ok := fault.Mem().Address(); ok {\n\t\tprint(\" with fault address \", addr)\n\t}\n\n\tif addr, ok := fault.Bus().Address(); ok {\n\t\tprint(\" with bus fault address \", addr)\n\t}\n\tif spValid {\n\t\tprint(\" with sp=\", sp)\n\t\tif uintptr(unsafe.Pointer(&sp.PC)) >= 0x20000000 {\n\t\t\t// Only print the PC if it points into memory.\n\t\t\t// It may not point into memory during a stack overflow, so check that\n\t\t\t// first before accessing the stack.\n\t\t\tprint(\" pc=\", sp.PC)\n\t\t}\n\t}\n\tprintln()\n\tabort()\n}\n\n// Descriptions are sourced from the K66 SVD and\n// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/Cihcfefj.html\n\n// GetFaultStatus reads the System Control Block Configurable Fault Status\n// Register and returns it as a FaultStatus.\nfunc GetFaultStatus() FaultStatus {\n\treturn FaultStatus(arm.SCB.CFSR.Get())\n}\n\ntype FaultStatus uint32\ntype MemFaultStatus uint32\ntype BusFaultStatus uint32\ntype UsageFaultStatus uint32\n\nfunc (fs FaultStatus) Mem() MemFaultStatus     { return MemFaultStatus(fs) }\nfunc (fs FaultStatus) Bus() BusFaultStatus     { return BusFaultStatus(fs) }\nfunc (fs FaultStatus) Usage() UsageFaultStatus { return UsageFaultStatus(fs) }\n\n// Unknown returns true if the cause of the fault is not know\nfunc (fs FaultStatus) Unknown() bool {\n\treturn fs&SCB_CFSR_KnownFault == 0\n}\n\n// InstructionAccessViolation: the processor attempted an instruction fetch from\n// a location that does not permit execution\n//\n// \"This fault occurs on any access to an XN region, even when the MPU is\n// disabled or not present.\n//\n// When this bit is 1, the PC value stacked for the exception return points to\n// the faulting instruction. The processor has not written a fault address to\n// the MMAR.\"\nfunc (fs MemFaultStatus) InstructionAccessViolation() bool {\n\treturn fs&arm.SCB_CFSR_IACCVIOL != 0\n}\n\n// DataAccessViolation: the processor attempted a load or store at a location\n// that does not permit the operation\n//\n// \"When this bit is 1, the PC value stacked for the exception return points to\n// the faulting instruction. The processor has loaded the MMAR with the address\n// of the attempted access.\"\nfunc (fs MemFaultStatus) DataAccessViolation() bool {\n\treturn fs&arm.SCB_CFSR_DACCVIOL != 0\n}\n\n// WhileUnstackingException: unstack for an exception return has caused one or\n// more access violations\n//\n// \"This fault is chained to the handler. This means that when this bit is 1,\n// the original return stack is still present. The processor has not adjusted\n// the SP from the failing return, and has not performed a new save. The\n// processor has not written a fault address to the MMAR.\"\nfunc (fs MemFaultStatus) WhileUnstackingException() bool {\n\treturn fs&arm.SCB_CFSR_MUNSTKERR != 0\n}\n\n// WileStackingException: stacking for an exception entry has caused one or more\n// access violations\n//\n// \"When this bit is 1, the SP is still adjusted but the values in the context\n// area on the stack might be incorrect. The processor has not written a fault\n// address to the MMAR.\"\nfunc (fs MemFaultStatus) WileStackingException() bool {\n\treturn fs&arm.SCB_CFSR_MSTKERR != 0\n}\n\n// DuringFPLazyStatePres: A MemManage fault occurred during floating-point lazy\n// state preservation\nfunc (fs MemFaultStatus) DuringFPLazyStatePres() bool {\n\treturn fs&arm.SCB_CFSR_MLSPERR != 0\n}\n\n// InstructionBusError: instruction bus error\n//\n// \"The processor detects the instruction bus error on prefetching an\n// instruction, but it sets the IBUSERR flag to 1 only if it attempts to issue\n// the faulting instruction.\n//\n// When the processor sets this bit is 1, it does not write a fault address to\n// the BFAR.\"\nfunc (fs BusFaultStatus) InstructionBusError() bool {\n\treturn fs&arm.SCB_CFSR_IBUSERR != 0\n}\n\n// PreciseDataBusError: a data bus error has occurred, and the PC value stacked\n// for the exception return points to the instruction that caused the fault\nfunc (fs BusFaultStatus) PreciseDataBusError() bool {\n\treturn fs&arm.SCB_CFSR_PRECISERR != 0\n}\n\n// ImpreciseDataBusError: a data bus error has occurred, but the return address\n// in the stack frame is not related to the instruction that caused the error\n//\n// \"When the processor sets this bit to 1, it does not write a fault address to\n// the BFAR.\n//\n// This is an asynchronous fault. Therefore, if it is detected when the priority\n// of the current process is higher than the BusFault priority, the BusFault\n// becomes pending and becomes active only when the processor returns from all\n// higher priority processes. If a precise fault occurs before the processor\n// enters the handler for the imprecise BusFault, the handler detects both\n// IMPRECISERR set to 1 and one of the precise fault status bits set to 1.\"\nfunc (fs BusFaultStatus) ImpreciseDataBusError() bool {\n\treturn fs&arm.SCB_CFSR_IMPRECISERR != 0\n}\n\n// WhileUnstackingException: unstack for an exception return has caused one or\n// more BusFaults\n//\n// \"This fault is chained to the handler. This means that when the processor\n// sets this bit to 1, the original return stack is still present. The processor\n// does not adjust the SP from the failing return, does not performed a new\n// save, and does not write a fault address to the BFAR.\"\nfunc (fs BusFaultStatus) WhileUnstackingException() bool {\n\treturn fs&arm.SCB_CFSR_UNSTKERR != 0\n}\n\n// WhileStackingException: stacking for an exception entry has caused one or\n// more BusFaults\n//\n// \"When the processor sets this bit to 1, the SP is still adjusted but the\n// values in the context area on the stack might be incorrect. The processor\n// does not write a fault address to the BFAR.\"\nfunc (fs BusFaultStatus) WhileStackingException() bool {\n\treturn fs&arm.SCB_CFSR_STKERR != 0\n}\n\n// DuringFPLazyStatePres: A bus fault occurred during floating-point lazy state\n// preservation\nfunc (fs BusFaultStatus) DuringFPLazyStatePres() bool {\n\treturn fs&arm.SCB_CFSR_LSPERR != 0\n}\n\n// UndefinedInstruction: the processor has attempted to execute an undefined\n// instruction\n//\n// \"When this bit is set to 1, the PC value stacked for the exception return\n// points to the undefined instruction.\n//\n// An undefined instruction is an instruction that the processor cannot decode.\"\nfunc (fs UsageFaultStatus) UndefinedInstruction() bool {\n\treturn fs&arm.SCB_CFSR_UNDEFINSTR != 0\n}\n\n// IllegalUseOfEPSR: the processor has attempted to execute an instruction that\n// makes illegal use of the EPSR\n//\n// \"When this bit is set to 1, the PC value stacked for the exception return\n// points to the instruction that attempted the illegal use of the EPSR.\n//\n// This bit is not set to 1 if an undefined instruction uses the EPSR.\"\nfunc (fs UsageFaultStatus) IllegalUseOfEPSR() bool {\n\treturn fs&arm.SCB_CFSR_INVSTATE != 0\n}\n\n// IllegalExceptionReturn: the processor has attempted an illegal load of\n// EXC_RETURN to the PC\n//\n// \"When this bit is set to 1, the PC value stacked for the exception return\n// points to the instruction that tried to perform the illegal load of the PC.\"\nfunc (fs UsageFaultStatus) IllegalExceptionReturn() bool {\n\treturn fs&arm.SCB_CFSR_INVPC != 0\n}\n\n// AttemptedToAccessCoprocessor: the processor has attempted to access a\n// coprocessor\nfunc (fs UsageFaultStatus) AttemptedToAccessCoprocessor() bool {\n\treturn fs&arm.SCB_CFSR_NOCP != 0\n}\n\n// UnalignedMemoryAccess: the processor has made an unaligned memory access\n//\n// \"Enable trapping of unaligned accesses by setting the UNALIGN_TRP bit in the\n// CCR to 1.\n//\n// Unaligned LDM, STM, LDRD, and STRD instructions always fault irrespective of\n// the setting of UNALIGN_TRP.\"\nfunc (fs UsageFaultStatus) UnalignedMemoryAccess() bool {\n\treturn fs&arm.SCB_CFSR_UNALIGNED != 0\n}\n\n// DivideByZero: the processor has executed an SDIV or UDIV instruction with a\n// divisor of 0\n//\n// \"When the processor sets this bit to 1, the PC value stacked for the\n// exception return points to the instruction that performed the divide by zero.\n//\n// Enable trapping of divide by zero by setting the DIV_0_TRP bit in the CCR to\n// 1.\"\nfunc (fs UsageFaultStatus) DivideByZero() bool {\n\treturn fs&arm.SCB_CFSR_DIVBYZERO != 0\n}\n\n// Address returns the MemManage Fault Address Register if the fault status\n// indicates the address is valid.\n//\n// \"If a MemManage fault occurs and is escalated to a HardFault because of\n// priority, the HardFault handler must set this bit to 0. This prevents\n// problems on return to a stacked active MemManage fault handler whose MMAR\n// value has been overwritten.\"\nfunc (fs MemFaultStatus) Address() (uintptr, bool) {\n\tif fs&arm.SCB_CFSR_MMARVALID == 0 {\n\t\treturn 0, false\n\t} else {\n\t\treturn uintptr(arm.SCB.MMFAR.Get()), true\n\t}\n}\n\n// Address returns the BusFault Address Register if the fault status\n// indicates the address is valid.\n//\n// \"The processor sets this bit to 1 after a BusFault where the address is\n// known. Other faults can set this bit to 0, such as a MemManage fault\n// occurring later.\n//\n// If a BusFault occurs and is escalated to a hard fault because of priority,\n// the hard fault handler must set this bit to 0. This prevents problems if\n// returning to a stacked active BusFault handler whose BFAR value has been\n// overwritten.\"\"\nfunc (fs BusFaultStatus) Address() (uintptr, bool) {\n\tif fs&arm.SCB_CFSR_BFARVALID == 0 {\n\t\treturn 0, false\n\t} else {\n\t\treturn uintptr(arm.SCB.BFAR.Get()), true\n\t}\n}\n"
  },
  {
    "path": "src/runtime/runtime_cortexm_qemu.go",
    "content": "//go:build cortexm && qemu\n\npackage runtime\n\n// This file implements the Stellaris LM3S6965 Cortex-M3 chip as implemented by\n// QEMU.\n\nimport (\n\t\"device/arm\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nvar timestamp timeUnit\n\n//export Reset_Handler\nfunc main() {\n\tpreinit()\n\trun()\n\n\t// Signal successful exit.\n\texit(0)\n}\n\nfunc ticksToNanoseconds(ticks timeUnit) int64 {\n\treturn int64(ticks)\n}\n\nfunc nanosecondsToTicks(ns int64) timeUnit {\n\treturn timeUnit(ns)\n}\n\nfunc sleepTicks(d timeUnit) {\n\t// TODO: actually sleep here for the given time.\n\ttimestamp += d\n}\n\nfunc ticks() timeUnit {\n\treturn timestamp\n}\n\n// UART0 output register.\nvar stdoutWrite = (*volatile.Register8)(unsafe.Pointer(uintptr(0x4000c000)))\n\nfunc putchar(c byte) {\n\tstdoutWrite.Set(uint8(c))\n}\n\nfunc getchar() byte {\n\t// dummy, TODO\n\treturn 0\n}\n\nfunc buffered() int {\n\t// dummy, TODO\n\treturn 0\n}\n\nfunc waitForEvents() {\n\tarm.Asm(\"wfe\")\n}\n\nfunc abort() {\n\texit(1)\n}\n\nfunc exit(code int) {\n\t// Exit QEMU.\n\tif code == 0 {\n\t\tarm.SemihostingCall(arm.SemihostingReportException, arm.SemihostingApplicationExit)\n\t} else {\n\t\tarm.SemihostingCall(arm.SemihostingReportException, arm.SemihostingRunTimeErrorUnknown)\n\t}\n\n\t// Lock up forever (should be unreachable).\n\tfor {\n\t\tarm.Asm(\"wfi\")\n\t}\n}\n"
  },
  {
    "path": "src/runtime/runtime_esp32.go",
    "content": "//go:build esp32\n\npackage runtime\n\nimport (\n\t\"device\"\n\t\"device/esp\"\n\t\"machine\"\n)\n\n// This is the function called on startup right after the stack pointer has been\n// set.\n//\n//export main\nfunc main() {\n\t// Disable the protection on the watchdog timer (needed when started from\n\t// the bootloader).\n\tesp.RTC_CNTL.WDTWPROTECT.Set(0x050D83AA1)\n\n\t// Disable both watchdog timers that are enabled by default on startup.\n\t// Note that these watchdogs can be protected, but the ROM bootloader\n\t// doesn't seem to protect them.\n\tesp.RTC_CNTL.WDTCONFIG0.Set(0)\n\tesp.TIMG0.WDTCONFIG0.Set(0)\n\n\t// Switch SoC clock source to PLL (instead of the default which is XTAL).\n\t// This switches the CPU (and APB) clock from 40MHz to 80MHz.\n\t// Options:\n\t//   RTC_CNTL_CLK_CONF_SOC_CLK_SEL:       PLL (1)       (default XTAL)\n\t//   RTC_CNTL_CLK_CONF_CK8M_DIV_SEL:      2             (default)\n\t//   RTC_CNTL_CLK_CONF_DIG_CLK8M_D256_EN: Enable        (default)\n\t//   RTC_CNTL_CLK_CONF_CK8M_DIV:          divide by 256 (default)\n\t// The only real change made here is modifying RTC_CNTL_CLK_CONF_SOC_CLK_SEL,\n\t// but setting a fixed value produces smaller code.\n\tesp.RTC_CNTL.CLK_CONF.Set((1 << esp.RTC_CNTL_CLK_CONF_SOC_CLK_SEL_Pos) |\n\t\t(2 << esp.RTC_CNTL_CLK_CONF_CK8M_DIV_SEL_Pos) |\n\t\t(1 << esp.RTC_CNTL_CLK_CONF_DIG_CLK8M_D256_EN_Pos) |\n\t\t(1 << esp.RTC_CNTL_CLK_CONF_CK8M_DIV_Pos))\n\n\t// Switch CPU from 80MHz to 160MHz. This doesn't affect the APB clock,\n\t// which is still running at 80MHz.\n\tesp.DPORT.CPU_PER_CONF.Set(1) // PLL_CLK / 2, see table 3-3 in the reference manual\n\n\t// Clear .bss section. .data has already been loaded by the ROM bootloader.\n\t// Do this after increasing the CPU clock to possibly make startup slightly\n\t// faster.\n\tclearbss()\n\n\t// Initialize UART.\n\tmachine.InitSerial()\n\n\t// Initialize main system timer used for time.Now.\n\tinitTimer()\n\n\t// Initialize the heap, call main.main, etc.\n\trun()\n\n\t// Fallback: if main ever returns, hang the CPU.\n\texit(0)\n}\n\n//go:extern _sbss\nvar _sbss [0]byte\n\n//go:extern _ebss\nvar _ebss [0]byte\n\nfunc abort() {\n\tfor {\n\t\tdevice.Asm(\"waiti 0\")\n\t}\n}\n"
  },
  {
    "path": "src/runtime/runtime_esp32c3.go",
    "content": "//go:build esp32c3\n\npackage runtime\n\nimport (\n\t\"device/esp\"\n\t\"device/riscv\"\n\t\"machine\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\n// This is the function called on startup after the flash (IROM/DROM) is\n// initialized and the stack pointer has been set.\n//\n//export main\nfunc main() {\n\t// This initialization configures the following things:\n\t// * It disables all watchdog timers. They might be useful at some point in\n\t//   the future, but will need integration into the scheduler. For now,\n\t//   they're all disabled.\n\t// * It sets the CPU frequency to 160MHz, which is the maximum speed allowed\n\t//   for this CPU. Lower frequencies might be possible in the future, but\n\t//   running fast and sleeping quickly is often also a good strategy to save\n\t//   power.\n\t// TODO: protect certain memory regions, especially the area below the stack\n\t// to protect against stack overflows. See\n\t// esp_cpu_configure_region_protection in ESP-IDF.\n\n\t// Disable Timer 0 watchdog.\n\tesp.TIMG0.WDTCONFIG0.Set(0)\n\n\t// Disable RTC watchdog.\n\tesp.RTC_CNTL.WDTWPROTECT.Set(0x50D83AA1)\n\tesp.RTC_CNTL.WDTCONFIG0.Set(0)\n\n\t// Disable super watchdog.\n\tesp.RTC_CNTL.SWD_WPROTECT.Set(0x8F1D312A)\n\tesp.RTC_CNTL.SWD_CONF.Set(esp.RTC_CNTL_SWD_CONF_SWD_DISABLE)\n\n\t// Change CPU frequency from 20MHz to 80MHz, by switching from the XTAL to\n\t// the PLL clock source (see table \"CPU Clock Frequency\" in the reference\n\t// manual).\n\tesp.SYSTEM.SYSCLK_CONF.Set(1 << esp.SYSTEM_SYSCLK_CONF_SOC_CLK_SEL_Pos)\n\n\t// Change CPU frequency from 80MHz to 160MHz by setting SYSTEM_CPUPERIOD_SEL\n\t// to 1 (see table \"CPU Clock Frequency\" in the reference manual).\n\t// Note: we might not want to set SYSTEM_CPU_WAIT_MODE_FORCE_ON to save\n\t// power. It is set here to keep the default on reset.\n\tesp.SYSTEM.CPU_PER_CONF.Set(esp.SYSTEM_CPU_PER_CONF_CPU_WAIT_MODE_FORCE_ON | esp.SYSTEM_CPU_PER_CONF_PLL_FREQ_SEL | 1<<esp.SYSTEM_CPU_PER_CONF_CPUPERIOD_SEL_Pos)\n\n\tclearbss()\n\n\t// Configure interrupt handler\n\tinterruptInit()\n\n\t// Initialize UART.\n\tmachine.USBCDC.Configure(machine.UARTConfig{})\n\tmachine.InitSerial()\n\n\t// Initialize main system timer used for time.Now.\n\tinitTimer()\n\n\t// Initialize the heap, call main.main, etc.\n\trun()\n\n\t// Fallback: if main ever returns, hang the CPU.\n\texit(0)\n}\n\nfunc abort() {\n\t// lock up forever\n\tfor {\n\t\triscv.Asm(\"wfi\")\n\t}\n}\n\n// interruptInit initialize the interrupt controller and called from runtime once.\nfunc interruptInit() {\n\tmie := riscv.DisableInterrupts()\n\n\t// Reset all interrupt source priorities to zero.\n\tpriReg := &esp.INTERRUPT_CORE0.CPU_INT_PRI_1\n\tfor i := 0; i < 31; i++ {\n\t\tpriReg.Set(0)\n\t\tpriReg = (*volatile.Register32)(unsafe.Add(unsafe.Pointer(priReg), 4))\n\t}\n\n\t// default threshold for interrupts is 5\n\tesp.INTERRUPT_CORE0.CPU_INT_THRESH.Set(5)\n\n\t// Set the interrupt address.\n\t// Set MODE field to 1 - a vector base address (only supported by ESP32C3)\n\t// Note that this address must be aligned to 256 bytes.\n\triscv.MTVEC.Set((uintptr(unsafe.Pointer(&_vector_table))) | 1)\n\n\triscv.EnableInterrupts(mie)\n}\n\n//go:extern _vector_table\nvar _vector_table [0]uintptr\n"
  },
  {
    "path": "src/runtime/runtime_esp32s3.go",
    "content": "//go:build esp32s3\n\npackage runtime\n\nimport (\n\t\"device/esp\"\n)\n\n// This is the function called on startup after the flash (IROM/DROM) is\n// initialized and the stack pointer has been set.\n//\n//export main\nfunc main() {\n\t// This initialization configures the following things:\n\t// * It disables all watchdog timers. They might be useful at some point in\n\t//   the future, but will need integration into the scheduler. For now,\n\t//   they're all disabled.\n\t// * It sets the CPU frequency to 240MHz, which is the maximum speed allowed\n\t//   for this CPU. Lower frequencies might be possible in the future, but\n\t//   running fast and sleeping quickly is often also a good strategy to save\n\t//   power.\n\t// TODO: protect certain memory regions, especially the area below the stack\n\t// to protect against stack overflows. See\n\t// esp_cpu_configure_region_protection in ESP-IDF.\n\n\t// Disable RTC watchdog.\n\tesp.RTC_CNTL.WDTWPROTECT.Set(0x50D83AA1)\n\tesp.RTC_CNTL.WDTCONFIG0.Set(0)\n\tesp.RTC_CNTL.WDTWPROTECT.Set(0x0) // Re-enable write protect\n\n\t// Disable Timer 0 watchdog.\n\tesp.TIMG1.WDTWPROTECT.Set(0x50D83AA1) // write protect\n\tesp.TIMG1.WDTCONFIG0.Set(0)           // disable TG0 WDT\n\tesp.TIMG1.WDTWPROTECT.Set(0x0)        // Re-enable write protect\n\n\tesp.TIMG0.WDTWPROTECT.Set(0x50D83AA1) // write protect\n\tesp.TIMG0.WDTCONFIG0.Set(0)           // disable TG0 WDT\n\tesp.TIMG0.WDTWPROTECT.Set(0x0)        // Re-enable write protect\n\n\t// Disable super watchdog.\n\tesp.RTC_CNTL.SWD_WPROTECT.Set(0x8F1D312A)\n\tesp.RTC_CNTL.SWD_CONF.Set(esp.RTC_CNTL_SWD_CONF_SWD_DISABLE)\n\tesp.RTC_CNTL.SWD_WPROTECT.Set(0x0) // Re-enable write protect\n\n\t// Change CPU frequency from 20MHz to 80MHz, by switching from the XTAL to the\n\t// PLL clock source (see table \"CPU Clock Frequency\" in the reference manual).\n\tesp.SYSTEM.SetSYSCLK_CONF_SOC_CLK_SEL(1)\n\n\t// Change CPU frequency from 80MHz to 240MHz by setting SYSTEM_PLL_FREQ_SEL to\n\t// 1 and SYSTEM_CPUPERIOD_SEL to 2 (see table \"CPU Clock Frequency\" in the\n\t// reference manual).\n\tesp.SYSTEM.SetCPU_PER_CONF_PLL_FREQ_SEL(1)\n\tesp.SYSTEM.SetCPU_PER_CONF_CPUPERIOD_SEL(2)\n\n\t// Clear bss. Repeat many times while we wait for cpu/clock to stabilize\n\tfor x := 0; x < 30; x++ {\n\t\tclearbss()\n\t}\n\n\t// Initialize main system timer used for time.Now.\n\tinitTimer()\n\n\t// Initialize the heap, call main.main, etc.\n\trun()\n\n\t// Fallback: if main ever returns, hang the CPU.\n\texit(0)\n}\n\nfunc abort() {\n\t// lock up forever\n\tprint(\"abort called\\n\")\n}\n\n//go:extern _vector_table\nvar _vector_table [0]uintptr\n\n//go:extern _sbss\nvar _sbss [0]byte\n\n//go:extern _ebss\nvar _ebss [0]byte\n"
  },
  {
    "path": "src/runtime/runtime_esp32sx.go",
    "content": "//go:build esp32s3\n\npackage runtime\n\nimport (\n\t\"device/esp\"\n\t\"machine\"\n\t\"unsafe\"\n)\n\n//type timeUnit int64\n\nfunc putchar(c byte) {\n\tmachine.Serial.WriteByte(c)\n}\n\nfunc getchar() byte {\n\tfor machine.Serial.Buffered() == 0 {\n\t\tGosched()\n\t}\n\tv, _ := machine.Serial.ReadByte()\n\treturn v\n}\n\nfunc buffered() int {\n\treturn machine.Serial.Buffered()\n}\n\n// Initialize .bss: zero-initialized global variables.\n// The .data section has already been loaded by the ROM bootloader.\nfunc clearbss() {\n\tptr := unsafe.Pointer(&_sbss)\n\tfor ptr != unsafe.Pointer(&_ebss) {\n\t\t*(*uint32)(ptr) = 0\n\t\tptr = unsafe.Add(ptr, 4)\n\t}\n}\n\nfunc initTimer() {\n\t// Configure timer 0 in timer group 0, for timekeeping.\n\t//   EN:       Enable the timer.\n\t//   INCREASE: Count up every tick (as opposed to counting down).\n\t//   DIVIDER:  16-bit prescaler, set to 2 for dividing the APB clock by two\n\t//             (40MHz).\n\t// esp.TIMG0.T0CONFIG.Set(0 << esp.TIMG_T0CONFIG_T0_EN_Pos)\n\tesp.TIMG0.T0CONFIG.Set(esp.TIMG_TCONFIG_EN | esp.TIMG_TCONFIG_INCREASE | 2<<esp.TIMG_TCONFIG_DIVIDER_Pos)\n\t// esp.TIMG0.T0CONFIG.Set(1 << esp.TIMG_T0CONFIG_T0_DIVCNT_RST_Pos)\n\t// esp.TIMG0.T0CONFIG.Set(esp.TIMG_T0CONFIG_T0_EN)\n\n\t// Set the timer counter value to 0.\n\tesp.TIMG0.T0LOADLO.Set(0)\n\tesp.TIMG0.T0LOADHI.Set(0)\n\tesp.TIMG0.T0LOAD.Set(0) // value doesn't matter.\n}\n\nfunc ticks() timeUnit {\n\t// First, update the LO and HI register pair by writing any value to the\n\t// register. This allows reading the pair atomically.\n\tesp.TIMG0.T0UPDATE.Set(0)\n\t// Then read the two 32-bit parts of the timer.\n\treturn timeUnit(uint64(esp.TIMG0.T0LO.Get()) | uint64(esp.TIMG0.T0HI.Get())<<32)\n}\n\nfunc nanosecondsToTicks(ns int64) timeUnit {\n\t// Calculate the number of ticks from the number of nanoseconds. At a 80MHz\n\t// APB clock, that's 25 nanoseconds per tick with a timer prescaler of 2:\n\t// 25 = 1e9 / (80MHz / 2)\n\treturn timeUnit(ns / 25)\n}\n\nfunc ticksToNanoseconds(ticks timeUnit) int64 {\n\t// See nanosecondsToTicks.\n\treturn int64(ticks) * 25\n}\n\n// sleepTicks busy-waits until the given number of ticks have passed.\nfunc sleepTicks(d timeUnit) {\n\tsleepUntil := ticks() + d\n\tfor ticks() < sleepUntil {\n\t\t// TODO: suspend the CPU to not burn power here unnecessarily.\n\t}\n}\n\nfunc exit(code int) {\n\tabort()\n}\n"
  },
  {
    "path": "src/runtime/runtime_esp32xx.go",
    "content": "//go:build esp32 || esp32c3\n\npackage runtime\n\nimport (\n\t\"device/esp\"\n\t\"machine\"\n\t\"unsafe\"\n)\n\n// Initialize .bss: zero-initialized global variables.\n// The .data section has already been loaded by the ROM bootloader.\nfunc clearbss() {\n\tptr := unsafe.Pointer(&_sbss)\n\tfor ptr != unsafe.Pointer(&_ebss) {\n\t\t*(*uint32)(ptr) = 0\n\t\tptr = unsafe.Add(ptr, 4)\n\t}\n}\n\nfunc initTimer() {\n\t// Configure timer 0 in timer group 0, for timekeeping.\n\t//   EN:       Enable the timer.\n\t//   INCREASE: Count up every tick (as opposed to counting down).\n\t//   DIVIDER:  16-bit prescaler, set to 2 for dividing the APB clock by two\n\t//             (40MHz).\n\t// esp.TIMG0.T0CONFIG.Set(0 << esp.TIMG_T0CONFIG_T0_EN_Pos)\n\tesp.TIMG0.T0CONFIG.Set(esp.TIMG_T0CONFIG_EN | esp.TIMG_T0CONFIG_INCREASE | 2<<esp.TIMG_T0CONFIG_DIVIDER_Pos)\n\t// esp.TIMG0.T0CONFIG.Set(1 << esp.TIMG_T0CONFIG_T0_DIVCNT_RST_Pos)\n\t// esp.TIMG0.T0CONFIG.Set(esp.TIMG_T0CONFIG_T0_EN)\n\n\t// Set the timer counter value to 0.\n\tesp.TIMG0.T0LOADLO.Set(0)\n\tesp.TIMG0.T0LOADHI.Set(0)\n\tesp.TIMG0.T0LOAD.Set(0) // value doesn't matter.\n}\n\nfunc ticks() timeUnit {\n\t// First, update the LO and HI register pair by writing any value to the\n\t// register. This allows reading the pair atomically.\n\tesp.TIMG0.T0UPDATE.Set(0)\n\t// Then read the two 32-bit parts of the timer.\n\treturn timeUnit(uint64(esp.TIMG0.T0LO.Get()) | uint64(esp.TIMG0.T0HI.Get())<<32)\n}\n\nfunc nanosecondsToTicks(ns int64) timeUnit {\n\t// Calculate the number of ticks from the number of nanoseconds. At a 80MHz\n\t// APB clock, that's 25 nanoseconds per tick with a timer prescaler of 2:\n\t// 25 = 1e9 / (80MHz / 2)\n\treturn timeUnit(ns / 25)\n}\n\nfunc ticksToNanoseconds(ticks timeUnit) int64 {\n\t// See nanosecondsToTicks.\n\treturn int64(ticks) * 25\n}\n\n// sleepTicks busy-waits until the given number of ticks have passed.\nfunc sleepTicks(d timeUnit) {\n\tsleepUntil := ticks() + d\n\tfor ticks() < sleepUntil {\n\t\t// TODO: suspend the CPU to not burn power here unnecessarily.\n\t}\n}\n\nfunc exit(code int) {\n\tabort()\n}\n\nfunc putchar(c byte) {\n\tmachine.Serial.WriteByte(c)\n}\n\nfunc getchar() byte {\n\tfor machine.Serial.Buffered() == 0 {\n\t\tGosched()\n\t}\n\tv, _ := machine.Serial.ReadByte()\n\treturn v\n}\n\nfunc buffered() int {\n\treturn machine.Serial.Buffered()\n}\n"
  },
  {
    "path": "src/runtime/runtime_esp8266.go",
    "content": "//go:build esp8266\n\npackage runtime\n\nimport (\n\t\"device\"\n\t\"device/esp\"\n\t\"machine\"\n\t\"unsafe\"\n)\n\nvar currentTime timeUnit = 0\n\nfunc putchar(c byte) {\n\tmachine.Serial.WriteByte(c)\n}\n\nfunc getchar() byte {\n\tfor machine.Serial.Buffered() == 0 {\n\t\tGosched()\n\t}\n\tv, _ := machine.Serial.ReadByte()\n\treturn v\n}\n\nfunc buffered() int {\n\treturn machine.Serial.Buffered()\n}\n\n// Write to the internal control bus (using I2C?).\n// Signature found here:\n// https://github.com/espressif/ESP8266_RTOS_SDK/blob/14171de0/components/esp8266/include/esp8266/rom_functions.h#L54\n//\n//export rom_i2c_writeReg\nfunc rom_i2c_writeReg(block, host_id, reg_add, data uint8)\n\n//export main\nfunc main() {\n\t// Clear .bss section. .data has already been loaded by the ROM bootloader.\n\tpreinit()\n\n\t// Initialize PLL.\n\t// I'm not quite sure what this magic incantation means, but it does set the\n\t// esp8266 to the right clock speed. Without this, it is running too slow.\n\trom_i2c_writeReg(103, 4, 1, 136)\n\trom_i2c_writeReg(103, 4, 2, 145)\n\n\t// Initialize UART.\n\tmachine.InitSerial()\n\n\t// Initialize timer. Bits:\n\t//  ENABLE:   timer enable\n\t//  ROLLOVER: automatically reload when hitting 0\n\t//  PRESCALE: divide by 256\n\tesp.TIMER.FRC1_CTRL.Set(\n\t\tesp.TIMER_FRC1_CTRL_TIMER_ENABLE | esp.TIMER_FRC1_CTRL_ROLLOVER | esp.TIMER_FRC1_CTRL_PRESCALE_DIVIDER_DEVIDED_BY_256<<esp.TIMER_FRC1_CTRL_PRESCALE_DIVIDER_Pos)\n\tesp.TIMER.FRC1_LOAD.Set(0x3fffff)  // set all 22 bits to 1\n\tesp.TIMER.FRC1_COUNT.Set(0x3fffff) // set all 22 bits to 1\n\n\trun()\n\n\t// Fallback: if main ever returns, hang the CPU.\n\texit(0)\n}\n\n//go:extern _sbss\nvar _sbss [0]byte\n\n//go:extern _ebss\nvar _ebss [0]byte\n\nfunc preinit() {\n\t// Initialize .bss: zero-initialized global variables.\n\tptr := unsafe.Pointer(&_sbss)\n\tfor ptr != unsafe.Pointer(&_ebss) {\n\t\t*(*uint32)(ptr) = 0\n\t\tptr = unsafe.Add(ptr, 4)\n\t}\n}\n\nfunc ticks() timeUnit {\n\t// Get the counter value of the timer. It is 22 bits and starts with all\n\t// ones (0x3fffff). To make it easier to work with, let it count upwards.\n\tcount := 0x3fffff - esp.TIMER.FRC1_COUNT.Get()\n\n\t// Replace the lowest 22 bits of the current time with the counter.\n\tnewTime := (currentTime &^ 0x3fffff) | timeUnit(count)\n\n\t// If there was an overflow, the new time will be lower than the current\n\t// time, so will need to add (1<<22).\n\tif newTime < currentTime {\n\t\tnewTime += 0x400000\n\t}\n\n\t// Update the timestamp for the next call to ticks().\n\tcurrentTime = newTime\n\n\treturn currentTime\n}\n\nconst tickNanos = 3200 // time.Second / (80MHz / 256)\n\nfunc ticksToNanoseconds(ticks timeUnit) int64 {\n\treturn int64(ticks) * tickNanos\n}\n\nfunc nanosecondsToTicks(ns int64) timeUnit {\n\treturn timeUnit(ns / tickNanos)\n}\n\n// sleepTicks busy-waits until the given number of ticks have passed.\nfunc sleepTicks(d timeUnit) {\n\tsleepUntil := ticks() + d\n\tfor ticks() < sleepUntil {\n\t}\n}\n\nfunc exit(code int) {\n\tabort()\n}\n\nfunc abort() {\n\tfor {\n\t\tdevice.Asm(\"waiti 0\")\n\t}\n}\n"
  },
  {
    "path": "src/runtime/runtime_fe310.go",
    "content": "//go:build fe310\n\n// This file implements target-specific things for the FE310 chip as used in the\n// HiFive1.\n\npackage runtime\n\nimport (\n\t\"machine\"\n\t\"unsafe\"\n\n\t\"device/riscv\"\n\t\"device/sifive\"\n\t\"runtime/volatile\"\n)\n\n//export main\nfunc main() {\n\t// Zero the PLIC enable bits on startup: they are not zeroed at reset.\n\tsifive.PLIC.ENABLE[0].Set(0)\n\tsifive.PLIC.ENABLE[1].Set(0)\n\n\t// Zero the threshold value to allow all priorities of interrupts.\n\tsifive.PLIC.THRESHOLD.Set(0)\n\n\t// Zero MCAUSE, which is set to the reset reason on reset. It must be zeroed\n\t// to make interrupt.In() work.\n\t// This would also be a good time to save the reset reason, but that hasn't\n\t// been implemented yet.\n\triscv.MCAUSE.Set(0)\n\n\t// Set the interrupt address.\n\t// Note that this address must be aligned specially, otherwise the MODE bits\n\t// of MTVEC won't be zero.\n\triscv.MTVEC.Set(uintptr(unsafe.Pointer(&handleInterruptASM)))\n\n\t// Reset the MIE register and enable external interrupts.\n\t// It must be reset here because it not zeroed at startup.\n\triscv.MIE.Set(riscv.MIE_MEIE)\n\n\t// Enable global interrupts now that they've been set up.\n\triscv.MSTATUS.SetBits(riscv.MSTATUS_MIE) // MIE: machine external interrupts\n\n\tpreinit()\n\tinitPeripherals()\n\trun()\n\texit(0)\n}\n\n//go:extern handleInterruptASM\nvar handleInterruptASM [0]uintptr\n\n//export handleInterrupt\nfunc handleInterrupt() {\n\tcause := riscv.MCAUSE.Get()\n\tcode := uint(cause &^ (1 << 31))\n\tif cause&(1<<31) != 0 {\n\t\t// Topmost bit is set, which means that it is an interrupt.\n\t\tswitch code {\n\t\tcase riscv.MachineTimerInterrupt:\n\t\t\t// Signal timeout.\n\t\t\ttimerWakeup.Set(1)\n\t\t\t// Disable the timer, to avoid triggering the interrupt right after\n\t\t\t// this interrupt returns.\n\t\t\triscv.MIE.ClearBits(riscv.MIE_MTIE)\n\t\tcase riscv.MachineExternalInterrupt:\n\t\t\t// Claim this interrupt.\n\t\t\tid := sifive.PLIC.CLAIM.Get()\n\t\t\t// Call the interrupt handler, if any is registered for this ID.\n\t\t\tsifive.HandleInterrupt(int(id))\n\t\t\t// Complete this interrupt.\n\t\t\tsifive.PLIC.CLAIM.Set(id)\n\t\t}\n\t} else {\n\t\t// Topmost bit is clear, so it is an exception of some sort.\n\t\t// We could implement support for unsupported instructions here (such as\n\t\t// misaligned loads). However, for now we'll just print a fatal error.\n\t\thandleException(code)\n\t}\n\n\t// Zero MCAUSE so that it can later be used to see whether we're in an\n\t// interrupt or not.\n\triscv.MCAUSE.Set(0)\n}\n\n// initPeripherals configures peripherals the way the runtime expects them.\nfunc initPeripherals() {\n\t// Configure PLL to output 320MHz.\n\t//   R=2:  divide 16MHz to 8MHz\n\t//   F=80: multiply 8MHz by 80 to get 640MHz (80/2-1=39)\n\t//   Q=2:  divide 640MHz by 2 to get 320MHz\n\t// This makes the main CPU run at 320MHz.\n\tsifive.PRCI.PLLCFG.Set(sifive.PRCI_PLLCFG_PLLR_R2<<sifive.PRCI_PLLCFG_PLLR_Pos | 39<<sifive.PRCI_PLLCFG_PLLF_Pos | sifive.PRCI_PLLCFG_PLLQ_Q2<<sifive.PRCI_PLLCFG_PLLQ_Pos | sifive.PRCI_PLLCFG_SEL | sifive.PRCI_PLLCFG_REFSEL)\n\n\t// Turn off HFROSC to save power\n\tsifive.PRCI.HFROSCCFG.ClearBits(sifive.PRCI_HFROSCCFG_ENABLE)\n\n\t// Enable the RTC.\n\tsifive.RTC.RTCCFG.Set(sifive.RTC_RTCCFG_ENALWAYS)\n\n\t// Configure the UART.\n\tmachine.InitSerial()\n}\n\nfunc putchar(c byte) {\n\tmachine.Serial.WriteByte(c)\n}\n\nfunc getchar() byte {\n\tfor machine.Serial.Buffered() == 0 {\n\t\tGosched()\n\t}\n\tv, _ := machine.Serial.ReadByte()\n\treturn v\n}\n\nfunc buffered() int {\n\treturn machine.Serial.Buffered()\n}\n\nvar timerWakeup volatile.Register8\n\nfunc ticks() timeUnit {\n\t// Combining the low bits and the high bits yields a time span of over 270\n\t// years without counter rollover.\n\thighBits := sifive.CLINT.MTIMEH.Get()\n\tfor {\n\t\tlowBits := sifive.CLINT.MTIME.Get()\n\t\tnewHighBits := sifive.CLINT.MTIMEH.Get()\n\t\tif newHighBits == highBits {\n\t\t\t// High bits stayed the same.\n\t\t\treturn timeUnit(lowBits) | (timeUnit(highBits) << 32)\n\t\t}\n\t\t// Retry, because there was a rollover in the low bits (happening every\n\t\t// 1.5 days).\n\t\thighBits = newHighBits\n\t}\n}\n\nfunc sleepTicks(d timeUnit) {\n\ttarget := uint64(ticks() + d)\n\tsifive.CLINT.MTIMECMPH.Set(uint32(target >> 32))\n\tsifive.CLINT.MTIMECMP.Set(uint32(target))\n\triscv.MIE.SetBits(riscv.MIE_MTIE)\n\tfor {\n\t\tif timerWakeup.Get() != 0 {\n\t\t\ttimerWakeup.Set(0)\n\t\t\t// Disable timer.\n\t\t\tbreak\n\t\t}\n\t\triscv.Asm(\"wfi\")\n\t}\n}\n\n// handleException is called from the interrupt handler for any exception.\n// Exceptions can be things like illegal instructions, invalid memory\n// read/write, and similar issues.\nfunc handleException(code uint) {\n\t// For a list of exception codes, see:\n\t// https://content.riscv.org/wp-content/uploads/2019/08/riscv-privileged-20190608-1.pdf#page=49\n\tprint(\"fatal error: exception with mcause=\")\n\tprint(code)\n\tprint(\" pc=\")\n\tprint(riscv.MEPC.Get())\n\tprintln()\n\tabort()\n}\n"
  },
  {
    "path": "src/runtime/runtime_fe310_baremetal.go",
    "content": "//go:build fe310 && !qemu\n\npackage runtime\n\nimport (\n\t\"device/riscv\"\n)\n\n// ticksToNanoseconds converts RTC ticks (at 32768Hz) to nanoseconds.\nfunc ticksToNanoseconds(ticks timeUnit) int64 {\n\t// The following calculation is actually the following, but with both sides\n\t// reduced to reduce the risk of overflow:\n\t//     ticks * 1e9 / 32768\n\treturn int64(ticks) * 1953125 / 64\n}\n\n// nanosecondsToTicks converts nanoseconds to RTC ticks (running at 32768Hz).\nfunc nanosecondsToTicks(ns int64) timeUnit {\n\t// The following calculation is actually the following, but with both sides\n\t// reduced to reduce the risk of overflow:\n\t//     ns * 32768 / 1e9\n\treturn timeUnit(ns * 64 / 1953125)\n}\n\nfunc exit(code int) {\n\tabort()\n}\n\nfunc abort() {\n\t// lock up forever\n\tfor {\n\t\triscv.Asm(\"wfi\")\n\t}\n}\n"
  },
  {
    "path": "src/runtime/runtime_fe310_qemu.go",
    "content": "//go:build fe310 && qemu\n\npackage runtime\n\nimport (\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\n// Special memory-mapped device to exit tests, created by SiFive.\nvar testExit = (*volatile.Register32)(unsafe.Pointer(uintptr(0x100000)))\n\n// ticksToNanoseconds converts CLINT ticks (at 100ns per tick) to nanoseconds.\nfunc ticksToNanoseconds(ticks timeUnit) int64 {\n\treturn int64(ticks) * 100\n}\n\n// nanosecondsToTicks converts nanoseconds to CLINT ticks (at 100ns per tick).\nfunc nanosecondsToTicks(ns int64) timeUnit {\n\treturn timeUnit(ns / 100)\n}\n\nfunc abort() {\n\texit(1)\n}\n\nfunc exit(code int) {\n\tif code == 0 {\n\t\t// Signal a successful exit.\n\t\ttestExit.Set(0x5555) // FINISHER_PASS\n\t} else {\n\t\t// Signal a failure. The exit code is stored in the upper 16 bits of the\n\t\t// 32 bit value.\n\t\ttestExit.Set(uint32(code)<<16 | 0x3333) // FINISHER_FAIL\n\t}\n}\n"
  },
  {
    "path": "src/runtime/runtime_k210.go",
    "content": "//go:build k210\n\n// This file implements target-specific things for the K210 chip as used in the\n// MAix Bit with Mic.\n\npackage runtime\n\nimport (\n\t\"device/kendryte\"\n\t\"device/riscv\"\n\t\"machine\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\n//export main\nfunc main() {\n\n\t// Both harts should disable all interrupts on startup.\n\tinitPLIC()\n\n\t// Only use one hart for the moment.\n\tif riscv.MHARTID.Get() != 0 {\n\t\tabort()\n\t}\n\n\t// Reset all interrupt source priorities to zero.\n\tfor i := 0; i < kendryte.IRQ_max; i++ {\n\t\tkendryte.PLIC.PRIORITY[i].Set(0)\n\t}\n\n\t// Zero MCAUSE, which is set to the reset reason on reset. It must be zeroed\n\t// to make interrupt.In() work.\n\t// This would also be a good time to save the reset reason, but that hasn't\n\t// been implemented yet.\n\triscv.MCAUSE.Set(0)\n\n\t// Set the interrupt address.\n\t// Note that this address must be aligned specially, otherwise the MODE bits\n\t// of MTVEC won't be zero.\n\triscv.MTVEC.Set(uintptr(unsafe.Pointer(&handleInterruptASM)))\n\n\t// Reset the MIE register and enable external interrupts.\n\t// It must be reset here because it not zeroed at startup.\n\triscv.MIE.Set(riscv.MIE_MEIE) // MEIE is for machine external interrupts\n\n\t// Enable global interrupts now that they've been set up.\n\triscv.MSTATUS.SetBits(riscv.MSTATUS_MIE)\n\n\tpreinit()\n\tinitPeripherals()\n\trun()\n\texit(0)\n}\n\nfunc initPLIC() {\n\thartId := riscv.MHARTID.Get()\n\n\t// Zero the PLIC enable bits at startup.\n\tfor i := 0; i < ((kendryte.IRQ_max + 32) / 32); i++ {\n\t\tkendryte.PLIC.TARGET_ENABLES[hartId].ENABLE[i].Set(0)\n\t}\n\n\t// Zero the PLIC threshold bits to allow all interrupts.\n\tkendryte.PLIC.TARGETS[hartId].THRESHOLD.Set(0)\n}\n\n//go:extern handleInterruptASM\nvar handleInterruptASM [0]uintptr\n\n//export handleInterrupt\nfunc handleInterrupt() {\n\tcause := riscv.MCAUSE.Get()\n\tcode := uint64(cause &^ (1 << 63))\n\tif cause&(1<<63) != 0 {\n\t\t// Topmost bit is set, which means that it is an interrupt.\n\t\tswitch code {\n\t\tcase riscv.MachineTimerInterrupt:\n\t\t\t// Signal timeout.\n\t\t\ttimerWakeup.Set(1)\n\t\t\t// Disable the timer, to avoid triggering the interrupt right after\n\t\t\t// this interrupt returns.\n\t\t\triscv.MIE.ClearBits(riscv.MIE_MTIE)\n\t\tcase riscv.MachineExternalInterrupt:\n\t\t\thartId := riscv.MHARTID.Get()\n\n\t\t\t// Claim this interrupt.\n\t\t\tid := kendryte.PLIC.TARGETS[hartId].CLAIM.Get()\n\t\t\t// Call the interrupt handler, if any is registered for this ID.\n\t\t\tkendryte.HandleInterrupt(int(id))\n\t\t\t// Complete this interrupt.\n\t\t\tkendryte.PLIC.TARGETS[hartId].CLAIM.Set(id)\n\t\t}\n\t} else {\n\t\t// Topmost bit is clear, so it is an exception of some sort.\n\t\t// We could implement support for unsupported instructions here (such as\n\t\t// misaligned loads). However, for now we'll just print a fatal error.\n\t\thandleException(code)\n\t}\n\n\t// Zero MCAUSE so that it can later be used to see whether we're in an\n\t// interrupt or not.\n\triscv.MCAUSE.Set(0)\n}\n\n// initPeripherals configures peripherals the way the runtime expects them.\nfunc initPeripherals() {\n\t// Enable APB0 clock.\n\tkendryte.SYSCTL.CLK_EN_CENT.SetBits(kendryte.SYSCTL_CLK_EN_CENT_APB0_CLK_EN)\n\n\t// Enable FPIOA peripheral.\n\tkendryte.SYSCTL.CLK_EN_PERI.SetBits(kendryte.SYSCTL_CLK_EN_PERI_FPIOA_CLK_EN)\n\n\tmachine.InitSerial()\n}\n\nfunc putchar(c byte) {\n\tmachine.Serial.WriteByte(c)\n}\n\nfunc getchar() byte {\n\tfor machine.Serial.Buffered() == 0 {\n\t\tGosched()\n\t}\n\tv, _ := machine.Serial.ReadByte()\n\treturn v\n}\n\nfunc buffered() int {\n\treturn machine.Serial.Buffered()\n}\n\nvar timerWakeup volatile.Register8\n\nfunc ticks() timeUnit {\n\thighBits := uint32(kendryte.CLINT.MTIME.Get() >> 32)\n\tfor {\n\t\tlowBits := uint32(kendryte.CLINT.MTIME.Get() & 0xffffffff)\n\t\tnewHighBits := uint32(kendryte.CLINT.MTIME.Get() >> 32)\n\t\tif newHighBits == highBits {\n\t\t\treturn timeUnit(lowBits) | (timeUnit(highBits) << 32)\n\t\t}\n\t\thighBits = newHighBits\n\t}\n}\n\nfunc sleepTicks(d timeUnit) {\n\ttarget := uint64(ticks() + d)\n\tkendryte.CLINT.MTIMECMP[0].Set(target)\n\triscv.MIE.SetBits(riscv.MIE_MTIE)\n\tfor {\n\t\tif timerWakeup.Get() != 0 {\n\t\t\ttimerWakeup.Set(0)\n\t\t\t// Disable timer.\n\t\t\tbreak\n\t\t}\n\t\triscv.Asm(\"wfi\")\n\t}\n}\n\n// handleException is called from the interrupt handler for any exception.\n// Exceptions can be things like illegal instructions, invalid memory\n// read/write, and similar issues.\nfunc handleException(code uint64) {\n\t// For a list of exception codes, see:\n\t// https://content.riscv.org/wp-content/uploads/2019/08/riscv-privileged-20190608-1.pdf#page=49\n\tprint(\"fatal error: exception with mcause=\")\n\tprint(code)\n\tprint(\" pc=\")\n\tprint(riscv.MEPC.Get())\n\tprintln()\n\tabort()\n}\n"
  },
  {
    "path": "src/runtime/runtime_k210_baremetal.go",
    "content": "//go:build k210 && !qemu\n\npackage runtime\n\nimport (\n\t\"device/riscv\"\n)\n\n// ticksToNanoseconds converts CPU ticks to nanoseconds.\nfunc ticksToNanoseconds(ticks timeUnit) int64 {\n\t// The following calculation is actually the following, but with both sides\n\t// reduced to reduce the risk of overflow:\n\t//     ticks * 1e9 / (390000000 / 50)\n\t// 50 is the CLINT divider and 390000000 is the CPU frequency.\n\treturn int64(ticks) * 5000 / 39\n}\n\n// nanosecondsToTicks converts nanoseconds to CPU ticks.\nfunc nanosecondsToTicks(ns int64) timeUnit {\n\treturn timeUnit(ns * 39 / 5000)\n}\n\nfunc exit(code int) {\n\tabort()\n}\n\nfunc abort() {\n\t// lock up forever\n\tfor {\n\t\triscv.Asm(\"wfi\")\n\t}\n}\n"
  },
  {
    "path": "src/runtime/runtime_mimxrt1062.go",
    "content": "//go:build mimxrt1062\n\npackage runtime\n\nimport (\n\t\"device/arm\"\n\t\"device/nxp\"\n\t\"machine\"\n\t\"math/bits\"\n\t\"unsafe\"\n)\n\n//go:extern _svectors\nvar _svectors [0]byte\n\n//go:extern _flexram_cfg\nvar _flexram_cfg [0]byte\n\n//export Reset_Handler\nfunc main() {\n\n\t// disable interrupts\n\tirq := arm.DisableInterrupts()\n\n\t// initialize FPU and VTOR, reset watchdogs\n\tinitSystem()\n\n\t// configure core and peripheral clocks/PLLs/PFDs\n\tinitClocks()\n\n\t// copy data/bss sections from flash to RAM\n\tpreinit()\n\n\t// initialize cache and MPU\n\tinitCache()\n\n\t// enable SysTick, GPIO, and peripherals\n\tinitPeripherals()\n\n\t// reenable interrupts\n\tarm.EnableInterrupts(irq)\n\n\trun()\n\texit(0)\n}\n\nfunc getRamSizeConfig(itcmKB, dtcmKB uint32) uint32 {\n\tconst minKB, disabled = uint32(4), uint32(0)\n\tif itcmKB < minKB {\n\t\titcmKB = disabled\n\t}\n\tif dtcmKB < minKB {\n\t\tdtcmKB = disabled\n\t}\n\titcmKB = uint32(bits.Len(uint(itcmKB))) << nxp.IOMUXC_GPR_GPR14_CM7_CFGITCMSZ_Pos\n\tdtcmKB = uint32(bits.Len(uint(dtcmKB))) << nxp.IOMUXC_GPR_GPR14_CM7_CFGDTCMSZ_Pos\n\treturn (itcmKB & nxp.IOMUXC_GPR_GPR14_CM7_CFGITCMSZ_Msk) |\n\t\t(dtcmKB & nxp.IOMUXC_GPR_GPR14_CM7_CFGDTCMSZ_Msk)\n}\n\nfunc initSystem() {\n\n\t// configure SRAM capacity (512K for both ITCM and DTCM)\n\tramc := uintptr(unsafe.Pointer(&_flexram_cfg))\n\tnxp.IOMUXC_GPR.GPR17.Set(uint32(ramc))\n\tnxp.IOMUXC_GPR.GPR16.Set(0x00200007)\n\tnxp.IOMUXC_GPR.GPR14.Set(getRamSizeConfig(512, 512))\n\n\t// from Teensyduino\n\tnxp.PMU.MISC0_SET.Set(nxp.PMU_MISC0_REFTOP_SELFBIASOFF)\n\n\t// install vector table (TODO: initialize interrupt/exception table?)\n\tvtor := uintptr(unsafe.Pointer(&_svectors))\n\tnxp.SystemControl.VTOR.Set(uint32(vtor))\n\n\tconst wdogUpdateKey = 0xD928C520\n\n\t// disable watchdog powerdown counter\n\tnxp.WDOG1.WMCR.ClearBits(nxp.WDOG_WMCR_PDE_Msk)\n\tnxp.WDOG2.WMCR.ClearBits(nxp.WDOG_WMCR_PDE_Msk)\n\n\t// disable watchdog\n\tif nxp.WDOG1.WCR.HasBits(nxp.WDOG_WCR_WDE_Msk) {\n\t\tnxp.WDOG1.WCR.ClearBits(nxp.WDOG_WCR_WDE_Msk)\n\t}\n\tif nxp.WDOG2.WCR.HasBits(nxp.WDOG_WCR_WDE_Msk) {\n\t\tnxp.WDOG2.WCR.ClearBits(nxp.WDOG_WCR_WDE_Msk)\n\t}\n\tif nxp.RTWDOG.CS.HasBits(nxp.RTWDOG_CS_CMD32EN_Msk) {\n\t\tnxp.RTWDOG.CNT.Set(wdogUpdateKey)\n\t} else {\n\t\tnxp.RTWDOG.CNT.Set((wdogUpdateKey >> 0) & 0xFFFF)\n\t\tnxp.RTWDOG.CNT.Set((wdogUpdateKey >> 16) & 0xFFFF)\n\t}\n\tnxp.RTWDOG.TOVAL.Set(0xFFFF)\n\tnxp.RTWDOG.CS.Set((nxp.RTWDOG.CS.Get() & ^uint32(nxp.RTWDOG_CS_EN_Msk)) | nxp.RTWDOG_CS_UPDATE_Msk)\n}\n\nfunc initPeripherals() {\n\n\tenableTimerClocks() // activate GPT/PIT clock gates\n\tinitSysTick()       // enable SysTick\n\tinitRTC()           // enable real-time clock\n\n\tenablePinClocks() // activate IOMUXC(_GPR)/GPIO clock gates\n\tinitPins()        // configure GPIO\n\n\tenablePeripheralClocks() // activate peripheral clock gates\n\tinitUART()               // configure UART (initialized first for debugging)\n}\n\nfunc initPins() {\n\t// use fast GPIO for all pins (GPIO6-9)\n\tnxp.IOMUXC_GPR.GPR26.Set(0xFFFFFFFF)\n\tnxp.IOMUXC_GPR.GPR27.Set(0xFFFFFFFF)\n\tnxp.IOMUXC_GPR.GPR28.Set(0xFFFFFFFF)\n\tnxp.IOMUXC_GPR.GPR29.Set(0xFFFFFFFF)\n}\n\nfunc initUART() {\n\tmachine.InitSerial()\n}\n\nfunc putchar(c byte) {\n\tmachine.Serial.WriteByte(c)\n}\n\nfunc getchar() byte {\n\tfor machine.UART1.Buffered() == 0 {\n\t\tGosched()\n\t}\n\tv, _ := machine.UART1.ReadByte()\n\treturn v\n}\n\nfunc buffered() int {\n\treturn machine.UART1.Buffered()\n}\n\nfunc exit(code int) {\n\tabort()\n}\n\nfunc abort() {\n\tfor {\n\t\tarm.Asm(\"wfe\")\n\t}\n}\n\nfunc waitForEvents() {\n\tarm.Asm(\"wfe\")\n}\n"
  },
  {
    "path": "src/runtime/runtime_mimxrt1062_clock.go",
    "content": "//go:build mimxrt1062\n\npackage runtime\n\nimport (\n\t\"device/nxp\"\n)\n\n// Core clock frequencies (Hz)\nconst (\n\tCORE_FREQ = 600000000 // 600 MHz\n\tOSC_FREQ  = 24000000  //  24 MHz\n)\n\n// Note from Teensyduino (cores/teensy4/startup.c):\n//\n// |  ARM SysTick is used for most Arduino timing functions, delay(), millis(),\n// |  micros().  SysTick can run from either the ARM core clock, or from an\n// |  \"external\" clock.  NXP documents it as \"24 MHz XTALOSC can be the external\n// |  clock source of SYSTICK\" (RT1052 ref manual, rev 1, page 411).  However,\n// |  NXP actually hid an undocumented divide-by-240 circuit in the hardware, so\n// |  the external clock is really 100 kHz.  We use this clock rather than the\n// |  ARM clock, to allow SysTick to maintain correct timing even when we change\n// |  the ARM clock to run at different speeds.\nconst SYSTICK_FREQ = 100000 // 100 kHz\n\nvar (\n\tArmPllConfig = nxp.ClockConfigArmPll{\n\t\tLoopDivider: 100, // PLL loop divider, Fout=Fin*50\n\t\tSrc:         0,   // bypass clock source, 0=OSC24M, 1=CLK1_P & CLK1_N\n\t}\n\tSysPllConfig = nxp.ClockConfigSysPll{\n\t\tLoopDivider: 1, // PLL loop divider, Fout=Fin*(20+LOOP*2+NUMER/DENOM)\n\t\tNumerator:   0, // 30-bit NUMER of fractional loop divider\n\t\tDenominator: 1, // 30-bit DENOM of fractional loop divider\n\t\tSrc:         0, // bypass clock source, 0=OSC24M, 1=CLK1_P & CLK1_N\n\t}\n\tUsb1PllConfig = nxp.ClockConfigUsbPll{\n\t\tInstance:    1, // USB PLL instance\n\t\tLoopDivider: 0, // PLL loop divider, Fout=Fin*20\n\t\tSrc:         0, // bypass clock source, 0=OSC24M, 1=CLK1_P & CLK1_N\n\t}\n\tUsb2PllConfig = nxp.ClockConfigUsbPll{\n\t\tInstance:    2, // USB PLL instance\n\t\tLoopDivider: 0, // PLL loop divider, Fout=Fin*20\n\t\tSrc:         0, // bypass clock source, 0=OSC24M, 1=CLK1_P & CLK1_N\n\t}\n)\n\n// initClocks configures the core, buses, and all peripherals' clock source mux\n// and dividers for runtime. The clock gates for individual peripherals are all\n// disabled prior to configuration and must be enabled afterwards using one of\n// these `enable*Clocks()` functions or the respective peripheral clocks'\n// `Enable()` method from the \"device/nxp\" package.\nfunc initClocks() {\n\t// disable low-power mode so that __WFI doesn't lock up at runtime.\n\t// see: Using the MIMXRT1060/4-EVK with MCUXpresso IDE v10.3.x (v1.0.2,\n\t// 2019MAR01), chapter 14\n\tnxp.ClockModeRun.Set()\n\n\t// enable and use 1MHz clock output\n\tnxp.XTALOSC24M.OSC_CONFIG2.SetBits(nxp.XTALOSC24M_OSC_CONFIG2_ENABLE_1M_Msk)\n\tnxp.XTALOSC24M.OSC_CONFIG2.ClearBits(nxp.XTALOSC24M_OSC_CONFIG2_MUX_1M_Msk)\n\n\t// initialize external 24 MHz clock\n\tnxp.CCM_ANALOG.MISC0_CLR.Set(nxp.CCM_ANALOG_MISC0_XTAL_24M_PWD_Msk) // power\n\tfor !nxp.XTALOSC24M.LOWPWR_CTRL.HasBits(nxp.XTALOSC24M_LOWPWR_CTRL_XTALOSC_PWRUP_STAT_Msk) {\n\t}\n\tnxp.CCM_ANALOG.MISC0_SET.Set(nxp.CCM_ANALOG_MISC0_OSC_XTALOK_EN_Msk) // detect freq\n\tfor !nxp.CCM_ANALOG.MISC0.HasBits(nxp.CCM_ANALOG_MISC0_OSC_XTALOK_Msk) {\n\t}\n\tnxp.CCM_ANALOG.MISC0_CLR.Set(nxp.CCM_ANALOG_MISC0_OSC_XTALOK_EN_Msk)\n\n\t// initialize internal RC OSC 24 MHz, and switch clock source to external OSC\n\tnxp.XTALOSC24M.LOWPWR_CTRL.SetBits(nxp.XTALOSC24M_LOWPWR_CTRL_RC_OSC_EN_Msk)\n\tnxp.XTALOSC24M.LOWPWR_CTRL_CLR.Set(nxp.XTALOSC24M_LOWPWR_CTRL_CLR_OSC_SEL_Msk)\n\n\t// set oscillator ready counter value\n\tnxp.CCM.CCR.Set((nxp.CCM.CCR.Get() & ^uint32(nxp.CCM_CCR_OSCNT_Msk)) |\n\t\t((127 << nxp.CCM_CCR_OSCNT_Pos) & nxp.CCM_CCR_OSCNT_Msk))\n\n\t// set PERIPH2_CLK and PERIPH to provide stable clock before PLLs initialed\n\tnxp.MuxIpPeriphClk2.Mux(1) // PERIPH_CLK2 select OSC24M\n\tnxp.MuxIpPeriph.Mux(1)     // PERIPH select PERIPH_CLK2\n\n\t// set VDD_SOC to 1.275V, necessary to config AHB to 600 MHz\n\tnxp.DCDC.REG3.Set((nxp.DCDC.REG3.Get() & ^uint32(nxp.DCDC_REG3_TRG_Msk)) |\n\t\t((13 << nxp.DCDC_REG3_TRG_Pos) & nxp.DCDC_REG3_TRG_Msk))\n\n\t// wait until DCDC_STS_DC_OK bit is asserted\n\tfor !nxp.DCDC.REG0.HasBits(nxp.DCDC_REG0_STS_DC_OK_Msk) {\n\t}\n\n\tnxp.DivIpAhb.Div(0) // divide AHB_PODF (DIV1)\n\n\tnxp.ClockIpAdc1.Enable(false) // disable ADC\n\tnxp.ClockIpAdc2.Enable(false) //\n\n\tnxp.ClockIpXbar1.Enable(false) //  disable XBAR\n\tnxp.ClockIpXbar2.Enable(false) //\n\tnxp.ClockIpXbar3.Enable(false) //\n\n\tnxp.DivIpIpg.Div(3)        // divide IPG_PODF (DIV4)\n\tnxp.DivIpArm.Div(1)        // divide ARM_PODF (DIV2)\n\tnxp.DivIpPeriphClk2.Div(0) // divide PERIPH_CLK2_PODF (DIV1)\n\n\tnxp.ClockIpGpt1.Enable(false)  // disable GPT/PIT\n\tnxp.ClockIpGpt1S.Enable(false) //\n\tnxp.ClockIpGpt2.Enable(false)  //\n\tnxp.ClockIpGpt2S.Enable(false) //\n\tnxp.ClockIpPit.Enable(false)   //\n\n\tnxp.DivIpPerclk.Div(0) // divide PERCLK_PODF (DIV1)\n\n\tnxp.ClockIpUsdhc1.Enable(false) // disable USDHC1\n\tnxp.DivIpUsdhc1.Div(1)          // divide USDHC1_PODF (DIV2)\n\tnxp.MuxIpUsdhc1.Mux(1)          // USDHC1 select PLL2_PFD0\n\tnxp.ClockIpUsdhc2.Enable(false) // disable USDHC2\n\tnxp.DivIpUsdhc2.Div(1)          // divide USDHC2_PODF (DIV2)\n\tnxp.MuxIpUsdhc2.Mux(1)          // USDHC2 select PLL2_PFD0\n\n\tnxp.ClockIpSemc.Enable(false) // disable SEMC\n\tnxp.DivIpSemc.Div(1)          // divide SEMC_PODF (DIV2)\n\tnxp.MuxIpSemcAlt.Mux(0)       // SEMC_ALT select PLL2_PFD2\n\tnxp.MuxIpSemc.Mux(1)          // SEMC select SEMC_ALT\n\n\tif false {\n\t\t// TODO: external flash is on this bus, configured via DCD block\n\t\tnxp.ClockIpFlexSpi.Enable(false) // disable FLEXSPI\n\t\tnxp.DivIpFlexSpi.Div(0)          // divide FLEXSPI_PODF (DIV1)\n\t\tnxp.MuxIpFlexSpi.Mux(2)          // FLEXSPI select PLL2_PFD2\n\t}\n\tnxp.ClockIpFlexSpi2.Enable(false) // disable FLEXSPI2\n\tnxp.DivIpFlexSpi2.Div(0)          // divide FLEXSPI2_PODF (DIV1)\n\tnxp.MuxIpFlexSpi2.Mux(0)          // FLEXSPI2 select PLL2_PFD2\n\n\tnxp.ClockIpCsi.Enable(false) // disable CSI\n\tnxp.DivIpCsi.Div(1)          // divide CSI_PODF (DIV2)\n\tnxp.MuxIpCsi.Mux(0)          // CSI select OSC24M\n\n\tnxp.ClockIpLpspi1.Enable(false) // disable LPSPI\n\tnxp.ClockIpLpspi2.Enable(false) //\n\tnxp.ClockIpLpspi3.Enable(false) //\n\tnxp.ClockIpLpspi4.Enable(false) //\n\tnxp.DivIpLpspi.Div(3)           // divide LPSPI_PODF (DIV4)\n\tnxp.MuxIpLpspi.Mux(2)           // LPSPI select PLL2\n\n\tnxp.ClockIpTrace.Enable(false) // disable TRACE\n\tnxp.DivIpTrace.Div(3)          // divide TRACE_PODF (DIV4)\n\tnxp.MuxIpTrace.Mux(0)          // TRACE select PLL2_MAIN\n\n\tnxp.ClockIpSai1.Enable(false) // disable SAI1\n\tnxp.DivIpSai1Pre.Div(3)       // divide SAI1_CLK_PRED (DIV4)\n\tnxp.DivIpSai1.Div(1)          // divide SAI1_CLK_PODF (DIV2)\n\tnxp.MuxIpSai1.Mux(0)          // SAI1 select PLL3_PFD2\n\tnxp.ClockIpSai2.Enable(false) // disable SAI2\n\tnxp.DivIpSai2Pre.Div(3)       // divide SAI2_CLK_PRED (DIV4)\n\tnxp.DivIpSai2.Div(1)          // divide SAI2_CLK_PODF (DIV2)\n\tnxp.MuxIpSai2.Mux(0)          // SAI2 select PLL3_PFD2\n\tnxp.ClockIpSai3.Enable(false) // disable SAI3\n\tnxp.DivIpSai3Pre.Div(3)       // divide SAI3_CLK_PRED (DIV4)\n\tnxp.DivIpSai3.Div(1)          // divide SAI3_CLK_PODF (DIV2)\n\tnxp.MuxIpSai3.Mux(0)          // SAI3 select PLL3_PFD2\n\n\tnxp.ClockIpLpi2c1.Enable(false) // disable LPI2C\n\tnxp.ClockIpLpi2c2.Enable(false) //\n\tnxp.ClockIpLpi2c3.Enable(false) //\n\tnxp.ClockIpLpi2c4.Enable(false) //\n\tnxp.DivIpLpi2c.Div(0)           // divide LPI2C_CLK_PODF (DIV1)\n\tnxp.MuxIpLpi2c.Mux(1)           // LPI2C select OSC\n\n\tnxp.ClockIpCan1.Enable(false)  // disable CAN\n\tnxp.ClockIpCan2.Enable(false)  //\n\tnxp.ClockIpCan3.Enable(false)  //\n\tnxp.ClockIpCan1S.Enable(false) //\n\tnxp.ClockIpCan2S.Enable(false) //\n\tnxp.ClockIpCan3S.Enable(false) //\n\tnxp.DivIpCan.Div(1)            // divide CAN_CLK_PODF (DIV2)\n\tnxp.MuxIpCan.Mux(2)            // CAN select PLL3_SW_80M\n\n\tnxp.ClockIpLpuart1.Enable(false) // disable UART\n\tnxp.ClockIpLpuart2.Enable(false) //\n\tnxp.ClockIpLpuart3.Enable(false) //\n\tnxp.ClockIpLpuart4.Enable(false) //\n\tnxp.ClockIpLpuart5.Enable(false) //\n\tnxp.ClockIpLpuart6.Enable(false) //\n\tnxp.ClockIpLpuart7.Enable(false) //\n\tnxp.ClockIpLpuart8.Enable(false) //\n\tnxp.DivIpUart.Div(0)             // divide UART_CLK_PODF (DIV1)\n\tnxp.MuxIpUart.Mux(1)             // UART select OSC\n\n\tnxp.ClockIpLcdPixel.Enable(false) // disable LCDIF\n\tnxp.DivIpLcdifPre.Div(1)          // divide LCDIF_PRED (DIV2)\n\tnxp.DivIpLcdif.Div(3)             // divide LCDIF_CLK_PODF (DIV4)\n\tnxp.MuxIpLcdifPre.Mux(5)          // LCDIF_PRE select PLL3_PFD1\n\n\tnxp.ClockIpSpdif.Enable(false) // disable SPDIF\n\tnxp.DivIpSpdif0Pre.Div(1)      // divide SPDIF0_CLK_PRED (DIV2)\n\tnxp.DivIpSpdif0.Div(7)         // divide SPDIF0_CLK_PODF (DIV8)\n\tnxp.MuxIpSpdif.Mux(3)          // SPDIF select PLL3_SW\n\n\tnxp.ClockIpFlexio1.Enable(false) // disable FLEXIO1\n\tnxp.DivIpFlexio1Pre.Div(1)       // divide FLEXIO1_CLK_PRED (DIV2)\n\tnxp.DivIpFlexio1.Div(7)          // divide FLEXIO1_CLK_PODF (DIV8)\n\tnxp.MuxIpFlexio1.Mux(3)          // FLEXIO1 select PLL3_SW\n\tnxp.ClockIpFlexio2.Enable(false) // disable FLEXIO2\n\tnxp.DivIpFlexio2Pre.Div(1)       // divide FLEXIO2_CLK_PRED (DIV2)\n\tnxp.DivIpFlexio2.Div(7)          // divide FLEXIO2_CLK_PODF (DIV8)\n\tnxp.MuxIpFlexio2.Mux(3)          // FLEXIO2 select PLL3_SW\n\n\tnxp.MuxIpPll3Sw.Mux(0) // PLL3_SW select PLL3_MAIN\n\n\tArmPllConfig.Configure() // init ARM PLL\n\t// SYS PLL (PLL2) @ 528 MHz\n\t//   PFD0 = 396    MHz -> USDHC1/USDHC2(DIV2)=198 MHz\n\t//   PFD1 = 594    MHz -> (currently unused)\n\t//   PFD2 = 327.72 MHz -> SEMC(DIV2)=163.86 MHz, FlexSPI/FlexSPI2=327.72 MHz\n\t//   PFD3 = 454.73 MHz -> (currently unused)\n\tSysPllConfig.Configure(24, 16, 29, 16) // init SYS PLL and PFDs\n\n\t// USB1 PLL (PLL3) @ 480 MHz\n\t//   PFD0 -> (currently unused)\n\t//   PFD1 -> (currently unused)\n\t//   PFD2 -> (currently unused)\n\t//   PFD3 -> (currently unused)\n\tUsb1PllConfig.Configure() // init USB1 PLL and PFDs\n\tUsb2PllConfig.Configure() // init USB2 PLL\n\n\tnxp.MuxIpPrePeriph.Mux(3)  // PRE_PERIPH select ARM_PLL\n\tnxp.MuxIpPeriph.Mux(0)     // PERIPH select PRE_PERIPH\n\tnxp.MuxIpPeriphClk2.Mux(1) // PERIPH_CLK2 select OSC\n\tnxp.MuxIpPerclk.Mux(1)     // PERCLK select OSC\n\n\t// set LVDS1 clock source\n\tnxp.CCM_ANALOG.MISC1.Set((nxp.CCM_ANALOG.MISC1.Get() & ^uint32(nxp.CCM_ANALOG_MISC1_LVDS1_CLK_SEL_Msk)) |\n\t\t((0 << nxp.CCM_ANALOG_MISC1_LVDS1_CLK_SEL_Pos) & nxp.CCM_ANALOG_MISC1_LVDS1_CLK_SEL_Msk))\n\n\t// set CLOCK_OUT1 divider\n\tnxp.CCM.CCOSR.Set((nxp.CCM.CCOSR.Get() & ^uint32(nxp.CCM_CCOSR_CLKO1_DIV_Msk)) |\n\t\t((0 << nxp.CCM_CCOSR_CLKO1_DIV_Pos) & nxp.CCM_CCOSR_CLKO1_DIV_Msk))\n\t// set CLOCK_OUT1 source\n\tnxp.CCM.CCOSR.Set((nxp.CCM.CCOSR.Get() & ^uint32(nxp.CCM_CCOSR_CLKO1_SEL_Msk)) |\n\t\t((1 << nxp.CCM_CCOSR_CLKO1_SEL_Pos) & nxp.CCM_CCOSR_CLKO1_SEL_Msk))\n\t// set CLOCK_OUT2 divider\n\tnxp.CCM.CCOSR.Set((nxp.CCM.CCOSR.Get() & ^uint32(nxp.CCM_CCOSR_CLKO2_DIV_Msk)) |\n\t\t((0 << nxp.CCM_CCOSR_CLKO2_DIV_Pos) & nxp.CCM_CCOSR_CLKO2_DIV_Msk))\n\t// set CLOCK_OUT2 source\n\tnxp.CCM.CCOSR.Set((nxp.CCM.CCOSR.Get() & ^uint32(nxp.CCM_CCOSR_CLKO2_SEL_Msk)) |\n\t\t((18 << nxp.CCM_CCOSR_CLKO2_SEL_Pos) & nxp.CCM_CCOSR_CLKO2_SEL_Msk))\n\n\tnxp.CCM.CCOSR.ClearBits(nxp.CCM_CCOSR_CLK_OUT_SEL_Msk) // set CLK_OUT1 drives CLK_OUT\n\tnxp.CCM.CCOSR.SetBits(nxp.CCM_CCOSR_CLKO1_EN_Msk)      // enable CLK_OUT1\n\tnxp.CCM.CCOSR.SetBits(nxp.CCM_CCOSR_CLKO2_EN_Msk)      // enable CLK_OUT2\n\n\tnxp.ClockIpIomuxcGpr.Enable(false) // disable IOMUXC_GPR\n\tnxp.ClockIpIomuxc.Enable(false)    // disable IOMUXC\n\t// set GPT1 High frequency reference clock source\n\tnxp.IOMUXC_GPR.GPR5.ClearBits(nxp.IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT1_Msk)\n\t// set GPT2 High frequency reference clock source\n\tnxp.IOMUXC_GPR.GPR5.ClearBits(nxp.IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT2_Msk)\n\n\tnxp.ClockIpGpio1.Enable(false) // disable GPIO\n\tnxp.ClockIpGpio2.Enable(false) //\n\tnxp.ClockIpGpio3.Enable(false) //\n\tnxp.ClockIpGpio4.Enable(false) //\n}\n\nfunc enableTimerClocks() {\n\tnxp.ClockIpGpt1.Enable(true)  // enable GPT/PIT\n\tnxp.ClockIpGpt1S.Enable(true) //\n\tnxp.ClockIpGpt2.Enable(true)  //\n\tnxp.ClockIpGpt2S.Enable(true) //\n\tnxp.ClockIpPit.Enable(true)   //\n}\n\nfunc enablePinClocks() {\n\tnxp.ClockIpIomuxcGpr.Enable(true) // enable IOMUXC\n\tnxp.ClockIpIomuxc.Enable(true)    //\n\n\tnxp.ClockIpGpio1.Enable(true) // enable GPIO\n\tnxp.ClockIpGpio2.Enable(true) //\n\tnxp.ClockIpGpio3.Enable(true) //\n\tnxp.ClockIpGpio4.Enable(true) //\n}\n\nfunc enablePeripheralClocks() {\n\tnxp.ClockIpAdc1.Enable(true) // enable ADC\n\tnxp.ClockIpAdc2.Enable(true) //\n\n\tnxp.ClockIpXbar1.Enable(true) // enable XBAR\n\tnxp.ClockIpXbar2.Enable(true) //\n\tnxp.ClockIpXbar3.Enable(true) //\n\n\tnxp.ClockIpUsdhc1.Enable(true) // enable USDHC\n\tnxp.ClockIpUsdhc2.Enable(true) //\n\n\tnxp.ClockIpSemc.Enable(true) // enable SEMC\n\n\tnxp.ClockIpFlexSpi2.Enable(true) // enable FLEXSPI2\n\n\tnxp.ClockIpLpspi1.Enable(true) // enable LPSPI\n\tnxp.ClockIpLpspi2.Enable(true) //\n\tnxp.ClockIpLpspi3.Enable(true) //\n\tnxp.ClockIpLpspi4.Enable(true) //\n\n\tnxp.ClockIpLpi2c1.Enable(true) // enable LPI2C\n\tnxp.ClockIpLpi2c2.Enable(true) //\n\tnxp.ClockIpLpi2c3.Enable(true) //\n\tnxp.ClockIpLpi2c4.Enable(true) //\n\n\tnxp.ClockIpCan1.Enable(true)  // enable CAN\n\tnxp.ClockIpCan2.Enable(true)  //\n\tnxp.ClockIpCan3.Enable(true)  //\n\tnxp.ClockIpCan1S.Enable(true) //\n\tnxp.ClockIpCan2S.Enable(true) //\n\tnxp.ClockIpCan3S.Enable(true) //\n\n\tnxp.ClockIpLpuart1.Enable(true) // enable UART\n\tnxp.ClockIpLpuart2.Enable(true) //\n\tnxp.ClockIpLpuart3.Enable(true) //\n\tnxp.ClockIpLpuart4.Enable(true) //\n\tnxp.ClockIpLpuart5.Enable(true) //\n\tnxp.ClockIpLpuart6.Enable(true) //\n\tnxp.ClockIpLpuart7.Enable(true) //\n\tnxp.ClockIpLpuart8.Enable(true) //\n\n\tnxp.ClockIpFlexio1.Enable(true) // enable FLEXIO\n\tnxp.ClockIpFlexio2.Enable(true) //\n}\n"
  },
  {
    "path": "src/runtime/runtime_mimxrt1062_mpu.go",
    "content": "//go:build mimxrt1062\n\npackage runtime\n\nimport (\n\t\"device/nxp\"\n)\n\nfunc initCache() {\n\n\tnxp.MPU.Enable(false)\n\n\t// add Default [0] region to deny access to whole address space to workaround\n\t// speculative prefetch. Refer to Arm errata 1013783-B for more details.\n\n\t// [0] Default {OVERLAY}: 4 GiB, -access, @device, -exec, -share, -cache, -buffer, -subregion\n\tnxp.MPU.SetRBAR(0, 0x00000000)\n\tnxp.MPU.SetRASR(nxp.RGNSZ_4GB, nxp.PERM_NONE, nxp.EXTN_DEVICE, false, false, false, false, false)\n\n\t// [1] Peripherals {OVERLAY}: 64 MiB, +ACCESS, @device, +EXEC, -share, -cache, -buffer, -subregion\n\tnxp.MPU.SetRBAR(1, 0x40000000)\n\tnxp.MPU.SetRASR(nxp.RGNSZ_64MB, nxp.PERM_FULL, nxp.EXTN_DEVICE, true, false, false, false, false)\n\n\t// [2] RAM {OVERLAY}: 1 GiB, +ACCESS, @device, +EXEC, -share, -cache, -buffer, -subregion\n\tnxp.MPU.SetRBAR(2, 0x00000000)\n\tnxp.MPU.SetRASR(nxp.RGNSZ_1GB, nxp.PERM_FULL, nxp.EXTN_DEVICE, true, false, false, false, false)\n\n\t// [3] ITCM: 512 KiB, +ACCESS, #NORMAL, +EXEC, -share, -cache, -buffer, -subregion\n\tnxp.MPU.SetRBAR(3, 0x00000000)\n\tnxp.MPU.SetRASR(nxp.RGNSZ_512KB, nxp.PERM_FULL, nxp.EXTN_NORMAL, true, false, false, false, false)\n\n\t// [4] DTCM: 512 KiB, +ACCESS, #NORMAL, +EXEC, -share, -cache, -buffer, -subregion\n\tnxp.MPU.SetRBAR(4, 0x20000000)\n\tnxp.MPU.SetRASR(nxp.RGNSZ_512KB, nxp.PERM_FULL, nxp.EXTN_NORMAL, true, false, false, false, false)\n\n\t// [5] RAM (AXI): 512 KiB, +ACCESS, #NORMAL, +EXEC, -share, +CACHE, +BUFFER, -subregion\n\tnxp.MPU.SetRBAR(5, 0x20200000)\n\tnxp.MPU.SetRASR(nxp.RGNSZ_512KB, nxp.PERM_FULL, nxp.EXTN_NORMAL, true, false, true, true, false)\n\n\t// [6] FlexSPI: 512 MiB, +ACCESS, #NORMAL, +EXEC, -share, +CACHE, +BUFFER, -subregion\n\tnxp.MPU.SetRBAR(6, 0x70000000)\n\tnxp.MPU.SetRASR(nxp.RGNSZ_512MB, nxp.PERM_FULL, nxp.EXTN_NORMAL, true, false, true, true, false)\n\n\t// [7] QSPI flash: 2 MiB, +ACCESS, #NORMAL, +EXEC, -share, +CACHE, +BUFFER, -subregion\n\tnxp.MPU.SetRBAR(7, 0x60000000)\n\tnxp.MPU.SetRASR(nxp.RGNSZ_2MB, nxp.PERM_FULL, nxp.EXTN_NORMAL, true, false, true, true, false)\n\n\tnxp.MPU.Enable(true)\n}\n"
  },
  {
    "path": "src/runtime/runtime_mimxrt1062_time.go",
    "content": "//go:build mimxrt1062\n\npackage runtime\n\nimport (\n\t\"device/arm\"\n\t\"device/nxp\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nconst (\n\tlastCycle      = SYSTICK_FREQ/1000 - 1\n\tcyclesPerMicro = CORE_FREQ / 1000000\n)\n\nconst (\n\tpitFreq           = OSC_FREQ // PIT/GPT are muxed to 24 MHz OSC\n\tpitCyclesPerMicro = pitFreq / 1000000\n\tpitSleepTimer     = 0 // x4 32-bit PIT timers [0..3]\n)\n\nvar (\n\ttickCount  volatile.Register64\n\tcycleCount volatile.Register32\n\tpitActive  volatile.Register32\n\tpitTimeout interrupt.Interrupt\n)\n\nvar (\n\t// debug exception and monitor control\n\tDEM_CR     = (*volatile.Register32)(unsafe.Pointer(uintptr(0xe000edfc)))\n\tDWT_CR     = (*volatile.Register32)(unsafe.Pointer(uintptr(0xe0001000)))\n\tDWT_CYCCNT = (*volatile.Register32)(unsafe.Pointer(uintptr(0xe0001004)))\n)\n\nfunc ticksToNanoseconds(ticks timeUnit) int64 {\n\treturn int64(ticks) * 1000\n}\n\nfunc nanosecondsToTicks(ns int64) timeUnit {\n\treturn timeUnit(ns / 1000)\n}\n\nfunc initSysTick() {\n\n\tconst (\n\t\ttraceEnable      = 0x01000000 // enable debugging & monitoring blocks\n\t\tcycleCountEnable = 0x00000001 // cycle count register\n\t)\n\n\t// disable SysTick if already running\n\tif arm.SYST.SYST_CSR.HasBits(arm.SYST_CSR_ENABLE_Msk) {\n\t\tarm.SYST.SYST_CSR.ClearBits(arm.SYST_CSR_ENABLE_Msk)\n\t}\n\n\t// zeroize the counter\n\ttickCount.Set(0)\n\tarm.SYST.SYST_RVR.Set(lastCycle)\n\tarm.SYST.SYST_CVR.Set(0)\n\tarm.SYST.SYST_CSR.Set(arm.SYST_CSR_TICKINT | arm.SYST_CSR_ENABLE)\n\n\t// set SysTick and PendSV priority to 32\n\tnxp.SystemControl.SHPR3.Set((0x20 << nxp.SCB_SHPR3_PRI_15_Pos) |\n\t\t(0x20 << nxp.SCB_SHPR3_PRI_14_Pos))\n\n\t// turn on cycle counter\n\tDEM_CR.SetBits(traceEnable)\n\tDWT_CR.SetBits(cycleCountEnable)\n\tcycleCount.Set(DWT_CYCCNT.Get())\n\n\t// enable PIT, disable counters\n\tnxp.PIT.MCR.Set(0)\n\tfor i := range nxp.PIT.TIMER {\n\t\tnxp.PIT.TIMER[i].TCTRL.Set(0)\n\t}\n\n\t// register sleep timer interrupt\n\tpitTimeout = interrupt.New(nxp.IRQ_PIT, timerWake)\n\tpitTimeout.SetPriority(0x21)\n\tpitTimeout.Enable()\n}\n\nfunc initRTC() {\n\tif !nxp.SNVS.LPCR.HasBits(nxp.SNVS_LPCR_SRTC_ENV) {\n\t\t// if SRTC isn't running, start it with default Jan 1, 2019\n\t\tnxp.SNVS.LPSRTCLR.Set(uint32((0x5c2aad80 << 15) & 0xFFFFFFFF))\n\t\tnxp.SNVS.LPSRTCMR.Set(uint32(0x5c2aad80 >> 17))\n\t\tnxp.SNVS.LPCR.SetBits(nxp.SNVS_LPCR_SRTC_ENV)\n\t}\n}\n\n//go:export SysTick_Handler\nfunc tick() {\n\ttickCount.Set(tickCount.Get() + 1)\n\tcycleCount.Set(DWT_CYCCNT.Get())\n}\n\nfunc ticks() timeUnit {\n\tmask := arm.DisableInterrupts()\n\ttick := tickCount.Get()\n\tcycs := cycleCount.Get()\n\tcurr := DWT_CYCCNT.Get()\n\tarm.EnableInterrupts(mask)\n\tvar diff uint32\n\tif curr < cycs { // cycle counter overflow/rollover occurred\n\t\tdiff = (0xFFFFFFFF - cycs) + curr\n\t} else {\n\t\tdiff = curr - cycs\n\t}\n\tfrac := uint64(diff*0xFFFFFFFF/cyclesPerMicro) >> 32\n\tif frac > 1000 {\n\t\tfrac = 1000\n\t}\n\treturn timeUnit(1000*tick + frac)\n}\n\nfunc sleepTicks(duration timeUnit) {\n\tcurr := ticks()\n\tlast := curr + duration // 64-bit overflow unlikely\n\tfor curr < last {\n\t\tcycles := timeUnit((last - curr) / pitCyclesPerMicro)\n\t\tif cycles > 0xFFFFFFFF {\n\t\t\tcycles = 0xFFFFFFFF\n\t\t}\n\t\tif !timerSleep(uint32(cycles)) {\n\t\t\treturn // return early due to interrupt\n\t\t}\n\t\tcurr = ticks()\n\t}\n}\n\nfunc timerSleep(cycles uint32) bool {\n\tpitActive.Set(1)\n\tnxp.PIT.TIMER[pitSleepTimer].LDVAL.Set(cycles)\n\tnxp.PIT.TIMER[pitSleepTimer].TCTRL.Set(nxp.PIT_TIMER_TCTRL_TIE)     // enable interrupts\n\tnxp.PIT.TIMER[pitSleepTimer].TCTRL.SetBits(nxp.PIT_TIMER_TCTRL_TEN) // start timer\n\tfor {\n\t\t//arm.Asm(\"wfi\") // TODO: causes hardfault! why?\n\t\tif pitActive.Get() == 0 {\n\t\t\treturn true\n\t\t}\n\t\tif hasScheduler {\n\t\t\tbreak // some other interrupt occurred and needs servicing\n\t\t}\n\t}\n\ttimerWake(interrupt.Interrupt{}) // clear and disable timer\n\treturn false\n}\n\nfunc timerWake(interrupt.Interrupt) {\n\tpitActive.Set(0)\n\t// TFLGn[TIF] are set to 1 when a timeout occurs on the associated timer, and\n\t// are cleared to 0 by writing a 1 to the corresponding TFLGn[TIF].\n\tnxp.PIT.TIMER[pitSleepTimer].TFLG.Set(nxp.PIT_TIMER_TFLG_TIF) // clear interrupt flag\n\tnxp.PIT.TIMER[pitSleepTimer].TCTRL.Set(0)                     // disable timer/interrupt enable flags\n}\n"
  },
  {
    "path": "src/runtime/runtime_nintendoswitch.S",
    "content": "// Macro for writing less code\n.macro FUNC name\n    .section .text.\\name, \"ax\", %progbits\n    .global \\name\n    .type \\name, %function\n    .align 2\n\\name:\n.endm\n\nFUNC armGetSystemTick\n    mrs x0, cntpct_el0\n    ret\n\n// Horizon System Calls\n// https://switchbrew.org/wiki/SVC\nFUNC svcSetHeapSize\n    str x0, [sp, #-16]!\n    svc 0x1\n    ldr x2, [sp], #16\n    str x1, [x2]\n    ret\n\nFUNC svcExitProcess\n    svc 0x7\n    ret\n\nFUNC svcSleepThread\n    svc 0xB\n    ret\n\nFUNC svcOutputDebugString\n    svc 0x27\n    ret\n\nFUNC svcGetInfo\n    str x0, [sp, #-16]!\n    svc 0x29\n    ldr x2, [sp], #16\n    str x1, [x2]\n    ret\n"
  },
  {
    "path": "src/runtime/runtime_nintendoswitch.go",
    "content": "//go:build nintendoswitch\n\npackage runtime\n\nimport \"unsafe\"\n\nconst (\n\t// Handles\n\tinfoTypeTotalMemorySize = 6          // Total amount of memory available for process.\n\tinfoTypeUsedMemorySize  = 7          // Amount of memory currently used by process.\n\tcurrentProcessHandle    = 0xFFFF8001 // Pseudo handle for the current process.\n\n\t// Types of config Entry\n\tenvEntryTypeEndOfList        = 0 // Entry list terminator.\n\tenvEntryTypeMainThreadHandle = 1 // Provides the handle to the main thread.\n\tenvEntryTypeOverrideHeap     = 3 // Provides heap override information.\n\n\t// Default heap size allocated by libnx\n\tdefaultHeapSize = 0x2000000 * 16\n\n\tdebugInit = false\n)\n\n//go:extern _saved_return_address\nvar savedReturnAddress uintptr\n\n//export __stack_top\nvar stackTop uintptr\n\n//go:extern _context\nvar context uintptr\n\n//go:extern _main_thread\nvar mainThread uintptr\n\nvar (\n\theapStart = uintptr(0)\n\theapEnd   = uintptr(0)\n\tusedRam   = uint64(0)\n\ttotalRam  = uint64(0)\n\ttotalHeap = uint64(0)\n)\n\nfunc preinit() {\n\t// Unsafe to use heap here\n\tsetupEnv()\n\tsetupHeap()\n}\n\n// Entry point for Go. Initialize all packages and call main.main().\n//\n//export main\nfunc main() {\n\tpreinit()\n\trun()\n\n\t// Call exit to correctly finish the program\n\t// Without this, the application crashes at start, not sure why\n\tfor {\n\t\texit(0)\n\t}\n}\n\n// sleepTicks sleeps for the specified system ticks\nfunc sleepTicks(d timeUnit) {\n\tsvcSleepThread(uint64(ticksToNanoseconds(d)))\n}\n\n// armTicksToNs converts cpu ticks to nanoseconds\n// Nintendo Switch CPU ticks has a fixed rate at 19200000\n// It is basically 52 ns per tick\n// The formula 625 / 12 is equivalent to 1e9 / 19200000\nfunc ticksToNanoseconds(tick timeUnit) int64 {\n\treturn int64(tick * 625 / 12)\n}\n\nfunc nanosecondsToTicks(ns int64) timeUnit {\n\treturn timeUnit(12 * ns / 625)\n}\n\nfunc ticks() timeUnit {\n\treturn timeUnit(ticksToNanoseconds(timeUnit(getArmSystemTick())))\n}\n\n// timeOffset is how long the monotonic clock started after the Unix epoch. It\n// should be a positive integer under normal operation or zero when it has not\n// been set.\nvar timeOffset int64\n\n//go:linkname now time.now\nfunc now() (sec int64, nsec int32, mono int64) {\n\tmono = nanotime()\n\tsec = (mono + timeOffset) / (1000 * 1000 * 1000)\n\tnsec = int32((mono + timeOffset) - sec*(1000*1000*1000))\n\treturn\n}\n\nvar stdoutBuffer = make([]byte, 120)\nvar position = 0\n\nfunc putchar(c byte) {\n\tif c == '\\n' || position >= len(stdoutBuffer) {\n\t\tsvcOutputDebugString(&stdoutBuffer[0], uint64(position))\n\t\tposition = 0\n\t\treturn\n\t}\n\n\tstdoutBuffer[position] = c\n\tposition++\n}\n\nfunc buffered() int {\n\treturn 0\n}\n\nfunc getchar() byte {\n\treturn 0\n}\n\nfunc abort() {\n\tfor {\n\t\texit(1)\n\t}\n}\n\n//export write\nfunc libc_write(fd int32, buf *byte, count int) int {\n\t// TODO: Proper handling write\n\tfor i := 0; i < count; i++ {\n\t\tputchar(*buf)\n\t\tbuf = (*byte)(unsafe.Add(unsafe.Pointer(buf), 1))\n\t}\n\treturn count\n}\n\n// exit checks if a savedReturnAddress were provided by the launcher\n// if so, calls the nxExit which restores the stack and returns to launcher\n// otherwise just calls systemcall exit\nfunc exit(code int) {\n\tif savedReturnAddress == 0 {\n\t\tsvcExitProcess(code)\n\t\treturn\n\t}\n\n\tnxExit(code, stackTop, savedReturnAddress)\n}\n\ntype configEntry struct {\n\tKey   uint32\n\tFlags uint32\n\tValue [2]uint64\n}\n\nfunc setupEnv() {\n\tif debugInit {\n\t\tprintln(\"Saved Return Address:\", savedReturnAddress)\n\t\tprintln(\"Context:\", context)\n\t\tprintln(\"Main Thread Handle:\", mainThread)\n\t}\n\n\t// See https://switchbrew.org/w/index.php?title=Homebrew_ABI\n\t// Here we parse only the required configs for initializing\n\tif context != 0 {\n\t\tptr := context\n\t\tentry := (*configEntry)(unsafe.Pointer(ptr))\n\t\tfor entry.Key != envEntryTypeEndOfList {\n\t\t\tswitch entry.Key {\n\t\t\tcase envEntryTypeOverrideHeap:\n\t\t\t\tif debugInit {\n\t\t\t\t\tprintln(\"Got heap override\")\n\t\t\t\t}\n\t\t\t\theapStart = uintptr(entry.Value[0])\n\t\t\t\theapEnd = heapStart + uintptr(entry.Value[1])\n\t\t\tcase envEntryTypeMainThreadHandle:\n\t\t\t\tmainThread = uintptr(entry.Value[0])\n\t\t\tdefault:\n\t\t\t\tif entry.Flags&1 > 0 {\n\t\t\t\t\t// Mandatory but not parsed\n\t\t\t\t\truntimePanic(\"mandatory config entry not parsed\")\n\t\t\t\t}\n\t\t\t}\n\t\t\tptr += unsafe.Sizeof(configEntry{})\n\t\t\tentry = (*configEntry)(unsafe.Pointer(ptr))\n\t\t}\n\t}\n\t// Fetch used / total RAM for allocating HEAP\n\tsvcGetInfo(&totalRam, infoTypeTotalMemorySize, currentProcessHandle, 0)\n\tsvcGetInfo(&usedRam, infoTypeUsedMemorySize, currentProcessHandle, 0)\n}\n\nfunc setupHeap() {\n\tif heapStart != 0 {\n\t\tif debugInit {\n\t\t\tprint(\"Heap already overridden by hblauncher\")\n\t\t}\n\t\t// Already overridden\n\t\treturn\n\t}\n\n\tif debugInit {\n\t\tprint(\"No heap override. Using normal initialization\")\n\t}\n\n\tsize := uint32(defaultHeapSize)\n\n\tif totalRam > usedRam+0x200000 {\n\t\t// Get maximum possible heap\n\t\tsize = uint32(totalRam-usedRam-0x200000) & ^uint32(0x1FFFFF)\n\t}\n\n\tif size < defaultHeapSize {\n\t\tsize = defaultHeapSize\n\t}\n\n\tif debugInit {\n\t\tprintln(\"Trying to allocate\", size, \"bytes of heap\")\n\t}\n\n\tsvcSetHeapSize(&heapStart, uint64(size))\n\n\tif heapStart == 0 {\n\t\truntimePanic(\"failed to allocate heap\")\n\t}\n\n\ttotalHeap = uint64(size)\n\n\theapEnd = heapStart + uintptr(size)\n\n\tif debugInit {\n\t\tprintln(\"Heap Start\", heapStart)\n\t\tprintln(\"Heap End  \", heapEnd)\n\t\tprintln(\"Total Heap\", totalHeap)\n\t}\n}\n\n// growHeap tries to grow the heap size. It returns true if it succeeds, false\n// otherwise.\nfunc growHeap() bool {\n\t// Growing the heap is unimplemented.\n\treturn false\n}\n\n// getHeapBase returns the start address of the heap\n// this is externally linked by gonx\nfunc getHeapBase() uintptr {\n\treturn heapStart\n}\n\n// getHeapEnd returns the end address of the heap\n// this is externally linked by gonx\nfunc getHeapEnd() uintptr {\n\treturn heapEnd\n}\n\n//go:extern __data_start\nvar dataStartSymbol [0]byte\n\n//go:extern __data_end\nvar dataEndSymbol [0]byte\n\n//go:extern __bss_start\nvar bssStartSymbol [0]byte\n\n//go:extern __bss_end\nvar bssEndSymbol [0]byte\n\n// Find global variables.\n// The linker script provides __*_start and __*_end symbols that can be used to\n// scan the given sections. They are already aligned so don't need to be\n// manually aligned here.\nfunc findGlobals(found func(start, end uintptr)) {\n\tdataStart := uintptr(unsafe.Pointer(&dataStartSymbol))\n\tdataEnd := uintptr(unsafe.Pointer(&dataEndSymbol))\n\tfound(dataStart, dataEnd)\n\tbssStart := uintptr(unsafe.Pointer(&bssStartSymbol))\n\tbssEnd := uintptr(unsafe.Pointer(&bssEndSymbol))\n\tfound(bssStart, bssEnd)\n}\n\n// getContextPtr returns the hblauncher context\n// this is externally linked by gonx\nfunc getContextPtr() uintptr {\n\treturn context\n}\n\n// getMainThreadHandle returns the main thread handler if any\n// this is externally linked by gonx\nfunc getMainThreadHandle() uintptr {\n\treturn mainThread\n}\n\n//export armGetSystemTick\nfunc getArmSystemTick() int64\n\n// nxExit exits the program to homebrew launcher\n//\n//export __nx_exit\nfunc nxExit(code int, stackTop uintptr, exitFunction uintptr)\n\n// Horizon System Calls\n// svcSetHeapSize Set the process heap to a given size. It can both extend and shrink the heap.\n// svc 0x01\n//\n//export svcSetHeapSize\nfunc svcSetHeapSize(addr *uintptr, length uint64) uint64\n\n// svcExitProcess Exits the current process.\n// svc 0x07\n//\n//export svcExitProcess\nfunc svcExitProcess(code int)\n\n// svcSleepThread Sleeps the current thread for the specified amount of time.\n// svc 0x0B\n//\n//export svcSleepThread\nfunc svcSleepThread(nanos uint64)\n\n// svcOutputDebugString Outputs debug text, if used during debugging.\n// svc 0x27\n//\n//export svcOutputDebugString\nfunc svcOutputDebugString(str *uint8, size uint64) uint64\n\n// svcGetInfo Retrieves information about the system, or a certain kernel object.\n// svc 0x29\n//\n//export svcGetInfo\nfunc svcGetInfo(output *uint64, id0 uint32, handle uint32, id1 uint64) uint64\n\nfunc hardwareRand() (n uint64, ok bool) {\n\t// TODO: see whether there is a RNG and use it.\n\treturn 0, false\n}\n\nfunc libc_errno_location() *int32 {\n\t// CGo is unavailable, so this function should be unreachable.\n\truntimePanic(\"runtime: no cgo errno\")\n\treturn nil\n}\n"
  },
  {
    "path": "src/runtime/runtime_nrf.go",
    "content": "//go:build nrf\n\npackage runtime\n\nimport (\n\t\"device/arm\"\n\t\"device/nrf\"\n\t\"machine\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n)\n\n//go:linkname systemInit SystemInit\nfunc systemInit()\n\n//export Reset_Handler\nfunc main() {\n\tif nrf.FPUPresent {\n\t\tarm.SCB.CPACR.Set(0) // disable FPU if it is enabled\n\t}\n\tsystemInit()\n\tpreinit()\n\trun()\n\texit(0)\n}\n\nfunc init() {\n\tmachine.InitSerial()\n\tinitLFCLK()\n\tinitRTC()\n}\n\nfunc initLFCLK() {\n\tif machine.HasLowFrequencyCrystal {\n\t\tnrf.CLOCK.LFCLKSRC.Set(nrf.CLOCK_LFCLKSTAT_SRC_Xtal)\n\t}\n\tnrf.CLOCK.TASKS_LFCLKSTART.Set(1)\n\tfor nrf.CLOCK.EVENTS_LFCLKSTARTED.Get() == 0 {\n\t}\n\tnrf.CLOCK.EVENTS_LFCLKSTARTED.Set(0)\n}\n\nfunc initRTC() {\n\tnrf.RTC1.TASKS_START.Set(1)\n\tintr := interrupt.New(nrf.IRQ_RTC1, func(intr interrupt.Interrupt) {\n\t\tif nrf.RTC1.EVENTS_COMPARE[0].Get() != 0 {\n\t\t\tnrf.RTC1.EVENTS_COMPARE[0].Set(0)\n\t\t\tnrf.RTC1.INTENCLR.Set(nrf.RTC_INTENSET_COMPARE0)\n\t\t\tnrf.RTC1.EVENTS_COMPARE[0].Set(0)\n\t\t\trtc_wakeup.Set(1)\n\t\t}\n\t\tif nrf.RTC1.EVENTS_OVRFLW.Get() != 0 {\n\t\t\tnrf.RTC1.EVENTS_OVRFLW.Set(0)\n\t\t\trtcOverflows.Set(rtcOverflows.Get() + 1)\n\t\t}\n\t})\n\tnrf.RTC1.INTENSET.Set(nrf.RTC_INTENSET_OVRFLW)\n\tintr.SetPriority(0xc0) // low priority\n\tintr.Enable()\n}\n\nfunc putchar(c byte) {\n\tmachine.Serial.WriteByte(c)\n}\n\nfunc getchar() byte {\n\tfor machine.Serial.Buffered() == 0 {\n\t\tGosched()\n\t}\n\tv, _ := machine.Serial.ReadByte()\n\treturn v\n}\n\nfunc buffered() int {\n\treturn machine.Serial.Buffered()\n}\n\nfunc sleepTicks(d timeUnit) {\n\tfor d != 0 {\n\t\tticks := uint32(d) & 0x7fffff // 23 bits (to be on the safe side)\n\t\tif d > 0x7fffff {\n\t\t\tticks = 0x7fffff\n\t\t}\n\t\trtc_sleep(ticks)\n\t\td -= timeUnit(ticks)\n\t}\n}\n\nvar rtcOverflows volatile.Register32 // number of times the RTC wrapped around\n\n// ticksToNanoseconds converts RTC ticks (at 32768Hz) to nanoseconds.\nfunc ticksToNanoseconds(ticks timeUnit) int64 {\n\t// The following calculation is actually the following, but with both sides\n\t// reduced to reduce the risk of overflow:\n\t//     ticks * 1e9 / 32768\n\treturn int64(ticks) * 1953125 / 64\n}\n\n// nanosecondsToTicks converts nanoseconds to RTC ticks (running at 32768Hz).\nfunc nanosecondsToTicks(ns int64) timeUnit {\n\t// The following calculation is actually the following, but with both sides\n\t// reduced to reduce the risk of overflow:\n\t//     ns * 32768 / 1e9\n\treturn timeUnit(ns * 64 / 1953125)\n}\n\n// Monotonically increasing number of ticks since start.\nfunc ticks() timeUnit {\n\t// For some ways of capturing the time atomically, see this thread:\n\t// https://www.eevblog.com/forum/microcontrollers/correct-timing-by-timer-overflow-count/msg749617/#msg749617\n\t// Here, instead of re-reading the counter register if an overflow has been\n\t// detected, we simply try again because that results in (slightly) smaller\n\t// code and is perhaps easier to prove correct.\n\tfor {\n\t\tmask := interrupt.Disable()\n\t\tcounter := uint32(nrf.RTC1.COUNTER.Get())\n\t\toverflows := rtcOverflows.Get()\n\t\thasOverflow := nrf.RTC1.EVENTS_OVRFLW.Get() != 0\n\t\tinterrupt.Restore(mask)\n\n\t\tif hasOverflow {\n\t\t\t// There was an overflow. Try again.\n\t\t\tcontinue\n\t\t}\n\n\t\t// The counter is 24 bits in size, so the number of overflows form the\n\t\t// upper 32 bits (together 56 bits, which covers 71493 years at\n\t\t// 32768kHz: I'd argue good enough for most purposes).\n\t\treturn timeUnit(overflows)<<24 + timeUnit(counter)\n\t}\n}\n\nvar rtc_wakeup volatile.Register8\n\nfunc rtc_sleep(ticks uint32) {\n\tnrf.RTC1.INTENSET.Set(nrf.RTC_INTENSET_COMPARE0)\n\trtc_wakeup.Set(0)\n\tif ticks == 1 {\n\t\t// Race condition (even in hardware) at ticks == 1.\n\t\t// TODO: fix this in a better way by detecting it, like the manual\n\t\t// describes.\n\t\tticks = 2\n\t}\n\tnrf.RTC1.CC[0].Set((nrf.RTC1.COUNTER.Get() + ticks) & 0x00ffffff)\n\tfor rtc_wakeup.Get() == 0 {\n\t\twaitForEvents()\n\t}\n}\n"
  },
  {
    "path": "src/runtime/runtime_nrf52840.go",
    "content": "//go:build nrf && nrf52840\n\npackage runtime\n\n// This package needs to be present so that the machine package can go:linkname\n// EnableUSBCDC from it.\nimport _ \"machine/usb/cdc\"\n"
  },
  {
    "path": "src/runtime/runtime_nrf_bare.go",
    "content": "//go:build nrf && !softdevice\n\npackage runtime\n\nimport \"device/arm\"\n\nfunc waitForEvents() {\n\tarm.Asm(\"wfe\")\n}\n"
  },
  {
    "path": "src/runtime/runtime_nrf_softdevice.go",
    "content": "//go:build nrf && softdevice\n\npackage runtime\n\nimport (\n\t\"device/arm\"\n\t\"device/nrf\"\n)\n\n//export sd_app_evt_wait\nfunc sd_app_evt_wait()\n\n// This is a global variable to avoid a heap allocation in waitForEvents.\nvar softdeviceEnabled uint8\n\n// Check whether the SoftDevice is currently enabled.\n// This function is also called from the machine package, so the signature has\n// to stay consistent.\nfunc isSoftDeviceEnabled() bool {\n\t// First check whether the SoftDevice is enabled. Unfortunately,\n\t// sd_app_evt_wait cannot be called when the SoftDevice is not enabled.\n\tarm.SVCall1(0x12, &softdeviceEnabled) // sd_softdevice_is_enabled\n\n\treturn softdeviceEnabled != 0\n}\n\nfunc waitForEvents() {\n\t// Call into the SoftDevice to sleep. This is necessary here because a\n\t// normal wfe will not put the chip in low power mode (it still consumes\n\t// 500µA-1mA). It is really needed to call sd_app_evt_wait for low power\n\t// consumption.\n\n\tif isSoftDeviceEnabled() {\n\t\t// Now pick the appropriate SVCall number. Hopefully they won't change\n\t\t// in the future with a different SoftDevice version.\n\t\tif nrf.Device == \"nrf51\" {\n\t\t\t// sd_app_evt_wait: SOC_SVC_BASE_NOT_AVAILABLE + 29\n\t\t\tarm.SVCall0(0x2B + 29)\n\t\t} else if nrf.Device == \"nrf52\" || nrf.Device == \"nrf52840\" || nrf.Device == \"nrf52833\" {\n\t\t\t// sd_app_evt_wait: SOC_SVC_BASE_NOT_AVAILABLE + 21\n\t\t\tarm.SVCall0(0x2C + 21)\n\t\t} else {\n\t\t\tsd_app_evt_wait()\n\t\t}\n\t} else {\n\t\t// SoftDevice is disabled so we can sleep normally.\n\t\tarm.Asm(\"wfe\")\n\t}\n}\n"
  },
  {
    "path": "src/runtime/runtime_nxpmk66f18.go",
    "content": "// Derivative work of Teensyduino Core Library\n// http://www.pjrc.com/teensy/\n// Copyright (c) 2017 PJRC.COM, LLC.\n//\n// Permission is hereby granted, free of charge, to any person obtaining\n// a copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to\n// the following conditions:\n//\n// 1. The above copyright notice and this permission notice shall be\n// included in all copies or substantial portions of the Software.\n//\n// 2. If the Software is incorporated into a build system that allows\n// selection among a list of target devices, then similar target\n// devices manufactured by PJRC.COM must be included in the list of\n// target devices and selectable in the same manner.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n//go:build nxp && mk66f18\n\npackage runtime\n\nimport (\n\t\"device/arm\"\n\t\"device/nxp\"\n\t\"machine\"\n)\n\nconst (\n\twatchdogUnlockSequence1 = 0xC520\n\twatchdogUnlockSequence2 = 0xD928\n\n\t_DEFAULT_FTM_MOD      = 61440 - 1\n\t_DEFAULT_FTM_PRESCALE = 1\n)\n\nconst (\n\t_SIM_SOPT2_IRC48SEL = 3 << nxp.SIM_SOPT2_PLLFLLSEL_Pos\n\t_SMC_PMCTRL_HSRUN   = 3 << nxp.SMC_PMCTRL_RUNM_Pos\n\t_SMC_PMSTAT_HSRUN   = 0x80 << nxp.SMC_PMSTAT_PMSTAT_Pos\n)\n\n//go:export Reset_Handler\nfunc main() {\n\tinitSystem()\n\tarm.Asm(\"CPSIE i\")\n\tinitInternal()\n\n\trun()\n\texit(0)\n}\n\nfunc initSystem() {\n\t// from: ResetHandler\n\n\tnxp.WDOG.UNLOCK.Set(watchdogUnlockSequence1)\n\tnxp.WDOG.UNLOCK.Set(watchdogUnlockSequence2)\n\tarm.Asm(\"nop\")\n\tarm.Asm(\"nop\")\n\t// TODO: hook for overriding? 'startupEarlyHook'\n\tnxp.WDOG.STCTRLH.Set(nxp.WDOG_STCTRLH_ALLOWUPDATE)\n\n\t// enable clocks to always-used peripherals\n\tnxp.SIM.SCGC3.Set(nxp.SIM_SCGC3_ADC1 | nxp.SIM_SCGC3_FTM2 | nxp.SIM_SCGC3_FTM3)\n\tnxp.SIM.SCGC5.Set(0x00043F82) // clocks active to all GPIO\n\tnxp.SIM.SCGC6.Set(nxp.SIM_SCGC6_RTC | nxp.SIM_SCGC6_FTM0 | nxp.SIM_SCGC6_FTM1 | nxp.SIM_SCGC6_ADC0 | nxp.SIM_SCGC6_FTF)\n\tnxp.LMEM.PCCCR.Set(0x85000003)\n\n\t// release I/O pins hold, if we woke up from VLLS mode\n\tif nxp.PMC.REGSC.HasBits(nxp.PMC_REGSC_ACKISO) {\n\t\tnxp.PMC.REGSC.SetBits(nxp.PMC_REGSC_ACKISO)\n\t}\n\n\t// since this is a write once register, make it visible to all F_CPU's\n\t// so we can into other sleep modes in the future at any speed\n\tnxp.SMC.PMPROT.Set(nxp.SMC_PMPROT_AHSRUN | nxp.SMC_PMPROT_AVLP | nxp.SMC_PMPROT_ALLS | nxp.SMC_PMPROT_AVLLS)\n\n\tpreinit()\n\n\t// copy the vector table to RAM default all interrupts to medium priority level\n\t// for (i=0; i < NVIC_NUM_INTERRUPTS + 16; i++) _VectorsRam[i] = _VectorsFlash[i];\n\tfor i := uint32(0); i <= nxp.IRQ_max; i++ {\n\t\tarm.SetPriority(i, 128)\n\t}\n\t// SCB_VTOR = (uint32_t)_VectorsRam;\t// use vector table in RAM\n\n\t// hardware always starts in FEI mode\n\t//  C1[CLKS] bits are written to 00\n\t//  C1[IREFS] bit is written to 1\n\t//  C6[PLLS] bit is written to 0\n\t// MCG_SC[FCDIV] defaults to divide by two for internal ref clock\n\t// I tried changing MSG_SC to divide by 1, it didn't work for me\n\t// enable capacitors for crystal\n\tnxp.OSC.CR.Set(nxp.OSC_CR_SC8P | nxp.OSC_CR_SC2P | nxp.OSC_CR_ERCLKEN)\n\t// enable osc, 8-32 MHz range, low power mode\n\tnxp.MCG.C2.Set(uint8((2 << nxp.MCG_C2_RANGE_Pos) | nxp.MCG_C2_EREFS))\n\t// switch to crystal as clock source, FLL input = 16 MHz / 512\n\tnxp.MCG.C1.Set(uint8((2 << nxp.MCG_C1_CLKS_Pos) | (4 << nxp.MCG_C1_FRDIV_Pos)))\n\t// wait for crystal oscillator to begin\n\tfor !nxp.MCG.S.HasBits(nxp.MCG_S_OSCINIT0) {\n\t}\n\t// wait for FLL to use oscillator\n\tfor nxp.MCG.S.HasBits(nxp.MCG_S_IREFST) {\n\t}\n\t// wait for MCGOUT to use oscillator\n\tfor (nxp.MCG.S.Get() & nxp.MCG_S_CLKST_Msk) != (2 << nxp.MCG_S_CLKST_Pos) {\n\t}\n\n\t// now in FBE mode\n\t//  C1[CLKS] bits are written to 10\n\t//  C1[IREFS] bit is written to 0\n\t//  C1[FRDIV] must be written to divide xtal to 31.25-39 kHz\n\t//  C6[PLLS] bit is written to 0\n\t//  C2[LP] is written to 0\n\t// we need faster than the crystal, turn on the PLL (F_CPU > 120000000)\n\tnxp.SMC.PMCTRL.Set(_SMC_PMCTRL_HSRUN) // enter HSRUN mode\n\tfor nxp.SMC.PMSTAT.Get() != _SMC_PMSTAT_HSRUN {\n\t} // wait for HSRUN\n\tnxp.MCG.C5.Set((1 << nxp.MCG_C5_PRDIV_Pos))\n\tnxp.MCG.C6.Set(nxp.MCG_C6_PLLS | (29 << nxp.MCG_C6_VDIV_Pos))\n\n\t// wait for PLL to start using xtal as its input\n\tfor !nxp.MCG.S.HasBits(nxp.MCG_S_PLLST) {\n\t}\n\t// wait for PLL to lock\n\tfor !nxp.MCG.S.HasBits(nxp.MCG_S_LOCK0) {\n\t}\n\t// now we're in PBE mode\n\n\t// now program the clock dividers\n\t// config divisors: 180 MHz core, 60 MHz bus, 25.7 MHz flash, USB = IRC48M\n\tnxp.SIM.CLKDIV1.Set((0 << nxp.SIM_CLKDIV1_OUTDIV1_Pos) | (2 << nxp.SIM_CLKDIV1_OUTDIV2_Pos) | (0 << nxp.SIM_CLKDIV1_OUTDIV3_Pos) | (6 << nxp.SIM_CLKDIV1_OUTDIV4_Pos))\n\tnxp.SIM.CLKDIV2.Set((0 << nxp.SIM_CLKDIV2_USBDIV_Pos))\n\n\t// switch to PLL as clock source, FLL input = 16 MHz / 512\n\tnxp.MCG.C1.Set((0 << nxp.MCG_C1_CLKS_Pos) | (4 << nxp.MCG_C1_FRDIV_Pos))\n\t// wait for PLL clock to be used\n\tfor (nxp.MCG.S.Get() & nxp.MCG_S_CLKST_Msk) != (3 << nxp.MCG_S_CLKST_Pos) {\n\t}\n\t// now we're in PEE mode\n\t// trace is CPU clock, CLKOUT=OSCERCLK0\n\t// USB uses IRC48\n\tnxp.SIM.SOPT2.Set(nxp.SIM_SOPT2_USBSRC | _SIM_SOPT2_IRC48SEL | nxp.SIM_SOPT2_TRACECLKSEL | (6 << nxp.SIM_SOPT2_CLKOUTSEL_Pos))\n\n\t// If the RTC oscillator isn't enabled, get it started.  For Teensy 3.6\n\t// we don't do this early.  See comment above about slow rising power.\n\tif !nxp.RTC.CR.HasBits(nxp.RTC_CR_OSCE) {\n\t\tnxp.RTC.SR.Set(0)\n\t\tnxp.RTC.CR.Set(nxp.RTC_CR_SC16P | nxp.RTC_CR_SC4P | nxp.RTC_CR_OSCE)\n\t}\n\n\t// initialize the SysTick counter\n\tinitSysTick()\n}\n\nfunc initInternal() {\n\t// from: _init_Teensyduino_internal_\n\t// arm.EnableIRQ(nxp.IRQ_PORTA)\n\t// arm.EnableIRQ(nxp.IRQ_PORTB)\n\t// arm.EnableIRQ(nxp.IRQ_PORTC)\n\t// arm.EnableIRQ(nxp.IRQ_PORTD)\n\t// arm.EnableIRQ(nxp.IRQ_PORTE)\n\n\tnxp.FTM0.CNT.Set(0)\n\tnxp.FTM0.MOD.Set(_DEFAULT_FTM_MOD)\n\tnxp.FTM0.C0SC.Set(0x28) // MSnB:MSnA = 10, ELSnB:ELSnA = 10\n\tnxp.FTM0.C1SC.Set(0x28)\n\tnxp.FTM0.C2SC.Set(0x28)\n\tnxp.FTM0.C3SC.Set(0x28)\n\tnxp.FTM0.C4SC.Set(0x28)\n\tnxp.FTM0.C5SC.Set(0x28)\n\tnxp.FTM0.C6SC.Set(0x28)\n\tnxp.FTM0.C7SC.Set(0x28)\n\n\tnxp.FTM3.C0SC.Set(0x28)\n\tnxp.FTM3.C1SC.Set(0x28)\n\tnxp.FTM3.C2SC.Set(0x28)\n\tnxp.FTM3.C3SC.Set(0x28)\n\tnxp.FTM3.C4SC.Set(0x28)\n\tnxp.FTM3.C5SC.Set(0x28)\n\tnxp.FTM3.C6SC.Set(0x28)\n\tnxp.FTM3.C7SC.Set(0x28)\n\n\tnxp.FTM0.SC.Set((1 << nxp.FTM_SC_CLKS_Pos) | (_DEFAULT_FTM_PRESCALE << nxp.FTM_SC_PS_Pos))\n\tnxp.FTM1.CNT.Set(0)\n\tnxp.FTM1.MOD.Set(_DEFAULT_FTM_MOD)\n\tnxp.FTM1.C0SC.Set(0x28)\n\tnxp.FTM1.C1SC.Set(0x28)\n\tnxp.FTM1.SC.Set((1 << nxp.FTM_SC_CLKS_Pos) | (_DEFAULT_FTM_PRESCALE << nxp.FTM_SC_PS_Pos))\n\n\t// causes a data bus error for unknown reasons\n\t// nxp.FTM2.CNT.Set(0)\n\t// nxp.FTM2.MOD.Set(_DEFAULT_FTM_MOD)\n\t// nxp.FTM2.C0SC.Set(0x28)\n\t// nxp.FTM2.C1SC.Set(0x28)\n\t// nxp.FTM2.SC.Set((1 << nxp.FTM_SC_CLKS_Pos) | (_DEFAULT_FTM_PRESCALE << nxp.FTM_SC_PS_Pos))\n\n\tnxp.FTM3.CNT.Set(0)\n\tnxp.FTM3.MOD.Set(_DEFAULT_FTM_MOD)\n\tnxp.FTM3.C0SC.Set(0x28)\n\tnxp.FTM3.C1SC.Set(0x28)\n\tnxp.FTM3.SC.Set((1 << nxp.FTM_SC_CLKS_Pos) | (_DEFAULT_FTM_PRESCALE << nxp.FTM_SC_PS_Pos))\n\n\tnxp.SIM.SCGC2.SetBits(nxp.SIM_SCGC2_TPM1)\n\tnxp.SIM.SOPT2.SetBits((2 << nxp.SIM_SOPT2_TPMSRC_Pos))\n\tnxp.TPM1.CNT.Set(0)\n\tnxp.TPM1.MOD.Set(32767)\n\tnxp.TPM1.C0SC.Set(0x28)\n\tnxp.TPM1.C1SC.Set(0x28)\n\tnxp.TPM1.SC.Set((1 << nxp.FTM_SC_CLKS_Pos) | (0 << nxp.FTM_SC_PS_Pos))\n\n\t// configure the sleep timer\n\tinitSleepTimer()\n\n\t// \tanalog_init();\n}\n\nfunc putchar(c byte) {\n\tmachine.PutcharUART(machine.UART0, c)\n}\n\nfunc getchar() byte {\n\t// dummy, TODO\n\treturn 0\n}\n\nfunc buffered() int {\n\t// dummy, TODO\n\treturn 0\n}\n\nfunc exit(code int) {\n\tabort()\n}\n\nfunc abort() {\n\tprintln(\"!!! ABORT !!!\")\n\n\tm := arm.DisableInterrupts()\n\tarm.Asm(\"mov r12, #1\")\n\tarm.Asm(\"msr basepri, r12\")                                           // only execute interrupts of priority 0\n\tnxp.SystemControl.SHPR3.ClearBits(nxp.SystemControl_SHPR3_PRI_15_Msk) // set systick to priority 0\n\tarm.EnableInterrupts(m)\n\n\tmachine.LED.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\n\tvar v bool\n\tfor {\n\t\tmachine.LED.Set(v)\n\t\tv = !v\n\n\t\tt := millisSinceBoot()\n\t\tfor millisSinceBoot()-t < 60 {\n\t\t\tarm.Asm(\"wfi\")\n\t\t}\n\n\t\t// keep polling some communication while in fault\n\t\t// mode, so we don't completely die.\n\t\t// machine.PollUSB(&machine.USB0)\n\t\tmachine.PollUART(machine.UART0)\n\t\tmachine.PollUART(machine.UART1)\n\t\tmachine.PollUART(machine.UART2)\n\t}\n}\n\nfunc waitForEvents() {\n\tarm.Asm(\"wfe\")\n}\n"
  },
  {
    "path": "src/runtime/runtime_rp2.go",
    "content": "//go:build rp2040 || rp2350\n\npackage runtime\n\nimport (\n\t\"device/arm\"\n\t\"device/rp\"\n\t\"internal/task\"\n\t\"machine\"\n\t_ \"machine/usb/cdc\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nconst numCPU = 2\nconst numSpinlocks = 32\n\n// machineTicks is provided by package machine.\nfunc machineTicks() uint64\n\n// machineLightSleep is provided by package machine.\nfunc machineLightSleep(uint64)\n\n// ticks returns the number of ticks (microseconds) elapsed since power up.\nfunc ticks() timeUnit {\n\tt := machineTicks()\n\treturn timeUnit(t)\n}\n\nfunc ticksToNanoseconds(ticks timeUnit) int64 {\n\treturn int64(ticks) * 1000\n}\n\nfunc nanosecondsToTicks(ns int64) timeUnit {\n\treturn timeUnit(ns / 1000)\n}\n\nfunc sleepTicks(d timeUnit) {\n\tif hasScheduler {\n\t\t// With scheduler, sleepTicks may return early if an interrupt or\n\t\t// event fires - so scheduler can schedule any go routines now\n\t\t// eligible to run\n\t\tmachineLightSleep(uint64(d))\n\t\treturn\n\t}\n\n\t// Busy loop\n\tsleepUntil := ticks() + d\n\tfor ticks() < sleepUntil {\n\t}\n}\n\n// Currently sleeping core, or 0xff.\n// Must only be accessed with the scheduler lock held.\nvar sleepingCore uint8 = 0xff\n\n// Return whether another core is sleeping.\n// May only be called with the scheduler lock held.\nfunc hasSleepingCore() bool {\n\treturn sleepingCore != 0xff\n}\n\n// Almost identical to sleepTicks, except that it will unlock/lock the scheduler\n// while sleeping and is interruptible by interruptSleepTicksMulticore.\n// This may only be called with the scheduler lock held.\nfunc sleepTicksMulticore(d timeUnit) {\n\tsleepingCore = uint8(currentCPU())\n\n\t// Note: interruptSleepTicksMulticore will be able to interrupt this, since\n\t// it executes the \"sev\" instruction which would make sleepTicks return\n\t// immediately without sleeping. Even if it happens while configuring the\n\t// sleep operation.\n\n\tschedulerLock.Unlock()\n\tsleepTicks(d)\n\tschedulerLock.Lock()\n\n\tsleepingCore = 0xff\n}\n\n// Interrupt an ongoing call to sleepTicksMulticore on another core.\nfunc interruptSleepTicksMulticore(wakeup timeUnit) {\n\tarm.Asm(\"sev\")\n}\n\n// Number of cores that are currently in schedulerUnlockAndWait.\n// It is possible for both cores to be sleeping, if the program is waiting for\n// an interrupt (or is deadlocked).\nvar waitingCore uint8\n\n// Put the scheduler to sleep, since there are no tasks to run.\n// This will unlock the scheduler lock, and must be called with the scheduler\n// lock held.\nfunc schedulerUnlockAndWait() {\n\twaitingCore++\n\tschedulerLock.Unlock()\n\tarm.Asm(\"wfe\")\n\tschedulerLock.Lock()\n\twaitingCore--\n}\n\n// Wake another core, if one is sleeping. Must be called with the scheduler lock\n// held.\nfunc schedulerWake() {\n\tif waitingCore != 0 {\n\t\tarm.Asm(\"sev\")\n\t}\n}\n\n// Return the current core number: 0 or 1.\nfunc currentCPU() uint32 {\n\treturn rp.SIO.CPUID.Get()\n}\n\n// Start the secondary cores for this chip.\n// On the RP2040/RP2350, there is only one other core to start.\nfunc startSecondaryCores() {\n\t// Start the second core of the RP2040/RP2350.\n\t// See sections 2.8.2 and 5.3 in the datasheets for RP2040 and RP2350 respectively.\n\tseq := 0\n\tfor {\n\t\tcmd := core1StartSequence[seq]\n\t\tif cmd == 0 {\n\t\t\tmulticore_fifo_drain()\n\t\t\tarm.Asm(\"sev\")\n\t\t}\n\t\tmulticore_fifo_push_blocking(cmd)\n\t\tresponse := multicore_fifo_pop_blocking()\n\t\tif cmd != response {\n\t\t\tseq = 0\n\t\t\tcontinue\n\t\t}\n\t\tseq = seq + 1\n\t\tif seq >= len(core1StartSequence) {\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// Enable the FIFO interrupt for the GC stop the world phase.\n\t// We can only do this after we don't need the FIFO anymore for starting the\n\t// second core.\n\tintr := interrupt.New(sioIrqFifoProc0, func(intr interrupt.Interrupt) {\n\t\tswitch rp.SIO.FIFO_RD.Get() {\n\t\tcase 1:\n\t\t\tgcInterruptHandler(0)\n\t\t}\n\t})\n\tintr.Enable()\n\tintr.SetPriority(0xff)\n}\n\nvar core1StartSequence = [...]uint32{\n\t0, 0, 1,\n\tuint32(uintptr(unsafe.Pointer(&__isr_vector))),\n\tuint32(uintptr(unsafe.Pointer(&stack1TopSymbol))),\n\tuint32(exportedFuncPtr(runCore1)),\n}\n\n//go:extern __isr_vector\nvar __isr_vector [0]uint32\n\n//go:extern _stack1_top\nvar stack1TopSymbol [0]uint32\n\n// The function that is started on the second core.\n//\n//export tinygo_runCore1\nfunc runCore1() {\n\t// Clear sticky bit that seems to have been set while starting this core.\n\trp.SIO.FIFO_ST.Set(rp.SIO_FIFO_ST_ROE)\n\n\t// Enable the FIFO interrupt, mainly used for the stop-the-world phase of\n\t// the GC.\n\t// Use the lowest possible priority (highest priority value), so that other\n\t// interrupts can still happen while the GC is running.\n\tintr := interrupt.New(sioIrqFifoProc1, func(intr interrupt.Interrupt) {\n\t\tswitch rp.SIO.FIFO_RD.Get() {\n\t\tcase 1:\n\t\t\tgcInterruptHandler(1)\n\t\t}\n\t})\n\tintr.Enable()\n\tintr.SetPriority(0xff)\n\n\t// Now start running the scheduler on this core.\n\tschedulerLock.Lock()\n\tscheduler(false)\n\tschedulerLock.Unlock()\n\n\t// The main function returned.\n\texit(0)\n}\n\n// The below multicore_fifo_* functions have been translated from the Raspberry\n// Pi Pico SDK.\n\nfunc multicore_fifo_rvalid() bool {\n\treturn rp.SIO.FIFO_ST.Get()&rp.SIO_FIFO_ST_VLD != 0\n}\n\nfunc multicore_fifo_wready() bool {\n\treturn rp.SIO.FIFO_ST.Get()&rp.SIO_FIFO_ST_RDY != 0\n}\n\nfunc multicore_fifo_drain() {\n\tfor multicore_fifo_rvalid() {\n\t\trp.SIO.FIFO_RD.Get()\n\t}\n}\n\nfunc multicore_fifo_push_blocking(data uint32) {\n\tfor !multicore_fifo_wready() {\n\t}\n\trp.SIO.FIFO_WR.Set(data)\n\tarm.Asm(\"sev\")\n}\n\nfunc multicore_fifo_pop_blocking() uint32 {\n\tfor !multicore_fifo_rvalid() {\n\t\tarm.Asm(\"wfe\")\n\t}\n\n\treturn rp.SIO.FIFO_RD.Get()\n}\n\n// Value used to communicate between the GC core and the other (paused) cores.\nvar gcSignalWait volatile.Register8\n\n// The GC interrupted this core for the stop-the-world phase.\n// This function handles that, and only returns after the stop-the-world phase\n// ended.\nfunc gcInterruptHandler(hartID uint32) {\n\t// Let the GC know we're ready.\n\tgcScanState.Add(1)\n\tarm.Asm(\"sev\")\n\n\t// Wait until we get a signal to start scanning.\n\tfor gcSignalWait.Get() == 0 {\n\t\tarm.Asm(\"wfe\")\n\t}\n\tgcSignalWait.Set(0)\n\n\t// Scan the stack(s) of this core.\n\tscanCurrentStack()\n\tif !task.OnSystemStack() {\n\t\t// Mark system stack.\n\t\tmarkRoots(task.SystemStack(), coreStackTop(hartID))\n\t}\n\n\t// Signal we've finished scanning.\n\tgcScanState.Store(1)\n\tarm.Asm(\"sev\")\n\n\t// Wait until we get a signal that the stop-the-world phase has ended.\n\tfor gcSignalWait.Get() == 0 {\n\t\tarm.Asm(\"wfe\")\n\t}\n\tgcSignalWait.Set(0)\n\n\t// Signal we received the signal and are going to exit the interrupt.\n\tgcScanState.Add(1)\n\tarm.Asm(\"sev\")\n}\n\n// Pause the given core by sending it an interrupt.\nfunc gcPauseCore(core uint32) {\n\trp.SIO.FIFO_WR.Set(1)\n}\n\n// Signal the given core that it can resume one step.\n// This is called twice after gcPauseCore: the first time to scan the stack of\n// the core, and the second time to end the stop-the-world phase.\nfunc gcSignalCore(core uint32) {\n\tgcSignalWait.Set(1)\n\tarm.Asm(\"sev\")\n}\n\n// Returns the stack top (highest address) of the system stack of the given\n// core.\nfunc coreStackTop(core uint32) uintptr {\n\tswitch core {\n\tcase 0:\n\t\treturn uintptr(unsafe.Pointer(&stackTopSymbol))\n\tcase 1:\n\t\treturn uintptr(unsafe.Pointer(&stack1TopSymbol))\n\tdefault:\n\t\truntimePanic(\"unexpected core\")\n\t\treturn 0\n\t}\n}\n\n// These spinlocks are needed by the runtime.\nvar (\n\tprintLock     = spinLock{id: 20}\n\tschedulerLock = spinLock{id: 21}\n\tatomicsLock   = spinLock{id: 22}\n\tfutexLock     = spinLock{id: 23}\n)\n\nfunc resetSpinLocks() {\n\tfor i := uint8(0); i < numSpinlocks; i++ {\n\t\tl := &spinLock{id: i}\n\t\tl.spinlock().Set(0)\n\t}\n}\n\n// A hardware spinlock, one of the 32 spinlocks defined in the SIO peripheral.\ntype spinLock struct {\n\tid uint8\n}\n\n// Return the spinlock register: rp.SIO.SPINLOCKx\nfunc (l *spinLock) spinlock() *volatile.Register32 {\n\treturn (*volatile.Register32)(unsafe.Add(unsafe.Pointer(&rp.SIO.SPINLOCK0), l.id*4))\n}\n\nfunc (l *spinLock) Lock() {\n\t// Wait for the lock to be available.\n\tspinlock := l.spinlock()\n\tfor spinlock.Get() == 0 {\n\t\tarm.Asm(\"wfe\")\n\t}\n}\n\nfunc (l *spinLock) Unlock() {\n\tl.spinlock().Set(0)\n\tarm.Asm(\"sev\")\n}\n\n// Wait until a signal is received, indicating that it can resume from the\n// spinloop.\nfunc spinLoopWait() {\n\tarm.Asm(\"wfe\")\n}\n\nfunc waitForEvents() {\n\tarm.Asm(\"wfe\")\n}\n\nfunc putchar(c byte) {\n\tmachine.Serial.WriteByte(c)\n}\n\nfunc getchar() byte {\n\tfor machine.Serial.Buffered() == 0 {\n\t\tGosched()\n\t}\n\tv, _ := machine.Serial.ReadByte()\n\treturn v\n}\n\nfunc buffered() int {\n\treturn machine.Serial.Buffered()\n}\n\n// machineInit is provided by package machine.\nfunc machineInit()\n\nfunc init() {\n\tmachineInit()\n\n\tmachine.InitSerial()\n}\n\nfunc prerun() {\n\t// Reset spinlocks before the full machineInit() so the scheduler doesn't\n\t// hang waiting for schedulerLock after a soft reset.\n\tresetSpinLocks()\n}\n\n//export Reset_Handler\nfunc main() {\n\tpreinit()\n\tprerun()\n\trun()\n\texit(0)\n}\n"
  },
  {
    "path": "src/runtime/runtime_rp2040.go",
    "content": "//go:build rp2040\n\npackage runtime\n\nimport (\n\t\"device/rp\"\n)\n\nconst (\n\tsioIrqFifoProc0 = rp.IRQ_SIO_IRQ_PROC0\n\tsioIrqFifoProc1 = rp.IRQ_SIO_IRQ_PROC1\n)\n"
  },
  {
    "path": "src/runtime/runtime_rp2350.go",
    "content": "//go:build rp2350\n\npackage runtime\n\nimport (\n\t\"device/rp\"\n)\n\nconst (\n\t// On RP2040 each core has a different IRQ number: SIO_IRQ_PROC0 and SIO_IRQ_PROC1.\n\t// On RP2350 both cores share the same irq number (SIO_IRQ_PROC) just with a\n\t// different SIO interrupt output routed to that IRQ input on each core.\n\t// https://www.raspberrypi.com/documentation/pico-sdk/high_level.html#group_pico_multicore_1ga1413ebfa65114c6f408f4675897ac5ee\n\tsioIrqFifoProc0 = rp.IRQ_SIO_IRQ_FIFO\n\tsioIrqFifoProc1 = rp.IRQ_SIO_IRQ_FIFO\n)\n"
  },
  {
    "path": "src/runtime/runtime_stm32.go",
    "content": "//go:build stm32\n\npackage runtime\n\nimport \"device/arm\"\n\n//export Reset_Handler\nfunc main() {\n\tpreinit()\n\trun()\n\texit(0)\n}\n\nfunc waitForEvents() {\n\tarm.Asm(\"wfe\")\n}\n"
  },
  {
    "path": "src/runtime/runtime_stm32_timers.go",
    "content": "//go:build stm32\n\npackage runtime\n\n// This file implements a common implementation of implementing 'ticks' and\n// 'sleep' for STM32 devices. The implementation uses a single timer.  The\n// timer's PWM frequency (controlled by PSC and ARR) are configured for\n// periodic interrupts at 100Hz (TICK_INTR_PERIOD_NS).  The PWM counter\n// register is used for fine-grained resolution (down to ~150ns) with an\n// Output Comparator used for fine-grained sleeps.\n\nimport (\n\t\"device/stm32\"\n\t\"machine\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n)\n\ntype timerInfo struct {\n\tEnableRegister *volatile.Register32\n\tEnableFlag     uint32\n\tDevice         *stm32.TIM_Type\n}\n\nconst (\n\t// All STM32 do a constant 16ns per tick.  This keeps time\n\t// conversion between ticks and ns fast (shift operation)\n\t// at the expense of more complex logic when getting current\n\t// time (which is already slow due to interfacing with hardware)\n\tNS_PER_TICK = 16\n\n\t// For very short sleeps a busy loop is used to avoid race\n\t// conditions where a trigger would take longer to setup than\n\t// the sleep duration.\n\tMAX_BUSY_LOOP_NS = 10e3 // 10us\n\n\t// The period of tick interrupts in nanoseconds\n\tTICK_INTR_PERIOD_NS = 10e6 // 10ms = 100Hz\n\n\t// The number of ticks that happen per overflow interrupt\n\tTICK_PER_INTR = TICK_INTR_PERIOD_NS / NS_PER_TICK\n)\n\nvar (\n\t// Tick count since boot\n\ttickCount volatile.Register64\n\n\t// The timer used for counting ticks\n\ttickTimer *machine.TIM\n\n\t// The max counter value (fractional part)\n\tcountMax uint32\n)\n\nfunc ticksToNanoseconds(ticks timeUnit) int64 {\n\treturn int64(ticks) * NS_PER_TICK\n}\n\nfunc nanosecondsToTicks(ns int64) timeUnit {\n\treturn timeUnit(ns / NS_PER_TICK)\n}\n\n// number of ticks since start.\n//\n//go:linkname ticks runtime.ticks\nfunc ticks() timeUnit {\n\t// For some ways of capturing the time atomically, see this thread:\n\t// https://www.eevblog.com/forum/microcontrollers/correct-timing-by-timer-overflow-count/msg749617/#msg749617\n\t// Here, instead of re-reading the counter register if an overflow has been\n\t// detected, we simply try again because that results in smaller code.\n\tfor {\n\t\tmask := interrupt.Disable()\n\t\tcounter := tickTimer.Count()\n\t\toverflows := uint64(tickCount.Get())\n\t\thasOverflow := tickTimer.Device.SR.HasBits(stm32.TIM_SR_UIF)\n\t\tinterrupt.Restore(mask)\n\n\t\tif hasOverflow {\n\t\t\tcontinue\n\t\t}\n\n\t\treturn timeUnit(overflows*TICK_PER_INTR + countToTicks(counter))\n\t}\n}\n\n//\n// --  Ticks  ---\n//\n\n// Enable the timer used to count ticks.\n//\n// For precise sleeps use a timer with at least one OutputCompare\n// channel otherwise minimum reliable sleep resolution is bounded\n// by TICK_INTR_PERIOD_NS.\n//\n// Typically avoid TIM6 / TIM7 as they often do not include an\n// output comparator.\nfunc initTickTimer(tim *machine.TIM) {\n\ttickTimer = tim\n\ttickTimer.Configure(machine.PWMConfig{Period: TICK_INTR_PERIOD_NS})\n\n\tcountMax = tickTimer.Top()\n\ttickTimer.SetWraparoundInterrupt(handleTick)\n}\n\nfunc handleTick() {\n\t// increment tick count\n\ttickCount.Set(tickCount.Get() + 1)\n}\n\n//\n//  ---  Sleep  ---\n//\n\nfunc sleepTicks(d timeUnit) {\n\t// If there is a scheduler, we sleep until any kind of CPU event up to\n\t// a maximum of the requested sleep duration.\n\t//\n\t// The scheduler will call again if there is nothing to do and a further\n\t// sleep is required.\n\tif hasScheduler {\n\t\ttimerSleep(uint64(d))\n\t\treturn\n\t}\n\n\t// There's no scheduler, so we sleep until at least the requested number\n\t// of ticks has passed.  For short sleeps, this forms a busy loop since\n\t// timerSleep will return immediately.\n\tend := ticks() + d\n\tfor ticks() < end {\n\t\ttimerSleep(uint64(d))\n\t}\n}\n\n// timerSleep sleeps for 'at most' ticks, but possibly less.\nfunc timerSleep(ticks uint64) {\n\t// If the sleep is super-small (<10us), busy loop by returning\n\t// to the scheduler (if any).  This avoids a busy loop here\n\t// that might delay tasks from being scheduled triggered by\n\t// an interrupt (e.g. channels).\n\tif ticksToNanoseconds(timeUnit(ticks)) < MAX_BUSY_LOOP_NS {\n\t\treturn\n\t}\n\n\t// If the sleep is long, the tick interrupt will occur before\n\t// the sleep expires, so just use that.  This routine will be\n\t// called again if the sleep is incomplete.\n\tif ticks >= TICK_PER_INTR {\n\t\twaitForEvents()\n\t\treturn\n\t}\n\n\t// Sleeping for less than one tick interrupt, now see if the\n\t// next tick interrupt will occur before the sleep expires.  If\n\t// so, use that interrupt.  (this routine will be called\n\t// again if sleep is incomplete)\n\tcnt := tickTimer.Count()\n\tticksUntilOverflow := countToTicks(countMax - cnt)\n\tif ticksUntilOverflow <= ticks {\n\t\twaitForEvents()\n\t\treturn\n\t}\n\n\t// The sleep is now known to be:\n\t//  - More than a few CPU cycles\n\t//  - Less than one interrupt period\n\t//  - Expiring before the next interrupt\n\t//\n\t// Setup a PWM channel to trigger an interrupt.\n\t// NOTE: ticks is known to be < MAX_UINT32 at this point.\n\ttickTimer.SetMatchInterrupt(0, handleSleep)\n\ttickTimer.Set(0, cnt+ticksToCount(ticks))\n\n\t// Wait till either the timer or some other event wakes\n\t// up the CPU\n\twaitForEvents()\n\n\t// In case it was not the sleep interrupt that woke the\n\t// CPU, disable the sleep interrupt now.\n\ttickTimer.Unset(0)\n}\n\nfunc handleSleep(ch uint8) {\n\t// Disable the sleep interrupt\n\ttickTimer.Unset(0)\n}\n\nfunc countToTicks(count uint32) uint64 {\n\treturn (uint64(count) * TICK_PER_INTR) / uint64(countMax)\n}\n\nfunc ticksToCount(ticks uint64) uint32 {\n\treturn uint32((ticks * uint64(countMax)) / TICK_PER_INTR)\n}\n"
  },
  {
    "path": "src/runtime/runtime_stm32f103.go",
    "content": "//go:build stm32 && stm32f103\n\npackage runtime\n\nimport (\n\t\"device/stm32\"\n\t\"machine\"\n)\n\nfunc init() {\n\tinitCLK()\n\n\tmachine.InitSerial()\n\n\tinitTickTimer(&machine.TIM4)\n}\n\nfunc putchar(c byte) {\n\tmachine.Serial.WriteByte(c)\n}\n\nfunc getchar() byte {\n\tfor machine.Serial.Buffered() == 0 {\n\t\tGosched()\n\t}\n\tv, _ := machine.Serial.ReadByte()\n\treturn v\n}\n\nfunc buffered() int {\n\treturn machine.Serial.Buffered()\n}\n\n// initCLK sets clock to 72MHz using HSE 8MHz crystal w/ PLL X 9 (8MHz x 9 = 72MHz).\nfunc initCLK() {\n\tstm32.FLASH.ACR.SetBits(stm32.FLASH_ACR_LATENCY_WS2)                            // Two wait states, per datasheet\n\tstm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE1_Div2 << stm32.RCC_CFGR_PPRE1_Pos)   // prescale PCLK1 = HCLK/2\n\tstm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE2_Div1 << stm32.RCC_CFGR_PPRE2_Pos)   // prescale PCLK2 = HCLK/1\n\tstm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_ADCPRE_Div6 << stm32.RCC_CFGR_ADCPRE_Pos) // prescale ADCCLK = PCLK2/6\n\tstm32.RCC.CR.SetBits(stm32.RCC_CR_HSEON)                                        // enable HSE clock\n\n\t// wait for the HSEREADY flag\n\tfor !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSERDY) {\n\t}\n\n\tstm32.RCC.CR.SetBits(stm32.RCC_CR_HSION) // enable HSI clock\n\n\t// wait for the HSIREADY flag\n\tfor !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSIRDY) {\n\t}\n\n\tstm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PLLSRC)                                   // set PLL source to HSE\n\tstm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PLLMUL_Mul9 << stm32.RCC_CFGR_PLLMUL_Pos) // multiply by 9\n\tstm32.RCC.CR.SetBits(stm32.RCC_CR_PLLON)                                        // enable the PLL\n\n\t// wait for the PLLRDY flag\n\tfor !stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) {\n\t}\n\n\tstm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_SW_PLL) // set clock source to pll\n\n\t// wait for PLL to be CLK\n\tfor !stm32.RCC.CFGR.HasBits(stm32.RCC_CFGR_SWS_PLL << stm32.RCC_CFGR_SWS_Pos) {\n\t}\n}\n"
  },
  {
    "path": "src/runtime/runtime_stm32f4.go",
    "content": "//go:build stm32f4 && (stm32f407 || stm32f469)\n\npackage runtime\n\nimport (\n\t\"device/stm32\"\n\t\"machine\"\n)\n\nfunc init() {\n\tinitCLK()\n\n\tmachine.InitSerial()\n\n\tinitTickTimer(&machine.TIM2)\n}\n\nfunc putchar(c byte) {\n\tmachine.Serial.WriteByte(c)\n}\n\nfunc getchar() byte {\n\tfor machine.Serial.Buffered() == 0 {\n\t\tGosched()\n\t}\n\tv, _ := machine.Serial.ReadByte()\n\treturn v\n}\n\nfunc buffered() int {\n\treturn machine.Serial.Buffered()\n}\n\nfunc initCLK() {\n\t// Reset clock registers\n\t// Set HSION\n\tstm32.RCC.CR.SetBits(stm32.RCC_CR_HSION)\n\tfor !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSIRDY) {\n\t}\n\n\t// Reset CFGR\n\tstm32.RCC.CFGR.Set(0x00000000)\n\t// Reset HSEON, CSSON and PLLON\n\tstm32.RCC.CR.ClearBits(stm32.RCC_CR_HSEON | stm32.RCC_CR_CSSON | stm32.RCC_CR_PLLON)\n\t// Reset PLLCFGR\n\tstm32.RCC.PLLCFGR.Set(0x24003010)\n\t// Reset HSEBYP\n\tstm32.RCC.CR.ClearBits(stm32.RCC_CR_HSEBYP)\n\t// Disable all interrupts\n\tstm32.RCC.CIR.Set(0x00000000)\n\n\t// Set up the clock\n\tvar startupCounter uint32 = 0\n\n\t// Enable HSE\n\tstm32.RCC.CR.Set(stm32.RCC_CR_HSEON)\n\n\t// Wait till HSE is ready and if timeout is reached exit\n\tfor {\n\t\tstartupCounter++\n\t\tif stm32.RCC.CR.HasBits(stm32.RCC_CR_HSERDY) || (startupCounter == HSE_STARTUP_TIMEOUT) {\n\t\t\tbreak\n\t\t}\n\t}\n\tif stm32.RCC.CR.HasBits(stm32.RCC_CR_HSERDY) {\n\t\t// Enable high performance mode, configure maximum system frequency.\n\t\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN)\n\t\tstm32.PWR.CR.SetBits(0x4000) // PWR_CR_VOS\n\t\t// HCLK = SYSCLK / 1\n\t\tstm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_HPRE_Div1 << stm32.RCC_CFGR_HPRE_Pos)\n\t\t// PCLK2 = HCLK / 2\n\t\tstm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE2_Div2 << stm32.RCC_CFGR_PPRE2_Pos)\n\t\t// PCLK1 = HCLK / 4\n\t\tstm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE1_Div4 << stm32.RCC_CFGR_PPRE1_Pos)\n\t\t// Configure the main PLL\n\t\tstm32.RCC.PLLCFGR.Set(PLL_CFGR)\n\t\t// Enable main PLL\n\t\tstm32.RCC.CR.SetBits(stm32.RCC_CR_PLLON)\n\t\t// Wait till the main PLL is ready\n\t\tfor (stm32.RCC.CR.Get() & stm32.RCC_CR_PLLRDY) == 0 {\n\t\t}\n\t\t// Configure Flash prefetch, Instruction cache, Data cache and wait state\n\t\tstm32.FLASH.ACR.Set(stm32.FLASH_ACR_ICEN | stm32.FLASH_ACR_DCEN | (5 << stm32.FLASH_ACR_LATENCY_Pos))\n\t\t// Select the main PLL as system clock source\n\t\tstm32.RCC.CFGR.ClearBits(stm32.RCC_CFGR_SW_Msk)\n\t\tstm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_SW_PLL << stm32.RCC_CFGR_SW_Pos)\n\t\tfor (stm32.RCC.CFGR.Get() & stm32.RCC_CFGR_SWS_Msk) != (stm32.RCC_CFGR_SWS_PLL << stm32.RCC_CFGR_SWS_Pos) {\n\t\t}\n\n\t} else {\n\t\t// If HSE failed to start up, the application will have wrong clock configuration\n\t\tfor {\n\t\t}\n\t}\n\n\t// Enable the CCM RAM clock\n\tstm32.RCC.AHB1ENR.SetBits(1 << 20)\n}\n"
  },
  {
    "path": "src/runtime/runtime_stm32f405.go",
    "content": "//go:build stm32f405\n\npackage runtime\n\nimport (\n\t\"device/stm32\"\n\t\"machine\"\n)\n\nconst (\n\t// +----------------------+\n\t// |    Clock Settings    |\n\t// +-------------+--------+\n\t// | HSE         | 12mhz  |\n\t// | SYSCLK      | 168mhz |\n\t// | HCLK        | 168mhz |\n\t// | APB1(PCLK1) | 42mhz  |\n\t// | APB2(PCLK2) | 84mhz  |\n\t// +-------------+--------+\n\tHCLK_FREQ_HZ  = 168000000\n\tPCLK1_FREQ_HZ = HCLK_FREQ_HZ / 4\n\tPCLK2_FREQ_HZ = HCLK_FREQ_HZ / 2\n)\n\nconst (\n\tPWR_SCALE1 = 1 << stm32.PWR_CSR_VOSRDY_Pos // max value of HCLK = 168 MHz\n\tPWR_SCALE2 = 0                             // max value of HCLK = 144 MHz\n\n\tPLL_SRC_HSE = 1 << stm32.RCC_PLLCFGR_PLLSRC_Pos // use HSE for PLL and PLLI2S\n\tPLL_SRC_HSI = 0                                 // use HSI for PLL and PLLI2S\n\n\tPLL_DIV_M = 6 << stm32.RCC_PLLCFGR_PLLM_Pos\n\tPLL_MLT_N = 168 << stm32.RCC_PLLCFGR_PLLN_Pos\n\tPLL_DIV_P = ((2 >> 1) - 1) << stm32.RCC_PLLCFGR_PLLP_Pos\n\tPLL_DIV_Q = 7 << stm32.RCC_PLLCFGR_PLLQ_Pos\n\n\tSYSCLK_SRC_PLL  = stm32.RCC_CFGR_SW_PLL << stm32.RCC_CFGR_SW_Pos\n\tSYSCLK_STAT_PLL = stm32.RCC_CFGR_SWS_PLL << stm32.RCC_CFGR_SWS_Pos\n\n\tRCC_DIV_PCLK1 = stm32.RCC_CFGR_PPRE1_Div4 << stm32.RCC_CFGR_PPRE1_Pos // HCLK / 4\n\tRCC_DIV_PCLK2 = stm32.RCC_CFGR_PPRE2_Div2 << stm32.RCC_CFGR_PPRE2_Pos // HCLK / 2\n\tRCC_DIV_HCLK  = stm32.RCC_CFGR_HPRE_Div1 << stm32.RCC_CFGR_HPRE_Pos   // SYSCLK / 1\n\n\tCLK_CCM_RAM = 1 << 20\n)\n\nconst (\n\t// +-----------------------------------+\n\t// |    Voltage range = 2.7V - 3.6V    |\n\t// +----------------+------------------+\n\t// |   Wait states  |    System Bus    |\n\t// |  (WS, LATENCY) |    HCLK (MHz)    |\n\t// +----------------+------------------+\n\t// | 0 WS, 1 cycle  |   0 < HCLK ≤ 30  |\n\t// | 1 WS, 2 cycles |  30 < HCLK ≤ 60  |\n\t// | 2 WS, 3 cycles |  60 < HCLK ≤ 90  |\n\t// | 3 WS, 4 cycles |  90 < HCLK ≤ 120 |\n\t// | 4 WS, 5 cycles | 120 < HCLK ≤ 150 |\n\t// | 5 WS, 6 cycles | 150 < HCLK ≤ 168 |\n\t// +----------------+------------------+\n\tFLASH_LATENCY = 5 << stm32.FLASH_ACR_LATENCY_Pos // 5 WS (6 CPU cycles)\n\n\t// instruction cache, data cache, and prefetch\n\tFLASH_OPTIONS = stm32.FLASH_ACR_ICEN | stm32.FLASH_ACR_DCEN | stm32.FLASH_ACR_PRFTEN\n)\n\nfunc init() {\n\tinitOSC() // configure oscillators\n\tinitCLK()\n\n\tinitCOM()\n\n\tinitTickTimer(&machine.TIM3)\n}\n\nfunc initOSC() {\n\t// enable voltage regulator\n\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN)\n\tstm32.PWR.CR.SetBits(PWR_SCALE1)\n\n\t// enable HSE\n\tstm32.RCC.CR.Set(stm32.RCC_CR_HSEON)\n\tfor !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSERDY) {\n\t}\n\n\t// Since the main-PLL configuration parameters cannot be changed once PLL is\n\t// enabled, it is recommended to configure PLL before enabling it (selection\n\t// of the HSI or HSE oscillator as PLL clock source, and configuration of\n\t// division factors M, N, P, and Q).\n\n\t// disable PLL and wait for it to reset\n\tstm32.RCC.CR.ClearBits(stm32.RCC_CR_PLLON)\n\tfor stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) {\n\t}\n\n\t// set HSE as PLL source and configure clock divisors\n\tstm32.RCC.PLLCFGR.Set(PLL_SRC_HSE | PLL_DIV_M | PLL_MLT_N | PLL_DIV_P | PLL_DIV_Q)\n\n\t// enable PLL and wait for it to sync\n\tstm32.RCC.CR.SetBits(stm32.RCC_CR_PLLON)\n\tfor !stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) {\n\t}\n}\n\nfunc initCLK() {\n\t// After reset, the CPU clock frequency is 16 MHz and 0 wait state (WS) is\n\t// configured in the FLASH_ACR register.\n\t//\n\t// It is highly recommended to use the following software sequences to tune\n\t// the number of wait states needed to access the Flash memory with the CPU\n\t// frequency.\n\t//\n\t// 1. Program the new number of wait states to the LATENCY bits in the\n\t//    FLASH_ACR register\n\t// 2. Check that the new number of wait states is taken into account to access\n\t//    the Flash memory by reading the FLASH_ACR register\n\t// 3. Modify the CPU clock source by writing the SW bits in the RCC_CFGR\n\t//    register\n\t// 4. If needed, modify the CPU clock prescaler by writing the HPRE bits in\n\t//    RCC_CFGR\n\t// 5. Check that the new CPU clock source or/and the new CPU clock prescaler\n\t//    value is/are taken into account by reading the clock source status (SWS\n\t//    bits) or/and the AHB prescaler value (HPRE bits), respectively, in the\n\t//    RCC_CFGR register.\n\n\t// configure instruction/data caching, prefetch, and flash access wait states\n\tstm32.FLASH.ACR.Set(FLASH_OPTIONS | FLASH_LATENCY)\n\tfor !stm32.FLASH.ACR.HasBits(FLASH_LATENCY) { // verify new wait states\n\t}\n\n\t// After a system reset, the HSI oscillator is selected as the system clock.\n\t// When a clock source is used directly or through PLL as the system clock, it\n\t// is not possible to stop it.\n\t//\n\t// A switch from one clock source to another occurs only if the target clock\n\t// source is ready (clock stable after startup delay or PLL locked). If a\n\t// clock source that is not yet ready is selected, the switch occurs when the\n\t// clock source is ready. Status bits in the RCC clock control register\n\t// (RCC_CR) indicate which clock(s) is (are) ready and which clock is\n\t// currently used as the system clock.\n\n\t// set CPU clock source to PLL\n\tstm32.RCC.CFGR.SetBits(SYSCLK_SRC_PLL)\n\n\t// update PCKL1/2 and HCLK divisors\n\tstm32.RCC.CFGR.SetBits(RCC_DIV_PCLK1 | RCC_DIV_PCLK2 | RCC_DIV_HCLK)\n\n\t// verify system clock source is ready\n\tfor !stm32.RCC.CFGR.HasBits(SYSCLK_STAT_PLL) {\n\t}\n\n\t// enable the CCM RAM clock\n\tstm32.RCC.AHB1ENR.SetBits(CLK_CCM_RAM)\n}\n\nfunc initCOM() {\n\tif machine.NUM_UART_INTERFACES > 0 {\n\t\tmachine.InitSerial()\n\t}\n}\n\nfunc putchar(c byte) {\n\tmachine.Serial.WriteByte(c)\n}\n\nfunc getchar() byte {\n\tfor machine.Serial.Buffered() == 0 {\n\t\tGosched()\n\t}\n\tv, _ := machine.Serial.ReadByte()\n\treturn v\n}\n\nfunc buffered() int {\n\treturn machine.Serial.Buffered()\n}\n"
  },
  {
    "path": "src/runtime/runtime_stm32f407.go",
    "content": "//go:build stm32f4 && stm32f407\n\npackage runtime\n\nimport \"device/stm32\"\n\n/*\nclock settings\n\n\t+-------------+--------+\n\t| HSE         | 8mhz   |\n\t| SYSCLK      | 168mhz |\n\t| HCLK        | 168mhz |\n\t| APB2(PCLK2) | 84mhz  |\n\t| APB1(PCLK1) | 42mhz  |\n\t+-------------+--------+\n*/\nconst (\n\tHSE_STARTUP_TIMEOUT = 0x0500\n\t// PLL Options - See RM0090 Reference Manual pg. 95\n\tPLL_M    = 8 // PLL_VCO = (HSE_VALUE or HSI_VLAUE / PLL_M) * PLL_N\n\tPLL_N    = 336\n\tPLL_P    = 2 // SYSCLK = PLL_VCO / PLL_P\n\tPLL_Q    = 7 // USB OTS FS, SDIO and RNG Clock = PLL_VCO / PLL_Q\n\tPLL_CFGR = PLL_M | (PLL_N << stm32.RCC_PLLCFGR_PLLN_Pos) | (((PLL_P >> 1) - 1) << stm32.RCC_PLLCFGR_PLLP_Pos) |\n\t\t(1 << stm32.RCC_PLLCFGR_PLLSRC_Pos) | (PLL_Q << stm32.RCC_PLLCFGR_PLLQ_Pos)\n)\n"
  },
  {
    "path": "src/runtime/runtime_stm32f469.go",
    "content": "//go:build stm32f4 && stm32f469\n\npackage runtime\n\nimport \"device/stm32\"\n\n/*\nclock settings\n\n\t+-------------+--------+\n\t| HSE         | 8mhz   |\n\t| SYSCLK      | 180mhz |\n\t| HCLK        | 180mhz |\n\t| APB2(PCLK2) | 90mhz  |\n\t| APB1(PCLK1) | 45mhz  |\n\t+-------------+--------+\n*/\nconst (\n\tHSE_STARTUP_TIMEOUT = 0x0500\n\t// PLL Options - See RM0386 Reference Manual pg. 148\n\tPLL_M    = 8 // PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N\n\tPLL_N    = 360\n\tPLL_P    = 2 // SYSCLK = PLL_VCO / PLL_P\n\tPLL_Q    = 7 // USB OTS FS, SDIO and RNG Clock = PLL_VCO / PLL_Q\n\tPLL_R    = 6 // DSI\n\tPLL_CFGR = PLL_M | (PLL_N << stm32.RCC_PLLCFGR_PLLN_Pos) | (((PLL_P >> 1) - 1) << stm32.RCC_PLLCFGR_PLLP_Pos) |\n\t\t(1 << stm32.RCC_PLLCFGR_PLLSRC_Pos) | (PLL_Q << stm32.RCC_PLLCFGR_PLLQ_Pos) | (PLL_R << stm32.RCC_PLLCFGR_PLLR_Pos)\n)\n"
  },
  {
    "path": "src/runtime/runtime_stm32f7x2.go",
    "content": "//go:build stm32 && stm32f7x2\n\npackage runtime\n\nimport (\n\t\"device/stm32\"\n\t\"machine\"\n)\n\n/*\nclock settings\n\n\t+-------------+--------+\n\t| HSE         | 8mhz   |\n\t| SYSCLK      | 216mhz |\n\t| HCLK        | 216mhz |\n\t| APB1(PCLK1) | 27mhz  |\n\t| APB2(PCLK2) | 108mhz |\n\t+-------------+--------+\n*/\nconst (\n\tHSE_STARTUP_TIMEOUT = 0x0500\n\tPLL_M               = 4\n\tPLL_N               = 216\n\tPLL_P               = 2\n\tPLL_Q               = 2\n)\n\nfunc init() {\n\tinitCLK()\n\n\tmachine.InitSerial()\n\n\tinitTickTimer(&machine.TIM3)\n}\n\nfunc putchar(c byte) {\n\tmachine.Serial.WriteByte(c)\n}\n\nfunc getchar() byte {\n\tfor machine.Serial.Buffered() == 0 {\n\t\tGosched()\n\t}\n\tv, _ := machine.Serial.ReadByte()\n\treturn v\n}\n\nfunc buffered() int {\n\treturn machine.Serial.Buffered()\n}\n\nfunc initCLK() {\n\t// PWR_CLK_ENABLE\n\tstm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN)\n\t_ = stm32.RCC.APB1ENR.Get()\n\n\t// PWR_VOLTAGESCALING_CONFIG\n\tstm32.PWR.CR1.ReplaceBits(0x3<<stm32.PWR_CR1_VOS_Pos, stm32.PWR_CR1_VOS_Msk, 0)\n\t_ = stm32.PWR.CR1.Get()\n\n\t// Initialize the High-Speed External Oscillator\n\tinitOsc()\n\n\t// Set flash wait states (min 7 latency units) based on clock\n\tif (stm32.FLASH.ACR.Get() & stm32.FLASH_ACR_LATENCY_Msk) < 7 {\n\t\tstm32.FLASH.ACR.ReplaceBits(7, stm32.FLASH_ACR_LATENCY_Msk, 0)\n\t}\n\n\t// HCLK (0x1C00 = DIV_16, 0x0 = RCC_SYSCLK_DIV1) - ensure timers remain\n\t// within spec as the SYSCLK source changes.\n\tstm32.RCC.CFGR.ReplaceBits(0x00001C00, stm32.RCC_CFGR_PPRE1_Msk, 0)\n\tstm32.RCC.CFGR.ReplaceBits(0x00001C00<<3, stm32.RCC_CFGR_PPRE2_Msk, 0)\n\tstm32.RCC.CFGR.ReplaceBits(0, stm32.RCC_CFGR_HPRE_Msk, 0)\n\n\t// Set SYSCLK source and wait\n\t// (2 = PLLCLK, 3 = RCC_CFGR_SW mask, 3 << 3 = RCC_CFGR_SWS mask)\n\tstm32.RCC.CFGR.ReplaceBits(2, 3, 0)\n\tfor stm32.RCC.CFGR.Get()&(3<<2) != (2 << 2) {\n\t}\n\n\t// Set flash wait states (max 7 latency units) based on clock\n\tif (stm32.FLASH.ACR.Get() & stm32.FLASH_ACR_LATENCY_Msk) > 7 {\n\t\tstm32.FLASH.ACR.ReplaceBits(7, stm32.FLASH_ACR_LATENCY_Msk, 0)\n\t}\n\n\t// Set APB1 and APB2 clocks (0x1800 = DIV8, 0x1000 = DIV2)\n\tstm32.RCC.CFGR.ReplaceBits(0x1800, stm32.RCC_CFGR_PPRE1_Msk, 0)\n\tstm32.RCC.CFGR.ReplaceBits(0x1000<<3, stm32.RCC_CFGR_PPRE2_Msk, 0)\n}\n\nfunc initOsc() {\n\t// Enable HSE, wait until ready\n\tstm32.RCC.CR.SetBits(stm32.RCC_CR_HSEON)\n\tfor !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSERDY) {\n\t}\n\n\t// Disable the PLL, wait until disabled\n\tstm32.RCC.CR.ClearBits(stm32.RCC_CR_PLLON)\n\tfor stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) {\n\t}\n\n\t// Configure the PLL\n\tstm32.RCC.PLLCFGR.Set(0x20000000 |\n\t\t(1 << stm32.RCC_PLLCFGR_PLLSRC_Pos) | // 1 = HSE\n\t\tPLL_M |\n\t\t(PLL_N << stm32.RCC_PLLCFGR_PLLN_Pos) |\n\t\t(((PLL_P >> 1) - 1) << stm32.RCC_PLLCFGR_PLLP_Pos) |\n\t\t(PLL_Q << stm32.RCC_PLLCFGR_PLLQ_Pos))\n\n\t// Enable the PLL, wait until ready\n\tstm32.RCC.CR.SetBits(stm32.RCC_CR_PLLON)\n\tfor !stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) {\n\t}\n}\n"
  },
  {
    "path": "src/runtime/runtime_stm32l0.go",
    "content": "//go:build stm32l0\n\npackage runtime\n\nimport (\n\t\"device/stm32\"\n\t\"machine\"\n)\n\nconst (\n\tRCC_SYSCLK_DIV1 = 0 // Needs SVD update (should be stm32.RCC_SYSCLK_DIV1)\n)\n\nfunc putchar(c byte) {\n\tmachine.Serial.WriteByte(c)\n}\n\nfunc getchar() byte {\n\tfor machine.Serial.Buffered() == 0 {\n\t\tGosched()\n\t}\n\tv, _ := machine.Serial.ReadByte()\n\treturn v\n}\n\nfunc buffered() int {\n\treturn machine.Serial.Buffered()\n}\n\nfunc initCLK() {\n\t// Set Power Regulator to enable max performance (1.8V)\n\tstm32.PWR.CR.ReplaceBits(1<<stm32.PWR_CR_VOS_Pos, stm32.PWR_CR_VOS_Msk, 0)\n\n\t// Calibration (default 0x10)\n\tstm32.RCC.ICSCR.ReplaceBits(0x10<<stm32.RCC_ICSCR_HSI16TRIM_Pos, stm32.RCC_ICSCR_HSI16TRIM_Msk, 0)\n\n\t// Enable the HSI16 oscillator, since the L0 series boots to the MSI one.\n\tstm32.RCC.CR.ReplaceBits(stm32.RCC_CR_HSI16ON, stm32.RCC_CR_HSI16ON_Msk|stm32.RCC_CR_HSI16DIVEN_Msk, 0)\n\n\t// Wait for HSI16 to be ready\n\tfor !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSI16RDYF) {\n\t}\n\n\t// Disable PLL\n\tstm32.RCC.CR.ClearBits(stm32.RCC_CR_PLLON)\n\n\t// Wait for PLL to be disabled\n\tfor stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) {\n\t}\n\n\t// Configure the PLL to use HSI16 with a PLLDIV of 2 and PLLMUL of 4.\n\tstm32.RCC.CFGR.ReplaceBits(\n\t\t(stm32.RCC_CFGR_PLLSRC_HSI16<<stm32.RCC_CFGR_PLLSRC_Pos)|\n\t\t\t(stm32.RCC_CFGR_PLLMUL_Mul4<<stm32.RCC_CFGR_PLLMUL_Pos)|\n\t\t\t(stm32.RCC_CFGR_PLLDIV_Div2<<stm32.RCC_CFGR_PLLDIV_Pos),\n\t\tstm32.RCC_CFGR_PLLSRC_Msk|\n\t\t\tstm32.RCC_CFGR_PLLMUL_Msk|\n\t\t\tstm32.RCC_CFGR_PLLDIV_Msk,\n\t\t0)\n\n\t// Enable PLL\n\tstm32.RCC.CR.SetBits(stm32.RCC_CR_PLLON)\n\n\t// Wait for PLL to be ready\n\tfor !stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) {\n\t}\n\n\t// Adjust flash latency\n\tif FlashLatency > getFlashLatency() {\n\t\tsetFlashLatency(FlashLatency)\n\t\tfor getFlashLatency() != FlashLatency {\n\t\t}\n\t}\n\n\t// HCLK\n\tstm32.RCC.CFGR.ReplaceBits(RCC_SYSCLK_DIV1, stm32.RCC_CFGR_HPRE_Msk, 0)\n\n\t// Use PLL As System clock\n\tstm32.RCC.CFGR.ReplaceBits(stm32.RCC_CFGR_SWS_PLL, stm32.RCC_CFGR_SW_Msk, 0)\n\tfor stm32.RCC.CFGR.Get()&stm32.RCC_CFGR_SW_Msk != stm32.RCC_CFGR_SWS_PLL {\n\t}\n\n\t// Set prescalers so half system clock (PCLKx = HCLK/2)\n\tstm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE1_Div2 << stm32.RCC_CFGR_PPRE1_Pos)\n\tstm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE2_Div2 << stm32.RCC_CFGR_PPRE2_Pos)\n}\n\nfunc getFlashLatency() uint32 {\n\treturn stm32.FLASH.ACR.Get() & stm32.Flash_ACR_LATENCY_Msk\n}\n\nfunc setFlashLatency(l uint32) {\n\tstm32.FLASH.ACR.ReplaceBits(l, stm32.Flash_ACR_LATENCY_Msk, 0)\n}\n"
  },
  {
    "path": "src/runtime/runtime_stm32l0x1.go",
    "content": "//go:build stm32l0x1\n\npackage runtime\n\nimport (\n\t\"device/stm32\"\n\t\"machine\"\n)\n\nconst (\n\tFlashLatency = stm32.Flash_ACR_LATENCY_WS1\n)\n\nfunc init() {\n\tinitCLK()\n\n\tmachine.InitSerial()\n\n\tinitTickTimer(&machine.TIM21)\n}\n"
  },
  {
    "path": "src/runtime/runtime_stm32l0x2.go",
    "content": "//go:build stm32l0x2\n\npackage runtime\n\nimport (\n\t\"device/stm32\"\n\t\"machine\"\n)\n\nconst (\n\tFlashLatency = stm32.Flash_ACR_LATENCY_WS1\n)\n\nfunc init() {\n\tinitCLK()\n\n\tmachine.InitSerial()\n\n\tinitTickTimer(&machine.TIM3)\n}\n"
  },
  {
    "path": "src/runtime/runtime_stm32l4.go",
    "content": "//go:build stm32 && stm32l4\n\npackage runtime\n\nimport (\n\t\"device/stm32\"\n\t\"machine\"\n)\n\nconst (\n\tPWR_CR1_VOS_0                = 1 << stm32.PWR_CR1_VOS_Pos\n\tPWR_CR1_VOS_1                = 2 << stm32.PWR_CR1_VOS_Pos\n\tPWR_REGULATOR_VOLTAGE_SCALE1 = PWR_CR1_VOS_0\n\tPWR_REGULATOR_VOLTAGE_SCALE2 = PWR_CR1_VOS_1\n\n\tFLASH_LATENCY_0 = 0\n\tFLASH_LATENCY_1 = 1\n\tFLASH_LATENCY_2 = 2\n\tFLASH_LATENCY_3 = 3\n\tFLASH_LATENCY_4 = 4\n\n\tRCC_PLLP_DIV2 = 2\n\tRCC_PLLP_DIV7 = 7\n\tRCC_PLLQ_DIV2 = 2\n\tRCC_PLLR_DIV2 = 2\n\n\tRCC_CFGR_SWS_MSI = 0x0\n\tRCC_CFGR_SWS_PLL = 0xC\n\n\tRCC_PLLSOURCE_MSI = 1\n\n\tRCC_PLL_SYSCLK = stm32.RCC_PLLCFGR_PLLREN\n)\n\ntype arrtype = uint32\n\nfunc init() {\n\tinitCLK()\n\n\tmachine.InitSerial()\n\n\tinitTickTimer(&machine.TIM15)\n}\n\nfunc putchar(c byte) {\n\tmachine.Serial.WriteByte(c)\n}\n\nfunc getchar() byte {\n\tfor machine.Serial.Buffered() == 0 {\n\t\tGosched()\n\t}\n\tv, _ := machine.Serial.ReadByte()\n\treturn v\n}\n\nfunc buffered() int {\n\treturn machine.Serial.Buffered()\n}\n\nfunc initCLK() {\n\t// PWR_CLK_ENABLE\n\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_PWREN)\n\t_ = stm32.RCC.APB1ENR1.Get()\n\n\t// Disable Backup domain protection\n\tif !stm32.PWR.CR1.HasBits(stm32.PWR_CR1_DBP) {\n\t\tstm32.PWR.CR1.SetBits(stm32.PWR_CR1_DBP)\n\t\tfor !stm32.PWR.CR1.HasBits(stm32.PWR_CR1_DBP) {\n\t\t}\n\t}\n\n\t// Set LSE Drive to LOW\n\tstm32.RCC.BDCR.ReplaceBits(0, stm32.RCC_BDCR_LSEDRV_Msk, 0)\n\n\t// Initialize the High-Speed External Oscillator\n\tinitOsc()\n\n\t// PWR_VOLTAGESCALING_CONFIG\n\tstm32.PWR.CR1.ReplaceBits(0, stm32.PWR_CR1_VOS_Msk, 0)\n\t_ = stm32.PWR.CR1.Get()\n\n\t// Set flash wait states (min 5 latency units) based on clock\n\tif (stm32.FLASH.ACR.Get() & 0xF) < 5 {\n\t\tstm32.FLASH.ACR.ReplaceBits(5, 0xF, 0)\n\t}\n\n\t// Ensure HCLK does not exceed max during transition\n\tstm32.RCC.CFGR.ReplaceBits(8<<stm32.RCC_CFGR_HPRE_Pos, stm32.RCC_CFGR_HPRE_Msk, 0)\n\n\t// Set SYSCLK source and wait\n\t// (3 = RCC_SYSCLKSOURCE_PLLCLK, 2=RCC_CFGR_SWS_Pos)\n\tstm32.RCC.CFGR.ReplaceBits(3, stm32.RCC_CFGR_SW_Msk, 0)\n\tfor stm32.RCC.CFGR.Get()&(3<<2) != (3 << 2) {\n\t}\n\n\t// Set HCLK\n\t// (0 = RCC_SYSCLKSOURCE_PLLCLK)\n\tstm32.RCC.CFGR.ReplaceBits(0, stm32.RCC_CFGR_HPRE_Msk, 0)\n\n\t// Set flash wait states (max 5 latency units) based on clock\n\tif (stm32.FLASH.ACR.Get() & 0xF) > 5 {\n\t\tstm32.FLASH.ACR.ReplaceBits(5, 0xF, 0)\n\t}\n\n\t// Set APB1 and APB2 clocks (0 = DIV1)\n\tstm32.RCC.CFGR.ReplaceBits(0, stm32.RCC_CFGR_PPRE1_Msk, 0)\n\tstm32.RCC.CFGR.ReplaceBits(0, stm32.RCC_CFGR_PPRE2_Msk, 0)\n}\n\nfunc initOsc() {\n\tsysclkSource := stm32.RCC.CFGR.Get() & stm32.RCC_CFGR_SWS_Msk\n\tpllConfig := stm32.RCC.PLLCFGR.Get() & stm32.RCC_PLLCFGR_PLLSRC_Msk\n\n\t// Enable MSI, adjusting flash latency\n\tif sysclkSource == RCC_CFGR_SWS_MSI ||\n\t\t(sysclkSource == RCC_CFGR_SWS_PLL && pllConfig == RCC_PLLSOURCE_MSI) {\n\t\tif MSIRANGE > getMSIRange() {\n\t\t\tsetFlashLatencyFromMSIRange(MSIRANGE)\n\n\t\t\tsetMSIFreq(MSIRANGE, 0)\n\t\t} else {\n\t\t\tsetMSIFreq(MSIRANGE, 0)\n\n\t\t\tif sysclkSource == RCC_CFGR_SWS_MSI {\n\t\t\t\tsetFlashLatencyFromMSIRange(MSIRANGE)\n\t\t\t}\n\t\t}\n\t} else {\n\t\tstm32.RCC.CR.SetBits(stm32.RCC_CR_MSION)\n\t\tfor !stm32.RCC.CR.HasBits(stm32.RCC_CR_MSIRDY) {\n\t\t}\n\n\t\tsetMSIFreq(MSIRANGE, 0)\n\t}\n\n\t// Enable LSE, wait until ready\n\tstm32.RCC.BDCR.SetBits(stm32.RCC_BDCR_LSEON)\n\tfor !stm32.RCC.BDCR.HasBits(stm32.RCC_BDCR_LSEON) {\n\t}\n\n\t// Disable the PLL, wait until disabled\n\tstm32.RCC.CR.ClearBits(stm32.RCC_CR_PLLON)\n\tfor stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) {\n\t}\n\n\t// Configure the PLL\n\tstm32.RCC.PLLCFGR.ReplaceBits(\n\t\t(1)| // 1 = RCC_PLLSOURCE_MSI\n\t\t\t(PLL_M-1)<<stm32.RCC_PLLCFGR_PLLM_Pos|\n\t\t\t(PLL_N<<stm32.RCC_PLLCFGR_PLLN_Pos)|\n\t\t\t(((PLL_Q>>1)-1)<<stm32.RCC_PLLCFGR_PLLQ_Pos)|\n\t\t\t(((PLL_R>>1)-1)<<stm32.RCC_PLLCFGR_PLLR_Pos)|\n\t\t\t(PLL_P<<stm32.RCC_PLLCFGR_PLLP_Pos),\n\t\tstm32.RCC_PLLCFGR_PLLSRC_Msk|stm32.RCC_PLLCFGR_PLLM_Msk|\n\t\t\tstm32.RCC_PLLCFGR_PLLN_Msk|stm32.RCC_PLLCFGR_PLLP_Msk|\n\t\t\tstm32.RCC_PLLCFGR_PLLR_Msk|stm32.RCC_PLLCFGR_PLLP_Msk,\n\t\t0)\n\n\t// Enable the PLL and PLL System Clock Output, wait until ready\n\tstm32.RCC.CR.SetBits(stm32.RCC_CR_PLLON)\n\tstm32.RCC.PLLCFGR.SetBits(stm32.RCC_PLLCFGR_PLLREN) // = RCC_PLL_SYSCLK\n\tfor !stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) {\n\t}\n\n\t// Enable system clock output\n\tstm32.RCC.PLLCFGR.SetBits(RCC_PLL_SYSCLK)\n}\n\nfunc getMSIRange() uint32 {\n\tif stm32.RCC.CR.HasBits(stm32.RCC_CR_MSIRGSEL) {\n\t\treturn (stm32.RCC.CR.Get() & stm32.RCC_CR_MSIRANGE_Msk) >> stm32.RCC_CR_MSIRANGE_Pos\n\t}\n\n\treturn (stm32.RCC.CSR.Get() & stm32.RCC_CSR_MSISRANGE_Msk) >> stm32.RCC_CSR_MSISRANGE_Pos\n}\n\nfunc setMSIFreq(r uint32, calibration uint32) {\n\tstm32.RCC.CR.SetBits(stm32.RCC_CR_MSIRGSEL)\n\tstm32.RCC.CR.ReplaceBits(r<<stm32.RCC_CR_MSIRANGE_Pos, stm32.RCC_CR_MSIRANGE_Msk, 0)\n\n\tstm32.RCC.ICSCR.ReplaceBits(calibration<<stm32.RCC_ICSCR_MSITRIM_Pos, stm32.RCC_ICSCR_MSITRIM_Msk, 0)\n}\n\nfunc setFlashLatencyFromMSIRange(r uint32) {\n\tvar vos uint32\n\tif pwrIsClkEnabled() {\n\t\tvos = pwrExGetVoltageRange()\n\t} else {\n\t\tpwrClkEnable()\n\t\tvos = pwrExGetVoltageRange()\n\t\tpwrClkDisable()\n\t}\n\n\tlatency := uint32(FLASH_LATENCY_0)\n\tif vos == PWR_REGULATOR_VOLTAGE_SCALE1 {\n\t\tif r > stm32.RCC_CR_MSIRANGE_Range16M {\n\t\t\tif r > stm32.RCC_CR_MSIRANGE_Range32M {\n\t\t\t\tlatency = FLASH_LATENCY_2\n\t\t\t} else {\n\t\t\t\tlatency = FLASH_LATENCY_1\n\t\t\t}\n\t\t}\n\t} else if r > stm32.RCC_CR_MSIRANGE_Range16M {\n\t\tlatency = FLASH_LATENCY_3\n\t} else {\n\t\tif r == stm32.RCC_CR_MSIRANGE_Range16M {\n\t\t\tlatency = FLASH_LATENCY_2\n\t\t} else if r == stm32.RCC_CR_MSIRANGE_Range8M {\n\t\t\tlatency = FLASH_LATENCY_1\n\t\t}\n\t}\n\n\tstm32.FLASH.ACR.ReplaceBits(latency, stm32.Flash_ACR_LATENCY_Msk, 0)\n}\n\nfunc pwrIsClkEnabled() bool {\n\treturn stm32.RCC.APB1ENR1.HasBits(stm32.RCC_APB1ENR1_PWREN)\n}\n\nfunc pwrClkEnable() {\n\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_PWREN)\n}\nfunc pwrClkDisable() {\n\tstm32.RCC.APB1ENR1.ClearBits(stm32.RCC_APB1ENR1_PWREN)\n}\n\nfunc pwrExGetVoltageRange() uint32 {\n\treturn stm32.PWR.CR1.Get() & stm32.PWR_CR1_VOS_Msk\n}\n"
  },
  {
    "path": "src/runtime/runtime_stm32l4x2.go",
    "content": "//go:build stm32 && stm32l4x2\n\npackage runtime\n\nimport (\n\t\"device/stm32\"\n)\n\n/*\nclock settings\n\n\t+-------------+-----------+\n\t| LSE         | 32.768khz |\n\t| SYSCLK      | 80mhz     |\n\t| HCLK        | 80mhz     |\n\t| APB1(PCLK1) | 80mhz     |\n\t| APB2(PCLK2) | 80mhz     |\n\t+-------------+-----------+\n*/\nconst (\n\tHSE_STARTUP_TIMEOUT = 0x0500\n\tPLL_M               = 1\n\tPLL_N               = 40\n\tPLL_P               = RCC_PLLP_DIV7\n\tPLL_Q               = RCC_PLLQ_DIV2\n\tPLL_R               = RCC_PLLR_DIV2\n\n\tMSIRANGE = stm32.RCC_CR_MSIRANGE_Range4M\n)\n"
  },
  {
    "path": "src/runtime/runtime_stm32l4x5.go",
    "content": "//go:build stm32 && stm32l4x5\n\npackage runtime\n\nimport (\n\t\"device/stm32\"\n)\n\n/*\nclock settings\n\n\t+-------------+-----------+\n\t| LSE         | 32.768khz |\n\t| SYSCLK      | 120mhz    |\n\t| HCLK        | 120mhz    |\n\t| APB1(PCLK1) | 120mhz    |\n\t| APB2(PCLK2) | 120mhz    |\n\t+-------------+-----------+\n*/\nconst (\n\tHSE_STARTUP_TIMEOUT = 0x0500\n\tPLL_M               = 1\n\tPLL_N               = 60\n\tPLL_P               = RCC_PLLP_DIV2\n\tPLL_Q               = RCC_PLLQ_DIV2\n\tPLL_R               = RCC_PLLR_DIV2\n\n\tMSIRANGE = stm32.RCC_CR_MSIRANGE_Range4M\n)\n"
  },
  {
    "path": "src/runtime/runtime_stm32l4x6.go",
    "content": "//go:build stm32 && stm32l4x6\n\npackage runtime\n\nimport (\n\t\"device/stm32\"\n)\n\n/*\nclock settings\n\n\t+-------------+-----------+\n\t| LSE         | 32.768khz |\n\t| SYSCLK      | 80mhz    |\n\t| HCLK        | 80mhz    |\n\t| APB1(PCLK1) | 80mhz    |\n\t| APB2(PCLK2) | 80mhz    |\n\t+-------------+-----------+\n*/\nconst (\n\tHSE_STARTUP_TIMEOUT = 0x0500\n\tPLL_M               = 1\n\tPLL_N               = 40\n\tPLL_P               = RCC_PLLP_DIV7\n\tPLL_Q               = RCC_PLLQ_DIV2\n\tPLL_R               = RCC_PLLR_DIV2\n\n\tMSIRANGE = stm32.RCC_CR_MSIRANGE_Range4M\n)\n"
  },
  {
    "path": "src/runtime/runtime_stm32l5x2.go",
    "content": "//go:build stm32 && stm32l5x2\n\npackage runtime\n\nimport (\n\t\"device/stm32\"\n\t\"machine\"\n)\n\n/*\nclock settings\n\n\t+-------------+-----------+\n\t| LSE         | 32.768khz |\n\t| SYSCLK      | 110mhz    |\n\t| HCLK        | 110mhz    |\n\t| APB1(PCLK1) | 110mhz    |\n\t| APB2(PCLK2) | 110mhz    |\n\t+-------------+-----------+\n*/\nconst (\n\tHSE_STARTUP_TIMEOUT = 0x0500\n\tPLL_M               = 1\n\tPLL_N               = 55\n\tPLL_P               = 7 // RCC_PLLP_DIV7\n\tPLL_Q               = 2 // RCC_PLLQ_DIV2\n\tPLL_R               = 2 // RCC_PLLR_DIV2\n)\n\nfunc init() {\n\tinitCLK()\n\n\tmachine.InitSerial()\n\n\tinitTickTimer(&machine.TIM16)\n}\n\nfunc putchar(c byte) {\n\tmachine.Serial.WriteByte(c)\n}\n\nfunc getchar() byte {\n\tfor machine.Serial.Buffered() == 0 {\n\t\tGosched()\n\t}\n\tv, _ := machine.Serial.ReadByte()\n\treturn v\n}\n\nfunc buffered() int {\n\treturn machine.Serial.Buffered()\n}\n\nfunc initCLK() {\n\n\t// PWR_CLK_ENABLE\n\tstm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_PWREN)\n\t_ = stm32.RCC.APB1ENR1.Get()\n\n\t// PWR_VOLTAGESCALING_CONFIG\n\tstm32.PWR.CR1.ReplaceBits(0, stm32.PWR_CR1_VOS_Msk, 0)\n\t_ = stm32.PWR.CR1.Get()\n\n\t// Initialize the High-Speed External Oscillator\n\tinitOsc()\n\n\t// Set flash wait states (min 5 latency units) based on clock\n\tif (stm32.FLASH.ACR.Get() & 0xF) < 5 {\n\t\tstm32.FLASH.ACR.ReplaceBits(5, 0xF, 0)\n\t}\n\n\t// Ensure HCLK does not exceed max during transition\n\tstm32.RCC.CFGR.ReplaceBits(8<<stm32.RCC_CFGR_HPRE_Pos, stm32.RCC_CFGR_HPRE_Msk, 0)\n\n\t// Set SYSCLK source and wait\n\t// (3 = RCC_SYSCLKSOURCE_PLLCLK, 2=RCC_CFGR_SWS_Pos)\n\tstm32.RCC.CFGR.ReplaceBits(3, stm32.RCC_CFGR_SW_Msk, 0)\n\tfor stm32.RCC.CFGR.Get()&(3<<2) != (3 << 2) {\n\t}\n\n\t// Set HCLK\n\t// (0 = RCC_SYSCLKSOURCE_PLLCLK)\n\tstm32.RCC.CFGR.ReplaceBits(0, stm32.RCC_CFGR_HPRE_Msk, 0)\n\n\t// Set flash wait states (max 5 latency units) based on clock\n\tif (stm32.FLASH.ACR.Get() & 0xF) > 5 {\n\t\tstm32.FLASH.ACR.ReplaceBits(5, 0xF, 0)\n\t}\n\n\t// Set APB1 and APB2 clocks (0 = DIV1)\n\tstm32.RCC.CFGR.ReplaceBits(0, stm32.RCC_CFGR_PPRE1_Msk, 0)\n\tstm32.RCC.CFGR.ReplaceBits(0, stm32.RCC_CFGR_PPRE2_Msk, 0)\n}\n\nfunc initOsc() {\n\t// Enable HSI, wait until ready\n\tstm32.RCC.CR.SetBits(stm32.RCC_CR_HSION)\n\tfor !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSIRDY) {\n\t}\n\n\t// Disable Backup domain protection\n\tif !stm32.PWR.CR1.HasBits(stm32.PWR_CR1_DBP) {\n\t\tstm32.PWR.CR1.SetBits(stm32.PWR_CR1_DBP)\n\t\tfor !stm32.PWR.CR1.HasBits(stm32.PWR_CR1_DBP) {\n\t\t}\n\t}\n\n\t// Set LSE Drive to LOW\n\tstm32.RCC.BDCR.ReplaceBits(0, stm32.RCC_BDCR_LSEDRV_Msk, 0)\n\n\t// Enable LSE, wait until ready\n\tstm32.RCC.BDCR.SetBits(stm32.RCC_BDCR_LSEON)\n\tfor !stm32.RCC.BDCR.HasBits(stm32.RCC_BDCR_LSEON) {\n\t}\n\n\t// Ensure LSESYS disabled\n\tstm32.RCC.BDCR.ClearBits(stm32.RCC_BDCR_LSESYSEN)\n\tfor stm32.RCC.BDCR.HasBits(stm32.RCC_BDCR_LSESYSEN) {\n\t}\n\n\t// Enable HSI48, wait until ready\n\tstm32.RCC.CRRCR.SetBits(stm32.RCC_CRRCR_HSI48ON)\n\tfor !stm32.RCC.CRRCR.HasBits(stm32.RCC_CRRCR_HSI48ON) {\n\t}\n\n\t// Disable the PLL, wait until disabled\n\tstm32.RCC.CR.ClearBits(stm32.RCC_CR_PLLON)\n\tfor stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) {\n\t}\n\n\t// Configure the PLL\n\tstm32.RCC.PLLCFGR.ReplaceBits(\n\t\t(1)| // 1 = RCC_PLLSOURCE_MSI\n\t\t\t(PLL_M-1)<<stm32.RCC_PLLCFGR_PLLM_Pos|\n\t\t\t(PLL_N<<stm32.RCC_PLLCFGR_PLLN_Pos)|\n\t\t\t(((PLL_Q>>1)-1)<<stm32.RCC_PLLCFGR_PLLQ_Pos)|\n\t\t\t(((PLL_R>>1)-1)<<stm32.RCC_PLLCFGR_PLLR_Pos)|\n\t\t\t(PLL_P<<stm32.RCC_PLLCFGR_PLLPDIV_Pos),\n\t\tstm32.RCC_PLLCFGR_PLLSRC_Msk|stm32.RCC_PLLCFGR_PLLM_Msk|\n\t\t\tstm32.RCC_PLLCFGR_PLLN_Msk|stm32.RCC_PLLCFGR_PLLP_Msk|\n\t\t\tstm32.RCC_PLLCFGR_PLLR_Msk|stm32.RCC_PLLCFGR_PLLPDIV_Msk,\n\t\t0)\n\n\t// Enable the PLL and PLL System Clock Output, wait until ready\n\tstm32.RCC.CR.SetBits(stm32.RCC_CR_PLLON)\n\tstm32.RCC.PLLCFGR.SetBits(stm32.RCC_PLLCFGR_PLLREN) // = RCC_PLL_SYSCLK\n\tfor !stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) {\n\t}\n\n}\n"
  },
  {
    "path": "src/runtime/runtime_stm32wlx.go",
    "content": "//go:build stm32wlx\n\npackage runtime\n\nimport (\n\t\"device/stm32\"\n\t\"machine\"\n)\n\nconst (\n\t/* PLL Options RMN0461.p247 */\n\tPLL_M = 2\n\tPLL_N = 6\n\tPLL_R = 2\n\tPLL_P = 2\n\tPLL_Q = 2\n)\n\nfunc init() {\n\n\t// Configure 48Mhz clock\n\tinitCLK()\n\n\t// Timers init\n\tinitTickTimer(&machine.TIM1)\n\n\t// UART init\n\tmachine.InitSerial()\n}\n\nfunc initCLK() {\n\n\t// Enable HSE32 VDDTCXO output on package pin PB0-VDDTCXO\n\tstm32.RCC.CR.ReplaceBits(stm32.RCC_CR_HSEBYPPWR_VDDTCXO, stm32.RCC_CR_HSEBYPPWR_Msk, 0)\n\n\t// SYSCLOCK from HSE32 clock division factor (SYSCLOCK=HSE32)\n\tstm32.RCC.CR.ReplaceBits(stm32.RCC_CR_HSEPRE_Div1, stm32.RCC_CR_HSEPRE_Msk, 0)\n\n\t// enable external Clock HSE32 TXCO (RM0461p226)\n\tstm32.RCC.CR.SetBits(stm32.RCC_CR_HSEBYPPWR)\n\tstm32.RCC.CR.SetBits(stm32.RCC_CR_HSEON)\n\tfor !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSERDY) {\n\t}\n\n\t// Disable PLL\n\tstm32.RCC.CR.ClearBits(stm32.RCC_CR_PLLON)\n\tfor stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) {\n\t}\n\n\t// Configure the PLL\n\tstm32.RCC.PLLCFGR.Set((PLL_M-1)<<stm32.RCC_PLLCFGR_PLLM_Pos |\n\t\t((PLL_N) << stm32.RCC_PLLCFGR_PLLN_Pos) |\n\t\t((PLL_Q - 1) << stm32.RCC_PLLCFGR_PLLQ_Pos) |\n\t\t((PLL_R - 1) << stm32.RCC_PLLCFGR_PLLR_Pos) |\n\t\t((PLL_P - 1) << stm32.RCC_PLLCFGR_PLLP_Pos) |\n\t\tstm32.RCC_PLLCFGR_PLLSRC_HSE32 | stm32.RCC_PLLCFGR_PLLPEN | stm32.RCC_PLLCFGR_PLLQEN)\n\n\t// Enable PLL\n\tstm32.RCC.CR.SetBits(stm32.RCC_CR_PLLON)\n\tfor !stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) {\n\t}\n\n\t// Enable PLL System Clock output.\n\tstm32.RCC.PLLCFGR.SetBits(stm32.RCC_PLLCFGR_PLLREN)\n\tfor !stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) {\n\t}\n\n\t// Set Flash Latency of 2\n\tstm32.FLASH.ACR.ReplaceBits(stm32.Flash_ACR_LATENCY_WS2, stm32.Flash_ACR_LATENCY_Msk, 0)\n\tfor (stm32.FLASH.ACR.Get() & stm32.Flash_ACR_LATENCY_Msk) != stm32.Flash_ACR_LATENCY_WS2 {\n\t}\n\n\t// HCLK1 clock division factor\n\tstm32.RCC.CFGR.ReplaceBits(stm32.RCC_CFGR_HPRE_Div1, stm32.RCC_CFGR_HPRE_Msk, 0)\n\tfor !stm32.RCC.CFGR.HasBits(stm32.RCC_CFGR_HPREF) {\n\t}\n\n\t// HCLK3 clock division factor\n\tstm32.RCC.EXTCFGR.ReplaceBits(stm32.RCC_EXTCFGR_SHDHPRE_Div1, stm32.RCC_EXTCFGR_SHDHPRE_Msk, 0)\n\tfor !stm32.RCC.EXTCFGR.HasBits(stm32.RCC_EXTCFGR_SHDHPREF) {\n\t}\n\n\t// PCLK1 clock division factor\n\tstm32.RCC.CFGR.ReplaceBits(stm32.RCC_CFGR_PPRE1_Div1, stm32.RCC_CFGR_PPRE1_Msk, 0)\n\tfor !stm32.RCC.CFGR.HasBits(stm32.RCC_CFGR_PPRE1F) {\n\t}\n\n\t// PCLK2 clock division factor\n\tstm32.RCC.CFGR.ReplaceBits(stm32.RCC_CFGR_PPRE2_Div1, stm32.RCC_CFGR_PPRE2_Msk, 0)\n\tfor !stm32.RCC.CFGR.HasBits(stm32.RCC_CFGR_PPRE2F) {\n\t}\n\n\t// Set clock source to PLL\n\tstm32.RCC.CFGR.ReplaceBits(stm32.RCC_CFGR_SW_PLLR, stm32.RCC_CFGR_SW_Msk, 0)\n\tfor (stm32.RCC.CFGR.Get() & stm32.RCC_CFGR_SWS_Msk) != (stm32.RCC_CFGR_SWS_PLLR << stm32.RCC_CFGR_SWS_Pos) {\n\t}\n\n}\n\nfunc putchar(c byte) {\n\tmachine.Serial.WriteByte(c)\n}\n\nfunc getchar() byte {\n\tfor machine.Serial.Buffered() == 0 {\n\t\tGosched()\n\t}\n\tv, _ := machine.Serial.ReadByte()\n\treturn v\n}\n\nfunc buffered() int {\n\treturn machine.Serial.Buffered()\n}\n"
  },
  {
    "path": "src/runtime/runtime_tinygoriscv.go",
    "content": "//go:build tinygo.riscv32\n\npackage runtime\n\nimport \"unsafe\"\n\n//go:extern _sbss\nvar _sbss [0]byte\n\n//go:extern _ebss\nvar _ebss [0]byte\n\n//go:extern _sdata\nvar _sdata [0]byte\n\n//go:extern _sidata\nvar _sidata [0]byte\n\n//go:extern _edata\nvar _edata [0]byte\n\nfunc preinit() {\n\t// Initialize .bss: zero-initialized global variables.\n\tptr := unsafe.Pointer(&_sbss)\n\tfor ptr != unsafe.Pointer(&_ebss) {\n\t\t*(*uint32)(ptr) = 0\n\t\tptr = unsafe.Add(ptr, 4)\n\t}\n\n\t// Initialize .data: global variables initialized from flash.\n\tsrc := unsafe.Pointer(&_sidata)\n\tdst := unsafe.Pointer(&_sdata)\n\tfor dst != unsafe.Pointer(&_edata) {\n\t\t*(*uint32)(dst) = *(*uint32)(src)\n\t\tdst = unsafe.Add(dst, 4)\n\t\tsrc = unsafe.Add(src, 4)\n\t}\n}\n"
  },
  {
    "path": "src/runtime/runtime_tinygoriscv64.go",
    "content": "//go:build tinygo.riscv64\n\npackage runtime\n\nimport \"unsafe\"\n\n//go:extern _sbss\nvar _sbss [0]byte\n\n//go:extern _ebss\nvar _ebss [0]byte\n\n//go:extern _sdata\nvar _sdata [0]byte\n\n//go:extern _sidata\nvar _sidata [0]byte\n\n//go:extern _edata\nvar _edata [0]byte\n\nfunc preinit() {\n\t// Initialize .bss: zero-initialized global variables.\n\tptr := unsafe.Pointer(&_sbss)\n\tfor ptr != unsafe.Pointer(&_ebss) {\n\t\t*(*uint64)(ptr) = 0\n\t\tptr = unsafe.Add(ptr, 8)\n\t}\n\n\t// Initialize .data: global variables initialized from flash.\n\tsrc := unsafe.Pointer(&_sidata)\n\tdst := unsafe.Pointer(&_sdata)\n\tfor dst != unsafe.Pointer(&_edata) {\n\t\t*(*uint64)(dst) = *(*uint64)(src)\n\t\tdst = unsafe.Add(dst, 8)\n\t\tsrc = unsafe.Add(src, 8)\n\t}\n}\n"
  },
  {
    "path": "src/runtime/runtime_tinygoriscv_qemu.go",
    "content": "//go:build tinygo.riscv && virt && qemu\n\npackage runtime\n\nimport (\n\t\"device/riscv\"\n\t\"internal/task\"\n\t\"math/bits\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n\t\"sync/atomic\"\n\t\"unsafe\"\n)\n\n// This file implements the VirtIO RISC-V interface implemented in QEMU, which\n// is an interface designed for emulation.\n\nconst numCPU = 4\n\n//export main\nfunc main() {\n\t// Set the interrupt address.\n\t// Note that this address must be aligned specially, otherwise the MODE bits\n\t// of MTVEC won't be zero.\n\triscv.MTVEC.Set(uintptr(unsafe.Pointer(&handleInterruptASM)))\n\n\t// Enable software interrupts. We'll need them to wake up other cores.\n\triscv.MIE.SetBits(riscv.MIE_MSIE)\n\n\t// If we're not hart 0, wait until we get the signal everything has been set\n\t// up.\n\tif hartID := riscv.MHARTID.Get(); hartID != 0 {\n\t\t// Wait until we get the signal this hart is ready to start.\n\t\t// Note that interrupts are disabled, which means that the interrupt\n\t\t// isn't actually taken. But we can still wait for it using wfi.\n\t\t// If the cores scheduler is not used, we'll stay in this state forever.\n\t\tfor riscv.MIP.Get()&riscv.MIP_MSIP == 0 {\n\t\t\triscv.Asm(\"wfi\")\n\t\t}\n\n\t\t// Clear the software interrupt.\n\t\taclintMSWI.MSIP[hartID].Set(0)\n\n\t\t// Now that we've cleared the software interrupt, we can enable\n\t\t// interrupts as was already done on hart 0.\n\t\triscv.MSTATUS.SetBits(riscv.MSTATUS_MIE)\n\n\t\t// Also enable timer interrupts, for sleepTicksMulticore.\n\t\triscv.MIE.SetBits(riscv.MIE_MTIE)\n\n\t\t// Now start running the scheduler on this core.\n\t\tschedulerLock.Lock()\n\t\tscheduler(false)\n\n\t\t// The scheduler exited, which means main returned and the program\n\t\t// should exit immediately.\n\t\t// Signal hart 0 to exit.\n\t\texitCodePlusOne.Store(0 + 1) // exit code 0\n\t\taclintMSWI.MSIP[0].Set(1)\n\n\t\t// Unlock the scheduler to be sure. Shouldn't be needed.\n\t\tschedulerLock.Unlock()\n\n\t\t// Wait until hart 0 actually exits.\n\t\tfor {\n\t\t\triscv.Asm(\"wfi\")\n\t\t}\n\t}\n\n\t// Enable global interrupts now that they've been set up.\n\t// This is currently only for timer interrupts.\n\triscv.MSTATUS.SetBits(riscv.MSTATUS_MIE)\n\n\t// Set all MTIMECMP registers to a value that clears the MTIP bit in MIP.\n\t// If we don't do this, the wfi instruction won't work as expected.\n\tfor i := 0; i < numCPU; i++ {\n\t\taclintMTIMECMP[i].Set(0xffff_ffff_ffff_ffff)\n\t}\n\n\t// Enable timer interrupts on hart 0.\n\triscv.MIE.SetBits(riscv.MIE_MTIE)\n\n\trun()\n\texit(0)\n}\n\n//go:extern handleInterruptASM\nvar handleInterruptASM [0]uintptr\n\n//export handleInterrupt\nfunc handleInterrupt() {\n\tcause := riscv.MCAUSE.Get()\n\tcode := uint(cause &^ (1 << 31))\n\tif cause&(1<<31) != 0 {\n\t\t// Topmost bit is set, which means that it is an interrupt.\n\t\thartID := currentCPU()\n\t\tswitch code {\n\t\tcase riscv.MachineSoftwareInterrupt:\n\t\t\tif exitCodePlusOne.Load() != 0 {\n\t\t\t\texitNow(exitCodePlusOne.Load() - 1)\n\t\t\t}\n\t\t\tif gcScanState.Load() != 0 {\n\t\t\t\t// The GC needs to run.\n\t\t\t\tgcInterruptHandler(hartID)\n\t\t\t}\n\t\t\tcheckpoint := &schedulerWaitCheckpoints[hartID]\n\t\t\tif checkpoint.Saved() {\n\t\t\t\taclintMSWI.MSIP[hartID].Set(0)\n\t\t\t\triscv.MCAUSE.Set(0)\n\t\t\t\tcheckpoint.Jump()\n\t\t\t}\n\t\tcase riscv.MachineTimerInterrupt:\n\t\t\tif sleepCheckpoint.Saved() {\n\t\t\t\t// Set MTIMECMP to a high value so that MTIP goes low.\n\t\t\t\taclintMTIMECMP[hartID].Set(0xffff_ffff_ffff_ffff)\n\t\t\t\triscv.MCAUSE.Set(0)\n\t\t\t\tsleepCheckpoint.Jump()\n\t\t\t}\n\t\tdefault:\n\t\t\truntimePanic(\"unknown interrupt\")\n\t\t\tabort()\n\t\t}\n\t} else {\n\t\t// Topmost bit is clear, so it is an exception of some sort.\n\t\t// We could implement support for unsupported instructions here (such as\n\t\t// misaligned loads). However, for now we'll just print a fatal error.\n\t\thandleException(code)\n\t}\n\n\t// Zero MCAUSE so that it can later be used to see whether we're in an\n\t// interrupt or not.\n\triscv.MCAUSE.Set(0)\n}\n\n// The GC interrupted this core for the stop-the-world phase.\n// This function handles that, and only returns after the stop-the-world phase\n// ended.\nfunc gcInterruptHandler(hartID uint32) {\n\t// *only* enable the MSIE interrupt\n\tsavedMIE := riscv.MIE.Get()\n\triscv.MIE.Set(riscv.MIE_MSIE)\n\n\t// Disable this interrupt (to be enabled again soon).\n\taclintMSWI.MSIP[hartID].Set(0)\n\n\t// Let the GC know we're ready.\n\tgcScanState.Add(1)\n\n\t// Wait until we get a signal to start scanning.\n\tfor riscv.MIP.Get()&riscv.MIP_MSIP == 0 {\n\t\triscv.Asm(\"wfi\")\n\t}\n\taclintMSWI.MSIP[hartID].Set(0)\n\n\t// Scan the stack(s) of this core.\n\tscanCurrentStack()\n\tif !task.OnSystemStack() {\n\t\t// Mark system stack.\n\t\tmarkRoots(task.SystemStack(), coreStackTop(hartID))\n\t}\n\n\t// Signal we've finished scanning.\n\tgcScanState.Store(1)\n\n\t// Wait until we get a signal that the stop-the-world phase has ended.\n\tfor riscv.MIP.Get()&riscv.MIP_MSIP == 0 {\n\t\triscv.Asm(\"wfi\")\n\t}\n\taclintMSWI.MSIP[hartID].Set(0)\n\n\t// Restore MIE bits.\n\triscv.MIE.Set(savedMIE)\n\n\t// Signal we received the signal and are going to exit the interrupt.\n\tgcScanState.Add(1)\n}\n\n//go:extern _stack_top\nvar stack0TopSymbol [0]byte\n\n//go:extern _stack1_top\nvar stack1TopSymbol [0]byte\n\n//go:extern _stack2_top\nvar stack2TopSymbol [0]byte\n\n//go:extern _stack3_top\nvar stack3TopSymbol [0]byte\n\n// Returns the stack top (highest address) of the system stack of the given\n// core.\nfunc coreStackTop(core uint32) uintptr {\n\tswitch core {\n\tcase 0:\n\t\treturn uintptr(unsafe.Pointer(&stack0TopSymbol))\n\tcase 1:\n\t\treturn uintptr(unsafe.Pointer(&stack1TopSymbol))\n\tcase 2:\n\t\treturn uintptr(unsafe.Pointer(&stack2TopSymbol))\n\tcase 3:\n\t\treturn uintptr(unsafe.Pointer(&stack3TopSymbol))\n\tdefault:\n\t\truntimePanic(\"unexpected core\")\n\t\treturn 0\n\t}\n}\n\n// One tick is 100ns by default in QEMU.\n// (This is not a standard, just the default used by QEMU).\nfunc ticksToNanoseconds(ticks timeUnit) int64 {\n\treturn int64(ticks) * 100 // one tick is 100ns\n}\n\nfunc nanosecondsToTicks(ns int64) timeUnit {\n\treturn timeUnit(ns / 100) // one tick is 100ns\n}\n\nvar sleepCheckpoint interrupt.Checkpoint\n\nfunc sleepTicks(d timeUnit) {\n\thartID := currentCPU()\n\tif sleepCheckpoint.Save() {\n\t\t// Configure timeout.\n\t\ttarget := uint64(ticks() + d)\n\t\taclintMTIMECMP[hartID].Set(target)\n\n\t\t// Wait for the interrupt to happen.\n\t\tfor {\n\t\t\triscv.Asm(\"wfi\")\n\t\t}\n\t}\n\n\t// We got awoken.\n}\n\n// Currently sleeping core, or 0xff.\n// Must only be accessed with the scheduler lock held.\nvar sleepingCore uint8 = 0xff\n\n// Return whether another core is sleeping.\n// May only be called with the scheduler lock held.\nfunc hasSleepingCore() bool {\n\treturn sleepingCore != 0xff\n}\n\n// Almost identical to sleepTicks, except that it will unlock/lock the scheduler\n// while sleeping and is interruptible by interruptSleepTicksMulticore.\n// This may only be called with the scheduler lock held.\nfunc sleepTicksMulticore(d timeUnit) {\n\t// Disable interrupts while configuring sleep.\n\t// This is needed because unlocking the scheduler and setting the timer\n\t// interrupt need to happen atomically.\n\triscv.MSTATUS.ClearBits(riscv.MSTATUS_MIE)\n\n\thartID := currentCPU()\n\tif sleepCheckpoint.Save() {\n\t\tsleepingCore = uint8(hartID)\n\n\t\t// Configure timeout.\n\t\ttarget := uint64(ticks() + d)\n\t\taclintMTIMECMP[hartID].Set(target)\n\n\t\t// Unlock, now that the timeout has been set (so that\n\t\t// interruptSleepTicksMulticore will see the correct wakeup time).\n\t\tschedulerLock.Unlock()\n\n\t\t// Sleep has been configured, interrupts may happen again.\n\t\triscv.MSTATUS.SetBits(riscv.MSTATUS_MIE)\n\n\t\t// Wait for the interrupt to happen.\n\t\tfor {\n\t\t\triscv.Asm(\"wfi\")\n\t\t}\n\t}\n\t// We got awoken.\n\n\t// Lock again, after we finished sleeping.\n\tschedulerLock.Lock()\n\tsleepingCore = 0xff\n}\n\n// Interrupt an ongoing call to sleepTicksMulticore on another core.\n// This may only be called with the scheduler lock held.\nfunc interruptSleepTicksMulticore(wakeup timeUnit) {\n\tif sleepingCore != 0xff {\n\t\t// Immediately exit the sleep.\n\t\told := aclintMTIMECMP[sleepingCore].Get()\n\t\tif uint64(wakeup) < old {\n\t\t\taclintMTIMECMP[sleepingCore].Set(uint64(wakeup))\n\t\t}\n\t}\n}\n\nfunc ticks() timeUnit {\n\t// Combining the low bits and the high bits (at a rate of 100ns per tick)\n\t// yields a time span of over 59930 years without counter rollover.\n\thighBits := aclintMTIME.high.Get()\n\tfor {\n\t\tlowBits := aclintMTIME.low.Get()\n\t\tnewHighBits := aclintMTIME.high.Get()\n\t\tif newHighBits == highBits {\n\t\t\t// High bits stayed the same.\n\t\t\treturn timeUnit(lowBits) | (timeUnit(highBits) << 32)\n\t\t}\n\t\t// Retry, because there was a rollover in the low bits (happening every\n\t\t// ~7 days).\n\t\thighBits = newHighBits\n\t}\n}\n\n// Memory-mapped I/O as defined by QEMU.\n// Source: https://github.com/qemu/qemu/blob/master/hw/riscv/virt.c\n// Technically this is an implementation detail but hopefully they won't change\n// the memory-mapped I/O registers.\nvar (\n\t// UART0 output register.\n\tstdoutWrite = (*volatile.Register8)(unsafe.Pointer(uintptr(0x10000000)))\n\t// SiFive test finisher\n\ttestFinisher = (*volatile.Register32)(unsafe.Pointer(uintptr(0x100000)))\n\n\t// RISC-V Advanced Core Local Interruptor.\n\t// It is backwards compatible with the SiFive CLINT.\n\t// https://github.com/riscvarchive/riscv-aclint/blob/main/riscv-aclint.adoc\n\taclintMTIME = (*struct {\n\t\tlow  volatile.Register32\n\t\thigh volatile.Register32\n\t})(unsafe.Pointer(uintptr(0x0200_bff8)))\n\taclintMTIMECMP = (*[4095]volatile.Register64)(unsafe.Pointer(uintptr(0x0200_4000)))\n\taclintMSWI     = (*struct {\n\t\tMSIP [4095]volatile.Register32\n\t})(unsafe.Pointer(uintptr(0x0200_0000)))\n)\n\nfunc putchar(c byte) {\n\tstdoutWrite.Set(uint8(c))\n}\n\nfunc getchar() byte {\n\t// dummy, TODO\n\treturn 0\n}\n\nfunc buffered() int {\n\t// dummy, TODO\n\treturn 0\n}\n\n// Define the various spinlocks needed by the runtime.\nvar (\n\tschedulerLock spinLock\n\tfutexLock     spinLock\n\tatomicsLock   spinLock\n\tprintLock     spinLock\n)\n\ntype spinLock struct {\n\tatomic.Uint32\n}\n\nfunc (l *spinLock) Lock() {\n\t// Try to replace 0 with 1. Once we succeed, the lock has been acquired.\n\tfor !l.Uint32.CompareAndSwap(0, 1) {\n\t\tspinLoopWait()\n\t}\n}\n\nfunc (l *spinLock) Unlock() {\n\t// Safety check: the spinlock should have been locked.\n\tif schedulerAsserts && l.Uint32.Load() != 1 {\n\t\truntimePanic(\"unlock of unlocked spinlock\")\n\t}\n\n\t// Unlock the lock. Simply write 0, because we already know it is locked.\n\tl.Uint32.Store(0)\n}\n\n// Hint to the CPU that this core is just waiting, and the core can go into a\n// lower energy state.\nfunc spinLoopWait() {\n\t// This is a no-op in QEMU TCG (but added here for completeness):\n\t// https://github.com/qemu/qemu/blob/v9.2.3/target/riscv/insn_trans/trans_rvi.c.inc#L856\n\triscv.Asm(\"pause\")\n}\n\nfunc currentCPU() uint32 {\n\treturn uint32(riscv.MHARTID.Get())\n}\n\nfunc startSecondaryCores() {\n\t// Start all the other cores besides hart 0.\n\tfor hart := 1; hart < numCPU; hart++ {\n\t\t// Signal the given hart it is ready to start using a software\n\t\t// interrupt.\n\t\taclintMSWI.MSIP[hart].Set(1)\n\t}\n}\n\n// Bitset of harts that are currently sleeping in schedulerUnlockAndWait.\n// This supports up to 8 harts.\n// This variable may only be accessed with the scheduler lock held.\nvar sleepingHarts uint8\n\n// Checkpoints for cores waiting for runnable tasks.\nvar schedulerWaitCheckpoints [numCPU]interrupt.Checkpoint\n\n// Put the scheduler to sleep, since there are no tasks to run.\n// This will unlock the scheduler lock, and must be called with the scheduler\n// lock held.\nfunc schedulerUnlockAndWait() {\n\thartID := currentCPU()\n\n\t// Mark the current hart as sleeping.\n\tsleepingHarts |= uint8(1 << hartID)\n\n\t// If this is the last core awake and is going to sleep, the scheduler is\n\t// deadlocked.\n\t// We can do this check since this is not baremetal: there won't be any\n\t// external interrupts that might unblock a goroutine.\n\tif sleepingHarts == (1<<numCPU)-1 {\n\t\truntimePanic(\"all cores are sleeping - deadlock!\")\n\t}\n\n\t// Need to disable interrupts while saving the checkpoint, otherwise if the\n\t// software interrupt happens earlier for another reason (e.g. a GC cycle)\n\t// it will see an incomplete checkpoint and the schedulerLock might not be\n\t// unlocked yet. That will lead to an invalid state.\n\triscv.MSTATUS.ClearBits(riscv.MSTATUS_MIE)\n\tif schedulerWaitCheckpoints[hartID].Save() {\n\t\tschedulerLock.Unlock()\n\t\triscv.MSTATUS.SetBits(riscv.MSTATUS_MIE)\n\n\t\t// Wait until we get awoken :)\n\t\tfor {\n\t\t\triscv.Asm(\"wfi\")\n\t\t}\n\t}\n\n\t// We got awoken again. We need to lock the scheduler again before\n\t// returning.\n\tschedulerLock.Lock()\n}\n\n// Wake another core, if one is sleeping. Must be called with the scheduler lock\n// held.\nfunc schedulerWake() {\n\t// Look up the lowest-numbered hart that is sleeping.\n\t// Returns 8 if there are no sleeping harts.\n\thart := bits.TrailingZeros8(sleepingHarts)\n\n\tif hart < 8 {\n\t\t// There is a sleeping hart. Wake it.\n\t\tsleepingHarts &^= 1 << hart  // clear the bit\n\t\taclintMSWI.MSIP[hart].Set(1) // send software interrupt\n\t}\n}\n\n// Pause the given core by sending it an interrupt.\nfunc gcPauseCore(core uint32) {\n\taclintMSWI.MSIP[core].Set(1) // send software interrupt\n}\n\n// Signal the given core that it can resume one step.\n// This is called twice after gcPauseCore: the first time to scan the stack of\n// the core, and the second time to end the stop-the-world phase.\nfunc gcSignalCore(core uint32) {\n\taclintMSWI.MSIP[core].Set(1) // send software interrupt\n}\n\nfunc abort() {\n\texit(1)\n}\n\n// Zero in the default state, when non-zero it indicates the exit code plus one.\n// So exit(0) will result in 1, exit(1) in 2, etc.\nvar exitCodePlusOne atomic.Uint32\n\nfunc exit(code int) {\n\t// Check for invalid values, to be sure.\n\tif code < 0 {\n\t\tcode = 255\n\t}\n\n\t// If we're not on hart 0, we can't exit QEMU.\n\t// Therefore, send an interrupt to hart 0 instead to request an exit.\n\tif currentCPU() != 0 {\n\t\t// Signal hart 0 to exit.\n\t\texitCodePlusOne.Store(uint32(code) + 1)\n\t\taclintMSWI.MSIP[0].Set(1)\n\n\t\t// Wait for the interrupt to happen. This should happen immediately.\n\t\tfor {\n\t\t\triscv.Asm(\"wfi\")\n\t\t}\n\t}\n\n\texitNow(uint32(code))\n}\n\n// Send an exit signal to the test finisher pseudo-device, without checking\n// whether we are on hart 0.\nfunc exitNow(code uint32) {\n\t// Make sure the QEMU process exits.\n\tif code == 0 {\n\t\ttestFinisher.Set(0x5555) // FINISHER_PASS\n\t} else {\n\t\t// Exit code is stored in the upper 16 bits of the 32 bit value.\n\t\ttestFinisher.Set(code<<16 | 0x3333) // FINISHER_FAIL\n\t}\n\n\t// Lock up forever (as a fallback).\n\tfor {\n\t\triscv.Asm(\"wfi\")\n\t}\n}\n\n// handleException is called from the interrupt handler for any exception.\n// Exceptions can be things like illegal instructions, invalid memory\n// read/write, and similar issues.\nfunc handleException(code uint) {\n\t// For a list of exception codes, see:\n\t// https://content.riscv.org/wp-content/uploads/2019/08/riscv-privileged-20190608-1.pdf#page=49\n\tprint(\"fatal error: exception with mcause=\", code, \" pc=\", riscv.MEPC.Get(), \" hart=\", uint(riscv.MHARTID.Get()), \"\\r\\n\")\n\tabort()\n}\n"
  },
  {
    "path": "src/runtime/runtime_tinygowasm.go",
    "content": "//go:build tinygo.wasm && !wasm_unknown && !wasip2\n\n// This file is for wasm/wasip1 and for wasm/js, which both use much of the\n// WASIp1 API.\n\npackage runtime\n\nimport (\n\t\"unsafe\"\n)\n\n// Implements __wasi_iovec_t.\ntype __wasi_iovec_t struct {\n\tbuf    unsafe.Pointer\n\tbufLen uint\n}\n\n//go:wasmimport wasi_snapshot_preview1 fd_write\nfunc fd_write(id uint32, iovs *__wasi_iovec_t, iovs_len uint, nwritten *uint) (errno uint)\n\n// See:\n// https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#-proc_exitrval-exitcode\n//\n//go:wasmimport wasi_snapshot_preview1 proc_exit\nfunc proc_exit(exitcode uint32)\n\n// Flush stdio on exit.\n//\n//export __stdio_exit\nfunc __stdio_exit()\n\nconst (\n\tputcharBufferSize = 120\n\tstdout            = 1\n)\n\n// Using global variables to avoid heap allocation.\nvar (\n\tputcharBuffer        = [putcharBufferSize]byte{}\n\tputcharPosition uint = 0\n\tputcharIOVec         = __wasi_iovec_t{\n\t\tbuf: unsafe.Pointer(&putcharBuffer[0]),\n\t}\n\tputcharNWritten uint\n)\n\nfunc putchar(c byte) {\n\tputcharBuffer[putcharPosition] = c\n\tputcharPosition++\n\n\tif c == '\\n' || putcharPosition >= putcharBufferSize {\n\t\tputcharIOVec.bufLen = putcharPosition\n\t\tfd_write(stdout, &putcharIOVec, 1, &putcharNWritten)\n\t\tputcharPosition = 0\n\t}\n}\n\nfunc getchar() byte {\n\t// dummy, TODO\n\treturn 0\n}\n\nfunc buffered() int {\n\t// dummy, TODO\n\treturn 0\n}\n\n//go:linkname now time.now\nfunc now() (sec int64, nsec int32, mono int64) {\n\tmono = nanotime()\n\tsec = mono / (1000 * 1000 * 1000)\n\tnsec = int32(mono - sec*(1000*1000*1000))\n\treturn\n}\n\n// Abort executes the wasm 'unreachable' instruction.\nfunc abort() {\n\ttrap()\n}\n\n//go:linkname syscall_Exit syscall.Exit\nfunc syscall_Exit(code int) {\n\t// Flush stdio buffers.\n\t__stdio_exit()\n\n\t// Exit the program.\n\tproc_exit(uint32(code))\n}\n\nfunc mainReturnExit() {\n\tsyscall_Exit(0)\n}\n\n// TinyGo does not yet support any form of parallelism on WebAssembly, so these\n// can be left empty.\n\n//go:linkname procPin sync/atomic.runtime_procPin\nfunc procPin() {\n}\n\n//go:linkname procUnpin sync/atomic.runtime_procUnpin\nfunc procUnpin() {\n}\n\nfunc hardwareRand() (n uint64, ok bool) {\n\tn |= uint64(libc_arc4random())\n\tn |= uint64(libc_arc4random()) << 32\n\treturn n, true\n}\n\n// uint32_t arc4random(void);\n//\n//export arc4random\nfunc libc_arc4random() uint32\n\n// int *__errno_location(void);\n//\n//export __errno_location\nfunc libc_errno_location() *int32\n"
  },
  {
    "path": "src/runtime/runtime_tinygowasm_unknown.go",
    "content": "//go:build wasm_unknown\n\npackage runtime\n\nconst (\n\tstdout = 1\n)\n\nfunc putchar(c byte) {\n}\n\nfunc getchar() byte {\n\t// dummy, TODO\n\treturn 0\n}\n\nfunc buffered() int {\n\t// dummy, TODO\n\treturn 0\n}\n\n//go:linkname now time.now\nfunc now() (sec int64, nsec int32, mono int64) {\n\treturn 0, 0, 0\n}\n\n// Abort executes the wasm 'unreachable' instruction.\nfunc abort() {\n\ttrap()\n}\n\n//go:linkname syscall_Exit syscall.Exit\nfunc syscall_Exit(code int) {\n\t// Because this is the \"unknown\" target we can't call an exit function.\n\t// But we also can't just return since the program will likely expect this\n\t// function to never return. So we panic instead.\n\truntimePanic(\"unsupported: syscall.Exit\")\n}\n\n// There is not yet any support for any form of parallelism on WebAssembly, so these\n// can be left empty.\n\n//go:linkname procPin sync/atomic.runtime_procPin\nfunc procPin() {\n}\n\n//go:linkname procUnpin sync/atomic.runtime_procUnpin\nfunc procUnpin() {\n}\n\nfunc hardwareRand() (n uint64, ok bool) {\n\treturn 0, false\n}\n\nfunc libc_errno_location() *int32 {\n\t// CGo is unavailable, so this function should be unreachable.\n\truntimePanic(\"runtime: no cgo errno\")\n\treturn nil\n}\n"
  },
  {
    "path": "src/runtime/runtime_tinygowasmp2.go",
    "content": "//go:build wasip2\n\npackage runtime\n\nimport (\n\t\"internal/cm\"\n\n\texit \"internal/wasi/cli/v0.2.0/exit\"\n\tstdout \"internal/wasi/cli/v0.2.0/stdout\"\n\tmonotonicclock \"internal/wasi/clocks/v0.2.0/monotonic-clock\"\n\twallclock \"internal/wasi/clocks/v0.2.0/wall-clock\"\n\trandom \"internal/wasi/random/v0.2.0/random\"\n)\n\nconst putcharBufferSize = 120\n\n// Using global variables to avoid heap allocation.\nvar (\n\tputcharStdout        = stdout.GetStdout()\n\tputcharBuffer        = [putcharBufferSize]byte{}\n\tputcharPosition uint = 0\n)\n\nfunc putchar(c byte) {\n\tputcharBuffer[putcharPosition] = c\n\tputcharPosition++\n\tif c == '\\n' || putcharPosition >= putcharBufferSize {\n\t\tlist := cm.NewList(&putcharBuffer[0], putcharPosition)\n\t\tputcharStdout.BlockingWriteAndFlush(list) // error return ignored; can't do anything anyways\n\t\tputcharPosition = 0\n\t}\n}\n\nfunc getchar() byte {\n\t// dummy, TODO\n\treturn 0\n}\n\nfunc buffered() int {\n\t// dummy, TODO\n\treturn 0\n}\n\n//go:linkname now time.now\nfunc now() (sec int64, nsec int32, mono int64) {\n\tnow := wallclock.Now()\n\tsec = int64(now.Seconds)\n\tnsec = int32(now.Nanoseconds)\n\tmono = int64(monotonicclock.Now())\n\treturn\n}\n\n// Abort executes the wasm 'unreachable' instruction.\nfunc abort() {\n\ttrap()\n}\n\n//go:linkname syscall_Exit syscall.Exit\nfunc syscall_Exit(code int) {\n\texit.Exit(code != 0)\n}\n\nfunc mainReturnExit() {\n\t// WASIp2 does not use _start, instead it uses _initialize and a custom\n\t// WASIp2-specific main function. So this should never be called in\n\t// practice.\n\truntimePanic(\"unreachable: _start was called\")\n}\n\n// TinyGo does not yet support any form of parallelism on WebAssembly, so these\n// can be left empty.\n\n//go:linkname procPin sync/atomic.runtime_procPin\nfunc procPin() {\n}\n\n//go:linkname procUnpin sync/atomic.runtime_procUnpin\nfunc procUnpin() {\n}\n\nfunc hardwareRand() (n uint64, ok bool) {\n\treturn random.GetRandomU64(), true\n}\n\nfunc libc_errno_location() *int32 {\n\t// CGo is unavailable, so this function should be unreachable.\n\truntimePanic(\"runtime: no cgo errno\")\n\treturn nil\n}\n"
  },
  {
    "path": "src/runtime/runtime_tkey.go",
    "content": "//go:build tkey\n\n// This file implements target-specific things for the TKey.\n\npackage runtime\n\nimport (\n\t\"device/tkey\"\n\t\"machine\"\n\t\"runtime/volatile\"\n)\n\n//export main\nfunc main() {\n\tpreinit()\n\tinitPeripherals()\n\trun()\n\texit(0)\n}\n\n// initPeripherals configures peripherals the way the runtime expects them.\nfunc initPeripherals() {\n\t// prescaler value that results in 0.00001-second timer-ticks.\n\t// given an 18 MHz processor, a millisecond is about 18,000 cycles.\n\ttkey.TIMER.PRESCALER.Set(18 * machine.MHz / 100000)\n\n\tmachine.InitSerial()\n}\n\nfunc putchar(c byte) {\n\tmachine.Serial.WriteByte(c)\n}\n\nfunc getchar() byte {\n\tfor machine.Serial.Buffered() == 0 {\n\t\tGosched()\n\t}\n\tv, _ := machine.Serial.ReadByte()\n\treturn v\n}\n\nfunc buffered() int {\n\treturn machine.Serial.Buffered()\n}\n\nvar timestamp volatile.Register32\n\n// ticks returns the current value of the timer in ticks.\nfunc ticks() timeUnit {\n\treturn timeUnit(timestamp.Get())\n}\n\n// sleepTicks sleeps for at least the duration d.\nfunc sleepTicks(d timeUnit) {\n\ttarget := uint32(ticks() + d)\n\n\ttkey.TIMER.TIMER.Set(uint32(d))\n\ttkey.TIMER.CTRL.SetBits(tkey.TK1_MMIO_TIMER_CTRL_START)\n\tfor tkey.TIMER.STATUS.Get() != 0 {\n\t}\n\ttimestamp.Set(target)\n}\n"
  },
  {
    "path": "src/runtime/runtime_tkey_baremetal.go",
    "content": "//go:build tkey && !qemu\n\npackage runtime\n\nimport \"device/riscv\"\n\n// ticksToNanoseconds converts ticks (at 18MHz) to 10 µs.\nfunc ticksToNanoseconds(ticks timeUnit) int64 {\n\treturn int64(ticks) * 10000\n}\n\n// nanosecondsToTicks converts 10 µs to ticks (at 18MHz).\nfunc nanosecondsToTicks(ns int64) timeUnit {\n\treturn timeUnit(ns / 10000)\n}\n\nfunc exit(code int) {\n\tabort()\n}\n\nfunc abort() {\n\t// Force illegal instruction to halt CPU\n\triscv.Asm(\"unimp\")\n}\n"
  },
  {
    "path": "src/runtime/runtime_unix.c",
    "content": "//go:build none\n\n// This file is included on Darwin and Linux (despite the //go:build line above).\n\n#define _GNU_SOURCE\n#define _XOPEN_SOURCE\n#include <signal.h>\n#include <unistd.h>\n#include <stdint.h>\n#include <ucontext.h>\n#include <string.h>\n\nvoid tinygo_handle_fatal_signal(int sig, uintptr_t addr);\n\nstatic void signal_handler(int sig, siginfo_t *info, void *context) {\n\tucontext_t* uctx = context;\n\tuintptr_t addr = 0;\n\t#if __APPLE__\n\t\t#if __arm64__\n\t\t\taddr = uctx->uc_mcontext->__ss.__pc;\n\t\t#elif __x86_64__\n\t\t\taddr = uctx->uc_mcontext->__ss.__rip;\n\t\t#else\n\t\t\t#error unknown architecture\n\t\t#endif\n\t#elif __linux__\n\t\t// Note: this can probably be simplified using the MC_PC macro in musl,\n\t\t// but this works for now.\n\t\t#if __arm__\n\t\t\taddr = uctx->uc_mcontext.arm_pc;\n\t\t#elif __i386__\n\t\t\taddr = uctx->uc_mcontext.gregs[REG_EIP];\n\t\t#elif __x86_64__\n\t\t\taddr = uctx->uc_mcontext.gregs[REG_RIP];\n\t\t#else // aarch64, mips, maybe others\n\t\t\taddr = uctx->uc_mcontext.pc;\n\t\t#endif\n\t#else\n\t\t#error unknown platform\n\t#endif\n\ttinygo_handle_fatal_signal(sig, addr);\n}\n\nvoid tinygo_register_fatal_signals(void) {\n\tstruct sigaction act = { 0 };\n\t// SA_SIGINFO:   we want the 2 extra parameters\n\t// SA_RESETHAND: only catch the signal once (the handler will re-raise the signal)\n\tact.sa_flags = SA_SIGINFO | SA_RESETHAND;\n\tact.sa_sigaction = &signal_handler;\n\n\t// Register the signal handler for common issues. There are more signals,\n\t// which can be added if needed.\n\tsigaction(SIGBUS, &act, NULL);\n\tsigaction(SIGILL, &act, NULL);\n\tsigaction(SIGSEGV, &act, NULL);\n}\n"
  },
  {
    "path": "src/runtime/runtime_unix.go",
    "content": "//go:build darwin || (linux && !baremetal && !wasip1 && !wasm_unknown && !wasip2 && !nintendoswitch)\n\npackage runtime\n\nimport (\n\t\"internal/futex\"\n\t\"internal/task\"\n\t\"math/bits\"\n\t\"sync/atomic\"\n\t\"tinygo\"\n\t\"unsafe\"\n)\n\n//export write\nfunc libc_write(fd int32, buf unsafe.Pointer, count uint) int\n\n//export usleep\nfunc usleep(usec uint) int\n\n//export pause\nfunc pause() int32\n\n// void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);\n// Note: off_t is defined as int64 because:\n//   - musl (used on Linux) always defines it as int64\n//   - darwin is practically always 64-bit anyway\n//\n//export mmap\nfunc mmap(addr unsafe.Pointer, length uintptr, prot, flags, fd int, offset int64) unsafe.Pointer\n\n//export abort\nfunc abort()\n\n//export exit\nfunc exit(code int)\n\n//export raise\nfunc raise(sig int32)\n\n//export clock_gettime\nfunc libc_clock_gettime(clk_id int32, ts *timespec)\n\n//export __clock_gettime64\nfunc libc_clock_gettime64(clk_id int32, ts *timespec)\n\n// Portable (64-bit) variant of clock_gettime.\nfunc clock_gettime(clk_id int32, ts *timespec) {\n\tif TargetBits == 32 {\n\t\t// This is a 32-bit architecture (386, arm, etc).\n\t\t// We would like to use the 64-bit version of this function so that\n\t\t// binaries will continue to run after Y2038.\n\t\t// For more information:\n\t\t//   - https://musl.libc.org/time64.html\n\t\t//   - https://sourceware.org/glibc/wiki/Y2038ProofnessDesign\n\t\tlibc_clock_gettime64(clk_id, ts)\n\t} else {\n\t\t// This is a 64-bit architecture (amd64, arm64, etc).\n\t\t// Use the regular variant, because it already fixes the Y2038 problem\n\t\t// by using 64-bit integer types.\n\t\tlibc_clock_gettime(clk_id, ts)\n\t}\n}\n\n// Note: tv_sec and tv_nsec normally vary in size by platform. However, we're\n// using the time64 variant (see clock_gettime above), so the formats are the\n// same between 32-bit and 64-bit architectures.\n// There is one issue though: on big-endian systems, tv_nsec would be incorrect.\n// But we don't support big-endian systems yet (as of 2021) so this is fine.\ntype timespec struct {\n\ttv_sec  int64 // time_t with time64 support (always 64-bit)\n\ttv_nsec int64 // unsigned 64-bit integer on all time64 platforms\n}\n\n// Highest address of the stack of the main thread.\nvar stackTop uintptr\n\n// Entry point for Go. Initialize all packages and call main.main().\n//\n//export main\nfunc main(argc int32, argv *unsafe.Pointer) int {\n\tif needsStaticHeap {\n\t\t// Allocate area for the heap if the GC needs it.\n\t\tallocateHeap()\n\t}\n\n\t// Store argc and argv for later use.\n\tmain_argc = argc\n\tmain_argv = argv\n\n\t// Register some fatal signals, so that we can print slightly better error\n\t// messages.\n\ttinygo_register_fatal_signals()\n\n\t// Obtain the initial stack pointer right before calling the run() function.\n\t// The run function has been moved to a separate (non-inlined) function so\n\t// that the correct stack pointer is read.\n\tstackTop = getCurrentStackPointer()\n\trunMain()\n\n\t// For libc compatibility.\n\treturn 0\n}\n\nvar (\n\tmain_argc int32\n\tmain_argv *unsafe.Pointer\n\targs      []string\n)\n\n//go:linkname os_runtime_args os.runtime_args\nfunc os_runtime_args() []string {\n\tif args == nil {\n\t\t// Make args slice big enough so that it can store all command line\n\t\t// arguments.\n\t\targs = make([]string, main_argc)\n\n\t\t// Initialize command line parameters.\n\t\targv := main_argv\n\t\tfor i := 0; i < int(main_argc); i++ {\n\t\t\t// Convert the C string to a Go string.\n\t\t\tlength := strlen(*argv)\n\t\t\targ := (*_string)(unsafe.Pointer(&args[i]))\n\t\t\targ.length = length\n\t\t\targ.ptr = (*byte)(*argv)\n\t\t\t// This is the Go equivalent of \"argv++\" in C.\n\t\t\targv = (*unsafe.Pointer)(unsafe.Add(unsafe.Pointer(argv), unsafe.Sizeof(argv)))\n\t\t}\n\t}\n\treturn args\n}\n\n// Must be a separate function to get the correct stack pointer.\n//\n//go:noinline\nfunc runMain() {\n\trun()\n}\n\n//export tinygo_register_fatal_signals\nfunc tinygo_register_fatal_signals()\n\n// Print fatal errors when they happen, including the instruction location.\n// With the particular formatting below, `tinygo run` can extract the location\n// where the signal happened and try to show the source location based on DWARF\n// information.\n//\n//export tinygo_handle_fatal_signal\nfunc tinygo_handle_fatal_signal(sig int32, addr uintptr) {\n\tif panicStrategy() == tinygo.PanicStrategyTrap {\n\t\ttrap()\n\t}\n\n\t// Print signal including the faulting instruction.\n\tif addr != 0 {\n\t\tprintstring(\"panic: runtime error at \")\n\t\tprintptr(addr)\n\t} else {\n\t\tprintstring(\"panic: runtime error\")\n\t}\n\tprintstring(\": caught signal \")\n\tswitch sig {\n\tcase sig_SIGBUS:\n\t\tprintln(\"SIGBUS\")\n\tcase sig_SIGILL:\n\t\tprintln(\"SIGILL\")\n\tcase sig_SIGSEGV:\n\t\tprintln(\"SIGSEGV\")\n\tdefault:\n\t\tprintln(sig)\n\t}\n\n\t// TODO: it might be interesting to also print the invalid address for\n\t// SIGSEGV and SIGBUS.\n\n\t// Do *not* abort here, instead raise the same signal again. The signal is\n\t// registered with SA_RESETHAND which means it executes only once. So when\n\t// we raise the signal again below, the signal isn't handled specially but\n\t// is handled in the default way (probably exiting the process, maybe with a\n\t// core dump).\n\traise(sig)\n}\n\n//go:extern environ\nvar environ *unsafe.Pointer\n\n//go:linkname syscall_runtime_envs syscall.runtime_envs\nfunc syscall_runtime_envs() []string {\n\t// Count how many environment variables there are.\n\tenv := environ\n\tnumEnvs := 0\n\tfor *env != nil {\n\t\tnumEnvs++\n\t\tenv = (*unsafe.Pointer)(unsafe.Add(unsafe.Pointer(env), unsafe.Sizeof(environ)))\n\t}\n\n\t// Create a string slice of all environment variables.\n\t// This requires just a single heap allocation.\n\tenv = environ\n\tenvs := make([]string, 0, numEnvs)\n\tfor *env != nil {\n\t\tptr := *env\n\t\tlength := strlen(ptr)\n\t\ts := _string{\n\t\t\tptr:    (*byte)(ptr),\n\t\t\tlength: length,\n\t\t}\n\t\tenvs = append(envs, *(*string)(unsafe.Pointer(&s)))\n\t\tenv = (*unsafe.Pointer)(unsafe.Add(unsafe.Pointer(env), unsafe.Sizeof(environ)))\n\t}\n\n\treturn envs\n}\n\nfunc putchar(c byte) {\n\tbuf := [1]byte{c}\n\tlibc_write(1, unsafe.Pointer(&buf[0]), 1)\n}\n\nfunc ticksToNanoseconds(ticks timeUnit) int64 {\n\t// The OS API works in nanoseconds so no conversion necessary.\n\treturn int64(ticks)\n}\n\nfunc nanosecondsToTicks(ns int64) timeUnit {\n\t// The OS API works in nanoseconds so no conversion necessary.\n\treturn timeUnit(ns)\n}\n\nfunc sleepTicks(d timeUnit) {\n\tuntil := ticks() + d\n\n\tfor {\n\t\t// Sleep for the given amount of time.\n\t\t// If a signal arrived before going to sleep, or during the sleep, the\n\t\t// sleep will exit early.\n\t\tsignalFutex.WaitUntil(0, uint64(ticksToNanoseconds(d)))\n\n\t\t// Check whether there was a signal before or during the call to\n\t\t// WaitUntil.\n\t\tif signalFutex.Swap(0) != 0 {\n\t\t\tif checkSignals() && hasScheduler {\n\t\t\t\t// We got a signal, so return to the scheduler.\n\t\t\t\t// (If there is no scheduler, there is no other goroutine that\n\t\t\t\t// might need to run now).\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\t// Set duration (in next loop iteration) to the remaining time.\n\t\td = until - ticks()\n\t\tif d <= 0 {\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc getTime(clock int32) uint64 {\n\tts := timespec{}\n\tclock_gettime(clock, &ts)\n\treturn uint64(ts.tv_sec)*1000*1000*1000 + uint64(ts.tv_nsec)\n}\n\n// Return monotonic time in nanoseconds.\nfunc monotime() uint64 {\n\treturn getTime(clock_MONOTONIC_RAW)\n}\n\nfunc ticks() timeUnit {\n\treturn timeUnit(monotime())\n}\n\n//go:linkname now time.now\nfunc now() (sec int64, nsec int32, mono int64) {\n\tts := timespec{}\n\tclock_gettime(clock_REALTIME, &ts)\n\tsec = int64(ts.tv_sec)\n\tnsec = int32(ts.tv_nsec)\n\tmono = nanotime()\n\treturn\n}\n\n//go:linkname syscall_Exit syscall.Exit\nfunc syscall_Exit(code int) {\n\texit(code)\n}\n\n// TinyGo does not yet support any form of parallelism on an OS, so these can be\n// left empty.\n\n//go:linkname procPin sync/atomic.runtime_procPin\nfunc procPin() {\n}\n\n//go:linkname procUnpin sync/atomic.runtime_procUnpin\nfunc procUnpin() {\n}\n\nvar heapSize uintptr = 128 * 1024 // small amount to start\nvar heapMaxSize uintptr\n\nvar heapStart, heapEnd uintptr\n\nfunc allocateHeap() {\n\t// Allocate a large chunk of virtual memory. Because it is virtual, it won't\n\t// really be allocated in RAM. Memory will only be allocated when it is\n\t// first touched.\n\theapMaxSize = 1 * 1024 * 1024 * 1024 // 1GB for the entire heap\n\tfor {\n\t\taddr := mmap(nil, heapMaxSize, flag_PROT_READ|flag_PROT_WRITE, flag_MAP_PRIVATE|flag_MAP_ANONYMOUS, -1, 0)\n\t\tif addr == unsafe.Pointer(^uintptr(0)) {\n\t\t\t// Heap was too big to be mapped by mmap. Reduce the maximum size.\n\t\t\t// We might want to make this a bit smarter than simply halving the\n\t\t\t// heap size.\n\t\t\t// This can happen on 32-bit systems.\n\t\t\theapMaxSize /= 2\n\t\t\tif heapMaxSize < 4096 {\n\t\t\t\truntimePanic(\"cannot allocate heap memory\")\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\theapStart = uintptr(addr)\n\t\theapEnd = heapStart + heapSize\n\t\tbreak\n\t}\n}\n\n// growHeap tries to grow the heap size. It returns true if it succeeds, false\n// otherwise.\nfunc growHeap() bool {\n\tif heapSize == heapMaxSize {\n\t\t// Already at the max. If we run out of memory, we should consider\n\t\t// increasing heapMaxSize on 64-bit systems.\n\t\treturn false\n\t}\n\t// Grow the heap size used by the program.\n\theapSize = (heapSize * 4 / 3) &^ 4095 // grow by around 33%\n\tif heapSize > heapMaxSize {\n\t\theapSize = heapMaxSize\n\t}\n\tsetHeapEnd(heapStart + heapSize)\n\treturn true\n}\n\n// Indicate whether signals have been registered.\nvar hasSignals bool\n\n// Futex for the signal handler.\n// The value is 0 when there are no new signals, or 1 when there are unhandled\n// signals and the main thread doesn't know about it yet.\n// When a signal arrives, the futex value is changed to 1 and if it was 0\n// before, all waiters are awoken.\n// When a wait exits, the value is changed to 0 and if it wasn't 0 before, the\n// signals are checked.\nvar signalFutex futex.Futex\n\n// Mask of signals that have been received. The signal handler atomically ORs\n// signals into this value.\nvar receivedSignals atomic.Uint32\n\n//go:linkname signal_enable os/signal.signal_enable\nfunc signal_enable(s uint32) {\n\tif s >= 32 {\n\t\t// TODO: to support higher signal numbers, we need to turn\n\t\t// receivedSignals into a uint32 array.\n\t\truntimePanicAt(returnAddress(0), \"unsupported signal number\")\n\t}\n\n\t// This is intentonally a non-atomic store. This is safe, since hasSignals\n\t// is only used in waitForEvents which is only called when there's a\n\t// scheduler (and therefore there is no parallelism).\n\thasSignals = true\n\n\t// It's easier to implement this function in C.\n\ttinygo_signal_enable(s)\n}\n\n//go:linkname signal_ignore os/signal.signal_ignore\nfunc signal_ignore(s uint32) {\n\tif s >= 32 {\n\t\t// TODO: to support higher signal numbers, we need to turn\n\t\t// receivedSignals into a uint32 array.\n\t\truntimePanicAt(returnAddress(0), \"unsupported signal number\")\n\t}\n\ttinygo_signal_ignore(s)\n}\n\n//go:linkname signal_disable os/signal.signal_disable\nfunc signal_disable(s uint32) {\n\tif s >= 32 {\n\t\t// TODO: to support higher signal numbers, we need to turn\n\t\t// receivedSignals into a uint32 array.\n\t\truntimePanicAt(returnAddress(0), \"unsupported signal number\")\n\t}\n\ttinygo_signal_disable(s)\n}\n\n//go:linkname signal_waitUntilIdle os/signal.signalWaitUntilIdle\nfunc signal_waitUntilIdle() {\n\t// Wait until signal_recv has processed all signals.\n\tfor receivedSignals.Load() != 0 {\n\t\t// TODO: this becomes a busy loop when using threads.\n\t\t// We might want to pause until signal_recv has no more incoming signals\n\t\t// to process.\n\t\tGosched()\n\t}\n}\n\n//export tinygo_signal_enable\nfunc tinygo_signal_enable(s uint32)\n\n//export tinygo_signal_ignore\nfunc tinygo_signal_ignore(s uint32)\n\n//export tinygo_signal_disable\nfunc tinygo_signal_disable(s uint32)\n\n// void tinygo_signal_handler(int sig);\n//\n//export tinygo_signal_handler\nfunc tinygo_signal_handler(s int32) {\n\t// The following loop is equivalent to the following:\n\t//\n\t//     receivedSignals.Or(uint32(1) << uint32(s))\n\t//\n\t// TODO: use this instead of a loop once we drop support for Go 1.22.\n\tfor {\n\t\tmask := uint32(1) << uint32(s)\n\t\tval := receivedSignals.Load()\n\t\tswapped := receivedSignals.CompareAndSwap(val, val|mask)\n\t\tif swapped {\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// Notify the main thread that there was a signal.\n\t// This will exit the call to Wait or WaitUntil early.\n\tif signalFutex.Swap(1) == 0 {\n\t\t// Changed from 0 to 1, so there may have been a waiting goroutine.\n\t\t// This could be optimized to avoid a syscall when there are no waiting\n\t\t// goroutines.\n\t\tsignalFutex.WakeAll()\n\t}\n}\n\n// Task waiting for a signal to arrive, or nil if it is running or there are no\n// signals.\nvar signalRecvWaiter atomic.Pointer[task.Task]\n\n//go:linkname signal_recv os/signal.signal_recv\nfunc signal_recv() uint32 {\n\t// Function called from os/signal to get the next received signal.\n\tfor {\n\t\tval := receivedSignals.Load()\n\t\tif val == 0 {\n\t\t\t// There are no signals to receive. Sleep until there are.\n\t\t\tif signalRecvWaiter.Swap(task.Current()) != nil {\n\t\t\t\t// We expect only a single goroutine to call signal_recv.\n\t\t\t\truntimePanic(\"signal_recv called concurrently\")\n\t\t\t}\n\t\t\ttask.Pause()\n\t\t\tcontinue\n\t\t}\n\n\t\t// Extract the lowest numbered signal number from receivedSignals.\n\t\tnum := uint32(bits.TrailingZeros32(val))\n\n\t\t// Atomically clear the signal number from receivedSignals.\n\t\t// TODO: use atomic.Uint32.And once we drop support for Go 1.22 instead\n\t\t// of this loop, like so:\n\t\t//\n\t\t//   receivedSignals.And(^(uint32(1) << num))\n\t\t//\n\t\tfor {\n\t\t\tnewVal := val &^ (1 << num)\n\t\t\tswapped := receivedSignals.CompareAndSwap(val, newVal)\n\t\t\tif swapped {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tval = receivedSignals.Load()\n\t\t}\n\n\t\treturn num\n\t}\n}\n\n// Reactivate the goroutine waiting for signals, if there are any.\n// Return true if it was reactivated (and therefore the scheduler should run\n// again), and false otherwise.\nfunc checkSignals() bool {\n\tif receivedSignals.Load() != 0 {\n\t\tif waiter := signalRecvWaiter.Swap(nil); waiter != nil {\n\t\t\tscheduleTask(waiter)\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc waitForEvents() {\n\tif hasSignals {\n\t\t// Wait as long as the futex value is 0.\n\t\t// This can happen either before or during the call to Wait.\n\t\t// This can be optimized: if the value is nonzero we don't need to do a\n\t\t// futex wait syscall and can instead immediately call checkSignals.\n\t\tsignalFutex.Wait(0)\n\n\t\t// Check for signals that arrived before or during the call to Wait.\n\t\t// If there are any signals, the value is 0.\n\t\tif signalFutex.Swap(0) != 0 {\n\t\t\tcheckSignals()\n\t\t}\n\t} else {\n\t\t// The program doesn't use signals, so this is a deadlock.\n\t\truntimePanic(\"deadlocked: no event source\")\n\t}\n}\n"
  },
  {
    "path": "src/runtime/runtime_wasip1.go",
    "content": "//go:build wasip1\n\npackage runtime\n\nimport (\n\t\"unsafe\"\n)\n\n// libc constructors\n//\n//export __wasm_call_ctors\nfunc __wasm_call_ctors()\n\n// Read the command line arguments from WASI.\n// For example, they can be passed to a program with wasmtime like this:\n//\n//\twasmtime run ./program.wasm arg1 arg2\nfunc init() {\n\t__wasm_call_ctors()\n}\n\nvar args []string\n\n//go:linkname os_runtime_args os.runtime_args\nfunc os_runtime_args() []string {\n\tif args == nil {\n\t\t// Read the number of args (argc) and the buffer size required to store\n\t\t// all these args (argv).\n\t\tvar argc, argv_buf_size uint32\n\t\targs_sizes_get(&argc, &argv_buf_size)\n\t\tif argc == 0 {\n\t\t\treturn nil\n\t\t}\n\n\t\t// Obtain the command line arguments\n\t\targsSlice := make([]unsafe.Pointer, argc)\n\t\tbuf := make([]byte, argv_buf_size)\n\t\targs_get(&argsSlice[0], unsafe.Pointer(&buf[0]))\n\n\t\t// Convert the array of C strings to an array of Go strings.\n\t\targs = make([]string, argc)\n\t\tfor i, cstr := range argsSlice {\n\t\t\tlength := strlen(cstr)\n\t\t\targString := _string{\n\t\t\t\tlength: length,\n\t\t\t\tptr:    (*byte)(cstr),\n\t\t\t}\n\t\t\targs[i] = *(*string)(unsafe.Pointer(&argString))\n\t\t}\n\t}\n\treturn args\n}\n\nfunc ticksToNanoseconds(ticks timeUnit) int64 {\n\treturn int64(ticks)\n}\n\nfunc nanosecondsToTicks(ns int64) timeUnit {\n\treturn timeUnit(ns)\n}\n\nconst timePrecisionNanoseconds = 1000 // TODO: how can we determine the appropriate `precision`?\n\nvar (\n\tsleepTicksSubscription = __wasi_subscription_t{\n\t\tuserData: 0,\n\t\tu: __wasi_subscription_u_t{\n\t\t\ttag: __wasi_eventtype_t_clock,\n\t\t\tu: __wasi_subscription_clock_t{\n\t\t\t\tid:        0,\n\t\t\t\ttimeout:   0,\n\t\t\t\tprecision: timePrecisionNanoseconds,\n\t\t\t\tflags:     0,\n\t\t\t},\n\t\t},\n\t}\n\tsleepTicksResult  = __wasi_event_t{}\n\tsleepTicksNEvents uint32\n)\n\nfunc sleepTicks(d timeUnit) {\n\tsleepTicksSubscription.u.u.timeout = uint64(d)\n\tpoll_oneoff(&sleepTicksSubscription, &sleepTicksResult, 1, &sleepTicksNEvents)\n}\n\nfunc ticks() timeUnit {\n\tvar nano uint64\n\tclock_time_get(0, timePrecisionNanoseconds, &nano)\n\treturn timeUnit(nano)\n}\n\n// Implementations of WASI APIs\n\n//go:wasmimport wasi_snapshot_preview1 args_get\nfunc args_get(argv *unsafe.Pointer, argv_buf unsafe.Pointer) (errno uint16)\n\n//go:wasmimport wasi_snapshot_preview1 args_sizes_get\nfunc args_sizes_get(argc *uint32, argv_buf_size *uint32) (errno uint16)\n\n//go:wasmimport wasi_snapshot_preview1 clock_time_get\nfunc clock_time_get(clockid uint32, precision uint64, time *uint64) (errno uint16)\n\n//go:wasmimport wasi_snapshot_preview1 poll_oneoff\nfunc poll_oneoff(in *__wasi_subscription_t, out *__wasi_event_t, nsubscriptions uint32, nevents *uint32) (errno uint16)\n\ntype __wasi_eventtype_t = uint8\n\nconst (\n\t__wasi_eventtype_t_clock __wasi_eventtype_t = 0\n\t// TODO: __wasi_eventtype_t_fd_read  __wasi_eventtype_t = 1\n\t// TODO: __wasi_eventtype_t_fd_write __wasi_eventtype_t = 2\n)\n\ntype (\n\t// https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#-subscription-record\n\t__wasi_subscription_t struct {\n\t\tuserData uint64\n\t\tu        __wasi_subscription_u_t\n\t}\n\n\t__wasi_subscription_u_t struct {\n\t\ttag __wasi_eventtype_t\n\n\t\t// TODO: support fd_read/fd_write event\n\t\tu __wasi_subscription_clock_t\n\t}\n\n\t// https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#-subscription_clock-record\n\t__wasi_subscription_clock_t struct {\n\t\tid        uint32\n\t\ttimeout   uint64\n\t\tprecision uint64\n\t\tflags     uint16\n\t}\n)\n\ntype (\n\t// https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#-event-record\n\t__wasi_event_t struct {\n\t\tuserData  uint64\n\t\terrno     uint16\n\t\teventType __wasi_eventtype_t\n\n\t\t// only used for fd_read or fd_write events\n\t\t// TODO: support fd_read/fd_write event\n\t\t_ struct {\n\t\t\tnBytes uint64\n\t\t\tflags  uint16\n\t\t}\n\t}\n)\n"
  },
  {
    "path": "src/runtime/runtime_wasip2.go",
    "content": "//go:build wasip2\n\npackage runtime\n\nimport (\n\t\"unsafe\"\n\n\t\"internal/wasi/cli/v0.2.0/environment\"\n\twasiclirun \"internal/wasi/cli/v0.2.0/run\"\n\tmonotonicclock \"internal/wasi/clocks/v0.2.0/monotonic-clock\"\n\n\t\"internal/cm\"\n)\n\nfunc init() {\n\twasiclirun.Exports.Run = func() cm.BoolResult {\n\t\tcallMain()\n\t\treturn false\n\t}\n}\n\nvar args []string\n\n//go:linkname os_runtime_args os.runtime_args\nfunc os_runtime_args() []string {\n\tif args == nil {\n\t\targs = environment.GetArguments().Slice()\n\t}\n\treturn args\n}\n\n//export cabi_realloc\nfunc cabi_realloc(ptr, oldsize, align, newsize unsafe.Pointer) unsafe.Pointer {\n\treturn realloc(ptr, uintptr(newsize))\n}\n\nfunc ticksToNanoseconds(ticks timeUnit) int64 {\n\treturn int64(ticks)\n}\n\nfunc nanosecondsToTicks(ns int64) timeUnit {\n\treturn timeUnit(ns)\n}\n\nfunc sleepTicks(d timeUnit) {\n\tp := monotonicclock.SubscribeDuration(monotonicclock.Duration(d))\n\tp.Block()\n}\n\nfunc ticks() timeUnit {\n\treturn timeUnit(monotonicclock.Now())\n}\n"
  },
  {
    "path": "src/runtime/runtime_wasm_js.go",
    "content": "//go:build wasm && !wasip1\n\npackage runtime\n\nvar handleEvent func()\n\n//go:linkname setEventHandler syscall/js.setEventHandler\nfunc setEventHandler(fn func()) {\n\thandleEvent = fn\n}\n\n// We use 1ns per tick, to simplify things.\n// It would probably be fine to use 1µs per tick, since performance.now only\n// promises a resolution of 5µs, but 1ns makes the conversions here a bit more\n// straightforward (since nothing needs to be converted).\nfunc ticksToNanoseconds(ticks timeUnit) int64 {\n\treturn int64(ticks)\n}\n\nfunc nanosecondsToTicks(ns int64) timeUnit {\n\treturn timeUnit(ns)\n}\n\n// This function is called by the scheduler.\n// Schedule a call to runtime.scheduler, do not actually sleep.\n//\n//go:wasmimport gojs runtime.sleepTicks\nfunc sleepTicks(d timeUnit)\n\n//go:wasmimport gojs runtime.ticks\nfunc ticks() timeUnit\n"
  },
  {
    "path": "src/runtime/runtime_wasm_js_scheduler.go",
    "content": "//go:build wasm && !wasi && !scheduler.none && !wasip1 && !wasip2 && !wasm_unknown\n\npackage runtime\n\n//export resume\nfunc resume() {\n\tgo func() {\n\t\thandleEvent()\n\t}()\n\n\tscheduler(false)\n}\n\n//export go_scheduler\nfunc go_scheduler() {\n\tscheduler(false)\n}\n"
  },
  {
    "path": "src/runtime/runtime_wasm_unknown.go",
    "content": "//go:build wasm_unknown\n\npackage runtime\n\n// TODO: this is essentially reactor mode wasm. So we might want to support\n// -buildmode=c-shared (and default to it).\n\n// libc constructors\n//\n//export __wasm_call_ctors\nfunc __wasm_call_ctors()\n\nfunc init() {\n\t__wasm_call_ctors()\n}\n\nfunc ticksToNanoseconds(ticks timeUnit) int64 {\n\treturn int64(ticks)\n}\n\nfunc nanosecondsToTicks(ns int64) timeUnit {\n\treturn timeUnit(ns)\n}\n\nfunc sleepTicks(d timeUnit) {\n}\n\nfunc ticks() timeUnit {\n\treturn timeUnit(0)\n}\n\nfunc mainReturnExit() {\n\t// Don't exit explicitly here. We can't (there is no environment with an\n\t// exit call) but also it's not needed. We can just let _start and main.main\n\t// return to the caller.\n}\n"
  },
  {
    "path": "src/runtime/runtime_wasmentry.go",
    "content": "//go:build tinygo.wasm\n\npackage runtime\n\n// Entry points for WebAssembly modules, and runtime support for\n// //go:wasmexport: runtime.wasmExport* function calls are inserted by the\n// compiler for //go:wasmexport support.\n\nimport (\n\t\"internal/task\"\n\t\"unsafe\"\n)\n\n// This is the _start entry point, when using -buildmode=default.\nfunc wasmEntryCommand() {\n\t// These need to be initialized early so that the heap can be initialized.\n\tinitializeCalled = true\n\theapStart = uintptr(unsafe.Pointer(&heapStartSymbol))\n\theapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)\n\trun()\n\tif mainExited {\n\t\t// To make sure wasm_exec.js knows that we've exited, exit explicitly.\n\t\tmainReturnExit()\n\t}\n}\n\n// This is the _initialize entry point, when using -buildmode=c-shared.\nfunc wasmEntryReactor() {\n\t// This function is called before any //go:wasmexport functions are called\n\t// to initialize everything. It must not block.\n\n\tinitializeCalled = true\n\n\t// Initialize the heap.\n\theapStart = uintptr(unsafe.Pointer(&heapStartSymbol))\n\theapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)\n\tinitRand()\n\tinitHeap()\n\n\tif hasScheduler {\n\t\t// A package initializer might do funky stuff like start a goroutine and\n\t\t// wait until it completes, so we have to run package initializers in a\n\t\t// goroutine.\n\t\tgo func() {\n\t\t\tinitAll()\n\t\t}()\n\t\tscheduler(true)\n\t} else {\n\t\t// There are no goroutines (except for the main one, if you can call it\n\t\t// that), so we can just run all the package initializers.\n\t\tinitAll()\n\t}\n}\n\n// This is the _start entry point, when using -buildmode=wasi-legacy.\nfunc wasmEntryLegacy() {\n\t// These need to be initialized early so that the heap can be initialized.\n\tinitializeCalled = true\n\theapStart = uintptr(unsafe.Pointer(&heapStartSymbol))\n\theapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)\n\trun()\n}\n\n// Whether the runtime was initialized by a call to _initialize or _start.\nvar initializeCalled bool\n\nfunc wasmExportCheckRun() {\n\tswitch {\n\tcase !initializeCalled:\n\t\truntimePanic(\"//go:wasmexport function called before runtime initialization\")\n\tcase mainExited:\n\t\truntimePanic(\"//go:wasmexport function called after main.main returned\")\n\t}\n}\n\n// Called from within a //go:wasmexport wrapper (the one that's exported from\n// the wasm module) after the goroutine has been queued. Just run the scheduler,\n// and check that the goroutine finished when the scheduler is idle (as required\n// by the //go:wasmexport proposal).\n//\n// This function is not called when the scheduler is disabled.\nfunc wasmExportRun(done *bool) {\n\tscheduler(true)\n\tif !*done {\n\t\truntimePanic(\"//go:wasmexport function did not finish\")\n\t}\n}\n\n// Called from the goroutine wrapper for the //go:wasmexport function. It just\n// signals to the runtime that the //go:wasmexport call has finished, and can\n// switch back to the wasmExportRun function.\n//\n// This function is not called when the scheduler is disabled.\nfunc wasmExportExit() {\n\t// Signal to the scheduler that it should return, since this call to a\n\t// //go:wasmexport function has exited.\n\tschedulerExit = true\n\n\ttask.Pause()\n\n\t// TODO: we could cache the allocated stack so we don't have to keep\n\t// allocating a new stack on every //go:wasmexport call.\n}\n"
  },
  {
    "path": "src/runtime/runtime_windows.go",
    "content": "package runtime\n\nimport \"unsafe\"\n\n//export abort\nfunc abort()\n\n//export exit\nfunc libc_exit(code int)\n\n//export putchar\nfunc libc_putchar(c int) int\n\n//export VirtualAlloc\nfunc _VirtualAlloc(lpAddress unsafe.Pointer, dwSize uintptr, flAllocationType, flProtect uint32) unsafe.Pointer\n\n//export QueryUnbiasedInterruptTime\nfunc _QueryUnbiasedInterruptTime(UnbiasedTime *uint64) bool\n\n// The parameter is really a LPFILETIME, but *uint64 should be compatible.\n//\n//export GetSystemTimeAsFileTime\nfunc _GetSystemTimeAsFileTime(lpSystemTimeAsFileTime *uint64)\n\n//export LoadLibraryExW\nfunc _LoadLibraryExW(lpLibFileName *uint16, hFile uintptr, dwFlags uint32) uintptr\n\n//export Sleep\nfunc _Sleep(milliseconds uint32)\n\nconst _LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800\n\n//export GetProcAddress\nfunc getProcAddress(handle uintptr, procname *byte) uintptr\n\n//export _configure_narrow_argv\nfunc _configure_narrow_argv(int32) int32\n\n//export __p___argc\nfunc __p___argc() *int32\n\n//export __p___argv\nfunc __p___argv() **unsafe.Pointer\n\ntype startupInfo struct {\n\tnewMode int32\n}\n\n//export __getmainargs\nfunc __getmainargs(argc *int32, argv, env **unsafe.Pointer, doWildcard int, startInfo *startupInfo) int32\n\nvar performanceFrequency int64\n\n//export mainCRTStartup\nfunc mainCRTStartup() int {\n\tpreinit()\n\n\t// Obtain the (constant) performance frequency when needed.\n\tif GOARCH == \"386\" {\n\t\t_QueryPerformanceFrequency(&performanceFrequency)\n\t}\n\n\t// Obtain the initial stack pointer right before calling the run() function.\n\t// The run function has been moved to a separate (non-inlined) function so\n\t// that the correct stack pointer is read.\n\tstackTop = getCurrentStackPointer()\n\trunMain()\n\n\t// Exit via exit(0) instead of returning. This matches\n\t// mingw-w64-crt/crt/crtexe.c, which exits using exit(0) instead of\n\t// returning the return value.\n\t// Exiting this way (instead of returning) also fixes an issue where not all\n\t// output would be sent to stdout before exit.\n\t// See: https://github.com/tinygo-org/tinygo/pull/4589\n\tlibc_exit(0)\n\n\t// Unreachable, since we've already exited. But we need to return something\n\t// here to make this valid Go code.\n\treturn 0\n}\n\n// Must be a separate function to get the correct stack pointer.\n//\n//go:noinline\nfunc runMain() {\n\trun()\n}\n\nvar args []string\n\n//go:linkname os_runtime_args os.runtime_args\nfunc os_runtime_args() []string {\n\tif args == nil {\n\t\t// Obtain argc/argv from the environment.\n\t\tvar argc int32\n\t\tvar argv *unsafe.Pointer\n\t\tif GOARCH == \"386\" {\n\t\t\t// MSVCRT.DLL\n\t\t\tvar env *unsafe.Pointer\n\t\t\tstartInfo := startupInfo{newMode: 0}\n\t\t\t__getmainargs(&argc, &argv, &env, 1, &startInfo)\n\t\t} else {\n\t\t\t// UCRT\n\t\t\t_configure_narrow_argv(2)\n\t\t\targc = *__p___argc()\n\t\t\targv = *__p___argv()\n\t\t}\n\n\t\t// Make args slice big enough so that it can store all command line\n\t\t// arguments.\n\t\targs = make([]string, argc)\n\n\t\t// Initialize command line parameters.\n\t\tfor i := 0; i < int(argc); i++ {\n\t\t\t// Convert the C string to a Go string.\n\t\t\tlength := strlen(*argv)\n\t\t\targ := (*_string)(unsafe.Pointer(&args[i]))\n\t\t\targ.length = length\n\t\t\targ.ptr = (*byte)(*argv)\n\t\t\t// This is the Go equivalent of \"argv++\" in C.\n\t\t\targv = (*unsafe.Pointer)(unsafe.Add(unsafe.Pointer(argv), unsafe.Sizeof(argv)))\n\t\t}\n\t}\n\treturn args\n}\n\nfunc putchar(c byte) {\n\tlibc_putchar(int(c))\n}\n\nvar heapSize uintptr = 128 * 1024 // small amount to start\nvar heapMaxSize uintptr\n\nvar heapStart, heapEnd uintptr\n\nfunc preinit() {\n\t// Allocate a large chunk of virtual memory. Because it is virtual, it won't\n\t// really be allocated in RAM. Memory will only be allocated when it is\n\t// first touched.\n\theapMaxSize = 1 * 1024 * 1024 * 1024 // 1GB for the entire heap\n\tconst (\n\t\tMEM_COMMIT     = 0x00001000\n\t\tMEM_RESERVE    = 0x00002000\n\t\tPAGE_READWRITE = 0x04\n\t)\n\theapStart = uintptr(_VirtualAlloc(nil, heapMaxSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE))\n\theapEnd = heapStart + heapSize\n}\n\nvar stackTop uintptr\n\nfunc ticksToNanoseconds(ticks timeUnit) int64 {\n\t// Interrupt time count works in units of 100 nanoseconds.\n\treturn int64(ticks) * 100\n}\n\nfunc nanosecondsToTicks(ns int64) timeUnit {\n\t// Interrupt time count works in units of 100 nanoseconds.\n\treturn timeUnit(ns) / 100\n}\n\nfunc sleepTicks(d timeUnit) {\n\t// Calculate milliseconds from ticks (which have a resolution of 100ns),\n\t// rounding up.\n\tmilliseconds := int64(d+9_999) / 10_000\n\tfor milliseconds != 0 {\n\t\tduration := uint32(milliseconds)\n\t\t_Sleep(duration)\n\t\tmilliseconds -= int64(duration)\n\t}\n}\n\n//export QueryPerformanceFrequency\nfunc _QueryPerformanceFrequency(*int64) bool\n\n//export QueryPerformanceCounter\nfunc _QueryPerformanceCounter(*int64) bool\n\nfunc ticks() timeUnit {\n\tif GOARCH == \"386\" {\n\t\t// Unfortunately QueryUnbiasedInterruptTime is only available starting\n\t\t// with Windows 7.\n\n\t\t// Obtain counter (that runs at a fixed frequency).\n\t\tvar counter int64\n\t\t_QueryPerformanceCounter(&counter)\n\t\t// Convert this counter to ticks of 100ns (just like\n\t\t// QueryUnbiasedInterruptTime).\n\t\t// (We could also change the definition of ticks on GOOS=386 but that\n\t\t// seems messy).\n\t\treturn timeUnit((counter * 10000000) / performanceFrequency)\n\t} else {\n\t\tvar unbiasedTime uint64\n\t\t_QueryUnbiasedInterruptTime(&unbiasedTime)\n\t\treturn timeUnit(unbiasedTime)\n\t}\n}\n\n//go:linkname now time.now\nfunc now() (sec int64, nsec int32, mono int64) {\n\t// Get the current time in Windows \"file time\" format.\n\tvar time uint64\n\t_GetSystemTimeAsFileTime(&time)\n\n\t// Convert file time to Unix time.\n\t// According to the documentation:\n\t// > Contains a 64-bit value representing the number of 100-nanosecond\n\t// > intervals since January 1, 1601 (UTC).\n\t// We'll convert it to 100 nanosecond intervals starting at 1970.\n\tconst (\n\t\t// number of 100-nanosecond intervals in a second\n\t\tintervalsPerSecond = 10_000_000\n\t\tsecondsPerDay      = 60 * 60 * 24\n\t\t// Number of days between the Windows epoch (1 january 1601) and the\n\t\t// Unix epoch (1 january 1970). Source:\n\t\t// https://www.wolframalpha.com/input/?i=days+between+1+january+1601+and+1+january+1970\n\t\tdays = 134774\n\t)\n\ttime -= days * secondsPerDay * intervalsPerSecond\n\n\t// Convert the time (in 100ns units) to sec/nsec/mono as expected by the\n\t// time package.\n\tsec = int64(time / intervalsPerSecond)\n\tnsec = int32((time - (uint64(sec) * intervalsPerSecond)) * 100)\n\tmono = ticksToNanoseconds(ticks())\n\treturn\n}\n\n//go:linkname syscall_Exit syscall.Exit\nfunc syscall_Exit(code int) {\n\tlibc_exit(code)\n}\n\nfunc growHeap() bool {\n\tif heapSize == heapMaxSize {\n\t\t// Already at the max. If we run out of memory, we should consider\n\t\t// increasing heapMaxSize..\n\t\treturn false\n\t}\n\t// Grow the heap size used by the program.\n\theapSize = (heapSize * 4 / 3) &^ 4095 // grow by around 33%\n\tif heapSize > heapMaxSize {\n\t\theapSize = heapMaxSize\n\t}\n\tsetHeapEnd(heapStart + heapSize)\n\treturn true\n}\n\n//go:linkname syscall_loadsystemlibrary syscall.loadsystemlibrary\nfunc syscall_loadsystemlibrary(filename *uint16, absoluteFilepath *uint16) (handle, err uintptr) {\n\thandle = _LoadLibraryExW(filename, 0, _LOAD_LIBRARY_SEARCH_SYSTEM32)\n\tif handle == 0 {\n\t\tpanic(\"todo: get error\")\n\t}\n\treturn\n}\n\n//go:linkname syscall_loadlibrary syscall.loadlibrary\nfunc syscall_loadlibrary(filename *uint16) (handle, err uintptr) {\n\tpanic(\"todo: syscall.loadlibrary\")\n}\n\n//go:linkname syscall_getprocaddress syscall.getprocaddress\nfunc syscall_getprocaddress(handle uintptr, procname *byte) (outhandle, err uintptr) {\n\touthandle = getProcAddress(handle, procname)\n\tif outhandle == 0 {\n\t\tpanic(\"todo: get error\")\n\t}\n\treturn\n}\n\n// TinyGo does not yet support any form of parallelism on Windows, so these can\n// be left empty.\n\n//go:linkname procPin sync/atomic.runtime_procPin\nfunc procPin() {\n}\n\n//go:linkname procUnpin sync/atomic.runtime_procUnpin\nfunc procUnpin() {\n}\n\nfunc hardwareRand() (n uint64, ok bool) {\n\t// Use the old RtlGenRandom, introduced in Windows XP.\n\t// See the rationale in src/crypto/rand/rand_windows.go for why we use this\n\t// one.\n\tok = _RtlGenRandom(unsafe.Pointer(&n), 8)\n\treturn\n}\n\n// This function is part of advapi32.dll, and is called SystemFunction036 for\n// some reason. It's available on Windows XP and newer.\n// See: https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom\n//\n//export SystemFunction036\nfunc _RtlGenRandom(buf unsafe.Pointer, len int) bool\n"
  },
  {
    "path": "src/runtime/scheduler.go",
    "content": "package runtime\n\nimport \"internal/task\"\n\nconst schedulerDebug = false\n\nvar timerQueue *timerNode\n\n// Simple logging, for debugging.\nfunc scheduleLog(msg string) {\n\tif schedulerDebug {\n\t\tprintln(\"---\", msg)\n\t}\n}\n\n// Simple logging with a task pointer, for debugging.\nfunc scheduleLogTask(msg string, t *task.Task) {\n\tif schedulerDebug {\n\t\tprintln(\"---\", msg, t)\n\t}\n}\n\n// Simple logging with a channel and task pointer.\nfunc scheduleLogChan(msg string, ch *channel, t *task.Task) {\n\tif schedulerDebug {\n\t\tprintln(\"---\", msg, ch, t)\n\t}\n}\n\nfunc timerQueueAdd(tn *timerNode) {\n\tq := &timerQueue\n\tfor ; *q != nil; q = &(*q).next {\n\t\tif tn.whenTicks() < (*q).whenTicks() {\n\t\t\t// this will finish earlier than the next - insert here\n\t\t\tbreak\n\t\t}\n\t}\n\ttn.next = *q\n\t*q = tn\n}\n\nfunc timerQueueRemove(t *timer) *timerNode {\n\tfor q := &timerQueue; *q != nil; q = &(*q).next {\n\t\tif (*q).timer == t {\n\t\t\tscheduleLog(\"removed timer\")\n\t\t\tn := *q\n\t\t\t*q = (*q).next\n\t\t\treturn n\n\t\t}\n\t}\n\tscheduleLog(\"did not remove timer\")\n\treturn nil\n}\n\n// Goexit terminates the currently running goroutine. No other goroutines are affected.\nfunc Goexit() {\n\tpanicOrGoexit(nil, panicGoexit)\n}\n\n//go:linkname fips_getIndicator crypto/internal/fips140.getIndicator\nfunc fips_getIndicator() uint8 {\n\treturn task.Current().FipsIndicator\n}\n\n//go:linkname fips_setIndicator crypto/internal/fips140.setIndicator\nfunc fips_setIndicator(indicator uint8) {\n\t// This indicator is stored per goroutine.\n\ttask.Current().FipsIndicator = indicator\n}\n"
  },
  {
    "path": "src/runtime/scheduler_cooperative.go",
    "content": "//go:build scheduler.tasks || scheduler.asyncify\n\npackage runtime\n\n// This file implements the TinyGo scheduler. This scheduler is a very simple\n// cooperative round robin scheduler, with a runqueue that contains a linked\n// list of goroutines (tasks) that should be run next, in order of when they\n// were added to the queue (first-in, first-out). It also contains a sleep queue\n// with sleeping goroutines in order of when they should be re-activated.\n//\n// The scheduler is used both for the asyncify based scheduler and for the task\n// based scheduler. In both cases, the 'internal/task.Task' type is used to represent one\n// goroutine.\n\nimport (\n\t\"internal/task\"\n\t\"runtime/interrupt\"\n)\n\n// On JavaScript, we can't do a blocking sleep. Instead we have to return and\n// queue a new scheduler invocation using setTimeout.\nconst asyncScheduler = GOOS == \"js\"\n\nconst hasScheduler = true\n\n// Concurrency is not parallelism. While the cooperative scheduler has\n// concurrency, it does not have parallelism.\nconst hasParallelism = false\n\n// Set to true after main.main returns.\nvar mainExited bool\n\n// Set to true when the scheduler should exit after the next switch to the\n// scheduler. This is a special case for //go:wasmexport.\nvar schedulerExit bool\n\n// Queues used by the scheduler.\nvar (\n\trunqueue           task.Queue\n\tsleepQueue         *task.Task\n\tsleepQueueBaseTime timeUnit\n)\n\n// deadlock is called when a goroutine cannot proceed any more, but is in theory\n// not exited (so deferred calls won't run). This can happen for example in code\n// like this, that blocks forever:\n//\n//\tselect{}\n//\n//go:noinline\nfunc deadlock() {\n\t// call yield without requesting a wakeup\n\ttask.Pause()\n\tpanic(\"unreachable\")\n}\n\n// Add this task to the end of the run queue.\nfunc scheduleTask(t *task.Task) {\n\trunqueue.Push(t)\n}\n\nfunc Gosched() {\n\trunqueue.Push(task.Current())\n\ttask.Pause()\n}\n\n// NumCPU returns the number of logical CPUs usable by the current process.\nfunc NumCPU() int {\n\treturn 1\n}\n\n// Add this task to the sleep queue, assuming its state is set to sleeping.\nfunc addSleepTask(t *task.Task, duration timeUnit) {\n\tif schedulerDebug {\n\t\tprintln(\"  set sleep:\", t, duration)\n\t\tif t.Next != nil {\n\t\t\tpanic(\"runtime: addSleepTask: expected next task to be nil\")\n\t\t}\n\t}\n\tnow := ticks()\n\tif sleepQueue == nil {\n\t\tscheduleLog(\"  -> sleep new queue\")\n\n\t\t// set new base time\n\t\tsleepQueueBaseTime = now\n\t}\n\tt.Data = uint64(duration + (now - sleepQueueBaseTime))\n\n\t// Add to sleep queue.\n\tq := &sleepQueue\n\tfor ; *q != nil; q = &(*q).Next {\n\t\tif t.Data < (*q).Data {\n\t\t\t// this will finish earlier than the next - insert here\n\t\t\tbreak\n\t\t} else {\n\t\t\t// this will finish later - adjust delay\n\t\t\tt.Data -= (*q).Data\n\t\t}\n\t}\n\tif *q != nil {\n\t\t// cut delay time between this sleep task and the next\n\t\t(*q).Data -= t.Data\n\t}\n\tt.Next = *q\n\t*q = t\n}\n\n// addTimer adds the given timer node to the timer queue. It must not be in the\n// queue already.\n// This function is very similar to addSleepTask but for timerQueue instead of\n// sleepQueue.\nfunc addTimer(tim *timerNode) {\n\tmask := interrupt.Disable()\n\ttimerQueueAdd(tim)\n\tinterrupt.Restore(mask)\n}\n\n// removeTimer is the implementation of time.stopTimer. It removes a timer from\n// the timer queue, returning it if the timer is present in the timer queue.\nfunc removeTimer(tim *timer) *timerNode {\n\tmask := interrupt.Disable()\n\tn := timerQueueRemove(tim)\n\tinterrupt.Restore(mask)\n\treturn n\n}\n\nfunc schedulerRunQueue() *task.Queue {\n\treturn &runqueue\n}\n\n// Run the scheduler until all tasks have finished.\n// There are a few special cases:\n//   - When returnAtDeadlock is true, it also returns when there are no more\n//     runnable goroutines.\n//   - When using the asyncify scheduler, it returns when it has to wait\n//     (JavaScript uses setTimeout so the scheduler must return to the JS\n//     environment).\nfunc scheduler(returnAtDeadlock bool) {\n\t// Main scheduler loop.\n\tvar now timeUnit\n\tfor !mainExited {\n\t\tscheduleLog(\"\")\n\t\tscheduleLog(\"  schedule\")\n\t\tif sleepQueue != nil || timerQueue != nil {\n\t\t\tnow = ticks()\n\t\t}\n\n\t\t// Add tasks that are done sleeping to the end of the runqueue so they\n\t\t// will be executed soon.\n\t\tif sleepQueue != nil && now-sleepQueueBaseTime >= timeUnit(sleepQueue.Data) {\n\t\t\tt := sleepQueue\n\t\t\tscheduleLogTask(\"  awake:\", t)\n\t\t\tsleepQueueBaseTime += timeUnit(t.Data)\n\t\t\tsleepQueue = t.Next\n\t\t\tt.Next = nil\n\t\t\trunqueue.Push(t)\n\t\t}\n\n\t\t// Check for expired timers to trigger.\n\t\tif timerQueue != nil && now >= timerQueue.whenTicks() {\n\t\t\tscheduleLog(\"--- timer awoke\")\n\t\t\tdelay := ticksToNanoseconds(now - timerQueue.whenTicks())\n\t\t\t// Pop timer from queue.\n\t\t\ttn := timerQueue\n\t\t\ttimerQueue = tn.next\n\t\t\ttn.next = nil\n\t\t\t// Run the callback stored in this timer node.\n\t\t\ttn.callback(tn, delay)\n\t\t}\n\n\t\tt := runqueue.Pop()\n\t\tif t == nil {\n\t\t\tif sleepQueue == nil && timerQueue == nil {\n\t\t\t\tif returnAtDeadlock {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif asyncScheduler {\n\t\t\t\t\t// JavaScript is treated specially, see below.\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\twaitForEvents()\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tvar timeLeft timeUnit\n\t\t\tif sleepQueue != nil {\n\t\t\t\ttimeLeft = timeUnit(sleepQueue.Data) - (now - sleepQueueBaseTime)\n\t\t\t}\n\t\t\tif timerQueue != nil {\n\t\t\t\ttimeLeftForTimer := timerQueue.whenTicks() - now\n\t\t\t\tif sleepQueue == nil || timeLeftForTimer < timeLeft {\n\t\t\t\t\ttimeLeft = timeLeftForTimer\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif schedulerDebug {\n\t\t\t\tprintln(\"  sleeping...\", sleepQueue, uint(timeLeft))\n\t\t\t\tfor t := sleepQueue; t != nil; t = t.Next {\n\t\t\t\t\tprintln(\"    task sleeping:\", t, timeUnit(t.Data))\n\t\t\t\t}\n\t\t\t\tfor tim := timerQueue; tim != nil; tim = tim.next {\n\t\t\t\t\tprintln(\"---   timer waiting:\", tim, tim.whenTicks())\n\t\t\t\t}\n\t\t\t}\n\t\t\tif timeLeft > 0 {\n\t\t\t\tsleepTicks(timeLeft)\n\t\t\t\tif asyncScheduler {\n\t\t\t\t\t// The sleepTicks function above only sets a timeout at\n\t\t\t\t\t// which point the scheduler will be called again. It does\n\t\t\t\t\t// not really sleep. So instead of sleeping, we return and\n\t\t\t\t\t// expect to be called again.\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// Run the given task.\n\t\tscheduleLogTask(\"  run:\", t)\n\t\tt.Resume()\n\n\t\t// The last call to Resume() was a signal to stop the scheduler since a\n\t\t// //go:wasmexport function returned.\n\t\tif GOARCH == \"wasm\" && schedulerExit {\n\t\t\tschedulerExit = false // reset the signal\n\t\t\treturn\n\t\t}\n\t}\n}\n\n// Pause the current task for a given time.\n//\n//go:linkname sleep time.Sleep\nfunc sleep(duration int64) {\n\tif duration <= 0 {\n\t\treturn\n\t}\n\n\taddSleepTask(task.Current(), nanosecondsToTicks(duration))\n\ttask.Pause()\n}\n\n// run is called by the program entry point to execute the go program.\n// With a scheduler, init and the main function are invoked in a goroutine before starting the scheduler.\nfunc run() {\n\tinitRand()\n\tinitHeap()\n\tgo func() {\n\t\tinitAll()\n\t\tcallMain()\n\t\tmainExited = true\n\t}()\n\tscheduler(false)\n}\n\nfunc lockAtomics() interrupt.State {\n\treturn interrupt.Disable()\n}\n\nfunc unlockAtomics(mask interrupt.State) {\n\tinterrupt.Restore(mask)\n}\n\nfunc printlock() {\n\t// nothing to do\n}\n\nfunc printunlock() {\n\t// nothing to do\n}\n"
  },
  {
    "path": "src/runtime/scheduler_cores.go",
    "content": "//go:build scheduler.cores\n\npackage runtime\n\nimport (\n\t\"internal/task\"\n\t\"runtime/interrupt\"\n\t\"sync/atomic\"\n)\n\nconst hasScheduler = true\n\nconst hasParallelism = true\n\nvar mainExited atomic.Uint32\n\n// True after the secondary cores have started.\nvar secondaryCoresStarted bool\n\n// Which task is running on a given core (or nil if there is no task running on\n// the core).\nvar cpuTasks [numCPU]*task.Task\n\nvar (\n\tsleepQueue *task.Task\n\trunqueue   task.Queue\n)\n\nfunc deadlock() {\n\t// Call yield without requesting a wakeup.\n\ttask.Pause()\n\ttrap()\n}\n\n// Mark the given task as ready to resume.\n// This is allowed even if the task isn't paused yet, but will pause soon.\nfunc scheduleTask(t *task.Task) {\n\tschedulerLock.Lock()\n\tswitch t.RunState {\n\tcase task.RunStatePaused:\n\t\t// Paused, state is saved on the stack.\n\t\t// Add it to the runqueue...\n\t\trunqueue.Push(t)\n\t\t// ...and wake up a sleeping core, if there is one.\n\t\t// (If all cores are already busy, this is a no-op).\n\t\tschedulerWake()\n\tcase task.RunStateRunning:\n\t\t// Not yet paused (probably going to pause very soon), so let the\n\t\t// Pause() function know it can resume immediately.\n\t\tt.RunState = task.RunStateResuming\n\tdefault:\n\t\tif schedulerAsserts {\n\t\t\truntimePanic(\"scheduler: unknown run state\")\n\t\t}\n\t}\n\tschedulerLock.Unlock()\n}\n\nfunc addSleepTask(t *task.Task, wakeup timeUnit) {\n\t// Save the timestamp when the task should be woken up.\n\tt.Data = uint64(wakeup)\n\n\t// If another core is currently using the timer, make sure it wakes up at\n\t// the right time.\n\tinterruptSleepTicksMulticore(wakeup)\n\n\t// Find the position where we should insert this task in the queue.\n\tq := &sleepQueue\n\tfor {\n\t\tif *q == nil {\n\t\t\t// Found the end of the time queue. Insert it here, at the end.\n\t\t\tbreak\n\t\t}\n\t\tif timeUnit((*q).Data) > timeUnit(t.Data) {\n\t\t\t// Found a task in the queue that has a timeout before the\n\t\t\t// to-be-sleeping task. Insert our task right before.\n\t\t\tbreak\n\t\t}\n\t\tq = &(*q).Next\n\t}\n\n\t// Insert the task into the queue (this could be at the end, if *q is nil).\n\tt.Next = *q\n\t*q = t\n}\n\nfunc Gosched() {\n\tschedulerLock.Lock()\n\trunqueue.Push(task.Current())\n\ttask.PauseLocked()\n}\n\n// NumCPU returns the number of CPU cores on this system.\nfunc NumCPU() int {\n\treturn numCPU\n}\n\nfunc addTimer(tn *timerNode) {\n\tschedulerLock.Lock()\n\ttimerQueueAdd(tn)\n\tinterruptSleepTicksMulticore(tn.whenTicks())\n\tschedulerLock.Unlock()\n}\n\nfunc removeTimer(t *timer) *timerNode {\n\tschedulerLock.Lock()\n\tn := timerQueueRemove(t)\n\tschedulerLock.Unlock()\n\treturn n\n}\n\nfunc schedulerRunQueue() *task.Queue {\n\treturn &runqueue\n}\n\n// Pause the current task for a given time.\n//\n//go:linkname sleep time.Sleep\nfunc sleep(duration int64) {\n\tif duration <= 0 {\n\t\treturn\n\t}\n\n\twakeup := ticks() + nanosecondsToTicks(duration)\n\n\t// While the scheduler is locked:\n\t// - add this task to the sleep queue\n\t// - switch to the scheduler (only allowed while locked)\n\t// - let the scheduler handle it from there\n\tschedulerLock.Lock()\n\taddSleepTask(task.Current(), wakeup)\n\ttask.PauseLocked()\n}\n\n// This function is called on the first core in the system. It will wake up the\n// other cores when ready.\nfunc run() {\n\tinitRand()\n\tinitHeap()\n\n\tgo func() {\n\t\t// Package initializers are currently run single-threaded.\n\t\t// This might help with registering interrupts and such.\n\t\tinitAll()\n\n\t\t// After package initializers have finished, start all the other cores.\n\t\tstartSecondaryCores()\n\t\tsecondaryCoresStarted = true\n\n\t\t// Run main.main.\n\t\tcallMain()\n\n\t\t// main.main has exited, so the program should exit.\n\t\tmainExited.Store(1)\n\t}()\n\n\t// The scheduler must always be entered while the scheduler lock is taken.\n\tschedulerLock.Lock()\n\tscheduler(false)\n\tschedulerLock.Unlock()\n}\n\nfunc scheduler(_ bool) {\n\tfor mainExited.Load() == 0 {\n\t\t// Check for ready-to-run tasks.\n\t\tif runnable := runqueue.Pop(); runnable != nil {\n\t\t\t// Resume it now.\n\t\t\tsetCurrentTask(runnable)\n\t\t\trunnable.RunState = task.RunStateRunning\n\t\t\tschedulerLock.Unlock() // unlock before resuming, Pause() will lock again\n\t\t\trunnable.Resume()\n\t\t\tsetCurrentTask(nil)\n\n\t\t\tcontinue\n\t\t}\n\n\t\tvar now timeUnit\n\t\tif sleepQueue != nil || timerQueue != nil {\n\t\t\tnow = ticks()\n\n\t\t\t// Check whether the first task in the sleep queue is ready to run.\n\t\t\tif sleepingTask := sleepQueue; sleepingTask != nil && now >= timeUnit(sleepingTask.Data) {\n\t\t\t\t// It is, pop it from the queue.\n\t\t\t\tsleepQueue = sleepQueue.Next\n\t\t\t\tsleepingTask.Next = nil\n\n\t\t\t\t// Run it now.\n\t\t\t\tsetCurrentTask(sleepingTask)\n\t\t\t\tsleepingTask.RunState = task.RunStateRunning\n\t\t\t\tschedulerLock.Unlock() // unlock before resuming, Pause() will lock again\n\t\t\t\tsleepingTask.Resume()\n\t\t\t\tsetCurrentTask(nil)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Check whether a timer has expired that needs to be run.\n\t\t\tif timerQueue != nil && now >= timerQueue.whenTicks() {\n\t\t\t\tdelay := ticksToNanoseconds(now - timerQueue.whenTicks())\n\t\t\t\t// Pop timer from queue.\n\t\t\t\ttn := timerQueue\n\t\t\t\ttimerQueue = tn.next\n\t\t\t\ttn.next = nil\n\n\t\t\t\t// Run the callback stored in this timer node.\n\t\t\t\tschedulerLock.Unlock()\n\t\t\t\ttn.callback(tn, delay)\n\t\t\t\tschedulerLock.Lock()\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\n\t\t// At this point, there are no runnable tasks anymore.\n\t\t// If another core is using the clock, let it handle the sleep queue.\n\t\tif hasSleepingCore() {\n\t\t\tschedulerUnlockAndWait()\n\t\t\tcontinue\n\t\t}\n\n\t\t// The timer is free to use, so check whether there are any future\n\t\t// tasks/timers that we can wait for.\n\t\tvar timeLeft timeUnit\n\t\tif sleepingTask := sleepQueue; sleepingTask != nil {\n\t\t\t// We already checked that there is no ready-to-run sleeping task\n\t\t\t// (using the same 'now' value), so timeLeft will always be\n\t\t\t// positive.\n\t\t\ttimeLeft = timeUnit(sleepingTask.Data) - now\n\t\t}\n\t\tif timerQueue != nil {\n\t\t\t// If the timer queue needs to run earlier, reduce the time we are\n\t\t\t// going to sleep.\n\t\t\t// Like with sleepQueue, we already know there is no timer ready to\n\t\t\t// run since we already checked above.\n\t\t\ttimeLeftForTimer := timerQueue.whenTicks() - now\n\t\t\tif sleepQueue == nil || timeLeftForTimer < timeLeft {\n\t\t\t\ttimeLeft = timeLeftForTimer\n\t\t\t}\n\t\t}\n\n\t\tif timeLeft > 0 {\n\t\t\t// Sleep for a bit until the next task or timer is ready to run.\n\t\t\tsleepTicksMulticore(timeLeft)\n\t\t\tcontinue\n\t\t}\n\n\t\t// No runnable tasks and no sleeping tasks or timers. There's nothing to\n\t\t// do.\n\t\t// Wait until something happens (like an interrupt).\n\t\tschedulerUnlockAndWait()\n\t}\n}\n\nfunc currentTask() *task.Task {\n\treturn cpuTasks[currentCPU()]\n}\n\nfunc setCurrentTask(task *task.Task) {\n\tcpuTasks[currentCPU()] = task\n}\n\nfunc lockScheduler() {\n\tschedulerLock.Lock()\n}\n\nfunc unlockScheduler() {\n\tschedulerLock.Unlock()\n}\n\nfunc lockFutex() interrupt.State {\n\tmask := interrupt.Disable()\n\tfutexLock.Lock()\n\treturn mask\n}\n\nfunc unlockFutex(state interrupt.State) {\n\tfutexLock.Unlock()\n\tinterrupt.Restore(state)\n}\n\n// Use a single spinlock for atomics. This works fine, since atomics are very\n// short sequences of instructions.\nfunc lockAtomics() interrupt.State {\n\tmask := interrupt.Disable()\n\tatomicsLock.Lock()\n\treturn mask\n}\n\nfunc unlockAtomics(mask interrupt.State) {\n\tatomicsLock.Unlock()\n\tinterrupt.Restore(mask)\n}\n\nvar systemStack [numCPU]uintptr\n\n// Implementation detail of the internal/task package.\n// It needs to store the system stack pointer somewhere, and needs to know how\n// many cores there are to do so. But it doesn't know the number of cores. Hence\n// why this is implemented in the runtime.\nfunc systemStackPtr() *uintptr {\n\treturn &systemStack[currentCPU()]\n}\n\n// Color the 'print' and 'println' output according to the current CPU.\n// This may be helpful for debugging, but should be disabled otherwise.\nconst cpuColoredPrint = false\n\nfunc printlock() {\n\t// Don't lock the print output inside an interrupt.\n\t// Locking the print output inside an interrupt can lead to a deadlock: if\n\t// the interrupt happens while the print lock is held, the interrupt won't\n\t// be able to take this lock anymore.\n\t// This isn't great, but the alternative would be to disable interrupts\n\t// while printing which seems like a worse idea to me.\n\tif !interrupt.In() {\n\t\tprintLock.Lock()\n\t}\n\n\tif cpuColoredPrint {\n\t\tswitch currentCPU() {\n\t\tcase 1:\n\t\t\tprintstring(\"\\x1b[32m\") // green\n\t\tcase 2:\n\t\t\tprintstring(\"\\x1b[33m\") // yellow\n\t\tcase 3:\n\t\t\tprintstring(\"\\x1b[34m\") // blue\n\t\t}\n\t}\n}\n\nfunc printunlock() {\n\tif cpuColoredPrint {\n\t\tif currentCPU() != 0 {\n\t\t\tprintstring(\"\\x1b[0m\") // reset colored output\n\t\t}\n\t}\n\n\tif !interrupt.In() {\n\t\tprintLock.Unlock()\n\t}\n}\n"
  },
  {
    "path": "src/runtime/scheduler_none.go",
    "content": "//go:build scheduler.none\n\npackage runtime\n\nimport (\n\t\"internal/task\"\n\t\"runtime/interrupt\"\n)\n\nconst hasScheduler = false\n\n// No goroutines are allowed, so there's no parallelism anywhere.\nconst hasParallelism = false\n\n// Set to true after main.main returns.\nvar mainExited bool\n\n// dummy flag, not used without scheduler\nvar schedulerExit bool\n\n// run is called by the program entry point to execute the go program.\n// With the \"none\" scheduler, init and the main function are invoked directly.\nfunc run() {\n\tinitRand()\n\tinitHeap()\n\tinitAll()\n\tcallMain()\n\tmainExited = true\n}\n\n//go:linkname sleep time.Sleep\nfunc sleep(duration int64) {\n\tif duration <= 0 {\n\t\treturn\n\t}\n\n\tsleepTicks(nanosecondsToTicks(duration))\n}\n\nfunc deadlock() {\n\t// The only goroutine available is deadlocked.\n\truntimePanic(\"all goroutines are asleep - deadlock!\")\n}\n\nfunc scheduleTask(t *task.Task) {\n\t// Pause() will panic, so this should not be reachable.\n}\n\nfunc Gosched() {\n\t// There are no other goroutines, so there's nothing to schedule.\n}\n\n// NumCPU returns the number of logical CPUs usable by the current process.\nfunc NumCPU() int {\n\treturn 1\n}\n\nfunc addTimer(tim *timerNode) {\n\truntimePanic(\"timers not supported without a scheduler\")\n}\n\nfunc removeTimer(tim *timer) *timerNode {\n\truntimePanic(\"timers not supported without a scheduler\")\n\treturn nil\n}\n\nfunc schedulerRunQueue() *task.Queue {\n\t// This function is not actually used, it is only called when hasScheduler\n\t// is true.\n\truntimePanic(\"unreachable: no runqueue without a scheduler\")\n\treturn nil\n}\n\nfunc scheduler(returnAtDeadlock bool) {\n\t// The scheduler should never be run when using -scheduler=none. Meaning,\n\t// this code should be unreachable.\n\truntimePanic(\"unreachable: scheduler must not be called with the 'none' scheduler\")\n}\n\nfunc lockAtomics() interrupt.State {\n\treturn interrupt.Disable()\n}\n\nfunc unlockAtomics(mask interrupt.State) {\n\tinterrupt.Restore(mask)\n}\n\nfunc printlock() {\n\t// nothing to do\n}\n\nfunc printunlock() {\n\t// nothing to do\n}\n"
  },
  {
    "path": "src/runtime/scheduler_tasks.go",
    "content": "//go:build scheduler.tasks\n\npackage runtime\n\nvar systemStack uintptr\n\n// Implementation detail of the internal/task package.\n// It needs to store the system stack pointer somewhere, and needs to know how\n// many cores there are to do so. But it doesn't know the number of cores. Hence\n// why this is implemented in the runtime.\nfunc systemStackPtr() *uintptr {\n\treturn &systemStack\n}\n"
  },
  {
    "path": "src/runtime/scheduler_threads.go",
    "content": "//go:build scheduler.threads\n\npackage runtime\n\nimport (\n\t\"internal/task\"\n\t\"runtime/interrupt\"\n)\n\nconst hasScheduler = false // not using the cooperative scheduler\n\n// We use threads, so yes there is parallelism.\nconst hasParallelism = true\n\nvar (\n\ttimerQueueLock    task.PMutex\n\ttimerQueueStarted bool\n\ttimerFutex        task.Futex\n)\n\n// Because we just use OS threads, we don't need to do anything special here. We\n// can just initialize everything and run main.main on the main thread.\nfunc run() {\n\tinitRand()\n\tinitHeap()\n\ttask.Init(stackTop)\n\tinitAll()\n\tcallMain()\n}\n\n// Pause the current task for a given time.\n//\n//go:linkname sleep time.Sleep\nfunc sleep(duration int64) {\n\tif duration <= 0 {\n\t\treturn\n\t}\n\n\tsleepTicks(nanosecondsToTicks(duration))\n}\n\nfunc deadlock() {\n\t// TODO: exit the thread via pthread_exit.\n\ttask.Pause()\n}\n\nfunc scheduleTask(t *task.Task) {\n\tt.Resume()\n}\n\nfunc Gosched() {\n\t// Each goroutine runs in a thread, so there's not much we can do here.\n\t// There is sched_yield but it's only really intended for realtime\n\t// operation, so is probably best not to use.\n}\n\n// NumCPU returns the number of logical CPUs usable by the current process.\nfunc NumCPU() int {\n\treturn task.NumCPU()\n}\n\n// Separate goroutine (thread) that runs timer callbacks when they expire.\nfunc timerRunner() {\n\tfor {\n\t\ttimerQueueLock.Lock()\n\n\t\tif timerQueue == nil {\n\t\t\t// No timer in the queue, so wait until one becomes available.\n\t\t\tval := timerFutex.Load()\n\t\t\ttimerQueueLock.Unlock()\n\t\t\ttimerFutex.Wait(val)\n\t\t\tcontinue\n\t\t}\n\n\t\tnow := ticks()\n\t\tif now < timerQueue.whenTicks() {\n\t\t\t// There is a timer in the queue, but we need to wait until it\n\t\t\t// expires.\n\t\t\t// Using a futex, so that the wait is exited early when adding a new\n\t\t\t// (sooner-to-expire) timer.\n\t\t\tval := timerFutex.Load()\n\t\t\ttimerQueueLock.Unlock()\n\t\t\ttimeout := ticksToNanoseconds(timerQueue.whenTicks() - now)\n\t\t\ttimerFutex.WaitUntil(val, uint64(timeout))\n\t\t\tcontinue\n\t\t}\n\n\t\t// Pop timer from queue.\n\t\ttn := timerQueue\n\t\ttimerQueue = tn.next\n\t\ttn.next = nil\n\n\t\ttimerQueueLock.Unlock()\n\n\t\t// Run the callback stored in this timer node.\n\t\tdelay := ticksToNanoseconds(now - tn.whenTicks())\n\t\ttn.callback(tn, delay)\n\t}\n}\n\nfunc addTimer(tim *timerNode) {\n\ttimerQueueLock.Lock()\n\n\tif !timerQueueStarted {\n\t\ttimerQueueStarted = true\n\t\tgo timerRunner()\n\t}\n\n\ttimerQueueAdd(tim)\n\n\ttimerFutex.Add(1)\n\ttimerFutex.Wake()\n\n\ttimerQueueLock.Unlock()\n}\n\nfunc removeTimer(tim *timer) *timerNode {\n\ttimerQueueLock.Lock()\n\tn := timerQueueRemove(tim)\n\ttimerQueueLock.Unlock()\n\treturn n\n}\n\nfunc schedulerRunQueue() *task.Queue {\n\t// This function is not actually used, it is only called when hasScheduler\n\t// is true. So we can just return nil here.\n\treturn nil\n}\n\nfunc runqueueForGC() *task.Queue {\n\t// There is only a runqueue when using the cooperative scheduler.\n\treturn nil\n}\n\n// Lock to make sure print calls do not interleave.\nvar printLock task.Mutex\n\nfunc printlock() {\n\tprintLock.Lock()\n}\n\nfunc printunlock() {\n\tprintLock.Unlock()\n}\n\n// The atomics lock isn't used as a lock for actual atomics. It is used inside\n// internal/task.Stack and internal/task.Queue to make sure their operations are\n// actually atomic. (This might not actually be needed, since the use in\n// sync.Cond doesn't need atomicity).\n\nvar atomicsLock task.Mutex\n\nfunc lockAtomics() interrupt.State {\n\tatomicsLock.Lock()\n\treturn 0\n}\n\nfunc unlockAtomics(mask interrupt.State) {\n\tatomicsLock.Unlock()\n}\n"
  },
  {
    "path": "src/runtime/signal.c",
    "content": "//go:build none\n\n// Ignore the //go:build above. This file is manually included on Linux and\n// MacOS to provide os/signal support.\n\n#include <stdint.h>\n#include <signal.h>\n#include <time.h>\n#include <unistd.h>\n\n// Signal handler in the runtime.\nvoid tinygo_signal_handler(int sig);\n\n// Enable a signal from the runtime.\nvoid tinygo_signal_enable(uint32_t sig) {\n    struct sigaction act = { 0 };\n    act.sa_handler = &tinygo_signal_handler;\n    act.sa_flags = SA_RESTART;\n    sigaction(sig, &act, NULL);\n}\n\nvoid tinygo_signal_ignore(uint32_t sig) {\n    struct sigaction act = { 0 };\n    act.sa_handler = SIG_IGN;\n    sigaction(sig, &act, NULL);\n}\n\nvoid tinygo_signal_disable(uint32_t sig) {\n    struct sigaction act = { 0 };\n    act.sa_handler = SIG_DFL;\n    sigaction(sig, &act, NULL);\n}\n"
  },
  {
    "path": "src/runtime/signalstub.go",
    "content": "//go:build tinygo.wasm || baremetal\n\npackage runtime\n\n// Some platforms don't support Unix signals (and never will), so we need to\n// stub the signal functions.\n\n//go:linkname signal_disable os/signal.signal_disable\nfunc signal_disable(uint32) {}\n\n//go:linkname signal_enable os/signal.signal_enable\nfunc signal_enable(uint32) {}\n\n//go:linkname signal_ignore os/signal.signal_ignore\nfunc signal_ignore(uint32) {}\n\n//go:linkname signal_waitUntilIdle os/signal.signalWaitUntilIdle\nfunc signal_waitUntilIdle() {}\n\n//go:linkname signal_recv os/signal.signal_recv\nfunc signal_recv() uint32 { return ^uint32(0) }\n"
  },
  {
    "path": "src/runtime/slice.go",
    "content": "package runtime\n\n// This file implements compiler builtins for slices: append() and copy().\n\nimport (\n\t\"internal/gclayout\"\n\t\"math/bits\"\n\t\"unsafe\"\n)\n\n// Builtin append(src, elements...) function: append elements to src and return\n// the modified (possibly expanded) slice.\nfunc sliceAppend(srcBuf, elemsBuf unsafe.Pointer, srcLen, srcCap, elemsLen, elemSize uintptr) (unsafe.Pointer, uintptr, uintptr) {\n\tnewLen := srcLen + elemsLen\n\tif elemsLen > 0 {\n\t\t// Allocate a new slice with capacity for elemsLen more elements, if necessary;\n\t\t// otherwise, reuse the passed slice.\n\t\tsrcBuf, _, srcCap = sliceGrow(srcBuf, srcLen, srcCap, newLen, elemSize)\n\n\t\t// Append the new elements in-place.\n\t\tmemmove(unsafe.Add(srcBuf, srcLen*elemSize), elemsBuf, elemsLen*elemSize)\n\t}\n\n\treturn srcBuf, newLen, srcCap\n}\n\n// Builtin copy(dst, src) function: copy bytes from dst to src.\nfunc sliceCopy(dst, src unsafe.Pointer, dstLen, srcLen uintptr, elemSize uintptr) int {\n\t// n = min(srcLen, dstLen)\n\tn := srcLen\n\tif n > dstLen {\n\t\tn = dstLen\n\t}\n\tmemmove(dst, src, n*elemSize)\n\treturn int(n)\n}\n\n// sliceGrow returns a new slice with space for at least newCap elements\nfunc sliceGrow(oldBuf unsafe.Pointer, oldLen, oldCap, newCap, elemSize uintptr) (unsafe.Pointer, uintptr, uintptr) {\n\tif oldCap >= newCap {\n\t\t// No need to grow, return the input slice.\n\t\treturn oldBuf, oldLen, oldCap\n\t}\n\n\t// This can be made more memory-efficient by multiplying by some other constant, such as 1.5,\n\t// which seems to be allowed by the Go language specification (but this can be observed by\n\t// programs); however, due to memory fragmentation and the current state of the TinyGo\n\t// memory allocators, this causes some difficult to debug issues.\n\tnewCap = 1 << bits.Len(uint(newCap))\n\n\tvar layout unsafe.Pointer\n\t// less type info here; can only go off element size\n\tif elemSize < unsafe.Sizeof(uintptr(0)) {\n\t\tlayout = gclayout.NoPtrs.AsPtr()\n\t}\n\n\tbuf := alloc(newCap*elemSize, layout)\n\tif oldLen > 0 {\n\t\t// copy any data to new slice\n\t\tmemmove(buf, oldBuf, oldLen*elemSize)\n\t}\n\n\treturn buf, oldLen, newCap\n}\n"
  },
  {
    "path": "src/runtime/stack.go",
    "content": "package runtime\n\ntype Func struct {\n}\n\nfunc FuncForPC(pc uintptr) *Func {\n\treturn nil\n}\n\nfunc (f *Func) Name() string {\n\treturn \"\"\n}\n\nfunc (f *Func) FileLine(pc uintptr) (file string, line int) {\n\treturn \"\", 0\n}\n\nfunc Caller(skip int) (pc uintptr, file string, line int, ok bool) {\n\treturn 0, \"\", 0, false\n}\n\nfunc Stack(buf []byte, all bool) int {\n\treturn 0\n}\n"
  },
  {
    "path": "src/runtime/string.go",
    "content": "package runtime\n\n// This file implements functions related to Go strings.\n\nimport (\n\t\"internal/gclayout\"\n\t\"unsafe\"\n)\n\n// The underlying struct for the Go string type.\ntype _string struct {\n\tptr    *byte\n\tlength uintptr\n}\n\n// The iterator state for a range over a string.\ntype stringIterator struct {\n\tbyteindex uintptr\n}\n\n// Return true iff the strings match.\n//\n//go:nobounds\nfunc stringEqual(x, y string) bool {\n\tif len(x) != len(y) {\n\t\treturn false\n\t}\n\tfor i := 0; i < len(x); i++ {\n\t\tif x[i] != y[i] {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// Return true iff x < y.\n//\n//go:nobounds\nfunc stringLess(x, y string) bool {\n\tl := len(x)\n\tif m := len(y); m < l {\n\t\tl = m\n\t}\n\tfor i := 0; i < l; i++ {\n\t\tif x[i] < y[i] {\n\t\t\treturn true\n\t\t}\n\t\tif x[i] > y[i] {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn len(x) < len(y)\n}\n\n// Add two strings together.\nfunc stringConcat(x, y _string) _string {\n\tif x.length == 0 {\n\t\treturn y\n\t} else if y.length == 0 {\n\t\treturn x\n\t} else {\n\t\tlength := x.length + y.length\n\t\tbuf := alloc(length, gclayout.NoPtrs.AsPtr())\n\t\tmemcpy(buf, unsafe.Pointer(x.ptr), x.length)\n\t\tmemcpy(unsafe.Add(buf, x.length), unsafe.Pointer(y.ptr), y.length)\n\t\treturn _string{ptr: (*byte)(buf), length: length}\n\t}\n}\n\n// Create a string from a []byte slice.\nfunc stringFromBytes(x struct {\n\tptr *byte\n\tlen uintptr\n\tcap uintptr\n}) _string {\n\tbuf := alloc(x.len, gclayout.NoPtrs.AsPtr())\n\tmemcpy(buf, unsafe.Pointer(x.ptr), x.len)\n\treturn _string{ptr: (*byte)(buf), length: x.len}\n}\n\n// Convert a string to a []byte slice.\nfunc stringToBytes(x _string) (slice struct {\n\tptr *byte\n\tlen uintptr\n\tcap uintptr\n}) {\n\tbuf := alloc(x.length, gclayout.NoPtrs.AsPtr())\n\tmemcpy(buf, unsafe.Pointer(x.ptr), x.length)\n\tslice.ptr = (*byte)(buf)\n\tslice.len = x.length\n\tslice.cap = x.length\n\treturn\n}\n\n// Convert a []rune slice to a string.\nfunc stringFromRunes(runeSlice []rune) (s _string) {\n\t// Count the number of characters that will be in the string.\n\tfor _, r := range runeSlice {\n\t\t_, numBytes := encodeUTF8(r)\n\t\ts.length += numBytes\n\t}\n\n\t// Allocate memory for the string.\n\ts.ptr = (*byte)(alloc(s.length, gclayout.NoPtrs.AsPtr()))\n\n\t// Encode runes to UTF-8 and store the resulting bytes in the string.\n\tindex := uintptr(0)\n\tfor _, r := range runeSlice {\n\t\tarray, numBytes := encodeUTF8(r)\n\t\tfor _, c := range array[:numBytes] {\n\t\t\t*(*byte)(unsafe.Add(unsafe.Pointer(s.ptr), index)) = c\n\t\t\tindex++\n\t\t}\n\t}\n\n\treturn\n}\n\n// Convert a string to []rune slice.\nfunc stringToRunes(s string) []rune {\n\tvar n = 0\n\tfor range s {\n\t\tn++\n\t}\n\tvar r = make([]rune, n)\n\tn = 0\n\tfor _, e := range s {\n\t\tr[n] = e\n\t\tn++\n\t}\n\treturn r\n}\n\n// Create a string from a Unicode code point.\nfunc stringFromUnicode(x rune) _string {\n\tarray, length := encodeUTF8(x)\n\t// Array will be heap allocated.\n\t// The heap most likely doesn't work with blocks below 4 bytes, so there's\n\t// no point in allocating a smaller buffer for the string here.\n\treturn _string{ptr: (*byte)(unsafe.Pointer(&array)), length: length}\n}\n\n// Iterate over a string.\n// Returns (ok, key, value).\nfunc stringNext(s string, it *stringIterator) (bool, int, rune) {\n\tif len(s) <= int(it.byteindex) {\n\t\treturn false, 0, 0\n\t}\n\ti := int(it.byteindex)\n\tr, length := decodeUTF8(s, it.byteindex)\n\tit.byteindex += length\n\treturn true, i, r\n}\n\n// Convert a Unicode code point into an array of bytes and its length.\nfunc encodeUTF8(x rune) ([4]byte, uintptr) {\n\t// https://stackoverflow.com/questions/6240055/manually-converting-unicode-codepoints-into-utf-8-and-utf-16\n\t// Note: this code can probably be optimized (in size and speed).\n\tswitch {\n\tcase x <= 0x7f:\n\t\treturn [4]byte{byte(x), 0, 0, 0}, 1\n\tcase x <= 0x7ff:\n\t\tb1 := 0xc0 | byte(x>>6)\n\t\tb2 := 0x80 | byte(x&0x3f)\n\t\treturn [4]byte{b1, b2, 0, 0}, 2\n\tcase 0xd800 <= x && x <= 0xdfff:\n\t\t// utf-16 surrogates are replaced with \"invalid code point\"\n\t\treturn [4]byte{0xef, 0xbf, 0xbd, 0}, 3\n\tcase x <= 0xffff:\n\t\tb1 := 0xe0 | byte(x>>12)\n\t\tb2 := 0x80 | byte((x>>6)&0x3f)\n\t\tb3 := 0x80 | byte((x>>0)&0x3f)\n\t\treturn [4]byte{b1, b2, b3, 0}, 3\n\tcase x <= 0x10ffff:\n\t\tb1 := 0xf0 | byte(x>>18)\n\t\tb2 := 0x80 | byte((x>>12)&0x3f)\n\t\tb3 := 0x80 | byte((x>>6)&0x3f)\n\t\tb4 := 0x80 | byte((x>>0)&0x3f)\n\t\treturn [4]byte{b1, b2, b3, b4}, 4\n\tdefault:\n\t\t// Invalid Unicode code point.\n\t\treturn [4]byte{0xef, 0xbf, 0xbd, 0}, 3\n\t}\n}\n\n// Decode a single UTF-8 character from a string.\n//\n//go:nobounds\nfunc decodeUTF8(s string, index uintptr) (rune, uintptr) {\n\tremaining := uintptr(len(s)) - index // must be >= 1 before calling this function\n\tx := s[index]\n\tswitch {\n\tcase x&0x80 == 0x00: // 0xxxxxxx\n\t\treturn rune(x), 1\n\tcase x&0xe0 == 0xc0: // 110xxxxx\n\t\tif remaining < 2 || !isContinuation(s[index+1]) {\n\t\t\treturn 0xfffd, 1\n\t\t}\n\t\tr := (rune(x&0x1f) << 6) | (rune(s[index+1]) & 0x3f)\n\t\tif r >= 1<<7 {\n\t\t\t// Check whether the rune really needed to be encoded as a two-byte\n\t\t\t// sequence. UTF-8 requires every rune to be encoded in the smallest\n\t\t\t// sequence possible.\n\t\t\treturn r, 2\n\t\t}\n\tcase x&0xf0 == 0xe0: // 1110xxxx\n\t\tif remaining < 3 || !isContinuation(s[index+1]) || !isContinuation(s[index+2]) {\n\t\t\treturn 0xfffd, 1\n\t\t}\n\t\tr := (rune(x&0x0f) << 12) | ((rune(s[index+1]) & 0x3f) << 6) | (rune(s[index+2]) & 0x3f)\n\t\tif r >= 1<<11 && !(r >= 0xD800 && r <= 0xDFFF) {\n\t\t\t// Check whether the rune really needed to be encoded as a\n\t\t\t// three-byte sequence and check that this is not a Unicode\n\t\t\t// surrogate pair (which are not allowed by UTF-8).\n\t\t\treturn r, 3\n\t\t}\n\tcase x&0xf8 == 0xf0: // 11110xxx\n\t\tif remaining < 4 || !isContinuation(s[index+1]) || !isContinuation(s[index+2]) || !isContinuation(s[index+3]) {\n\t\t\treturn 0xfffd, 1\n\t\t}\n\t\tr := (rune(x&0x07) << 18) | ((rune(s[index+1]) & 0x3f) << 12) | ((rune(s[index+2]) & 0x3f) << 6) | (rune(s[index+3]) & 0x3f)\n\t\tif r >= 1<<16 && r <= '\\U0010FFFF' {\n\t\t\t// Check whether this rune really needed to be encoded as a four\n\t\t\t// byte sequence and check that the resulting rune is in the valid\n\t\t\t// range (up to at most U+10FFFF).\n\t\t\treturn r, 4\n\t\t}\n\t}\n\n\t// Failed to decode. Return the Unicode replacement character and a length of 1.\n\treturn 0xfffd, 1\n}\n\n// isContinuation returns true if (and only if) this is a UTF-8 continuation\n// byte.\nfunc isContinuation(b byte) bool {\n\t// Continuation bytes have their topmost bits set to 0b10.\n\treturn b&0xc0 == 0x80\n}\n\n// Functions used in CGo.\n\n// Convert a Go string to a C string.\nfunc cgo_CString(s _string) unsafe.Pointer {\n\tbuf := malloc(s.length + 1)\n\tmemcpy(buf, unsafe.Pointer(s.ptr), s.length)\n\t*(*byte)(unsafe.Add(buf, s.length)) = 0 // trailing 0 byte\n\treturn buf\n}\n\n// Convert a C string to a Go string.\nfunc cgo_GoString(cstr unsafe.Pointer) _string {\n\tif cstr == nil {\n\t\treturn _string{}\n\t}\n\treturn makeGoString(cstr, strlen(cstr))\n}\n\n// Convert a C data buffer to a Go string (that possibly contains 0 bytes).\nfunc cgo_GoStringN(cstr unsafe.Pointer, length uintptr) _string {\n\treturn makeGoString(cstr, length)\n}\n\n// Make a Go string given a source buffer and a length.\nfunc makeGoString(cstr unsafe.Pointer, length uintptr) _string {\n\ts := _string{\n\t\tlength: length,\n\t}\n\tif s.length != 0 {\n\t\tbuf := make([]byte, s.length)\n\t\ts.ptr = &buf[0]\n\t\tmemcpy(unsafe.Pointer(s.ptr), cstr, s.length)\n\t}\n\treturn s\n}\n\n// Convert a C data buffer to a Go byte slice.\nfunc cgo_GoBytes(ptr unsafe.Pointer, length uintptr) []byte {\n\t// Note: don't return nil if length is 0, to match the behavior of C.GoBytes\n\t// of upstream Go.\n\tbuf := make([]byte, length)\n\tif length != 0 {\n\t\tmemcpy(unsafe.Pointer(&buf[0]), ptr, uintptr(length))\n\t}\n\treturn buf\n}\n\nfunc cgo_CBytes(b []byte) unsafe.Pointer {\n\tp := malloc(uintptr(len(b)))\n\ts := unsafe.Slice((*byte)(p), len(b))\n\tcopy(s, b)\n\treturn p\n}\n"
  },
  {
    "path": "src/runtime/symtab.go",
    "content": "package runtime\n\ntype Frames struct {\n\t//\n}\n\ntype Frame struct {\n\tPC uintptr\n\n\tFunc *Func\n\n\tFunction string\n\n\tFile string\n\tLine int\n\n\tEntry uintptr\n}\n\nfunc CallersFrames(callers []uintptr) *Frames {\n\treturn nil\n}\n\nfunc (ci *Frames) Next() (frame Frame, more bool) {\n\treturn Frame{}, false\n}\n"
  },
  {
    "path": "src/runtime/sync.go",
    "content": "package runtime\n\n// This file contains stub implementations for internal/poll.\n\n//go:linkname semacquire internal/poll.runtime_Semacquire\nfunc semacquire(sema *uint32) {\n\tpanic(\"todo: semacquire\")\n}\n\n//go:linkname semrelease internal/poll.runtime_Semrelease\nfunc semrelease(sema *uint32) {\n\tpanic(\"todo: semrelease\")\n}\n"
  },
  {
    "path": "src/runtime/synctest.go",
    "content": "package runtime\n\n// Dummy implementation of synctest functions (we don't support synctest at the\n// moment).\n\n//go:linkname synctest_acquire internal/synctest.acquire\nfunc synctest_acquire() any {\n\t// Dummy: we don't support synctest.\n\treturn nil\n}\n\n//go:linkname synctest_release internal/synctest.release\nfunc synctest_release(sg any) {\n\t// Dummy: we don't support synctest.\n}\n"
  },
  {
    "path": "src/runtime/time.go",
    "content": "package runtime\n\n//go:linkname time_runtimeNano time.runtimeNano\nfunc time_runtimeNano() int64 {\n\t// Note: we're ignoring sync groups here (package testing/synctest).\n\t// See: https://github.com/golang/go/issues/67434\n\treturn nanotime()\n}\n\n//go:linkname time_runtimeNow time.runtimeNow\nfunc time_runtimeNow() (sec int64, nsec int32, mono int64) {\n\t// Also ignoring the sync group here, like time_runtimeNano above.\n\treturn now()\n}\n\n// timerNode is an element in a linked list of timers.\ntype timerNode struct {\n\tnext     *timerNode\n\ttimer    *timer\n\tcallback func(node *timerNode, delta int64)\n}\n\n// whenTicks returns the (absolute) time when this timer should trigger next.\nfunc (t *timerNode) whenTicks() timeUnit {\n\treturn nanosecondsToTicks(t.timer.when)\n}\n\n// timerCallback is called when a timer expires. It makes sure to call the\n// callback in the time package and to re-add the timer to the queue if this is\n// a ticker (repeating timer).\n// This is intentionally used as a callback and not a direct call (even though a\n// direct call would be trivial), because otherwise a circular dependency\n// between scheduler, addTimer and timerQueue would form. Such a circular\n// dependency causes timerQueue not to get optimized away.\n// If timerQueue doesn't get optimized away, small programs (that don't call\n// time.NewTimer etc) would still pay the cost of these timers.\nfunc timerCallback(tn *timerNode, delta int64) {\n\t// Run timer function (implemented in the time package).\n\t// The seq parameter to the f function is not used in the time\n\t// package so is left zero.\n\ttn.timer.callCallback(delta)\n\n\t// If this is a periodic timer (a ticker), re-add it to the queue.\n\tif tn.timer.period != 0 {\n\t\ttn.timer.when += tn.timer.period\n\t\taddTimer(tn)\n\t}\n}\n\n//go:linkname time_runtimeIsBubbled time.runtimeIsBubbled\nfunc time_runtimeIsBubbled() bool {\n\t// We don't currently support bubbles.\n\treturn false\n}\n"
  },
  {
    "path": "src/runtime/time_go122.go",
    "content": "//go:build !go1.23\n\n// Portions copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage runtime\n\n// Time functions for Go 1.22 and below.\n\ntype puintptr uintptr\n\n// Package time knows the layout of this structure.\n// If this struct changes, adjust ../time/sleep.go:/runtimeTimer.\ntype timer struct {\n\t// If this timer is on a heap, which P's heap it is on.\n\t// puintptr rather than *p to match uintptr in the versions\n\t// of this struct defined in other packages.\n\tpp puintptr\n\n\t// Timer wakes up at when, and then at when+period, ... (period > 0 only)\n\t// each time calling f(arg, now) in the timer goroutine, so f must be\n\t// a well-behaved function and not block.\n\t//\n\t// when must be positive on an active timer.\n\twhen   int64\n\tperiod int64\n\tf      func(any, uintptr)\n\targ    any\n\tseq    uintptr\n\n\t// What to set the when field to in timerModifiedXX status.\n\tnextwhen int64\n\n\t// The status field holds one of the values below.\n\tstatus uint32\n}\n\nfunc (tim *timer) callCallback(delta int64) {\n\ttim.f(tim.arg, 0)\n}\n\n// Defined in the time package, implemented here in the runtime.\n//\n//go:linkname startTimer time.startTimer\nfunc startTimer(tim *timer) {\n\taddTimer(&timerNode{\n\t\ttimer:    tim,\n\t\tcallback: timerCallback,\n\t})\n\tscheduleLog(\"adding timer\")\n}\n\n//go:linkname stopTimer time.stopTimer\nfunc stopTimer(tim *timer) bool {\n\treturn removeTimer(tim) != nil\n}\n\n//go:linkname resetTimer time.resetTimer\nfunc resetTimer(tim *timer, when int64) bool {\n\ttim.when = when\n\tn := removeTimer(tim)\n\tstartTimer(tim)\n\treturn n != nil\n}\n"
  },
  {
    "path": "src/runtime/time_go123.go",
    "content": "//go:build go1.23\n\npackage runtime\n\nimport \"unsafe\"\n\n// Time functions for Go 1.23 and above.\n\n// This is the timer that's used internally inside the runtime.\ntype timer struct {\n\t// When to call the timer, and the interval for the ticker.\n\twhen   int64\n\tperiod int64\n\n\t// Callback from the time package.\n\tf   func(arg any, seq uintptr, delta int64)\n\targ any\n}\n\nfunc (tim *timer) callCallback(delta int64) {\n\ttim.f(tim.arg, 0, delta)\n}\n\n// This is the struct used internally in the runtime. The first two fields are\n// the same as time.Timer and time.Ticker so it can be used as-is in the time\n// package.\ntype timeTimer struct {\n\tc    unsafe.Pointer // <-chan time.Time\n\tinit bool\n\ttimer\n}\n\n//go:linkname newTimer time.newTimer\nfunc newTimer(when, period int64, f func(arg any, seq uintptr, delta int64), arg any, c unsafe.Pointer) *timeTimer {\n\ttim := &timeTimer{\n\t\tc:    c,\n\t\tinit: true,\n\t\ttimer: timer{\n\t\t\twhen:   when,\n\t\t\tperiod: period,\n\t\t\tf:      f,\n\t\t\targ:    arg,\n\t\t},\n\t}\n\tscheduleLog(\"new timer\")\n\taddTimer(&timerNode{\n\t\ttimer:    &tim.timer,\n\t\tcallback: timerCallback,\n\t})\n\treturn tim\n}\n\n//go:linkname stopTimer time.stopTimer\nfunc stopTimer(tim *timeTimer) bool {\n\treturn removeTimer(&tim.timer) != nil\n}\n\n//go:linkname resetTimer time.resetTimer\nfunc resetTimer(t *timeTimer, when, period int64) bool {\n\tt.timer.when = when\n\tt.timer.period = period\n\tn := removeTimer(&t.timer)\n\tremoved := n != nil\n\tif n == nil {\n\t\tn = new(timerNode)\n\t}\n\tn.timer = &t.timer\n\tn.callback = timerCallback\n\taddTimer(n)\n\treturn removed\n}\n"
  },
  {
    "path": "src/runtime/time_nxpmk66f18.go",
    "content": "// Derivative work of Teensyduino Core Library\n// http://www.pjrc.com/teensy/\n// Copyright (c) 2017 PJRC.COM, LLC.\n//\n// Permission is hereby granted, free of charge, to any person obtaining\n// a copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to\n// the following conditions:\n//\n// 1. The above copyright notice and this permission notice shall be\n// included in all copies or substantial portions of the Software.\n//\n// 2. If the Software is incorporated into a build system that allows\n// selection among a list of target devices, then similar target\n// devices manufactured by PJRC.COM must be included in the list of\n// target devices and selectable in the same manner.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n//go:build nxp && mk66f18\n\npackage runtime\n\nimport (\n\t\"device/arm\"\n\t\"device/nxp\"\n\t\"machine\"\n\t\"runtime/interrupt\"\n\t\"runtime/volatile\"\n)\n\nfunc ticksToNanoseconds(ticks timeUnit) int64 {\n\treturn int64(ticks) * 1000\n}\n\nfunc nanosecondsToTicks(ns int64) timeUnit {\n\treturn timeUnit(ns / 1000)\n}\n\n// cyclesPerMilli-1 is used for the systick reset value.\n// The systick current value will be decremented on every clock cycle.\n// An interrupt is generated when the current value reaches 0.\n// A value of freq/1000 generates a tick (irq) every millisecond (1/1000 s).\nvar cyclesPerMilli = machine.CPUFrequency() / 1000\n\n// number of systick irqs (milliseconds) since boot\nvar systickCount volatile.Register64\n\nfunc millisSinceBoot() uint64 {\n\treturn systickCount.Get()\n}\n\nfunc initSysTick() {\n\tnxp.SysTick.RVR.Set(cyclesPerMilli - 1)\n\tnxp.SysTick.CVR.Set(0)\n\tnxp.SysTick.CSR.Set(nxp.SysTick_CSR_CLKSOURCE | nxp.SysTick_CSR_TICKINT | nxp.SysTick_CSR_ENABLE)\n\tnxp.SystemControl.SHPR3.Set((32 << nxp.SystemControl_SHPR3_PRI_15_Pos) | (32 << nxp.SystemControl_SHPR3_PRI_14_Pos)) // set systick and pendsv priority to 32\n}\n\nfunc initSleepTimer() {\n\tnxp.SIM.SCGC5.SetBits(nxp.SIM_SCGC5_LPTMR)\n\tnxp.LPTMR0.CSR.Set(nxp.LPTMR0_CSR_TIE)\n\n\ttimerInterrupt = interrupt.New(nxp.IRQ_LPTMR0, timerWake)\n\ttimerInterrupt.Enable()\n}\n\n//go:export SysTick_Handler\nfunc tick() {\n\tsystickCount.Set(systickCount.Get() + 1)\n}\n\n// ticks are in microseconds\nfunc ticks() timeUnit {\n\tmask := arm.DisableInterrupts()\n\tcurrent := nxp.SysTick.CVR.Get()        // current value of the systick counter\n\tcount := millisSinceBoot()              // number of milliseconds since boot\n\tistatus := nxp.SystemControl.ICSR.Get() // interrupt status register\n\tarm.EnableInterrupts(mask)\n\n\tmicros := timeUnit(count * 1000) // a tick (1ms) = 1000 us\n\n\t// if the systick counter was about to reset and ICSR indicates a pending systick irq, increment count\n\tif istatus&nxp.SystemControl_ICSR_PENDSTSET != 0 && current > 50 {\n\t\tmicros += 1000\n\t} else {\n\t\tcycles := cyclesPerMilli - 1 - current // number of cycles since last 1ms tick\n\t\tcyclesPerMicro := machine.CPUFrequency() / 1000000\n\t\tmicros += timeUnit(cycles / cyclesPerMicro)\n\t}\n\n\treturn micros\n}\n\n// sleepTicks spins for a number of microseconds\nfunc sleepTicks(duration timeUnit) {\n\tnow := ticks()\n\tend := duration + now\n\tcyclesPerMicro := machine.ClockFrequency() / 1000000\n\n\tif duration <= 0 {\n\t\treturn\n\t}\n\n\tnxp.LPTMR0.PSR.Set((3 << nxp.LPTMR0_PSR_PCS_Pos) | nxp.LPTMR0_PSR_PBYP) // use 16MHz clock, undivided\n\n\tfor now < end {\n\t\tcount := uint32(end-now) / cyclesPerMicro\n\t\tif count > 65535 {\n\t\t\tcount = 65535\n\t\t}\n\n\t\tif !timerSleep(count) {\n\t\t\t// return early due to interrupt\n\t\t\treturn\n\t\t}\n\n\t\tnow = ticks()\n\t}\n}\n\nvar timerInterrupt interrupt.Interrupt\nvar timerActive volatile.Register32\n\nfunc timerSleep(count uint32) bool {\n\ttimerActive.Set(1)\n\tnxp.LPTMR0.CMR.Set(count)                  // set count\n\tnxp.LPTMR0.CSR.SetBits(nxp.LPTMR0_CSR_TEN) // enable\n\n\tfor {\n\t\tarm.Asm(\"wfi\")\n\t\tif timerActive.Get() == 0 {\n\t\t\treturn true\n\t\t}\n\n\t\tif hasScheduler {\n\t\t\t// bail out, as the interrupt may have awoken a goroutine\n\t\t\tbreak\n\t\t}\n\n\t\t// if there is no scheduler, block for the entire count\n\t}\n\n\ttimerWake(timerInterrupt)\n\treturn false\n}\n\nfunc timerWake(interrupt.Interrupt) {\n\ttimerActive.Set(0)\n\tnxp.LPTMR0.CSR.Set(nxp.LPTMR0.CSR.Get()&^nxp.LPTMR0_CSR_TEN | nxp.LPTMR0_CSR_TCF) // clear flag and disable\n}\n"
  },
  {
    "path": "src/runtime/trace/trace.go",
    "content": "// Stubs for the runtime/trace package\npackage trace\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"io\"\n)\n\nfunc Start(w io.Writer) error {\n\treturn errors.New(\"not implemented\")\n}\n\nfunc Stop() {}\n\nfunc NewTask(pctx context.Context, taskType string) (ctx context.Context, task *Task) {\n\treturn context.TODO(), nil\n}\n\ntype Task struct{}\n\nfunc (t *Task) End() {}\n\nfunc Log(ctx context.Context, category, message string) {}\n\nfunc Logf(ctx context.Context, category, format string, args ...any) {}\n\nfunc WithRegion(ctx context.Context, regionType string, fn func()) {\n\tfn()\n}\n\nfunc StartRegion(ctx context.Context, regionType string) *Region {\n\treturn nil\n}\n\ntype Region struct{}\n\nfunc (r *Region) End() {}\n\nfunc IsEnabled() bool {\n\treturn false\n}\n"
  },
  {
    "path": "src/runtime/volatile/bitband_nxpmk66f18.go",
    "content": "//go:build nxp && mk66f18\n\npackage volatile\n\nimport \"unsafe\"\n\nconst registerBase = 0x40000000\nconst registerEnd = 0x40100000\nconst bitbandBase = 0x42000000\n\n//go:inline\nfunc bitbandAddress(reg uintptr, bit uint8) uintptr {\n\tif uintptr(bit) > 32 {\n\t\tpanic(\"invalid bit position\")\n\t}\n\tif reg < registerBase || reg >= registerEnd {\n\t\tpanic(\"register is out of range\")\n\t}\n\treturn (reg-registerBase)*32 + uintptr(bit)*4 + bitbandBase\n}\n\n// Special types that causes loads/stores to be volatile (necessary for\n// memory-mapped registers).\ntype BitRegister struct {\n\tReg uint32\n}\n\n// Get returns the of the mapped register bit. It is the volatile equivalent of:\n//\n//\t*r.Reg\n//\n//go:inline\nfunc (r *BitRegister) Get() bool {\n\treturn LoadUint32(&r.Reg) != 0\n}\n\n// Set sets the mapped register bit. It is the volatile equivalent of:\n//\n//\t*r.Reg = 1\n//\n//go:inline\nfunc (r *BitRegister) Set(v bool) {\n\tvar i uint32\n\tif v {\n\t\ti = 1\n\t}\n\tStoreUint32(&r.Reg, i)\n}\n\n// Bit maps bit N of register R to the corresponding bitband address. Bit panics\n// if R is not an AIPS or GPIO register or if N is out of range (greater than\n// the number of bits in a register minus one).\n//\n//go:inline\nfunc (r *Register8) Bit(bit uint8) *BitRegister {\n\tptr := bitbandAddress(uintptr(unsafe.Pointer(&r.Reg)), bit)\n\treturn (*BitRegister)(unsafe.Pointer(ptr))\n}\n\n// Bit maps bit N of register R to the corresponding bitband address. Bit panics\n// if R is not an AIPS or GPIO register or if N is out of range (greater than\n// the number of bits in a register minus one).\n//\n//go:inline\nfunc (r *Register16) Bit(bit uint8) *BitRegister {\n\tptr := bitbandAddress(uintptr(unsafe.Pointer(&r.Reg)), bit)\n\treturn (*BitRegister)(unsafe.Pointer(ptr))\n}\n\n// Bit maps bit N of register R to the corresponding bitband address. Bit panics\n// if R is not an AIPS or GPIO register or if N is out of range (greater than\n// the number of bits in a register minus one).\n//\n//go:inline\nfunc (r *Register32) Bit(bit uint8) *BitRegister {\n\tptr := bitbandAddress(uintptr(unsafe.Pointer(&r.Reg)), bit)\n\treturn (*BitRegister)(unsafe.Pointer(ptr))\n}\n"
  },
  {
    "path": "src/runtime/volatile/register.go",
    "content": "package volatile\n\n// This file defines Register{8,16,32,64} types, which are convenience types for\n// volatile register accesses.\n\n// Special types that causes loads/stores to be volatile (necessary for\n// memory-mapped registers).\ntype Register8 struct {\n\tReg uint8\n}\n\n// Get returns the value in the register. It is the volatile equivalent of:\n//\n//\t*r.Reg\n//\n//go:inline\nfunc (r *Register8) Get() uint8 {\n\treturn LoadUint8(&r.Reg)\n}\n\n// Set updates the register value. It is the volatile equivalent of:\n//\n//\t*r.Reg = value\n//\n//go:inline\nfunc (r *Register8) Set(value uint8) {\n\tStoreUint8(&r.Reg, value)\n}\n\n// SetBits reads the register, sets the given bits, and writes it back. It is\n// the volatile equivalent of:\n//\n//\tr.Reg |= value\n//\n//go:inline\nfunc (r *Register8) SetBits(value uint8) {\n\tStoreUint8(&r.Reg, LoadUint8(&r.Reg)|value)\n}\n\n// ClearBits reads the register, clears the given bits, and writes it back. It\n// is the volatile equivalent of:\n//\n//\tr.Reg &^= value\n//\n//go:inline\nfunc (r *Register8) ClearBits(value uint8) {\n\tStoreUint8(&r.Reg, LoadUint8(&r.Reg)&^value)\n}\n\n// HasBits reads the register and then checks to see if the passed bits are set. It\n// is the volatile equivalent of:\n//\n//\t(*r.Reg & value) > 0\n//\n//go:inline\nfunc (r *Register8) HasBits(value uint8) bool {\n\treturn (r.Get() & value) > 0\n}\n\n// ReplaceBits is a helper to simplify setting multiple bits high and/or low at\n// once. It is the volatile equivalent of:\n//\n//\tr.Reg = (r.Reg & ^(mask << pos)) | value << pos\n//\n//go:inline\nfunc (r *Register8) ReplaceBits(value uint8, mask uint8, pos uint8) {\n\tStoreUint8(&r.Reg, LoadUint8(&r.Reg)&^(mask<<pos)|value<<pos)\n}\n\ntype Register16 struct {\n\tReg uint16\n}\n\n// Get returns the value in the register. It is the volatile equivalent of:\n//\n//\t*r.Reg\n//\n//go:inline\nfunc (r *Register16) Get() uint16 {\n\treturn LoadUint16(&r.Reg)\n}\n\n// Set updates the register value. It is the volatile equivalent of:\n//\n//\t*r.Reg = value\n//\n//go:inline\nfunc (r *Register16) Set(value uint16) {\n\tStoreUint16(&r.Reg, value)\n}\n\n// SetBits reads the register, sets the given bits, and writes it back. It is\n// the volatile equivalent of:\n//\n//\tr.Reg |= value\n//\n//go:inline\nfunc (r *Register16) SetBits(value uint16) {\n\tStoreUint16(&r.Reg, LoadUint16(&r.Reg)|value)\n}\n\n// ClearBits reads the register, clears the given bits, and writes it back. It\n// is the volatile equivalent of:\n//\n//\tr.Reg &^= value\n//\n//go:inline\nfunc (r *Register16) ClearBits(value uint16) {\n\tStoreUint16(&r.Reg, LoadUint16(&r.Reg)&^value)\n}\n\n// HasBits reads the register and then checks to see if the passed bits are set. It\n// is the volatile equivalent of:\n//\n//\t(*r.Reg & value) > 0\n//\n//go:inline\nfunc (r *Register16) HasBits(value uint16) bool {\n\treturn (r.Get() & value) > 0\n}\n\n// ReplaceBits is a helper to simplify setting multiple bits high and/or low at\n// once. It is the volatile equivalent of:\n//\n//\tr.Reg = (r.Reg & ^(mask << pos)) | value << pos\n//\n//go:inline\nfunc (r *Register16) ReplaceBits(value uint16, mask uint16, pos uint8) {\n\tStoreUint16(&r.Reg, LoadUint16(&r.Reg)&^(mask<<pos)|value<<pos)\n}\n\ntype Register32 struct {\n\tReg uint32\n}\n\n// Get returns the value in the register. It is the volatile equivalent of:\n//\n//\t*r.Reg\n//\n//go:inline\nfunc (r *Register32) Get() uint32 {\n\treturn LoadUint32(&r.Reg)\n}\n\n// Set updates the register value. It is the volatile equivalent of:\n//\n//\t*r.Reg = value\n//\n//go:inline\nfunc (r *Register32) Set(value uint32) {\n\tStoreUint32(&r.Reg, value)\n}\n\n// SetBits reads the register, sets the given bits, and writes it back. It is\n// the volatile equivalent of:\n//\n//\tr.Reg |= value\n//\n//go:inline\nfunc (r *Register32) SetBits(value uint32) {\n\tStoreUint32(&r.Reg, LoadUint32(&r.Reg)|value)\n}\n\n// ClearBits reads the register, clears the given bits, and writes it back. It\n// is the volatile equivalent of:\n//\n//\tr.Reg &^= value\n//\n//go:inline\nfunc (r *Register32) ClearBits(value uint32) {\n\tStoreUint32(&r.Reg, LoadUint32(&r.Reg)&^value)\n}\n\n// HasBits reads the register and then checks to see if the passed bits are set. It\n// is the volatile equivalent of:\n//\n//\t(*r.Reg & value) > 0\n//\n//go:inline\nfunc (r *Register32) HasBits(value uint32) bool {\n\treturn (r.Get() & value) > 0\n}\n\n// ReplaceBits is a helper to simplify setting multiple bits high and/or low at\n// once. It is the volatile equivalent of:\n//\n//\tr.Reg = (r.Reg & ^(mask << pos)) | value << pos\n//\n//go:inline\nfunc (r *Register32) ReplaceBits(value uint32, mask uint32, pos uint8) {\n\tStoreUint32(&r.Reg, LoadUint32(&r.Reg)&^(mask<<pos)|value<<pos)\n}\n\ntype Register64 struct {\n\tReg uint64\n}\n\n// Get returns the value in the register. It is the volatile equivalent of:\n//\n//\t*r.Reg\n//\n//go:inline\nfunc (r *Register64) Get() uint64 {\n\treturn LoadUint64(&r.Reg)\n}\n\n// Set updates the register value. It is the volatile equivalent of:\n//\n//\t*r.Reg = value\n//\n//go:inline\nfunc (r *Register64) Set(value uint64) {\n\tStoreUint64(&r.Reg, value)\n}\n\n// SetBits reads the register, sets the given bits, and writes it back. It is\n// the volatile equivalent of:\n//\n//\tr.Reg |= value\n//\n//go:inline\nfunc (r *Register64) SetBits(value uint64) {\n\tStoreUint64(&r.Reg, LoadUint64(&r.Reg)|value)\n}\n\n// ClearBits reads the register, clears the given bits, and writes it back. It\n// is the volatile equivalent of:\n//\n//\tr.Reg &^= value\n//\n//go:inline\nfunc (r *Register64) ClearBits(value uint64) {\n\tStoreUint64(&r.Reg, LoadUint64(&r.Reg)&^value)\n}\n\n// HasBits reads the register and then checks to see if the passed bits are set. It\n// is the volatile equivalent of:\n//\n//\t(*r.Reg & value) > 0\n//\n//go:inline\nfunc (r *Register64) HasBits(value uint64) bool {\n\treturn (r.Get() & value) > 0\n}\n\n// ReplaceBits is a helper to simplify setting multiple bits high and/or low at\n// once. It is the volatile equivalent of:\n//\n//\tr.Reg = (r.Reg & ^(mask << pos)) | value << pos\n//\n//go:inline\nfunc (r *Register64) ReplaceBits(value uint64, mask uint64, pos uint8) {\n\tStoreUint64(&r.Reg, LoadUint64(&r.Reg)&^(mask<<pos)|value<<pos)\n}\n"
  },
  {
    "path": "src/runtime/volatile/volatile.go",
    "content": "// Package volatile provides definitions for volatile loads and stores. These\n// are implemented as compiler builtins.\n//\n// The load operations load a volatile value. The store operations store to a\n// volatile value. The compiler will emit exactly one load or store operation\n// when possible and will not reorder volatile operations. However, the compiler\n// may move other operations across load/store operations, so make sure that all\n// relevant loads/stores are done in a volatile way if this is a problem.\n//\n// These loads and stores are commonly used to read/write values from memory\n// mapped peripheral devices. They do not provide atomicity, use the sync/atomic\n// package for that.\n//\n// For more details: https://llvm.org/docs/LangRef.html#volatile-memory-accesses\n// and https://blog.regehr.org/archives/28.\npackage volatile\n\n// LoadUint8 loads the volatile value *addr.\nfunc LoadUint8(addr *uint8) (val uint8)\n\n// LoadUint16 loads the volatile value *addr.\nfunc LoadUint16(addr *uint16) (val uint16)\n\n// LoadUint32 loads the volatile value *addr.\nfunc LoadUint32(addr *uint32) (val uint32)\n\n// LoadUint64 loads the volatile value *addr.\nfunc LoadUint64(addr *uint64) (val uint64)\n\n// StoreUint8 stores val to the volatile value *addr.\nfunc StoreUint8(addr *uint8, val uint8)\n\n// StoreUint16 stores val to the volatile value *addr.\nfunc StoreUint16(addr *uint16, val uint16)\n\n// StoreUint32 stores val to the volatile value *addr.\nfunc StoreUint32(addr *uint32, val uint32)\n\n// StoreUint64 stores val to the volatile value *addr.\nfunc StoreUint64(addr *uint64, val uint64)\n"
  },
  {
    "path": "src/runtime/wait_other.go",
    "content": "//go:build !tinygo.riscv && !cortexm && !(linux && !baremetal && !tinygo.wasm && !nintendoswitch) && !darwin\n\npackage runtime\n\nfunc waitForEvents() {\n\truntimePanic(\"deadlocked: no event source\")\n}\n"
  },
  {
    "path": "src/runtime/zero_new_alloc.go",
    "content": "//go:build gc.leaking && (baremetal || nintendoswitch)\n\npackage runtime\n\nimport (\n\t\"unsafe\"\n)\n\n//go:inline\nfunc zero_new_alloc(ptr unsafe.Pointer, size uintptr) {\n\tmemzero(ptr, size)\n}\n"
  },
  {
    "path": "src/runtime/zero_new_alloc_noop.go",
    "content": "//go:build gc.leaking && !baremetal && !nintendoswitch\n\npackage runtime\n\nimport (\n\t\"unsafe\"\n)\n\n//go:inline\nfunc zero_new_alloc(ptr unsafe.Pointer, size uintptr) {\n\t// Wasm linear memory is initialized to zero by default, so\n\t// there's no need to do anything.  This is also the case for\n\t// fresh-allocated memory from an mmap() system call.\n}\n"
  },
  {
    "path": "src/sync/cond.go",
    "content": "package sync\n\nimport (\n\t\"internal/task\"\n\t\"unsafe\"\n)\n\n// Condition variable.\n// A goroutine that called Wait() can be in one of a few states depending on the\n// Task.Data field:\n// - When entering Wait, and before going to sleep, the data field is 0.\n// - When the goroutine that calls Wait changes its data value from 0 to 1, it\n//   is going to sleep. It has not been awoken early.\n// - When instead a call to Signal or Broadcast can change the data field from 0\n//   to 1, it will _not_ go to sleep but be signalled early.\n//   This can happen when a concurrent call to Signal happens, or the Unlock\n//   function calls Signal for some reason.\n\ntype Cond struct {\n\tL Locker\n\n\tblocked task.Stack\n\tlock    task.PMutex\n}\n\nfunc NewCond(l Locker) *Cond {\n\treturn &Cond{L: l}\n}\n\nfunc (c *Cond) trySignal() bool {\n\t// Pop a blocked task off of the stack, and schedule it if applicable.\n\tt := c.blocked.Pop()\n\tif t != nil {\n\t\tdataPtr := (*task.Uint32)(unsafe.Pointer(&t.Data))\n\n\t\t// The data value is 0 when the task is not yet sleeping, and 1 when it is.\n\t\tif dataPtr.Swap(1) != 0 {\n\t\t\t// The value was already 1, so the task went to sleep (or is about to go\n\t\t\t// to sleep). Schedule the task to be resumed.\n\t\t\tscheduleTask(t)\n\t\t}\n\t\treturn true\n\t}\n\n\t// There was nothing to signal.\n\treturn false\n}\n\nfunc (c *Cond) Signal() {\n\tc.lock.Lock()\n\tc.trySignal()\n\tc.lock.Unlock()\n}\n\nfunc (c *Cond) Broadcast() {\n\t// Signal everything.\n\tc.lock.Lock()\n\tfor c.trySignal() {\n\t}\n\tc.lock.Unlock()\n}\n\nfunc (c *Cond) Wait() {\n\t// Mark us as not yet signalled or sleeping.\n\tt := task.Current()\n\tdataPtr := (*task.Uint32)(unsafe.Pointer(&t.Data))\n\tdataPtr.Store(0)\n\n\t// Add us to the list of waiting goroutines.\n\tc.lock.Lock()\n\tc.blocked.Push(t)\n\tc.lock.Unlock()\n\n\t// Temporarily unlock L.\n\tc.L.Unlock()\n\n\t// Re-acquire the lock before returning.\n\tdefer c.L.Lock()\n\n\t// If we were signaled while unlocking, immediately complete.\n\tif dataPtr.Swap(1) != 0 {\n\t\t// The data value was already 1, so we got a signal already (and weren't\n\t\t// scheduled because trySignal was the first to change the value).\n\t\treturn\n\t}\n\n\t// We were the first to change the value from 0 to 1, meaning we did not get\n\t// a signal during the call to Unlock(). So we wait until we do get a\n\t// signal.\n\ttask.Pause()\n}\n\n//go:linkname scheduleTask runtime.scheduleTask\nfunc scheduleTask(*task.Task)\n"
  },
  {
    "path": "src/sync/cond_test.go",
    "content": "package sync_test\n\nimport (\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"testing\"\n)\n\n// TestCondSignal tests waiting on a Cond and notifying it with Signal.\nfunc TestCondSignal(t *testing.T) {\n\t// Create a Cond with a normal mutex.\n\tcond := sync.Cond{\n\t\tL: &sync.Mutex{},\n\t}\n\tcond.L.Lock()\n\n\t// Start a goroutine to signal us once we wait.\n\tvar signaled uint32\n\tgo func() {\n\t\t// Wait for the test goroutine to wait.\n\t\tcond.L.Lock()\n\t\tdefer cond.L.Unlock()\n\n\t\t// Send a signal to the test goroutine.\n\t\tatomic.StoreUint32(&signaled, 1)\n\t\tcond.Signal()\n\t}()\n\n\t// Wait for a signal.\n\t// This will unlock the mutex, and allow the spawned goroutine to run.\n\tcond.Wait()\n\tif atomic.LoadUint32(&signaled) == 0 {\n\t\tt.Error(\"wait returned before a signal was sent\")\n\t}\n}\n\nfunc TestCondBroadcast(t *testing.T) {\n\t// Create a Cond with an RWMutex.\n\tvar mu sync.RWMutex\n\tcond := sync.Cond{\n\t\tL: mu.RLocker(),\n\t}\n\n\t// Start goroutines to wait for the broadcast.\n\tvar wg sync.WaitGroup\n\tconst n = 5\n\tfor i := 0; i < n; i++ {\n\t\twg.Add(1)\n\t\tmu.RLock()\n\t\tgo func() {\n\t\t\tdefer wg.Done()\n\n\t\t\tcond.Wait()\n\t\t}()\n\t}\n\n\t// Wait for all goroutines to start waiting.\n\tmu.Lock()\n\n\t// Broadcast to all of the waiting goroutines.\n\tcond.Broadcast()\n\n\t// Wait for all spawned goroutines to process the broadcast.\n\tmu.Unlock()\n\twg.Wait()\n}\n\n// TestCondUnlockNotify verifies that a signal is processed even if it happens during the mutex unlock in Wait.\nfunc TestCondUnlockNotify(t *testing.T) {\n\t// Create a Cond that signals itself when waiting.\n\tvar cond sync.Cond\n\tcond.L = fakeLocker{cond.Signal}\n\n\tcond.Wait()\n}\n\n// fakeLocker is a fake sync.Locker where unlock calls an arbitrary function.\ntype fakeLocker struct {\n\tunlock func()\n}\n\nfunc (l fakeLocker) Lock()   {}\nfunc (l fakeLocker) Unlock() { l.unlock() }\n"
  },
  {
    "path": "src/sync/doc.go",
    "content": "// Package sync implements synchronization primitives similar to those provided by the standard Go implementation.\n// These are not safe to access from within interrupts, or from another thread.\n// The primitives also lack any fairness guarantees, similar to channels and the scheduler.\npackage sync\n"
  },
  {
    "path": "src/sync/map.go",
    "content": "package sync\n\nimport \"internal/task\"\n\n// This file implements just enough of sync.Map to get packages to compile. It\n// is no more efficient than a map with a lock.\n\ntype Map struct {\n\tlock task.PMutex\n\tm    map[interface{}]interface{}\n}\n\nfunc (m *Map) Delete(key interface{}) {\n\tm.lock.Lock()\n\tdefer m.lock.Unlock()\n\tdelete(m.m, key)\n}\n\nfunc (m *Map) Load(key interface{}) (value interface{}, ok bool) {\n\tm.lock.Lock()\n\tdefer m.lock.Unlock()\n\tvalue, ok = m.m[key]\n\treturn\n}\n\nfunc (m *Map) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool) {\n\tm.lock.Lock()\n\tdefer m.lock.Unlock()\n\tif m.m == nil {\n\t\tm.m = make(map[interface{}]interface{})\n\t}\n\tif existing, ok := m.m[key]; ok {\n\t\treturn existing, true\n\t}\n\tm.m[key] = value\n\treturn value, false\n}\n\nfunc (m *Map) LoadAndDelete(key interface{}) (value interface{}, loaded bool) {\n\tm.lock.Lock()\n\tdefer m.lock.Unlock()\n\tvalue, ok := m.m[key]\n\tif !ok {\n\t\treturn nil, false\n\t}\n\tdelete(m.m, key)\n\treturn value, true\n}\n\nfunc (m *Map) Store(key, value interface{}) {\n\tm.lock.Lock()\n\tdefer m.lock.Unlock()\n\tif m.m == nil {\n\t\tm.m = make(map[interface{}]interface{})\n\t}\n\tm.m[key] = value\n}\n\nfunc (m *Map) Range(f func(key, value interface{}) bool) {\n\tm.lock.Lock()\n\tdefer m.lock.Unlock()\n\n\tif m.m == nil {\n\t\treturn\n\t}\n\n\tfor k, v := range m.m {\n\t\tif !f(k, v) {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\n// Swap replaces the value for the given key, and returns the old value if any.\nfunc (m *Map) Swap(key, value any) (previous any, loaded bool) {\n\tm.lock.Lock()\n\tdefer m.lock.Unlock()\n\tif m.m == nil {\n\t\tm.m = make(map[interface{}]interface{})\n\t}\n\tprevious, loaded = m.m[key]\n\tm.m[key] = value\n\treturn\n}\n"
  },
  {
    "path": "src/sync/map_go123.go",
    "content": "//go:build go1.23\n\npackage sync\n\n// Go 1.23 added the Clear() method. The clear() function is added in Go 1.21,\n// so this method can be moved to map.go once we drop support for Go 1.20 and\n// below.\n\nfunc (m *Map) Clear() {\n\tm.lock.Lock()\n\tdefer m.lock.Unlock()\n\tclear(m.m)\n}\n"
  },
  {
    "path": "src/sync/map_test.go",
    "content": "package sync_test\n\nimport (\n\t\"sync\"\n\t\"testing\"\n)\n\nfunc TestMapLoadAndDelete(t *testing.T) {\n\tvar sm sync.Map\n\tsm.Store(\"present\", \"value\")\n\n\tif v, ok := sm.LoadAndDelete(\"present\"); !ok || v != \"value\" {\n\t\tt.Errorf(\"LoadAndDelete returned %v, %v, want value, true\", v, ok)\n\t}\n\n\tif v, ok := sm.LoadAndDelete(\"absent\"); ok || v != nil {\n\t\tt.Errorf(\"LoadAndDelete returned %v, %v, want nil, false\", v, ok)\n\t}\n}\n\nfunc TestMapSwap(t *testing.T) {\n\tvar sm sync.Map\n\tsm.Store(\"present\", \"value\")\n\n\tif v, ok := sm.Swap(\"present\", \"value2\"); !ok || v != \"value\" {\n\t\tt.Errorf(\"Swap returned %v, %v, want value, true\", v, ok)\n\t}\n\tif v, ok := sm.Load(\"present\"); !ok || v != \"value2\" {\n\t\tt.Errorf(\"Load after Swap returned %v, %v, want value2, true\", v, ok)\n\t}\n\n\tif v, ok := sm.Swap(\"new\", \"foo\"); ok || v != nil {\n\t\tt.Errorf(\"Swap returned %v, %v, want nil, false\", v, ok)\n\t}\n\tif v, ok := sm.Load(\"present\"); !ok || v != \"value2\" {\n\t\tt.Errorf(\"Load after Swap returned %v, %v, want foo, true\", v, ok)\n\t}\n}\n"
  },
  {
    "path": "src/sync/mutex.go",
    "content": "package sync\n\nimport (\n\t\"internal/task\"\n)\n\ntype Mutex = task.Mutex\n\n//go:linkname runtimePanic runtime.runtimePanic\nfunc runtimePanic(msg string)\n\ntype RWMutex struct {\n\t// Reader count, with the number of readers that currently have read-locked\n\t// this mutex.\n\t// The value can be in two states: one where 0 means no readers and another\n\t// where -rwMutexMaxReaders means no readers. A base of 0 is normal\n\t// uncontended operation, a base of -rwMutexMaxReaders means a writer has\n\t// the lock or is trying to get the lock. In the second case, readers should\n\t// wait until the reader count becomes non-negative again to give the writer\n\t// a chance to obtain the lock.\n\treaders task.Futex\n\n\t// Writer futex, normally 0. If there is a writer waiting until all readers\n\t// have unlocked, this value is 1. It will be changed to a 2 (and get a\n\t// wake) when the last reader unlocks.\n\twriter task.Futex\n\n\t// Writer lock. Held between Lock() and Unlock().\n\twriterLock Mutex\n}\n\nconst rwMutexMaxReaders = 1 << 30\n\n// Lock locks rw for writing.\n// If the lock is already locked for reading or writing,\n// Lock blocks until the lock is available.\nfunc (rw *RWMutex) Lock() {\n\t// Exclusive lock for writers.\n\trw.writerLock.Lock()\n\n\t// Flag that we need to be awakened after the last read-lock unlocks.\n\trw.writer.Store(1)\n\n\t// Signal to readers that they can't lock this mutex anymore.\n\tn := uint32(rwMutexMaxReaders)\n\twaiting := rw.readers.Add(-n)\n\tif int32(waiting) == -rwMutexMaxReaders {\n\t\t// All readers were already unlocked, so we don't need to wait for them.\n\t\trw.writer.Store(0)\n\t\treturn\n\t}\n\n\t// There is at least one reader.\n\t// Wait until all readers are unlocked. The last reader to unlock will set\n\t// rw.writer to 2 and awaken us.\n\tfor rw.writer.Load() == 1 {\n\t\trw.writer.Wait(1)\n\t}\n\trw.writer.Store(0)\n}\n\n// Unlock unlocks rw for writing. It is a run-time error if rw is\n// not locked for writing on entry to Unlock.\n//\n// As with Mutexes, a locked [RWMutex] is not associated with a particular\n// goroutine. One goroutine may [RWMutex.RLock] ([RWMutex.Lock]) a RWMutex and then\n// arrange for another goroutine to [RWMutex.RUnlock] ([RWMutex.Unlock]) it.\nfunc (rw *RWMutex) Unlock() {\n\t// Signal that new readers can lock this mutex.\n\twaiting := rw.readers.Add(rwMutexMaxReaders)\n\tif waiting != 0 {\n\t\t// Awaken all waiting readers.\n\t\trw.readers.WakeAll()\n\t}\n\n\t// Done with this lock (next writer can try to get a lock).\n\trw.writerLock.Unlock()\n}\n\n// TryLock tries to lock m and reports whether it succeeded.\n//\n// Note that while correct uses of TryLock do exist, they are rare,\n// and use of TryLock is often a sign of a deeper problem\n// in a particular use of mutexes.\nfunc (rw *RWMutex) TryLock() bool {\n\t// Check for active writers\n\tif !rw.writerLock.TryLock() {\n\t\treturn false\n\t}\n\t// Have write lock, now check for active readers\n\tn := uint32(rwMutexMaxReaders)\n\tif !rw.readers.CompareAndSwap(0, -n) {\n\t\t// Active readers, give up write lock\n\t\trw.writerLock.Unlock()\n\t\treturn false\n\t}\n\treturn true\n}\n\n// RLock locks rw for reading.\n//\n// It should not be used for recursive read locking; a blocked Lock\n// call excludes new readers from acquiring the lock. See the\n// documentation on the [RWMutex] type.\nfunc (rw *RWMutex) RLock() {\n\t// Add us as a reader.\n\tnewVal := rw.readers.Add(1)\n\n\t// Wait until the RWMutex is available for readers.\n\tfor int32(newVal) <= 0 {\n\t\trw.readers.Wait(newVal)\n\t\tnewVal = rw.readers.Load()\n\t}\n}\n\n// RUnlock undoes a single [RWMutex.RLock] call;\n// it does not affect other simultaneous readers.\n// It is a run-time error if rw is not locked for reading\n// on entry to RUnlock.\nfunc (rw *RWMutex) RUnlock() {\n\t// Remove us as a reader.\n\tone := uint32(1)\n\treaders := int32(rw.readers.Add(-one))\n\n\t// Check whether RUnlock was called too often.\n\tif readers == -1 || readers == (-rwMutexMaxReaders)-1 {\n\t\truntimePanic(\"sync: RUnlock of unlocked RWMutex\")\n\t}\n\n\tif readers == -rwMutexMaxReaders {\n\t\t// This was the last read lock. Check whether we need to wake up a write\n\t\t// lock.\n\t\tif rw.writer.CompareAndSwap(1, 2) {\n\t\t\trw.writer.Wake()\n\t\t}\n\t}\n}\n\n// TryRLock tries to lock rw for reading and reports whether it succeeded.\n//\n// Note that while correct uses of TryRLock do exist, they are rare,\n// and use of TryRLock is often a sign of a deeper problem\n// in a particular use of mutexes.\nfunc (rw *RWMutex) TryRLock() bool {\n\tfor {\n\t\tc := rw.readers.Load()\n\t\tif c < 0 {\n\t\t\t// There is a writer waiting or writing.\n\t\t\treturn false\n\t\t}\n\t\tif rw.readers.CompareAndSwap(c, c+1) {\n\t\t\t// Read lock obtained.\n\t\t\treturn true\n\t\t}\n\t}\n}\n\ntype Locker interface {\n\tLock()\n\tUnlock()\n}\n\n// RLocker returns a Locker interface that implements\n// the Lock and Unlock methods by calling rw.RLock and rw.RUnlock.\nfunc (rw *RWMutex) RLocker() Locker {\n\treturn (*rlocker)(rw)\n}\n\ntype rlocker RWMutex\n\nfunc (r *rlocker) Lock()   { (*RWMutex)(r).RLock() }\nfunc (r *rlocker) Unlock() { (*RWMutex)(r).RUnlock() }\n"
  },
  {
    "path": "src/sync/mutex_test.go",
    "content": "package sync_test\n\nimport (\n\t\"runtime\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"testing\"\n)\n\ntype mutex interface {\n\tLock()\n\tUnlock()\n\tTryLock() bool\n}\n\nfunc HammerMutex(m mutex, loops int, cdone chan bool) {\n\tfor i := 0; i < loops; i++ {\n\t\tif i%3 == 0 {\n\t\t\tif m.TryLock() {\n\t\t\t\tm.Unlock()\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tm.Lock()\n\t\tm.Unlock()\n\t}\n\tcdone <- true\n}\n\nfunc TestMutex(t *testing.T) {\n\tm := new(sync.Mutex)\n\n\tm.Lock()\n\tif m.TryLock() {\n\t\tt.Fatalf(\"TryLock succeeded with mutex locked\")\n\t}\n\tm.Unlock()\n\tif !m.TryLock() {\n\t\tt.Fatalf(\"TryLock failed with mutex unlocked\")\n\t}\n\tm.Unlock()\n\n\tc := make(chan bool)\n\tfor i := 0; i < 10; i++ {\n\t\tgo HammerMutex(m, 1000, c)\n\t}\n\tfor i := 0; i < 10; i++ {\n\t\t<-c\n\t}\n}\n\n// TestMutexUncontended tests locking and unlocking a Mutex that is not shared with any other goroutines.\nfunc TestMutexUncontended(t *testing.T) {\n\tvar mu sync.Mutex\n\n\t// Lock and unlock the mutex a few times.\n\tfor i := 0; i < 3; i++ {\n\t\tmu.Lock()\n\t\tmu.Unlock()\n\t}\n}\n\n// TestMutexConcurrent tests a mutex concurrently from multiple goroutines.\n// It will fail if multiple goroutines hold the lock simultaneously.\nfunc TestMutexConcurrent(t *testing.T) {\n\tvar mu sync.Mutex\n\tvar active atomic.Uint32\n\tvar completed atomic.Uint32\n\tvar fail atomic.Uint32\n\n\tconst n = 10\n\tfor i := 0; i < n; i++ {\n\t\tj := i\n\t\tgo func() {\n\t\t\t// Delay a bit.\n\t\t\tfor k := j; k > 0; k-- {\n\t\t\t\truntime.Gosched()\n\t\t\t}\n\n\t\t\tmu.Lock()\n\n\t\t\t// Increment the active counter.\n\t\t\tnowActive := active.Add(1)\n\n\t\t\tif nowActive > 1 {\n\t\t\t\t// Multiple things are holding the lock at the same time.\n\t\t\t\tfail.Store(1)\n\t\t\t} else {\n\t\t\t\t// Delay a bit.\n\t\t\t\tfor k := j; k < n; k++ {\n\t\t\t\t\truntime.Gosched()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Decrement the active counter.\n\t\t\tvar one = 1\n\t\t\tactive.Add(uint32(-one))\n\n\t\t\t// This is completed.\n\t\t\tcompleted.Add(1)\n\n\t\t\tmu.Unlock()\n\t\t}()\n\t}\n\n\t// Wait for everything to finish.\n\tvar done bool\n\tfor !done {\n\t\t// Wait a bit for other things to run.\n\t\truntime.Gosched()\n\n\t\t// Acquire the lock and check whether everything has completed.\n\t\tmu.Lock()\n\t\tdone = completed.Load() == n\n\t\tmu.Unlock()\n\t}\n\tif fail.Load() != 0 {\n\t\tt.Error(\"lock held concurrently\")\n\t}\n}\n\n// TestRWMutexUncontended tests locking and unlocking an RWMutex that is not shared with any other goroutines.\nfunc TestRWMutexUncontended(t *testing.T) {\n\tvar mu sync.RWMutex\n\n\t// Lock the mutex exclusively and then unlock it.\n\tmu.Lock()\n\tmu.Unlock()\n\n\t// Acquire several read locks.\n\tconst n = 5\n\tfor i := 0; i < n; i++ {\n\t\tmu.RLock()\n\t}\n\n\t// Release all of the read locks.\n\tfor i := 0; i < n; i++ {\n\t\tmu.RUnlock()\n\t}\n\n\t// Re-acquire the lock exclusively.\n\tmu.Lock()\n\tmu.Unlock()\n}\n\n// TestRWMutexWriteToRead tests the transition from a write lock to a read lock while contended.\nfunc TestRWMutexWriteToRead(t *testing.T) {\n\t// Create a new RWMutex and acquire a write lock.\n\tvar mu sync.RWMutex\n\tmu.Lock()\n\n\tconst n = 3\n\tvar readAcquires uint32\n\tvar completed uint32\n\tvar unlocked uint32\n\tvar bad uint32\n\tfor i := 0; i < n; i++ {\n\t\tgo func() {\n\t\t\t// Acquire a read lock.\n\t\t\tmu.RLock()\n\n\t\t\t// Verify that the write lock is supposed to be released by now.\n\t\t\tif atomic.LoadUint32(&unlocked) == 0 {\n\t\t\t\t// The write lock is still being held.\n\t\t\t\tatomic.AddUint32(&bad, 1)\n\t\t\t}\n\n\t\t\t// Add ourselves to the read lock counter.\n\t\t\tatomic.AddUint32(&readAcquires, 1)\n\n\t\t\t// Wait for everything to hold the read lock simultaneously.\n\t\t\tfor atomic.LoadUint32(&readAcquires) < n {\n\t\t\t\truntime.Gosched()\n\t\t\t}\n\n\t\t\t// Notify of completion.\n\t\t\tatomic.AddUint32(&completed, 1)\n\n\t\t\t// Release the read lock.\n\t\t\tmu.RUnlock()\n\t\t}()\n\t}\n\n\t// Wait a bit for the goroutines to block.\n\tfor i := 0; i < 3*n; i++ {\n\t\truntime.Gosched()\n\t}\n\n\t// Release the write lock so that the goroutines acquire read locks.\n\tatomic.StoreUint32(&unlocked, 1)\n\tmu.Unlock()\n\n\t// Wait for everything to complete.\n\tfor atomic.LoadUint32(&completed) < n {\n\t\truntime.Gosched()\n\t}\n\n\t// Acquire another write lock.\n\tmu.Lock()\n\n\tif bad != 0 {\n\t\tt.Error(\"read lock acquired while write-locked\")\n\t}\n}\n\n// TestRWMutexReadToWrite tests the transition from a read lock to a write lock while contended.\nfunc TestRWMutexReadToWrite(t *testing.T) {\n\t// Create a new RWMutex and read-lock it several times.\n\tconst n = 3\n\tvar mu sync.RWMutex\n\tvar readers uint32\n\tfor i := 0; i < n; i++ {\n\t\tmu.RLock()\n\t\treaders++\n\t}\n\n\t// Start a goroutine to acquire a write lock.\n\tresult := ^uint32(0)\n\tgo func() {\n\t\t// Acquire a write lock.\n\t\tmu.Lock()\n\n\t\t// Check for active readers.\n\t\treaders := atomic.LoadUint32(&readers)\n\n\t\tmu.Unlock()\n\n\t\t// Report the number of active readers.\n\t\tatomic.StoreUint32(&result, readers)\n\t}()\n\n\t// Release the read locks.\n\tfor i := 0; i < n; i++ {\n\t\truntime.Gosched()\n\t\tatomic.AddUint32(&readers, ^uint32(0))\n\t\tmu.RUnlock()\n\t}\n\n\t// Wait for a result.\n\tvar res uint32\n\tfor res == ^uint32(0) {\n\t\truntime.Gosched()\n\t\tres = atomic.LoadUint32(&result)\n\t}\n\tif res != 0 {\n\t\tt.Errorf(\"write lock acquired while %d readers were active\", res)\n\t}\n}\n\nfunc TestRWMutex(t *testing.T) {\n\tm := new(sync.RWMutex)\n\n\tm.Lock()\n\tif m.TryLock() {\n\t\tt.Fatalf(\"TryLock succeeded with mutex locked\")\n\t}\n\tm.Unlock()\n\tif !m.TryLock() {\n\t\tt.Fatalf(\"TryLock failed with mutex unlocked\")\n\t}\n\tm.Unlock()\n\n\tc := make(chan bool)\n\tfor i := 0; i < 10; i++ {\n\t\tgo HammerMutex(m, 1000, c)\n\t}\n\tfor i := 0; i < 10; i++ {\n\t\t<-c\n\t}\n}\n"
  },
  {
    "path": "src/sync/once.go",
    "content": "package sync\n\ntype Once struct {\n\tdone bool\n\tm    Mutex\n}\n\nfunc (o *Once) Do(f func()) {\n\to.m.Lock()\n\tdefer o.m.Unlock()\n\tif o.done {\n\t\treturn\n\t}\n\to.done = true\n\tf()\n}\n"
  },
  {
    "path": "src/sync/once_test.go",
    "content": "package sync_test\n\nimport (\n\t\"sync\"\n\t\"testing\"\n)\n\n// TestOnceUncontended tests Once on a single goroutine.\nfunc TestOnceUncontended(t *testing.T) {\n\tvar once sync.Once\n\t{\n\t\tvar ran bool\n\t\tonce.Do(func() {\n\t\t\tran = true\n\t\t})\n\t\tif !ran {\n\t\t\tt.Error(\"first call to Do did not run\")\n\t\t}\n\t}\n\t{\n\t\tvar ran bool\n\t\tonce.Do(func() {\n\t\t\tran = true\n\t\t})\n\t\tif ran {\n\t\t\tt.Error(\"second call to Do ran\")\n\t\t}\n\t}\n}\n\n// TestOnceConcurrent tests multiple concurrent invocations of sync.Once.\nfunc TestOnceConcurrent(t *testing.T) {\n\tvar once sync.Once\n\tvar mu sync.Mutex\n\tmu.Lock()\n\tvar ran bool\n\tvar ranTwice bool\n\tonce.Do(func() {\n\t\tran = true\n\n\t\t// Start a goroutine and (approximately) wait for it to enter the call to Do.\n\t\tvar startWait sync.Mutex\n\t\tstartWait.Lock()\n\t\tgo func() {\n\t\t\tstartWait.Unlock()\n\t\t\tonce.Do(func() {\n\t\t\t\tranTwice = true\n\t\t\t})\n\t\t\tmu.Unlock()\n\t\t}()\n\t\tstartWait.Lock()\n\t})\n\tif !ran {\n\t\tt.Error(\"first call to Do did not run\")\n\t}\n\n\t// Wait for the goroutine to finish.\n\tmu.Lock()\n\tif ranTwice {\n\t\tt.Error(\"second concurrent call to Once also ran\")\n\t}\n}\n"
  },
  {
    "path": "src/sync/oncefunc.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage sync\n\n// OnceFunc returns a function that invokes f only once. The returned function\n// may be called concurrently.\n//\n// If f panics, the returned function will panic with the same value on every call.\nfunc OnceFunc(f func()) func() {\n\tvar (\n\t\tonce  Once\n\t\tvalid bool\n\t\tp     any\n\t)\n\t// Construct the inner closure just once to reduce costs on the fast path.\n\tg := func() {\n\t\tdefer func() {\n\t\t\tp = recover()\n\t\t\tif !valid {\n\t\t\t\t// Re-panic immediately so on the first call the user gets a\n\t\t\t\t// complete stack trace into f.\n\t\t\t\tpanic(p)\n\t\t\t}\n\t\t}()\n\t\tf()\n\t\tvalid = true // Set only if f does not panic\n\t}\n\treturn func() {\n\t\tonce.Do(g)\n\t\tif !valid {\n\t\t\tpanic(p)\n\t\t}\n\t}\n}\n\n// OnceValue returns a function that invokes f only once and returns the value\n// returned by f. The returned function may be called concurrently.\n//\n// If f panics, the returned function will panic with the same value on every call.\nfunc OnceValue[T any](f func() T) func() T {\n\tvar (\n\t\tonce   Once\n\t\tvalid  bool\n\t\tp      any\n\t\tresult T\n\t)\n\tg := func() {\n\t\tdefer func() {\n\t\t\tp = recover()\n\t\t\tif !valid {\n\t\t\t\tpanic(p)\n\t\t\t}\n\t\t}()\n\t\tresult = f()\n\t\tvalid = true\n\t}\n\treturn func() T {\n\t\tonce.Do(g)\n\t\tif !valid {\n\t\t\tpanic(p)\n\t\t}\n\t\treturn result\n\t}\n}\n\n// OnceValues returns a function that invokes f only once and returns the values\n// returned by f. The returned function may be called concurrently.\n//\n// If f panics, the returned function will panic with the same value on every call.\nfunc OnceValues[T1, T2 any](f func() (T1, T2)) func() (T1, T2) {\n\tvar (\n\t\tonce  Once\n\t\tvalid bool\n\t\tp     any\n\t\tr1    T1\n\t\tr2    T2\n\t)\n\tg := func() {\n\t\tdefer func() {\n\t\t\tp = recover()\n\t\t\tif !valid {\n\t\t\t\tpanic(p)\n\t\t\t}\n\t\t}()\n\t\tr1, r2 = f()\n\t\tvalid = true\n\t}\n\treturn func() (T1, T2) {\n\t\tonce.Do(g)\n\t\tif !valid {\n\t\t\tpanic(p)\n\t\t}\n\t\treturn r1, r2\n\t}\n}\n"
  },
  {
    "path": "src/sync/oncefunc_test.go",
    "content": "// Copyright 2022 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage sync_test\n\nimport (\n\t\"sync\"\n\t\"testing\"\n)\n\n// We assume that the Once.Do tests have already covered parallelism.\n\nfunc TestOnceFunc(t *testing.T) {\n\tcalls := 0\n\tf := sync.OnceFunc(func() { calls++ })\n\tallocs := testing.AllocsPerRun(10, f)\n\tif calls != 1 {\n\t\tt.Errorf(\"want calls==1, got %d\", calls)\n\t}\n\tif allocs != 0 {\n\t\tt.Errorf(\"want 0 allocations per call, got %v\", allocs)\n\t}\n}\n\nfunc TestOnceValue(t *testing.T) {\n\tcalls := 0\n\tf := sync.OnceValue(func() int {\n\t\tcalls++\n\t\treturn calls\n\t})\n\tallocs := testing.AllocsPerRun(10, func() { f() })\n\tvalue := f()\n\tif calls != 1 {\n\t\tt.Errorf(\"want calls==1, got %d\", calls)\n\t}\n\tif value != 1 {\n\t\tt.Errorf(\"want value==1, got %d\", value)\n\t}\n\tif allocs != 0 {\n\t\tt.Errorf(\"want 0 allocations per call, got %v\", allocs)\n\t}\n}\n\nfunc TestOnceValues(t *testing.T) {\n\tcalls := 0\n\tf := sync.OnceValues(func() (int, int) {\n\t\tcalls++\n\t\treturn calls, calls + 1\n\t})\n\tallocs := testing.AllocsPerRun(10, func() { f() })\n\tv1, v2 := f()\n\tif calls != 1 {\n\t\tt.Errorf(\"want calls==1, got %d\", calls)\n\t}\n\tif v1 != 1 || v2 != 2 {\n\t\tt.Errorf(\"want v1==1 and v2==2, got %d and %d\", v1, v2)\n\t}\n\tif allocs != 0 {\n\t\tt.Errorf(\"want 0 allocations per call, got %v\", allocs)\n\t}\n}\n\n// TODO: need to implement more complete panic handling for these tests.\n// func testOncePanicX(t *testing.T, calls *int, f func()) {\n// \ttestOncePanicWith(t, calls, f, func(label string, p any) {\n// \t\tif p != \"x\" {\n// \t\t\tt.Fatalf(\"%s: want panic %v, got %v\", label, \"x\", p)\n// \t\t}\n// \t})\n// }\n\n// func testOncePanicWith(t *testing.T, calls *int, f func(), check func(label string, p any)) {\n// \t// Check that the each call to f panics with the same value, but the\n// \t// underlying function is only called once.\n// \tfor _, label := range []string{\"first time\", \"second time\"} {\n// \t\tvar p any\n// \t\tpanicked := true\n// \t\tfunc() {\n// \t\t\tdefer func() {\n// \t\t\t\tp = recover()\n// \t\t\t}()\n// \t\t\tf()\n// \t\t\tpanicked = false\n// \t\t}()\n// \t\tif !panicked {\n// \t\t\tt.Fatalf(\"%s: f did not panic\", label)\n// \t\t}\n// \t\tcheck(label, p)\n// \t}\n// \tif *calls != 1 {\n// \t\tt.Errorf(\"want calls==1, got %d\", *calls)\n// \t}\n// }\n\n// func TestOnceFuncPanic(t *testing.T) {\n// \tcalls := 0\n// \tf := sync.OnceFunc(func() {\n// \t\tcalls++\n// \t\tpanic(\"x\")\n// \t})\n// \ttestOncePanicX(t, &calls, f)\n// }\n\n// func TestOnceValuePanic(t *testing.T) {\n// \tcalls := 0\n// \tf := sync.OnceValue(func() int {\n// \t\tcalls++\n// \t\tpanic(\"x\")\n// \t})\n// \ttestOncePanicX(t, &calls, func() { f() })\n// }\n\n// func TestOnceValuesPanic(t *testing.T) {\n// \tcalls := 0\n// \tf := sync.OnceValues(func() (int, int) {\n// \t\tcalls++\n// \t\tpanic(\"x\")\n// \t})\n// \ttestOncePanicX(t, &calls, func() { f() })\n// }\n//\n// func TestOnceFuncPanicNil(t *testing.T) {\n// \tcalls := 0\n// \tf := sync.OnceFunc(func() {\n// \t\tcalls++\n// \t\tpanic(nil)\n// \t})\n// \ttestOncePanicWith(t, &calls, f, func(label string, p any) {\n// \t\tswitch p.(type) {\n// \t\tcase nil, *runtime.PanicNilError:\n// \t\t\treturn\n// \t\t}\n// \t\tt.Fatalf(\"%s: want nil panic, got %v\", label, p)\n// \t})\n// }\n//\n// func TestOnceFuncGoexit(t *testing.T) {\n// \t// If f calls Goexit, the results are unspecified. But check that f doesn't\n// \t// get called twice.\n// \tcalls := 0\n// \tf := sync.OnceFunc(func() {\n// \t\tcalls++\n// \t\truntime.Goexit()\n// \t})\n// \tvar wg sync.WaitGroup\n// \tfor i := 0; i < 2; i++ {\n// \t\twg.Add(1)\n// \t\tgo func() {\n// \t\t\tdefer wg.Done()\n// \t\t\tdefer func() { recover() }()\n// \t\t\tf()\n// \t\t}()\n// \t\twg.Wait()\n// \t}\n// \tif calls != 1 {\n// \t\tt.Errorf(\"want calls==1, got %d\", calls)\n// \t}\n// }\n"
  },
  {
    "path": "src/sync/pool.go",
    "content": "package sync\n\nimport \"internal/task\"\n\n// Pool is a very simple implementation of sync.Pool.\ntype Pool struct {\n\tlock  task.PMutex\n\tNew   func() interface{}\n\titems []interface{}\n}\n\n// Get returns an item in the pool, or the value of calling Pool.New() if there are no items.\nfunc (p *Pool) Get() interface{} {\n\tp.lock.Lock()\n\tif len(p.items) > 0 {\n\t\tx := p.items[len(p.items)-1]\n\t\tp.items = p.items[:len(p.items)-1]\n\t\tp.lock.Unlock()\n\t\treturn x\n\t}\n\tp.lock.Unlock()\n\tif p.New == nil {\n\t\treturn nil\n\t}\n\treturn p.New()\n}\n\n// Put adds a value back into the pool.\nfunc (p *Pool) Put(x interface{}) {\n\tp.lock.Lock()\n\tp.items = append(p.items, x)\n\tp.lock.Unlock()\n}\n"
  },
  {
    "path": "src/sync/pool_test.go",
    "content": "package sync_test\n\nimport (\n\t\"sync\"\n\t\"testing\"\n)\n\ntype testItem struct {\n\tval int\n}\n\nfunc TestPool(t *testing.T) {\n\tp := sync.Pool{\n\t\tNew: func() interface{} {\n\t\t\treturn &testItem{}\n\t\t},\n\t}\n\n\ti1P := p.Get()\n\tif i1P == nil {\n\t\tt.Error(\"pool with New returned nil\")\n\t}\n\ti1 := i1P.(*testItem)\n\tif got, want := i1.val, 0; got != want {\n\t\tt.Errorf(\"empty pool item value: got %v, want %v\", got, want)\n\t}\n\ti1.val = 1\n\n\ti2 := p.Get().(*testItem)\n\tif got, want := i2.val, 0; got != want {\n\t\tt.Errorf(\"empty pool item value: got %v, want %v\", got, want)\n\t}\n\ti2.val = 2\n\n\tp.Put(i1)\n\n\ti3 := p.Get().(*testItem)\n\tif got, want := i3.val, 1; got != want {\n\t\tt.Errorf(\"pool with item value: got %v, want %v\", got, want)\n\t}\n}\n\nfunc TestPool_noNew(t *testing.T) {\n\tp := sync.Pool{}\n\n\ti1 := p.Get()\n\tif i1 != nil {\n\t\tt.Errorf(\"pool without New returned %v, want nil\", i1)\n\t}\n}\n"
  },
  {
    "path": "src/sync/waitgroup.go",
    "content": "package sync\n\nimport \"internal/task\"\n\ntype WaitGroup struct {\n\tfutex task.Futex\n}\n\nfunc (wg *WaitGroup) Add(delta int) {\n\tswitch {\n\tcase delta > 0:\n\t\t// Delta is positive.\n\t\tfor {\n\t\t\t// Check for overflow.\n\t\t\tcounter := wg.futex.Load()\n\t\t\tif uint32(delta) > (^uint32(0))-counter {\n\t\t\t\tpanic(\"sync: WaitGroup counter overflowed\")\n\t\t\t}\n\n\t\t\t// Add to the counter.\n\t\t\tif wg.futex.CompareAndSwap(counter, counter+uint32(delta)) {\n\t\t\t\t// Successfully added.\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\tdefault:\n\t\t// Delta is negative (or zero).\n\t\tfor {\n\t\t\tcounter := wg.futex.Load()\n\n\t\t\t// Check for underflow.\n\t\t\tif uint32(-delta) > counter {\n\t\t\t\tpanic(\"sync: negative WaitGroup counter\")\n\t\t\t}\n\n\t\t\t// Subtract from the counter.\n\t\t\tif !wg.futex.CompareAndSwap(counter, counter-uint32(-delta)) {\n\t\t\t\t// Could not swap, trying again.\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// If the counter is zero, everything is done and the waiters should\n\t\t\t// be resumed.\n\t\t\t// When there are multiple thread, there is a chance for the counter\n\t\t\t// to go to zero, WakeAll to be called, and then the counter to be\n\t\t\t// incremented again before a waiting goroutine has a chance to\n\t\t\t// check the new (zero) value. However the last increment is\n\t\t\t// explicitly given in the docs as something that should not be\n\t\t\t// done:\n\t\t\t//\n\t\t\t//   > Note that calls with a positive delta that occur when the\n\t\t\t//   > counter is zero must happen before a Wait.\n\t\t\t//\n\t\t\t// So we're fine here.\n\t\t\tif counter-uint32(-delta) == 0 {\n\t\t\t\t// TODO: this is not the most efficient implementation possible\n\t\t\t\t// because we wake up all waiters unconditionally, even if there\n\t\t\t\t// might be none. Though since the common usage is for this to\n\t\t\t\t// be called with at least one waiter, it's probably fine.\n\t\t\t\twg.futex.WakeAll()\n\t\t\t}\n\n\t\t\t// Successfully swapped (and woken all waiting tasks if needed).\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc (wg *WaitGroup) Done() {\n\twg.Add(-1)\n}\n\nfunc (wg *WaitGroup) Wait() {\n\tfor {\n\t\tcounter := wg.futex.Load()\n\t\tif counter == 0 {\n\t\t\treturn // everything already finished\n\t\t}\n\n\t\tif wg.futex.Wait(counter) {\n\t\t\t// Successfully woken by WakeAll (in wg.Add).\n\t\t\tbreak\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/sync/waitgroup_test.go",
    "content": "package sync_test\n\nimport (\n\t\"sync\"\n\t\"testing\"\n)\n\n// TestWaitGroupUncontended tests the wait group from a single goroutine.\nfunc TestWaitGroupUncontended(t *testing.T) {\n\t// Check that a single add-and-done works.\n\tvar wg sync.WaitGroup\n\twg.Add(1)\n\twg.Done()\n\twg.Wait()\n\n\t// Check that mixing positive and negative counts works.\n\twg.Add(10)\n\twg.Add(-8)\n\twg.Add(-1)\n\twg.Add(0)\n\twg.Done()\n\twg.Wait()\n}\n\n// TestWaitGroup tests the typical usage of WaitGroup.\nfunc TestWaitGroup(t *testing.T) {\n\tconst n = 5\n\tvar wg sync.WaitGroup\n\twg.Add(n)\n\tfor i := 0; i < n; i++ {\n\t\tgo wg.Done()\n\t}\n\n\twg.Wait()\n}\n"
  },
  {
    "path": "src/syscall/env_libc.go",
    "content": "//go:build nintendoswitch || wasip1\n\npackage syscall\n\nimport (\n\t\"unsafe\"\n)\n\nfunc Environ() []string {\n\n\t// This function combines all the environment into a single allocation.\n\t// While this optimizes for memory usage and garbage collector\n\t// overhead, it does run the risk of potentially pinning a \"large\"\n\t// allocation if a user holds onto a single environment variable or\n\t// value.  Having each variable be its own allocation would make the\n\t// trade-off in the other direction.\n\n\t// calculate total memory required\n\tvar length uintptr\n\tvar vars int\n\tfor environ := libc_environ; *environ != nil; {\n\t\tlength += libc_strlen(*environ)\n\t\tvars++\n\t\tenviron = (*unsafe.Pointer)(unsafe.Add(unsafe.Pointer(environ), unsafe.Sizeof(environ)))\n\t}\n\n\t// allocate our backing slice for the strings\n\tb := make([]byte, length)\n\t// and the slice we're going to return\n\tenvs := make([]string, 0, vars)\n\n\t// loop over the environment again, this time copying over the data to the backing slice\n\tfor environ := libc_environ; *environ != nil; {\n\t\tlength = libc_strlen(*environ)\n\t\t// construct a Go string pointing at the libc-allocated environment variable data\n\t\tvar envVar string\n\t\trawEnvVar := (*struct {\n\t\t\tptr    unsafe.Pointer\n\t\t\tlength uintptr\n\t\t})(unsafe.Pointer(&envVar))\n\t\trawEnvVar.ptr = *environ\n\t\trawEnvVar.length = length\n\t\t// pull off the number of bytes we need for this environment variable\n\t\tvar bs []byte\n\t\tbs, b = b[:length], b[length:]\n\t\t// copy over the bytes to the Go heap\n\t\tcopy(bs, envVar)\n\t\t// convert trimmed slice to string\n\t\ts := *(*string)(unsafe.Pointer(&bs))\n\t\t// add s to our list of environment variables\n\t\tenvs = append(envs, s)\n\t\t// environ++\n\t\tenviron = (*unsafe.Pointer)(unsafe.Add(unsafe.Pointer(environ), unsafe.Sizeof(environ)))\n\t}\n\treturn envs\n}\n\nfunc Getenv(key string) (value string, found bool) {\n\tdata := cstring(key)\n\traw := libc_getenv(&data[0])\n\tif raw == nil {\n\t\treturn \"\", false\n\t}\n\n\tptr := uintptr(unsafe.Pointer(raw))\n\tfor size := uintptr(0); ; size++ {\n\t\tv := *(*byte)(unsafe.Pointer(ptr))\n\t\tif v == 0 {\n\t\t\tsrc := *(*[]byte)(unsafe.Pointer(&sliceHeader{buf: raw, len: size, cap: size}))\n\t\t\treturn string(src), true\n\t\t}\n\t\tptr += unsafe.Sizeof(byte(0))\n\t}\n}\n\nfunc Setenv(key, val string) (err error) {\n\tif len(key) == 0 {\n\t\treturn EINVAL\n\t}\n\tfor i := 0; i < len(key); i++ {\n\t\tif key[i] == '=' || key[i] == 0 {\n\t\t\treturn EINVAL\n\t\t}\n\t}\n\tfor i := 0; i < len(val); i++ {\n\t\tif val[i] == 0 {\n\t\t\treturn EINVAL\n\t\t}\n\t}\n\truntimeSetenv(key, val)\n\treturn\n}\n\nfunc Unsetenv(key string) (err error) {\n\truntimeUnsetenv(key)\n\treturn\n}\n\nfunc Clearenv() {\n\tfor _, s := range Environ() {\n\t\tfor j := 0; j < len(s); j++ {\n\t\t\tif s[j] == '=' {\n\t\t\t\tUnsetenv(s[0:j])\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n}\n\n//go:extern environ\nvar libc_environ *unsafe.Pointer\n"
  },
  {
    "path": "src/syscall/env_nonhosted.go",
    "content": "//go:build baremetal || js || wasm_unknown\n\npackage syscall\n\nfunc Environ() []string {\n\tenv := runtime_envs()\n\tenvCopy := make([]string, len(env))\n\tcopy(envCopy, env)\n\treturn envCopy\n}\n\nfunc Getenv(key string) (value string, found bool) {\n\tenv := runtime_envs()\n\tfor _, keyval := range env {\n\t\t// Split at '=' character.\n\t\tvar k, v string\n\t\tfor i := 0; i < len(keyval); i++ {\n\t\t\tif keyval[i] == '=' {\n\t\t\t\tk = keyval[:i]\n\t\t\t\tv = keyval[i+1:]\n\t\t\t}\n\t\t}\n\t\tif k == key {\n\t\t\treturn v, true\n\t\t}\n\t}\n\treturn \"\", false\n}\n\nfunc Setenv(key, val string) (err error) {\n\t// stub for now\n\treturn ENOSYS\n}\n\nfunc Unsetenv(key string) (err error) {\n\t// stub for now\n\treturn ENOSYS\n}\n\nfunc Clearenv() (err error) {\n\t// stub for now\n\treturn ENOSYS\n}\n\nfunc runtime_envs() []string\n"
  },
  {
    "path": "src/syscall/env_wasip2.go",
    "content": "//go:build wasip2\n\npackage syscall\n\nimport (\n\t\"internal/wasi/cli/v0.2.0/environment\"\n)\n\nvar libc_envs map[string]string\n\nfunc populateEnvironment() {\n\tlibc_envs = make(map[string]string)\n\tfor _, kv := range environment.GetEnvironment().Slice() {\n\t\tlibc_envs[kv[0]] = kv[1]\n\t}\n}\n\nfunc Environ() []string {\n\tvar env []string\n\tfor k, v := range libc_envs {\n\t\tenv = append(env, k+\"=\"+v)\n\t}\n\treturn env\n}\n\nfunc Getenv(key string) (value string, found bool) {\n\tvalue, found = libc_envs[key]\n\treturn\n}\n\nfunc Setenv(key, val string) (err error) {\n\tif len(key) == 0 {\n\t\treturn EINVAL\n\t}\n\tfor i := 0; i < len(key); i++ {\n\t\tif key[i] == '=' || key[i] == 0 {\n\t\t\treturn EINVAL\n\t\t}\n\t}\n\tfor i := 0; i < len(val); i++ {\n\t\tif val[i] == 0 {\n\t\t\treturn EINVAL\n\t\t}\n\t}\n\tlibc_envs[key] = val\n\treturn nil\n}\n\nfunc Unsetenv(key string) (err error) {\n\tdelete(libc_envs, key)\n\treturn nil\n}\n\nfunc Clearenv() {\n\tclear(libc_envs)\n}\n"
  },
  {
    "path": "src/syscall/errno.go",
    "content": "package syscall\n\nimport \"internal/itoa\"\n\n// Most code here has been copied from the Go sources:\n//   https://github.com/golang/go/blob/go1.12/src/syscall/syscall_js.go\n// It has the following copyright note:\n//\n//     Copyright 2018 The Go Authors. All rights reserved.\n//     Use of this source code is governed by a BSD-style\n//     license that can be found in the LICENSE file.\n\n// An Errno is an unsigned number describing an error condition.\n// It implements the error interface. The zero Errno is by convention\n// a non-error, so code to convert from Errno to error should use:\n//\n//\terr = nil\n//\tif errno != 0 {\n//\t        err = errno\n//\t}\ntype Errno uintptr\n\nfunc (e Errno) Error() string {\n\treturn \"errno \" + itoa.Itoa(int(e))\n}\n\nfunc (e Errno) Temporary() bool {\n\treturn e == EINTR || e == EMFILE || e.Timeout()\n}\n\nfunc (e Errno) Timeout() bool {\n\treturn e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT\n}\n"
  },
  {
    "path": "src/syscall/errno_other.go",
    "content": "//go:build !js && !wasip1 && !wasip2\n\npackage syscall\n\nfunc (e Errno) Is(target error) bool { return false }\n"
  },
  {
    "path": "src/syscall/errno_wasilibc.go",
    "content": "//go:build wasip1 || js\n\npackage syscall\n\n// Use a go:extern definition to access the errno from wasi-libc\n//\n//go:extern errno\nvar libcErrno Errno\n"
  },
  {
    "path": "src/syscall/errno_wasip2.go",
    "content": "//go:build wasip2\n\npackage syscall\n\n// The errno for libc_wasip2.go\n\nvar libcErrno Errno\n"
  },
  {
    "path": "src/syscall/file_emulated.go",
    "content": "//go:build baremetal || (wasm && !wasip1 && !wasip2) || wasm_unknown\n\n// This file emulates some file-related functions that are only available\n// under a real operating system.\n\npackage syscall\n\nfunc Getwd() (string, error) {\n\treturn \"\", nil\n}\n"
  },
  {
    "path": "src/syscall/file_hosted.go",
    "content": "//go:build !(baremetal || (wasm && !wasip1 && !wasip2) || wasm_unknown)\n\n// This file assumes there is a libc available that runs on a real operating\n// system.\n\npackage syscall\n\nconst pathMax = 1024\n\nfunc Getwd() (string, error) {\n\tvar buf [pathMax]byte\n\ts := libc_getcwd(&buf[0], uint(len(buf)))\n\tif s == nil {\n\t\treturn \"\", getErrno()\n\t}\n\tn := clen(buf[:])\n\tif n < 1 {\n\t\treturn \"\", EINVAL\n\t}\n\treturn string(buf[:n]), nil\n}\n\n// char *getcwd(char *buf, size_t size)\n//\n//export getcwd\nfunc libc_getcwd(buf *byte, size uint) *byte\n"
  },
  {
    "path": "src/syscall/libc_wasip2.go",
    "content": "//go:build wasip2\n\n// mini libc wrapping wasi preview2 calls in a libc api\n\npackage syscall\n\nimport (\n\t\"unsafe\"\n\n\t\"internal/cm\"\n\n\t\"internal/wasi/cli/v0.2.0/environment\"\n\t\"internal/wasi/cli/v0.2.0/stderr\"\n\t\"internal/wasi/cli/v0.2.0/stdin\"\n\t\"internal/wasi/cli/v0.2.0/stdout\"\n\twallclock \"internal/wasi/clocks/v0.2.0/wall-clock\"\n\t\"internal/wasi/filesystem/v0.2.0/preopens\"\n\t\"internal/wasi/filesystem/v0.2.0/types\"\n\tioerror \"internal/wasi/io/v0.2.0/error\"\n\t\"internal/wasi/io/v0.2.0/streams\"\n\t\"internal/wasi/random/v0.2.0/random\"\n)\n\nfunc goString(cstr *byte) string {\n\treturn unsafe.String(cstr, strlen(cstr))\n}\n\n//export strlen\nfunc strlen(cstr *byte) uintptr {\n\tif cstr == nil {\n\t\treturn 0\n\t}\n\tptr := unsafe.Pointer(cstr)\n\tvar i uintptr\n\tfor p := (*byte)(ptr); *p != 0; p = (*byte)(unsafe.Add(unsafe.Pointer(p), 1)) {\n\t\ti++\n\t}\n\treturn i\n}\n\n// ssize_t write(int fd, const void *buf, size_t count)\n//\n//export write\nfunc write(fd int32, buf *byte, count uint) int {\n\tif stream, ok := wasiStreams[fd]; ok {\n\t\treturn writeStream(stream, buf, count, 0)\n\t}\n\n\tstream, ok := wasiFiles[fd]\n\tif !ok {\n\t\tlibcErrno = EBADF\n\t\treturn -1\n\t}\n\tif stream.d == cm.ResourceNone {\n\t\tlibcErrno = EBADF\n\t\treturn -1\n\t}\n\n\tn := pwrite(fd, buf, count, int64(stream.offset))\n\tif n == -1 {\n\t\treturn -1\n\t}\n\tstream.offset += int64(n)\n\treturn int(n)\n}\n\n// ssize_t read(int fd, void *buf, size_t count);\n//\n//export read\nfunc read(fd int32, buf *byte, count uint) int {\n\tif stream, ok := wasiStreams[fd]; ok {\n\t\treturn readStream(stream, buf, count, 0)\n\t}\n\n\tstream, ok := wasiFiles[fd]\n\tif !ok {\n\t\tlibcErrno = EBADF\n\t\treturn -1\n\t}\n\tif stream.d == cm.ResourceNone {\n\t\tlibcErrno = EBADF\n\t\treturn -1\n\t}\n\n\tn := pread(fd, buf, count, int64(stream.offset))\n\tif n == -1 {\n\t\t// error during pread\n\t\treturn -1\n\t}\n\tstream.offset += int64(n)\n\treturn int(n)\n}\n\n// At the moment, each time we have a file read or write we create a new stream.  Future implementations\n// could change the current in or out file stream lazily.  We could do this by tracking input and output\n// offsets individually, and if they don't match the current main offset, reopen the file stream at that location.\n\ntype wasiFile struct {\n\td      types.Descriptor\n\toflag  int32 // original open flags: O_RDONLY, O_WRONLY, O_RDWR\n\toffset int64 // current fd offset; updated with each read/write\n\trefs   int\n}\n\n// Need to figure out which system calls we're using:\n//   stdin/stdout/stderr want streams, so we use stream read/write\n//   but for regular files we can use the descriptor and explicitly write a buffer to the offset?\n//   The mismatch comes from trying to combine these.\n\nvar wasiFiles map[int32]*wasiFile = make(map[int32]*wasiFile)\n\nfunc findFreeFD() int32 {\n\tvar newfd int32\n\tfor wasiStreams[newfd] != nil || wasiFiles[newfd] != nil {\n\t\tnewfd++\n\t}\n\treturn newfd\n}\n\nvar wasiErrno ioerror.Error\n\ntype wasiStream struct {\n\tin   *streams.InputStream\n\tout  *streams.OutputStream\n\trefs int\n}\n\n// This holds entries for stdin/stdout/stderr.\n\nvar wasiStreams map[int32]*wasiStream\n\nfunc init() {\n\tsin := stdin.GetStdin()\n\tsout := stdout.GetStdout()\n\tserr := stderr.GetStderr()\n\twasiStreams = map[int32]*wasiStream{\n\t\t0: &wasiStream{\n\t\t\tin:   &sin,\n\t\t\trefs: 1,\n\t\t},\n\t\t1: &wasiStream{\n\t\t\tout:  &sout,\n\t\t\trefs: 1,\n\t\t},\n\t\t2: &wasiStream{\n\t\t\tout:  &serr,\n\t\t\trefs: 1,\n\t\t},\n\t}\n}\n\nfunc readStream(stream *wasiStream, buf *byte, count uint, offset int64) int {\n\tif stream.in == nil {\n\t\t// not a stream we can read from\n\t\tlibcErrno = EBADF\n\t\treturn -1\n\t}\n\n\tif offset != 0 {\n\t\tlibcErrno = EINVAL\n\t\treturn -1\n\t}\n\n\tlibcErrno = 0\n\tlist, err, isErr := stream.in.BlockingRead(uint64(count)).Result()\n\tif isErr {\n\t\tif err.Closed() {\n\t\t\tlibcErrno = 0\n\t\t\treturn 0\n\t\t} else if err := err.LastOperationFailed(); err != nil {\n\t\t\twasiErrno = *err\n\t\t\tlibcErrno = EWASIERROR\n\t\t}\n\t\treturn -1\n\t}\n\n\tcopy(unsafe.Slice(buf, count), list.Slice())\n\treturn int(list.Len())\n}\n\nfunc writeStream(stream *wasiStream, buf *byte, count uint, offset int64) int {\n\tif stream.out == nil {\n\t\t// not a stream we can write to\n\t\tlibcErrno = EBADF\n\t\treturn -1\n\t}\n\n\tif offset != 0 {\n\t\tlibcErrno = EINVAL\n\t\treturn -1\n\t}\n\n\tsrc := unsafe.Slice(buf, count)\n\tvar remaining = count\n\n\t// The blocking-write-and-flush call allows a maximum of 4096 bytes at a time.\n\t// We loop here by instead of doing subscribe/check-write/poll-one/write by hand.\n\tfor remaining > 0 {\n\t\tlen := uint(4096)\n\t\tif len > remaining {\n\t\t\tlen = remaining\n\t\t}\n\t\t_, err, isErr := stream.out.BlockingWriteAndFlush(cm.ToList(src[:len])).Result()\n\t\tif isErr {\n\t\t\tif err.Closed() {\n\t\t\t\tlibcErrno = 0\n\t\t\t\treturn 0\n\t\t\t} else if err := err.LastOperationFailed(); err != nil {\n\t\t\t\twasiErrno = *err\n\t\t\t\tlibcErrno = EWASIERROR\n\t\t\t}\n\t\t\treturn -1\n\t\t}\n\t\tremaining -= len\n\t\tsrc = src[len:]\n\t}\n\n\treturn int(count)\n}\n\n//go:linkname memcpy runtime.memcpy\nfunc memcpy(dst, src unsafe.Pointer, size uintptr)\n\n// ssize_t pread(int fd, void *buf, size_t count, off_t offset);\n//\n//export pread\nfunc pread(fd int32, buf *byte, count uint, offset int64) int {\n\t// TODO(dgryski): Need to be consistent about all these checks; EBADF/EINVAL/... ?\n\n\tif stream, ok := wasiStreams[fd]; ok {\n\t\treturn readStream(stream, buf, count, offset)\n\n\t}\n\n\tstreams, ok := wasiFiles[fd]\n\tif !ok {\n\t\t// TODO(dgryski): EINVAL?\n\t\tlibcErrno = EBADF\n\t\treturn -1\n\t}\n\tif streams.d == cm.ResourceNone {\n\t\tlibcErrno = EBADF\n\t\treturn -1\n\t}\n\tif streams.oflag&O_RDONLY == 0 {\n\t\tlibcErrno = EBADF\n\t\treturn -1\n\t}\n\n\tlistEOF, err, isErr := streams.d.Read(types.FileSize(count), types.FileSize(offset)).Result()\n\tif isErr {\n\t\tlibcErrno = errorCodeToErrno(err)\n\t\treturn -1\n\t}\n\n\tlist := listEOF.F0\n\tcopy(unsafe.Slice(buf, count), list.Slice())\n\n\t// TODO(dgryski): EOF bool is ignored?\n\treturn int(list.Len())\n}\n\n// ssize_t pwrite(int fd, void *buf, size_t count, off_t offset);\n//\n//export pwrite\nfunc pwrite(fd int32, buf *byte, count uint, offset int64) int {\n\t// TODO(dgryski): Need to be consistent about all these checks; EBADF/EINVAL/... ?\n\tif stream, ok := wasiStreams[fd]; ok {\n\t\treturn writeStream(stream, buf, count, 0)\n\t}\n\n\tstreams, ok := wasiFiles[fd]\n\tif !ok {\n\t\t// TODO(dgryski): EINVAL?\n\t\tlibcErrno = EBADF\n\t\treturn -1\n\t}\n\tif streams.d == cm.ResourceNone {\n\t\tlibcErrno = EBADF\n\t\treturn -1\n\t}\n\tif streams.oflag&O_WRONLY == 0 {\n\t\tlibcErrno = EBADF\n\t\treturn -1\n\t}\n\n\tn, err, isErr := streams.d.Write(cm.NewList(buf, count), types.FileSize(offset)).Result()\n\tif isErr {\n\t\t// TODO(dgryski):\n\t\tlibcErrno = errorCodeToErrno(err)\n\t\treturn -1\n\t}\n\n\treturn int(n)\n}\n\n// ssize_t lseek(int fd, off_t offset, int whence);\n//\n//export lseek\nfunc lseek(fd int32, offset int64, whence int) int64 {\n\tif _, ok := wasiStreams[fd]; ok {\n\t\t// can't lseek a stream\n\t\tlibcErrno = EBADF\n\t\treturn -1\n\t}\n\n\tstream, ok := wasiFiles[fd]\n\tif !ok {\n\t\tlibcErrno = EBADF\n\t\treturn -1\n\t}\n\tif stream.d == cm.ResourceNone {\n\t\tlibcErrno = EBADF\n\t\treturn -1\n\t}\n\n\tswitch whence {\n\tcase 0: // SEEK_SET\n\t\tstream.offset = offset\n\tcase 1: // SEEK_CUR\n\t\tstream.offset += offset\n\tcase 2: // SEEK_END\n\t\tstat, err, isErr := stream.d.Stat().Result()\n\t\tif isErr {\n\t\t\tlibcErrno = errorCodeToErrno(err)\n\t\t\treturn -1\n\t\t}\n\t\tstream.offset = int64(stat.Size) + offset\n\t}\n\n\treturn int64(stream.offset)\n}\n\n// int close(int fd)\n//\n//export close\nfunc close(fd int32) int32 {\n\tif streams, ok := wasiStreams[fd]; ok {\n\t\tif streams.out != nil {\n\t\t\t// ignore any error\n\t\t\tstreams.out.BlockingFlush()\n\t\t}\n\n\t\tif streams.refs--; streams.refs == 0 {\n\t\t\tif streams.out != nil {\n\t\t\t\tstreams.out.ResourceDrop()\n\t\t\t\tstreams.out = nil\n\t\t\t}\n\t\t\tif streams.in != nil {\n\t\t\t\tstreams.in.ResourceDrop()\n\t\t\t\tstreams.in = nil\n\t\t\t}\n\t\t}\n\n\t\tdelete(wasiStreams, fd)\n\t\treturn 0\n\t}\n\n\tstreams, ok := wasiFiles[fd]\n\tif !ok {\n\t\tlibcErrno = EBADF\n\t\treturn -1\n\t}\n\tif streams.refs--; streams.refs == 0 && streams.d != cm.ResourceNone {\n\t\tstreams.d.ResourceDrop()\n\t\tstreams.d = 0\n\t}\n\tdelete(wasiFiles, fd)\n\n\treturn 0\n}\n\n// int dup(int fd)\n//\n//export dup\nfunc dup(fd int32) int32 {\n\t// is fd a stream?\n\tif stream, ok := wasiStreams[fd]; ok {\n\t\tnewfd := findFreeFD()\n\t\tstream.refs++\n\t\twasiStreams[newfd] = stream\n\t\treturn newfd\n\t}\n\n\t// is fd a file?\n\tif file, ok := wasiFiles[fd]; ok {\n\t\t// scan for first free file descriptor\n\t\tnewfd := findFreeFD()\n\t\tfile.refs++\n\t\twasiFiles[newfd] = file\n\t\treturn newfd\n\t}\n\n\t// unknown file descriptor\n\tlibcErrno = EBADF\n\treturn -1\n}\n\n// void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);\n//\n//export mmap\nfunc mmap(addr unsafe.Pointer, length uintptr, prot, flags, fd int32, offset uintptr) unsafe.Pointer {\n\tlibcErrno = ENOSYS\n\treturn unsafe.Pointer(^uintptr(0))\n}\n\n// int munmap(void *addr, size_t length);\n//\n//export munmap\nfunc munmap(addr unsafe.Pointer, length uintptr) int32 {\n\tlibcErrno = ENOSYS\n\treturn -1\n}\n\n// int mprotect(void *addr, size_t len, int prot);\n//\n//export mprotect\nfunc mprotect(addr unsafe.Pointer, len uintptr, prot int32) int32 {\n\tlibcErrno = ENOSYS\n\treturn -1\n}\n\n// int chmod(const char *pathname, mode_t mode);\n//\n//export chmod\nfunc chmod(pathname *byte, mode uint32) int32 {\n\treturn 0\n}\n\n// int mkdir(const char *pathname, mode_t mode);\n//\n//export mkdir\nfunc mkdir(pathname *byte, mode uint32) int32 {\n\tpath := goString(pathname)\n\tdir, relPath := findPreopenForPath(path)\n\tif dir.d == cm.ResourceNone {\n\t\tlibcErrno = EACCES\n\t\treturn -1\n\t}\n\n\t_, err, isErr := dir.d.CreateDirectoryAt(relPath).Result()\n\tif isErr {\n\t\tlibcErrno = errorCodeToErrno(err)\n\t\treturn -1\n\t}\n\n\treturn 0\n}\n\n// int rmdir(const char *pathname);\n//\n//export rmdir\nfunc rmdir(pathname *byte) int32 {\n\tpath := goString(pathname)\n\tdir, relPath := findPreopenForPath(path)\n\tif dir.d == cm.ResourceNone {\n\t\tlibcErrno = EACCES\n\t\treturn -1\n\t}\n\n\t_, err, isErr := dir.d.RemoveDirectoryAt(relPath).Result()\n\tif isErr {\n\t\tlibcErrno = errorCodeToErrno(err)\n\t\treturn -1\n\t}\n\n\treturn 0\n}\n\n// int rename(const char *from, *to);\n//\n//export rename\nfunc rename(from, to *byte) int32 {\n\tfromPath := goString(from)\n\tfromDir, fromRelPath := findPreopenForPath(fromPath)\n\tif fromDir.d == cm.ResourceNone {\n\t\tlibcErrno = EACCES\n\t\treturn -1\n\t}\n\n\ttoPath := goString(to)\n\ttoDir, toRelPath := findPreopenForPath(toPath)\n\tif toDir.d == cm.ResourceNone {\n\t\tlibcErrno = EACCES\n\t\treturn -1\n\t}\n\n\t_, err, isErr := fromDir.d.RenameAt(fromRelPath, toDir.d, toRelPath).Result()\n\tif isErr {\n\t\tlibcErrno = errorCodeToErrno(err)\n\t\treturn -1\n\t}\n\n\treturn 0\n}\n\n// int symlink(const char *from, *to);\n//\n//export symlink\nfunc symlink(from, to *byte) int32 {\n\tfromPath := goString(from)\n\tfromDir, fromRelPath := findPreopenForPath(fromPath)\n\tif fromDir.d == cm.ResourceNone {\n\t\tlibcErrno = EACCES\n\t\treturn -1\n\t}\n\n\ttoPath := goString(to)\n\ttoDir, toRelPath := findPreopenForPath(toPath)\n\tif toDir.d == cm.ResourceNone {\n\t\tlibcErrno = EACCES\n\t\treturn -1\n\t}\n\n\tif fromDir.d != toDir.d {\n\t\tlibcErrno = EACCES\n\t\treturn -1\n\t}\n\n\t// TODO(dgryski): check fromDir == toDir?\n\n\t_, err, isErr := fromDir.d.SymlinkAt(fromRelPath, toRelPath).Result()\n\tif isErr {\n\t\tlibcErrno = errorCodeToErrno(err)\n\t\treturn -1\n\t}\n\n\treturn 0\n}\n\n// int link(const char *from, *to);\n//\n//export link\nfunc link(from, to *byte) int32 {\n\tfromPath := goString(from)\n\tfromDir, fromRelPath := findPreopenForPath(fromPath)\n\tif fromDir.d == cm.ResourceNone {\n\t\tlibcErrno = EACCES\n\t\treturn -1\n\t}\n\n\ttoPath := goString(to)\n\ttoDir, toRelPath := findPreopenForPath(toPath)\n\tif toDir.d == cm.ResourceNone {\n\t\tlibcErrno = EACCES\n\t\treturn -1\n\t}\n\n\tif fromDir.d != toDir.d {\n\t\tlibcErrno = EACCES\n\t\treturn -1\n\t}\n\n\t// TODO(dgryski): check fromDir == toDir?\n\n\t_, err, isErr := fromDir.d.LinkAt(0, fromRelPath, toDir.d, toRelPath).Result()\n\tif isErr {\n\t\tlibcErrno = errorCodeToErrno(err)\n\t\treturn -1\n\t}\n\n\treturn 0\n}\n\n// int fsync(int fd);\n//\n//export fsync\nfunc fsync(fd int32) int32 {\n\tif _, ok := wasiStreams[fd]; ok {\n\t\t// can't sync a stream\n\t\tlibcErrno = EBADF\n\t\treturn -1\n\t}\n\n\tstreams, ok := wasiFiles[fd]\n\tif !ok {\n\t\tlibcErrno = EBADF\n\t\treturn -1\n\t}\n\tif streams.d == cm.ResourceNone {\n\t\tlibcErrno = EBADF\n\t\treturn -1\n\t}\n\tif streams.oflag&O_WRONLY == 0 {\n\t\tlibcErrno = EBADF\n\t\treturn -1\n\t}\n\n\t_, err, isErr := streams.d.SyncData().Result()\n\tif isErr {\n\t\tlibcErrno = errorCodeToErrno(err)\n\t\treturn -1\n\t}\n\n\treturn 0\n}\n\n// ssize_t readlink(const char *path, void *buf, size_t count);\n//\n//export readlink\nfunc readlink(pathname *byte, buf *byte, count uint) int {\n\tpath := goString(pathname)\n\tdir, relPath := findPreopenForPath(path)\n\tif dir.d == cm.ResourceNone {\n\t\tlibcErrno = EACCES\n\t\treturn -1\n\t}\n\n\ts, err, isErr := dir.d.ReadLinkAt(relPath).Result()\n\tif isErr {\n\t\tlibcErrno = errorCodeToErrno(err)\n\t\treturn -1\n\t}\n\n\tsize := uintptr(count)\n\tif size > uintptr(len(s)) {\n\t\tsize = uintptr(len(s))\n\t}\n\n\tmemcpy(unsafe.Pointer(buf), unsafe.Pointer(unsafe.StringData(s)), size)\n\treturn int(size)\n}\n\n// int unlink(const char *pathname);\n//\n//export unlink\nfunc unlink(pathname *byte) int32 {\n\tpath := goString(pathname)\n\tdir, relPath := findPreopenForPath(path)\n\tif dir.d == cm.ResourceNone {\n\t\tlibcErrno = EACCES\n\t\treturn -1\n\t}\n\n\t_, err, isErr := dir.d.UnlinkFileAt(relPath).Result()\n\tif isErr {\n\t\tlibcErrno = errorCodeToErrno(err)\n\t\treturn -1\n\t}\n\n\treturn 0\n}\n\n// int getpagesize(void);\n//\n//export getpagesize\nfunc getpagesize() int {\n\treturn 65536\n}\n\n// int stat(const char *path, struct stat * buf);\n//\n//export stat\nfunc stat(pathname *byte, dst *Stat_t) int32 {\n\tpath := goString(pathname)\n\tdir, relPath := findPreopenForPath(path)\n\tif dir.d == cm.ResourceNone {\n\t\tlibcErrno = EACCES\n\t\treturn -1\n\t}\n\n\tstat, err, isErr := dir.d.StatAt(0, relPath).Result()\n\tif isErr {\n\t\tlibcErrno = errorCodeToErrno(err)\n\t\treturn -1\n\t}\n\n\tsetStatFromWASIStat(dst, &stat)\n\n\treturn 0\n}\n\n// int fstat(int fd, struct stat * buf);\n//\n//export fstat\nfunc fstat(fd int32, dst *Stat_t) int32 {\n\tif _, ok := wasiStreams[fd]; ok {\n\t\t// TODO(dgryski): fill in stat buffer for stdin etc\n\t\treturn -1\n\t}\n\n\tstream, ok := wasiFiles[fd]\n\tif !ok {\n\t\tlibcErrno = EBADF\n\t\treturn -1\n\t}\n\tif stream.d == cm.ResourceNone {\n\t\tlibcErrno = EBADF\n\t\treturn -1\n\t}\n\tstat, err, isErr := stream.d.Stat().Result()\n\tif isErr {\n\t\tlibcErrno = errorCodeToErrno(err)\n\t\treturn -1\n\t}\n\n\tsetStatFromWASIStat(dst, &stat)\n\n\treturn 0\n}\n\nfunc setStatFromWASIStat(sstat *Stat_t, wstat *types.DescriptorStat) {\n\t// This will cause problems for people who want to compare inodes\n\tsstat.Dev = 0\n\tsstat.Ino = 0\n\tsstat.Rdev = 0\n\n\tsstat.Nlink = uint64(wstat.LinkCount)\n\n\tsstat.Mode = p2fileTypeToStatType(wstat.Type)\n\n\t// No uid/gid\n\tsstat.Uid = 0\n\tsstat.Gid = 0\n\tsstat.Size = int64(wstat.Size)\n\n\t// made up numbers\n\tsstat.Blksize = 512\n\tsstat.Blocks = (sstat.Size + 511) / int64(sstat.Blksize)\n\n\tsetOptTime := func(t *Timespec, o *wallclock.DateTime) {\n\t\tt.Sec = 0\n\t\tt.Nsec = 0\n\t\tif o != nil {\n\t\t\tt.Sec = int32(o.Seconds)\n\t\t\tt.Nsec = int64(o.Nanoseconds)\n\t\t}\n\t}\n\n\tsetOptTime(&sstat.Atim, wstat.DataAccessTimestamp.Some())\n\tsetOptTime(&sstat.Mtim, wstat.DataModificationTimestamp.Some())\n\tsetOptTime(&sstat.Ctim, wstat.StatusChangeTimestamp.Some())\n}\n\n// int lstat(const char *path, struct stat * buf);\n//\n//export lstat\nfunc lstat(pathname *byte, dst *Stat_t) int32 {\n\tpath := goString(pathname)\n\tdir, relPath := findPreopenForPath(path)\n\tif dir.d == cm.ResourceNone {\n\t\tlibcErrno = EACCES\n\t\treturn -1\n\t}\n\n\tstat, err, isErr := dir.d.StatAt(0, relPath).Result()\n\tif isErr {\n\t\tlibcErrno = errorCodeToErrno(err)\n\t\treturn -1\n\t}\n\n\tsetStatFromWASIStat(dst, &stat)\n\n\treturn 0\n}\n\nfunc init() {\n\tpopulateEnvironment()\n\tpopulatePreopens()\n}\n\ntype wasiDir struct {\n\td    types.Descriptor // wasip2 descriptor\n\troot string           // root path for this descriptor\n\trel  string           // relative path under root\n}\n\nvar libcCWD wasiDir\n\nvar wasiPreopens map[string]types.Descriptor\n\nfunc populatePreopens() {\n\tvar cwd string\n\n\t// find CWD\n\tresult := environment.InitialCWD()\n\tif s := result.Some(); s != nil {\n\t\tcwd = *s\n\t} else if s, _ := Getenv(\"PWD\"); s != \"\" {\n\t\tcwd = s\n\t}\n\n\tdirs := preopens.GetDirectories().Slice()\n\tpreopens := make(map[string]types.Descriptor, len(dirs))\n\tfor _, tup := range dirs {\n\t\tdesc, path := tup.F0, tup.F1\n\t\tif path == cwd {\n\t\t\tlibcCWD.d = desc\n\t\t\tlibcCWD.root = path\n\t\t\tlibcCWD.rel = \"\"\n\t\t}\n\t\tpreopens[path] = desc\n\t}\n\twasiPreopens = preopens\n}\n\n// -- BEGIN fs_wasip1.go --\n// The following section has been taken from upstream Go with the following copyright:\n// Copyright 2023 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:nosplit\nfunc appendCleanPath(buf []byte, path string, lookupParent bool) ([]byte, bool) {\n\ti := 0\n\tfor i < len(path) {\n\t\tfor i < len(path) && path[i] == '/' {\n\t\t\ti++\n\t\t}\n\n\t\tj := i\n\t\tfor j < len(path) && path[j] != '/' {\n\t\t\tj++\n\t\t}\n\n\t\ts := path[i:j]\n\t\ti = j\n\n\t\tswitch s {\n\t\tcase \"\":\n\t\t\tcontinue\n\t\tcase \".\":\n\t\t\tcontinue\n\t\tcase \"..\":\n\t\t\tif !lookupParent {\n\t\t\t\tk := len(buf)\n\t\t\t\tfor k > 0 && buf[k-1] != '/' {\n\t\t\t\t\tk--\n\t\t\t\t}\n\t\t\t\tfor k > 1 && buf[k-1] == '/' {\n\t\t\t\t\tk--\n\t\t\t\t}\n\t\t\t\tbuf = buf[:k]\n\t\t\t\tif k == 0 {\n\t\t\t\t\tlookupParent = true\n\t\t\t\t} else {\n\t\t\t\t\ts = \"\"\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\tdefault:\n\t\t\tlookupParent = false\n\t\t}\n\n\t\tif len(buf) > 0 && buf[len(buf)-1] != '/' {\n\t\t\tbuf = append(buf, '/')\n\t\t}\n\t\tbuf = append(buf, s...)\n\t}\n\treturn buf, lookupParent\n}\n\n// joinPath concatenates dir and file paths, producing a cleaned path where\n// \".\" and \"..\" have been removed, unless dir is relative and the references\n// to parent directories in file represented a location relative to a parent\n// of dir.\n//\n// This function is used for path resolution of all wasi functions expecting\n// a path argument; the returned string is heap allocated, which we may want\n// to optimize in the future. Instead of returning a string, the function\n// could append the result to an output buffer that the functions in this\n// file can manage to have allocated on the stack (e.g. initializing to a\n// fixed capacity). Since it will significantly increase code complexity,\n// we prefer to optimize for readability and maintainability at this time.\nfunc joinPath(dir, file string) string {\n\tbuf := make([]byte, 0, len(dir)+len(file)+1)\n\tif isAbs(dir) {\n\t\tbuf = append(buf, '/')\n\t}\n\n\tbuf, lookupParent := appendCleanPath(buf, dir, true)\n\tbuf, _ = appendCleanPath(buf, file, lookupParent)\n\t// The appendCleanPath function cleans the path so it does not inject\n\t// references to the current directory. If both the dir and file args\n\t// were \".\", this results in the output buffer being empty so we handle\n\t// this condition here.\n\tif len(buf) == 0 {\n\t\tbuf = append(buf, '.')\n\t}\n\t// If the file ended with a '/' we make sure that the output also ends\n\t// with a '/'. This is needed to ensure that programs have a mechanism\n\t// to represent dereferencing symbolic links pointing to directories.\n\tif buf[len(buf)-1] != '/' && isDir(file) {\n\t\tbuf = append(buf, '/')\n\t}\n\treturn unsafe.String(&buf[0], len(buf))\n}\n\nfunc isAbs(path string) bool {\n\treturn hasPrefix(path, \"/\")\n}\n\nfunc isDir(path string) bool {\n\treturn hasSuffix(path, \"/\")\n}\n\nfunc hasPrefix(s, p string) bool {\n\treturn len(s) >= len(p) && s[:len(p)] == p\n}\n\nfunc hasSuffix(s, x string) bool {\n\treturn len(s) >= len(x) && s[len(s)-len(x):] == x\n}\n\n// findPreopenForPath finds which preopen it relates to and return that descriptor/root and the path relative to that directory descriptor/root\nfunc findPreopenForPath(path string) (wasiDir, string) {\n\tdir := \"/\"\n\tvar wasidir wasiDir\n\n\tif !isAbs(path) {\n\t\tdir = libcCWD.root\n\t\twasidir = libcCWD\n\t\tif libcCWD.rel != \"\" && libcCWD.rel != \".\" && libcCWD.rel != \"./\" {\n\t\t\tpath = libcCWD.rel + \"/\" + path\n\t\t}\n\t}\n\tpath = joinPath(dir, path)\n\n\tvar best string\n\tfor k, v := range wasiPreopens {\n\t\tif len(k) > len(best) && hasPrefix(path, k) {\n\t\t\twasidir = wasiDir{d: v, root: k}\n\t\t\tbest = wasidir.root\n\t\t}\n\t}\n\n\tif hasPrefix(path, wasidir.root) {\n\t\tpath = path[len(wasidir.root):]\n\t}\n\tfor isAbs(path) {\n\t\tpath = path[1:]\n\t}\n\tif len(path) == 0 {\n\t\tpath = \".\"\n\t}\n\n\treturn wasidir, path\n}\n\n// -- END fs_wasip1.go --\n\n// int open(const char *pathname, int flags, mode_t mode);\n//\n//export open\nfunc open(pathname *byte, flags int32, mode uint32) int32 {\n\tpath := goString(pathname)\n\tdir, relPath := findPreopenForPath(path)\n\tif dir.d == cm.ResourceNone {\n\t\tlibcErrno = EACCES\n\t\treturn -1\n\t}\n\n\tvar dflags types.DescriptorFlags\n\tif (flags & O_RDONLY) == O_RDONLY {\n\t\tdflags |= types.DescriptorFlagsRead\n\t}\n\tif (flags & O_WRONLY) == O_WRONLY {\n\t\tdflags |= types.DescriptorFlagsWrite\n\t}\n\n\tvar oflags types.OpenFlags\n\tif flags&O_CREAT == O_CREAT {\n\t\toflags |= types.OpenFlagsCreate\n\t}\n\tif flags&O_DIRECTORY == O_DIRECTORY {\n\t\toflags |= types.OpenFlagsDirectory\n\t}\n\tif flags&O_EXCL == O_EXCL {\n\t\toflags |= types.OpenFlagsExclusive\n\t}\n\tif flags&O_TRUNC == O_TRUNC {\n\t\toflags |= types.OpenFlagsTruncate\n\t}\n\n\t// By default, follow symlinks for open() unless O_NOFOLLOW was passed\n\tvar pflags types.PathFlags = types.PathFlagsSymlinkFollow\n\tif flags&O_NOFOLLOW == O_NOFOLLOW {\n\t\t// O_NOFOLLOW was passed, so turn off SymlinkFollow\n\t\tpflags &^= types.PathFlagsSymlinkFollow\n\t}\n\n\tdescriptor, err, isErr := dir.d.OpenAt(pflags, relPath, oflags, dflags).Result()\n\tif isErr {\n\t\tlibcErrno = errorCodeToErrno(err)\n\t\treturn -1\n\t}\n\n\tstream := wasiFile{\n\t\td:     descriptor,\n\t\toflag: flags,\n\t\trefs:  1,\n\t}\n\n\tif flags&(O_WRONLY|O_APPEND) == (O_WRONLY | O_APPEND) {\n\t\tstat, err, isErr := stream.d.Stat().Result()\n\t\tif isErr {\n\t\t\tlibcErrno = errorCodeToErrno(err)\n\t\t\treturn -1\n\t\t}\n\t\tstream.offset = int64(stat.Size)\n\t}\n\n\tlibcfd := findFreeFD()\n\n\twasiFiles[libcfd] = &stream\n\n\treturn int32(libcfd)\n}\n\nfunc errorCodeToErrno(err types.ErrorCode) Errno {\n\tswitch err {\n\tcase types.ErrorCodeAccess:\n\t\treturn EACCES\n\tcase types.ErrorCodeWouldBlock:\n\t\treturn EAGAIN\n\tcase types.ErrorCodeAlready:\n\t\treturn EALREADY\n\tcase types.ErrorCodeBadDescriptor:\n\t\treturn EBADF\n\tcase types.ErrorCodeBusy:\n\t\treturn EBUSY\n\tcase types.ErrorCodeDeadlock:\n\t\treturn EDEADLK\n\tcase types.ErrorCodeQuota:\n\t\treturn EDQUOT\n\tcase types.ErrorCodeExist:\n\t\treturn EEXIST\n\tcase types.ErrorCodeFileTooLarge:\n\t\treturn EFBIG\n\tcase types.ErrorCodeIllegalByteSequence:\n\t\treturn EILSEQ\n\tcase types.ErrorCodeInProgress:\n\t\treturn EINPROGRESS\n\tcase types.ErrorCodeInterrupted:\n\t\treturn EINTR\n\tcase types.ErrorCodeInvalid:\n\t\treturn EINVAL\n\tcase types.ErrorCodeIO:\n\t\treturn EIO\n\tcase types.ErrorCodeIsDirectory:\n\t\treturn EISDIR\n\tcase types.ErrorCodeLoop:\n\t\treturn ELOOP\n\tcase types.ErrorCodeTooManyLinks:\n\t\treturn EMLINK\n\tcase types.ErrorCodeMessageSize:\n\t\treturn EMSGSIZE\n\tcase types.ErrorCodeNameTooLong:\n\t\treturn ENAMETOOLONG\n\tcase types.ErrorCodeNoDevice:\n\t\treturn ENODEV\n\tcase types.ErrorCodeNoEntry:\n\t\treturn ENOENT\n\tcase types.ErrorCodeNoLock:\n\t\treturn ENOLCK\n\tcase types.ErrorCodeInsufficientMemory:\n\t\treturn ENOMEM\n\tcase types.ErrorCodeInsufficientSpace:\n\t\treturn ENOSPC\n\tcase types.ErrorCodeNotDirectory:\n\t\treturn ENOTDIR\n\tcase types.ErrorCodeNotEmpty:\n\t\treturn ENOTEMPTY\n\tcase types.ErrorCodeNotRecoverable:\n\t\treturn ENOTRECOVERABLE\n\tcase types.ErrorCodeUnsupported:\n\t\treturn ENOSYS\n\tcase types.ErrorCodeNoTTY:\n\t\treturn ENOTTY\n\tcase types.ErrorCodeNoSuchDevice:\n\t\treturn ENXIO\n\tcase types.ErrorCodeOverflow:\n\t\treturn EOVERFLOW\n\tcase types.ErrorCodeNotPermitted:\n\t\treturn EPERM\n\tcase types.ErrorCodePipe:\n\t\treturn EPIPE\n\tcase types.ErrorCodeReadOnly:\n\t\treturn EROFS\n\tcase types.ErrorCodeInvalidSeek:\n\t\treturn ESPIPE\n\tcase types.ErrorCodeTextFileBusy:\n\t\treturn ETXTBSY\n\tcase types.ErrorCodeCrossDevice:\n\t\treturn EXDEV\n\t}\n\treturn Errno(err)\n}\n\ntype libc_DIR struct {\n\td types.DirectoryEntryStream\n}\n\n// DIR *fdopendir(int);\n//\n//export fdopendir\nfunc fdopendir(fd int32) unsafe.Pointer {\n\tif _, ok := wasiStreams[fd]; ok {\n\t\tlibcErrno = EBADF\n\t\treturn nil\n\t}\n\n\tstream, ok := wasiFiles[fd]\n\tif !ok {\n\t\tlibcErrno = EBADF\n\t\treturn nil\n\t}\n\tif stream.d == cm.ResourceNone {\n\t\tlibcErrno = EBADF\n\t\treturn nil\n\t}\n\n\tdir, err, isErr := stream.d.ReadDirectory().Result()\n\tif isErr {\n\t\tlibcErrno = errorCodeToErrno(err)\n\t\treturn nil\n\t}\n\n\treturn unsafe.Pointer(&libc_DIR{d: dir})\n}\n\n// int fdclosedir(DIR *);\n//\n//export fdclosedir\nfunc fdclosedir(dirp unsafe.Pointer) int32 {\n\tif dirp == nil {\n\t\treturn 0\n\n\t}\n\tdir := (*libc_DIR)(dirp)\n\tif dir.d == cm.ResourceNone {\n\t\treturn 0\n\t}\n\n\tdir.d.ResourceDrop()\n\tdir.d = cm.ResourceNone\n\n\treturn 0\n}\n\n// struct dirent *readdir(DIR *);\n//\n//export readdir\nfunc readdir(dirp unsafe.Pointer) *Dirent {\n\tif dirp == nil {\n\t\treturn nil\n\n\t}\n\tdir := (*libc_DIR)(dirp)\n\tif dir.d == cm.ResourceNone {\n\t\treturn nil\n\t}\n\n\tsomeEntry, err, isErr := dir.d.ReadDirectoryEntry().Result()\n\tif isErr {\n\t\tlibcErrno = errorCodeToErrno(err)\n\t\treturn nil\n\t}\n\n\tentry := someEntry.Some()\n\tif entry == nil {\n\t\tlibcErrno = 0\n\t\treturn nil\n\t}\n\n\t// The dirent C struct uses a flexible array member to indicate that the\n\t// directory name is laid out in memory right after the struct data:\n\t//\n\t// struct dirent {\n\t//   ino_t d_ino;\n\t//   unsigned char d_type;\n\t//   char d_name[];\n\t// };\n\tbuf := make([]byte, unsafe.Sizeof(Dirent{})+uintptr(len(entry.Name)))\n\tdirent := (*Dirent)((unsafe.Pointer)(&buf[0]))\n\n\t// No inodes in wasi\n\tdirent.Ino = 0\n\tdirent.Type = p2fileTypeToDirentType(entry.Type)\n\tcopy(buf[unsafe.Offsetof(dirent.Type)+1:], entry.Name)\n\n\treturn dirent\n}\n\nfunc p2fileTypeToDirentType(t types.DescriptorType) uint8 {\n\tswitch t {\n\tcase types.DescriptorTypeUnknown:\n\t\treturn DT_UNKNOWN\n\tcase types.DescriptorTypeBlockDevice:\n\t\treturn DT_BLK\n\tcase types.DescriptorTypeCharacterDevice:\n\t\treturn DT_CHR\n\tcase types.DescriptorTypeDirectory:\n\t\treturn DT_DIR\n\tcase types.DescriptorTypeFIFO:\n\t\treturn DT_FIFO\n\tcase types.DescriptorTypeSymbolicLink:\n\t\treturn DT_LNK\n\tcase types.DescriptorTypeRegularFile:\n\t\treturn DT_REG\n\tcase types.DescriptorTypeSocket:\n\t\treturn DT_FIFO\n\t}\n\n\treturn DT_UNKNOWN\n}\n\nfunc p2fileTypeToStatType(t types.DescriptorType) uint32 {\n\tswitch t {\n\tcase types.DescriptorTypeUnknown:\n\t\treturn 0\n\tcase types.DescriptorTypeBlockDevice:\n\t\treturn S_IFBLK\n\tcase types.DescriptorTypeCharacterDevice:\n\t\treturn S_IFCHR\n\tcase types.DescriptorTypeDirectory:\n\t\treturn S_IFDIR\n\tcase types.DescriptorTypeFIFO:\n\t\treturn S_IFIFO\n\tcase types.DescriptorTypeSymbolicLink:\n\t\treturn S_IFLNK\n\tcase types.DescriptorTypeRegularFile:\n\t\treturn S_IFREG\n\tcase types.DescriptorTypeSocket:\n\t\treturn S_IFSOCK\n\t}\n\n\treturn 0\n}\n\n// void arc4random_buf (void *, size_t);\n//\n//export arc4random_buf\nfunc arc4random_buf(p unsafe.Pointer, l uint) {\n\tresult := random.GetRandomBytes(uint64(l))\n\ts := result.Slice()\n\tmemcpy(unsafe.Pointer(p), unsafe.Pointer(unsafe.SliceData(s)), uintptr(l))\n}\n\n// int chdir(char *name)\n//\n//export chdir\nfunc chdir(name *byte) int {\n\tpath := goString(name) + \"/\"\n\n\tif !isAbs(path) {\n\t\tpath = joinPath(libcCWD.root+\"/\"+libcCWD.rel+\"/\", path)\n\t}\n\n\tif path == \".\" {\n\t\treturn 0\n\t}\n\n\tdir, rel := findPreopenForPath(path)\n\tif dir.d == cm.ResourceNone {\n\t\tlibcErrno = EACCES\n\t\treturn -1\n\t}\n\n\t_, err, isErr := dir.d.OpenAt(types.PathFlagsSymlinkFollow, rel, types.OpenFlagsDirectory, types.DescriptorFlagsRead).Result()\n\tif isErr {\n\t\tlibcErrno = errorCodeToErrno(err)\n\t\treturn -1\n\t}\n\n\tlibcCWD = dir\n\t// keep the same cwd base but update \"rel\" to point to new base path\n\tlibcCWD.rel = rel\n\n\treturn 0\n}\n\n// char *getcwd(char *buf, size_t size)\n//\n//export getcwd\nfunc getcwd(buf *byte, size uint) *byte {\n\n\tcwd := libcCWD.root\n\tif libcCWD.rel != \"\" && libcCWD.rel != \".\" && libcCWD.rel != \"./\" {\n\t\tcwd += libcCWD.rel\n\t}\n\n\tif buf == nil {\n\t\tb := make([]byte, len(cwd)+1)\n\t\tbuf = unsafe.SliceData(b)\n\t} else if size == 0 {\n\t\tlibcErrno = EINVAL\n\t\treturn nil\n\t}\n\n\tif size < uint(len(cwd)+1) {\n\t\tlibcErrno = ERANGE\n\t\treturn nil\n\t}\n\n\ts := unsafe.Slice(buf, size)\n\ts[size-1] = 0 // Enforce NULL termination\n\tcopy(s, cwd)\n\treturn buf\n}\n\n// int truncate(const char *path, off_t length);\n//\n//export truncate\nfunc truncate(path *byte, length int64) int32 {\n\tlibcErrno = ENOSYS\n\treturn -1\n}\n"
  },
  {
    "path": "src/syscall/mmap_unix_test.go",
    "content": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build linux\n\npackage syscall_test\n\nimport (\n\t\"syscall\"\n\t\"testing\"\n)\n\nfunc TestMmap(t *testing.T) {\n\tb, err := syscall.Mmap(-1, 0, syscall.Getpagesize(), syscall.PROT_NONE, syscall.MAP_ANON|syscall.MAP_PRIVATE)\n\tif err != nil {\n\t\tt.Fatalf(\"Mmap: %v\", err)\n\t}\n\tif err := syscall.Munmap(b); err != nil {\n\t\tt.Fatalf(\"Munmap: %v\", err)\n\t}\n}\n"
  },
  {
    "path": "src/syscall/net.go",
    "content": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage syscall\n\n// A RawConn is a raw network connection.\ntype RawConn interface {\n\t// Control invokes f on the underlying connection's file\n\t// descriptor or handle.\n\t// The file descriptor fd is guaranteed to remain valid while\n\t// f executes but not after f returns.\n\tControl(f func(fd uintptr)) error\n\n\t// Read invokes f on the underlying connection's file\n\t// descriptor or handle; f is expected to try to read from the\n\t// file descriptor.\n\t// If f returns true, Read returns. Otherwise Read blocks\n\t// waiting for the connection to be ready for reading and\n\t// tries again repeatedly.\n\t// The file descriptor is guaranteed to remain valid while f\n\t// executes but not after f returns.\n\tRead(f func(fd uintptr) (done bool)) error\n\n\t// Write is like Read but for writing.\n\tWrite(f func(fd uintptr) (done bool)) error\n}\n\n// Conn is implemented by some types in the net and os packages to provide\n// access to the underlying file descriptor or handle.\ntype Conn interface {\n\t// SyscallConn returns a raw network connection.\n\tSyscallConn() (RawConn, error)\n}\n"
  },
  {
    "path": "src/syscall/proc_emulated.go",
    "content": "//go:build baremetal || tinygo.wasm || nintendoswitch\n\n// This file emulates some process-related functions that are only available\n// under a real operating system.\n\npackage syscall\n\nfunc Getuid() int  { return -1 }\nfunc Geteuid() int { return -1 }\nfunc Getgid() int  { return -1 }\nfunc Getegid() int { return -1 }\nfunc Getpid() int  { return -1 }\nfunc Getppid() int { return -1 }\n"
  },
  {
    "path": "src/syscall/proc_hosted.go",
    "content": "//go:build !baremetal && !tinygo.wasm && !nintendoswitch\n\n// This file assumes there is a libc available that runs on a real operating\n// system.\n\npackage syscall\n\nfunc Getuid() int  { return int(libc_getuid()) }\nfunc Geteuid() int { return int(libc_geteuid()) }\nfunc Getgid() int  { return int(libc_getgid()) }\nfunc Getegid() int { return int(libc_getegid()) }\nfunc Getpid() int  { return int(libc_getpid()) }\nfunc Getppid() int { return int(libc_getppid()) }\n\n// uid_t getuid(void)\n//\n//export getuid\nfunc libc_getuid() int32\n\n// gid_t getgid(void)\n//\n//export getgid\nfunc libc_getgid() int32\n\n// uid_t geteuid(void)\n//\n//export geteuid\nfunc libc_geteuid() int32\n\n// gid_t getegid(void)\n//\n//export getegid\nfunc libc_getegid() int32\n\n// gid_t getpid(void)\n//\n//export getpid\nfunc libc_getpid() int32\n\n// gid_t getppid(void)\n//\n//export getppid\nfunc libc_getppid() int32\n"
  },
  {
    "path": "src/syscall/str.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage syscall\n\n// clen returns the index of the first NULL byte in n or len(n) if n contains no NULL byte.\nfunc clen(n []byte) int {\n\tfor i := 0; i < len(n); i++ {\n\t\tif n[i] == 0 {\n\t\t\treturn i\n\t\t}\n\t}\n\treturn len(n)\n}\n"
  },
  {
    "path": "src/syscall/syscall.go",
    "content": "package syscall\n\nimport (\n\t\"errors\"\n)\n\nconst (\n\tMSG_DONTWAIT = 0x40\n\tAF_INET      = 0x2\n\tAF_INET6     = 0xa\n)\n\nfunc Exit(code int)\n\ntype Rlimit struct {\n\tCur uint64\n\tMax uint64\n}\n\nfunc Setrlimit(resource int, rlim *Rlimit) error {\n\treturn errors.New(\"Setrlimit not implemented\")\n}\n"
  },
  {
    "path": "src/syscall/syscall_libc.go",
    "content": "//go:build js || nintendoswitch || wasip1 || wasip2\n\npackage syscall\n\nimport (\n\t\"unsafe\"\n)\n\ntype sliceHeader struct {\n\tbuf *byte\n\tlen uintptr\n\tcap uintptr\n}\n\nfunc Close(fd int) (err error) {\n\tif libc_close(int32(fd)) < 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\nfunc Dup(fd int) (fd2 int, err error) {\n\tfd2 = int(libc_dup(int32(fd)))\n\tif fd2 < 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\nfunc Write(fd int, p []byte) (n int, err error) {\n\tbuf, count := splitSlice(p)\n\tn = libc_write(int32(fd), buf, uint(count))\n\tif n < 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\nfunc Read(fd int, p []byte) (n int, err error) {\n\tbuf, count := splitSlice(p)\n\tn = libc_read(int32(fd), buf, uint(count))\n\tif n < 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\nfunc Pread(fd int, p []byte, offset int64) (n int, err error) {\n\tbuf, count := splitSlice(p)\n\tn = libc_pread(int32(fd), buf, uint(count), offset)\n\tif n < 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\nfunc Pwrite(fd int, p []byte, offset int64) (n int, err error) {\n\tbuf, count := splitSlice(p)\n\tn = libc_pwrite(int32(fd), buf, uint(count), offset)\n\tif n < 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\nfunc Seek(fd int, offset int64, whence int) (newoffset int64, err error) {\n\tnewoffset = libc_lseek(int32(fd), offset, whence)\n\tif newoffset < 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\nfunc Open(path string, flag int, mode uint32) (fd int, err error) {\n\tdata := cstring(path)\n\tfd = int(libc_open(&data[0], int32(flag), mode))\n\tif fd < 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\nfunc Fsync(fd int) (err error) {\n\tif libc_fsync(int32(fd)) < 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\nfunc Readlink(path string, p []byte) (n int, err error) {\n\tdata := cstring(path)\n\tbuf, count := splitSlice(p)\n\tn = libc_readlink(&data[0], buf, uint(count))\n\tif n < 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\nfunc Chdir(path string) (err error) {\n\tdata := cstring(path)\n\tfail := int(libc_chdir(&data[0]))\n\tif fail < 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\nfunc Mkdir(path string, mode uint32) (err error) {\n\tdata := cstring(path)\n\tfail := int(libc_mkdir(&data[0], mode))\n\tif fail < 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\nfunc Rmdir(path string) (err error) {\n\tdata := cstring(path)\n\tfail := int(libc_rmdir(&data[0]))\n\tif fail < 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\nfunc Rename(from, to string) (err error) {\n\tfromdata := cstring(from)\n\ttodata := cstring(to)\n\tfail := int(libc_rename(&fromdata[0], &todata[0]))\n\tif fail < 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\nfunc Link(oldname, newname string) (err error) {\n\tfromdata := cstring(oldname)\n\ttodata := cstring(newname)\n\tfail := int(libc_link(&fromdata[0], &todata[0]))\n\tif fail < 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\nfunc Symlink(from, to string) (err error) {\n\tfromdata := cstring(from)\n\ttodata := cstring(to)\n\tfail := int(libc_symlink(&fromdata[0], &todata[0]))\n\tif fail < 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\nfunc Unlink(path string) (err error) {\n\tdata := cstring(path)\n\tfail := int(libc_unlink(&data[0]))\n\tif fail < 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\nfunc Chown(path string, uid, gid int) (err error) {\n\tdata := cstring(path)\n\tfail := int(libc_chown(&data[0], uid, gid))\n\tif fail < 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\nfunc Fork() (err error) {\n\tfail := int(libc_fork())\n\tif fail < 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\nfunc Execve(pathname string, argv []string, envv []string) (err error) {\n\targv0 := cstring(pathname)\n\n\t// transform argv and envv into the format expected by execve\n\targv1 := make([]*byte, len(argv)+1)\n\tfor i, arg := range argv {\n\t\targv1[i] = &cstring(arg)[0]\n\t}\n\targv1[len(argv)] = nil\n\n\tenv1 := make([]*byte, len(envv)+1)\n\tfor i, env := range envv {\n\t\tenv1[i] = &cstring(env)[0]\n\t}\n\tenv1[len(envv)] = nil\n\n\tfail := int(libc_execve(&argv0[0], &argv1[0], &env1[0]))\n\tif fail < 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\nfunc Truncate(path string, length int64) (err error) {\n\tdata := cstring(path)\n\tfail := int(libc_truncate(&data[0], length))\n\tif fail < 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\nfunc Faccessat(dirfd int, path string, mode uint32, flags int) (err error)\n\nfunc Kill(pid int, sig Signal) (err error) {\n\treturn ENOSYS // TODO\n}\n\ntype SysProcAttr struct{}\n\n// TODO\ntype WaitStatus uint32\n\nfunc (w WaitStatus) Exited() bool       { return false }\nfunc (w WaitStatus) ExitStatus() int    { return 0 }\nfunc (w WaitStatus) Signaled() bool     { return false }\nfunc (w WaitStatus) Signal() Signal     { return 0 }\nfunc (w WaitStatus) CoreDump() bool     { return false }\nfunc (w WaitStatus) Stopped() bool      { return false }\nfunc (w WaitStatus) Continued() bool    { return false }\nfunc (w WaitStatus) StopSignal() Signal { return 0 }\nfunc (w WaitStatus) TrapCause() int     { return 0 }\n\n// Purely here for compatibility.\ntype Rusage struct {\n}\n\n// since rusage is quite a big struct and we stub it out anyway no need to define it here\nfunc Wait4(pid int, wstatus *WaitStatus, options int, rusage uintptr) (wpid int, err error) {\n\treturn 0, ENOSYS // TODO\n}\n\nfunc Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {\n\taddr := libc_mmap(nil, uintptr(length), int32(prot), int32(flags), int32(fd), uintptr(offset))\n\tif addr == unsafe.Pointer(^uintptr(0)) {\n\t\treturn nil, getErrno()\n\t}\n\treturn (*[1 << 30]byte)(addr)[:length:length], nil\n}\n\nfunc Munmap(b []byte) (err error) {\n\terrCode := libc_munmap(unsafe.Pointer(&b[0]), uintptr(len(b)))\n\tif errCode != 0 {\n\t\terr = getErrno()\n\t}\n\treturn err\n}\n\nfunc Mprotect(b []byte, prot int) (err error) {\n\terrCode := libc_mprotect(unsafe.Pointer(&b[0]), uintptr(len(b)), int32(prot))\n\tif errCode != 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\n// BytePtrFromString returns a pointer to a NUL-terminated array of\n// bytes containing the text of s. If s contains a NUL byte at any\n// location, it returns (nil, EINVAL).\nfunc BytePtrFromString(s string) (*byte, error) {\n\tfor i := 0; i < len(s); i++ {\n\t\tif s[i] == 0 {\n\t\t\treturn nil, EINVAL\n\t\t}\n\t}\n\treturn &cstring(s)[0], nil\n}\n\n// cstring converts a Go string to a C string.\nfunc cstring(s string) []byte {\n\tdata := make([]byte, len(s)+1)\n\tcopy(data, s)\n\t// final byte should be zero from the initial allocation\n\treturn data\n}\n\nfunc splitSlice(p []byte) (buf *byte, len uintptr) {\n\tslice := (*sliceHeader)(unsafe.Pointer(&p))\n\treturn slice.buf, slice.len\n}\n\n// These two functions are provided by the runtime.\nfunc runtimeSetenv(key, value string)\nfunc runtimeUnsetenv(key string)\n\n//export strlen\nfunc libc_strlen(ptr unsafe.Pointer) uintptr\n\n// ssize_t write(int fd, const void *buf, size_t count)\n//\n//export write\nfunc libc_write(fd int32, buf *byte, count uint) int\n\n// char *getenv(const char *name);\n//\n//export getenv\nfunc libc_getenv(name *byte) *byte\n\n// ssize_t read(int fd, void *buf, size_t count);\n//\n//export read\nfunc libc_read(fd int32, buf *byte, count uint) int\n\n// ssize_t pread(int fd, void *buf, size_t count, off_t offset);\n//\n//export pread\nfunc libc_pread(fd int32, buf *byte, count uint, offset int64) int\n\n// ssize_t pwrite(int fd, void *buf, size_t count, off_t offset);\n//\n//export pwrite\nfunc libc_pwrite(fd int32, buf *byte, count uint, offset int64) int\n\n// ssize_t lseek(int fd, off_t offset, int whence);\n//\n//export lseek\nfunc libc_lseek(fd int32, offset int64, whence int) int64\n\n// int close(int fd)\n//\n//export close\nfunc libc_close(fd int32) int32\n\n// int dup(int fd)\n//\n//export dup\nfunc libc_dup(fd int32) int32\n\n// void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);\n//\n//export mmap\nfunc libc_mmap(addr unsafe.Pointer, length uintptr, prot, flags, fd int32, offset uintptr) unsafe.Pointer\n\n// int munmap(void *addr, size_t length);\n//\n//export munmap\nfunc libc_munmap(addr unsafe.Pointer, length uintptr) int32\n\n// int mprotect(void *addr, size_t len, int prot);\n//\n//export mprotect\nfunc libc_mprotect(addr unsafe.Pointer, len uintptr, prot int32) int32\n\n// int chdir(const char *pathname, mode_t mode);\n//\n//export chdir\nfunc libc_chdir(pathname *byte) int32\n\n// int chmod(const char *pathname, mode_t mode);\n//\n//export chmod\nfunc libc_chmod(pathname *byte, mode uint32) int32\n\n// int chown(const char *pathname, uid_t owner, gid_t group);\n//\n//export chown\nfunc libc_chown(pathname *byte, owner, group int) int32\n\n// int mkdir(const char *pathname, mode_t mode);\n//\n//export mkdir\nfunc libc_mkdir(pathname *byte, mode uint32) int32\n\n// int rmdir(const char *pathname);\n//\n//export rmdir\nfunc libc_rmdir(pathname *byte) int32\n\n// int rename(const char *from, *to);\n//\n//export rename\nfunc libc_rename(from, to *byte) int32\n\n// int symlink(const char *from, *to);\n//\n//export symlink\nfunc libc_symlink(from, to *byte) int32\n\n// int link(const char *oldname, *newname);\n//\n//export link\nfunc libc_link(oldname, newname *byte) int32\n\n// int fsync(int fd);\n//\n//export fsync\nfunc libc_fsync(fd int32) int32\n\n// ssize_t readlink(const char *path, void *buf, size_t count);\n//\n//export readlink\nfunc libc_readlink(path *byte, buf *byte, count uint) int\n\n// int unlink(const char *pathname);\n//\n//export unlink\nfunc libc_unlink(pathname *byte) int32\n\n// pid_t fork(void);\n//\n//export fork\nfunc libc_fork() int32\n\n// int execve(const char *filename, char *const argv[], char *const envp[]);\n//\n//export execve\nfunc libc_execve(filename *byte, argv **byte, envp **byte) int\n\n// int truncate(const char *path, off_t length);\n//\n//export truncate\nfunc libc_truncate(path *byte, length int64) int32\n"
  },
  {
    "path": "src/syscall/syscall_libc_nintendoswitch.go",
    "content": "//go:build nintendoswitch\n\npackage syscall\n\nimport (\n\t\"internal/itoa\"\n)\n\n// A Signal is a number describing a process signal.\n// It implements the os.Signal interface.\ntype Signal int\n\nconst (\n\t_ Signal = iota\n\tSIGCHLD\n\tSIGINT\n\tSIGKILL\n\tSIGTRAP\n\tSIGQUIT\n\tSIGTERM\n)\n\nfunc (s Signal) Signal() {}\n\nfunc (s Signal) String() string {\n\tif 0 <= s && int(s) < len(signals) {\n\t\tstr := signals[s]\n\t\tif str != \"\" {\n\t\t\treturn str\n\t\t}\n\t}\n\treturn \"signal \" + itoa.Itoa(int(s))\n}\n\nvar signals = [...]string{}\n\n// File system\n\nconst (\n\tStdin  = 0\n\tStdout = 1\n\tStderr = 2\n)\n\nconst (\n\tO_RDONLY = 0\n\tO_WRONLY = 1\n\tO_RDWR   = 2\n\n\tO_CREAT  = 0100\n\tO_TRUNC  = 01000\n\tO_APPEND = 02000\n\tO_EXCL   = 0200\n\tO_SYNC   = 010000\n\n\tO_CLOEXEC = 0\n)\n\n//go:extern errno\nvar libcErrno uintptr\n\nfunc getErrno() error {\n\treturn Errno(libcErrno)\n}\n\nfunc Pipe2(p []int, flags int) (err error) {\n\treturn ENOSYS // TODO\n}\n\nfunc Getpagesize() int {\n\treturn 4096 // TODO\n}\n\ntype RawSockaddrInet4 struct {\n\t// stub\n}\n\ntype RawSockaddrInet6 struct {\n\t// stub\n}\n\nfunc Chmod(path string, mode uint32) (err error) {\n\tdata := cstring(path)\n\tfail := int(libc_chmod(&data[0], mode))\n\tif fail < 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\n// int open(const char *pathname, int flags, mode_t mode);\n//\n//export open\nfunc libc_open(pathname *byte, flags int32, mode uint32) int32\n"
  },
  {
    "path": "src/syscall/syscall_libc_wasi.go",
    "content": "//go:build js || wasip1 || wasip2\n\n// Note: also including js in here because it also uses wasi-libc.\n\npackage syscall\n\nimport (\n\t\"internal/itoa\"\n\t\"unsafe\"\n)\n\n// https://github.com/WebAssembly/wasi-libc/blob/main/expected/wasm32-wasi/predefined-macros.txt\n// disagrees with ../../lib/wasi-libc/libc-top-half/musl/arch/wasm32/bits/signal.h for SIGCHLD?\n// https://github.com/WebAssembly/wasi-libc/issues/271\n\ntype Signal int\n\nconst (\n\tSIGINT  Signal = 2\n\tSIGQUIT Signal = 3\n\tSIGILL  Signal = 4\n\tSIGTRAP Signal = 5\n\tSIGABRT Signal = 6\n\tSIGBUS  Signal = 7\n\tSIGFPE  Signal = 8\n\tSIGKILL Signal = 9\n\tSIGSEGV Signal = 11\n\tSIGPIPE Signal = 13\n\tSIGTERM Signal = 15\n\tSIGCHLD Signal = 17\n)\n\nfunc (s Signal) Signal() {}\n\nfunc (s Signal) String() string {\n\tif 0 <= s && int(s) < len(signals) {\n\t\tstr := signals[s]\n\t\tif str != \"\" {\n\t\t\treturn str\n\t\t}\n\t}\n\treturn \"signal \" + itoa.Itoa(int(s))\n}\n\nvar signals = [...]string{}\n\nconst (\n\tStdin  = 0\n\tStdout = 1\n\tStderr = 2\n)\n\nconst (\n\t__WASI_OFLAGS_CREAT     = 1\n\t__WASI_OFLAGS_DIRECTORY = 2\n\t__WASI_OFLAGS_EXCL      = 4\n\t__WASI_OFLAGS_TRUNC     = 8\n\n\t__WASI_FDFLAGS_APPEND   = 1\n\t__WASI_FDFLAGS_DSYNC    = 2\n\t__WASI_FDFLAGS_NONBLOCK = 4\n\t__WASI_FDFLAGS_RSYNC    = 8\n\t__WASI_FDFLAGS_SYNC     = 16\n\n\t__WASI_FILETYPE_UNKNOWN          = 0\n\t__WASI_FILETYPE_BLOCK_DEVICE     = 1\n\t__WASI_FILETYPE_CHARACTER_DEVICE = 2\n\t__WASI_FILETYPE_DIRECTORY        = 3\n\t__WASI_FILETYPE_REGULAR_FILE     = 4\n\t__WASI_FILETYPE_SOCKET_DGRAM     = 5\n\t__WASI_FILETYPE_SOCKET_STREAM    = 6\n\t__WASI_FILETYPE_SYMBOLIC_LINK    = 7\n\n\t// ../../lib/wasi-libc/libc-bottom-half/headers/public/__header_fcntl.h\n\tO_NOFOLLOW = 0x01000000\n\tO_RDONLY   = 0x04000000\n\tO_WRONLY   = 0x10000000\n\tO_RDWR     = O_RDONLY | O_WRONLY\n\n\tO_CREAT     = __WASI_OFLAGS_CREAT << 12\n\tO_TRUNC     = __WASI_OFLAGS_TRUNC << 12\n\tO_EXCL      = __WASI_OFLAGS_EXCL << 12\n\tO_DIRECTORY = __WASI_OFLAGS_DIRECTORY << 12\n\n\tO_APPEND   = __WASI_FDFLAGS_APPEND\n\tO_DSYNC    = __WASI_FDFLAGS_DSYNC\n\tO_NONBLOCK = __WASI_FDFLAGS_NONBLOCK\n\tO_RSYNC    = __WASI_FDFLAGS_RSYNC\n\tO_SYNC     = __WASI_FDFLAGS_SYNC\n\n\tO_CLOEXEC = 0\n\n\t// ../../lib/wasi-libc/sysroot/include/sys/mman.h\n\tMAP_FILE      = 0\n\tMAP_SHARED    = 0x01\n\tMAP_PRIVATE   = 0x02\n\tMAP_ANON      = 0x20\n\tMAP_ANONYMOUS = MAP_ANON\n\n\t// ../../lib/wasi-libc/sysroot/include/sys/mman.h\n\tPROT_NONE  = 0\n\tPROT_READ  = 1\n\tPROT_WRITE = 2\n\tPROT_EXEC  = 4\n\n\t// ../../lib/wasi-libc/expected/wasm32-wasi/predefined-macros.txt\n\tF_GETFL = 3\n\tF_SETFL = 4\n\n\t// ../../lib/wasi-libc/libc-top-half/musl/arch/generic/bits/ioctl.h\n\tTIOCSPGRP = 0x5410\n)\n\n// These values are needed as a stub until Go supports WASI as a full target.\n// The constant values don't have a meaning and don't correspond to anything\n// real.\nconst (\n\t_ = iota\n\tSYS_FCNTL\n\tSYS_FCNTL64\n\tSYS_FSTATAT64\n\tSYS_IOCTL\n\tSYS_MKDIRAT\n\tSYS_OPENAT\n\tSYS_READLINKAT\n\tSYS_UNLINKAT\n\tSYS_WAITID\n\tPATH_MAX = 4096\n)\n\nfunc getErrno() error {\n\t// libcErrno is the errno from wasi-libc for wasip1 and the errno for libc_wasip2 for wasip2\n\treturn libcErrno\n}\n\nfunc (e Errno) Is(target error) bool {\n\tswitch target.Error() {\n\tcase \"permission denied\":\n\t\treturn e == EACCES || e == EPERM || e == ENOTCAPABLE // ENOTCAPABLE is unique in WASI\n\tcase \"file already exists\":\n\t\treturn e == EEXIST || e == ENOTEMPTY\n\tcase \"file does not exist\":\n\t\treturn e == ENOENT\n\t}\n\treturn false\n}\n\n// https://github.com/WebAssembly/wasi-libc/blob/main/libc-bottom-half/headers/public/__errno.h\nconst (\n\tE2BIG           Errno = 1      /* Argument list too long */\n\tEACCES          Errno = 2      /* Permission denied */\n\tEADDRINUSE      Errno = 3      /* Address already in use */\n\tEADDRNOTAVAIL   Errno = 4      /* Address not available */\n\tEAFNOSUPPORT    Errno = 5      /* Address family not supported by protocol family */\n\tEAGAIN          Errno = 6      /* Try again */\n\tEWOULDBLOCK     Errno = EAGAIN /* Operation would block */\n\tEALREADY        Errno = 7      /* Socket already connected */\n\tEBADF           Errno = 8      /* Bad file number */\n\tEBADMSG         Errno = 9      /* Trying to read unreadable message */\n\tEBUSY           Errno = 10     /* Device or resource busy */\n\tECANCELED       Errno = 11     /* Operation canceled. */\n\tECHILD          Errno = 12     /* No child processes */\n\tECONNABORTED    Errno = 13     /* Connection aborted */\n\tECONNREFUSED    Errno = 14     /* Connection refused */\n\tECONNRESET      Errno = 15     /* Connection reset by peer */\n\tEDEADLK         Errno = 16     /* Deadlock condition */\n\tEDESTADDRREQ    Errno = 17     /* Destination address required */\n\tEDOM            Errno = 18     /* Math arg out of domain of func */\n\tEDQUOT          Errno = 19     /* Quota exceeded */\n\tEEXIST          Errno = 20     /* File exists */\n\tEFAULT          Errno = 21     /* Bad address */\n\tEFBIG           Errno = 22     /* File too large */\n\tEHOSTUNREACH    Errno = 23     /* Host is unreachable */\n\tEIDRM           Errno = 24     /* Identifier removed */\n\tEILSEQ          Errno = 25\n\tEINPROGRESS     Errno = 26 /* Connection already in progress */\n\tEINTR           Errno = 27 /* Interrupted system call */\n\tEINVAL          Errno = 28 /* Invalid argument */\n\tEIO             Errno = 29 /* I/O error */\n\tEISCONN         Errno = 30 /* Socket is already connected */\n\tEISDIR          Errno = 31 /* Is a directory */\n\tELOOP           Errno = 32 /* Too many symbolic links */\n\tEMFILE          Errno = 33 /* Too many open files */\n\tEMLINK          Errno = 34 /* Too many links */\n\tEMSGSIZE        Errno = 35 /* Message too long */\n\tEMULTIHOP       Errno = 36 /* Multihop attempted */\n\tENAMETOOLONG    Errno = 37 /* File name too long */\n\tENETDOWN        Errno = 38 /* Network interface is not configured */\n\tENETRESET       Errno = 39\n\tENETUNREACH     Errno = 40         /* Network is unreachable */\n\tENFILE          Errno = 41         /* File table overflow */\n\tENOBUFS         Errno = 42         /* No buffer space available */\n\tENODEV          Errno = 43         /* No such device */\n\tENOENT          Errno = 44         /* No such file or directory */\n\tENOEXEC         Errno = 45         /* Exec format error */\n\tENOLCK          Errno = 46         /* No record locks available */\n\tENOLINK         Errno = 47         /* The link has been severed */\n\tENOMEM          Errno = 48         /* Out of memory */\n\tENOMSG          Errno = 49         /* No message of desired type */\n\tENOPROTOOPT     Errno = 50         /* Protocol not available */\n\tENOSPC          Errno = 51         /* No space left on device */\n\tENOSYS          Errno = 52         /* Function not implemented */\n\tENOTCONN        Errno = 53         /* Socket is not connected */\n\tENOTDIR         Errno = 54         /* Not a directory */\n\tENOTEMPTY       Errno = 55         /* Directory not empty */\n\tENOTRECOVERABLE Errno = 56         /* State not recoverable */\n\tENOTSOCK        Errno = 57         /* Socket operation on non-socket */\n\tESOCKTNOSUPPORT Errno = 58         /* Socket type not supported */\n\tEOPNOTSUPP      Errno = 58         /* Operation not supported on transport endpoint */\n\tENOTSUP         Errno = EOPNOTSUPP /* Not supported */\n\tENOTTY          Errno = 59         /* Not a typewriter */\n\tENXIO           Errno = 60         /* No such device or address */\n\tEOVERFLOW       Errno = 61         /* Value too large for defined data type */\n\tEPERM           Errno = 63         /* Operation not permitted */\n\tEPIPE           Errno = 64         /* Broken pipe */\n\tEPROTO          Errno = 65         /* Protocol error */\n\tEPROTONOSUPPORT Errno = 66         /* Unknown protocol */\n\tEPROTOTYPE      Errno = 67         /* Protocol wrong type for socket */\n\tERANGE          Errno = 68         /* Math result not representable */\n\tEROFS           Errno = 69         /* Read-only file system */\n\tESPIPE          Errno = 70         /* Illegal seek */\n\tESRCH           Errno = 71         /* No such process */\n\tESTALE          Errno = 72\n\tETIMEDOUT       Errno = 73 /* Connection timed out */\n\tETXTBSY         Errno = 74 /* Text file busy */\n\tEXDEV           Errno = 75 /* Cross-device link */\n\tENOTCAPABLE     Errno = 76 /* Extension: Capabilities insufficient. */\n\n\tEWASIERROR Errno = 255 /* Unknown WASI error */\n)\n\n// TODO(ydnar): remove Timespec for WASI Preview 2 (seconds is uint64).\n//\n// https://github.com/WebAssembly/wasi-libc/blob/main/libc-bottom-half/headers/public/__struct_timespec.h\ntype Timespec struct {\n\tSec  int32\n\tNsec int64\n}\n\n// Unix returns the time stored in ts as seconds plus nanoseconds.\nfunc (ts *Timespec) Unix() (sec int64, nsec int64) {\n\treturn int64(ts.Sec), int64(ts.Nsec)\n}\n\n// https://github.com/WebAssembly/wasi-libc/blob/main/libc-bottom-half/headers/public/__struct_stat.h\n// https://github.com/WebAssembly/wasi-libc/blob/main/libc-bottom-half/headers/public/__typedef_ino_t.h\n// etc.\ntype Stat_t struct {\n\tDev       uint64\n\tIno       uint64\n\tNlink     uint64\n\tMode      uint32\n\tUid       uint32\n\tGid       uint32\n\tPad_cgo_0 [4]byte\n\tRdev      uint64\n\tSize      int64\n\tBlksize   int32\n\tBlocks    int64\n\n\tAtim   Timespec\n\tMtim   Timespec\n\tCtim   Timespec\n\tQspare [3]int64\n}\n\n// https://github.com/WebAssembly/wasi-libc/blob/main/libc-top-half/musl/include/sys/stat.h\nconst (\n\tS_IFBLK  = 0x6000\n\tS_IFCHR  = 0x2000\n\tS_IFDIR  = 0x4000\n\tS_IFIFO  = 0x1000\n\tS_IFLNK  = 0xa000\n\tS_IFMT   = 0xf000\n\tS_IFREG  = 0x8000\n\tS_IFSOCK = 0xc000\n\tS_IREAD  = 0x100\n\tS_IRGRP  = 0x20\n\tS_IROTH  = 0x4\n\tS_IRUSR  = 0x100\n\tS_IRWXG  = 0x38\n\tS_IRWXO  = 0x7\n\tS_IRWXU  = 0x1c0\n\tS_ISGID  = 0x400\n\tS_ISUID  = 0x800\n\tS_ISVTX  = 0x200\n\tS_IWGRP  = 0x10\n\tS_IWOTH  = 0x2\n\tS_IWRITE = 0x80\n\tS_IWUSR  = 0x80\n\tS_IXGRP  = 0x8\n\tS_IXOTH  = 0x1\n\tS_IXUSR  = 0x40\n)\n\n// https://github.com/WebAssembly/wasi-libc/blob/main/libc-bottom-half/headers/public/__header_dirent.h\nconst (\n\tDT_BLK     = __WASI_FILETYPE_BLOCK_DEVICE\n\tDT_CHR     = __WASI_FILETYPE_CHARACTER_DEVICE\n\tDT_DIR     = __WASI_FILETYPE_DIRECTORY\n\tDT_FIFO    = __WASI_FILETYPE_SOCKET_STREAM\n\tDT_LNK     = __WASI_FILETYPE_SYMBOLIC_LINK\n\tDT_REG     = __WASI_FILETYPE_REGULAR_FILE\n\tDT_UNKNOWN = __WASI_FILETYPE_UNKNOWN\n)\n\n// Dirent is returned by pointer from Readdir to iterate over directory entries.\n//\n// The pointer is managed by wasi-libc and is only valid until the next call to\n// Readdir or Fdclosedir.\n//\n// https://github.com/WebAssembly/wasi-libc/blob/main/libc-bottom-half/headers/public/__struct_dirent.h\ntype Dirent struct {\n\tIno  uint64\n\tType uint8\n}\n\nfunc (dirent *Dirent) Name() []byte {\n\t// The dirent C struct uses a flexible array member to indicate that the\n\t// directory name is laid out in memory right after the struct data:\n\t//\n\t// struct dirent {\n\t//   ino_t d_ino;\n\t//   unsigned char d_type;\n\t//   char d_name[];\n\t// };\n\tname := (*[PATH_MAX]byte)(unsafe.Add(unsafe.Pointer(dirent), 9))\n\tfor i, c := range name {\n\t\tif c == 0 {\n\t\t\treturn name[:i:i]\n\t\t}\n\t}\n\treturn name[:]\n}\n\nfunc Fdopendir(fd int) (dir uintptr, err error) {\n\td := libc_fdopendir(int32(fd))\n\n\tif d == nil {\n\t\terr = getErrno()\n\t}\n\treturn uintptr(d), err\n}\n\nfunc Fdclosedir(dir uintptr) (err error) {\n\t// Unlike on other unix platform where only closedir exists, wasi-libc has\n\t// fdclosedir which releases resources and returns the file descriptor but\n\t// does not close it. This is useful for us since we want to be able to keep\n\t// using it.\n\tn := libc_fdclosedir(unsafe.Pointer(dir))\n\n\tif n < 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\nfunc Readdir(dir uintptr) (dirent *Dirent, err error) {\n\t// There might be a leftover errno value in the global variable, so we have\n\t// to clear it before calling readdir because we cannot know whether a nil\n\t// return means that we reached EOF or that an error occurred.\n\tlibcErrno = 0\n\n\tdirent = libc_readdir(unsafe.Pointer(dir))\n\n\tif dirent == nil && libcErrno != 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\nfunc Stat(path string, p *Stat_t) (err error) {\n\tdata := cstring(path)\n\tn := libc_stat(&data[0], unsafe.Pointer(p))\n\n\tif n < 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\nfunc Fstat(fd int, p *Stat_t) (err error) {\n\tn := libc_fstat(int32(fd), unsafe.Pointer(p))\n\n\tif n < 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\nfunc Lstat(path string, p *Stat_t) (err error) {\n\tdata := cstring(path)\n\tn := libc_lstat(&data[0], unsafe.Pointer(p))\n\tif n < 0 {\n\t\terr = getErrno()\n\t}\n\treturn\n}\n\nfunc Pipe2(p []int, flags int) (err error) {\n\treturn ENOSYS // TODO\n}\n\nfunc Chmod(path string, mode uint32) (err error) {\n\t// wasi does not have chmod, but there are tests that validate that calling\n\t// os.Chmod does not error (e.g. io/fs.TestIssue51617).\n\t//\n\t// We make a call to Lstat instead so we detect conditions like the path not\n\t// existing, but we don't honnor the request to modify the file permissions.\n\tstat := Stat_t{}\n\treturn Lstat(path, &stat)\n}\n\n// TODO: should this return runtime.wasmPageSize?\nfunc Getpagesize() int {\n\treturn libc_getpagesize()\n}\n\ntype Utsname struct {\n\tSysname    [65]int8\n\tNodename   [65]int8\n\tRelease    [65]int8\n\tVersion    [65]int8\n\tMachine    [65]int8\n\tDomainname [65]int8\n}\n\n//go:linkname faccessat syscall.Faccessat\nfunc faccessat(dirfd int, path string, mode uint32, flags int) (err error) {\n\treturn ENOSYS\n}\n\n// Stub Utsname, needed because WASI pretends to be linux/arm.\nfunc Uname(buf *Utsname) (err error)\n\ntype RawSockaddrInet4 struct {\n\t// stub\n}\n\ntype RawSockaddrInet6 struct {\n\t// stub\n}\n\nfunc RandomGet(b []byte) error {\n\tif len(b) > 0 {\n\t\tlibc_arc4random_buf(unsafe.Pointer(&b[0]), uint(len(b)))\n\t}\n\treturn nil\n}\n\n// This is a stub, it is not functional.\nfunc Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)\n\n// This is a stub, it is not functional.\nfunc Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)\n\n// int getpagesize(void);\n//\n//export getpagesize\nfunc libc_getpagesize() int\n\n// int stat(const char *path, struct stat * buf);\n//\n//export stat\nfunc libc_stat(pathname *byte, ptr unsafe.Pointer) int32\n\n// int fstat(int fd, struct stat * buf);\n//\n//export fstat\nfunc libc_fstat(fd int32, ptr unsafe.Pointer) int32\n\n// int lstat(const char *path, struct stat * buf);\n//\n//export lstat\nfunc libc_lstat(pathname *byte, ptr unsafe.Pointer) int32\n\n// int open(const char *pathname, int flags, mode_t mode);\n//\n//export open\nfunc libc_open(pathname *byte, flags int32, mode uint32) int32\n\n// DIR *fdopendir(int);\n//\n//export fdopendir\nfunc libc_fdopendir(fd int32) unsafe.Pointer\n\n// int fdclosedir(DIR *);\n//\n//export fdclosedir\nfunc libc_fdclosedir(unsafe.Pointer) int32\n\n// struct dirent *readdir(DIR *);\n//\n//export readdir\nfunc libc_readdir(unsafe.Pointer) *Dirent\n\n// void arc4random_buf(void *buf, size_t buflen);\n//\n//export arc4random_buf\nfunc libc_arc4random_buf(buf unsafe.Pointer, buflen uint)\n"
  },
  {
    "path": "src/syscall/syscall_linux.go",
    "content": "package syscall\n\nfunc Setuid(code int) (err error)\nfunc Setgid(code int) (err error)\nfunc Setreuid(ruid, euid int) (err error)\nfunc Setregid(rgid, egid int) (err error)\nfunc Setresuid(ruid, euid, suid int) (err error)\nfunc Setresgid(rgid, egid, sgid int) (err error)\n"
  },
  {
    "path": "src/syscall/syscall_nonhosted.go",
    "content": "//go:build baremetal || wasm_unknown\n\npackage syscall\n\nimport (\n\t\"internal/itoa\"\n)\n\n// Most code here has been copied from the Go sources:\n//   https://github.com/golang/go/blob/go1.12/src/syscall/syscall_js.go\n// It has the following copyright note:\n//\n//     Copyright 2018 The Go Authors. All rights reserved.\n//     Use of this source code is governed by a BSD-style\n//     license that can be found in the LICENSE file.\n\n// A Signal is a number describing a process signal.\n// It implements the os.Signal interface.\ntype Signal int\n\nconst (\n\t_ Signal = iota\n\tSIGCHLD\n\tSIGINT\n\tSIGKILL\n\tSIGTRAP\n\tSIGQUIT\n\tSIGTERM\n\tSIGILL\n\tSIGABRT\n\tSIGBUS\n\tSIGFPE\n\tSIGSEGV\n\tSIGPIPE\n)\n\nfunc (s Signal) Signal() {}\n\nfunc (s Signal) String() string {\n\tif 0 <= s && int(s) < len(signals) {\n\t\tstr := signals[s]\n\t\tif str != \"\" {\n\t\t\treturn str\n\t\t}\n\t}\n\treturn \"signal \" + itoa.Itoa(int(s))\n}\n\nvar signals = [...]string{}\n\n// File system\n\nconst (\n\tStdin  = 0\n\tStdout = 1\n\tStderr = 2\n)\n\nconst (\n\tO_RDONLY = 0\n\tO_WRONLY = 1\n\tO_RDWR   = 2\n\n\tO_CREAT  = 0100\n\tO_CREATE = O_CREAT\n\tO_TRUNC  = 01000\n\tO_APPEND = 02000\n\tO_EXCL   = 0200\n\tO_SYNC   = 010000\n\n\tO_CLOEXEC = 0\n)\n\n// Dummy values to allow compiling tests\n// Dummy source: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/sys/mman.h.auto.html\nconst (\n\tPROT_NONE  = 0x00 // no permissions\n\tPROT_READ  = 0x01 // pages can be read\n\tPROT_WRITE = 0x02 // pages can be written\n\tPROT_EXEC  = 0x04 // pages can be executed\n\n\tMAP_SHARED  = 0x0001 // share changes\n\tMAP_PRIVATE = 0x0002 // changes are private\n\n\tMAP_FILE      = 0x0000 // map from file (default)\n\tMAP_ANON      = 0x1000 // allocated from memory, swap space\n\tMAP_ANONYMOUS = MAP_ANON\n)\n\nfunc Open(path string, mode int, perm uint32) (fd int, err error) {\n\treturn 0, ENOSYS\n}\n\nfunc Read(fd int, p []byte) (n int, err error) {\n\treturn 0, ENOSYS\n}\n\nfunc Seek(fd int, offset int64, whence int) (off int64, err error) {\n\treturn 0, ENOSYS\n}\n\nfunc Close(fd int) (err error) {\n\treturn ENOSYS\n}\n\n// Processes\n\ntype WaitStatus uint32\n\nfunc (w WaitStatus) Exited() bool       { return false }\nfunc (w WaitStatus) ExitStatus() int    { return 0 }\nfunc (w WaitStatus) Signaled() bool     { return false }\nfunc (w WaitStatus) Signal() Signal     { return 0 }\nfunc (w WaitStatus) CoreDump() bool     { return false }\nfunc (w WaitStatus) Stopped() bool      { return false }\nfunc (w WaitStatus) Continued() bool    { return false }\nfunc (w WaitStatus) StopSignal() Signal { return 0 }\nfunc (w WaitStatus) TrapCause() int     { return 0 }\n\n// XXX made up\ntype Rusage struct {\n\tUtime Timeval\n\tStime Timeval\n}\n\n// XXX made up\ntype ProcAttr struct {\n\tDir   string\n\tEnv   []string\n\tFiles []uintptr\n\tSys   *SysProcAttr\n}\n\ntype SysProcAttr struct {\n}\n\nfunc Getgroups() ([]int, error)         { return []int{1}, nil }\nfunc Gettimeofday(tv *Timeval) error    { return ENOSYS }\nfunc Kill(pid int, signum Signal) error { return ENOSYS }\nfunc Pipe2(p []int, flags int) (err error) {\n\treturn ENOSYS // TODO\n}\nfunc Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {\n\treturn 0, ENOSYS\n}\nfunc StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle uintptr, err error) {\n\treturn 0, 0, ENOSYS\n}\nfunc Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {\n\treturn 0, ENOSYS\n}\n\nfunc Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {\n\treturn nil, ENOSYS\n}\n\nfunc Munmap(b []byte) (err error) {\n\treturn ENOSYS\n}\n\ntype Timeval struct {\n\tSec  int64\n\tUsec int64\n}\n\nfunc Getpagesize() int {\n\t// There is no right value to return here, but 4096 is a\n\t// common assumption when pagesize is unknown\n\treturn 4096\n}\n\ntype RawSockaddrInet4 struct {\n\t// stub\n}\n\ntype RawSockaddrInet6 struct {\n\t// stub\n}\n"
  },
  {
    "path": "src/syscall/syscall_unix.go",
    "content": "//go:build linux || unix\n\npackage syscall\n\nfunc Exec(argv0 string, argv []string, envv []string) (err error)\n\n// The two SockaddrInet* structs have been copied from the Go source tree.\n\ntype SockaddrInet4 struct {\n\tPort int\n\tAddr [4]byte\n\traw  RawSockaddrInet4\n}\n\ntype SockaddrInet6 struct {\n\tPort   int\n\tZoneId uint32\n\tAddr   [16]byte\n\traw    RawSockaddrInet6\n}\n"
  },
  {
    "path": "src/syscall/tables_nonhosted.go",
    "content": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build baremetal || nintendoswitch || wasm_unknown\n\npackage syscall\n\n// TODO: generate with runtime/mknacl.sh, allow override with IRT.\nconst (\n\tsys_null                 = 1\n\tsys_nameservice          = 2\n\tsys_dup                  = 8\n\tsys_dup2                 = 9\n\tsys_open                 = 10\n\tsys_close                = 11\n\tsys_read                 = 12\n\tsys_write                = 13\n\tsys_lseek                = 14\n\tsys_stat                 = 16\n\tsys_fstat                = 17\n\tsys_chmod                = 18\n\tsys_isatty               = 19\n\tsys_brk                  = 20\n\tsys_mmap                 = 21\n\tsys_munmap               = 22\n\tsys_getdents             = 23\n\tsys_mprotect             = 24\n\tsys_list_mappings        = 25\n\tsys_exit                 = 30\n\tsys_getpid               = 31\n\tsys_sched_yield          = 32\n\tsys_sysconf              = 33\n\tsys_gettimeofday         = 40\n\tsys_clock                = 41\n\tsys_nanosleep            = 42\n\tsys_clock_getres         = 43\n\tsys_clock_gettime        = 44\n\tsys_mkdir                = 45\n\tsys_rmdir                = 46\n\tsys_chdir                = 47\n\tsys_getcwd               = 48\n\tsys_unlink               = 49\n\tsys_imc_makeboundsock    = 60\n\tsys_imc_accept           = 61\n\tsys_imc_connect          = 62\n\tsys_imc_sendmsg          = 63\n\tsys_imc_recvmsg          = 64\n\tsys_imc_mem_obj_create   = 65\n\tsys_imc_socketpair       = 66\n\tsys_mutex_create         = 70\n\tsys_mutex_lock           = 71\n\tsys_mutex_trylock        = 72\n\tsys_mutex_unlock         = 73\n\tsys_cond_create          = 74\n\tsys_cond_wait            = 75\n\tsys_cond_signal          = 76\n\tsys_cond_broadcast       = 77\n\tsys_cond_timed_wait_abs  = 79\n\tsys_thread_create        = 80\n\tsys_thread_exit          = 81\n\tsys_tls_init             = 82\n\tsys_thread_nice          = 83\n\tsys_tls_get              = 84\n\tsys_second_tls_set       = 85\n\tsys_second_tls_get       = 86\n\tsys_exception_handler    = 87\n\tsys_exception_stack      = 88\n\tsys_exception_clear_flag = 89\n\tsys_sem_create           = 100\n\tsys_sem_wait             = 101\n\tsys_sem_post             = 102\n\tsys_sem_get_value        = 103\n\tsys_dyncode_create       = 104\n\tsys_dyncode_modify       = 105\n\tsys_dyncode_delete       = 106\n\tsys_test_infoleak        = 109\n\tsys_test_crash           = 110\n\tsys_test_syscall_1       = 111\n\tsys_test_syscall_2       = 112\n\tsys_futex_wait_abs       = 120\n\tsys_futex_wake           = 121\n\tsys_pread                = 130\n\tsys_pwrite               = 131\n\tsys_truncate             = 140\n\tsys_lstat                = 141\n\tsys_link                 = 142\n\tsys_rename               = 143\n\tsys_symlink              = 144\n\tsys_access               = 145\n\tsys_readlink             = 146\n\tsys_utimes               = 147\n\tsys_get_random_bytes     = 150\n)\n\n// TODO: Auto-generate some day. (Hard-coded in binaries so not likely to change.)\nconst (\n\t// native_client/src/trusted/service_runtime/include/sys/errno.h\n\t// The errors are mainly copied from Linux.\n\tEPERM           Errno = 1       /* Operation not permitted */\n\tENOENT          Errno = 2       /* No such file or directory */\n\tESRCH           Errno = 3       /* No such process */\n\tEINTR           Errno = 4       /* Interrupted system call */\n\tEIO             Errno = 5       /* I/O error */\n\tENXIO           Errno = 6       /* No such device or address */\n\tE2BIG           Errno = 7       /* Argument list too long */\n\tENOEXEC         Errno = 8       /* Exec format error */\n\tEBADF           Errno = 9       /* Bad file number */\n\tECHILD          Errno = 10      /* No child processes */\n\tEAGAIN          Errno = 11      /* Try again */\n\tENOMEM          Errno = 12      /* Out of memory */\n\tEACCES          Errno = 13      /* Permission denied */\n\tEFAULT          Errno = 14      /* Bad address */\n\tEBUSY           Errno = 16      /* Device or resource busy */\n\tEEXIST          Errno = 17      /* File exists */\n\tEXDEV           Errno = 18      /* Cross-device link */\n\tENODEV          Errno = 19      /* No such device */\n\tENOTDIR         Errno = 20      /* Not a directory */\n\tEISDIR          Errno = 21      /* Is a directory */\n\tEINVAL          Errno = 22      /* Invalid argument */\n\tENFILE          Errno = 23      /* File table overflow */\n\tEMFILE          Errno = 24      /* Too many open files */\n\tENOTTY          Errno = 25      /* Not a typewriter */\n\tEFBIG           Errno = 27      /* File too large */\n\tENOSPC          Errno = 28      /* No space left on device */\n\tESPIPE          Errno = 29      /* Illegal seek */\n\tEROFS           Errno = 30      /* Read-only file system */\n\tEMLINK          Errno = 31      /* Too many links */\n\tEPIPE           Errno = 32      /* Broken pipe */\n\tENAMETOOLONG    Errno = 36      /* File name too long */\n\tENOSYS          Errno = 38      /* Function not implemented */\n\tEDQUOT          Errno = 122     /* Quota exceeded */\n\tEDOM            Errno = 33      /* Math arg out of domain of func */\n\tERANGE          Errno = 34      /* Math result not representable */\n\tEDEADLK         Errno = 35      /* Deadlock condition */\n\tENOLCK          Errno = 37      /* No record locks available */\n\tENOTEMPTY       Errno = 39      /* Directory not empty */\n\tELOOP           Errno = 40      /* Too many symbolic links */\n\tENOMSG          Errno = 42      /* No message of desired type */\n\tEIDRM           Errno = 43      /* Identifier removed */\n\tECHRNG          Errno = 44      /* Channel number out of range */\n\tEL2NSYNC        Errno = 45      /* Level 2 not synchronized */\n\tEL3HLT          Errno = 46      /* Level 3 halted */\n\tEL3RST          Errno = 47      /* Level 3 reset */\n\tELNRNG          Errno = 48      /* Link number out of range */\n\tEUNATCH         Errno = 49      /* Protocol driver not attached */\n\tENOCSI          Errno = 50      /* No CSI structure available */\n\tEL2HLT          Errno = 51      /* Level 2 halted */\n\tEBADE           Errno = 52      /* Invalid exchange */\n\tEBADR           Errno = 53      /* Invalid request descriptor */\n\tEXFULL          Errno = 54      /* Exchange full */\n\tENOANO          Errno = 55      /* No anode */\n\tEBADRQC         Errno = 56      /* Invalid request code */\n\tEBADSLT         Errno = 57      /* Invalid slot */\n\tEDEADLOCK       Errno = EDEADLK /* File locking deadlock error */\n\tEBFONT          Errno = 59      /* Bad font file fmt */\n\tENOSTR          Errno = 60      /* Device not a stream */\n\tENODATA         Errno = 61      /* No data (for no delay io) */\n\tETIME           Errno = 62      /* Timer expired */\n\tENOSR           Errno = 63      /* Out of streams resources */\n\tENONET          Errno = 64      /* Machine is not on the network */\n\tENOPKG          Errno = 65      /* Package not installed */\n\tEREMOTE         Errno = 66      /* The object is remote */\n\tENOLINK         Errno = 67      /* The link has been severed */\n\tEADV            Errno = 68      /* Advertise error */\n\tESRMNT          Errno = 69      /* Srmount error */\n\tECOMM           Errno = 70      /* Communication error on send */\n\tEPROTO          Errno = 71      /* Protocol error */\n\tEMULTIHOP       Errno = 72      /* Multihop attempted */\n\tEDOTDOT         Errno = 73      /* Cross mount point (not really error) */\n\tEBADMSG         Errno = 74      /* Trying to read unreadable message */\n\tEOVERFLOW       Errno = 75      /* Value too large for defined data type */\n\tENOTUNIQ        Errno = 76      /* Given log. name not unique */\n\tEBADFD          Errno = 77      /* f.d. invalid for this operation */\n\tEREMCHG         Errno = 78      /* Remote address changed */\n\tELIBACC         Errno = 79      /* Can't access a needed shared lib */\n\tELIBBAD         Errno = 80      /* Accessing a corrupted shared lib */\n\tELIBSCN         Errno = 81      /* .lib section in a.out corrupted */\n\tELIBMAX         Errno = 82      /* Attempting to link in too many libs */\n\tELIBEXEC        Errno = 83      /* Attempting to exec a shared library */\n\tEILSEQ          Errno = 84\n\tEUSERS          Errno = 87\n\tENOTSOCK        Errno = 88  /* Socket operation on non-socket */\n\tEDESTADDRREQ    Errno = 89  /* Destination address required */\n\tEMSGSIZE        Errno = 90  /* Message too long */\n\tEPROTOTYPE      Errno = 91  /* Protocol wrong type for socket */\n\tENOPROTOOPT     Errno = 92  /* Protocol not available */\n\tEPROTONOSUPPORT Errno = 93  /* Unknown protocol */\n\tESOCKTNOSUPPORT Errno = 94  /* Socket type not supported */\n\tEOPNOTSUPP      Errno = 95  /* Operation not supported on transport endpoint */\n\tEPFNOSUPPORT    Errno = 96  /* Protocol family not supported */\n\tEAFNOSUPPORT    Errno = 97  /* Address family not supported by protocol family */\n\tEADDRINUSE      Errno = 98  /* Address already in use */\n\tEADDRNOTAVAIL   Errno = 99  /* Address not available */\n\tENETDOWN        Errno = 100 /* Network interface is not configured */\n\tENETUNREACH     Errno = 101 /* Network is unreachable */\n\tENETRESET       Errno = 102\n\tECONNABORTED    Errno = 103 /* Connection aborted */\n\tECONNRESET      Errno = 104 /* Connection reset by peer */\n\tENOBUFS         Errno = 105 /* No buffer space available */\n\tEISCONN         Errno = 106 /* Socket is already connected */\n\tENOTCONN        Errno = 107 /* Socket is not connected */\n\tESHUTDOWN       Errno = 108 /* Can't send after socket shutdown */\n\tETOOMANYREFS    Errno = 109\n\tETIMEDOUT       Errno = 110 /* Connection timed out */\n\tECONNREFUSED    Errno = 111 /* Connection refused */\n\tEHOSTDOWN       Errno = 112 /* Host is down */\n\tEHOSTUNREACH    Errno = 113 /* Host is unreachable */\n\tEALREADY        Errno = 114 /* Socket already connected */\n\tEINPROGRESS     Errno = 115 /* Connection already in progress */\n\tESTALE          Errno = 116\n\tENOTSUP         Errno = EOPNOTSUPP /* Not supported */\n\tENOMEDIUM       Errno = 123        /* No medium (in tape drive) */\n\tECANCELED       Errno = 125        /* Operation canceled. */\n\tELBIN           Errno = 2048       /* Inode is remote (not really error) */\n\tEFTYPE          Errno = 2049       /* Inappropriate file type or format */\n\tENMFILE         Errno = 2050       /* No more files */\n\tEPROCLIM        Errno = 2051\n\tENOSHARE        Errno = 2052   /* No such host or network path */\n\tECASECLASH      Errno = 2053   /* Filename exists with different case */\n\tEWOULDBLOCK     Errno = EAGAIN /* Operation would block */\n)\n\n// Do the interface allocations only once for common\n// Errno values.\nvar (\n\terrEAGAIN error = EAGAIN\n\terrEINVAL error = EINVAL\n\terrENOENT error = ENOENT\n)\n\n// errnoErr returns common boxed Errno values, to prevent\n// allocations at runtime.\nfunc errnoErr(e Errno) error {\n\tswitch e {\n\tcase 0:\n\t\treturn nil\n\tcase EAGAIN:\n\t\treturn errEAGAIN\n\tcase EINVAL:\n\t\treturn errEINVAL\n\tcase ENOENT:\n\t\treturn errENOENT\n\t}\n\treturn e\n}\n\nvar errnoByCode = map[string]Errno{\n\t\"EPERM\":           EPERM,\n\t\"ENOENT\":          ENOENT,\n\t\"ESRCH\":           ESRCH,\n\t\"EINTR\":           EINTR,\n\t\"EIO\":             EIO,\n\t\"ENXIO\":           ENXIO,\n\t\"E2BIG\":           E2BIG,\n\t\"ENOEXEC\":         ENOEXEC,\n\t\"EBADF\":           EBADF,\n\t\"ECHILD\":          ECHILD,\n\t\"EAGAIN\":          EAGAIN,\n\t\"ENOMEM\":          ENOMEM,\n\t\"EACCES\":          EACCES,\n\t\"EFAULT\":          EFAULT,\n\t\"EBUSY\":           EBUSY,\n\t\"EEXIST\":          EEXIST,\n\t\"EXDEV\":           EXDEV,\n\t\"ENODEV\":          ENODEV,\n\t\"ENOTDIR\":         ENOTDIR,\n\t\"EISDIR\":          EISDIR,\n\t\"EINVAL\":          EINVAL,\n\t\"ENFILE\":          ENFILE,\n\t\"EMFILE\":          EMFILE,\n\t\"ENOTTY\":          ENOTTY,\n\t\"EFBIG\":           EFBIG,\n\t\"ENOSPC\":          ENOSPC,\n\t\"ESPIPE\":          ESPIPE,\n\t\"EROFS\":           EROFS,\n\t\"EMLINK\":          EMLINK,\n\t\"EPIPE\":           EPIPE,\n\t\"ENAMETOOLONG\":    ENAMETOOLONG,\n\t\"ENOSYS\":          ENOSYS,\n\t\"EDQUOT\":          EDQUOT,\n\t\"EDOM\":            EDOM,\n\t\"ERANGE\":          ERANGE,\n\t\"EDEADLK\":         EDEADLK,\n\t\"ENOLCK\":          ENOLCK,\n\t\"ENOTEMPTY\":       ENOTEMPTY,\n\t\"ELOOP\":           ELOOP,\n\t\"ENOMSG\":          ENOMSG,\n\t\"EIDRM\":           EIDRM,\n\t\"ECHRNG\":          ECHRNG,\n\t\"EL2NSYNC\":        EL2NSYNC,\n\t\"EL3HLT\":          EL3HLT,\n\t\"EL3RST\":          EL3RST,\n\t\"ELNRNG\":          ELNRNG,\n\t\"EUNATCH\":         EUNATCH,\n\t\"ENOCSI\":          ENOCSI,\n\t\"EL2HLT\":          EL2HLT,\n\t\"EBADE\":           EBADE,\n\t\"EBADR\":           EBADR,\n\t\"EXFULL\":          EXFULL,\n\t\"ENOANO\":          ENOANO,\n\t\"EBADRQC\":         EBADRQC,\n\t\"EBADSLT\":         EBADSLT,\n\t\"EDEADLOCK\":       EDEADLOCK,\n\t\"EBFONT\":          EBFONT,\n\t\"ENOSTR\":          ENOSTR,\n\t\"ENODATA\":         ENODATA,\n\t\"ETIME\":           ETIME,\n\t\"ENOSR\":           ENOSR,\n\t\"ENONET\":          ENONET,\n\t\"ENOPKG\":          ENOPKG,\n\t\"EREMOTE\":         EREMOTE,\n\t\"ENOLINK\":         ENOLINK,\n\t\"EADV\":            EADV,\n\t\"ESRMNT\":          ESRMNT,\n\t\"ECOMM\":           ECOMM,\n\t\"EPROTO\":          EPROTO,\n\t\"EMULTIHOP\":       EMULTIHOP,\n\t\"EDOTDOT\":         EDOTDOT,\n\t\"EBADMSG\":         EBADMSG,\n\t\"EOVERFLOW\":       EOVERFLOW,\n\t\"ENOTUNIQ\":        ENOTUNIQ,\n\t\"EBADFD\":          EBADFD,\n\t\"EREMCHG\":         EREMCHG,\n\t\"ELIBACC\":         ELIBACC,\n\t\"ELIBBAD\":         ELIBBAD,\n\t\"ELIBSCN\":         ELIBSCN,\n\t\"ELIBMAX\":         ELIBMAX,\n\t\"ELIBEXEC\":        ELIBEXEC,\n\t\"EILSEQ\":          EILSEQ,\n\t\"EUSERS\":          EUSERS,\n\t\"ENOTSOCK\":        ENOTSOCK,\n\t\"EDESTADDRREQ\":    EDESTADDRREQ,\n\t\"EMSGSIZE\":        EMSGSIZE,\n\t\"EPROTOTYPE\":      EPROTOTYPE,\n\t\"ENOPROTOOPT\":     ENOPROTOOPT,\n\t\"EPROTONOSUPPORT\": EPROTONOSUPPORT,\n\t\"ESOCKTNOSUPPORT\": ESOCKTNOSUPPORT,\n\t\"EOPNOTSUPP\":      EOPNOTSUPP,\n\t\"EPFNOSUPPORT\":    EPFNOSUPPORT,\n\t\"EAFNOSUPPORT\":    EAFNOSUPPORT,\n\t\"EADDRINUSE\":      EADDRINUSE,\n\t\"EADDRNOTAVAIL\":   EADDRNOTAVAIL,\n\t\"ENETDOWN\":        ENETDOWN,\n\t\"ENETUNREACH\":     ENETUNREACH,\n\t\"ENETRESET\":       ENETRESET,\n\t\"ECONNABORTED\":    ECONNABORTED,\n\t\"ECONNRESET\":      ECONNRESET,\n\t\"ENOBUFS\":         ENOBUFS,\n\t\"EISCONN\":         EISCONN,\n\t\"ENOTCONN\":        ENOTCONN,\n\t\"ESHUTDOWN\":       ESHUTDOWN,\n\t\"ETOOMANYREFS\":    ETOOMANYREFS,\n\t\"ETIMEDOUT\":       ETIMEDOUT,\n\t\"ECONNREFUSED\":    ECONNREFUSED,\n\t\"EHOSTDOWN\":       EHOSTDOWN,\n\t\"EHOSTUNREACH\":    EHOSTUNREACH,\n\t\"EALREADY\":        EALREADY,\n\t\"EINPROGRESS\":     EINPROGRESS,\n\t\"ESTALE\":          ESTALE,\n\t\"ENOTSUP\":         ENOTSUP,\n\t\"ENOMEDIUM\":       ENOMEDIUM,\n\t\"ECANCELED\":       ECANCELED,\n\t\"ELBIN\":           ELBIN,\n\t\"EFTYPE\":          EFTYPE,\n\t\"ENMFILE\":         ENMFILE,\n\t\"EPROCLIM\":        EPROCLIM,\n\t\"ENOSHARE\":        ENOSHARE,\n\t\"ECASECLASH\":      ECASECLASH,\n\t\"EWOULDBLOCK\":     EWOULDBLOCK,\n}\n"
  },
  {
    "path": "src/testing/benchmark.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n//\n// This file has been modified for use by the TinyGo compiler.\n\npackage testing\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"math\"\n\t\"os\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n)\n\nfunc initBenchmarkFlags() {\n\tmatchBenchmarks = flag.String(\"test.bench\", \"\", \"run only benchmarks matching `regexp`\")\n\tbenchmarkMemory = flag.Bool(\"test.benchmem\", false, \"print memory allocations for benchmarks\")\n\tflag.Var(&benchTime, \"test.benchtime\", \"run each benchmark for duration `d`\")\n}\n\nvar (\n\tmatchBenchmarks *string\n\tbenchmarkMemory *bool\n\tbenchTime       = benchTimeFlag{d: 1 * time.Second} // changed during test of testing package\n)\n\ntype benchTimeFlag struct {\n\td time.Duration\n\tn int\n}\n\nfunc (f *benchTimeFlag) String() string {\n\tif f.n > 0 {\n\t\treturn fmt.Sprintf(\"%dx\", f.n)\n\t}\n\treturn time.Duration(f.d).String()\n}\n\nfunc (f *benchTimeFlag) Set(s string) error {\n\tif strings.HasSuffix(s, \"x\") {\n\t\tn, err := strconv.ParseInt(s[:len(s)-1], 10, 0)\n\t\tif err != nil || n <= 0 {\n\t\t\treturn fmt.Errorf(\"invalid count\")\n\t\t}\n\t\t*f = benchTimeFlag{n: int(n)}\n\t\treturn nil\n\t}\n\td, err := time.ParseDuration(s)\n\tif err != nil || d <= 0 {\n\t\treturn fmt.Errorf(\"invalid duration\")\n\t}\n\t*f = benchTimeFlag{d: d}\n\treturn nil\n}\n\n// InternalBenchmark is an internal type but exported because it is cross-package;\n// it is part of the implementation of the \"go test\" command.\ntype InternalBenchmark struct {\n\tName string\n\tF    func(b *B)\n}\n\n// B is a type passed to Benchmark functions to manage benchmark\n// timing and to specify the number of iterations to run.\n//\n// A benchmark ends when its Benchmark function returns or calls any of the methods\n// FailNow, Fatal, Fatalf, SkipNow, Skip, or Skipf. Those methods must be called\n// only from the goroutine running the Benchmark function.\n// The other reporting methods, such as the variations of Log and Error,\n// may be called simultaneously from multiple goroutines.\n//\n// Like in tests, benchmark logs are accumulated during execution\n// and dumped to standard output when done. Unlike in tests, benchmark logs\n// are always printed, so as not to hide output whose existence may be\n// affecting benchmark results.\ntype B struct {\n\tcommon\n\tcontext      *benchContext\n\tN            int\n\tbenchFunc    func(b *B)\n\tbytes        int64\n\tmissingBytes bool // one of the subbenchmarks does not have bytes set.\n\tbenchTime    benchTimeFlag\n\ttimerOn      bool\n\tresult       BenchmarkResult\n\n\t// report memory statistics\n\tshowAllocResult bool\n\t// initial state of MemStats.Mallocs and MemStats.TotalAlloc\n\tstartAllocs uint64\n\tstartBytes  uint64\n\t// net total after running benchmar\n\tnetAllocs uint64\n\tnetBytes  uint64\n}\n\n// StartTimer starts timing a test. This function is called automatically\n// before a benchmark starts, but it can also be used to resume timing after\n// a call to StopTimer.\nfunc (b *B) StartTimer() {\n\tif !b.timerOn {\n\t\tb.start = time.Now()\n\t\tb.timerOn = true\n\n\t\tvar mstats runtime.MemStats\n\t\truntime.ReadMemStats(&mstats)\n\t\tb.startAllocs = mstats.Mallocs\n\t\tb.startBytes = mstats.TotalAlloc\n\t}\n}\n\n// StopTimer stops timing a test. This can be used to pause the timer\n// while performing complex initialization that you don't\n// want to measure.\nfunc (b *B) StopTimer() {\n\tif b.timerOn {\n\t\tb.duration += time.Since(b.start)\n\t\tb.timerOn = false\n\n\t\tvar mstats runtime.MemStats\n\t\truntime.ReadMemStats(&mstats)\n\t\tb.netAllocs += mstats.Mallocs - b.startAllocs\n\t\tb.netBytes += mstats.TotalAlloc - b.startBytes\n\t}\n}\n\n// ResetTimer zeroes the elapsed benchmark time and memory allocation counters\n// and deletes user-reported metrics.\nfunc (b *B) ResetTimer() {\n\tif b.timerOn {\n\t\tb.start = time.Now()\n\n\t\tvar mstats runtime.MemStats\n\t\truntime.ReadMemStats(&mstats)\n\t\tb.startAllocs = mstats.Mallocs\n\t\tb.startBytes = mstats.TotalAlloc\n\t}\n\tb.duration = 0\n\tb.netAllocs = 0\n\tb.netBytes = 0\n}\n\n// SetBytes records the number of bytes processed in a single operation.\n// If this is called, the benchmark will report ns/op and MB/s.\nfunc (b *B) SetBytes(n int64) { b.bytes = n }\n\n// ReportAllocs enables malloc statistics for this benchmark.\n// It is equivalent to setting -test.benchmem, but it only affects the\n// benchmark function that calls ReportAllocs.\nfunc (b *B) ReportAllocs() {\n\tb.showAllocResult = true\n}\n\n// runN runs a single benchmark for the specified number of iterations.\nfunc (b *B) runN(n int) {\n\tb.N = n\n\truntime.GC()\n\tb.ResetTimer()\n\tb.StartTimer()\n\tb.benchFunc(b)\n\tb.StopTimer()\n}\n\nfunc min(x, y int64) int64 {\n\tif x > y {\n\t\treturn y\n\t}\n\treturn x\n}\n\nfunc max(x, y int64) int64 {\n\tif x < y {\n\t\treturn y\n\t}\n\treturn x\n}\n\n// run1 runs the first iteration of benchFunc. It reports whether more\n// iterations of this benchmarks should be run.\nfunc (b *B) run1() bool {\n\tif ctx := b.context; ctx != nil {\n\t\t// Extend maxLen, if needed.\n\t\tif n := len(b.name); n > ctx.maxLen {\n\t\t\tctx.maxLen = n + 8 // Add additional slack to avoid too many jumps in size.\n\t\t}\n\t}\n\tb.runN(1)\n\treturn !b.hasSub\n}\n\n// run executes the benchmark.\nfunc (b *B) run() {\n\tif b.context != nil {\n\t\t// Running go test --test.bench\n\t\tb.processBench(b.context) // calls doBench and prints results\n\t} else {\n\t\t// Running func Benchmark.\n\t\tb.doBench()\n\t}\n}\n\nfunc (b *B) doBench() BenchmarkResult {\n\t// in upstream, this uses a goroutine\n\tb.launch()\n\treturn b.result\n}\n\n// launch launches the benchmark function. It gradually increases the number\n// of benchmark iterations until the benchmark runs for the requested benchtime.\n// run1 must have been called on b.\nfunc (b *B) launch() {\n\t// Run the benchmark for at least the specified amount of time.\n\tif b.benchTime.n > 0 {\n\t\tb.runN(b.benchTime.n)\n\t} else {\n\t\td := b.benchTime.d\n\t\tb.failed = false\n\t\tb.duration = 0\n\t\tfor n := int64(1); !b.failed && b.duration < d && n < 1e9; {\n\t\t\tlast := n\n\t\t\t// Predict required iterations.\n\t\t\tgoalns := d.Nanoseconds()\n\t\t\tprevIters := int64(b.N)\n\t\t\tprevns := b.duration.Nanoseconds()\n\t\t\tif prevns <= 0 {\n\t\t\t\t// Round up, to avoid div by zero.\n\t\t\t\tprevns = 1\n\t\t\t}\n\t\t\t// Order of operations matters.\n\t\t\t// For very fast benchmarks, prevIters ~= prevns.\n\t\t\t// If you divide first, you get 0 or 1,\n\t\t\t// which can hide an order of magnitude in execution time.\n\t\t\t// So multiply first, then divide.\n\t\t\tn = goalns * prevIters / prevns\n\t\t\t// Run more iterations than we think we'll need (1.2x).\n\t\t\tn += n / 5\n\t\t\t// Don't grow too fast in case we had timing errors previously.\n\t\t\tn = min(n, 100*last)\n\t\t\t// Be sure to run at least one more than last time.\n\t\t\tn = max(n, last+1)\n\t\t\t// Don't run more than 1e9 times. (This also keeps n in int range on 32 bit platforms.)\n\t\t\tn = min(n, 1e9)\n\t\t\tb.runN(int(n))\n\t\t}\n\t}\n\tb.result = BenchmarkResult{b.N, b.duration, b.bytes, b.netAllocs, b.netBytes}\n}\n\n// BenchmarkResult contains the results of a benchmark run.\ntype BenchmarkResult struct {\n\tN     int           // The number of iterations.\n\tT     time.Duration // The total time taken.\n\tBytes int64         // Bytes processed in one iteration.\n\n\tMemAllocs uint64 // The total number of memory allocations.\n\tMemBytes  uint64 // The total number of bytes allocated.\n}\n\n// NsPerOp returns the \"ns/op\" metric.\nfunc (r BenchmarkResult) NsPerOp() int64 {\n\tif r.N <= 0 {\n\t\treturn 0\n\t}\n\treturn r.T.Nanoseconds() / int64(r.N)\n}\n\n// mbPerSec returns the \"MB/s\" metric.\nfunc (r BenchmarkResult) mbPerSec() float64 {\n\tif r.Bytes <= 0 || r.T <= 0 || r.N <= 0 {\n\t\treturn 0\n\t}\n\treturn (float64(r.Bytes) * float64(r.N) / 1e6) / r.T.Seconds()\n}\n\n// AllocsPerOp returns the \"allocs/op\" metric,\n// which is calculated as r.MemAllocs / r.N.\nfunc (r BenchmarkResult) AllocsPerOp() int64 {\n\tif r.N <= 0 {\n\t\treturn 0\n\t}\n\treturn int64(r.MemAllocs) / int64(r.N)\n}\n\n// AllocedBytesPerOp returns the \"B/op\" metric,\n// which is calculated as r.MemBytes / r.N.\nfunc (r BenchmarkResult) AllocedBytesPerOp() int64 {\n\tif r.N <= 0 {\n\t\treturn 0\n\t}\n\treturn int64(r.MemBytes) / int64(r.N)\n}\n\n// String returns a summary of the benchmark results.\n// It follows the benchmark result line format from\n// https://golang.org/design/14313-benchmark-format, not including the\n// benchmark name.\n// Extra metrics override built-in metrics of the same name.\n// String does not include allocs/op or B/op, since those are reported\n// by MemString.\nfunc (r BenchmarkResult) String() string {\n\tbuf := new(strings.Builder)\n\tfmt.Fprintf(buf, \"%8d\", r.N)\n\n\t// Get ns/op as a float.\n\tns := float64(r.T.Nanoseconds()) / float64(r.N)\n\tif ns != 0 {\n\t\tbuf.WriteByte('\\t')\n\t\tprettyPrint(buf, ns, \"ns/op\")\n\t}\n\n\tif mbs := r.mbPerSec(); mbs != 0 {\n\t\tfmt.Fprintf(buf, \"\\t%7.2f MB/s\", mbs)\n\t}\n\treturn buf.String()\n}\n\n// MemString returns r.AllocedBytesPerOp and r.AllocsPerOp in the same format as 'go test'.\nfunc (r BenchmarkResult) MemString() string {\n\treturn fmt.Sprintf(\"%8d B/op\\t%8d allocs/op\",\n\t\tr.AllocedBytesPerOp(), r.AllocsPerOp())\n}\n\nfunc prettyPrint(w io.Writer, x float64, unit string) {\n\t// Print all numbers with 10 places before the decimal point\n\t// and small numbers with four sig figs. Field widths are\n\t// chosen to fit the whole part in 10 places while aligning\n\t// the decimal point of all fractional formats.\n\tvar format string\n\tswitch y := math.Abs(x); {\n\tcase y == 0 || y >= 999.95:\n\t\tformat = \"%10.0f %s\"\n\tcase y >= 99.995:\n\t\tformat = \"%12.1f %s\"\n\tcase y >= 9.9995:\n\t\tformat = \"%13.2f %s\"\n\tcase y >= 0.99995:\n\t\tformat = \"%14.3f %s\"\n\tcase y >= 0.099995:\n\t\tformat = \"%15.4f %s\"\n\tcase y >= 0.0099995:\n\t\tformat = \"%16.5f %s\"\n\tcase y >= 0.00099995:\n\t\tformat = \"%17.6f %s\"\n\tdefault:\n\t\tformat = \"%18.7f %s\"\n\t}\n\tfmt.Fprintf(w, format, x, unit)\n}\n\ntype benchContext struct {\n\tmatch *matcher\n\n\tmaxLen int // The largest recorded benchmark name.\n}\n\nfunc runBenchmarks(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark) bool {\n\t// If no flag was specified, don't run benchmarks.\n\tif len(*matchBenchmarks) == 0 {\n\t\treturn true\n\t}\n\tctx := &benchContext{\n\t\tmatch: newMatcher(matchString, *matchBenchmarks, \"-test.bench\", flagSkipRegexp),\n\t}\n\tvar bs []InternalBenchmark\n\tfor _, Benchmark := range benchmarks {\n\t\tif _, matched, _ := ctx.match.fullName(nil, Benchmark.Name); matched {\n\t\t\tbs = append(bs, Benchmark)\n\t\t\tbenchName := Benchmark.Name\n\t\t\tif l := len(benchName); l > ctx.maxLen {\n\t\t\t\tctx.maxLen = l\n\t\t\t}\n\t\t}\n\t}\n\tmain := &B{\n\t\tcommon: common{\n\t\t\toutput: &logger{},\n\t\t\tname:   \"Main\",\n\t\t},\n\t\tbenchTime: benchTime,\n\t\tbenchFunc: func(b *B) {\n\t\t\tfor _, Benchmark := range bs {\n\t\t\t\tb.Run(Benchmark.Name, Benchmark.F)\n\t\t\t}\n\t\t},\n\t\tcontext: ctx,\n\t}\n\n\tmain.runN(1)\n\treturn true\n}\n\n// processBench runs bench b and prints the results.\nfunc (b *B) processBench(ctx *benchContext) {\n\tbenchName := b.name\n\n\tfor i := 0; i < flagCount; i++ {\n\t\tif ctx != nil {\n\t\t\tfmt.Printf(\"%-*s\\t\", ctx.maxLen, benchName)\n\t\t}\n\t\tr := b.doBench()\n\t\tif b.failed {\n\t\t\t// The output could be very long here, but probably isn't.\n\t\t\t// We print it all, regardless, because we don't want to trim the reason\n\t\t\t// the benchmark failed.\n\t\t\tfmt.Printf(\"--- FAIL: %s\\n%s\", benchName, \"\") // b.output)\n\t\t\treturn\n\t\t}\n\t\tif ctx != nil {\n\t\t\tresults := r.String()\n\n\t\t\tif *benchmarkMemory || b.showAllocResult {\n\t\t\t\tresults += \"\\t\" + r.MemString()\n\t\t\t}\n\t\t\tfmt.Println(results)\n\n\t\t\t// Print any benchmark output\n\t\t\tif b.output.Len() > 0 {\n\t\t\t\tfmt.Printf(\"--- BENCH: %s\\n\", benchName)\n\t\t\t\tb.output.WriteTo(os.Stdout)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Run benchmarks f as a subbenchmark with the given name. It reports\n// true if the subbenchmark succeeded.\n//\n// A subbenchmark is like any other benchmark. A benchmark that calls Run at\n// least once will not be measured itself and will be called once with N=1.\nfunc (b *B) Run(name string, f func(b *B)) bool {\n\tbenchName, ok, partial := b.name, true, false\n\tif b.context != nil {\n\t\tbenchName, ok, partial = b.context.match.fullName(&b.common, name)\n\t}\n\tif !ok {\n\t\treturn true\n\t}\n\tb.hasSub = true\n\tsub := &B{\n\t\tcommon: common{\n\t\t\toutput: &logger{},\n\t\t\tname:   benchName,\n\t\t\tlevel:  b.level + 1,\n\t\t},\n\t\tbenchFunc: f,\n\t\tbenchTime: b.benchTime,\n\t\tcontext:   b.context,\n\t}\n\tif partial {\n\t\t// Partial name match, like -bench=X/Y matching BenchmarkX.\n\t\t// Only process sub-benchmarks, if any.\n\t\tsub.hasSub = true\n\t}\n\tif sub.run1() {\n\t\tsub.run()\n\t}\n\tb.add(sub.result)\n\treturn !sub.failed\n}\n\n// add simulates running benchmarks in sequence in a single iteration. It is\n// used to give some meaningful results in case func Benchmark is used in\n// combination with Run.\nfunc (b *B) add(other BenchmarkResult) {\n\tr := &b.result\n\t// The aggregated BenchmarkResults resemble running all subbenchmarks as\n\t// in sequence in a single benchmark.\n\tr.N = 1\n\tr.T += time.Duration(other.NsPerOp())\n\tif other.Bytes == 0 {\n\t\t// Summing Bytes is meaningless in aggregate if not all subbenchmarks\n\t\t// set it.\n\t\tb.missingBytes = true\n\t\tr.Bytes = 0\n\t}\n\tif !b.missingBytes {\n\t\tr.Bytes += other.Bytes\n\t}\n}\n\n// A PB is used by RunParallel for running parallel benchmarks.\ntype PB struct {\n}\n\n// Next reports whether there are more iterations to execute.\nfunc (pb *PB) Next() bool {\n\treturn false\n}\n\n// RunParallel runs a benchmark in parallel.\n//\n// Not implemented\nfunc (b *B) RunParallel(body func(*PB)) {\n\treturn\n}\n\nfunc (b *B) Loop() bool {\n\tpanic(\"unimplemented: testing.B.Loop\")\n}\n\n// Benchmark benchmarks a single function. It is useful for creating\n// custom benchmarks that do not use the \"go test\" command.\n//\n// If f calls Run, the result will be an estimate of running all its\n// subbenchmarks that don't call Run in sequence in a single benchmark.\nfunc Benchmark(f func(b *B)) BenchmarkResult {\n\tb := &B{\n\t\tbenchFunc: f,\n\t\tbenchTime: benchTime,\n\t}\n\tif b.run1() {\n\t\tb.run()\n\t}\n\treturn b.result\n}\n"
  },
  {
    "path": "src/testing/benchmark_test.go",
    "content": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage testing_test\n\nimport (\n\t\"testing\"\n)\n\nvar buf = make([]byte, 13579)\n\nfunc NonASCII(b []byte, i int, offset int) int {\n\tfor i = offset; i < len(b)+offset; i++ {\n\t\tif b[i%len(b)] >= 0x80 {\n\t\t\tbreak\n\t\t}\n\t}\n\treturn i\n}\n\nfunc BenchmarkFastNonASCII(b *testing.B) {\n\tvar val int\n\tfor i := 0; i < b.N; i++ {\n\t\tval += NonASCII(buf, 0, 0)\n\t}\n}\n\nfunc BenchmarkSlowNonASCII(b *testing.B) {\n\tvar val int\n\tfor i := 0; i < b.N; i++ {\n\t\tval += NonASCII(buf, 0, 0)\n\t\tval += NonASCII(buf, 0, 1)\n\t}\n}\n\n// TestBenchmark simply uses Benchmark twice and makes sure it does not crash.\nfunc TestBenchmark(t *testing.T) {\n\t// FIXME: reduce runtime from the current 3 seconds.\n\trslow := testing.Benchmark(BenchmarkSlowNonASCII)\n\trfast := testing.Benchmark(BenchmarkFastNonASCII)\n\ttslow := rslow.NsPerOp()\n\ttfast := rfast.NsPerOp()\n\n\t// Be exceedingly forgiving; do not fail even if system gets busy.\n\tspeedup := float64(tslow) / float64(tfast)\n\tif speedup < 0.3 {\n\t\tt.Errorf(\"Expected speedup >= 0.3, got %f\", speedup)\n\t}\n}\n\nfunc BenchmarkSub(b *testing.B) {\n\tb.Run(\"Fast\", func(b *testing.B) { BenchmarkFastNonASCII(b) })\n\tb.Run(\"Slow\", func(b *testing.B) { BenchmarkSlowNonASCII(b) })\n}\n"
  },
  {
    "path": "src/testing/doc.go",
    "content": "package testing\n\n/*\n This is a sad stub of the upstream testing package because it doesn't compile\n with tinygo right now.\n*/\n"
  },
  {
    "path": "src/testing/fuzz.go",
    "content": "package testing\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"time\"\n)\n\n// InternalFuzzTarget is an internal type but exported because it is\n// cross-package; it is part of the implementation of the \"go test\" command.\ntype InternalFuzzTarget struct {\n\tName string\n\tFn   func(f *F)\n}\n\n// F is a type passed to fuzz tests.\n//\n// Fuzz tests run generated inputs against a provided fuzz target, which can\n// find and report potential bugs in the code being tested.\n//\n// A fuzz test runs the seed corpus by default, which includes entries provided\n// by (*F).Add and entries in the testdata/fuzz/<FuzzTestName> directory. After\n// any necessary setup and calls to (*F).Add, the fuzz test must then call\n// (*F).Fuzz to provide the fuzz target. See the testing package documentation\n// for an example, and see the F.Fuzz and F.Add method documentation for\n// details.\n//\n// *F methods can only be called before (*F).Fuzz. Once the test is\n// executing the fuzz target, only (*T) methods can be used. The only *F methods\n// that are allowed in the (*F).Fuzz function are (*F).Failed and (*F).Name.\ntype F struct {\n\tcommon\n\tfuzzContext *fuzzContext\n\ttestContext *testContext\n\n\t// inFuzzFn is true when the fuzz function is running. Most F methods cannot\n\t// be called when inFuzzFn is true.\n\tinFuzzFn bool\n\n\t// corpus is a set of seed corpus entries, added with F.Add and loaded\n\t// from testdata.\n\tcorpus []corpusEntry\n\n\tresult     fuzzResult\n\tfuzzCalled bool\n}\n\n// corpusEntry is an alias to the same type as internal/fuzz.CorpusEntry.\n// We use a type alias because we don't want to export this type, and we can't\n// import internal/fuzz from testing.\ntype corpusEntry = struct {\n\tParent     string\n\tPath       string\n\tData       []byte\n\tValues     []interface{}\n\tGeneration int\n\tIsSeed     bool\n}\n\n// Add will add the arguments to the seed corpus for the fuzz test. This will be\n// a no-op if called after or within the fuzz target, and args must match the\n// arguments for the fuzz target.\nfunc (f *F) Add(args ...interface{}) {\n\tvar values []interface{}\n\tfor i := range args {\n\t\tif t := reflect.TypeOf(args[i]); !supportedTypes[t] {\n\t\t\tpanic(fmt.Sprintf(\"testing: unsupported type to Add %v\", t))\n\t\t}\n\t\tvalues = append(values, args[i])\n\t}\n\tf.corpus = append(f.corpus, corpusEntry{Values: values, IsSeed: true, Path: fmt.Sprintf(\"seed#%d\", len(f.corpus))})\n}\n\n// supportedTypes represents all of the supported types which can be fuzzed.\nvar supportedTypes = map[reflect.Type]bool{\n\treflect.TypeOf(([]byte)(\"\")):  true,\n\treflect.TypeOf((string)(\"\")):  true,\n\treflect.TypeOf((bool)(false)): true,\n\treflect.TypeOf((byte)(0)):     true,\n\treflect.TypeOf((rune)(0)):     true,\n\treflect.TypeOf((float32)(0)):  true,\n\treflect.TypeOf((float64)(0)):  true,\n\treflect.TypeOf((int)(0)):      true,\n\treflect.TypeOf((int8)(0)):     true,\n\treflect.TypeOf((int16)(0)):    true,\n\treflect.TypeOf((int32)(0)):    true,\n\treflect.TypeOf((int64)(0)):    true,\n\treflect.TypeOf((uint)(0)):     true,\n\treflect.TypeOf((uint8)(0)):    true,\n\treflect.TypeOf((uint16)(0)):   true,\n\treflect.TypeOf((uint32)(0)):   true,\n\treflect.TypeOf((uint64)(0)):   true,\n}\n\n// Fuzz runs the fuzz function, ff, for fuzz testing. If ff fails for a set of\n// arguments, those arguments will be added to the seed corpus.\n//\n// ff must be a function with no return value whose first argument is *T and\n// whose remaining arguments are the types to be fuzzed.\n// For example:\n//\n//\tf.Fuzz(func(t *testing.T, b []byte, i int) { ... })\n//\n// The following types are allowed: []byte, string, bool, byte, rune, float32,\n// float64, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64.\n// More types may be supported in the future.\n//\n// ff must not call any *F methods, e.g. (*F).Log, (*F).Error, (*F).Skip. Use\n// the corresponding *T method instead. The only *F methods that are allowed in\n// the (*F).Fuzz function are (*F).Failed and (*F).Name.\n//\n// This function should be fast and deterministic, and its behavior should not\n// depend on shared state. No mutatable input arguments, or pointers to them,\n// should be retained between executions of the fuzz function, as the memory\n// backing them may be mutated during a subsequent invocation. ff must not\n// modify the underlying data of the arguments provided by the fuzzing engine.\n//\n// When fuzzing, F.Fuzz does not return until a problem is found, time runs out\n// (set with -fuzztime), or the test process is interrupted by a signal. F.Fuzz\n// should be called exactly once, unless F.Skip or F.Fail is called beforehand.\nfunc (f *F) Fuzz(ff interface{}) {\n\tf.failed = true\n\tf.result.N = 0\n\tf.result.T = 0\n\tf.result.Error = errors.New(\"operation not implemented\")\n\treturn\n}\n\n// fuzzContext holds fields common to all fuzz tests.\ntype fuzzContext struct {\n\tdeps testDeps\n\tmode fuzzMode\n}\n\ntype fuzzMode uint8\n\n// fuzzResult contains the results of a fuzz run.\ntype fuzzResult struct {\n\tN     int           // The number of iterations.\n\tT     time.Duration // The total time taken.\n\tError error         // Error is the error from the failing input\n}\n"
  },
  {
    "path": "src/testing/is_baremetal.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n//\n//go:build baremetal\n\npackage testing\n\nconst isBaremetal = true\n"
  },
  {
    "path": "src/testing/is_not_baremetal.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n//\n//go:build !baremetal\n\npackage testing\n\nconst isBaremetal = false\n"
  },
  {
    "path": "src/testing/match.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage testing\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n)\n\n// matcher sanitizes, uniques, and filters names of subtests and subbenchmarks.\ntype matcher struct {\n\tfilter    filterMatch\n\tskip      filterMatch\n\tmatchFunc func(pat, str string) (bool, error)\n\n\tmu sync.Mutex\n\n\t// subNames is used to deduplicate subtest names.\n\t// Each key is the subtest name joined to the deduplicated name of the parent test.\n\t// Each value is the count of the number of occurrences of the given subtest name\n\t// already seen.\n\tsubNames map[string]int32\n}\n\ntype filterMatch interface {\n\t// matches checks the name against the receiver's pattern strings using the\n\t// given match function.\n\tmatches(name []string, matchString func(pat, str string) (bool, error)) (ok, partial bool)\n\n\t// verify checks that the receiver's pattern strings are valid filters by\n\t// calling the given match function.\n\tverify(name string, matchString func(pat, str string) (bool, error)) error\n}\n\n// simpleMatch matches a test name if all of the pattern strings match in\n// sequence.\ntype simpleMatch []string\n\n// alternationMatch matches a test name if one of the alternations match.\ntype alternationMatch []filterMatch\n\n// TODO: fix test_main to avoid race and improve caching, also allowing to\n// eliminate this Mutex.\nvar matchMutex sync.Mutex\n\nfunc allMatcher() *matcher {\n\treturn newMatcher(nil, \"\", \"\", \"\")\n}\n\nfunc newMatcher(matchString func(pat, str string) (bool, error), patterns, name, skips string) *matcher {\n\tif isBaremetal {\n\t\tmatchString = fakeMatchString\n\t}\n\n\tvar filter, skip filterMatch\n\tif patterns == \"\" {\n\t\tfilter = simpleMatch{} // always partial true\n\t} else {\n\t\tfilter = splitRegexp(patterns)\n\t\tif err := filter.verify(name, matchString); err != nil {\n\t\t\tfmt.Fprintf(os.Stderr, \"testing: invalid regexp for %s\\n\", err)\n\t\t\tos.Exit(1)\n\t\t}\n\t}\n\tif skips == \"\" {\n\t\tskip = alternationMatch{} // always false\n\t} else {\n\t\tskip = splitRegexp(skips)\n\t\tif err := skip.verify(\"-test.skip\", matchString); err != nil {\n\t\t\tfmt.Fprintf(os.Stderr, \"testing: invalid regexp for %v\\n\", err)\n\t\t\tos.Exit(1)\n\t\t}\n\t}\n\treturn &matcher{\n\t\tfilter:    filter,\n\t\tskip:      skip,\n\t\tmatchFunc: matchString,\n\t\tsubNames:  map[string]int32{},\n\t}\n}\n\nfunc (m *matcher) fullName(c *common, subname string) (name string, ok, partial bool) {\n\tname = subname\n\n\tm.mu.Lock()\n\tdefer m.mu.Unlock()\n\n\tif c != nil && c.level > 0 {\n\t\tname = m.unique(c.name, rewrite(subname))\n\t}\n\n\tmatchMutex.Lock()\n\tdefer matchMutex.Unlock()\n\n\t// We check the full array of paths each time to allow for the case that a pattern contains a '/'.\n\telem := strings.Split(name, \"/\")\n\n\t// filter must match.\n\t// accept partial match that may produce full match later.\n\tok, partial = m.filter.matches(elem, m.matchFunc)\n\tif !ok {\n\t\treturn name, false, false\n\t}\n\n\t// skip must not match.\n\t// ignore partial match so we can get to more precise match later.\n\tskip, partialSkip := m.skip.matches(elem, m.matchFunc)\n\tif skip && !partialSkip {\n\t\treturn name, false, false\n\t}\n\n\treturn name, ok, partial\n}\n\n// clearSubNames clears the matcher's internal state, potentially freeing\n// memory. After this is called, T.Name may return the same strings as it did\n// for earlier subtests.\nfunc (m *matcher) clearSubNames() {\n\tm.mu.Lock()\n\tdefer m.mu.Unlock()\n\tfor key := range m.subNames {\n\t\tdelete(m.subNames, key)\n\t}\n}\n\nfunc (m simpleMatch) matches(name []string, matchString func(pat, str string) (bool, error)) (ok, partial bool) {\n\tfor i, s := range name {\n\t\tif i >= len(m) {\n\t\t\tbreak\n\t\t}\n\t\tif ok, _ := matchString(m[i], s); !ok {\n\t\t\treturn false, false\n\t\t}\n\t}\n\treturn true, len(name) < len(m)\n}\n\nfunc (m simpleMatch) verify(name string, matchString func(pat, str string) (bool, error)) error {\n\tfor i, s := range m {\n\t\tm[i] = rewrite(s)\n\t}\n\t// Verify filters before doing any processing.\n\tfor i, s := range m {\n\t\tif _, err := matchString(s, \"non-empty\"); err != nil {\n\t\t\treturn fmt.Errorf(\"element %d of %s (%q): %s\", i, name, s, err)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (m alternationMatch) matches(name []string, matchString func(pat, str string) (bool, error)) (ok, partial bool) {\n\tfor _, m := range m {\n\t\tif ok, partial = m.matches(name, matchString); ok {\n\t\t\treturn ok, partial\n\t\t}\n\t}\n\treturn false, false\n}\n\nfunc (m alternationMatch) verify(name string, matchString func(pat, str string) (bool, error)) error {\n\tfor i, m := range m {\n\t\tif err := m.verify(name, matchString); err != nil {\n\t\t\treturn fmt.Errorf(\"alternation %d of %s\", i, err)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc splitRegexp(s string) filterMatch {\n\ta := make(simpleMatch, 0, strings.Count(s, \"/\"))\n\tb := make(alternationMatch, 0, strings.Count(s, \"|\"))\n\tcs := 0\n\tcp := 0\n\tfor i := 0; i < len(s); {\n\t\tswitch s[i] {\n\t\tcase '[':\n\t\t\tcs++\n\t\tcase ']':\n\t\t\tif cs--; cs < 0 { // An unmatched ']' is legal.\n\t\t\t\tcs = 0\n\t\t\t}\n\t\tcase '(':\n\t\t\tif cs == 0 {\n\t\t\t\tcp++\n\t\t\t}\n\t\tcase ')':\n\t\t\tif cs == 0 {\n\t\t\t\tcp--\n\t\t\t}\n\t\tcase '\\\\':\n\t\t\ti++\n\t\tcase '/':\n\t\t\tif cs == 0 && cp == 0 {\n\t\t\t\ta = append(a, s[:i])\n\t\t\t\ts = s[i+1:]\n\t\t\t\ti = 0\n\t\t\t\tcontinue\n\t\t\t}\n\t\tcase '|':\n\t\t\tif cs == 0 && cp == 0 {\n\t\t\t\ta = append(a, s[:i])\n\t\t\t\ts = s[i+1:]\n\t\t\t\ti = 0\n\t\t\t\tb = append(b, a)\n\t\t\t\ta = make(simpleMatch, 0, len(a))\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\ti++\n\t}\n\n\ta = append(a, s)\n\tif len(b) == 0 {\n\t\treturn a\n\t}\n\treturn append(b, a)\n}\n\n// unique creates a unique name for the given parent and subname by affixing it\n// with one or more counts, if necessary.\nfunc (m *matcher) unique(parent, subname string) string {\n\tbase := parent + \"/\" + subname\n\n\tfor {\n\t\tn := m.subNames[base]\n\t\tif n < 0 {\n\t\t\tpanic(\"subtest count overflow\")\n\t\t}\n\t\tm.subNames[base] = n + 1\n\n\t\tif n == 0 && subname != \"\" {\n\t\t\tprefix, nn := parseSubtestNumber(base)\n\t\t\tif len(prefix) < len(base) && nn < m.subNames[prefix] {\n\t\t\t\t// This test is explicitly named like \"parent/subname#NN\",\n\t\t\t\t// and #NN was already used for the NNth occurrence of \"parent/subname\".\n\t\t\t\t// Loop to add a disambiguating suffix.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn base\n\t\t}\n\n\t\tname := fmt.Sprintf(\"%s#%02d\", base, n)\n\t\tif m.subNames[name] != 0 {\n\t\t\t// This is the nth occurrence of base, but the name \"parent/subname#NN\"\n\t\t\t// collides with the first occurrence of a subtest *explicitly* named\n\t\t\t// \"parent/subname#NN\". Try the next number.\n\t\t\tcontinue\n\t\t}\n\n\t\treturn name\n\t}\n}\n\n// parseSubtestNumber splits a subtest name into a \"#%02d\"-formatted int32\n// suffix (if present), and a prefix preceding that suffix (always).\nfunc parseSubtestNumber(s string) (prefix string, nn int32) {\n\ti := strings.LastIndex(s, \"#\")\n\tif i < 0 {\n\t\treturn s, 0\n\t}\n\n\tprefix, suffix := s[:i], s[i+1:]\n\tif len(suffix) < 2 || (len(suffix) > 2 && suffix[0] == '0') {\n\t\t// Even if suffix is numeric, it is not a possible output of a \"%02\" format\n\t\t// string: it has either too few digits or too many leading zeroes.\n\t\treturn s, 0\n\t}\n\tif suffix == \"00\" {\n\t\tif !strings.HasSuffix(prefix, \"/\") {\n\t\t\t// We only use \"#00\" as a suffix for subtests named with the empty\n\t\t\t// string — it isn't a valid suffix if the subtest name is non-empty.\n\t\t\treturn s, 0\n\t\t}\n\t}\n\n\tn, err := strconv.ParseInt(suffix, 10, 32)\n\tif err != nil || n < 0 {\n\t\treturn s, 0\n\t}\n\treturn prefix, int32(n)\n}\n\n// rewrite rewrites a subname to having only printable characters and no white\n// space.\nfunc rewrite(s string) string {\n\tb := []byte{}\n\tfor _, r := range s {\n\t\tswitch {\n\t\tcase isSpace(r):\n\t\t\tb = append(b, '_')\n\t\tcase !strconv.IsPrint(r):\n\t\t\ts := strconv.QuoteRune(r)\n\t\t\tb = append(b, s[1:len(s)-1]...)\n\t\tdefault:\n\t\t\tb = append(b, string(r)...)\n\t\t}\n\t}\n\treturn string(b)\n}\n\nfunc isSpace(r rune) bool {\n\tif r < 0x2000 {\n\t\tswitch r {\n\t\t// Note: not the same as Unicode Z class.\n\t\tcase '\\t', '\\n', '\\v', '\\f', '\\r', ' ', 0x85, 0xA0, 0x1680:\n\t\t\treturn true\n\t\t}\n\t} else {\n\t\tif r <= 0x200a {\n\t\t\treturn true\n\t\t}\n\t\tswitch r {\n\t\tcase 0x2028, 0x2029, 0x202f, 0x205f, 0x3000:\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "src/testing/match_test.go",
    "content": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage testing\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"strings\"\n\t\"unicode\"\n)\n\n// Verify that our IsSpace agrees with unicode.IsSpace.\nfunc TestIsSpace(t *T) {\n\tn := 0\n\tfor r := rune(0); r <= unicode.MaxRune; r++ {\n\t\tif isSpace(r) != unicode.IsSpace(r) {\n\t\t\tt.Errorf(\"IsSpace(%U)=%t incorrect\", r, isSpace(r))\n\t\t\tn++\n\t\t\tif n > 10 {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestSplitRegexp(t *T) {\n\tres := func(s ...string) filterMatch { return simpleMatch(s) }\n\talt := func(m ...filterMatch) filterMatch { return alternationMatch(m) }\n\ttestCases := []struct {\n\t\tpattern string\n\t\tresult  filterMatch\n\t}{\n\t\t// Correct patterns\n\t\t// If a regexp pattern is correct, all split regexps need to be correct\n\t\t// as well.\n\t\t{\"\", res(\"\")},\n\t\t{\"/\", res(\"\", \"\")},\n\t\t{\"//\", res(\"\", \"\", \"\")},\n\t\t{\"A\", res(\"A\")},\n\t\t{\"A/B\", res(\"A\", \"B\")},\n\t\t{\"A/B/\", res(\"A\", \"B\", \"\")},\n\t\t{\"/A/B/\", res(\"\", \"A\", \"B\", \"\")},\n\t\t{\"[A]/(B)\", res(\"[A]\", \"(B)\")},\n\t\t{\"[/]/[/]\", res(\"[/]\", \"[/]\")},\n\t\t{\"[/]/[:/]\", res(\"[/]\", \"[:/]\")},\n\t\t{\"/]\", res(\"\", \"]\")},\n\t\t{\"]/\", res(\"]\", \"\")},\n\t\t{\"]/[/]\", res(\"]\", \"[/]\")},\n\t\t{`([)/][(])`, res(`([)/][(])`)},\n\t\t{\"[(]/[)]\", res(\"[(]\", \"[)]\")},\n\n\t\t{\"A/B|C/D\", alt(res(\"A\", \"B\"), res(\"C\", \"D\"))},\n\n\t\t// Faulty patterns\n\t\t// Errors in original should produce at least one faulty regexp in results.\n\t\t{\")/\", res(\")/\")},\n\t\t{\")/(/)\", res(\")/(\", \")\")},\n\t\t{\"a[/)b\", res(\"a[/)b\")},\n\t\t{\"(/]\", res(\"(/]\")},\n\t\t{\"(/\", res(\"(/\")},\n\t\t{\"[/]/[/\", res(\"[/]\", \"[/\")},\n\t\t{`\\p{/}`, res(`\\p{`, \"}\")},\n\t\t{`\\p/`, res(`\\p`, \"\")},\n\t\t{`[[:/:]]`, res(`[[:/:]]`)},\n\t}\n\tfor _, tc := range testCases {\n\t\ta := splitRegexp(tc.pattern)\n\t\tif !reflect.DeepEqual(a, tc.result) {\n\t\t\tt.Errorf(\"splitRegexp(%q) = %#v; want %#v\", tc.pattern, a, tc.result)\n\t\t}\n\n\t\t// If there is any error in the pattern, one of the returned subpatterns\n\t\t// needs to have an error as well.\n\t\tif _, err := regexp.Compile(tc.pattern); err != nil {\n\t\t\tok := true\n\t\t\tif err := a.verify(\"\", regexp.MatchString); err != nil {\n\t\t\t\tok = false\n\t\t\t}\n\t\t\tif ok {\n\t\t\t\tt.Errorf(\"%s: expected error in any of %q\", tc.pattern, a)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestMatcher(t *T) {\n\ttestCases := []struct {\n\t\tpattern     string\n\t\tskip        string\n\t\tparent, sub string\n\t\tok          bool\n\t\tpartial     bool\n\t}{\n\t\t// Behavior without subtests.\n\t\t{\"\", \"\", \"\", \"TestFoo\", true, false},\n\t\t{\"TestFoo\", \"\", \"\", \"TestFoo\", true, false},\n\t\t{\"TestFoo/\", \"\", \"\", \"TestFoo\", true, true},\n\t\t{\"TestFoo/bar/baz\", \"\", \"\", \"TestFoo\", true, true},\n\t\t{\"TestFoo\", \"\", \"\", \"TestBar\", false, false},\n\t\t{\"TestFoo/\", \"\", \"\", \"TestBar\", false, false},\n\t\t{\"TestFoo/bar/baz\", \"\", \"\", \"TestBar/bar/baz\", false, false},\n\t\t{\"\", \"TestBar\", \"\", \"TestFoo\", true, false},\n\t\t{\"\", \"TestBar\", \"\", \"TestBar\", false, false},\n\n\t\t// Skipping a non-existent test doesn't change anything.\n\t\t{\"\", \"TestFoo/skipped\", \"\", \"TestFoo\", true, false},\n\t\t{\"TestFoo\", \"TestFoo/skipped\", \"\", \"TestFoo\", true, false},\n\t\t{\"TestFoo/\", \"TestFoo/skipped\", \"\", \"TestFoo\", true, true},\n\t\t{\"TestFoo/bar/baz\", \"TestFoo/skipped\", \"\", \"TestFoo\", true, true},\n\t\t{\"TestFoo\", \"TestFoo/skipped\", \"\", \"TestBar\", false, false},\n\t\t{\"TestFoo/\", \"TestFoo/skipped\", \"\", \"TestBar\", false, false},\n\t\t{\"TestFoo/bar/baz\", \"TestFoo/skipped\", \"\", \"TestBar/bar/baz\", false, false},\n\n\t\t// with subtests\n\t\t{\"\", \"\", \"TestFoo\", \"x\", true, false},\n\t\t{\"TestFoo\", \"\", \"TestFoo\", \"x\", true, false},\n\t\t{\"TestFoo/\", \"\", \"TestFoo\", \"x\", true, false},\n\t\t{\"TestFoo/bar/baz\", \"\", \"TestFoo\", \"bar\", true, true},\n\n\t\t{\"\", \"TestFoo/skipped\", \"TestFoo\", \"x\", true, false},\n\t\t{\"TestFoo\", \"TestFoo/skipped\", \"TestFoo\", \"x\", true, false},\n\t\t{\"TestFoo\", \"TestFoo/skipped\", \"TestFoo\", \"skipped\", false, false},\n\t\t{\"TestFoo/\", \"TestFoo/skipped\", \"TestFoo\", \"x\", true, false},\n\t\t{\"TestFoo/bar/baz\", \"TestFoo/skipped\", \"TestFoo\", \"bar\", true, true},\n\n\t\t// Subtest with a '/' in its name still allows for copy and pasted names\n\t\t// to match.\n\t\t{\"TestFoo/bar/baz\", \"\", \"TestFoo\", \"bar/baz\", true, false},\n\t\t{\"TestFoo/bar/baz\", \"TestFoo/bar/baz\", \"TestFoo\", \"bar/baz\", false, false},\n\t\t{\"TestFoo/bar/baz\", \"TestFoo/bar/baz/skip\", \"TestFoo\", \"bar/baz\", true, false},\n\t\t{\"TestFoo/bar/baz\", \"\", \"TestFoo/bar\", \"baz\", true, false},\n\t\t{\"TestFoo/bar/baz\", \"\", \"TestFoo\", \"x\", false, false},\n\t\t{\"TestFoo\", \"\", \"TestBar\", \"x\", false, false},\n\t\t{\"TestFoo/\", \"\", \"TestBar\", \"x\", false, false},\n\t\t{\"TestFoo/bar/baz\", \"\", \"TestBar\", \"x/bar/baz\", false, false},\n\n\t\t{\"A/B|C/D\", \"\", \"TestA\", \"B\", true, false},\n\t\t{\"A/B|C/D\", \"\", \"TestC\", \"D\", true, false},\n\t\t{\"A/B|C/D\", \"\", \"TestA\", \"C\", false, false},\n\n\t\t// subtests only\n\t\t{\"\", \"\", \"TestFoo\", \"x\", true, false},\n\t\t{\"/\", \"\", \"TestFoo\", \"x\", true, false},\n\t\t{\"./\", \"\", \"TestFoo\", \"x\", true, false},\n\t\t{\"./.\", \"\", \"TestFoo\", \"x\", true, false},\n\t\t{\"/bar/baz\", \"\", \"TestFoo\", \"bar\", true, true},\n\t\t{\"/bar/baz\", \"\", \"TestFoo\", \"bar/baz\", true, false},\n\t\t{\"//baz\", \"\", \"TestFoo\", \"bar/baz\", true, false},\n\t\t{\"//\", \"\", \"TestFoo\", \"bar/baz\", true, false},\n\t\t{\"/bar/baz\", \"\", \"TestFoo/bar\", \"baz\", true, false},\n\t\t{\"//foo\", \"\", \"TestFoo\", \"bar/baz\", false, false},\n\t\t{\"/bar/baz\", \"\", \"TestFoo\", \"x\", false, false},\n\t\t{\"/bar/baz\", \"\", \"TestBar\", \"x/bar/baz\", false, false},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tm := newMatcher(regexp.MatchString, tc.pattern, \"-test.run\", tc.skip)\n\n\t\tparent := &common{name: tc.parent}\n\t\tif tc.parent != \"\" {\n\t\t\tparent.level = 1\n\t\t}\n\t\tif n, ok, partial := m.fullName(parent, tc.sub); ok != tc.ok || partial != tc.partial {\n\t\t\tt.Errorf(\"for pattern %q, fullName(parent=%q, sub=%q) = %q, ok %v partial %v; want ok %v partial %v\",\n\t\t\t\ttc.pattern, tc.parent, tc.sub, n, ok, partial, tc.ok, tc.partial)\n\t\t}\n\t}\n}\n\nvar namingTestCases = []struct{ name, want string }{\n\t// Uniqueness\n\t{\"\", \"x/#00\"},\n\t{\"\", \"x/#01\"},\n\t{\"#0\", \"x/#0\"},      // Doesn't conflict with #00 because the number of digits differs.\n\t{\"#00\", \"x/#00#01\"}, // Conflicts with implicit #00 (used above), so add a suffix.\n\t{\"#\", \"x/#\"},\n\t{\"#\", \"x/##01\"},\n\n\t{\"t\", \"x/t\"},\n\t{\"t\", \"x/t#01\"},\n\t{\"t\", \"x/t#02\"},\n\t{\"t#00\", \"x/t#00\"}, // Explicit \"#00\" doesn't conflict with the unsuffixed first subtest.\n\n\t{\"a#01\", \"x/a#01\"},    // user has subtest with this name.\n\t{\"a\", \"x/a\"},          // doesn't conflict with this name.\n\t{\"a\", \"x/a#02\"},       // This string is claimed now, so resume\n\t{\"a\", \"x/a#03\"},       // with counting.\n\t{\"a#02\", \"x/a#02#01\"}, // We already used a#02 once, so add a suffix.\n\n\t{\"b#00\", \"x/b#00\"},\n\t{\"b\", \"x/b\"}, // Implicit 0 doesn't conflict with explicit \"#00\".\n\t{\"b\", \"x/b#01\"},\n\t{\"b#9223372036854775807\", \"x/b#9223372036854775807\"}, // MaxInt64\n\t{\"b\", \"x/b#02\"},\n\t{\"b\", \"x/b#03\"},\n\n\t// Sanitizing\n\t{\"A:1 B:2\", \"x/A:1_B:2\"},\n\t{\"s\\t\\r\\u00a0\", \"x/s___\"},\n\t{\"\\x01\", `x/\\x01`},\n\t{\"\\U0010ffff\", `x/\\U0010ffff`},\n}\n\nfunc TestNaming(t *T) {\n\tm := newMatcher(regexp.MatchString, \"\", \"\", \"\")\n\tparent := &common{name: \"x\", level: 1} // top-level test.\n\n\tfor i, tc := range namingTestCases {\n\t\tif got, _, _ := m.fullName(parent, tc.name); got != tc.want {\n\t\t\tt.Errorf(\"%d:%s: got %q; want %q\", i, tc.name, got, tc.want)\n\t\t}\n\t}\n}\n\nfunc FuzzNaming(f *F) {\n\tfor _, tc := range namingTestCases {\n\t\tf.Add(tc.name)\n\t}\n\tparent := &common{name: \"x\", level: 1}\n\tvar m *matcher\n\tvar seen map[string]string\n\treset := func() {\n\t\tm = allMatcher()\n\t\tseen = make(map[string]string)\n\t}\n\treset()\n\n\tf.Fuzz(func(t *T, subname string) {\n\t\tif len(subname) > 10 {\n\t\t\t// Long names attract the OOM killer.\n\t\t\tt.Skip()\n\t\t}\n\t\tname := m.unique(parent.name, subname)\n\t\tif !strings.Contains(name, \"/\"+subname) {\n\t\t\tt.Errorf(\"name %q does not contain subname %q\", name, subname)\n\t\t}\n\t\tif prev, ok := seen[name]; ok {\n\t\t\tt.Errorf(\"name %q generated by both %q and %q\", name, prev, subname)\n\t\t}\n\t\tif len(seen) > 1e6 {\n\t\t\t// Free up memory.\n\t\t\treset()\n\t\t}\n\t\tseen[name] = subname\n\t})\n}\n\n// GoString returns a string that is more readable than the default, which makes\n// it easier to read test errors.\nfunc (m alternationMatch) GoString() string {\n\ts := make([]string, len(m))\n\tfor i, m := range m {\n\t\ts[i] = fmt.Sprintf(\"%#v\", m)\n\t}\n\treturn fmt.Sprintf(\"(%s)\", strings.Join(s, \" | \"))\n}\n"
  },
  {
    "path": "src/testing/sub_test.go",
    "content": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage testing\n\nimport (\n\t\"reflect\"\n)\n\nfunc TestCleanup(t *T) {\n\tvar cleanups []int\n\tt.Run(\"test\", func(t *T) {\n\t\tt.Cleanup(func() { cleanups = append(cleanups, 1) })\n\t\tt.Cleanup(func() { cleanups = append(cleanups, 2) })\n\t})\n\tif got, want := cleanups, []int{2, 1}; !reflect.DeepEqual(got, want) {\n\t\tt.Errorf(\"unexpected cleanup record; got %v want %v\", got, want)\n\t}\n}\n\nfunc TestRunCleanup(t *T) {\n\touterCleanup := 0\n\tinnerCleanup := 0\n\tt.Run(\"test\", func(t *T) {\n\t\tt.Cleanup(func() { outerCleanup++ })\n\t\tt.Run(\"x\", func(t *T) {\n\t\t\tt.Cleanup(func() { innerCleanup++ })\n\t\t})\n\t})\n\tif innerCleanup != 1 {\n\t\tt.Errorf(\"unexpected inner cleanup count; got %d want 1\", innerCleanup)\n\t}\n\tif outerCleanup != 1 {\n\t\tt.Errorf(\"unexpected outer cleanup count; got %d want 1\", outerCleanup) // wrong upstream!\n\t}\n}\n\nfunc TestCleanupParallelSubtests(t *T) {\n\tranCleanup := 0\n\tt.Run(\"test\", func(t *T) {\n\t\tt.Cleanup(func() { ranCleanup++ })\n\t\tt.Run(\"x\", func(t *T) {\n\t\t\tt.Parallel()\n\t\t\tif ranCleanup > 0 {\n\t\t\t\tt.Error(\"outer cleanup ran before parallel subtest\")\n\t\t\t}\n\t\t})\n\t})\n\tif ranCleanup != 1 {\n\t\tt.Errorf(\"unexpected cleanup count; got %d want 1\", ranCleanup)\n\t}\n}\n\nfunc TestNestedCleanup(t *T) {\n\tranCleanup := 0\n\tt.Run(\"test\", func(t *T) {\n\t\tt.Cleanup(func() {\n\t\t\tif ranCleanup != 2 {\n\t\t\t\tt.Errorf(\"unexpected cleanup count in first cleanup: got %d want 2\", ranCleanup)\n\t\t\t}\n\t\t\tranCleanup++\n\t\t})\n\t\tt.Cleanup(func() {\n\t\t\tif ranCleanup != 0 {\n\t\t\t\tt.Errorf(\"unexpected cleanup count in second cleanup: got %d want 0\", ranCleanup)\n\t\t\t}\n\t\t\tranCleanup++\n\t\t\tt.Cleanup(func() {\n\t\t\t\tif ranCleanup != 1 {\n\t\t\t\t\tt.Errorf(\"unexpected cleanup count in nested cleanup: got %d want 1\", ranCleanup)\n\t\t\t\t}\n\t\t\t\tranCleanup++\n\t\t\t})\n\t\t})\n\t})\n\tif ranCleanup != 3 {\n\t\tt.Errorf(\"unexpected cleanup count: got %d want 3\", ranCleanup)\n\t}\n}\n"
  },
  {
    "path": "src/testing/testing.go",
    "content": "// Copyright 2009 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n//\n// This file has been modified for use by the TinyGo compiler.\n// src: https://github.com/golang/go/blob/61bb56ad/src/testing/testing.go\n\n// Package testing provides support for automated testing of Go packages.\npackage testing\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"io/fs\"\n\t\"math/rand\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\t\"unicode\"\n\t\"unicode/utf8\"\n)\n\n// Testing flags.\nvar (\n\tflagVerbose    bool\n\tflagShort      bool\n\tflagRunRegexp  string\n\tflagSkipRegexp string\n\tflagShuffle    string\n\tflagCount      int\n)\n\nvar initRan bool\n\n// Init registers testing flags. It has no effect if it has already run.\nfunc Init() {\n\tif initRan {\n\t\treturn\n\t}\n\tinitRan = true\n\n\tflag.BoolVar(&flagVerbose, \"test.v\", false, \"verbose: print additional output\")\n\tflag.BoolVar(&flagShort, \"test.short\", false, \"short: run smaller test suite to save time\")\n\tflag.StringVar(&flagRunRegexp, \"test.run\", \"\", \"run: regexp of tests to run\")\n\tflag.StringVar(&flagSkipRegexp, \"test.skip\", \"\", \"skip: regexp of tests to run\")\n\tflag.StringVar(&flagShuffle, \"test.shuffle\", \"off\", \"shuffle: off, on, <numeric-seed>\")\n\n\tflag.IntVar(&flagCount, \"test.count\", 1, \"run each test or benchmark `count` times\")\n\n\tinitBenchmarkFlags()\n}\n\n// common holds the elements common between T and B and\n// captures common methods such as Errorf.\ntype common struct {\n\toutput   *logger\n\tindent   string\n\tran      bool     // Test or benchmark (or one of its subtests) was executed.\n\tfailed   bool     // Test or benchmark has failed.\n\tskipped  bool     // Test of benchmark has been skipped.\n\tcleanups []func() // optional functions to be called at the end of the test\n\tfinished bool     // Test function has completed.\n\n\thasSub bool // TODO: should be atomic\n\n\tparent   *common\n\tlevel    int       // Nesting depth of test or benchmark.\n\tname     string    // Name of test or benchmark.\n\tstart    time.Time // Time test or benchmark started\n\tduration time.Duration\n\n\ttempDir    string\n\ttempDirErr error\n\ttempDirSeq int32\n\n\tctx       context.Context\n\tcancelCtx context.CancelFunc\n}\n\ntype logger struct {\n\tlogToStdout bool\n\tb           bytes.Buffer\n}\n\nfunc (l *logger) Write(p []byte) (int, error) {\n\tif l.logToStdout {\n\t\treturn os.Stdout.Write(p)\n\t}\n\treturn l.b.Write(p)\n}\n\nfunc (l *logger) WriteTo(w io.Writer) (int64, error) {\n\tif l.logToStdout {\n\t\t// We've already been logging to stdout; nothing to do.\n\t\treturn 0, nil\n\t}\n\treturn l.b.WriteTo(w)\n\n}\n\nfunc (l *logger) Len() int {\n\treturn l.b.Len()\n}\n\n// Short reports whether the -test.short flag is set.\nfunc Short() bool {\n\treturn flagShort\n}\n\n// CoverMode reports what the test coverage mode is set to.\n//\n// Test coverage is not supported; this returns the empty string.\nfunc CoverMode() string {\n\treturn \"\"\n}\n\n// Verbose reports whether the -test.v flag is set.\nfunc Verbose() bool {\n\treturn flagVerbose\n}\n\n// String constant that is being set when running a test.\nvar testBinary string\n\n// Testing returns whether the program was compiled as a test, using \"tinygo\n// test\". It returns false when built using \"tinygo build\", \"tinygo flash\", etc.\nfunc Testing() bool {\n\treturn testBinary == \"1\"\n}\n\n// flushToParent writes c.output to the parent after first writing the header\n// with the given format and arguments.\nfunc (c *common) flushToParent(testName, format string, args ...interface{}) {\n\tif c.parent == nil {\n\t\t// The fake top-level test doesn't want a FAIL or PASS banner.\n\t\t// Not quite sure how this works upstream.\n\t\tc.output.WriteTo(os.Stdout)\n\t} else {\n\t\tfmt.Fprintf(c.parent.output, format, args...)\n\t\tc.output.WriteTo(c.parent.output)\n\t}\n}\n\n// fmtDuration returns a string representing d in the form \"87.00s\".\nfunc fmtDuration(d time.Duration) string {\n\treturn fmt.Sprintf(\"%.2fs\", d.Seconds())\n}\n\n// TB is the interface common to T and B.\ntype TB interface {\n\tCleanup(func())\n\tContext() context.Context\n\tError(args ...interface{})\n\tErrorf(format string, args ...interface{})\n\tFail()\n\tFailNow()\n\tFailed() bool\n\tFatal(args ...interface{})\n\tFatalf(format string, args ...interface{})\n\tHelper()\n\tLog(args ...interface{})\n\tLogf(format string, args ...interface{})\n\tName() string\n\tSetenv(key, value string)\n\tSkip(args ...interface{})\n\tSkipNow()\n\tSkipf(format string, args ...interface{})\n\tSkipped() bool\n\tTempDir() string\n}\n\nvar _ TB = (*T)(nil)\nvar _ TB = (*B)(nil)\n\n// T is a type passed to Test functions to manage test state and support formatted test logs.\n// Logs are accumulated during execution and dumped to standard output when done.\ntype T struct {\n\tcommon\n\tcontext *testContext // For running tests and subtests.\n}\n\n// Name returns the name of the running test or benchmark.\nfunc (c *common) Name() string {\n\treturn c.name\n}\n\nfunc (c *common) setRan() {\n\tif c.parent != nil {\n\t\tc.parent.setRan()\n\t}\n\tc.ran = true\n}\n\n// Fail marks the function as having failed but continues execution.\nfunc (c *common) Fail() {\n\tc.failed = true\n}\n\n// Failed reports whether the function has failed.\nfunc (c *common) Failed() bool {\n\tfailed := c.failed\n\treturn failed\n}\n\n// FailNow marks the function as having failed and stops its execution\n// by calling runtime.Goexit (which then runs all deferred calls in the\n// current goroutine).\nfunc (c *common) FailNow() {\n\tc.Fail()\n\n\tc.finished = true\n\tc.Error(\"FailNow is incomplete, requires runtime.Goexit()\")\n}\n\n// log generates the output.\nfunc (c *common) log(s string) {\n\t// This doesn't print the same as in upstream go, but works for now.\n\tif len(s) != 0 && s[len(s)-1] == '\\n' {\n\t\ts = s[:len(s)-1]\n\t}\n\tlines := strings.Split(s, \"\\n\")\n\t// First line.\n\tfmt.Fprintf(c.output, \"%s    %s\\n\", c.indent, lines[0])\n\t// More lines.\n\tfor _, line := range lines[1:] {\n\t\tfmt.Fprintf(c.output, \"%s        %s\\n\", c.indent, line)\n\t}\n}\n\n// Log formats its arguments using default formatting, analogous to Println,\n// and records the text in the error log. For tests, the text will be printed only if\n// the test fails or the -test.v flag is set. For benchmarks, the text is always\n// printed to avoid having performance depend on the value of the -test.v flag.\nfunc (c *common) Log(args ...interface{}) { c.log(fmt.Sprintln(args...)) }\n\n// Logf formats its arguments according to the format, analogous to Printf, and\n// records the text in the error log. A final newline is added if not provided. For\n// tests, the text will be printed only if the test fails or the -test.v flag is\n// set. For benchmarks, the text is always printed to avoid having performance\n// depend on the value of the -test.v flag.\nfunc (c *common) Logf(format string, args ...interface{}) { c.log(fmt.Sprintf(format, args...)) }\n\n// Error is equivalent to Log followed by Fail.\nfunc (c *common) Error(args ...interface{}) {\n\tc.log(fmt.Sprintln(args...))\n\tc.Fail()\n}\n\n// Errorf is equivalent to Logf followed by Fail.\nfunc (c *common) Errorf(format string, args ...interface{}) {\n\tc.log(fmt.Sprintf(format, args...))\n\tc.Fail()\n}\n\n// Fatal is equivalent to Log followed by FailNow.\nfunc (c *common) Fatal(args ...interface{}) {\n\tc.log(fmt.Sprintln(args...))\n\tc.FailNow()\n}\n\n// Fatalf is equivalent to Logf followed by FailNow.\nfunc (c *common) Fatalf(format string, args ...interface{}) {\n\tc.log(fmt.Sprintf(format, args...))\n\tc.FailNow()\n}\n\n// Skip is equivalent to Log followed by SkipNow.\nfunc (c *common) Skip(args ...interface{}) {\n\tc.log(fmt.Sprintln(args...))\n\tc.SkipNow()\n}\n\n// Skipf is equivalent to Logf followed by SkipNow.\nfunc (c *common) Skipf(format string, args ...interface{}) {\n\tc.log(fmt.Sprintf(format, args...))\n\tc.SkipNow()\n}\n\n// SkipNow marks the test as having been skipped and stops its execution\n// by calling runtime.Goexit.\nfunc (c *common) SkipNow() {\n\tc.skip()\n\tc.finished = true\n\tc.Error(\"SkipNow is incomplete, requires runtime.Goexit()\")\n}\n\nfunc (c *common) skip() {\n\tc.skipped = true\n}\n\n// Skipped reports whether the test was skipped.\nfunc (c *common) Skipped() bool {\n\treturn c.skipped\n}\n\n// Helper is not implemented, it is only provided for compatibility.\nfunc (c *common) Helper() {\n\t// Unimplemented.\n}\n\n// Cleanup registers a function to be called when the test (or subtest) and all its\n// subtests complete. Cleanup functions will be called in last added,\n// first called order.\nfunc (c *common) Cleanup(f func()) {\n\tc.cleanups = append(c.cleanups, f)\n}\n\n// Context returns a context that is canceled just before\n// Cleanup-registered functions are called.\n//\n// Cleanup functions can wait for any resources\n// that shut down on [context.Context.Done] before the test or benchmark completes.\nfunc (c *common) Context() context.Context {\n\treturn c.ctx\n}\n\n// TempDir returns a temporary directory for the test to use.\n// The directory is automatically removed by Cleanup when the test and\n// all its subtests complete.\n// Each subsequent call to t.TempDir returns a unique directory;\n// if the directory creation fails, TempDir terminates the test by calling Fatal.\nfunc (c *common) TempDir() string {\n\t// Use a single parent directory for all the temporary directories\n\t// created by a test, each numbered sequentially.\n\tvar nonExistent bool\n\tif c.tempDir == \"\" { // Usually the case with js/wasm\n\t\tnonExistent = true\n\t} else {\n\t\t_, err := os.Stat(c.tempDir)\n\t\tnonExistent = errors.Is(err, fs.ErrNotExist)\n\t\tif err != nil && !nonExistent {\n\t\t\tc.Fatalf(\"TempDir: %v\", err)\n\t\t}\n\t}\n\n\tif nonExistent {\n\t\tc.Helper()\n\n\t\t// Drop unusual characters (such as path separators or\n\t\t// characters interacting with globs) from the directory name to\n\t\t// avoid surprising os.MkdirTemp behavior.\n\t\tmapper := func(r rune) rune {\n\t\t\tif r < utf8.RuneSelf {\n\t\t\t\tconst allowed = \"!#$%&()+,-.=@^_{}~ \"\n\t\t\t\tif '0' <= r && r <= '9' ||\n\t\t\t\t\t'a' <= r && r <= 'z' ||\n\t\t\t\t\t'A' <= r && r <= 'Z' {\n\t\t\t\t\treturn r\n\t\t\t\t}\n\t\t\t\tif strings.ContainsRune(allowed, r) {\n\t\t\t\t\treturn r\n\t\t\t\t}\n\t\t\t} else if unicode.IsLetter(r) || unicode.IsNumber(r) {\n\t\t\t\treturn r\n\t\t\t}\n\t\t\treturn -1\n\t\t}\n\t\tpattern := strings.Map(mapper, c.Name())\n\t\tc.tempDir, c.tempDirErr = os.MkdirTemp(\"\", pattern)\n\t\tif c.tempDirErr == nil {\n\t\t\tc.Cleanup(func() {\n\t\t\t\tif err := os.RemoveAll(c.tempDir); err != nil {\n\t\t\t\t\tc.Errorf(\"TempDir RemoveAll cleanup: %v\", err)\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t}\n\n\tif c.tempDirErr != nil {\n\t\tc.Fatalf(\"TempDir: %v\", c.tempDirErr)\n\t}\n\tseq := c.tempDirSeq\n\tc.tempDirSeq++\n\tdir := fmt.Sprintf(\"%s%c%03d\", c.tempDir, os.PathSeparator, seq)\n\tif err := os.Mkdir(dir, 0777); err != nil {\n\t\tc.Fatalf(\"TempDir: %v\", err)\n\t}\n\treturn dir\n}\n\n// Setenv calls os.Setenv(key, value) and uses Cleanup to\n// restore the environment variable to its original value\n// after the test.\nfunc (c *common) Setenv(key, value string) {\n\tprevValue, ok := os.LookupEnv(key)\n\n\tif err := os.Setenv(key, value); err != nil {\n\t\tc.Fatalf(\"cannot set environment variable: %v\", err)\n\t}\n\n\tif ok {\n\t\tc.Cleanup(func() {\n\t\t\tos.Setenv(key, prevValue)\n\t\t})\n\t} else {\n\t\tc.Cleanup(func() {\n\t\t\tos.Unsetenv(key)\n\t\t})\n\t}\n}\n\n// Chdir calls os.Chdir(dir) and uses Cleanup to restore the current\n// working directory to its original value after the test. On Unix, it\n// also sets PWD environment variable for the duration of the test.\n//\n// Because Chdir affects the whole process, it cannot be used\n// in parallel tests or tests with parallel ancestors.\nfunc (c *common) Chdir(dir string) {\n\t// Note: function copied from the Go 1.24.0 source tree.\n\n\toldwd, err := os.Open(\".\")\n\tif err != nil {\n\t\tc.Fatal(err)\n\t}\n\tif err := os.Chdir(dir); err != nil {\n\t\tc.Fatal(err)\n\t}\n\t// On POSIX platforms, PWD represents “an absolute pathname of the\n\t// current working directory.” Since we are changing the working\n\t// directory, we should also set or update PWD to reflect that.\n\tswitch runtime.GOOS {\n\tcase \"windows\", \"plan9\":\n\t\t// Windows and Plan 9 do not use the PWD variable.\n\tdefault:\n\t\tif !filepath.IsAbs(dir) {\n\t\t\tdir, err = os.Getwd()\n\t\t\tif err != nil {\n\t\t\t\tc.Fatal(err)\n\t\t\t}\n\t\t}\n\t\tc.Setenv(\"PWD\", dir)\n\t}\n\tc.Cleanup(func() {\n\t\terr := oldwd.Chdir()\n\t\toldwd.Close()\n\t\tif err != nil {\n\t\t\t// It's not safe to continue with tests if we can't\n\t\t\t// get back to the original working directory. Since\n\t\t\t// we are holding a dirfd, this is highly unlikely.\n\t\t\tpanic(\"testing.Chdir: \" + err.Error())\n\t\t}\n\t})\n}\n\n// runCleanup is called at the end of the test.\nfunc (c *common) runCleanup() {\n\tfor {\n\t\tvar cleanup func()\n\t\tif len(c.cleanups) > 0 {\n\t\t\tlast := len(c.cleanups) - 1\n\t\t\tcleanup = c.cleanups[last]\n\t\t\tc.cleanups = c.cleanups[:last]\n\t\t}\n\t\tif cleanup == nil {\n\t\t\treturn\n\t\t}\n\t\tif c.cancelCtx != nil {\n\t\t\tc.cancelCtx()\n\t\t}\n\t\tcleanup()\n\t}\n}\n\n// Parallel is not implemented, it is only provided for compatibility.\nfunc (t *T) Parallel() {\n\t// Unimplemented.\n}\n\n// InternalTest is a reference to a test that should be called during a test suite run.\ntype InternalTest struct {\n\tName string\n\tF    func(*T)\n}\n\nfunc tRunner(t *T, fn func(t *T)) {\n\tdefer func() {\n\t\tt.runCleanup()\n\t}()\n\n\t// Run the test.\n\tt.start = time.Now()\n\tfn(t)\n\tt.duration += time.Since(t.start) // TODO: capture cleanup time, too.\n\n\tt.report() // Report after all subtests have finished.\n\tif t.parent != nil && !t.hasSub {\n\t\tt.setRan()\n\t}\n}\n\n// Run runs f as a subtest of t called name. It waits until the subtest is finished\n// and returns whether the subtest succeeded.\nfunc (t *T) Run(name string, f func(t *T)) bool {\n\tt.hasSub = true\n\ttestName, ok, _ := t.context.match.fullName(&t.common, name)\n\tif !ok {\n\t\treturn true\n\t}\n\n\t// Create a subtest.\n\tctx, cancelCtx := context.WithCancel(context.Background())\n\tsub := T{\n\t\tcommon: common{\n\t\t\toutput:    &logger{logToStdout: flagVerbose},\n\t\t\tname:      testName,\n\t\t\tparent:    &t.common,\n\t\t\tlevel:     t.level + 1,\n\t\t\tctx:       ctx,\n\t\t\tcancelCtx: cancelCtx,\n\t\t},\n\t\tcontext: t.context,\n\t}\n\tif t.level > 0 {\n\t\tsub.indent = sub.indent + \"    \"\n\t}\n\tif flagVerbose {\n\t\tfmt.Fprintf(t.output, \"=== RUN   %s\\n\", sub.name)\n\t}\n\n\ttRunner(&sub, f)\n\treturn !sub.failed\n}\n\n// Deadline reports the time at which the test binary will have\n// exceeded the timeout specified by the -timeout flag.\n//\n// The ok result is false if the -timeout flag indicates “no timeout” (0).\n// For now tinygo always return 0, false.\n//\n// Not Implemented.\nfunc (t *T) Deadline() (deadline time.Time, ok bool) {\n\tdeadline = t.context.deadline\n\treturn deadline, !deadline.IsZero()\n}\n\n// testContext holds all fields that are common to all tests. This includes\n// synchronization primitives to run at most *parallel tests.\ntype testContext struct {\n\tmatch    *matcher\n\tdeadline time.Time\n}\n\nfunc newTestContext(m *matcher) *testContext {\n\treturn &testContext{\n\t\tmatch: m,\n\t}\n}\n\n// M is a test suite.\ntype M struct {\n\t// tests is a list of the test names to execute\n\tTests      []InternalTest\n\tBenchmarks []InternalBenchmark\n\n\tdeps testDeps\n\n\t// value to pass to os.Exit, the outer test func main\n\t// harness calls os.Exit with this code. See #34129.\n\texitCode int\n}\n\ntype testDeps interface {\n\tMatchString(pat, str string) (bool, error)\n}\n\nfunc (m *M) shuffle() error {\n\tvar n int64\n\n\tif flagShuffle == \"on\" {\n\t\tn = time.Now().UnixNano()\n\t} else {\n\t\tvar err error\n\t\tn, err = strconv.ParseInt(flagShuffle, 10, 64)\n\t\tif err != nil {\n\t\t\tm.exitCode = 2\n\t\t\treturn fmt.Errorf(`testing: -shuffle should be \"off\", \"on\", or a valid integer: %v`, err)\n\t\t}\n\t}\n\n\tfmt.Println(\"-test.shuffle\", n)\n\trng := rand.New(rand.NewSource(n))\n\trng.Shuffle(len(m.Tests), func(i, j int) { m.Tests[i], m.Tests[j] = m.Tests[j], m.Tests[i] })\n\trng.Shuffle(len(m.Benchmarks), func(i, j int) { m.Benchmarks[i], m.Benchmarks[j] = m.Benchmarks[j], m.Benchmarks[i] })\n\treturn nil\n}\n\n// Run runs the tests. It returns an exit code to pass to os.Exit.\nfunc (m *M) Run() (code int) {\n\tdefer func() {\n\t\tcode = m.exitCode\n\t}()\n\n\tif !flag.Parsed() {\n\t\tflag.Parse()\n\t}\n\n\tif flagShuffle != \"off\" {\n\t\tif err := m.shuffle(); err != nil {\n\t\t\tfmt.Fprintln(os.Stderr, err)\n\t\t\treturn\n\t\t}\n\t}\n\n\ttestRan, testOk := runTests(m.deps.MatchString, m.Tests)\n\tif !testRan && *matchBenchmarks == \"\" {\n\t\tfmt.Fprintln(os.Stderr, \"testing: warning: no tests to run\")\n\t}\n\tif !testOk || !runBenchmarks(m.deps.MatchString, m.Benchmarks) {\n\t\tfmt.Println(\"FAIL\")\n\t\tm.exitCode = 1\n\t} else {\n\t\tfmt.Println(\"PASS\")\n\t\tm.exitCode = 0\n\t}\n\treturn\n}\n\nfunc runTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ran, ok bool) {\n\tok = true\n\n\tctx := newTestContext(newMatcher(matchString, flagRunRegexp, \"-test.run\", flagSkipRegexp))\n\trunCtx, cancelCtx := context.WithCancel(context.Background())\n\tt := &T{\n\t\tcommon: common{\n\t\t\toutput:    &logger{logToStdout: flagVerbose},\n\t\t\tctx:       runCtx,\n\t\t\tcancelCtx: cancelCtx,\n\t\t},\n\t\tcontext: ctx,\n\t}\n\n\tfor i := 0; i < flagCount; i++ {\n\t\ttRunner(t, func(t *T) {\n\t\t\tfor _, test := range tests {\n\t\t\t\tt.Run(test.Name, test.F)\n\t\t\t\tok = ok && !t.Failed()\n\t\t\t}\n\t\t})\n\t}\n\n\treturn t.ran, ok\n}\n\nfunc (t *T) report() {\n\tdstr := fmtDuration(t.duration)\n\tformat := t.indent + \"--- %s: %s (%s)\\n\"\n\tif t.Failed() {\n\t\tif t.parent != nil {\n\t\t\tt.parent.failed = true\n\t\t}\n\t\tt.flushToParent(t.name, format, \"FAIL\", t.name, dstr)\n\t} else if flagVerbose {\n\t\tif t.Skipped() {\n\t\t\tt.flushToParent(t.name, format, \"SKIP\", t.name, dstr)\n\t\t} else {\n\t\t\tt.flushToParent(t.name, format, \"PASS\", t.name, dstr)\n\t\t}\n\t}\n}\n\n// AllocsPerRun returns the average number of allocations during calls to f.\n// Although the return value has type float64, it will always be an integral\n// value.\n//\n// Not implemented.\nfunc AllocsPerRun(runs int, f func()) (avg float64) {\n\tf()\n\tfor i := 0; i < runs; i++ {\n\t\tf()\n\t}\n\treturn 0\n}\n\ntype InternalExample struct {\n\tName      string\n\tF         func()\n\tOutput    string\n\tUnordered bool\n}\n\n// MainStart is meant for use by tests generated by 'go test'.\n// It is not meant to be called directly and is not subject to the Go 1 compatibility document.\n// It may change signature from release to release.\nfunc MainStart(deps interface{}, tests []InternalTest, benchmarks []InternalBenchmark, fuzzTargets []InternalFuzzTarget, examples []InternalExample) *M {\n\tInit()\n\treturn &M{\n\t\tTests:      tests,\n\t\tBenchmarks: benchmarks,\n\t\tdeps:       deps.(testDeps),\n\t}\n}\n\n// A fake regexp matcher.\n// Inflexible, but saves 50KB of flash and 50KB of RAM per -size full,\n// and lets tests pass on cortex-m.\nfunc fakeMatchString(pat, str string) (bool, error) {\n\tif pat == \".*\" {\n\t\treturn true, nil\n\t}\n\tmatched := strings.Contains(str, pat)\n\treturn matched, nil\n}\n"
  },
  {
    "path": "src/testing/testing_test.go",
    "content": "//go:build !windows\n\n// TODO: implement readdir for windows, then enable this file\n\n// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage testing_test\n\nimport (\n\t\"errors\"\n\t\"io/fs\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"testing\"\n)\n\n// This is exactly what a test would do without a TestMain.\n// It's here only so that there is at least one package in the\n// standard library with a TestMain, so that code is executed.\n\nfunc TestMain(m *testing.M) {\n\tos.Exit(m.Run())\n}\n\nfunc TestTempDirInCleanup(t *testing.T) {\n\tif runtime.GOOS == \"wasip1\" || runtime.GOOS == \"wasip2\" {\n\t\tt.Log(\"Skipping.  TODO: implement RemoveAll for wasi\")\n\t\treturn\n\t}\n\n\tvar dir string\n\n\tt.Run(\"test\", func(t *testing.T) {\n\t\tt.Cleanup(func() {\n\t\t\tdir = t.TempDir()\n\t\t})\n\t\t_ = t.TempDir()\n\t})\n\n\tfi, err := os.Stat(dir)\n\tif fi != nil {\n\t\tt.Fatalf(\"Directory %q from user Cleanup still exists\", dir)\n\t}\n\tif !errors.Is(err, fs.ErrNotExist) {\n\t\tt.Fatalf(\"Unexpected error: %v\", err)\n\t}\n}\n\nfunc TestTempDirInBenchmark(t *testing.T) {\n\ttesting.Benchmark(func(b *testing.B) {\n\t\tif !b.Run(\"test\", func(b *testing.B) {\n\t\t\t// Add a loop so that the test won't fail. See issue 38677.\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = b.TempDir()\n\t\t\t}\n\t\t}) {\n\t\t\tt.Fatal(\"Sub test failure in a benchmark\")\n\t\t}\n\t})\n}\n\nfunc TestTempDir(t *testing.T) {\n\tif runtime.GOOS == \"wasip1\" || runtime.GOOS == \"wasip2\" {\n\t\tt.Log(\"Skipping.  TODO: implement RemoveAll for wasi\")\n\t\treturn\n\t}\n\n\ttestTempDir(t)\n\tt.Run(\"InSubtest\", testTempDir)\n\tt.Run(\"test/subtest\", testTempDir)\n\tt.Run(\"test\\\\subtest\", testTempDir)\n\tt.Run(\"test:subtest\", testTempDir)\n\tt.Run(\"test/..\", testTempDir)\n\tt.Run(\"../test\", testTempDir)\n\tt.Run(\"test[]\", testTempDir)\n\tt.Run(\"test*\", testTempDir)\n\tt.Run(\"äöüéè\", testTempDir)\n}\n\nfunc testTempDir(t *testing.T) {\n\tdirCh := make(chan string, 1)\n\tt.Cleanup(func() {\n\t\t// Verify directory has been removed.\n\t\tselect {\n\t\tcase dir := <-dirCh:\n\t\t\tfi, err := os.Stat(dir)\n\t\t\tif errors.Is(err, fs.ErrNotExist) {\n\t\t\t\t// All good\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tt.Errorf(\"directory %q still exists: %v, isDir=%v\", dir, fi, fi.IsDir())\n\t\tdefault:\n\t\t\tif !t.Failed() {\n\t\t\t\tt.Fatal(\"never received dir channel\")\n\t\t\t}\n\t\t}\n\t})\n\n\tdir := t.TempDir()\n\tif dir == \"\" {\n\t\tt.Fatal(\"expected dir\")\n\t}\n\tdir2 := t.TempDir()\n\tif dir == dir2 {\n\t\tt.Fatal(\"subsequent calls to TempDir returned the same directory\")\n\t}\n\tif filepath.Dir(dir) != filepath.Dir(dir2) {\n\t\tt.Fatalf(\"calls to TempDir do not share a parent; got %q, %q\", dir, dir2)\n\t}\n\tdirCh <- dir\n\tfi, err := os.Stat(dir)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !fi.IsDir() {\n\t\tt.Errorf(\"dir %q is not a dir\", dir)\n\t}\n\tfiles, err := os.ReadDir(dir)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(files) > 0 {\n\t\tt.Errorf(\"unexpected %d files in TempDir: %v\", len(files), files)\n\t}\n\n\tglob := filepath.Join(dir, \"*.txt\")\n\tif _, err := filepath.Glob(glob); err != nil {\n\t\tt.Error(err)\n\t}\n\n\terr = os.Remove(dir)\n\tif err != nil {\n\t\tt.Errorf(\"unexpected files in TempDir\")\n\t}\n}\n\nfunc TestSetenv(t *testing.T) {\n\ttests := []struct {\n\t\tname               string\n\t\tkey                string\n\t\tinitialValueExists bool\n\t\tinitialValue       string\n\t\tnewValue           string\n\t}{\n\t\t{\n\t\t\tname:               \"initial value exists\",\n\t\t\tkey:                \"GO_TEST_KEY_1\",\n\t\t\tinitialValueExists: true,\n\t\t\tinitialValue:       \"111\",\n\t\t\tnewValue:           \"222\",\n\t\t},\n\t\t{\n\t\t\tname:               \"initial value exists but empty\",\n\t\t\tkey:                \"GO_TEST_KEY_2\",\n\t\t\tinitialValueExists: true,\n\t\t\tinitialValue:       \"\",\n\t\t\tnewValue:           \"222\",\n\t\t},\n\t\t{\n\t\t\tname:               \"initial value is not exists\",\n\t\t\tkey:                \"GO_TEST_KEY_3\",\n\t\t\tinitialValueExists: false,\n\t\t\tinitialValue:       \"\",\n\t\t\tnewValue:           \"222\",\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tif test.initialValueExists {\n\t\t\tif err := os.Setenv(test.key, test.initialValue); err != nil {\n\t\t\t\tt.Fatalf(\"unable to set env: got %v\", err)\n\t\t\t}\n\t\t} else {\n\t\t\tos.Unsetenv(test.key)\n\t\t}\n\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\tt.Setenv(test.key, test.newValue)\n\t\t\tif os.Getenv(test.key) != test.newValue {\n\t\t\t\tt.Fatalf(\"unexpected value after t.Setenv: got %s, want %s\", os.Getenv(test.key), test.newValue)\n\t\t\t}\n\t\t})\n\n\t\tgot, exists := os.LookupEnv(test.key)\n\t\tif got != test.initialValue {\n\t\t\tt.Fatalf(\"unexpected value after t.Setenv cleanup: got %s, want %s\", got, test.initialValue)\n\t\t}\n\t\tif exists != test.initialValueExists {\n\t\t\tt.Fatalf(\"unexpected value after t.Setenv cleanup: got %t, want %t\", exists, test.initialValueExists)\n\t\t}\n\t}\n}\n\nfunc TestTesting(t *testing.T) {\n\tif !testing.Testing() {\n\t\tt.Error(\"Expected testing.Testing() to return true while in a test\")\n\t}\n}\n"
  },
  {
    "path": "src/tinygo/runtime.go",
    "content": "// Package tinygo contains constants used between the TinyGo compiler and\n// runtime.\npackage tinygo\n\nconst (\n\tPanicStrategyPrint = iota + 1\n\tPanicStrategyTrap\n)\n\ntype HashmapAlgorithm uint8\n\n// Constants for hashmap algorithms.\nconst (\n\tHashmapAlgorithmBinary HashmapAlgorithm = iota\n\tHashmapAlgorithmString\n\tHashmapAlgorithmInterface\n)\n"
  },
  {
    "path": "src/unique/handle.go",
    "content": "// Package unique implements the upstream Go unique package for TinyGo.\n//\n// It is not a full implementation: while it should behave the same way, it\n// doesn't free unreferenced uniqued objects.\npackage unique\n\nimport (\n\t\"sync\"\n\t\"unsafe\"\n)\n\nvar (\n\t// We use a two-level map because that way it's easier to store and retrieve\n\t// values.\n\tglobalMap map[unsafe.Pointer]any // map value type is always map[T]Handle[T]\n\n\tglobalMapMutex sync.Mutex\n)\n\n// Unique handle for the given value. Comparing two handles is cheap.\ntype Handle[T comparable] struct {\n\tvalue *T\n}\n\n// Value returns a shallow copy of the T value that produced the Handle.\nfunc (h Handle[T]) Value() T {\n\treturn *h.value\n}\n\n// Make a new unqique handle for the given value.\nfunc Make[T comparable](value T) Handle[T] {\n\t// Very simple implementation of the unique package. This is much, *much*\n\t// simpler than the upstream implementation. Sadly it's not possible to\n\t// reuse the upstream version because it relies on implementation details of\n\t// the upstream runtime.\n\t// It probably isn't as efficient as the upstream version, but the first\n\t// goal here is compatibility. If the performance is a problem, it can be\n\t// optimized later.\n\n\tglobalMapMutex.Lock()\n\n\t// The map isn't initialized at program startup (and after a test run), so\n\t// create it.\n\tif globalMap == nil {\n\t\tglobalMap = make(map[unsafe.Pointer]any)\n\t}\n\n\t// Retrieve the type-specific map, creating it if not yet present.\n\ttypeptr, _ := decomposeInterface(value)\n\tvar typeSpecificMap map[T]Handle[T]\n\tif typeSpecificMapValue, ok := globalMap[typeptr]; !ok {\n\t\ttypeSpecificMap = make(map[T]Handle[T])\n\t\tglobalMap[typeptr] = typeSpecificMap\n\t} else {\n\t\ttypeSpecificMap = typeSpecificMapValue.(map[T]Handle[T])\n\t}\n\n\t// Retrieve the handle for the value, creating it if it isn't created yet.\n\tvar handle Handle[T]\n\tif h, ok := typeSpecificMap[value]; !ok {\n\t\tvar clone T = value\n\t\thandle.value = &clone\n\t\ttypeSpecificMap[value] = handle\n\t} else {\n\t\thandle = h\n\t}\n\n\tglobalMapMutex.Unlock()\n\n\treturn handle\n}\n\n//go:linkname decomposeInterface runtime.decomposeInterface\nfunc decomposeInterface(i interface{}) (unsafe.Pointer, unsafe.Pointer)\n"
  },
  {
    "path": "src/unique/handle_test.go",
    "content": "// Copyright 2024 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// This file is a copy of src/unique/handle_test.go in upstream Go, but with\n// some parts removed that rely on Go runtime implementation details.\n\npackage unique\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"testing\"\n)\n\n// Set up special types. Because the internal maps are sharded by type,\n// this will ensure that we're not overlapping with other tests.\ntype testString string\ntype testIntArray [4]int\ntype testEface any\ntype testStringArray [3]string\ntype testStringStruct struct {\n\ta string\n}\ntype testStringStructArrayStruct struct {\n\ts [2]testStringStruct\n}\ntype testStruct struct {\n\tz float64\n\tb string\n}\n\nfunc TestHandle(t *testing.T) {\n\ttestHandle[testString](t, \"foo\")\n\ttestHandle[testString](t, \"bar\")\n\ttestHandle[testString](t, \"\")\n\ttestHandle[testIntArray](t, [4]int{7, 77, 777, 7777})\n\t//testHandle[testEface](t, nil) // requires Go 1.20\n\ttestHandle[testStringArray](t, [3]string{\"a\", \"b\", \"c\"})\n\ttestHandle[testStringStruct](t, testStringStruct{\"x\"})\n\ttestHandle[testStringStructArrayStruct](t, testStringStructArrayStruct{\n\t\ts: [2]testStringStruct{testStringStruct{\"y\"}, testStringStruct{\"z\"}},\n\t})\n\ttestHandle[testStruct](t, testStruct{0.5, \"184\"})\n}\n\nfunc testHandle[T comparable](t *testing.T, value T) {\n\tname := reflect.TypeFor[T]().Name()\n\tt.Run(fmt.Sprintf(\"%s/%#v\", name, value), func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\tv0 := Make(value)\n\t\tv1 := Make(value)\n\n\t\tif v0.Value() != v1.Value() {\n\t\t\tt.Error(\"v0.Value != v1.Value\")\n\t\t}\n\t\tif v0.Value() != value {\n\t\t\tt.Errorf(\"v0.Value not %#v\", value)\n\t\t}\n\t\tif v0 != v1 {\n\t\t\tt.Error(\"v0 != v1\")\n\t\t}\n\n\t\tdrainMaps(t)\n\t})\n}\n\n// drainMaps ensures that the internal maps are drained.\nfunc drainMaps(t *testing.T) {\n\tt.Helper()\n\n\tglobalMapMutex.Lock()\n\tglobalMap = nil\n\tglobalMapMutex.Unlock()\n}\n"
  },
  {
    "path": "stacksize/dwarf.go",
    "content": "package stacksize\n\n// This file implements parsing DWARF call frame information and interpreting\n// the CFI bytecode, or enough of it for most practical code.\n\nimport (\n\t\"bytes\"\n\t\"debug/elf\"\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"io\"\n)\n\n// dwarfCIE represents one DWARF Call Frame Information structure.\ntype dwarfCIE struct {\n\tbytecode            []byte\n\tcodeAlignmentFactor uint64\n}\n\n// parseFrames parses all call frame information from a .debug_frame section and\n// provides the passed in symbols map with frame size information.\nfunc parseFrames(f *elf.File, data []byte, symbols map[uint64]*CallNode) error {\n\tif f.Class != elf.ELFCLASS32 {\n\t\t// TODO: ELF64\n\t\treturn fmt.Errorf(\"expected ELF32\")\n\t}\n\tcies := make(map[uint32]*dwarfCIE)\n\n\t// Read each entity.\n\tr := bytes.NewBuffer(data)\n\tfor {\n\t\tstart := len(data) - r.Len()\n\t\tvar length uint32\n\t\terr := binary.Read(r, binary.LittleEndian, &length)\n\t\tif err == io.EOF {\n\t\t\treturn nil\n\t\t}\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tvar cie uint32\n\t\terr = binary.Read(r, binary.LittleEndian, &cie)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif cie == 0xffffffff {\n\t\t\t// This is a CIE.\n\t\t\tvar fields struct {\n\t\t\t\tVersion      uint8\n\t\t\t\tAugmentation uint8\n\t\t\t\tAddressSize  uint8\n\t\t\t\tSegmentSize  uint8\n\t\t\t}\n\t\t\terr = binary.Read(r, binary.LittleEndian, &fields)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif fields.Version != 4 {\n\t\t\t\treturn fmt.Errorf(\"unimplemented: .debug_frame version %d\", fields.Version)\n\t\t\t}\n\t\t\tif fields.Augmentation != 0 {\n\t\t\t\treturn fmt.Errorf(\"unimplemented: .debug_frame with augmentation\")\n\t\t\t}\n\t\t\tif fields.SegmentSize != 0 {\n\t\t\t\treturn fmt.Errorf(\"unimplemented: .debug_frame with segment size\")\n\t\t\t}\n\t\t\tcodeAlignmentFactor, err := readULEB128(r)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\t_, err = readSLEB128(r) // data alignment factor\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\t_, err = readULEB128(r) // return address register\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\trest := (start + int(length) + 4) - (len(data) - r.Len())\n\t\t\tbytecode := r.Next(rest)\n\t\t\tcies[uint32(start)] = &dwarfCIE{\n\t\t\t\tcodeAlignmentFactor: codeAlignmentFactor,\n\t\t\t\tbytecode:            bytecode,\n\t\t\t}\n\t\t} else {\n\t\t\t// This is a FDE.\n\t\t\tvar fields struct {\n\t\t\t\tInitialLocation uint32\n\t\t\t\tAddressRange    uint32\n\t\t\t}\n\t\t\terr = binary.Read(r, binary.LittleEndian, &fields)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif _, ok := cies[cie]; !ok {\n\t\t\t\treturn fmt.Errorf(\"could not find CIE 0x%x in .debug_frame section\", cie)\n\t\t\t}\n\t\t\tframe := frameInfo{\n\t\t\t\tcie:    cies[cie],\n\t\t\t\tstart:  uint64(fields.InitialLocation),\n\t\t\t\tloc:    uint64(fields.InitialLocation),\n\t\t\t\tlength: uint64(fields.AddressRange),\n\t\t\t}\n\t\t\trest := (start + int(length) + 4) - (len(data) - r.Len())\n\t\t\tbytecode := r.Next(rest)\n\n\t\t\tif frame.start == 0 {\n\t\t\t\t// Not sure where these come from but they don't seem to be\n\t\t\t\t// important.\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t_, err = frame.exec(frame.cie.bytecode)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tentries, err := frame.exec(bytecode)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tvar maxFrameSize uint64\n\t\t\tfor _, entry := range entries {\n\t\t\t\tswitch f.Machine {\n\t\t\t\tcase elf.EM_ARM:\n\t\t\t\t\tif entry.cfaRegister != 13 { // r13 or sp\n\t\t\t\t\t\t// something other than a stack pointer (on ARM)\n\t\t\t\t\t\treturn fmt.Errorf(\"%08x..%08x: unknown CFA register number %d\", frame.start, frame.start+frame.length, entry.cfaRegister)\n\t\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\treturn fmt.Errorf(\"unknown architecture: %s\", f.Machine)\n\t\t\t\t}\n\t\t\t\tif entry.cfaOffset > maxFrameSize {\n\t\t\t\t\tmaxFrameSize = entry.cfaOffset\n\t\t\t\t}\n\t\t\t}\n\t\t\tnode := symbols[frame.start]\n\t\t\tif node.Size != frame.length {\n\t\t\t\treturn fmt.Errorf(\"%s: symtab gives symbol length %d while DWARF gives symbol length %d\", node, node.Size, frame.length)\n\t\t\t}\n\t\t\tnode.FrameSize = maxFrameSize\n\t\t\tnode.FrameSizeType = Bounded\n\t\t\tif debugPrint {\n\t\t\t\tfmt.Printf(\"%08x..%08x: frame size %4d %s\\n\", frame.start, frame.start+frame.length, maxFrameSize, node)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// frameInfo contains the state of executing call frame information bytecode.\ntype frameInfo struct {\n\tcie         *dwarfCIE\n\tstart       uint64\n\tloc         uint64\n\tlength      uint64\n\tcfaRegister uint64\n\tcfaOffset   uint64\n}\n\n// frameInfoLine represents one line in the frame table (.debug_frame) at one\n// point in the execution of the bytecode.\ntype frameInfoLine struct {\n\tloc         uint64\n\tcfaRegister uint64\n\tcfaOffset   uint64\n}\n\nfunc (fi *frameInfo) newLine() frameInfoLine {\n\treturn frameInfoLine{\n\t\tloc:         fi.loc,\n\t\tcfaRegister: fi.cfaRegister,\n\t\tcfaOffset:   fi.cfaOffset,\n\t}\n}\n\n// exec executes the given bytecode in the CFI. Most CFI bytecode is actually\n// very simple and provides a way to determine the maximum call frame size.\n//\n// The frame size often changes multiple times in a function, for example the\n// frame size may be adjusted in the prologue and epilogue. Each frameInfoLine\n// may contain such a change.\nfunc (fi *frameInfo) exec(bytecode []byte) ([]frameInfoLine, error) {\n\tvar entries []frameInfoLine\n\tr := bytes.NewBuffer(bytecode)\n\tfor {\n\t\top, err := r.ReadByte()\n\t\tif err != nil {\n\t\t\tif err == io.EOF {\n\t\t\t\tentries = append(entries, fi.newLine())\n\t\t\t\treturn entries, nil\n\t\t\t}\n\t\t\treturn nil, err\n\t\t}\n\t\t// For details on the various opcodes, see:\n\t\t// http://dwarfstd.org/doc/DWARF5.pdf (page 239)\n\t\thighBits := op >> 6 // high order 2 bits\n\t\tlowBits := op & 0x1f\n\t\tswitch highBits {\n\t\tcase 1: // DW_CFA_advance_loc\n\t\t\tfi.loc += uint64(lowBits) * fi.cie.codeAlignmentFactor\n\t\t\tentries = append(entries, fi.newLine())\n\t\tcase 2: // DW_CFA_offset\n\t\t\t// This indicates where a register is saved on the stack in the\n\t\t\t// prologue. We can ignore that for our purposes.\n\t\t\t_, err := readULEB128(r)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\tcase 3: // DW_CFA_restore\n\t\t\t// Restore a register. Used after an outlined function call.\n\t\t\t// It should be possible to ignore this.\n\t\t\t// TODO: check that this is not the stack pointer.\n\t\tcase 0:\n\t\t\tswitch lowBits {\n\t\t\tcase 0: // DW_CFA_nop\n\t\t\t\t// no operation\n\t\t\tcase 0x02: // DW_CFA_advance_loc1\n\t\t\t\t// Very similar to DW_CFA_advance_loc but allows for a slightly\n\t\t\t\t// larger range.\n\t\t\t\toffset, err := r.ReadByte()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tfi.loc += uint64(offset) * fi.cie.codeAlignmentFactor\n\t\t\t\tentries = append(entries, fi.newLine())\n\t\t\tcase 0x03: // DW_CFA_advance_loc2\n\t\t\t\tvar offset uint16\n\t\t\t\terr := binary.Read(r, binary.LittleEndian, &offset)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tfi.loc += uint64(offset) * fi.cie.codeAlignmentFactor\n\t\t\t\tentries = append(entries, fi.newLine())\n\t\t\tcase 0x04: // DW_CFA_advance_loc4\n\t\t\t\tvar offset uint32\n\t\t\t\terr := binary.Read(r, binary.LittleEndian, &offset)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tfi.loc += uint64(offset) * fi.cie.codeAlignmentFactor\n\t\t\t\tentries = append(entries, fi.newLine())\n\t\t\tcase 0x05: // DW_CFA_offset_extended\n\t\t\t\t// Semantics are the same as DW_CFA_offset, but the encoding is\n\t\t\t\t// different. Ignore it just like DW_CFA_offset.\n\t\t\t\t_, err := readULEB128(r) // ULEB128 register\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\t_, err = readULEB128(r) // ULEB128 offset\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\tcase 0x07: // DW_CFA_undefined\n\t\t\t\t// Marks a single register as undefined. This is used to stop\n\t\t\t\t// unwinding in tinygo_startTask using:\n\t\t\t\t//     .cfi_undefined lr\n\t\t\t\t// Ignore this directive.\n\t\t\t\t_, err := readULEB128(r)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\tcase 0x09: // DW_CFA_register\n\t\t\t\t// Copies a register. Emitted by the machine outliner, for example.\n\t\t\t\t// It should be possible to ignore this.\n\t\t\t\t// TODO: check that the stack pointer is not affected.\n\t\t\t\t_, err := readULEB128(r)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\t_, err = readULEB128(r)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\tcase 0x0c: // DW_CFA_def_cfa\n\t\t\t\tregister, err := readULEB128(r)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\toffset, err := readULEB128(r)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tfi.cfaRegister = register\n\t\t\t\tfi.cfaOffset = offset\n\t\t\tcase 0x0e: // DW_CFA_def_cfa_offset\n\t\t\t\toffset, err := readULEB128(r)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tfi.cfaOffset = offset\n\t\t\tdefault:\n\t\t\t\treturn nil, fmt.Errorf(\"could not decode .debug_frame bytecode op 0x%x (for address 0x%x)\", op, fi.loc)\n\t\t\t}\n\t\tdefault:\n\t\t\treturn nil, fmt.Errorf(\"could not decode .debug_frame bytecode op 0x%x (for address 0x%x)\", op, fi.loc)\n\t\t}\n\t}\n}\n\n// Source: https://en.wikipedia.org/wiki/LEB128#Decode_unsigned_integer\nfunc readULEB128(r *bytes.Buffer) (result uint64, err error) {\n\t// TODO: guard against overflowing 64-bit integers.\n\tvar shift uint8\n\tfor {\n\t\tb, err := r.ReadByte()\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t\tresult |= uint64(b&0x7f) << shift\n\t\tif b&0x80 == 0 {\n\t\t\tbreak\n\t\t}\n\t\tshift += 7\n\t}\n\treturn\n}\n\n// Source: https://en.wikipedia.org/wiki/LEB128#Decode_signed_integer\nfunc readSLEB128(r *bytes.Buffer) (result int64, err error) {\n\tvar shift uint8\n\n\tvar b byte\n\tvar rawResult uint64\n\tfor {\n\t\tb, err = r.ReadByte()\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t\trawResult |= uint64(b&0x7f) << shift\n\t\tshift += 7\n\t\tif b&0x80 == 0 {\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// sign bit of byte is second high order bit (0x40)\n\tif shift < 64 && b&0x40 != 0 {\n\t\t// sign extend\n\t\trawResult |= ^uint64(0) << shift\n\t}\n\tresult = int64(rawResult)\n\n\treturn\n}\n"
  },
  {
    "path": "stacksize/stacksize.go",
    "content": "// Package stacksize tries to determine the call graph for ELF binaries and\n// tries to parse stack size information from DWARF call frame information.\npackage stacksize\n\nimport (\n\t\"debug/elf\"\n\t\"encoding/binary\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"sort\"\n)\n\n// set to true to print information useful for debugging\nconst debugPrint = false\n\n// SizeType indicates whether a stack or frame size could be determined and if\n// not, why.\ntype SizeType uint8\n\n// Results after trying to determine the stack size of a function in the call\n// graph. The goal is to find a maximum (bounded) stack size, but sometimes this\n// is not possible for some reasons such as recursion or indirect calls.\nconst (\n\tUndefined SizeType = iota // not yet calculated\n\tUnknown                   // child has unknown stack size\n\tBounded                   // stack size is fixed at compile time (no recursion etc)\n\tRecursive\n\tIndirectCall\n)\n\nfunc (s SizeType) String() string {\n\tswitch s {\n\tcase Undefined:\n\t\treturn \"undefined\"\n\tcase Unknown:\n\t\treturn \"unknown\"\n\tcase Bounded:\n\t\treturn \"bounded\"\n\tcase Recursive:\n\t\treturn \"recursive\"\n\tcase IndirectCall:\n\t\treturn \"indirect call\"\n\tdefault:\n\t\treturn \"<?>\"\n\t}\n}\n\n// CallNode is a node in the call graph (that is, a function). Because this is\n// determined after linking, there may be multiple names for a single function\n// (due to aliases). It is also possible multiple functions have the same name\n// (but are in fact different), for example for static functions in C.\ntype CallNode struct {\n\tNames            []string\n\tAddress          uint64      // address at which the function is linked (without T bit on ARM)\n\tSize             uint64      // symbol size, in bytes\n\tChildren         []*CallNode // functions this function calls\n\tFrameSize        uint64      // frame size, if FrameSizeType is Bounded\n\tFrameSizeType    SizeType    // can be Undefined or Bounded\n\tstackSize        uint64\n\tstackSizeType    SizeType\n\tmissingFrameInfo *CallNode // the child function that is the cause for not being able to determine the stack size\n}\n\nfunc (n *CallNode) String() string {\n\tif n == nil {\n\t\treturn \"<nil>\"\n\t}\n\treturn n.Names[0]\n}\n\n// CallGraph parses the ELF file and reads DWARF call frame information to\n// determine frame sizes for each function, as far as that's possible. Because\n// at this point it is not possible to determine indirect calls, a list of\n// indirect function calling functions needs to be supplied separately.\n//\n// This function does not attempt to determine the stack size for functions.\n// This is done by calling StackSize on a function in the call graph.\nfunc CallGraph(f *elf.File, callsIndirectFunction []string) (map[string][]*CallNode, error) {\n\t// Sanity check that there is exactly one symbol table.\n\t// Multiple symbol tables are possible, but aren't yet supported below.\n\tnumSymbolTables := 0\n\tfor _, section := range f.Sections {\n\t\tif section.Type == elf.SHT_SYMTAB {\n\t\t\tnumSymbolTables++\n\t\t}\n\t}\n\tif numSymbolTables != 1 {\n\t\treturn nil, fmt.Errorf(\"expected exactly one symbol table, got %d\", numSymbolTables)\n\t}\n\n\t// Collect all symbols in the executable.\n\tsymbols := make(map[uint64]*CallNode)\n\tsymbolList := make([]*CallNode, 0)\n\tsymbolNames := make(map[string][]*CallNode)\n\telfSymbols, err := f.Symbols()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tfor _, elfSymbol := range elfSymbols {\n\t\tif elf.ST_TYPE(elfSymbol.Info) != elf.STT_FUNC {\n\t\t\tcontinue\n\t\t}\n\t\taddress := elfSymbol.Value\n\t\tif f.Machine == elf.EM_ARM {\n\t\t\taddress = address &^ 1\n\t\t}\n\t\tvar node *CallNode\n\t\tif n, ok := symbols[address]; ok {\n\t\t\t// Existing symbol.\n\t\t\tif n.Size != elfSymbol.Size {\n\t\t\t\treturn nil, fmt.Errorf(\"symbol at 0x%x has inconsistent size (%d for %s and %d for %s)\", address, n.Size, n.Names[0], elfSymbol.Size, elfSymbol.Name)\n\t\t\t}\n\t\t\tnode = n\n\t\t\tnode.Names = append(node.Names, elfSymbol.Name)\n\t\t} else {\n\t\t\t// New symbol.\n\t\t\tnode = &CallNode{\n\t\t\t\tNames:   []string{elfSymbol.Name},\n\t\t\t\tAddress: address,\n\t\t\t\tSize:    elfSymbol.Size,\n\t\t\t}\n\t\t\tsymbols[address] = node\n\t\t\tsymbolList = append(symbolList, node)\n\t\t}\n\t\tsymbolNames[elfSymbol.Name] = append(symbolNames[elfSymbol.Name], node)\n\t}\n\n\t// Sort symbols by address, for binary searching.\n\tsort.Slice(symbolList, func(i, j int) bool {\n\t\treturn symbolList[i].Address < symbolList[j].Address\n\t})\n\n\t// Load relocations and construct the call graph.\n\tfor _, section := range f.Sections {\n\t\tif section.Type != elf.SHT_REL {\n\t\t\tcontinue\n\t\t}\n\t\tif section.Entsize != 8 {\n\t\t\t// Assume ELF32, this should be fixed.\n\t\t\treturn nil, fmt.Errorf(\"only ELF32 is supported at this time\")\n\t\t}\n\t\tdata, err := section.Data()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tfor i := uint64(0); i < section.Size/section.Entsize; i++ {\n\t\t\toffset := binary.LittleEndian.Uint32(data[i*section.Entsize:])\n\t\t\tinfo := binary.LittleEndian.Uint32(data[i*section.Entsize+4:])\n\t\t\tif elf.R_SYM32(info) == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\telfSymbol := elfSymbols[elf.R_SYM32(info)-1]\n\t\t\tif elf.ST_TYPE(elfSymbol.Info) != elf.STT_FUNC {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\taddress := elfSymbol.Value\n\t\t\tif f.Machine == elf.EM_ARM {\n\t\t\t\taddress = address &^ 1\n\t\t\t}\n\t\t\tchildSym := symbols[address]\n\t\t\tswitch f.Machine {\n\t\t\tcase elf.EM_ARM:\n\t\t\t\trelocType := elf.R_ARM(elf.R_TYPE32(info))\n\t\t\t\tparentSym := findSymbol(symbolList, uint64(offset))\n\t\t\t\tif debugPrint {\n\t\t\t\t\tfmt.Fprintf(os.Stderr, \"found relocation %-24s at %s (0x%x) to %s (0x%x)\\n\", relocType, parentSym, offset, childSym, childSym.Address)\n\t\t\t\t}\n\t\t\t\tisCall := true\n\t\t\t\tswitch relocType {\n\t\t\t\tcase elf.R_ARM_THM_PC22: // actually R_ARM_THM_CALL\n\t\t\t\t\t// used for bl calls\n\t\t\t\tcase elf.R_ARM_THM_JUMP24:\n\t\t\t\t\t// used for b.w jumps\n\t\t\t\t\tisCall = parentSym != childSym\n\t\t\t\tcase elf.R_ARM_THM_JUMP11:\n\t\t\t\t\t// used for b.n jumps\n\t\t\t\t\tisCall = parentSym != childSym\n\t\t\t\tcase elf.R_ARM_THM_MOVW_ABS_NC, elf.R_ARM_THM_MOVT_ABS:\n\t\t\t\t\t// used for getting a function pointer\n\t\t\t\t\tisCall = false\n\t\t\t\tcase elf.R_ARM_ABS32:\n\t\t\t\t\t// when compiling with -Oz (minsize), used for calling\n\t\t\t\t\tisCall = true\n\t\t\t\tdefault:\n\t\t\t\t\treturn nil, fmt.Errorf(\"unknown relocation: %s\", relocType)\n\t\t\t\t}\n\t\t\t\tif isCall {\n\t\t\t\t\tif parentSym != nil {\n\t\t\t\t\t\tparentSym.Children = append(parentSym.Children, childSym)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn nil, fmt.Errorf(\"unknown architecture: %s\", f.Machine)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set fixed frame size information, depending on the architecture.\n\tswitch f.Machine {\n\tcase elf.EM_ARM:\n\t\tknownFrameSizes := map[string]uint64{\n\t\t\t// implemented with assembly in compiler-rt\n\t\t\t\"__aeabi_idivmod\":  3 * 4, // 3 registers on thumb1 but 1 register on thumb2\n\t\t\t\"__aeabi_uidivmod\": 3 * 4, // 3 registers on thumb1 but 1 register on thumb2\n\t\t\t\"__aeabi_ldivmod\":  2 * 4,\n\t\t\t\"__aeabi_uldivmod\": 2 * 4,\n\t\t\t\"__aeabi_memclr\":   2 * 4, // 2 registers on thumb1\n\t\t\t\"__aeabi_memset\":   2 * 4, // 2 registers on thumb1\n\t\t\t\"__aeabi_memcmp\":   2 * 4, // 2 registers on thumb1\n\t\t\t\"__aeabi_memcpy\":   2 * 4, // 2 registers on thumb1\n\t\t\t\"__aeabi_memmove\":  2 * 4, // 2 registers on thumb1\n\t\t\t\"__aeabi_dcmpeq\":   2 * 4,\n\t\t\t\"__aeabi_dcmplt\":   2 * 4,\n\t\t\t\"__aeabi_dcmple\":   2 * 4,\n\t\t\t\"__aeabi_dcmpge\":   2 * 4,\n\t\t\t\"__aeabi_dcmpgt\":   2 * 4,\n\t\t\t\"__aeabi_fcmpeq\":   2 * 4,\n\t\t\t\"__aeabi_fcmplt\":   2 * 4,\n\t\t\t\"__aeabi_fcmple\":   2 * 4,\n\t\t\t\"__aeabi_fcmpge\":   2 * 4,\n\t\t\t\"__aeabi_fcmpgt\":   2 * 4,\n\t\t}\n\t\tfor name, size := range knownFrameSizes {\n\t\t\tif sym, ok := symbolNames[name]; ok {\n\t\t\t\tif len(sym) > 1 {\n\t\t\t\t\treturn nil, fmt.Errorf(\"expected zero or one occurrence of the symbol %s, found %d\", name, len(sym))\n\t\t\t\t}\n\t\t\t\tsym[0].FrameSize = size\n\t\t\t\tsym[0].FrameSizeType = Bounded\n\t\t\t}\n\t\t}\n\t}\n\n\t// Mark functions that do indirect calls (which cannot be determined\n\t// directly from ELF/DWARF information).\n\tfor _, name := range callsIndirectFunction {\n\t\tfor _, fn := range symbolNames[name] {\n\t\t\tfn.stackSizeType = IndirectCall\n\t\t\tfn.missingFrameInfo = fn\n\t\t}\n\t}\n\n\t// Read the .debug_frame section.\n\tsection := f.Section(\".debug_frame\")\n\tif section == nil {\n\t\treturn nil, errors.New(\"no .debug_frame section present, binary was compiled without debug information\")\n\t}\n\tdata, err := section.Data()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"could not read .debug_frame section: %w\", err)\n\t}\n\terr = parseFrames(f, data, symbols)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn symbolNames, nil\n}\n\n// findSymbol determines in which symbol the given address lies.\nfunc findSymbol(symbolList []*CallNode, address uint64) *CallNode {\n\t// TODO: binary search\n\tfor _, sym := range symbolList {\n\t\tif address >= sym.Address && address < sym.Address+sym.Size {\n\t\t\treturn sym\n\t\t}\n\t}\n\treturn nil\n}\n\n// StackSize tries to determine the stack size of the given call graph node. It\n// returns the maximum stack size, whether this size can be known at compile\n// time and the call node responsible for failing to determine the maximum stack\n// usage. The stack size is only valid if sizeType is Bounded.\nfunc (node *CallNode) StackSize() (uint64, SizeType, *CallNode) {\n\tif node.stackSizeType == Undefined {\n\t\tnode.determineStackSize(make(map[*CallNode]struct{}))\n\t}\n\treturn node.stackSize, node.stackSizeType, node.missingFrameInfo\n}\n\n// determineStackSize tries to determine the maximum stack size for this\n// function, recursively.\nfunc (node *CallNode) determineStackSize(parents map[*CallNode]struct{}) {\n\tif _, ok := parents[node]; ok {\n\t\t// The function calls itself (directly or indirectly).\n\t\tnode.stackSizeType = Recursive\n\t\tnode.missingFrameInfo = node\n\t\treturn\n\t}\n\tparents[node] = struct{}{}\n\tdefer func() {\n\t\tdelete(parents, node)\n\t}()\n\tswitch node.FrameSizeType {\n\tcase Bounded:\n\t\t// Determine the stack size recursively.\n\t\tchildMaxStackSize := uint64(0)\n\t\tfor _, child := range node.Children {\n\t\t\tif child.stackSizeType == Undefined {\n\t\t\t\tchild.determineStackSize(parents)\n\t\t\t}\n\t\t\tswitch child.stackSizeType {\n\t\t\tcase Bounded:\n\t\t\t\tif child.stackSize > childMaxStackSize {\n\t\t\t\t\tchildMaxStackSize = child.stackSize\n\t\t\t\t}\n\t\t\tcase Unknown, Recursive, IndirectCall:\n\t\t\t\tnode.stackSizeType = child.stackSizeType\n\t\t\t\tnode.missingFrameInfo = child.missingFrameInfo\n\t\t\t\treturn\n\t\t\tdefault:\n\t\t\t\tpanic(\"unknown child stack size type\")\n\t\t\t}\n\t\t}\n\t\tnode.stackSize = node.FrameSize + childMaxStackSize\n\t\tnode.stackSizeType = Bounded\n\tcase Undefined:\n\t\tnode.stackSizeType = Unknown\n\t\tnode.missingFrameInfo = node\n\tdefault:\n\t\tpanic(\"unknown frame size type\") // unreachable\n\t}\n}\n"
  },
  {
    "path": "targets/adafruit-esp32-feather-v2.json",
    "content": "{\n\t\"inherits\": [\"esp32\"],\n\t\"build-tags\": [\"adafruit_esp32_feather_v2\"]\n}\n"
  },
  {
    "path": "targets/ae-rp2040.json",
    "content": "{\n    \"inherits\": [\n        \"rp2040\"\n    ],\n    \"build-tags\": [\"ae_rp2040\"],\n    \"serial-port\": [\"2e8a:000A\"],\n    \"ldflags\": [\n        \"--defsym=__flash_size=2048K\"\n    ],\n    \"extra-files\": [\n        \"targets/pico-boot-stage2.S\"\n    ]\n}\n\n"
  },
  {
    "path": "targets/arduino-leonardo.json",
    "content": "{\n\t\"inherits\": [\"atmega32u4\"],\n\t\"build-tags\": [\"arduino_leonardo\"],\n\t\"ldflags\": [\n\t\t\"--defsym=_bootloader_size=512\",\n\t\t\"--defsym=_stack_size=512\"\n\t],\n\t\"flash-command\": \"avrdude -c avr109 -p atmega32u4 -b 57600 -P {port} -U flash:w:{hex}:i\",\n\t\"emulator\": \"simavr -m atmega32u4 -f 16000000 {}\"\n}\n"
  },
  {
    "path": "targets/arduino-mega1280.json",
    "content": "{\n    \"inherits\": [\"atmega1280\"],\n    \"build-tags\": [\"arduino_mega1280\"],\n    \"ldflags\": [\n        \"--defsym=_bootloader_size=4096\"\n    ],\n    \"flash-command\":\"avrdude -c arduino -b 57600 -p atmega1280 -P {port} -U flash:w:{hex}:i -v -D\"\n}\n"
  },
  {
    "path": "targets/arduino-mega2560.json",
    "content": "{\n    \"inherits\": [\"atmega2560\"],\n    \"build-tags\": [\"arduino_mega2560\"],\n    \"ldflags\": [\n        \"--defsym=_bootloader_size=8192\"\n    ],\n    \"flash-command\":\"avrdude -c wiring -b 115200 -p atmega2560 -P {port} -U flash:w:{hex}:i -v -D\"\n}\n"
  },
  {
    "path": "targets/arduino-mkr1000.json",
    "content": "{\n    \"inherits\": [\"atsamd21g18a\"],\n    \"build-tags\": [\"arduino_mkr1000\"],\n\t\"serial\": \"usb\",\n    \"flash-command\": \"bossac -i -e -w -v -R -U --port={port} --offset=0x2000 {bin}\",\n    \"flash-1200-bps-reset\": \"true\"\n}\n"
  },
  {
    "path": "targets/arduino-mkrwifi1010.json",
    "content": "{\n    \"inherits\": [\"atsamd21g18a\"],\n    \"build-tags\": [\"arduino_mkrwifi1010\", \"ninafw\"],\n    \"serial\": \"usb\",\n    \"serial-port\": [\"2341:8054\", \"2341:0054\"],\n    \"flash-command\": \"bossac -i -e -w -v -R -U --port={port} --offset=0x2000 {bin}\",\n    \"flash-1200-bps-reset\": \"true\"\n}\n"
  },
  {
    "path": "targets/arduino-nano-new.json",
    "content": "{\n\t\"inherits\": [\"arduino-nano\"],\n\t\"flash-command\": \"avrdude -c arduino -p atmega328p -b 115200 -P {port} -U flash:w:{hex}:i\"\n}\n"
  },
  {
    "path": "targets/arduino-nano.json",
    "content": "{\n\t\"inherits\": [\"atmega328p\"],\n\t\"build-tags\": [\"arduino_nano\"],\n\t\"ldflags\": [\n\t\t\"--defsym=_bootloader_size=512\",\n\t\t\"--defsym=_stack_size=512\"\n\t],\n\t\"flash-command\": \"avrdude -c arduino -p atmega328p -b 57600 -P {port} -U flash:w:{hex}:i\",\n\t\"emulator\": \"simavr -m atmega328p -f 16000000 {}\"\n}\n"
  },
  {
    "path": "targets/arduino-nano33.json",
    "content": "{\n    \"inherits\": [\"atsamd21g18a\"],\n    \"build-tags\": [\"arduino_nano33\", \"ninafw\", \"ninafw_machine_init\"],\n    \"flash-command\": \"bossac -i -e -w -v -R -U --port={port} --offset=0x2000 {bin}\",\n    \"serial-port\": [\"2341:8057\", \"2341:0057\"],\n    \"flash-1200-bps-reset\": \"true\"\n}\n"
  },
  {
    "path": "targets/arduino-zero.json",
    "content": "{\n    \"inherits\": [\"atsamd21g18a\"],\n    \"build-tags\": [\"arduino_zero\"],\n\t\"serial\": \"usb\",\n    \"flash-command\": \"bossac -i -e -w -v -R -U --port={port} --offset=0x2000 {bin}\",\n    \"flash-1200-bps-reset\": \"true\"\n}\n"
  },
  {
    "path": "targets/arduino.json",
    "content": "{\n\t\"inherits\": [\"atmega328p\"],\n\t\"build-tags\": [\"arduino\"],\n\t\"ldflags\": [\n\t\t\"--defsym=_bootloader_size=512\",\n\t\t\"--defsym=_stack_size=512\"\n\t],\n\t\"flash-command\": \"avrdude -c arduino -p atmega328p -P {port} -U flash:w:{hex}:i\",\n\t\"serial-port\": [\"2341:0043\", \"2341:0001\", \"2a03:0043\", \"2341:0243\"],\n\t\"emulator\": \"simavr -m atmega328p -f 16000000 {}\"\n}\n"
  },
  {
    "path": "targets/arm.ld",
    "content": "\n/* Unused, but here to silence a linker warning. */\nENTRY(Reset_Handler)\n\n/* define output sections */\nSECTIONS\n{\n    /* Program code and read-only data goes to FLASH_TEXT. */\n    .text :\n    {\n        KEEP(*(.isr_vector))\n        KEEP(*(.after_isr_vector)) /* for the RP2350 */\n        *(.text)\n        *(.text.*)\n        *(.rodata)\n        *(.rodata.*)\n        . = ALIGN(4);\n    } >FLASH_TEXT\n\n    .tinygo_stacksizes :\n    {\n        *(.tinygo_stacksizes)\n    } > FLASH_TEXT\n\n    /* Put the stack at the bottom of RAM, so that the application will\n     * crash on stack overflow instead of silently corrupting memory.\n     * See: http://blog.japaric.io/stack-overflow-protection/ */\n    .stack (NOLOAD) :\n    {\n        . = ALIGN(4);\n        . += _stack_size;\n        _stack_top = .;\n    } >RAM\n\n    /* Stack for second core (core 1), if there is one. */\n    .stack1 (NOLOAD) :\n    {\n        . = ALIGN(4);\n        . += DEFINED(__num_stacks) && __num_stacks >= 2 ? _stack_size : 0;\n        _stack1_top = .;\n    } >RAM\n\n    /* Start address (in flash) of .data, used by startup code. */\n    _sidata = LOADADDR(.data);\n\n    /* Globals with initial value */\n    .data :\n    {\n        . = ALIGN(4);\n        _sdata = .;        /* used by startup code */\n        *(.data)\n        *(.data.*)\n        . = ALIGN(4);\n        *(.ramfuncs*)      /* Functions that must execute from RAM */\n        . = ALIGN(4);\n        _edata = .;        /* used by startup code */\n    } >RAM AT>FLASH_TEXT\n\n    /* Zero-initialized globals  */\n    .bss :\n    {\n        . = ALIGN(4);\n        _sbss = .;         /* used by startup code */\n        *(.bss)\n        *(.bss.*)\n        *(COMMON)\n        . = ALIGN(4);\n        _ebss = .;         /* used by startup code */\n    } >RAM\n\n    /DISCARD/ :\n    {\n        *(.ARM.exidx)      /* causes 'no memory region specified' error in lld */\n        *(.ARM.exidx.*)    /* causes spurious 'undefined reference' errors */\n    }\n}\n\n/* For the memory allocator. */\n_heap_start = _ebss;\n_heap_end = ORIGIN(RAM) + LENGTH(RAM);\n_globals_start = _sdata;\n_globals_end = _ebss;\n\n/* For the flash API */\n__flash_data_start = LOADADDR(.data) + SIZEOF(.data);\n__flash_data_end = ORIGIN(FLASH_TEXT) + LENGTH(FLASH_TEXT);\n"
  },
  {
    "path": "targets/atmega1280.json",
    "content": "{\n    \"inherits\": [\"avr\"],\n    \"cpu\": \"atmega1280\",\n    \"build-tags\": [\"atmega1280\", \"atmega\"],\n    \"serial\": \"uart\",\n    \"ldflags\": [\n        \"--defsym=_stack_size=512\"\n    ],\n    \"linkerscript\": \"src/device/avr/atmega1280.ld\",\n    \"extra-files\": [\n        \"targets/avr.S\",\n        \"src/device/avr/atmega1280.s\"\n    ]\n}\n"
  },
  {
    "path": "targets/atmega1284p.json",
    "content": "{\n    \"inherits\": [\"avr\"],\n    \"cpu\": \"atmega1284p\",\n    \"build-tags\": [\"atmega1284p\", \"atmega\"],\n    \"serial\": \"uart\",\n    \"ldflags\": [\n        \"--defsym=_bootloader_size=0\",\n        \"--defsym=_stack_size=512\"\n    ],\n    \"linkerscript\": \"src/device/avr/atmega1284p.ld\",\n    \"extra-files\": [\n        \"targets/avr.S\",\n        \"src/device/avr/atmega1284p.s\"\n    ],\n    \"emulator\": \"simavr -m atmega1284p -f 20000000 {}\"\n}\n"
  },
  {
    "path": "targets/atmega2560.json",
    "content": "{\n    \"inherits\": [\"avr\"],\n    \"cpu\": \"atmega2560\",\n    \"build-tags\": [\"atmega2560\", \"atmega\"],\n    \"serial\": \"uart\",\n    \"ldflags\": [\n        \"--defsym=_stack_size=512\"\n    ],\n    \"linkerscript\": \"src/device/avr/atmega2560.ld\",\n    \"extra-files\": [\n        \"targets/avr.S\",\n        \"src/device/avr/atmega2560.s\"\n    ]\n}\n"
  },
  {
    "path": "targets/atmega328p.json",
    "content": "{\n\t\"inherits\": [\"avr\"],\n\t\"cpu\": \"atmega328p\",\n\t\"build-tags\": [\"atmega328p\", \"atmega\", \"avr5\"],\n\t\"serial\": \"uart\",\n\t\"linkerscript\": \"src/device/avr/atmega328p.ld\",\n\t\"extra-files\": [\n\t\t\"targets/avr.S\",\n\t\t\"src/device/avr/atmega328p.s\"\n\t]\n}\n"
  },
  {
    "path": "targets/atmega328pb.json",
    "content": "{\n\t\"inherits\": [\"avr\"],\n\t\"cpu\": \"atmega328pb\",\n\t\"build-tags\": [\"atmega328pb\", \"atmega\", \"avr5\"],\n\t\"ldflags\": [\n\t\t\"--defsym=_bootloader_size=512\",\n\t\t\"--defsym=_stack_size=512\"\n\t],\n\t\"serial\": \"uart\",\n\t\"linkerscript\": \"src/device/avr/atmega328pb.ld\",\n\t\"extra-files\": [\n\t\t\"targets/avr.S\",\n\t\t\"src/device/avr/atmega328pb.s\"\n\t]\n}\n"
  },
  {
    "path": "targets/atmega32u4.json",
    "content": "{\n\t\"inherits\": [\"avr\"],\n\t\"cpu\": \"atmega32u4\",\n\t\"build-tags\": [\"atmega32u4\", \"avr5\"],\n\t\"serial\": \"none\",\n\t\"linkerscript\": \"src/device/avr/atmega32u4.ld\",\n\t\"extra-files\": [\n\t\t\"targets/avr.S\",\n\t\t\"src/device/avr/atmega32u4.s\"\n\t]\n}\n"
  },
  {
    "path": "targets/atsamd21.ld",
    "content": "\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2000  /* First 8KB used by bootloader */\n    RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 0x00008000\n}\n\n_stack_size = 2K;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/atsamd21e18a.json",
    "content": "{\n\t\"inherits\": [\"cortex-m0plus\"],\n\t\"build-tags\": [\"atsamd21e18a\", \"atsamd21e18\", \"atsamd21\", \"sam\"],\n\t\"serial\": \"usb\",\n\t\"linkerscript\": \"targets/atsamd21.ld\",\n\t\"extra-files\": [\n\t\t\"src/device/sam/atsamd21e18a.s\"\n\t],\n\t\"openocd-transport\": \"swd\",\n\t\"openocd-target\": \"at91samdXX\"\n}\n"
  },
  {
    "path": "targets/atsamd21g18a.json",
    "content": "{\n\t\"inherits\": [\"cortex-m0plus\"],\n\t\"build-tags\": [\"atsamd21g18a\", \"atsamd21g18\", \"atsamd21\", \"sam\"],\n\t\"serial\": \"usb\",\n\t\"linkerscript\": \"targets/atsamd21.ld\",\n\t\"extra-files\": [\n\t\t\"src/device/sam/atsamd21g18a.s\"\n\t],\n\t\"openocd-transport\": \"swd\",\n\t\"openocd-target\": \"at91samdXX\"\n}\n"
  },
  {
    "path": "targets/atsamd51.ld",
    "content": "\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x00080000-0x4000  /* First 16KB used by bootloader */\n    RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 0x00030000\n}\n\n_stack_size = 4K;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/atsamd51g19a.json",
    "content": "{\n\t\"inherits\": [\"cortex-m4\"],\n\t\"build-tags\": [\"atsamd51g19a\", \"atsamd51g19\", \"atsamd51\", \"sam\"],\n\t\"linkerscript\": \"targets/atsamd51.ld\",\n\t\"extra-files\": [\n\t\t\"src/device/sam/atsamd51g19a.s\"\n\t],\n\t\"openocd-transport\": \"swd\",\n\t\"openocd-target\": \"atsame5x\"\n}\n"
  },
  {
    "path": "targets/atsamd51j19a.json",
    "content": "{\n\t\"inherits\": [\"cortex-m4\"],\n\t\"build-tags\": [\"atsamd51j19a\", \"atsamd51j19\", \"atsamd51\", \"sam\"],\n\t\"linkerscript\": \"targets/atsamd51.ld\",\n\t\"extra-files\": [\n\t\t\"src/device/sam/atsamd51j19a.s\"\n\t],\n\t\"openocd-transport\": \"swd\",\n\t\"openocd-target\": \"atsame5x\"\n}\n"
  },
  {
    "path": "targets/atsamd51j20a.json",
    "content": "{\n\t\"inherits\": [\"cortex-m4\"],\n\t\"build-tags\": [\"sam\", \"atsamd51\", \"atsamd51j20\", \"atsamd51j20a\"],\n\t\"linkerscript\": \"targets/atsamd51j20a.ld\",\n\t\"extra-files\": [\n\t\t\"src/device/sam/atsamd51j20a.s\"\n\t],\n\t\"openocd-transport\": \"swd\",\n\t\"openocd-target\": \"atsame5x\"\n}\n"
  },
  {
    "path": "targets/atsamd51j20a.ld",
    "content": "\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x00100000-0x4000  /* First 16KB used by bootloader */\n    RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 0x00040000\n}\n\n_stack_size = 4K;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/atsamd51p19a.json",
    "content": "{\n\t\"inherits\": [\"cortex-m4\"],\n\t\"build-tags\": [\"atsamd51p19a\", \"atsamd51p19\", \"atsamd51\", \"sam\"],\n\t\"linkerscript\": \"targets/atsamd51.ld\",\n\t\"extra-files\": [\n\t\t\"src/device/sam/atsamd51p19a.s\"\n\t],\n\t\"openocd-transport\": \"swd\",\n\t\"openocd-target\": \"atsame5x\"\n}\n"
  },
  {
    "path": "targets/atsamd51p20a.json",
    "content": "{\n\t\"inherits\": [\"cortex-m4\"],\n\t\"build-tags\": [\"sam\", \"atsamd51\", \"atsamd51p20\", \"atsamd51p20a\"],\n\t\"linkerscript\": \"targets/atsamd51p20a.ld\",\n\t\"extra-files\": [\n\t\t\"src/device/sam/atsamd51p20a.s\"\n\t],\n\t\"openocd-transport\": \"swd\",\n\t\"openocd-target\": \"atsame5x\"\n}\n"
  },
  {
    "path": "targets/atsamd51p20a.ld",
    "content": "\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x00100000-0x4000  /* First 16KB used by bootloader */\n    RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 0x00040000\n}\n\n_stack_size = 4K;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/atsame51j19a.json",
    "content": "{\n\t\"inherits\": [\"cortex-m4\"],\n\t\"build-tags\": [\"atsame51j19a\", \"atsame51j19\", \"atsame51\", \"atsame5x\", \"sam\"],\n\t\"linkerscript\": \"targets/atsame5xx19.ld\",\n\t\"extra-files\": [\n\t\t\"src/device/sam/atsame51j19a.s\"\n\t],\n\t\"openocd-transport\": \"swd\",\n\t\"openocd-target\": \"atsame5x\"\n}\n"
  },
  {
    "path": "targets/atsame54-xpro.json",
    "content": "{\n    \"inherits\": [\"atsame54p20a\"],\n    \"build-tags\": [\"atsame54_xpro\"],\n    \"serial\": \"usb\",\n    \"flash-method\": \"openocd\",\n    \"openocd-interface\": \"cmsis-dap\"\n}\n"
  },
  {
    "path": "targets/atsame54p20a.json",
    "content": "{\n\t\"inherits\": [\"cortex-m4\"],\n\t\"build-tags\": [\"sam\", \"atsame5x\", \"atsame54\", \"atsame54p20\", \"atsame54p20a\"],\n\t\"linkerscript\": \"targets/atsame5xx20-no-bootloader.ld\",\n\t\"extra-files\": [\n\t\t\"src/device/sam/atsame54p20a.s\"\n\t],\n\t\"openocd-transport\": \"swd\",\n\t\"openocd-target\": \"atsame5x\"\n}\n"
  },
  {
    "path": "targets/atsame5xx19.ld",
    "content": "\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x00080000-0x4000  /* First 16KB used by bootloader */\n    RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 0x00030000\n}\n\n_stack_size = 4K;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/atsame5xx20-no-bootloader.ld",
    "content": "\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x00000000+0x0000, LENGTH = 0x00100000-0x0000\n    RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 0x00040000\n}\n\n_stack_size = 4K;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/attiny1616.json",
    "content": "{\n    \"inherits\": [\"avrtiny\"],\n    \"cpu\": \"attiny1616\",\n    \"build-tags\": [\"attiny1616\"],\n    \"gc\": \"none\",\n    \"cflags\": [\n        \"-D__AVR_ARCH__=103\"\n    ],\n    \"linkerscript\": \"src/device/avr/attiny1616.ld\",\n    \"extra-files\": [\n        \"src/device/avr/attiny1616.s\"\n    ],\n    \"flash-command\": \"pymcuprog write -f {hex} --erase --verify -d attiny1616 -t uart -u {port}\"\n}\n"
  },
  {
    "path": "targets/attiny85.json",
    "content": "{\n\t\"inherits\": [\"avr\"],\n\t\"cpu\": \"attiny85\",\n\t\"build-tags\": [\"attiny85\", \"attiny\", \"avr2\", \"avr25\"],\n\t\"cflags\": [\n\t\t\"-D__AVR_ARCH__=25\"\n\t],\n\t\"linkerscript\": \"src/device/avr/attiny85.ld\",\n\t\"extra-files\": [\n\t\t\"targets/avr.S\",\n\t\t\"src/device/avr/attiny85.s\"\n\t]\n}\n"
  },
  {
    "path": "targets/avr.S",
    "content": "; This file provides common code across AVRs that cannot be implemented directly\n; in Go.\n; The reset vector is device-specific and is generated by tools/gen-device-avr.py.\n\n; These definitions are necessary because LLVM does not yet know these register\n; aliases. See: https://reviews.llvm.org/D96492\n#define xl r26\n#define xh r27\n#define yl r28\n#define yh r29\n#define zl r30\n#define zh r31\n\n; Ugly hack until https://reviews.llvm.org/D137572 is merged.\n#if !defined(__AVR_HAVE_ELPM__) && defined(__flash1)\n#define __AVR_HAVE_ELPM__\n#endif\n\n; Startup code\n.section .text.__vector_RESET\n.global  __vector_RESET\n__vector_RESET:\n    clr  r1          ; r1 is expected to be 0 by the C calling convention\n\n    ; Set up the stack pointer.\n    ldi  xl, lo8(_stack_top)\n    ldi  xh, hi8(_stack_top)\n    out  0x3d, xl; SPL\n    out  0x3e, xh; SPH\n\n    ; Subtract one from the stack pointer, so it doesn't point in the .data section.\n    push r0\n\n    ; Initialize .data\ninit_data:\n    ldi  xl, lo8(_sdata)\n    ldi  xh, hi8(_sdata)\n    ldi  yl, lo8(_edata)\n    ldi  yh, hi8(_edata)\n    ldi  zl, lo8(_sidata)\n    ldi  zh, hi8(_sidata)\n#ifdef __AVR_HAVE_ELPM__\n    ldi  r16, hh8(_sidata) ; RAMPZ = hh8(_sidata)\n    out  0x3b, r16\n#endif\ninit_data_loop:\n    cp   xl, yl         ; if x == y\n    cpc  xh, yh\n    breq init_data_end  ; goto main\n#ifdef __AVR_HAVE_ELPM__\n    elpm r0, Z+         ; r0 = *(z++)\n#else\n    lpm  r0, Z+         ; r0 = *(z++)\n#endif\n    st   X+, r0         ; *(x++) = r0\n    rjmp init_data_loop ; goto init_data_loop\ninit_data_end:\n\n    ; main will be placed right after here by the linker script so there's no\n    ; need to jump.\n\n\n; The only thing this WDT handler really does is disable itself, to get out of\n; sleep mode.\n.section .text.__vector_WDT\n.global  __vector_WDT\n__vector_WDT:\n    push r16\n\n    clr  r16\n    wdr            ; Reset watchdog\n    out  0x34, r16 ; Clear reset reason (MCUSR)\n\n    ; part 1: set WDCE and WDE to enable editing WDTCSR\n    lds  r16, 0x60 ; r16 = WDTCSR\n    ori  r16, 0x18 ; r16 |= WDCE | WDE\n    sts  0x60, r16 ; WDTCSR = r16\n\n    ; part 2: within 4 clock cycles, set the new value for WDTCSR\n    clr  r16\n    sts  0x60, r16 ; WDTCSR = 0\n\n    pop  r16\n    reti\n"
  },
  {
    "path": "targets/avr.json",
    "content": "{\n\t\"llvm-target\": \"avr\",\n\t\"build-tags\": [\"avr\", \"baremetal\", \"linux\", \"arm\"],\n\t\"goos\": \"linux\",\n\t\"goarch\": \"arm\",\n\t\"gc\": \"conservative\",\n\t\"linker\": \"ld.lld\",\n\t\"scheduler\": \"none\",\n\t\"rtlib\": \"compiler-rt\",\n\t\"libc\": \"picolibc\",\n\t\"default-stack-size\": 256,\n\t\"cflags\": [\n\t\t\"-Werror\"\n\t],\n\t\"ldflags\": [\n\t\t\"-T\", \"targets/avr.ld\",\n\t\t\"--gc-sections\"\n\t],\n\t\"extra-files\": [\n\t\t\"src/internal/task/task_stack_avr.S\",\n\t\t\"src/runtime/asm_avr.S\"\n\t],\n\t\"gdb\": [\"avr-gdb\"]\n}\n"
  },
  {
    "path": "targets/avr.ld",
    "content": "\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0,                      LENGTH = __flash_size - _bootloader_size\n    RAM (xrw)       : ORIGIN = 0x800000 + __ram_start, LENGTH = __ram_size\n}\n\nENTRY(main)\n\nSECTIONS\n{\n    .text :\n    {\n        KEEP(*(.vectors))\n        KEEP(*(.text.__vector_RESET))\n        KEEP(*(.text.main)) /* main must follow the reset handler */\n        *(.text)\n        *(.text.*)\n        *(.progmem)\n        *(.progmem.*)\n        . = ALIGN(16); /* needed with ld.lld for some reasoon */\n    }\n\n    .stack (NOLOAD) :\n    {\n        . += _stack_size;\n        _stack_top = .;\n    } >RAM\n\n    _sidata = LOADADDR(.data);\n\n    .data :\n    {\n        _sdata = .;        /* used by startup code */\n        *(.rodata)\n        *(.rodata.*)\n        *(.data)\n        *(.data*)\n        _edata = .;        /* used by startup code */\n    } >RAM AT>FLASH_TEXT\n\n    .bss :\n    {\n        _sbss = .;         /* used by startup code */\n        *(.bss)\n        *(.bss*)\n        *(COMMON)\n        _ebss = .;         /* used by startup code */\n    } >RAM\n}\n\n/* For the memory allocator. */\n_heap_start = _ebss;\n_heap_end = ORIGIN(RAM) + LENGTH(RAM);\n_globals_start = _sdata;\n_globals_end = _ebss;\n"
  },
  {
    "path": "targets/avrtiny.S",
    "content": "#define __tmp_reg__ r16\n#define __zero_reg__ r17\n\n; Startup code\n.section .text.__vector_RESET\n.global  __vector_RESET\n__vector_RESET:\n    clr  __zero_reg__ ; this register is expected to be 0 by the C calling convention\n\n    ; Keep the stack pointer at the default location, which is RAMEND.\n\n; Initialize .data section.\n.section .text.__do_copy_data,\"ax\",@progbits\n.global __do_copy_data\n__do_copy_data:\n    ldi  xl, lo8(__data_start)\n    ldi  xh, hi8(__data_start)\n    ldi  yl, lo8(__data_end)\n    ldi  yh, hi8(__data_end)\n    ldi  zl, lo8(__data_load_start)\n    ldi  zh, hi8(__data_load_start)\n1: ; loop\n    cp   xl, yl         ; if x == y\n    cpc  xh, yh\n    breq 2f             ; goto end\n    ld   r16, Z+        ; r0 = *(z++)\n    st   X+, r16        ; *(x++) = r0\n    rjmp 1b             ; goto loop\n2: ; end\n\n; Initialize .bss section.\n.section .text.__do_clear_bss,\"ax\",@progbits\n.global __do_clear_bss\n__do_clear_bss:\n    ldi  xl, lo8(__bss_start)\n    ldi  xh, hi8(__bss_start)\n    ldi  yl, lo8(__bss_end)\n1: ; loop\n    cp   xl, yl           ; if x == y\n    breq 2f               ; goto end\n    st   X+, __zero_reg__ ; *(x++) = 0\n    rjmp 1b               ; goto loop\n2: ; end\n"
  },
  {
    "path": "targets/avrtiny.json",
    "content": "{\n\t\"llvm-target\": \"avr\",\n\t\"build-tags\": [\"avr\", \"avrtiny\", \"baremetal\", \"linux\", \"arm\"],\n\t\"goos\": \"linux\",\n\t\"goarch\": \"arm\",\n\t\"gc\": \"conservative\",\n\t\"linker\": \"ld.lld\",\n\t\"scheduler\": \"none\",\n\t\"rtlib\": \"compiler-rt\",\n\t\"libc\": \"picolibc\",\n\t\"default-stack-size\": 256,\n\t\"cflags\": [\n\t\t\"-Werror\"\n\t],\n\t\"ldflags\": [\n\t\t\"-T\", \"targets/avrtiny.ld\",\n\t\t\"--gc-sections\"\n\t],\n\t\"extra-files\": [\n\t\t\"src/internal/task/task_stack_avr.S\",\n\t\t\"src/runtime/asm_avr.S\",\n\t\t\"targets/avrtiny.S\"\n\t],\n\t\"gdb\": [\"avr-gdb\"]\n}\n"
  },
  {
    "path": "targets/avrtiny.ld",
    "content": "/* Linker script for AVRs with a unified flash and RAM address space. This\n * includes the ATtiny10 and the ATtiny1616.\n */\n\nMEMORY\n{\n    FLASH_TEXT (x) : ORIGIN = 0,                    LENGTH = __flash_size\n    FLASH_DATA (r) : ORIGIN = __mapped_flash_start, LENGTH = __flash_size\n    RAM (xrw)      : ORIGIN = __ram_start,          LENGTH = __ram_size\n}\n\nENTRY(main)\n\nSECTIONS\n{\n    .text :\n    {\n        KEEP(*(.vectors))\n        *(.text.__vector_RESET)\n        KEEP(*(.text.__do_copy_data)) /* TODO: only use when __do_copy_data is requested */\n        KEEP(*(.text.__do_clear_bss))\n        KEEP(*(.text.main)) /* main must follow the reset handler */\n        *(.text)\n        *(.text.*)\n    } > FLASH_TEXT\n\n    /* Read-only data is stored in flash, but is read from an offset (0x4000 or\n     * 0x8000 depending on the chip). This requires some weird math to get it in\n     * the right place.\n     */\n    .rodata ORIGIN(FLASH_DATA) + ADDR(.text) + SIZEOF(.text):\n    {\n        *(.rodata)\n        *(.rodata.*)\n    } AT>FLASH_TEXT\n\n    /* The address to which the data section should be copied by the startup\n     * code.\n     */\n    __data_load_start = ORIGIN(FLASH_DATA) + LOADADDR(.data);\n\n    .data :\n    {\n        __data_start = .;  /* used by startup code */\n        *(.data)\n        *(.data*)\n        __data_end = .;    /* used by startup code */\n    } >RAM AT>FLASH_TEXT\n\n    .bss :\n    {\n        __bss_start = .;   /* used by startup code */\n        *(.bss)\n        *(.bss*)\n        *(COMMON)\n        __bss_end = .;     /* used by startup code */\n    } >RAM\n}\n"
  },
  {
    "path": "targets/badger2040-w.json",
    "content": "{\n    \"inherits\": [\n        \"rp2040\"\n    ],\n    \"serial-port\": [\"2e8a:0003\"],\n    \"default-stack-size\": 8192,\n    \"build-tags\": [\"badger2040_w\", \"cyw43439\"],\n    \"ldflags\": [\n        \"--defsym=__flash_size=1020K\"\n    ],\n    \"extra-files\": [\n        \"targets/pico-boot-stage2.S\"\n    ]\n}\n"
  },
  {
    "path": "targets/badger2040.json",
    "content": "{\n    \"inherits\": [\n        \"rp2040\"\n    ],\n    \"serial-port\": [\"2e8a:0003\"],\n    \"default-stack-size\": 8192,\n    \"build-tags\": [\"badger2040\"],\n    \"ldflags\": [\n        \"--defsym=__flash_size=1020K\"\n    ],\n    \"extra-files\": [\n        \"targets/pico-boot-stage2.S\"\n    ]\n}\n"
  },
  {
    "path": "targets/bluemicro840.json",
    "content": "{\n    \"inherits\": [\"nrf52840\", \"nrf52840-s140v6-uf2\"],\n    \"build-tags\": [\"bluemicro840\"],\n    \"serial-port\": [\"1d50:6161\"],\n    \"msd-volume-name\": [\"BLUEMICRO\"]\n}\n"
  },
  {
    "path": "targets/bluepill-clone.json",
    "content": "{\n\t\"inherits\": [\"bluepill\"],\n\t\"openocd-commands\": [\"set CPUTAPID 0x2ba01477\"]\n}\n"
  },
  {
    "path": "targets/bluepill.json",
    "content": "{\n\t\"inherits\": [\"cortex-m3\"],\n\t\"build-tags\": [\"bluepill\", \"stm32f103\", \"stm32f1\", \"stm32\"],\n\t\"serial\": \"uart\",\n\t\"linkerscript\": \"targets/stm32.ld\",\n\t\"extra-files\": [\n\t\t\"src/device/stm32/stm32f103.s\"\n\t],\n\t\"flash-method\": \"openocd\",\n\t\"openocd-interface\": \"stlink-v2\",\n\t\"openocd-target\": \"stm32f1x\"\n}\n"
  },
  {
    "path": "targets/btt-skr-pico.json",
    "content": "{\n    \"inherits\": [\n        \"rp2040\"\n    ],\n    \"build-tags\": [\"btt_skr_pico\"],\n    \"serial-port\": [\"2e8a:000A\"],\n    \"ldflags\": [\n        \"--defsym=__flash_size=16M\"\n    ],\n    \"extra-files\": [\n        \"targets/pico-boot-stage2.S\"\n    ]\n}\n"
  },
  {
    "path": "targets/challenger-rp2040.json",
    "content": "{\n    \"inherits\": [\n        \"rp2040\"\n    ],\n    \"serial-port\": [\"2e8a:1023\"],\n    \"default-stack-size\": 8192,\n    \"build-tags\": [\"challenger_rp2040\"],\n    \"ldflags\": [\n        \"--defsym=__flash_size=8M\"\n    ],\n    \"extra-files\": [\n        \"targets/feather-rp2040-boot-stage2.S\"\n    ]\n}\n"
  },
  {
    "path": "targets/circuitplay-bluefruit.json",
    "content": "{\n    \"inherits\": [\"nrf52840\", \"nrf52840-s140v6-uf2\"],\n    \"build-tags\": [\"circuitplay_bluefruit\"],\n    \"serial-port\": [\"239a:8045\"],\n    \"msd-volume-name\": [\"CPLAYBTBOOT\"]\n}\n"
  },
  {
    "path": "targets/circuitplay-express.json",
    "content": "{\n    \"inherits\": [\"atsamd21g18a\"],\n    \"build-tags\": [\"circuitplay_express\"],\n    \"flash-1200-bps-reset\": \"true\",\n    \"flash-method\": \"msd\",\n    \"serial-port\": [\"239a:8018\"],\n    \"msd-volume-name\": [\"CPLAYBOOT\"],\n    \"msd-firmware-name\": \"firmware.uf2\"\n}\n"
  },
  {
    "path": "targets/clue-alpha.json",
    "content": "{\n    \"inherits\": [\"nrf52840\", \"nrf52840-s140v6-uf2\"],\n    \"build-tags\": [\"clue_alpha\"],\n    \"serial-port\": [\"239a:8072\", \"239a:8071\"],\n    \"msd-volume-name\": [\"CLUEBOOT\"]\n}\n"
  },
  {
    "path": "targets/clue.json",
    "content": "{\n\t\"inherits\": [\"clue-alpha\"]\n}\n"
  },
  {
    "path": "targets/cortex-m-qemu.json",
    "content": "{\n\t\"inherits\": [\"cortex-m3\"],\n\t\"build-tags\": [\"qemu\", \"lm3s6965\"],\n\t\"linkerscript\": \"targets/lm3s6965.ld\",\n        \"default-stack-size\": 4096,\n\t\"extra-files\": [\n\t\t\"targets/cortex-m-qemu.s\"\n\t],\n\t\"emulator\": \"qemu-system-arm -machine lm3s6965evb -semihosting -nographic -kernel {}\"\n}\n"
  },
  {
    "path": "targets/cortex-m-qemu.s",
    "content": "// Generic Cortex-M interrupt vector.\n// This vector is used by the Cortex-M QEMU target.\n\n.cfi_sections .debug_frame\n.syntax unified\n\n// This is the default handler for interrupts, if triggered but not defined.\n.section .text.Default_Handler\n.global  Default_Handler\n.type    Default_Handler, %function\nDefault_Handler:\n    .cfi_startproc\n    wfe\n    b    Default_Handler\n    .cfi_endproc\n.size Default_Handler, .-Default_Handler\n\n// Avoid the need for repeated .weak and .set instructions.\n.macro IRQ handler\n    .weak  \\handler\n    .set   \\handler, Default_Handler\n.endm\n\n.section .isr_vector, \"a\", %progbits\n.global  __isr_vector\n__isr_vector:\n    // Interrupt vector as defined by Cortex-M, starting with the stack top.\n    // On reset, SP is initialized with *0x0 and PC is loaded with *0x4, loading\n    // _stack_top and Reset_Handler.\n    .long _stack_top\n    .long Reset_Handler\n    .long NMI_Handler\n    .long HardFault_Handler\n    .long MemoryManagement_Handler\n    .long BusFault_Handler\n    .long UsageFault_Handler\n    .long 0\n    .long 0\n    .long 0\n    .long 0\n    .long SVC_Handler\n    .long DebugMon_Handler\n    .long 0\n    .long PendSV_Handler\n    .long SysTick_Handler\n\n    // Define default implementations for interrupts, redirecting to\n    // Default_Handler when not implemented.\n    IRQ NMI_Handler\n    IRQ HardFault_Handler\n    IRQ MemoryManagement_Handler\n    IRQ BusFault_Handler\n    IRQ UsageFault_Handler\n    IRQ SVC_Handler\n    IRQ DebugMon_Handler\n    IRQ PendSV_Handler\n    IRQ SysTick_Handler\n\n.size __isr_vector, .-__isr_vector\n"
  },
  {
    "path": "targets/cortex-m.json",
    "content": "{\n\t\"build-tags\": [\"cortexm\", \"baremetal\", \"linux\", \"arm\"],\n\t\"goos\": \"linux\",\n\t\"goarch\": \"arm\",\n\t\"gc\": \"conservative\",\n\t\"scheduler\": \"tasks\",\n\t\"linker\": \"ld.lld\",\n\t\"rtlib\": \"compiler-rt\",\n\t\"libc\": \"picolibc\",\n\t\"automatic-stack-size\": true,\n\t\"default-stack-size\": 2048,\n\t\"cflags\": [\n\t\t\"-Werror\",\n\t\t\"-fshort-enums\",\n\t\t\"-fomit-frame-pointer\",\n\t\t\"-mfloat-abi=soft\",\n\t\t\"-fno-exceptions\", \"-fno-unwind-tables\", \"-fno-asynchronous-unwind-tables\",\n\t\t\"-ffunction-sections\", \"-fdata-sections\"\n\t],\n\t\"ldflags\": [\n\t\t\"--emit-relocs\",\n\t\t\"--gc-sections\"\n\t],\n\t\"extra-files\": [\n\t\t\"src/device/arm/cortexm.S\",\n\t\t\"src/internal/task/task_stack_cortexm.S\",\n\t\t\"src/runtime/asm_arm.S\"\n\t],\n\t\"gdb\": [\"gdb-multiarch\", \"arm-none-eabi-gdb\", \"gdb\"]\n}\n"
  },
  {
    "path": "targets/cortex-m0.json",
    "content": "{\n\t\"inherits\": [\"cortex-m\"],\n\t\"llvm-target\": \"thumbv6m-unknown-unknown-eabi\",\n\t\"cpu\": \"cortex-m0\",\n\t\"features\": \"+armv6-m,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp\"\n}\n"
  },
  {
    "path": "targets/cortex-m0plus.json",
    "content": "{\n\t\"inherits\": [\"cortex-m\"],\n\t\"llvm-target\": \"thumbv6m-unknown-unknown-eabi\",\n\t\"cpu\": \"cortex-m0plus\",\n\t\"features\": \"+armv6-m,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp\"\n}\n"
  },
  {
    "path": "targets/cortex-m3.json",
    "content": "{\n\t\"inherits\": [\"cortex-m\"],\n\t\"llvm-target\": \"thumbv7m-unknown-unknown-eabi\",\n\t\"cpu\": \"cortex-m3\",\n\t\"features\": \"+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp\"\n}\n"
  },
  {
    "path": "targets/cortex-m33.json",
    "content": "{\n    \"inherits\": [\"cortex-m\"],\n    \"llvm-target\": \"thumbv8m.main-unknown-unknown-eabi\",\n    \"cpu\": \"cortex-m33\",\n    \"features\": \"+armv8-m.main,+dsp,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp\"\n}\n"
  },
  {
    "path": "targets/cortex-m4.json",
    "content": "{\n\t\"inherits\": [\"cortex-m\"],\n\t\"llvm-target\": \"thumbv7em-unknown-unknown-eabi\",\n\t\"cpu\": \"cortex-m4\",\n\t\"features\": \"+armv7e-m,+dsp,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp\"\n}\n"
  },
  {
    "path": "targets/cortex-m7.json",
    "content": "{\n\t\"inherits\": [\"cortex-m\"],\n\t\"llvm-target\": \"thumbv7em-unknown-unknown-eabi\",\n\t\"cpu\": \"cortex-m7\",\n\t\"features\": \"+armv7e-m,+dsp,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp\"\n}\n"
  },
  {
    "path": "targets/d1mini.json",
    "content": "{\n\t\"inherits\": [\"nodemcu\"]\n}\n"
  },
  {
    "path": "targets/digispark.json",
    "content": "{\n\t\"inherits\": [\"attiny85\"],\n\t\"build-tags\": [\"digispark\"],\n\t\"ldflags\": [\n\t\t\"--defsym=_bootloader_size=2180\",\n\t\t\"--defsym=_stack_size=128\"\n\t],\n\t\"flash-command\": \"micronucleus --run {hex}\",\n\t\"emulator\": \"simavr -m attiny85 -f 16000000 {}\"\n}\n"
  },
  {
    "path": "targets/elecrow-rp2040.json",
    "content": "{\n    \"inherits\": [\"rp2040\"],\n    \"build-tags\": [\"elecrow_rp2040\", \"comboat_fw\"],\n    \"serial-port\": [\"2e8a:000a\"],\n    \"default-stack-size\": 8192,\n    \"ldflags\": [\n        \"--defsym=__flash_size=8M\"\n    ],\n    \"extra-files\": [\n        \"targets/pico-boot-stage2.S\"\n    ]\n}\n"
  },
  {
    "path": "targets/elecrow-rp2350.json",
    "content": "{\n    \"inherits\": [\"rp2350\"],\n    \"build-tags\": [\"elecrow_rp2350\", \"comboat_fw\"],\n    \"serial-port\": [\"2e8a:000f\"],\n    \"default-stack-size\": 8192,\n    \"ldflags\": [\n        \"--defsym=__flash_size=8M\"\n    ],\n    \"extra-files\": [\n        \"targets/pico-boot-stage2.S\"\n    ]\n}\n"
  },
  {
    "path": "targets/esp-c3-32s-kit.json",
    "content": "{\n\t\"inherits\": [\"esp32c3\"],\n\t\"build-tags\": [\"esp_c3_32s_kit\"],\n\t\"serial-port\": [\"1a86:7523\"]\n}\n"
  },
  {
    "path": "targets/esp32-c3-devkit-rust-1.json",
    "content": "{\n\t\"inherits\": [\"esp32c3\"],\n\t\"build-tags\": [\"esp32_c3_devkit_rust_1\"]\n}\n"
  },
  {
    "path": "targets/esp32-coreboard-v2.json",
    "content": "{\n\t\"inherits\": [\"esp32\"],\n\t\"build-tags\": [\"esp32_coreboard_v2\"]\n}\n"
  },
  {
    "path": "targets/esp32-mini32.json",
    "content": "{\n\t\"inherits\": [\"esp32-coreboard-v2\"]\n}\n"
  },
  {
    "path": "targets/esp32.json",
    "content": "{\n\t\"inherits\": [\"xtensa\"],\n\t\"cpu\": \"esp32\",\n\t\"features\": \"+atomctl,+bool,+clamps,+coprocessor,+debug,+density,+dfpaccel,+div32,+exception,+fp,+highpriinterrupts,+interrupt,+loop,+mac16,+memctl,+minmax,+miscsr,+mul32,+mul32high,+nsa,+prid,+regprotect,+rvector,+s32c1i,+sext,+threadptr,+timerint,+windowed\",\n\t\"build-tags\": [\"esp32\", \"esp\"],\n\t\"scheduler\": \"tasks\",\n\t\"serial\": \"uart\",\n\t\"linker\": \"ld.lld\",\n\t\"default-stack-size\": 2048,\n\t\"rtlib\": \"compiler-rt\",\n\t\"libc\": \"picolibc\",\n\t\"linkerscript\": \"targets/esp32.ld\",\n\t\"extra-files\": [\n\t\t\"src/device/esp/esp32.S\",\n\t\t\"src/internal/task/task_stack_esp32.S\"\n\t],\n\t\"binary-format\": \"esp32\",\n\t\"flash-command\": \"esptool.py --chip=esp32 --port {port} write_flash 0x1000 {bin} -ff 80m -fm dout\",\n\t\"emulator\": \"qemu-system-xtensa -machine esp32 -nographic -drive file={img},if=mtd,format=raw\",\n\t\"gdb\": [\"xtensa-esp32-elf-gdb\"]\n}\n"
  },
  {
    "path": "targets/esp32.ld",
    "content": "/* Linker script for the ESP32 */\n\nMEMORY\n{\n    /* Data RAM. Allows byte access.\n     * There are various data RAM regions:\n     *   SRAM2: 0x3FFA_E000..0x3FFD_FFFF (72 + 128 = 200K)\n     *   SRAM1: 0x3FFE_0000..0x3FFF_FFFF (128K)\n     * This gives us 328K of contiguous RAM, which is the largest span possible.\n     * SRAM1 has other addresses as well but the datasheet seems to indicate\n     * these are aliases.\n     */\n    DRAM  (rw) : ORIGIN = 0x3FFAE000, LENGTH = 200K + 128K /* Internal SRAM 1 + 2 */\n\n    /* Instruction RAM. */\n    IRAM  (x)  : ORIGIN = 0x40080000, LENGTH = 128K /* Internal SRAM 0 */\n}\n\n/* The entry point. It is set in the image flashed to the chip, so must be\n * defined.\n */\nENTRY(call_start_cpu0)\n\nSECTIONS\n{\n    /* Constant literals and code. Loaded into IRAM for now. Eventually, most\n     * code should be executed directly from flash.\n     * Note that literals must be before code for the l32r instruction to work.\n     */\n    .text : ALIGN(4)\n    {\n        *(.literal.call_start_cpu0)\n        *(.text.call_start_cpu0)\n        *(.literal .text)\n        *(.literal.* .text.*)\n    } >IRAM\n\n    /* Put the stack at the bottom of DRAM, so that the application will\n     * crash on stack overflow instead of silently corrupting memory.\n     * See: http://blog.japaric.io/stack-overflow-protection/ */\n    .stack (NOLOAD) :\n    {\n        . = ALIGN(16);\n        . += _stack_size;\n        _stack_top = .;\n    } >DRAM\n\n    /* Constant global variables.\n     * They are loaded in DRAM for ease of use. Eventually they should be stored\n     * in flash and loaded directly from there but they're kept in RAM to make\n     * sure they can always be accessed (even in interrupts).\n     */\n    .rodata : ALIGN(4)\n    {\n        *(.rodata)\n        *(.rodata.*)\n    } >DRAM\n\n    /* Mutable global variables.\n     */\n    .data : ALIGN(4)\n    {\n        _sdata = ABSOLUTE(.);\n        *(.data)\n        *(.data.*)\n        _edata = ABSOLUTE(.);\n    } >DRAM\n\n    /* Check that the boot ROM stack (for the APP CPU) does not overlap with the\n     * data that is loaded by the boot ROM. There may be ways to avoid this\n     * issue if it occurs in practice.\n     * The magic value here is _stack_sentry in the boot ROM ELF file.\n     */\n    ASSERT(_edata < 0x3ffe1320, \"the .data section overlaps with the stack used by the boot ROM, possibly causing corruption at startup\")\n\n    /* Global variables that are mutable and zero-initialized.\n     * These must be zeroed at startup (unlike data, which is loaded by the\n     * bootloader).\n     */\n    .bss (NOLOAD) : ALIGN(4)\n    {\n        . = ALIGN (4);\n        _sbss = ABSOLUTE(.);\n        *(.bss)\n        *(.bss.*)\n        . = ALIGN (4);\n        _ebss = ABSOLUTE(.);\n    } >DRAM\n}\n\n/* For the garbage collector.\n */\n_globals_start = _sdata;\n_globals_end = _ebss;\n_heap_start = _ebss;\n_heap_end = ORIGIN(DRAM) + LENGTH(DRAM);\n\n_stack_size = 4K;\n\n/* From ESP-IDF:\n * components/esp_rom/esp32/ld/esp32.rom.newlib-funcs.ld\n * This is the subset that is sometimes used by LLVM during codegen, and thus\n * must always be present.\n */\nmemcpy  = 0x4000c2c8;\nmemmove = 0x4000c3c0;\nmemset  = 0x4000c44c;\n\n/* From ESP-IDF:\n * components/esp_rom/esp32/ld/esp32.rom.libgcc.ld\n * These are called from LLVM during codegen. The original license is Apache\n * 2.0, but I believe that a list of function names and addresses can't really\n * be copyrighted.\n */\n__absvdi2      = 0x4006387c;\n__absvsi2      = 0x40063868;\n__adddf3       = 0x40002590;\n__addsf3       = 0x400020e8;\n__addvdi3      = 0x40002cbc;\n__addvsi3      = 0x40002c98;\n__ashldi3      = 0x4000c818;\n__ashrdi3      = 0x4000c830;\n__bswapdi2     = 0x40064b08;\n__bswapsi2     = 0x40064ae0;\n__clrsbdi2     = 0x40064b7c;\n__clrsbsi2     = 0x40064b64;\n__clzdi2       = 0x4000ca50;\n__clzsi2       = 0x4000c7e8;\n__cmpdi2       = 0x40063820;\n__ctzdi2       = 0x4000ca64;\n__ctzsi2       = 0x4000c7f0;\n__divdc3       = 0x400645a4;\n__divdf3       = 0x40002954;\n__divdi3       = 0x4000ca84;\n__divsi3       = 0x4000c7b8;\n__eqdf2        = 0x400636a8;\n__eqsf2        = 0x40063374;\n__extendsfdf2  = 0x40002c34;\n__ffsdi2       = 0x4000ca2c;\n__ffssi2       = 0x4000c804;\n__fixdfdi      = 0x40002ac4;\n__fixdfsi      = 0x40002a78;\n__fixsfdi      = 0x4000244c;\n__fixsfsi      = 0x4000240c;\n__fixunsdfsi   = 0x40002b30;\n__fixunssfdi   = 0x40002504;\n__fixunssfsi   = 0x400024ac;\n__floatdidf    = 0x4000c988;\n__floatdisf    = 0x4000c8c0;\n__floatsidf    = 0x4000c944;\n__floatsisf    = 0x4000c870;\n__floatundidf  = 0x4000c978;\n__floatundisf  = 0x4000c8b0;\n__floatunsidf  = 0x4000c938;\n__floatunsisf  = 0x4000c864;\n__gcc_bcmp     = 0x40064a70;\n__gedf2        = 0x40063768;\n__gesf2        = 0x4006340c;\n__gtdf2        = 0x400636dc;\n__gtsf2        = 0x400633a0;\n__ledf2        = 0x40063704;\n__lesf2        = 0x400633c0;\n__lshrdi3      = 0x4000c84c;\n__ltdf2        = 0x40063790;\n__ltsf2        = 0x4006342c;\n__moddi3       = 0x4000cd4c;\n__modsi3       = 0x4000c7c0;\n__muldc3       = 0x40063c90;\n__muldf3       = 0x4006358c;\n__muldi3       = 0x4000c9fc;\n__mulsf3       = 0x400632c8;\n__mulsi3       = 0x4000c7b0;\n__mulvdi3      = 0x40002d78;\n__mulvsi3      = 0x40002d60;\n__nedf2        = 0x400636a8;\n__negdf2       = 0x400634a0;\n__negdi2       = 0x4000ca14;\n__negsf2       = 0x400020c0;\n__negvdi2      = 0x40002e98;\n__negvsi2      = 0x40002e78;\n__nesf2        = 0x40063374;\n__nsau_data    = 0x3ff96544;\n__paritysi2    = 0x40002f3c;\n__popcount_tab = 0x3ff96544;\n__popcountdi2  = 0x40002ef8;\n__popcountsi2  = 0x40002ed0;\n__powidf2      = 0x400638e4;\n__subdf3       = 0x400026e4;\n__subsf3       = 0x400021d0;\n__subvdi3      = 0x40002d20;\n__subvsi3      = 0x40002cf8;\n__truncdfsf2   = 0x40002b90;\n__ucmpdi2      = 0x40063840;\n__udiv_w_sdiv  = 0x40064bec;\n__udivdi3      = 0x4000cff8;\n__udivmoddi4   = 0x40064bf4;\n__udivsi3      = 0x4000c7c8;\n__umoddi3      = 0x4000d280;\n__umodsi3      = 0x4000c7d0;\n__umulsidi3    = 0x4000c7d8;\n__unorddf2     = 0x400637f4;\n__unordsf2     = 0x40063478;\n"
  },
  {
    "path": "targets/esp32c3-12f.json",
    "content": "{\n\t\"inherits\": [\"esp32c3\"],\n\t\"build-tags\": [\"esp32c312f\"]\n}\n\n"
  },
  {
    "path": "targets/esp32c3-supermini.json",
    "content": "{\n  \"inherits\": [\"esp32c3\"],\n  \"build-tags\": [\"esp32c3_supermini\"]\n}\n"
  },
  {
    "path": "targets/esp32c3.json",
    "content": "{\n\t\"inherits\": [\"riscv32\"],\n\t\"features\": \"+32bit,+c,+m,+zmmul,-a,-b,-d,-e,-experimental-sdext,-experimental-sdtrig,-experimental-smctr,-experimental-ssctr,-experimental-svukte,-experimental-xqcia,-experimental-xqciac,-experimental-xqcicli,-experimental-xqcicm,-experimental-xqcics,-experimental-xqcicsr,-experimental-xqciint,-experimental-xqcilo,-experimental-xqcilsm,-experimental-xqcisls,-experimental-zalasr,-experimental-zicfilp,-experimental-zicfiss,-experimental-zvbc32e,-experimental-zvkgs,-f,-h,-relax,-sha,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smcdeleg,-smcsrind,-smdbltrp,-smepmp,-smmpm,-smnpm,-smrnmi,-smstateen,-ssaia,-ssccfg,-ssccptr,-sscofpmf,-sscounterenw,-sscsrind,-ssdbltrp,-ssnpm,-sspm,-ssqosid,-ssstateen,-ssstrict,-sstc,-sstvala,-sstvecd,-ssu64xl,-supm,-svade,-svadu,-svbare,-svinval,-svnapot,-svpbmt,-svvptc,-v,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xesppie,-xmipscmove,-xmipslsp,-xsfcease,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xsifivecdiscarddlone,-xsifivecflushdlone,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-xwchc,-za128rs,-za64rs,-zaamo,-zabha,-zacas,-zalrsc,-zama16b,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmop,-zcmp,-zcmt,-zdinx,-zfa,-zfbfmin,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zicsr,-zifencei,-zihintntl,-zihintpause,-zihpm,-zimop,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-ztso,-zvbb,-zvbc,-zve32f,-zve32x,-zve64d,-zve64f,-zve64x,-zvfbfmin,-zvfbfwma,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl128b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl32b,-zvl4096b,-zvl512b,-zvl64b,-zvl65536b,-zvl8192b\",\n\t\"build-tags\": [\"esp32c3\", \"esp\"],\n\t\"serial\": \"usb\",\n\t\"rtlib\": \"compiler-rt\",\n\t\"libc\": \"picolibc\",\n\t\"cflags\": [\n\t\t\"-march=rv32imc\"\n\t],\n\t\"linkerscript\": \"targets/esp32c3.ld\",\n\t\"extra-files\": [\n\t\t\"src/device/esp/esp32c3.S\"\n\t],\n\t\"binary-format\": \"esp32c3\",\n\t\"flash-command\": \"esptool.py --chip=esp32c3 --port {port} write_flash 0x0 {bin}\",\n\t\"serial-port\": [\"303a:1001\"],\n\t\"openocd-interface\": \"esp_usb_jtag\",\n\t\"openocd-target\": \"esp32c3\",\n \t\"openocd-commands\": [\"gdb_memory_map disable\"],\n \t\"gdb\": [\"riscv32-esp-elf-gdb\"]\n}\n\n"
  },
  {
    "path": "targets/esp32c3.ld",
    "content": "/* Linker script for the ESP32-C3\n *\n * The ESP32-C3 has a rather funky memory layout, more like its Xtensa\n * predecessors than like other RISC-V chips:\n *   - It has 384kB of regular RAM. This RAM can be used both as data RAM and\n *     instruction RAM, but needs to be accessed via a different address space\n *     (DRAM/IRAM).\n *   - It has another 16kB of RAM, that could be used as regular RAM but is\n *     normally used by the flash cache.\n *   - It has 8MB of address space for the DROM and IROM, but for some reason\n *     this address space is shared. So it isn't possible to map all DROM at\n *     0x3C000000 and all DRAM at 0x42000000: they would overlap.\n *   - The MMU works in pages of 64kB, which means the bottom 16 bits of the\n *     address in flash and the address in DROM/IROM need to match.\n *   - Memory in DRAM and IRAM is loaded at reset by the ROM bootloader.\n *     Luckily, this doesn't have significant alignment requirements.\n *\n * This linker script has been written to carefully work around (or with) these\n * limitations:\n *   - It adds dummy sections so that the bottom 16 bits of the virtual address\n *     and the physical address (in the generated firmware image) match.\n *   - It also offsets sections that share an address space using those same\n *     dummy sections.\n *   - It sorts the sections by load address, to avoid surprises as esptool.py\n *     also does it.\n * This way, it's possible to create a very small firmware image that still\n * conforms to the expectations of esptool.py and the ROM bootloader.\n */\n\nMEMORY\n{\n    /* Note: DRAM and IRAM below are actually in the same 384K address space. */\n    DRAM (rw) : ORIGIN = 0x3FC80000, LENGTH = 384K /* Internal SRAM 1 (data bus) */\n    IRAM (x)  : ORIGIN = 0x40380000, LENGTH = 384K /* Internal SRAM 1 (instruction bus) */\n\n    /* Note: DROM and IROM below are actually in the same 8M address space. */\n    DROM (r)  : ORIGIN = 0x3C000000, LENGTH = 8M /* Data bus (read-only) */\n    IROM (rx) : ORIGIN = 0x42000000, LENGTH = 8M /* Instruction bus */\n}\n\n/* The entry point. It is set in the image flashed to the chip, so must be\n * defined.\n */\nENTRY(call_start_cpu0)\n\nSECTIONS\n{\n    /* Dummy section to make sure the .rodata section starts exactly behind the\n     * image header.\n     */\n    .rodata_dummy (NOLOAD): ALIGN(4)\n    {\n        . += 0x18; /* image header at start of flash: esp_image_header_t */\n        . += 0x8;  /* DROM segment header (8 bytes) */\n    } > DROM\n\n    /* Constant global variables, stored in DROM.\n     */\n    .rodata : ALIGN(4)\n    {\n        *(.rodata*)\n        . = ALIGN (4);\n    } >DROM\n\n    /* Put the stack at the bottom of DRAM, so that the application will\n     * crash on stack overflow instead of silently corrupting memory.\n     * See: http://blog.japaric.io/stack-overflow-protection/\n     * TODO: this might not actually work because memory protection hasn't been set up.\n     */\n    .stack (NOLOAD) :\n    {\n        . = ALIGN(16);\n        . += _stack_size;\n        _stack_top = .;\n    } >DRAM\n\n    /* Global variables that are mutable and zero-initialized.\n     * These must be zeroed at startup (unlike data, which is loaded by the\n     * bootloader).\n     */\n    .bss (NOLOAD) : ALIGN(4)\n    {\n        . = ALIGN (4);\n        _sbss = ABSOLUTE(.);\n        *(.sbss)\n        *(.bss .bss.*)\n        . = ALIGN (4);\n        _ebss = ABSOLUTE(.);\n    } >DRAM\n\n    /* Mutable global variables. This data (in the DRAM segment) is initialized\n     * by the ROM bootloader.\n     */\n    .data : ALIGN(4)\n    {\n        . = ALIGN (4);\n        _sdata = ABSOLUTE(.);\n        *(.sdata)\n        *(.data .data.*)\n        *(.dram*)\n        . = ALIGN (4);\n        _edata = ABSOLUTE(.);\n    } >DRAM\n\n    /* Dummy section to make sure the .init section (in the IRAM segment) is just\n     * behind the DRAM segment. For IRAM and DRAM, we luckily don't have to\n     * worry about 64kB pages or image headers as they're loaded in RAM by the\n     * bootloader (not mapped from flash).\n     */\n    .iram_dummy (NOLOAD): ALIGN(4)\n    {\n        . += SIZEOF(.stack);\n        . += SIZEOF(.bss);\n        . += SIZEOF(.data);\n    } > IRAM\n\n    /* IRAM segment. This contains some functions that always need to be loaded\n     * in IRAM, and contains initialization code.\n     * The initialization code is later reclaimed for the heap, so no RAM is\n     * wasted.\n     */\n    .iram : ALIGN(4)\n    {\n        *(.iram*)\n        *(.wifislprxiram*)\n        *(.wifiextrairam*)\n        *(.wifi0iram*)\n        *(.wifislpiram*)\n        *(.wifirxiram*)\n        __init_start = .;\n        *(.init)\n        __init_end = .;\n    } >IRAM\n\n    /* Dummy section to put the IROM segment exactly behind the IRAM segment.\n     * This has to follow the app image format exactly.\n     */\n    .text_dummy (NOLOAD): ALIGN(4)\n    {\n        /* Note: DRAM and DROM are not always present so the header should only\n         * be inserted if it actually exists.\n         */\n        . += 0x18;                                                 /* esp_image_header_t */\n        . += SIZEOF(.rodata) + ((SIZEOF(.rodata) != 0) ? 0x8 : 0); /* DROM segment (optional) */\n        . += SIZEOF(.data)   + ((SIZEOF(.data)   != 0) ? 0x8 : 0); /* DRAM segment (optional) */\n        . += SIZEOF(.iram)   + 0x8;                                /* IRAM segment */\n        . += 0x8;                                                  /* IROM segment header */\n    } > IROM\n\n    /* IROM segment. This contains all the actual code and is placed right after\n     * the DROM segment.\n     */\n    .text : ALIGN(4)\n    {\n        . = ALIGN (256);\n        *(.text.exception_vectors)\n        . = ALIGN (4);\n        *(.text .text.*)\n    } >IROM\n\n    /DISCARD/ :\n    {\n        *(.eh_frame)       /* causes 'no memory region specified' error in lld */\n    }\n\n    /* Check that the boot ROM stack (for the APP CPU) does not overlap with the\n     * data that is loaded by the boot ROM. This is unlikely to happen in\n     * practice. \n     * The magic value comes from here:\n     * https://github.com/espressif/esp-idf/blob/61299f879e/components/bootloader/subproject/main/ld/esp32c3/bootloader.ld#L191\n     */\n    ASSERT((_edata + SIZEOF(.iram)) < 0x3FCDE710, \"the .iram section overlaps with the stack used by the boot ROM, possibly causing corruption at startup\")\n}\n\n/* For the garbage collector.\n * Note that _heap_start starts after _edata + most of the IRAM section.\n * It starts just before the initialisation code, which isn't necessary anymore\n * after startup and can thus be overwritten by the heap.\n */\n_globals_start = _sbss;\n_globals_end = _edata;\n_heap_start = _edata + SIZEOF(.iram) - (__init_end - __init_start);\n_heap_end = ORIGIN(DRAM) + LENGTH(DRAM);\n\n_stack_size = 4K;\n\n/* ROM functions used for setting up the flash mapping.\n */\nCache_Invalidate_ICache_All = 0x400004d8;\nCache_Suspend_ICache        = 0x40000524;\nCache_Resume_ICache         = 0x40000528;\nCache_MMU_Init              = 0x4000055c;\nCache_Dbus_MMU_Set          = 0x40000564;\n\n/* From ESP-IDF:\n * components/esp_rom/esp32c3/ld/esp32c3.rom.libgcc.ld\n * These are called from LLVM during codegen. The original license is Apache\n * 2.0.\n */\n__absvdi2     = 0x40000764;\n__absvsi2     = 0x40000768;\n__adddf3      = 0x4000076c;\n__addsf3      = 0x40000770;\n__addvdi3     = 0x40000774;\n__addvsi3     = 0x40000778;\n__ashldi3     = 0x4000077c;\n__ashrdi3     = 0x40000780;\n__bswapdi2    = 0x40000784;\n__bswapsi2    = 0x40000788;\n__clear_cache = 0x4000078c;\n__clrsbdi2    = 0x40000790;\n__clrsbsi2    = 0x40000794;\n__clzdi2      = 0x40000798;\n__clzsi2      = 0x4000079c;\n__cmpdi2      = 0x400007a0;\n__ctzdi2      = 0x400007a4;\n__ctzsi2      = 0x400007a8;\n__divdc3      = 0x400007ac;\n__divdf3      = 0x400007b0;\n__divdi3      = 0x400007b4;\n__divsc3      = 0x400007b8;\n__divsf3      = 0x400007bc;\n__divsi3      = 0x400007c0;\n__eqdf2       = 0x400007c4;\n__eqsf2       = 0x400007c8;\n__extendsfdf2 = 0x400007cc;\n__ffsdi2      = 0x400007d0;\n__ffssi2      = 0x400007d4;\n__fixdfdi     = 0x400007d8;\n__fixdfsi     = 0x400007dc;\n__fixsfdi     = 0x400007e0;\n__fixsfsi     = 0x400007e4;\n__fixunsdfsi  = 0x400007e8;\n__fixunssfdi  = 0x400007ec;\n__fixunssfsi  = 0x400007f0;\n__floatdidf   = 0x400007f4;\n__floatdisf   = 0x400007f8;\n__floatsidf   = 0x400007fc;\n__floatsisf   = 0x40000800;\n__floatundidf = 0x40000804;\n__floatundisf = 0x40000808;\n__floatunsidf = 0x4000080c;\n__floatunsisf = 0x40000810;\n__gcc_bcmp    = 0x40000814;\n__gedf2       = 0x40000818;\n__gesf2       = 0x4000081c;\n__gtdf2       = 0x40000820;\n__gtsf2       = 0x40000824;\n__ledf2       = 0x40000828;\n__lesf2       = 0x4000082c;\n__lshrdi3     = 0x40000830;\n__ltdf2       = 0x40000834;\n__ltsf2       = 0x40000838;\n__moddi3      = 0x4000083c;\n__modsi3      = 0x40000840;\n__muldc3      = 0x40000844;\n__muldf3      = 0x40000848;\n__muldi3      = 0x4000084c;\n__mulsc3      = 0x40000850;\n__mulsf3      = 0x40000854;\n__mulsi3      = 0x40000858;\n__mulvdi3     = 0x4000085c;\n__mulvsi3     = 0x40000860;\n__nedf2       = 0x40000864;\n__negdf2      = 0x40000868;\n__negdi2      = 0x4000086c;\n__negsf2      = 0x40000870;\n__negvdi2     = 0x40000874;\n__negvsi2     = 0x40000878;\n__nesf2       = 0x4000087c;\n__paritysi2   = 0x40000880;\n__popcountdi2 = 0x40000884;\n__popcountsi2 = 0x40000888;\n__powidf2     = 0x4000088c;\n__powisf2     = 0x40000890;\n__subdf3      = 0x40000894;\n__subsf3      = 0x40000898;\n__subvdi3     = 0x4000089c;\n__subvsi3     = 0x400008a0;\n__truncdfsf2  = 0x400008a4;\n__ucmpdi2     = 0x400008a8;\n__udivdi3     = 0x400008ac;\n__udivmoddi4  = 0x400008b0;\n__udivsi3     = 0x400008b4;\n__udiv_w_sdiv = 0x400008b8;\n__umoddi3     = 0x400008bc;\n__umodsi3     = 0x400008c0;\n__unorddf2    = 0x400008c4;\n__unordsf2    = 0x400008c8;\n\n/* From ESP-IDF:\n * components/esp_rom/esp32c3/ld/esp32c3.rom.newlib.ld\n * These are called during codegen and thus it's a good idea to make them always\n * available. ROM functions may also be faster than functions in IROM (that go\n * through the flash cache) and are always available in interrupts.\n */\nmemset  = 0x40000354;\nmemcpy  = 0x40000358;\nmemmove = 0x4000035c;\n\n\n/* From ESP-IDF:\n * components/esp_rom/esp32c3/ld/esp32c3.rom.ld\n * These are needed for wifi/BLE support and are available on the Apache 2.0\n * license.\n */\n/* ROM function interface esp32c3.rom.ld for esp32c3\n *\n *\n * Generated from ./interface-esp32c3.yml md5sum 93b28a9e1fe42d212018eb4336849208\n *\n * Compatible with ROM where ECO version equal or greater to 0.\n *\n * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT.\n */\n\n/***************************************\n Group common\n ***************************************/\n\n/* Functions */\nrtc_get_reset_reason = 0x40000018;\nanalog_super_wdt_reset_happened = 0x4000001c;\njtag_cpu_reset_happened = 0x40000020;\nrtc_get_wakeup_cause = 0x40000024;\nrtc_boot_control = 0x40000028;\nrtc_select_apb_bridge = 0x4000002c;\nrtc_unhold_all_pads = 0x40000030;\nset_rtc_memory_crc = 0x40000034;\ncacl_rtc_memory_crc = 0x40000038;\nets_is_print_boot = 0x4000003c;\nets_printf = 0x40000040;\nets_install_putc1 = 0x40000044;\nets_install_uart_printf = 0x40000048;\nets_install_putc2 = 0x4000004c;\nPROVIDE( ets_delay_us = 0x40000050 );\nets_get_stack_info = 0x40000054;\nets_install_lock = 0x40000058;\nets_backup_dma_copy = 0x4000005c;\nets_apb_backup_init_lock_func = 0x40000060;\nUartRxString = 0x40000064;\nuart_tx_one_char = 0x40000068;\nuart_tx_one_char2 = 0x4000006c;\nuart_rx_one_char = 0x40000070;\nuart_rx_one_char_block = 0x40000074;\nuart_rx_readbuff = 0x40000078;\nuartAttach = 0x4000007c;\nuart_tx_flush = 0x40000080;\nuart_tx_wait_idle = 0x40000084;\nuart_div_modify = 0x40000088;\nmultofup = 0x4000008c;\nsoftware_reset = 0x40000090;\nsoftware_reset_cpu = 0x40000094;\nassist_debug_clock_enable = 0x40000098;\nassist_debug_record_enable = 0x4000009c;\nclear_super_wdt_reset_flag = 0x400000a0;\ndisable_default_watchdog = 0x400000a4;\nsend_packet = 0x400000a8;\nrecv_packet = 0x400000ac;\nGetUartDevice = 0x400000b0;\nUartDwnLdProc = 0x400000b4;\nUart_Init = 0x400000b8;\nets_set_user_start = 0x400000bc;\n/* Data (.data, .bss, .rodata) */\nets_rom_layout_p = 0x3ff1fffc;\nets_ops_table_ptr = 0x3fcdfffc;\n\n\n/***************************************\n Group miniz\n ***************************************/\n\n/* Functions */\nmz_adler32 = 0x400000c0;\nmz_crc32 = 0x400000c4;\nmz_free = 0x400000c8;\ntdefl_compress = 0x400000cc;\ntdefl_compress_buffer = 0x400000d0;\ntdefl_compress_mem_to_heap = 0x400000d4;\ntdefl_compress_mem_to_mem = 0x400000d8;\ntdefl_compress_mem_to_output = 0x400000dc;\ntdefl_get_adler32 = 0x400000e0;\ntdefl_get_prev_return_status = 0x400000e4;\ntdefl_init = 0x400000e8;\ntdefl_write_image_to_png_file_in_memory = 0x400000ec;\ntdefl_write_image_to_png_file_in_memory_ex = 0x400000f0;\ntinfl_decompress = 0x400000f4;\ntinfl_decompress_mem_to_callback = 0x400000f8;\ntinfl_decompress_mem_to_heap = 0x400000fc;\ntinfl_decompress_mem_to_mem = 0x40000100;\n\n\n/***************************************\n Group tjpgd\n ***************************************/\n\n/* Functions */\nPROVIDE( jd_prepare = 0x40000104 );\nPROVIDE( jd_decomp = 0x40000108 );\n\n\n/***************************************\n Group spiflash_legacy\n ***************************************/\n\n/* Functions */\nPROVIDE( esp_rom_spiflash_wait_idle = 0x4000010c );\nPROVIDE( esp_rom_spiflash_write_encrypted = 0x40000110 );\nPROVIDE( esp_rom_spiflash_write_encrypted_dest = 0x40000114 );\nPROVIDE( esp_rom_spiflash_write_encrypted_enable = 0x40000118 );\nPROVIDE( esp_rom_spiflash_write_encrypted_disable = 0x4000011c );\nPROVIDE( esp_rom_spiflash_erase_chip = 0x40000120 );\nPROVIDE( esp_rom_spiflash_erase_block = 0x40000124 );\nPROVIDE( esp_rom_spiflash_erase_sector = 0x40000128 );\nPROVIDE( esp_rom_spiflash_write = 0x4000012c );\nPROVIDE( esp_rom_spiflash_read = 0x40000130 );\nPROVIDE( esp_rom_spiflash_config_param = 0x40000134 );\nPROVIDE( esp_rom_spiflash_read_user_cmd = 0x40000138 );\nPROVIDE( esp_rom_spiflash_select_qio_pins = 0x4000013c );\nPROVIDE( esp_rom_spiflash_unlock = 0x40000140 );\nPROVIDE( esp_rom_spi_flash_auto_sus_res = 0x40000144 );\nPROVIDE( esp_rom_spi_flash_send_resume = 0x40000148 );\nPROVIDE( esp_rom_spi_flash_update_id = 0x4000014c );\nPROVIDE( esp_rom_spiflash_config_clk = 0x40000150 );\nPROVIDE( esp_rom_spiflash_config_readmode = 0x40000154 );\nPROVIDE( esp_rom_spiflash_read_status = 0x40000158 );\nPROVIDE( esp_rom_spiflash_read_statushigh = 0x4000015c );\nPROVIDE( esp_rom_spiflash_write_status = 0x40000160 );\nPROVIDE( esp_rom_spiflash_attach = 0x40000164 );\nPROVIDE( spi_flash_get_chip_size = 0x40000168 );\nPROVIDE( spi_flash_guard_set = 0x4000016c );\nPROVIDE( spi_flash_guard_get = 0x40000170 );\nPROVIDE( spi_flash_write_config_set = 0x40000174 );\nPROVIDE( spi_flash_write_config_get = 0x40000178 );\nPROVIDE( spi_flash_safe_write_address_func_set = 0x4000017c );\nPROVIDE( spi_flash_unlock = 0x40000180 );\nPROVIDE( spi_flash_erase_range = 0x40000184 );\nPROVIDE( spi_flash_erase_sector = 0x40000188 );\nPROVIDE( spi_flash_write = 0x4000018c );\nPROVIDE( spi_flash_read = 0x40000190 );\nPROVIDE( spi_flash_write_encrypted = 0x40000194 );\nPROVIDE( spi_flash_read_encrypted = 0x40000198 );\nPROVIDE( spi_flash_mmap_os_func_set = 0x4000019c );\nPROVIDE( spi_flash_mmap_page_num_init = 0x400001a0 );\nPROVIDE( spi_flash_mmap = 0x400001a4 );\nPROVIDE( spi_flash_mmap_pages = 0x400001a8 );\nPROVIDE( spi_flash_munmap = 0x400001ac );\nPROVIDE( spi_flash_mmap_dump = 0x400001b0 );\nPROVIDE( spi_flash_check_and_flush_cache = 0x400001b4 );\nPROVIDE( spi_flash_mmap_get_free_pages = 0x400001b8 );\nPROVIDE( spi_flash_cache2phys = 0x400001bc );\nPROVIDE( spi_flash_phys2cache = 0x400001c0 );\nPROVIDE( spi_flash_disable_cache = 0x400001c4 );\nPROVIDE( spi_flash_restore_cache = 0x400001c8 );\nPROVIDE( spi_flash_cache_enabled = 0x400001cc );\nPROVIDE( spi_flash_enable_cache = 0x400001d0 );\nPROVIDE( spi_cache_mode_switch = 0x400001d4 );\nPROVIDE( spi_common_set_dummy_output = 0x400001d8 );\nPROVIDE( spi_common_set_flash_cs_timing = 0x400001dc );\nPROVIDE( esp_enable_cache_flash_wrap = 0x400001e0 );\nPROVIDE( SPIEraseArea = 0x400001e4 );\nPROVIDE( SPILock = 0x400001e8 );\nPROVIDE( SPIMasterReadModeCnfig = 0x400001ec );\nPROVIDE( SPI_Common_Command = 0x400001f0 );\nPROVIDE( SPI_WakeUp = 0x400001f4 );\nPROVIDE( SPI_block_erase = 0x400001f8 );\nPROVIDE( SPI_chip_erase = 0x400001fc );\nPROVIDE( SPI_init = 0x40000200 );\nPROVIDE( SPI_page_program = 0x40000204 );\nPROVIDE( SPI_read_data = 0x40000208 );\nPROVIDE( SPI_sector_erase = 0x4000020c );\nPROVIDE( SPI_write_enable = 0x40000210 );\nPROVIDE( SelectSpiFunction = 0x40000214 );\nPROVIDE( SetSpiDrvs = 0x40000218 );\nPROVIDE( Wait_SPI_Idle = 0x4000021c );\nPROVIDE( spi_dummy_len_fix = 0x40000220 );\nPROVIDE( Disable_QMode = 0x40000224 );\nPROVIDE( Enable_QMode = 0x40000228 );\n/* Data (.data, .bss, .rodata) */\nPROVIDE( rom_spiflash_legacy_funcs = 0x3fcdfff4 );\nPROVIDE( rom_spiflash_legacy_data = 0x3fcdfff0 );\nPROVIDE( g_flash_guard_ops = 0x3fcdfff8 );\n\n\n/***************************************\n Group spi_flash_hal\n ***************************************/\n\n/* Functions */\nPROVIDE( spi_flash_hal_poll_cmd_done = 0x4000022c );\nPROVIDE( spi_flash_hal_device_config = 0x40000230 );\nPROVIDE( spi_flash_hal_configure_host_io_mode = 0x40000234 );\nPROVIDE( spi_flash_hal_common_command = 0x40000238 );\nPROVIDE( spi_flash_hal_read = 0x4000023c );\nPROVIDE( spi_flash_hal_erase_chip = 0x40000240 );\nPROVIDE( spi_flash_hal_erase_sector = 0x40000244 );\nPROVIDE( spi_flash_hal_erase_block = 0x40000248 );\nPROVIDE( spi_flash_hal_program_page = 0x4000024c );\nPROVIDE( spi_flash_hal_set_write_protect = 0x40000250 );\nPROVIDE( spi_flash_hal_host_idle = 0x40000254 );\n\n\n/***************************************\n Group spi_flash_chips\n ***************************************/\n\n/* Functions */\nPROVIDE( spi_flash_chip_generic_probe = 0x40000258 );\nPROVIDE( spi_flash_chip_generic_detect_size = 0x4000025c );\nPROVIDE( spi_flash_chip_generic_write = 0x40000260 );\nPROVIDE( spi_flash_chip_generic_write_encrypted = 0x40000264 );\nPROVIDE( spi_flash_chip_generic_set_write_protect = 0x40000268 );\nPROVIDE( spi_flash_common_write_status_16b_wrsr = 0x4000026c );\nPROVIDE( spi_flash_chip_generic_reset = 0x40000270 );\nPROVIDE( spi_flash_chip_generic_erase_chip = 0x40000274 );\nPROVIDE( spi_flash_chip_generic_erase_sector = 0x40000278 );\nPROVIDE( spi_flash_chip_generic_erase_block = 0x4000027c );\nPROVIDE( spi_flash_chip_generic_page_program = 0x40000280 );\nPROVIDE( spi_flash_chip_generic_get_write_protect = 0x40000284 );\nPROVIDE( spi_flash_common_read_status_16b_rdsr_rdsr2 = 0x40000288 );\nPROVIDE( spi_flash_chip_generic_read_reg = 0x4000028c );\nPROVIDE( spi_flash_chip_generic_yield = 0x40000290 );\nPROVIDE( spi_flash_generic_wait_host_idle = 0x40000294 );\nPROVIDE( spi_flash_chip_generic_wait_idle = 0x40000298 );\nPROVIDE( spi_flash_chip_generic_config_host_io_mode = 0x4000029c );\nPROVIDE( spi_flash_chip_generic_read = 0x400002a0 );\nPROVIDE( spi_flash_common_read_status_8b_rdsr2 = 0x400002a4 );\nPROVIDE( spi_flash_chip_generic_get_io_mode = 0x400002a8 );\nPROVIDE( spi_flash_common_read_status_8b_rdsr = 0x400002ac );\nPROVIDE( spi_flash_common_write_status_8b_wrsr = 0x400002b0 );\nPROVIDE( spi_flash_common_write_status_8b_wrsr2 = 0x400002b4 );\nPROVIDE( spi_flash_common_set_io_mode = 0x400002b8 );\nPROVIDE( spi_flash_chip_generic_set_io_mode = 0x400002bc );\nPROVIDE( spi_flash_chip_gd_get_io_mode = 0x400002c0 );\nPROVIDE( spi_flash_chip_gd_probe = 0x400002c4 );\nPROVIDE( spi_flash_chip_gd_set_io_mode = 0x400002c8 );\n/* Data (.data, .bss, .rodata) */\nPROVIDE( spi_flash_chip_generic_config_data = 0x3fcdffec );\n\n\n/***************************************\n Group memspi_host\n ***************************************/\n\n/* Functions */\nPROVIDE( memspi_host_read_id_hs = 0x400002cc );\nPROVIDE( memspi_host_read_status_hs = 0x400002d0 );\nPROVIDE( memspi_host_flush_cache = 0x400002d4 );\nPROVIDE( memspi_host_erase_chip = 0x400002d8 );\nPROVIDE( memspi_host_erase_sector = 0x400002dc );\nPROVIDE( memspi_host_erase_block = 0x400002e0 );\nPROVIDE( memspi_host_program_page = 0x400002e4 );\nPROVIDE( memspi_host_read = 0x400002e8 );\nPROVIDE( memspi_host_set_write_protect = 0x400002ec );\nPROVIDE( memspi_host_set_max_read_len = 0x400002f0 );\nPROVIDE( memspi_host_read_data_slicer = 0x400002f4 );\nPROVIDE( memspi_host_write_data_slicer = 0x400002f8 );\n\n\n/***************************************\n Group esp_flash\n ***************************************/\n\n/* Functions */\nPROVIDE( esp_flash_chip_driver_initialized = 0x400002fc );\nPROVIDE( esp_flash_read_id = 0x40000300 );\nPROVIDE( esp_flash_get_size = 0x40000304 );\nPROVIDE( esp_flash_erase_chip = 0x40000308 );\nPROVIDE( rom_esp_flash_erase_region = 0x4000030c );\nPROVIDE( esp_flash_get_chip_write_protect = 0x40000310 );\nPROVIDE( esp_flash_set_chip_write_protect = 0x40000314 );\nPROVIDE( esp_flash_get_protectable_regions = 0x40000318 );\nPROVIDE( esp_flash_get_protected_region = 0x4000031c );\nPROVIDE( esp_flash_set_protected_region = 0x40000320 );\nPROVIDE( esp_flash_read = 0x40000324 );\nPROVIDE( esp_flash_write = 0x40000328 );\nPROVIDE( esp_flash_write_encrypted = 0x4000032c );\nPROVIDE( esp_flash_read_encrypted = 0x40000330 );\nPROVIDE( esp_flash_get_io_mode = 0x40000334 );\nPROVIDE( esp_flash_set_io_mode = 0x40000338 );\nPROVIDE( spi_flash_boot_attach = 0x4000033c );\nPROVIDE( spi_flash_dump_counters = 0x40000340 );\nPROVIDE( spi_flash_get_counters = 0x40000344 );\nPROVIDE( spi_flash_op_counters_config = 0x40000348 );\nPROVIDE( spi_flash_reset_counters = 0x4000034c );\n/* Data (.data, .bss, .rodata) */\nPROVIDE( esp_flash_default_chip = 0x3fcdffe8 );\nPROVIDE( esp_flash_api_funcs = 0x3fcdffe4 );\n\n\n/***************************************\n Group cache\n ***************************************/\n\n/* Functions */\nPROVIDE( Cache_Get_ICache_Line_Size = 0x400004b0 );\nPROVIDE( Cache_Get_Mode = 0x400004b4 );\nPROVIDE( Cache_Address_Through_IBus = 0x400004b8 );\nPROVIDE( Cache_Address_Through_DBus = 0x400004bc );\nPROVIDE( Cache_Set_Default_Mode = 0x400004c0 );\nPROVIDE( Cache_Enable_Defalut_ICache_Mode = 0x400004c4 );\nPROVIDE( ROM_Boot_Cache_Init = 0x400004c8 );\nPROVIDE( Cache_Invalidate_ICache_Items = 0x400004cc );\nPROVIDE( Cache_Op_Addr = 0x400004d0 );\nPROVIDE( Cache_Invalidate_Addr = 0x400004d4 );\nPROVIDE( Cache_Invalidate_ICache_All = 0x400004d8 );\nPROVIDE( Cache_Mask_All = 0x400004dc );\nPROVIDE( Cache_UnMask_Dram0 = 0x400004e0 );\nPROVIDE( Cache_Suspend_ICache_Autoload = 0x400004e4 );\nPROVIDE( Cache_Resume_ICache_Autoload = 0x400004e8 );\nPROVIDE( Cache_Start_ICache_Preload = 0x400004ec );\nPROVIDE( Cache_ICache_Preload_Done = 0x400004f0 );\nPROVIDE( Cache_End_ICache_Preload = 0x400004f4 );\nPROVIDE( Cache_Config_ICache_Autoload = 0x400004f8 );\nPROVIDE( Cache_Enable_ICache_Autoload = 0x400004fc );\nPROVIDE( Cache_Disable_ICache_Autoload = 0x40000500 );\nPROVIDE( Cache_Enable_ICache_PreLock = 0x40000504 );\nPROVIDE( Cache_Disable_ICache_PreLock = 0x40000508 );\nPROVIDE( Cache_Lock_ICache_Items = 0x4000050c );\nPROVIDE( Cache_Unlock_ICache_Items = 0x40000510 );\nPROVIDE( Cache_Lock_Addr = 0x40000514 );\nPROVIDE( Cache_Unlock_Addr = 0x40000518 );\nPROVIDE( Cache_Disable_ICache = 0x4000051c );\nPROVIDE( Cache_Enable_ICache = 0x40000520 );\nPROVIDE( Cache_Suspend_ICache = 0x40000524 );\nPROVIDE( Cache_Resume_ICache = 0x40000528 );\nPROVIDE( Cache_Freeze_ICache_Enable = 0x4000052c );\nPROVIDE( Cache_Freeze_ICache_Disable = 0x40000530 );\nPROVIDE( Cache_Pms_Lock = 0x40000534 );\nPROVIDE( Cache_Ibus_Pms_Set_Addr = 0x40000538 );\nPROVIDE( Cache_Ibus_Pms_Set_Attr = 0x4000053c );\nPROVIDE( Cache_Dbus_Pms_Set_Addr = 0x40000540 );\nPROVIDE( Cache_Dbus_Pms_Set_Attr = 0x40000544 );\nPROVIDE( Cache_Set_IDROM_MMU_Size = 0x40000548 );\nPROVIDE( Cache_Get_IROM_MMU_End = 0x4000054c );\nPROVIDE( Cache_Get_DROM_MMU_End = 0x40000550 );\nPROVIDE( Cache_Owner_Init = 0x40000554 );\nPROVIDE( Cache_Occupy_ICache_MEMORY = 0x40000558 );\nPROVIDE( Cache_MMU_Init = 0x4000055c );\nPROVIDE( Cache_Ibus_MMU_Set = 0x40000560 );\nPROVIDE( Cache_Dbus_MMU_Set = 0x40000564 );\nPROVIDE( Cache_Count_Flash_Pages = 0x40000568 );\nPROVIDE( Cache_Travel_Tag_Memory = 0x4000056c );\nPROVIDE( Cache_Get_Virtual_Addr = 0x40000570 );\nPROVIDE( Cache_Get_Memory_BaseAddr = 0x40000574 );\nPROVIDE( Cache_Get_Memory_Addr = 0x40000578 );\nPROVIDE( Cache_Get_Memory_value = 0x4000057c );\n/* Data (.data, .bss, .rodata) */\nPROVIDE( rom_cache_op_cb = 0x3fcdffd8 );\nPROVIDE( rom_cache_internal_table_ptr = 0x3fcdffd4 );\n\n\n/***************************************\n Group clock\n ***************************************/\n\n/* Functions */\nets_get_apb_freq = 0x40000580;\nets_get_cpu_frequency = 0x40000584;\nets_update_cpu_frequency = 0x40000588;\nets_get_printf_channel = 0x4000058c;\nets_get_xtal_div = 0x40000590;\nets_set_xtal_div = 0x40000594;\nets_get_xtal_freq = 0x40000598;\n\n\n/***************************************\n Group gpio\n ***************************************/\n\n/* Functions */\ngpio_input_get = 0x4000059c;\ngpio_matrix_in = 0x400005a0;\ngpio_matrix_out = 0x400005a4;\ngpio_output_disable = 0x400005a8;\ngpio_output_enable = 0x400005ac;\ngpio_output_set = 0x400005b0;\ngpio_pad_hold = 0x400005b4;\ngpio_pad_input_disable = 0x400005b8;\ngpio_pad_input_enable = 0x400005bc;\ngpio_pad_pulldown = 0x400005c0;\ngpio_pad_pullup = 0x400005c4;\ngpio_pad_select_gpio = 0x400005c8;\ngpio_pad_set_drv = 0x400005cc;\ngpio_pad_unhold = 0x400005d0;\ngpio_pin_wakeup_disable = 0x400005d4;\ngpio_pin_wakeup_enable = 0x400005d8;\ngpio_bypass_matrix_in = 0x400005dc;\n\n\n/***************************************\n Group interrupts\n ***************************************/\n\n/* Functions */\nesprv_intc_int_set_priority = 0x400005e0;\nesprv_intc_int_set_threshold = 0x400005e4;\nesprv_intc_int_enable = 0x400005e8;\nesprv_intc_int_disable = 0x400005ec;\nesprv_intc_int_set_type = 0x400005f0;\nintr_matrix_set = 0x400005f4;\nets_intr_lock = 0x400005f8;\nets_intr_unlock = 0x400005fc;\nPROVIDE( intr_handler_set = 0x40000600 );\nets_isr_attach = 0x40000604;\nets_isr_mask = 0x40000608;\nets_isr_unmask = 0x4000060c;\n\n\n/***************************************\n Group crypto\n ***************************************/\n\n/* Functions */\nmd5_vector = 0x40000610;\nMD5Init = 0x40000614;\nMD5Update = 0x40000618;\nMD5Final = 0x4000061c;\nhmac_md5_vector = 0x40000620;\nhmac_md5 = 0x40000624;\ncrc32_le = 0x40000628;\ncrc32_be = 0x4000062c;\ncrc16_le = 0x40000630;\ncrc16_be = 0x40000634;\ncrc8_le = 0x40000638;\ncrc8_be = 0x4000063c;\nesp_crc8 = 0x40000640;\nets_sha_enable = 0x40000644;\nets_sha_disable = 0x40000648;\nets_sha_get_state = 0x4000064c;\nets_sha_init = 0x40000650;\nets_sha_process = 0x40000654;\nets_sha_starts = 0x40000658;\nets_sha_update = 0x4000065c;\nets_sha_finish = 0x40000660;\nets_sha_clone = 0x40000664;\nets_hmac_enable = 0x40000668;\nets_hmac_disable = 0x4000066c;\nets_hmac_calculate_message = 0x40000670;\nets_hmac_calculate_downstream = 0x40000674;\nets_hmac_invalidate_downstream = 0x40000678;\nets_jtag_enable_temporarily = 0x4000067c;\nets_aes_enable = 0x40000680;\nets_aes_disable = 0x40000684;\nets_aes_setkey = 0x40000688;\nets_aes_block = 0x4000068c;\nets_bigint_enable = 0x40000690;\nets_bigint_disable = 0x40000694;\nets_bigint_multiply = 0x40000698;\nets_bigint_modmult = 0x4000069c;\nets_bigint_modexp = 0x400006a0;\nets_bigint_wait_finish = 0x400006a4;\nets_bigint_getz = 0x400006a8;\nets_ds_enable = 0x400006ac;\nets_ds_disable = 0x400006b0;\nets_ds_start_sign = 0x400006b4;\nets_ds_is_busy = 0x400006b8;\nets_ds_finish_sign = 0x400006bc;\nets_ds_encrypt_params = 0x400006c0;\nets_aes_setkey_dec = 0x400006c4;\nets_aes_setkey_enc = 0x400006c8;\nets_mgf1_sha256 = 0x400006cc;\n\n\n/***************************************\n Group efuse\n ***************************************/\n\n/* Functions */\nets_efuse_read = 0x400006d0;\nets_efuse_program = 0x400006d4;\nets_efuse_clear_program_registers = 0x400006d8;\nets_efuse_write_key = 0x400006dc;\nets_efuse_get_read_register_address = 0x400006e0;\nets_efuse_get_key_purpose = 0x400006e4;\nets_efuse_key_block_unused = 0x400006e8;\nets_efuse_find_unused_key_block = 0x400006ec;\nets_efuse_rs_calculate = 0x400006f0;\nets_efuse_count_unused_key_blocks = 0x400006f4;\nets_efuse_secure_boot_enabled = 0x400006f8;\nets_efuse_secure_boot_aggressive_revoke_enabled = 0x400006fc;\nets_efuse_cache_encryption_enabled = 0x40000700;\nets_efuse_download_modes_disabled = 0x40000704;\nets_efuse_find_purpose = 0x40000708;\nets_efuse_flash_opi_5pads_power_sel_vddspi = 0x4000070c;\nets_efuse_force_send_resume = 0x40000710;\nets_efuse_get_flash_delay_us = 0x40000714;\nets_efuse_get_mac = 0x40000718;\nets_efuse_get_spiconfig = 0x4000071c;\nets_efuse_usb_print_is_disabled = 0x40000720;\n/*ets_efuse_get_uart_print_channel = 0x40000724;*/\nets_efuse_usb_serial_jtag_print_is_disabled = 0x40000724;\nets_efuse_get_uart_print_control = 0x40000728;\nets_efuse_get_wp_pad = 0x4000072c;\nets_efuse_legacy_spi_boot_mode_disabled = 0x40000730;\nets_efuse_security_download_modes_enabled = 0x40000734;\nets_efuse_set_timing = 0x40000738;\nets_efuse_jtag_disabled = 0x4000073c;\nets_efuse_usb_download_mode_disabled = 0x40000740;\nets_efuse_usb_module_disabled = 0x40000744;\nets_efuse_usb_device_disabled = 0x40000748;\n\n\n/***************************************\n Group secureboot\n ***************************************/\n\n/* Functions */\nets_emsa_pss_verify = 0x4000074c;\nets_rsa_pss_verify = 0x40000750;\nets_secure_boot_verify_bootloader_with_keys = 0x40000754;\nets_secure_boot_verify_signature = 0x40000758;\nets_secure_boot_read_key_digests = 0x4000075c;\nets_secure_boot_revoke_public_key_digest = 0x40000760;\n\n\n/***************************************\n Group usb_uart\n ***************************************/\n\n/* Functions */\nPROVIDE( usb_uart_rx_one_char = 0x400008cc );\nPROVIDE( usb_uart_rx_one_char_block = 0x400008d0 );\nPROVIDE( usb_uart_tx_flush = 0x400008d4 );\nPROVIDE( usb_uart_tx_one_char = 0x400008d8 );\n/* Data (.data, .bss, .rodata) */\nPROVIDE( g_uart_print = 0x3fcdffd1 );\nPROVIDE( g_usb_print = 0x3fcdffd0 );\n\n\n/***************************************\n Group bluetooth\n ***************************************/\n\n/* Functions */\nbt_rf_coex_get_dft_cfg = 0x400008dc;\nbt_rf_coex_hooks_p_set = 0x400008e0;\nbtdm_con_maxevtime_cal_impl = 0x400008e4;\nbtdm_controller_get_compile_version_impl = 0x400008e8;\nbtdm_controller_rom_data_init = 0x400008ec;\nbtdm_dis_privacy_err_report_impl = 0x400008f0;\nbtdm_disable_adv_delay_impl = 0x400008f4;\nbtdm_enable_scan_continue_impl = 0x400008f8;\nbtdm_enable_scan_forever_impl = 0x400008fc;\nbtdm_get_power_state_impl = 0x40000900;\nbtdm_get_prevent_sleep_flag_impl = 0x40000904;\nbtdm_power_state_active_impl = 0x40000908;\nbtdm_switch_phy_coded_impl = 0x4000090c;\nhci_acl_data_handler = 0x40000910;\nhci_disconnect_cmd_handler = 0x40000914;\nhci_le_con_upd_cmd_handler = 0x40000918;\nhci_le_ltk_req_neg_reply_cmd_handler = 0x4000091c;\nhci_le_ltk_req_reply_cmd_handler = 0x40000920;\nhci_le_rd_chnl_map_cmd_handler = 0x40000924;\nhci_le_rd_phy_cmd_handler = 0x40000928;\nhci_le_rd_rem_feats_cmd_handler = 0x4000092c;\nhci_le_rem_con_param_req_neg_reply_cmd_handler = 0x40000930;\nhci_le_rem_con_param_req_reply_cmd_handler = 0x40000934;\nhci_le_set_data_len_cmd_handler = 0x40000938;\nhci_le_set_phy_cmd_handler = 0x4000093c;\nhci_le_start_enc_cmd_handler = 0x40000940;\nhci_rd_auth_payl_to_cmd_handler = 0x40000944;\nhci_rd_rem_ver_info_cmd_handler = 0x40000948;\nhci_rd_rssi_cmd_handler = 0x4000094c;\nhci_rd_tx_pwr_lvl_cmd_handler = 0x40000950;\nhci_vs_set_pref_slave_evt_dur_cmd_handler = 0x40000954;\nhci_vs_set_pref_slave_latency_cmd_handler = 0x40000958;\nhci_wr_auth_payl_to_cmd_handler = 0x4000095c;\nll_channel_map_ind_handler = 0x40000960;\nll_connection_param_req_handler = 0x40000964;\nll_connection_param_rsp_handler = 0x40000968;\nll_connection_update_ind_handler = 0x4000096c;\nll_enc_req_handler = 0x40000970;\nll_enc_rsp_handler = 0x40000974;\nll_feature_req_handler = 0x40000978;\nll_feature_rsp_handler = 0x4000097c;\nll_length_req_handler = 0x40000980;\nll_length_rsp_handler = 0x40000984;\nll_min_used_channels_ind_handler = 0x40000988;\nll_pause_enc_req_handler = 0x4000098c;\nll_pause_enc_rsp_handler = 0x40000990;\nll_phy_req_handler = 0x40000994;\nll_phy_rsp_handler = 0x40000998;\nll_phy_update_ind_handler = 0x4000099c;\nll_ping_req_handler = 0x400009a0;\nll_ping_rsp_handler = 0x400009a4;\nll_slave_feature_req_handler = 0x400009a8;\nll_start_enc_req_handler = 0x400009ac;\nll_start_enc_rsp_handler = 0x400009b0;\nll_terminate_ind_handler = 0x400009b4;\nll_version_ind_handler = 0x400009b8;\nllc_auth_payl_nearly_to_handler = 0x400009bc;\nllc_auth_payl_real_to_handler = 0x400009c0;\nllc_encrypt_ind_handler = 0x400009c4;\nllc_hci_command_handler_wrapper = 0x400009c8;\nllc_ll_connection_param_req_pdu_send = 0x400009cc;\nllc_ll_connection_param_rsp_pdu_send = 0x400009d0;\nllc_ll_connection_update_ind_pdu_send = 0x400009d4;\nllc_ll_enc_req_pdu_send = 0x400009d8;\nllc_ll_enc_rsp_pdu_send = 0x400009dc;\nllc_ll_feature_req_pdu_send = 0x400009e0;\nllc_ll_feature_rsp_pdu_send = 0x400009e4;\nllc_ll_length_req_pdu_send = 0x400009e8;\nllc_ll_length_rsp_pdu_send = 0x400009ec;\nllc_ll_pause_enc_req_pdu_send = 0x400009f0;\nllc_ll_pause_enc_rsp_pdu_send = 0x400009f4;\nllc_ll_phy_req_pdu_send = 0x400009f8;\nllc_ll_phy_rsp_pdu_send = 0x400009fc;\nllc_ll_ping_req_pdu_send = 0x40000a00;\nllc_ll_ping_rsp_pdu_send = 0x40000a04;\nllc_ll_start_enc_req_pdu_send = 0x40000a08;\nllc_ll_start_enc_rsp_pdu_send = 0x40000a0c;\nllc_ll_terminate_ind_pdu_send = 0x40000a10;\nllc_ll_unknown_rsp_pdu_send = 0x40000a14;\nllc_llcp_ch_map_update_ind_pdu_send = 0x40000a18;\nllc_llcp_phy_upd_ind_pdu_send = 0x40000a1c;\nllc_llcp_version_ind_pdu_send = 0x40000a20;\nllc_op_ch_map_upd_ind_handler = 0x40000a24;\nllc_op_con_upd_ind_handler = 0x40000a28;\nllc_op_disconnect_ind_handler = 0x40000a2c;\nllc_op_dl_upd_ind_handler = 0x40000a30;\nllc_op_encrypt_ind_handler = 0x40000a34;\nllc_op_feats_exch_ind_handler = 0x40000a38;\nllc_op_le_ping_ind_handler = 0x40000a3c;\nllc_op_phy_upd_ind_handler = 0x40000a40;\nllc_op_ver_exch_ind_handler = 0x40000a44;\nllc_stopped_ind_handler = 0x40000a48;\nlld_acl_rx_ind_handler = 0x40000a4c;\nlld_acl_tx_cfm_handler = 0x40000a50;\nlld_adv_end_ind_handler = 0x40000a54;\nlld_adv_rep_ind_handler = 0x40000a58;\nlld_ch_map_upd_cfm_handler = 0x40000a5c;\nlld_con_estab_ind_handler = 0x40000a60;\nlld_con_evt_sd_evt_time_set = 0x40000a64;\nlld_con_offset_upd_ind_handler = 0x40000a68;\nlld_con_param_upd_cfm_handler = 0x40000a6c;\nlld_disc_ind_handler = 0x40000a70;\nlld_init_end_ind_handler = 0x40000a74;\nlld_llcp_rx_ind_handler_wrapper = 0x40000a78;\nlld_llcp_tx_cfm_handler = 0x40000a7c;\nlld_per_adv_end_ind_handler = 0x40000a80;\nlld_per_adv_rep_ind_handler = 0x40000a84;\nlld_per_adv_rx_end_ind_handler = 0x40000a88;\nlld_phy_coded_500k_get = 0x40000a8c;\nlld_phy_upd_cfm_handler = 0x40000a90;\nlld_scan_end_ind_handler = 0x40000a94;\nlld_scan_req_ind_handler = 0x40000a98;\nlld_sync_start_req_handler = 0x40000a9c;\nlld_test_end_ind_handler = 0x40000aa0;\nlld_update_rxbuf_handler = 0x40000aa4;\nllm_ch_map_update_ind_handler = 0x40000aa8;\nllm_hci_command_handler_wrapper = 0x40000aac;\nllm_scan_period_to_handler = 0x40000ab0;\nr_Add2SelfBigHex256 = 0x40000ab4;\nr_AddBigHex256 = 0x40000ab8;\nr_AddBigHexModP256 = 0x40000abc;\nr_AddP256 = 0x40000ac0;\nr_AddPdiv2_256 = 0x40000ac4;\nr_GF_Jacobian_Point_Addition256 = 0x40000ac8;\nr_GF_Jacobian_Point_Double256 = 0x40000acc;\nr_GF_Point_Jacobian_To_Affine256 = 0x40000ad0;\nr_MultiplyBigHexByUint32_256 = 0x40000ad4;\nr_MultiplyBigHexModP256 = 0x40000ad8;\nr_MultiplyByU16ModP256 = 0x40000adc;\nr_SubtractBigHex256 = 0x40000ae0;\nr_SubtractBigHexMod256 = 0x40000ae4;\nr_SubtractBigHexUint32_256 = 0x40000ae8;\nr_SubtractFromSelfBigHex256 = 0x40000aec;\nr_SubtractFromSelfBigHexSign256 = 0x40000af0;\nr_aes_alloc = 0x40000af4;\nr_aes_ccm_continue = 0x40000af8;\nr_aes_ccm_process_e = 0x40000afc;\nr_aes_ccm_xor_128_lsb = 0x40000b00;\nr_aes_ccm_xor_128_msb = 0x40000b04;\nr_aes_cmac_continue = 0x40000b08;\nr_aes_cmac_start = 0x40000b0c;\nr_aes_k1_continue = 0x40000b10;\nr_aes_k2_continue = 0x40000b14;\nr_aes_k3_continue = 0x40000b18;\nr_aes_k4_continue = 0x40000b1c;\nr_aes_shift_left_128 = 0x40000b20;\nr_aes_start = 0x40000b24;\nr_aes_xor_128 = 0x40000b28;\nr_assert_err = 0x40000b2c;\nr_assert_param = 0x40000b30;\nr_assert_warn = 0x40000b34;\nr_bigHexInversion256 = 0x40000b38;\nr_ble_sw_cca_check_isr = 0x40000b3c;\nr_ble_util_buf_acl_tx_alloc = 0x40000b40;\nr_ble_util_buf_acl_tx_elt_get = 0x40000b44;\nr_ble_util_buf_acl_tx_free = 0x40000b48;\nr_ble_util_buf_acl_tx_free_in_isr = 0x40000b4c;\nr_ble_util_buf_adv_tx_alloc = 0x40000b50;\nr_ble_util_buf_adv_tx_free = 0x40000b54;\nr_ble_util_buf_adv_tx_free_in_isr = 0x40000b58;\nr_ble_util_buf_env_deinit = 0x40000b5c;\nr_ble_util_buf_env_init = 0x40000b60;\nr_ble_util_buf_get_rx_buf_nb = 0x40000b64;\nr_ble_util_buf_get_rx_buf_size = 0x40000b68;\nr_ble_util_buf_llcp_tx_alloc = 0x40000b6c;\nr_ble_util_buf_llcp_tx_free = 0x40000b70;\nr_ble_util_buf_rx_alloc = 0x40000b74;\nr_ble_util_buf_rx_alloc_in_isr = 0x40000b78;\nr_ble_util_buf_rx_free = 0x40000b7c;\nr_ble_util_buf_rx_free_in_isr = 0x40000b80;\nr_ble_util_buf_set_rx_buf_nb = 0x40000b84;\nr_ble_util_buf_set_rx_buf_size = 0x40000b88;\nr_ble_util_data_rx_buf_reset = 0x40000b8c;\nr_bt_bb_get_intr_mask = 0x40000b90;\nr_bt_bb_intr_clear = 0x40000b94;\nr_bt_bb_intr_mask_set = 0x40000b98;\nr_bt_rf_coex_cfg_set = 0x40000ba0;\nr_bt_rf_coex_conn_dynamic_pti_en_get = 0x40000ba4;\nr_bt_rf_coex_ext_adv_dynamic_pti_en_get = 0x40000bac;\nr_bt_rf_coex_ext_scan_dynamic_pti_en_get = 0x40000bb0;\nr_bt_rf_coex_legacy_adv_dynamic_pti_en_get = 0x40000bb4;\nr_bt_rf_coex_per_adv_dynamic_pti_en_get = 0x40000bb8;\nr_bt_rf_coex_pti_table_get = 0x40000bbc;\nr_bt_rf_coex_st_param_get = 0x40000bc0;\nr_bt_rf_coex_st_param_set = 0x40000bc4;\nr_bt_rf_coex_sync_scan_dynamic_pti_en_get = 0x40000bc8;\nr_bt_rma_apply_rule_cs_fmt = 0x40000bcc;\nr_bt_rma_apply_rule_cs_idx = 0x40000bd0;\nr_bt_rma_configure = 0x40000bd4;\nr_bt_rma_deregister_rule_cs_fmt = 0x40000bd8;\nr_bt_rma_deregister_rule_cs_idx = 0x40000bdc;\nr_bt_rma_get_ant_by_act = 0x40000be0;\nr_bt_rma_init = 0x40000be4;\nr_bt_rma_register_rule_cs_fmt = 0x40000be8;\nr_bt_rma_register_rule_cs_idx = 0x40000bec;\nr_bt_rtp_apply_rule_cs_fmt = 0x40000bf0;\nr_bt_rtp_apply_rule_cs_idx = 0x40000bf4;\nr_bt_rtp_deregister_rule_cs_fmt = 0x40000bf8;\nr_bt_rtp_deregister_rule_cs_idx = 0x40000bfc;\nr_bt_rtp_init = 0x40000c04;\nr_bt_rtp_register_rule_cs_fmt = 0x40000c08;\nr_bt_rtp_register_rule_cs_idx = 0x40000c0c;\nr_btdm_isr = 0x40000c10;\nr_cali_phase_match_p = 0x40000c20;\nr_cmp_abs_time = 0x40000c24;\nr_cmp_dest_id = 0x40000c28;\nr_cmp_timer_id = 0x40000c2c;\nr_co_bdaddr_compare = 0x40000c30;\nr_co_ble_pkt_dur_in_us = 0x40000c34;\nr_co_list_extract = 0x40000c38;\nr_co_list_extract_after = 0x40000c3c;\nr_co_list_extract_sublist = 0x40000c40;\nr_co_list_find = 0x40000c44;\nr_co_list_init = 0x40000c48;\nr_co_list_insert_after = 0x40000c4c;\nr_co_list_insert_before = 0x40000c50;\nr_co_list_merge = 0x40000c54;\nr_co_list_pool_init = 0x40000c58;\nr_co_list_pop_front = 0x40000c5c;\nr_co_list_push_back = 0x40000c60;\nr_co_list_push_back_sublist = 0x40000c64;\nr_co_list_push_front = 0x40000c68;\nr_co_list_size = 0x40000c6c;\nr_co_nb_good_le_channels = 0x40000c70;\nr_co_util_pack = 0x40000c74;\nr_co_util_read_array_size = 0x40000c78;\nr_co_util_unpack = 0x40000c7c;\nr_dbg_env_deinit = 0x40000c80;\nr_dbg_env_init = 0x40000c84;\nr_dbg_platform_reset_complete = 0x40000c88;\nr_dl_upd_proc_start = 0x40000c8c;\nr_dump_data = 0x40000c90;\nr_ecc_abort_key256_generation = 0x40000c94;\nr_ecc_gen_new_public_key = 0x40000c98;\nr_ecc_gen_new_secret_key = 0x40000c9c;\nr_ecc_generate_key256 = 0x40000ca0;\nr_ecc_get_debug_Keys = 0x40000ca4;\nr_ecc_init = 0x40000ca8;\nr_ecc_is_valid_point = 0x40000cac;\nr_ecc_multiplication_event_handler = 0x40000cb0;\nr_ecc_point_multiplication_win_256 = 0x40000cb4;\nr_emi_alloc_em_mapping_by_offset = 0x40000cb8;\nr_emi_base_reg_lut_show = 0x40000cbc;\nr_emi_em_base_reg_show = 0x40000cc0;\nr_emi_free_em_mapping_by_offset = 0x40000cc4;\nr_emi_get_em_mapping_idx_by_offset = 0x40000cc8;\nr_emi_get_mem_addr_by_offset = 0x40000ccc;\nr_emi_overwrite_em_mapping_by_offset = 0x40000cd0;\nr_esp_vendor_hci_command_handler = 0x40000cd4;\nr_get_stack_usage = 0x40000cd8;\nr_h4tl_acl_hdr_rx_evt_handler = 0x40000cdc;\nr_h4tl_cmd_hdr_rx_evt_handler = 0x40000ce0;\nr_h4tl_cmd_pld_rx_evt_handler = 0x40000ce4;\nr_h4tl_eif_io_event_post = 0x40000ce8;\nr_h4tl_eif_register = 0x40000cec;\nr_h4tl_init = 0x40000cf0;\nr_h4tl_out_of_sync = 0x40000cf4;\nr_h4tl_out_of_sync_check = 0x40000cf8;\nr_h4tl_read_hdr = 0x40000cfc;\nr_h4tl_read_next_out_of_sync = 0x40000d00;\nr_h4tl_read_payl = 0x40000d04;\nr_h4tl_read_start = 0x40000d08;\nr_h4tl_rx_acl_hdr_extract = 0x40000d0c;\nr_h4tl_rx_cmd_hdr_extract = 0x40000d10;\nr_h4tl_rx_done = 0x40000d14;\nr_h4tl_start = 0x40000d18;\nr_h4tl_stop = 0x40000d1c;\nr_h4tl_tx_done = 0x40000d20;\nr_h4tl_tx_evt_handler = 0x40000d24;\nr_h4tl_write = 0x40000d28;\nr_hci_acl_tx_data_alloc = 0x40000d2c;\nr_hci_acl_tx_data_received = 0x40000d30;\nr_hci_basic_cmd_send_2_controller = 0x40000d34;\nr_hci_ble_adv_report_filter_check = 0x40000d38;\nr_hci_ble_adv_report_tx_check = 0x40000d3c;\nr_hci_ble_conhdl_register = 0x40000d40;\nr_hci_ble_conhdl_unregister = 0x40000d44;\nr_hci_build_acl_data = 0x40000d48;\nr_hci_build_cc_evt = 0x40000d4c;\nr_hci_build_cs_evt = 0x40000d50;\nr_hci_build_evt = 0x40000d54;\nr_hci_build_le_evt = 0x40000d58;\nr_hci_cmd_get_max_param_size = 0x40000d5c;\nr_hci_cmd_received = 0x40000d60;\nr_hci_cmd_reject = 0x40000d64;\nr_hci_evt_mask_check = 0x40000d68;\nr_hci_evt_mask_set = 0x40000d6c;\nr_hci_fc_acl_buf_size_set = 0x40000d70;\nr_hci_fc_acl_en = 0x40000d74;\nr_hci_fc_acl_packet_sent = 0x40000d78;\nr_hci_fc_check_host_available_nb_acl_packets = 0x40000d7c;\nr_hci_fc_host_nb_acl_pkts_complete = 0x40000d80;\nr_hci_fc_init = 0x40000d84;\nr_hci_look_for_cmd_desc = 0x40000d88;\nr_hci_look_for_evt_desc = 0x40000d8c;\nr_hci_look_for_le_evt_desc = 0x40000d90;\nr_hci_look_for_le_evt_desc_esp = 0x40000d94;\nr_hci_pack_bytes = 0x40000d98;\nr_hci_send_2_controller = 0x40000da0;\nr_hci_send_2_host = 0x40000da4;\nr_hci_tl_c2h_data_flow_on = 0x40000da8;\nr_hci_tl_cmd_hdr_rx_evt_handler = 0x40000dac;\nr_hci_tl_cmd_pld_rx_evt_handler = 0x40000db0;\nr_hci_tl_get_pkt = 0x40000db4;\nr_hci_tl_hci_pkt_handler = 0x40000db8;\nr_hci_tl_hci_tx_done_evt_handler = 0x40000dbc;\nr_hci_tl_inc_nb_h2c_cmd_pkts = 0x40000dc0;\nr_hci_tl_save_pkt = 0x40000dc4;\nr_hci_tl_send = 0x40000dc8;\nr_hci_tx_done = 0x40000dcc;\nr_hci_tx_start = 0x40000dd0;\nr_hci_tx_trigger = 0x40000dd4;\nr_isValidSecretKey_256 = 0x40000dd8;\nr_ke_check_malloc = 0x40000ddc;\nr_ke_event_callback_set = 0x40000de0;\nr_ke_event_clear = 0x40000de4;\nr_ke_event_flush = 0x40000de8;\nr_ke_event_get = 0x40000dec;\nr_ke_event_get_all = 0x40000df0;\nr_ke_event_init = 0x40000df4;\nr_ke_event_schedule = 0x40000df8;\nr_ke_event_set = 0x40000dfc;\nr_ke_flush = 0x40000e00;\nr_ke_free = 0x40000e04;\nr_ke_handler_search = 0x40000e08;\nr_ke_init = 0x40000e0c;\nr_ke_is_free = 0x40000e10;\nr_ke_malloc = 0x40000e14;\nr_ke_mem_init = 0x40000e18;\nr_ke_mem_is_empty = 0x40000e1c;\nr_ke_mem_is_in_heap = 0x40000e20;\nr_ke_msg_alloc = 0x40000e24;\nr_ke_msg_dest_id_get = 0x40000e28;\nr_ke_msg_discard = 0x40000e2c;\nr_ke_msg_forward = 0x40000e30;\nr_ke_msg_forward_new_id = 0x40000e34;\nr_ke_msg_free = 0x40000e38;\nr_ke_msg_in_queue = 0x40000e3c;\nr_ke_msg_save = 0x40000e40;\nr_ke_msg_send = 0x40000e44;\nr_ke_msg_send_basic = 0x40000e48;\nr_ke_msg_src_id_get = 0x40000e4c;\nr_ke_queue_extract = 0x40000e50;\nr_ke_queue_insert = 0x40000e54;\nr_ke_sleep_check = 0x40000e58;\nr_ke_state_get = 0x40000e5c;\nr_ke_state_set = 0x40000e60;\nr_ke_task_check = 0x40000e64;\nr_ke_task_create = 0x40000e68;\nr_ke_task_delete = 0x40000e6c;\nr_ke_task_handler_get = 0x40000e70;\nr_ke_task_init = 0x40000e74;\nr_ke_task_msg_flush = 0x40000e78;\nr_ke_task_saved_update = 0x40000e7c;\nr_ke_time = 0x40000e84;\nr_ke_time_cmp = 0x40000e88;\nr_ke_time_past = 0x40000e8c;\nr_ke_timer_active = 0x40000e90;\nr_ke_timer_adjust_all = 0x40000e94;\nr_ke_timer_clear = 0x40000e98;\nr_ke_timer_init = 0x40000e9c;\nr_ke_timer_schedule = 0x40000ea0;\nr_ke_timer_set = 0x40000ea4;\nr_led_init = 0x40000ea8;\nr_led_set_all = 0x40000eac;\nr_llc_aes_res_cb = 0x40000eb0;\nr_llc_ch_map_up_proc_err_cb = 0x40000eb4;\nr_llc_cleanup = 0x40000eb8;\nr_llc_cmd_cmp_send = 0x40000ebc;\nr_llc_cmd_stat_send = 0x40000ec0;\nr_llc_con_move_cbk = 0x40000ec4;\nr_llc_con_plan_set_update = 0x40000ec8;\nr_llc_con_upd_param_in_range = 0x40000ecc;\nr_llc_disconnect = 0x40000ed0;\nr_llc_disconnect_end = 0x40000ed4;\nr_llc_disconnect_proc_continue = 0x40000ed8;\nr_llc_disconnect_proc_err_cb = 0x40000edc;\nr_llc_dl_chg_check = 0x40000ee0;\nr_llc_dle_proc_err_cb = 0x40000ee4;\nr_llc_feats_exch_proc_err_cb = 0x40000ee8;\nr_llc_hci_cmd_handler_tab_p_get = 0x40000eec;\nr_llc_hci_con_param_req_evt_send = 0x40000ef4;\nr_llc_hci_con_upd_info_send = 0x40000ef8;\nr_llc_hci_disconnected_dis = 0x40000efc;\nr_llc_hci_dl_upd_info_send = 0x40000f00;\nr_llc_hci_enc_evt_send = 0x40000f04;\nr_llc_hci_feats_info_send = 0x40000f08;\nr_llc_hci_le_phy_upd_cmp_evt_send = 0x40000f0c;\nr_llc_hci_ltk_request_evt_send = 0x40000f10;\nr_llc_hci_nb_cmp_pkts_evt_send = 0x40000f14;\nr_llc_hci_version_info_send = 0x40000f18;\nr_llc_init_term_proc = 0x40000f1c;\nr_llc_iv_skd_rand_gen = 0x40000f20;\nr_llc_le_ping_proc_continue = 0x40000f24;\nr_llc_le_ping_proc_err_cb = 0x40000f28;\nr_llc_le_ping_restart = 0x40000f2c;\nr_llc_le_ping_set = 0x40000f30;\nr_llc_ll_pause_enc_rsp_ack_handler = 0x40000f34;\nr_llc_ll_reject_ind_ack_handler = 0x40000f38;\nr_llc_ll_reject_ind_pdu_send = 0x40000f3c;\nr_llc_ll_start_enc_rsp_ack_handler = 0x40000f40;\nr_llc_ll_terminate_ind_ack = 0x40000f44;\nr_llc_ll_unknown_ind_handler = 0x40000f48;\nr_llc_llcp_send = 0x40000f4c;\nr_llc_llcp_state_set = 0x40000f50;\nr_llc_llcp_trans_timer_set = 0x40000f54;\nr_llc_llcp_tx_check = 0x40000f58;\nr_llc_loc_ch_map_proc_continue = 0x40000f5c;\nr_llc_loc_con_upd_proc_err_cb = 0x40000f64;\nr_llc_loc_dl_upd_proc_continue = 0x40000f68;\nr_llc_loc_encrypt_proc_continue = 0x40000f6c;\nr_llc_loc_encrypt_proc_err_cb = 0x40000f70;\nr_llc_loc_feats_exch_proc_continue = 0x40000f74;\nr_llc_loc_phy_upd_proc_err_cb = 0x40000f7c;\nr_llc_msg_handler_tab_p_get = 0x40000f80;\nr_llc_pref_param_compute = 0x40000f84;\nr_llc_proc_collision_check = 0x40000f88;\nr_llc_proc_err_ind = 0x40000f8c;\nr_llc_proc_get = 0x40000f90;\nr_llc_proc_id_get = 0x40000f94;\nr_llc_proc_reg = 0x40000f98;\nr_llc_proc_state_get = 0x40000f9c;\nr_llc_proc_state_set = 0x40000fa0;\nr_llc_proc_timer_pause_set = 0x40000fa4;\nr_llc_proc_timer_set = 0x40000fa8;\nr_llc_proc_unreg = 0x40000fac;\nr_llc_rem_ch_map_proc_continue = 0x40000fb0;\nr_llc_rem_con_upd_proc_err_cb = 0x40000fb8;\nr_llc_rem_dl_upd_proc = 0x40000fbc;\nr_llc_rem_encrypt_proc_continue = 0x40000fc0;\nr_llc_rem_encrypt_proc_err_cb = 0x40000fc4;\nr_llc_rem_phy_upd_proc_continue = 0x40000fc8;\nr_llc_rem_phy_upd_proc_err_cb = 0x40000fcc;\nr_llc_role_get = 0x40000fd0;\nr_llc_sk_gen = 0x40000fd4;\nr_llc_start = 0x40000fd8;\nr_llc_stop = 0x40000fdc;\nr_llc_ver_exch_loc_proc_continue = 0x40000fe0;\nr_llc_ver_proc_err_cb = 0x40000fe4;\nr_llcp_pdu_handler_tab_p_get = 0x40000fe8;\nr_lld_aa_gen = 0x40000fec;\nr_lld_adv_adv_data_set = 0x40000ff0;\nr_lld_adv_adv_data_update = 0x40000ff4;\nr_lld_adv_aux_ch_idx_set = 0x40000ff8;\nr_lld_adv_aux_evt_canceled_cbk = 0x40000ffc;\nr_lld_adv_aux_evt_start_cbk = 0x40001000;\nr_lld_adv_coex_check_ext_adv_synced = 0x40001004;\nr_lld_adv_coex_env_reset = 0x40001008;\nr_lld_adv_duration_update = 0x4000100c;\nr_lld_adv_dynamic_pti_process = 0x40001010;\nr_lld_adv_end = 0x40001014;\nr_lld_adv_evt_canceled_cbk = 0x40001018;\nr_lld_adv_evt_start_cbk = 0x4000101c;\nr_lld_adv_ext_chain_construct = 0x40001020;\nr_lld_adv_ext_pkt_prepare = 0x40001024;\nr_lld_adv_frm_cbk = 0x40001028;\nr_lld_adv_frm_isr = 0x4000102c;\nr_lld_adv_frm_skip_isr = 0x40001030;\nr_lld_adv_init = 0x40001034;\nr_lld_adv_pkt_rx = 0x40001038;\nr_lld_adv_pkt_rx_connect_ind = 0x4000103c;\nr_lld_adv_pkt_rx_send_scan_req_evt = 0x40001040;\nr_lld_adv_rand_addr_update = 0x40001044;\nr_lld_adv_restart = 0x40001048;\nr_lld_adv_scan_rsp_data_set = 0x4000104c;\nr_lld_adv_scan_rsp_data_update = 0x40001050;\nr_lld_adv_set_tx_power = 0x40001054;\nr_lld_adv_start = 0x40001058;\nr_lld_adv_stop = 0x4000105c;\nr_lld_adv_sync_info_set = 0x40001060;\nr_lld_adv_sync_info_update = 0x40001064;\nr_lld_calc_aux_rx = 0x40001068;\nr_lld_cca_alloc = 0x4000106c;\nr_lld_cca_data_reset = 0x40001070;\nr_lld_cca_free = 0x40001074;\nr_lld_ch_assess_data_get = 0x40001078;\nr_lld_ch_idx_get = 0x4000107c;\nr_lld_ch_map_set = 0x40001080;\nr_lld_channel_assess = 0x40001084;\nr_lld_con_activity_act_offset_compute = 0x40001088;\nr_lld_con_activity_offset_compute = 0x4000108c;\nr_lld_con_ch_map_update = 0x40001090;\nr_lld_con_cleanup = 0x40001094;\nr_lld_con_current_tx_power_get = 0x40001098;\nr_lld_con_data_flow_set = 0x4000109c;\nr_lld_con_data_len_update = 0x400010a0;\nr_lld_con_data_tx = 0x400010a4;\nr_lld_con_enc_key_load = 0x400010a8;\nr_lld_con_event_counter_get = 0x400010ac;\nr_lld_con_evt_canceled_cbk = 0x400010b0;\nr_lld_con_evt_duration_min_get = 0x400010b4;\nr_lld_con_evt_max_eff_time_cal = 0x400010b8;\nr_lld_con_evt_sd_evt_time_get = 0x400010bc;\nr_lld_con_evt_start_cbk = 0x400010c0;\nr_lld_con_evt_time_update = 0x400010c4;\nr_lld_con_free_all_tx_buf = 0x400010c8;\nr_lld_con_frm_cbk = 0x400010cc;\nr_lld_con_frm_isr = 0x400010d0;\nr_lld_con_frm_skip_isr = 0x400010d4;\nr_lld_con_init = 0x400010d8;\nr_lld_con_llcp_tx = 0x400010dc;\nr_lld_con_max_lat_calc = 0x400010e0;\nr_lld_con_offset_get = 0x400010e4;\nr_lld_con_param_update = 0x400010e8;\nr_lld_con_phys_update = 0x400010ec;\nr_lld_con_pref_slave_evt_dur_set = 0x400010f0;\nr_lld_con_pref_slave_latency_set = 0x400010f4;\nr_lld_con_rssi_get = 0x400010f8;\nr_lld_con_rx = 0x400010fc;\nr_lld_con_rx_channel_assess = 0x40001100;\nr_lld_con_rx_enc = 0x40001104;\nr_lld_con_rx_isr = 0x40001108;\nr_lld_con_rx_link_info_check = 0x4000110c;\nr_lld_con_rx_llcp_check = 0x40001110;\nr_lld_con_rx_sync_time_update = 0x40001114;\nr_lld_con_set_tx_power = 0x4000111c;\nr_lld_con_start = 0x40001120;\nr_lld_con_tx = 0x40001128;\nr_lld_con_tx_enc = 0x4000112c;\nr_lld_con_tx_isr = 0x40001130;\nr_lld_con_tx_len_update = 0x40001134;\nr_lld_con_tx_len_update_for_intv = 0x40001138;\nr_lld_con_tx_len_update_for_rate = 0x4000113c;\nr_lld_con_tx_prog = 0x40001140;\nr_lld_conn_dynamic_pti_process = 0x40001144;\nr_lld_continue_scan_rx_isr_end_process = 0x40001148;\nr_lld_ext_scan_dynamic_pti_process = 0x4000114c;\nr_lld_hw_cca_end_isr = 0x40001150;\nr_lld_hw_cca_evt_handler = 0x40001154;\nr_lld_hw_cca_isr = 0x40001158;\nr_lld_init_cal_anchor_point = 0x4000115c;\nr_lld_init_compute_winoffset = 0x40001160;\nr_lld_init_connect_req_pack = 0x40001164;\nr_lld_init_end = 0x40001168;\nr_lld_init_evt_canceled_cbk = 0x4000116c;\nr_lld_init_evt_start_cbk = 0x40001170;\nr_lld_init_frm_cbk = 0x40001174;\nr_lld_init_frm_eof_isr = 0x40001178;\nr_lld_init_frm_skip_isr = 0x4000117c;\nr_lld_init_init = 0x40001180;\nr_lld_init_process_pkt_rx = 0x40001184;\nr_lld_init_process_pkt_rx_adv_ext_ind = 0x40001188;\nr_lld_init_process_pkt_rx_adv_ind_or_direct_ind = 0x4000118c;\nr_lld_init_process_pkt_rx_aux_connect_rsp = 0x40001190;\nr_lld_init_process_pkt_tx = 0x40001194;\nr_lld_init_process_pkt_tx_cal_con_timestamp = 0x40001198;\nr_lld_init_sched = 0x4000119c;\nr_lld_init_set_tx_power = 0x400011a0;\nr_lld_init_start = 0x400011a4;\nr_lld_init_stop = 0x400011a8;\nr_lld_instant_proc_end = 0x400011ac;\nr_lld_per_adv_ch_map_update = 0x400011b4;\nr_lld_per_adv_chain_construct = 0x400011b8;\nr_lld_per_adv_cleanup = 0x400011bc;\nr_lld_per_adv_coex_env_reset = 0x400011c0;\nr_lld_per_adv_data_set = 0x400011c4;\nr_lld_per_adv_data_update = 0x400011c8;\nr_lld_per_adv_dynamic_pti_process = 0x400011cc;\nr_lld_per_adv_evt_canceled_cbk = 0x400011d0;\nr_lld_per_adv_evt_start_cbk = 0x400011d4;\nr_lld_per_adv_ext_pkt_prepare = 0x400011d8;\nr_lld_per_adv_frm_cbk = 0x400011dc;\nr_lld_per_adv_frm_isr = 0x400011e0;\nr_lld_per_adv_frm_skip_isr = 0x400011e4;\nr_lld_per_adv_init = 0x400011e8;\nr_lld_per_adv_init_info_get = 0x400011ec;\nr_lld_per_adv_list_add = 0x400011f0;\nr_lld_per_adv_list_rem = 0x400011f4;\nr_lld_per_adv_set_tx_power = 0x400011fc;\nr_lld_per_adv_start = 0x40001200;\nr_lld_per_adv_stop = 0x40001204;\nr_lld_per_adv_sync_info_get = 0x40001208;\nr_lld_process_cca_data = 0x4000120c;\nr_lld_ral_search = 0x40001210;\nr_lld_read_clock = 0x40001214;\nr_lld_res_list_add = 0x40001218;\nr_lld_res_list_is_empty = 0x40001220;\nr_lld_res_list_local_rpa_get = 0x40001224;\nr_lld_res_list_peer_rpa_get = 0x40001228;\nr_lld_res_list_peer_update = 0x4000122c;\nr_lld_res_list_priv_mode_update = 0x40001230;\nr_lld_reset_reg = 0x40001238;\nr_lld_rpa_renew = 0x4000123c;\nr_lld_rpa_renew_evt_canceled_cbk = 0x40001240;\nr_lld_rpa_renew_evt_start_cbk = 0x40001244;\nr_lld_rpa_renew_instant_cbk = 0x40001248;\nr_lld_rxdesc_check = 0x4000124c;\nr_lld_rxdesc_free = 0x40001250;\nr_lld_scan_create_sync = 0x40001254;\nr_lld_scan_create_sync_cancel = 0x40001258;\nr_lld_scan_end = 0x4000125c;\nr_lld_scan_evt_canceled_cbk = 0x40001260;\nr_lld_scan_evt_start_cbk = 0x40001264;\nr_lld_scan_frm_cbk = 0x40001268;\nr_lld_scan_frm_eof_isr = 0x4000126c;\nr_lld_scan_frm_rx_isr = 0x40001270;\nr_lld_scan_frm_skip_isr = 0x40001274;\nr_lld_scan_init = 0x40001278;\nr_lld_scan_params_update = 0x4000127c;\nr_lld_scan_process_pkt_rx_aux_adv_ind = 0x40001288;\nr_lld_scan_process_pkt_rx_aux_chain_ind = 0x4000128c;\nr_lld_scan_process_pkt_rx_aux_scan_rsp = 0x40001290;\nr_lld_scan_process_pkt_rx_ext_adv = 0x40001294;\nr_lld_scan_process_pkt_rx_ext_adv_ind = 0x40001298;\nr_lld_scan_process_pkt_rx_legacy_adv = 0x4000129c;\nr_lld_scan_restart = 0x400012a0;\nr_lld_scan_sched = 0x400012a4;\nr_lld_scan_set_tx_power = 0x400012a8;\nr_lld_scan_start = 0x400012ac;\nr_lld_scan_stop = 0x400012b0;\nr_lld_scan_sync_accept = 0x400012b4;\nr_lld_scan_sync_info_unpack = 0x400012b8;\nr_lld_scan_trunc_ind = 0x400012bc;\nr_lld_sw_cca_evt_handler = 0x400012c0;\nr_lld_sw_cca_isr = 0x400012c4;\nr_lld_sync_ch_map_update = 0x400012c8;\nr_lld_sync_cleanup = 0x400012cc;\nr_lld_sync_evt_canceled_cbk = 0x400012d0;\nr_lld_sync_evt_start_cbk = 0x400012d4;\nr_lld_sync_frm_cbk = 0x400012d8;\nr_lld_sync_frm_eof_isr = 0x400012dc;\nr_lld_sync_frm_rx_isr = 0x400012e0;\nr_lld_sync_frm_skip_isr = 0x400012e4;\nr_lld_sync_init = 0x400012e8;\nr_lld_sync_process_pkt_rx = 0x400012ec;\nr_lld_sync_process_pkt_rx_aux_sync_ind = 0x400012f0;\nr_lld_sync_process_pkt_rx_pkt_check = 0x400012f4;\nr_lld_sync_scan_dynamic_pti_process = 0x400012f8;\nr_lld_sync_sched = 0x400012fc;\nr_lld_sync_start = 0x40001300;\nr_lld_sync_stop = 0x40001304;\nr_lld_sync_trunc_ind = 0x40001308;\nr_lld_test_cleanup = 0x4000130c;\nr_lld_test_evt_canceled_cbk = 0x40001310;\nr_lld_test_evt_start_cbk = 0x40001314;\nr_lld_test_freq2chnl = 0x40001318;\nr_lld_test_frm_cbk = 0x4000131c;\nr_lld_test_frm_isr = 0x40001320;\nr_lld_test_init = 0x40001324;\nr_lld_test_rx_isr = 0x40001328;\nr_lld_test_set_tx_power = 0x4000132c;\nr_lld_test_start = 0x40001330;\nr_lld_test_stop = 0x40001334;\nr_lld_update_rxbuf = 0x40001338;\nr_lld_update_rxbuf_isr = 0x4000133c;\nr_lld_white_list_add = 0x40001340;\nr_lld_white_list_rem = 0x40001344;\nr_llm_activity_free_get = 0x40001348;\nr_llm_activity_free_set = 0x4000134c;\nr_llm_activity_syncing_get = 0x40001350;\nr_llm_adv_con_len_check = 0x40001354;\nr_llm_adv_hdl_to_id = 0x40001358;\nr_llm_adv_rep_flow_control_check = 0x4000135c;\nr_llm_adv_rep_flow_control_update = 0x40001360;\nr_llm_adv_reports_list_check = 0x40001364;\nr_llm_adv_set_all_release = 0x40001368;\nr_llm_adv_set_dft_params = 0x4000136c;\nr_llm_adv_set_release = 0x40001370;\nr_llm_aes_res_cb = 0x40001374;\nr_llm_ble_update_adv_flow_control = 0x40001378;\nr_llm_ch_map_update = 0x4000137c;\nr_llm_cmd_cmp_send = 0x40001380;\nr_llm_cmd_stat_send = 0x40001384;\nr_llm_dev_list_empty_entry = 0x40001388;\nr_llm_dev_list_search = 0x4000138c;\nr_llm_env_adv_dup_filt_deinit = 0x40001390;\nr_llm_env_adv_dup_filt_init = 0x40001394;\nr_llm_init_ble_adv_report_flow_contol = 0x40001398;\nr_llm_is_dev_connected = 0x4000139c;\nr_llm_is_dev_synced = 0x400013a0;\nr_llm_is_non_con_act_ongoing_check = 0x400013a4;\nr_llm_is_wl_accessible = 0x400013a8;\nr_llm_le_evt_mask_check = 0x400013ac;\nr_llm_link_disc = 0x400013b4;\nr_llm_master_ch_map_get = 0x400013b8;\nr_llm_msg_handler_tab_p_get = 0x400013bc;\nr_llm_no_activity = 0x400013c0;\nr_llm_per_adv_slot_dur = 0x400013c4;\nr_llm_plan_elt_get = 0x400013c8;\nr_llm_rx_path_comp_get = 0x400013cc;\nr_llm_scan_start = 0x400013d0;\nr_llm_scan_sync_acad_attach = 0x400013d4;\nr_llm_scan_sync_acad_detach = 0x400013d8;\nr_llm_send_adv_lost_event_to_host = 0x400013dc;\nr_llm_tx_path_comp_get = 0x400013e0;\nr_misc_deinit = 0x400013e4;\nr_misc_free_em_buf_in_isr = 0x400013e8;\nr_misc_init = 0x400013ec;\nr_misc_msg_handler_tab_p_get = 0x400013f0;\nr_notEqual256 = 0x400013f4;\nr_phy_upd_proc_start = 0x400013f8;\nr_platform_reset = 0x400013fc;\nr_rf_em_init = 0x40001404;\nr_rf_force_agc_enable = 0x40001408;\nr_rf_reg_rd = 0x4000140c;\nr_rf_reg_wr = 0x40001410;\nr_rf_reset = 0x40001414;\nr_rf_rssi_convert = 0x40001418;\nr_rf_rw_v9_le_disable = 0x4000141c;\nr_rf_rw_v9_le_enable = 0x40001420;\nr_rf_sleep = 0x40001424;\nr_rf_util_cs_fmt_convert = 0x40001430;\nr_rw_crypto_aes_ccm = 0x40001434;\nr_rw_crypto_aes_encrypt = 0x40001438;\nr_rw_crypto_aes_init = 0x4000143c;\nr_rw_crypto_aes_k1 = 0x40001440;\nr_rw_crypto_aes_k2 = 0x40001444;\nr_rw_crypto_aes_k3 = 0x40001448;\nr_rw_crypto_aes_k4 = 0x4000144c;\nr_rw_crypto_aes_rand = 0x40001450;\nr_rw_crypto_aes_result_handler = 0x40001454;\nr_rw_crypto_aes_s1 = 0x40001458;\nr_rw_cryto_aes_cmac = 0x4000145c;\nr_rw_v9_init_em_radio_table = 0x40001460;\nr_rwble_sleep_enter = 0x40001468;\nr_rwble_sleep_wakeup_end = 0x4000146c;\nr_rwbtdm_isr_wrapper = 0x40001470;\nr_rwip_active_check = 0x40001474;\nr_rwip_aes_encrypt = 0x40001478;\nr_rwip_assert = 0x4000147c;\nr_rwip_crypt_evt_handler = 0x40001480;\nr_rwip_crypt_isr_handler = 0x40001484;\nr_rwip_eif_get = 0x40001488;\nr_rwip_half_slot_2_lpcycles = 0x4000148c;\nr_rwip_hus_2_lpcycles = 0x40001490;\nr_rwip_isr = 0x40001494;\nr_rwip_lpcycles_2_hus = 0x40001498;\nr_rwip_prevent_sleep_clear = 0x4000149c;\nr_rwip_prevent_sleep_set = 0x400014a0;\nr_rwip_schedule = 0x400014a4;\nr_rwip_sleep = 0x400014a8;\nr_rwip_sw_int_handler = 0x400014ac;\nr_rwip_sw_int_req = 0x400014b0;\nr_rwip_time_get = 0x400014b4;\nr_rwip_timer_10ms_handler = 0x400014b8;\nr_rwip_timer_10ms_set = 0x400014bc;\nr_rwip_timer_hs_handler = 0x400014c0;\nr_rwip_timer_hs_set = 0x400014c4;\nr_rwip_timer_hus_handler = 0x400014c8;\nr_rwip_timer_hus_set = 0x400014cc;\nr_rwip_wakeup = 0x400014d0;\nr_rwip_wakeup_end = 0x400014d4;\nr_rwip_wlcoex_set = 0x400014d8;\nr_sch_alarm_clear = 0x400014dc;\nr_sch_alarm_init = 0x400014e0;\nr_sch_alarm_prog = 0x400014e4;\nr_sch_alarm_set = 0x400014e8;\nr_sch_alarm_timer_isr = 0x400014ec;\nr_sch_arb_conflict_check = 0x400014f0;\nr_sch_arb_elt_cancel = 0x400014f4;\nr_sch_arb_init = 0x400014fc;\nr_sch_arb_insert = 0x40001500;\nr_sch_arb_prog_timer = 0x40001504;\nr_sch_arb_remove = 0x40001508;\nr_sch_arb_sw_isr = 0x4000150c;\nr_sch_plan_chk = 0x40001510;\nr_sch_plan_clock_wrap_offset_update = 0x40001514;\nr_sch_plan_init = 0x40001518;\nr_sch_plan_interval_req = 0x4000151c;\nr_sch_plan_offset_max_calc = 0x40001520;\nr_sch_plan_offset_req = 0x40001524;\nr_sch_plan_position_range_compute = 0x40001528;\nr_sch_plan_rem = 0x4000152c;\nr_sch_plan_req = 0x40001530;\nr_sch_prog_init = 0x4000153c;\nr_sch_prog_push = 0x40001540;\nr_sch_prog_rx_isr = 0x40001544;\nr_sch_prog_skip_isr = 0x40001548;\nr_sch_prog_tx_isr = 0x4000154c;\nr_sch_slice_bg_add = 0x40001550;\nr_sch_slice_bg_remove = 0x40001554;\nr_sch_slice_compute = 0x40001558;\nr_sch_slice_fg_add = 0x4000155c;\nr_sch_slice_fg_remove = 0x40001560;\nr_sch_slice_init = 0x40001564;\nr_sch_slice_per_add = 0x40001568;\nr_sch_slice_per_remove = 0x4000156c;\nr_sdk_config_get_bt_sleep_enable = 0x40001570;\nr_sdk_config_get_hl_derived_opts = 0x40001574;\nr_sdk_config_get_opts = 0x40001578;\nr_sdk_config_get_priv_opts = 0x4000157c;\nr_sdk_config_set_bt_sleep_enable = 0x40001580;\nr_sdk_config_set_hl_derived_opts = 0x40001584;\nr_sdk_config_set_opts = 0x40001588;\nr_specialModP256 = 0x4000158c;\nr_unloaded_area_init = 0x40001590;\nr_vhci_flow_off = 0x40001594;\nr_vhci_flow_on = 0x40001598;\nr_vhci_notify_host_send_available = 0x4000159c;\nr_vhci_send_to_host = 0x400015a0;\nr_vnd_hci_command_handler = 0x400015a4;\nr_vshci_init = 0x400015a8;\nvnd_hci_command_handler_wrapper = 0x400015ac;\n/* Data (.data, .bss, .rodata) */\nbt_rf_coex_cfg_p = 0x3fcdffcc;\nbt_rf_coex_hooks_p = 0x3fcdffc8;\nbtdm_env_p = 0x3fcdffc4;\ng_rw_controller_task_handle = 0x3fcdffc0;\ng_rw_init_sem = 0x3fcdffbc;\ng_rw_schd_queue = 0x3fcdffb8;\nlld_init_env = 0x3fcdffb4;\nlld_rpa_renew_env = 0x3fcdffb0;\nlld_scan_env = 0x3fcdffac;\nlld_scan_sync_env = 0x3fcdffa8;\nlld_test_env = 0x3fcdffa4;\np_ble_util_buf_env = 0x3fcdffa0;\np_lld_env = 0x3fcdff9c;\np_llm_env = 0x3fcdff98;\nr_h4tl_eif_p = 0x3fcdff94;\nr_hli_funcs_p = 0x3fcdff90;\nr_ip_funcs_p = 0x3fcdff8c;\nr_modules_funcs_p = 0x3fcdff88;\nr_osi_funcs_p = 0x3fcdff84;\nr_plf_funcs_p = 0x3fcdff80;\nvhci_env_p = 0x3fcdff7c;\naa_gen = 0x3fcdff78;\naes_env = 0x3fcdff6c;\nbt_rf_coex_cfg_cb = 0x3fcdff1c;\nbtdm_pwr_state = 0x3fcdff18;\nbtdm_slp_err = 0x3fcdff14;\necc_env = 0x3fcdff0c;\nesp_handler = 0x3fcdff04;\nesp_vendor_cmd = 0x3fcdfefc;\ng_adv_delay_dis = 0x3fcdfef8;\ng_conflict_elt = 0x3fcdfef4;\ng_eif_api = 0x3fcdfee4;\ng_event_empty = 0x3fcdfed8;\ng_llc_state = 0x3fcdfecc;\ng_llm_state = 0x3fcdfec8;\ng_max_evt_env = 0x3fcdfec4;\ng_misc_state = 0x3fcdfec0;\ng_rma_rule_db = 0x3fcdfea4;\ng_rtp_rule_db = 0x3fcdfe88;\ng_scan_forever = 0x3fcdfe85;\ng_time_msb = 0x3fcdfe84;\nh4tl_env = 0x3fcdfe5c;\nhci_env = 0x3fcdfe38;\nhci_ext_host = 0x3fcdfe34;\nhci_fc_env = 0x3fcdfe2c;\nhci_tl_env = 0x3fcdfe00;\nke_env = 0x3fcdfdd0;\nke_event_env = 0x3fcdfd90;\nke_task_env = 0x3fcdfd14;\nllc_env = 0x3fcdfcec;\nlld_adv_env = 0x3fcdfcc4;\nlld_con_env = 0x3fcdfc9c;\nlld_exp_sync_pos_tab = 0x3fcdfc94;\nlld_per_adv_env = 0x3fcdfc6c;\nlld_sync_env = 0x3fcdfc44;\nllm_le_adv_flow_env = 0x3fcdfc38;\nrw_sleep_enable = 0x3fcdfc34;\nrwble_env = 0x3fcdfc2c;\nrwip_env = 0x3fcdfc10;\nrwip_param = 0x3fcdfc04;\nrwip_prog_delay = 0x3fcdfc00;\nrwip_rf = 0x3fcdfbc8;\nsch_alarm_env = 0x3fcdfbc0;\nsch_arb_env = 0x3fcdfbac;\nsch_plan_env = 0x3fcdfba4;\nsch_prog_env = 0x3fcdfaa0;\nsch_slice_env = 0x3fcdfa40;\nsch_slice_params = 0x3fcdfa38;\ntimer_env = 0x3fcdfa30;\nunloaded_area = 0x3fcdfa2c;\nvshci_state = 0x3fcdfa28;\nTASK_DESC_LLC = 0x3fcdfa1c;\nTASK_DESC_LLM = 0x3fcdfa10;\nTASK_DESC_VSHCI = 0x3fcdfa04;\nco_default_bdaddr = 0x3fcdf9fc;\ndbg_assert_block = 0x3fcdf9f8;\ng_bt_plf_log_level = 0x3fcdf9f4;\nhci_cmd_desc_tab_vs_esp = 0x3fcdf9d0;\nhci_command_handler_tab_esp = 0x3fcdf9b8;\nprivacy_en = 0x3fcdf9b4;\nsdk_cfg_priv_opts = 0x3fcdf96c;\nBasePoint_x_256 = 0x3ff1ffdc;\nBasePoint_y_256 = 0x3ff1ffbc;\nDebugE256PublicKey_x = 0x3ff1ff9c;\nDebugE256PublicKey_y = 0x3ff1ff7c;\nDebugE256SecretKey = 0x3ff1ff5c;\nECC_4Win_Look_up_table = 0x3ff1f7a0;\nLLM_AA_CT1 = 0x3ff1f79c;\nLLM_AA_CT2 = 0x3ff1f798;\nRF_TX_PW_CONV_TBL = 0x3ff1f790;\nTASK_DESC_MISC = 0x3ff1f784;\nadv_evt_prop2type = 0x3ff1f768;\nadv_evt_type2prop = 0x3ff1f760;\naes_cmac_zero = 0x3ff1f750;\naes_k2_salt = 0x3ff1f740;\naes_k3_id64 = 0x3ff1f738;\naes_k3_salt = 0x3ff1f728;\naes_k4_id6 = 0x3ff1f724;\naes_k4_salt = 0x3ff1f714;\nbigHexP256 = 0x3ff1f6e8;\nbyte_tx_time = 0x3ff1f6e0;\nco_null_bdaddr = 0x3ff1f6d8;\nco_phy_mask_to_rate = 0x3ff1f6d0;\nco_phy_mask_to_value = 0x3ff1f6c8;\nco_phy_to_rate = 0x3ff1f6c4;\nco_phy_value_to_mask = 0x3ff1f6c0;\nco_rate_to_byte_dur_us = 0x3ff1f6b8;\nco_rate_to_phy = 0x3ff1f6b0;\nco_rate_to_phy_mask = 0x3ff1f6ac;\nco_sca2ppm = 0x3ff1f69c;\ncoef_B = 0x3ff1f670;\nconnect_req_dur_tab = 0x3ff1f668;\necc_Jacobian_InfinityPoint256 = 0x3ff1f5e4;\nem_base_reg_lut = 0x3ff1f518;\nfixed_tx_time = 0x3ff1f510;\nh4tl_msgtype2hdrlen = 0x3ff1f508;\nhci_cmd_desc_root_tab = 0x3ff1f4d8;\nhci_cmd_desc_tab_ctrl_bb = 0x3ff1f46c;\nhci_cmd_desc_tab_info_par = 0x3ff1f43c;\nhci_cmd_desc_tab_le = 0x3ff1f0a0;\nhci_cmd_desc_tab_lk_ctrl = 0x3ff1f088;\nhci_cmd_desc_tab_stat_par = 0x3ff1f07c;\nhci_cmd_desc_tab_vs = 0x3ff1f040;\nhci_evt_desc_tab = 0x3ff1eff8;\nhci_evt_le_desc_tab = 0x3ff1ef58;\nhci_evt_le_desc_tab_esp = 0x3ff1ef50;\nhci_rsvd_evt_msk = 0x3ff1ef48;\nlld_aux_phy_to_rate = 0x3ff1ef44;\nlld_init_max_aux_dur_tab = 0x3ff1ef3c;\nlld_scan_map_legacy_pdu_to_evt_type = 0x3ff1ef34;\nlld_scan_max_aux_dur_tab = 0x3ff1ef2c;\nlld_sync_max_aux_dur_tab = 0x3ff1ef24;\nllm_local_le_feats = 0x3ff1ef1c;\nllm_local_le_states = 0x3ff1ef14;\nllm_local_supp_cmds = 0x3ff1eeec;\nmaxSecretKey_256 = 0x3ff1eecc;\nmax_data_tx_time = 0x3ff1eec4;\none_bits = 0x3ff1eeb4;\nrwip_coex_cfg = 0x3ff1eeac;\nrwip_priority = 0x3ff1ee94;\nveryBigHexP256 = 0x3ff1ee48;\n\n/* bluetooth hook funcs */\nr_llc_loc_encrypt_proc_continue_hook = 0x40001c60;\nr_llc_loc_phy_upd_proc_continue_hook = 0x40001c64;\nr_llc_rem_phy_upd_proc_continue_hook = 0x40001c68;\nr_lld_scan_frm_eof_isr_hook = 0x40001c6c;\nr_lld_scan_evt_start_cbk_hook = 0x40001c70;\nr_lld_scan_process_pkt_rx_ext_adv_hook = 0x40001c78;\nr_lld_scan_sched_hook = 0x40001c7c;\nr_lld_adv_evt_start_cbk_hook = 0x40001c84;\nr_lld_adv_aux_evt_start_cbk_hook = 0x40001c88;\nr_lld_adv_frm_isr_hook = 0x40001c8c;\nr_lld_adv_start_init_evt_param_hook = 0x40001c90;\nr_lld_con_evt_canceled_cbk_hook = 0x40001c94;\nr_lld_con_frm_isr_hook = 0x40001c98;\nr_lld_con_tx_hook = 0x40001c9c;\nr_lld_con_rx_hook = 0x40001ca0;\nr_lld_con_evt_start_cbk_hook = 0x40001ca4;\nr_lld_con_tx_prog_new_packet_hook = 0x40001cac;\nr_lld_init_frm_eof_isr_hook = 0x40001cb0;\nr_lld_init_evt_start_cbk_hook = 0x40001cb4;\nr_lld_init_sched_hook = 0x40001cbc;\nr_lld_init_process_pkt_tx_hook = 0x40001cc0;\nr_lld_per_adv_evt_start_cbk_hook = 0x40001cc4;\nr_lld_per_adv_frm_isr_hook = 0x40001cc8;\nr_lld_per_adv_start_hook = 0x40001ccc;\nr_lld_sync_frm_eof_isr_hook = 0x40001cd0;\nr_lld_sync_evt_start_cbk_hook = 0x40001cd4;\nr_lld_sync_start_hook = 0x40001cd8;\nr_lld_sync_process_pkt_rx_pkt_check_hook = 0x40001cdc;\nr_sch_arb_insert_hook = 0x40001ce0;\nr_sch_plan_offset_req_hook = 0x40001ce4;\n\n/***************************************\n Group rom_pp\n ***************************************/\n\n/* Functions */\nesp_pp_rom_version_get = 0x400015b0;\nRC_GetBlockAckTime = 0x400015b4;\nebuf_list_remove = 0x400015b8;\n/*esf_buf_alloc = 0x400015bc;*/\nGetAccess = 0x400015c8;\nhal_mac_is_low_rate_enabled = 0x400015cc;\nhal_mac_tx_get_blockack = 0x400015d0;\n/* hal_mac_tx_set_ppdu = 0x400015d4;*/\nic_get_trc = 0x400015d8;\n/* ic_mac_deinit = 0x400015dc; */\nic_mac_init = 0x400015e0;\nic_interface_enabled = 0x400015e4;\nis_lmac_idle = 0x400015e8;\n/*lmacAdjustTimestamp = 0x400015ec;*/\nlmacDiscardAgedMSDU = 0x400015f0;\n/*lmacDiscardMSDU = 0x400015f4;*/\nlmacEndFrameExchangeSequence = 0x400015f8;\nlmacIsIdle = 0x400015fc;\nlmacIsLongFrame = 0x40001600;\n/*lmacMSDUAged = 0x40001604;*/\nlmacPostTxComplete = 0x40001608;\nlmacProcessAllTxTimeout = 0x4000160c;\nlmacProcessCollisions = 0x40001610;\nlmacProcessRxSucData = 0x40001614;\nlmacReachLongLimit = 0x40001618;\nlmacReachShortLimit = 0x4000161c;\nlmacRecycleMPDU = 0x40001620;\nlmacRxDone = 0x40001624;\n/*lmacSetTxFrame = 0x40001628;*/\n/*lmacTxFrame = 0x40001630;*/\nmac_tx_set_duration = 0x40001634;\n/* mac_tx_set_htsig = 0x40001638;*/\nmac_tx_set_plcp0 = 0x4000163c;\n/* mac_tx_set_plcp1 = 0x40001640;*/\nmac_tx_set_plcp2 = 0x40001644;\n/* pm_check_state = 0x40001648; */\npm_disable_dream_timer = 0x4000164c;\npm_disable_sleep_delay_timer = 0x40001650;\npm_dream = 0x40001654;\npm_mac_wakeup = 0x40001658;\npm_mac_sleep = 0x4000165c;\npm_enable_active_timer = 0x40001660;\npm_enable_sleep_delay_timer = 0x40001664;\npm_local_tsf_process = 0x40001668;\npm_set_beacon_filter = 0x4000166c;\npm_is_in_wifi_slice_threshold = 0x40001670;\npm_is_waked = 0x40001674;\npm_keep_alive = 0x40001678;\n/* pm_on_beacon_rx = 0x4000167c; */\npm_on_data_rx = 0x40001680;\npm_on_tbtt = 0x40001684;\n/* pm_parse_beacon = 0x40001688;*/\n/* pm_process_tim = 0x4000168c; */\n/*pm_rx_beacon_process = 0x40001690;*/\n/* pm_rx_data_process = 0x40001694; */\n/*pm_sleep = 0x40001698;*/\npm_sleep_for = 0x4000169c;\n/* pm_tbtt_process = 0x400016a0; */\nppAMPDU2Normal = 0x400016a4;\n/*ppAssembleAMPDU = 0x400016a8;*/\nppCalFrameTimes = 0x400016ac;\nppCalSubFrameLength = 0x400016b0;\n/*ppCalTxAMPDULength = 0x400016b4;*/\nppCheckTxAMPDUlength = 0x400016b8;\nppDequeueRxq_Locked = 0x400016bc;\nppDequeueTxQ = 0x400016c0;\nppEmptyDelimiterLength = 0x400016c4;\nppEnqueueRxq = 0x400016c8;\nppEnqueueTxDone = 0x400016cc;\nppGetTxQFirstAvail_Locked = 0x400016d0;\nppGetTxframe = 0x400016d4;\nppProcessRxPktHdr = 0x400016e0;\nppProcessTxQ = 0x400016e4;\nppRecordBarRRC = 0x400016e8;\nlmacRequestTxopQueue = 0x400016ec;\nlmacReleaseTxopQueue = 0x400016f0;\nppRecycleAmpdu = 0x400016f4;\nppRecycleRxPkt = 0x400016f8;\nppResortTxAMPDU = 0x400016fc;\nppResumeTxAMPDU = 0x40001700;\n/* ppRxFragmentProc = 0x40001704; */\n/* ppRxPkt = 0x40001708; */\nppRxProtoProc = 0x4000170c;\nppSearchTxQueue = 0x40001710;\nppSearchTxframe = 0x40001714;\nppSelectNextQueue = 0x40001718;\nppSubFromAMPDU = 0x4000171c;\nppTask = 0x40001720;\nppTxPkt = 0x40001724;\nppTxProtoProc = 0x40001728;\nppTxqUpdateBitmap = 0x4000172c;\npp_coex_tx_request = 0x40001730;\npp_hdrsize = 0x40001734;\npp_post = 0x40001738;\npp_process_hmac_waiting_txq = 0x4000173c;\nrcGetAmpduSched = 0x40001740;\nrcUpdateRxDone = 0x40001744;\nrc_get_trc = 0x40001748;\nrc_get_trc_by_index = 0x4000174c;\nrcAmpduLowerRate = 0x40001750;\nrcampduuprate = 0x40001754;\nrcClearCurAMPDUSched = 0x40001758;\nrcClearCurSched = 0x4000175c;\nrcClearCurStat = 0x40001760;\nrcLowerSched = 0x40001768;\nrcSetTxAmpduLimit = 0x4000176c;\n/* rcTxUpdatePer = 0x40001770;*/\nrcUpdateAckSnr = 0x40001774;\n/*rcUpdateRate = 0x40001778;*/\n/* rcUpdateTxDone = 0x4000177c; */\nrcUpdateTxDoneAmpdu2 = 0x40001780;\nrcUpSched = 0x40001784;\nrssi_margin = 0x40001788;\nrx11NRate2AMPDULimit = 0x4000178c;\nTRC_AMPDU_PER_DOWN_THRESHOLD = 0x40001790;\nTRC_AMPDU_PER_UP_THRESHOLD = 0x40001794;\ntrc_calc_duration = 0x40001798;\ntrc_isTxAmpduOperational = 0x4000179c;\ntrc_onAmpduOp = 0x400017a0;\nTRC_PER_IS_GOOD = 0x400017a4;\ntrc_SetTxAmpduState = 0x400017a8;\ntrc_tid_isTxAmpduOperational = 0x400017ac;\ntrcAmpduSetState = 0x400017b0;\nwDev_AppendRxBlocks = 0x400017b8;\nwDev_DiscardFrame = 0x400017bc;\nwDev_GetNoiseFloor = 0x400017c0;\nwDev_IndicateAmpdu = 0x400017c4;\n/*wDev_IndicateFrame = 0x400017c8;*/\nwdev_bank_store = 0x400017cc;\nwdev_bank_load = 0x400017d0;\nwdev_mac_reg_load = 0x400017d4;\nwdev_mac_reg_store = 0x400017d8;\nwdev_mac_special_reg_load = 0x400017dc;\nwdev_mac_special_reg_store = 0x400017e0;\nwdev_mac_wakeup = 0x400017e4;\nwdev_mac_sleep = 0x400017e8;\nhal_mac_is_dma_enable = 0x400017ec;\n/*wDev_ProcessFiq = 0x400017f0;*/\n/*wDev_ProcessRxSucData = 0x400017f4;*/\nwdevProcessRxSucDataAll = 0x400017f8;\nwdev_csi_len_align = 0x400017fc;\nppDequeueTxDone_Locked = 0x40001800;\n/*pm_tx_data_done_process = 0x40001808;*/\nconfig_is_cache_tx_buf_enabled = 0x4000180c;\n//ppMapWaitTxq = 0x40001810;\nppProcessWaitingQueue = 0x40001814;\nppDisableQueue = 0x40001818;\npm_allow_tx = 0x4000181c;\n/* Data (.data, .bss, .rodata) */\nour_instances_ptr = 0x3ff1ee44;\npTxRx = 0x3fcdf968;\nlmacConfMib_ptr = 0x3fcdf964;\nour_wait_eb = 0x3fcdf960;\nour_tx_eb = 0x3fcdf95c;\npp_wdev_funcs = 0x3fcdf958;\ng_osi_funcs_p = 0x3fcdf954;\nwDevCtrl_ptr = 0x3fcdf950;\ng_wdev_last_desc_reset_ptr = 0x3ff1ee40;\nwDevMacSleep_ptr = 0x3fcdf94c;\ng_lmac_cnt_ptr = 0x3fcdf948;\nour_controls_ptr = 0x3ff1ee3c;\npp_sig_cnt_ptr = 0x3fcdf944;\ng_eb_list_desc_ptr = 0x3fcdf940;\ns_fragment_ptr = 0x3fcdf93c;\nif_ctrl_ptr = 0x3fcdf938;\ng_intr_lock_mux = 0x3fcdf934;\ng_wifi_global_lock = 0x3fcdf930;\ns_wifi_queue = 0x3fcdf92c;\npp_task_hdl = 0x3fcdf928;\ns_pp_task_create_sem = 0x3fcdf924;\ns_pp_task_del_sem = 0x3fcdf920;\ng_wifi_menuconfig_ptr = 0x3fcdf91c;\nxphyQueue = 0x3fcdf918;\nap_no_lr_ptr = 0x3fcdf914;\nrc11BSchedTbl_ptr = 0x3fcdf910;\nrc11NSchedTbl_ptr = 0x3fcdf90c;\nrcLoRaSchedTbl_ptr = 0x3fcdf908;\nBasicOFDMSched_ptr = 0x3fcdf904;\ntrc_ctl_ptr = 0x3fcdf900;\ng_pm_cnt_ptr = 0x3fcdf8fc;\ng_pm_ptr = 0x3fcdf8f8;\ng_pm_cfg_ptr = 0x3fcdf8f4;\ng_esp_mesh_quick_funcs_ptr = 0x3fcdf8f0;\ng_txop_queue_status_ptr = 0x3fcdf8ec;\ng_mac_sleep_en_ptr = 0x3fcdf8e8;\ng_mesh_is_root_ptr = 0x3fcdf8e4;\ng_mesh_topology_ptr = 0x3fcdf8e0;\ng_mesh_init_ps_type_ptr = 0x3fcdf8dc;\ng_mesh_is_started_ptr = 0x3fcdf8d8;\ng_config_func = 0x3fcdf8d4;\ng_net80211_tx_func = 0x3fcdf8d0;\ng_timer_func = 0x3fcdf8cc;\ns_michael_mic_failure_cb = 0x3fcdf8c8;\nwifi_sta_rx_probe_req = 0x3fcdf8c4;\ng_tx_done_cb_func = 0x3fcdf8c0;\ng_per_conn_trc = 0x3fcdf874;\ns_encap_amsdu_func = 0x3fcdf870;\n\n\n/***************************************\n Group rom_net80211\n ***************************************/\n\n/* Functions */\nesp_net80211_rom_version_get = 0x40001820;\nampdu_dispatch = 0x40001824;\nampdu_dispatch_all = 0x40001828;\nampdu_dispatch_as_many_as_possible = 0x4000182c;\nampdu_dispatch_movement = 0x40001830;\nampdu_dispatch_upto = 0x40001834;\nchm_is_at_home_channel = 0x40001838;\ncnx_node_is_existing = 0x4000183c;\ncnx_node_search = 0x40001840;\nic_ebuf_recycle_rx = 0x40001844;\nic_ebuf_recycle_tx = 0x40001848;\nic_reset_rx_ba = 0x4000184c;\nieee80211_align_eb = 0x40001850;\nieee80211_ampdu_reorder = 0x40001854;\nieee80211_ampdu_start_age_timer = 0x40001858;\n/*ieee80211_encap_esfbuf = 0x4000185c;*/\nieee80211_is_tx_allowed = 0x40001860;\nieee80211_output_pending_eb = 0x40001864;\n/*ieee80211_output_process = 0x40001868;*/\nieee80211_set_tx_desc = 0x4000186c;\nrom_sta_input = 0x40001870;\nwifi_get_macaddr = 0x40001874;\nwifi_rf_phy_disable = 0x40001878;\nwifi_rf_phy_enable = 0x4000187c;\nic_ebuf_alloc = 0x40001880;\nieee80211_classify = 0x40001884;\nieee80211_copy_eb_header = 0x40001888;\nieee80211_recycle_cache_eb = 0x4000188c;\nieee80211_search_node = 0x40001890;\nroundup2 = 0x40001894;\nieee80211_crypto_encap = 0x40001898;\n/* ieee80211_crypto_decap = 0x4000189c; */\n/* ieee80211_decap = 0x400018a0; */\nieee80211_set_tx_pti = 0x400018a4;\nwifi_is_started = 0x400018a8;\n/* Data (.data, .bss, .rodata) */\nnet80211_funcs = 0x3fcdf86c;\ng_scan = 0x3fcdf868;\ng_chm = 0x3fcdf864;\ng_ic_ptr = 0x3fcdf860;\ng_hmac_cnt_ptr = 0x3fcdf85c;\ng_tx_cacheq_ptr = 0x3fcdf858;\ns_netstack_free = 0x3fcdf854;\nmesh_rxcb = 0x3fcdf850;\nsta_rxcb = 0x3fcdf84c;\n\n\n/***************************************\n Group rom_coexist\n ***************************************/\n\n/* Functions */\nesp_coex_rom_version_get = 0x400018ac;\ncoex_bt_release = 0x400018b0;\ncoex_bt_request = 0x400018b4;\ncoex_core_ble_conn_dyn_prio_get = 0x400018b8;\ncoex_core_event_duration_get = 0x400018bc;\ncoex_core_pti_get = 0x400018c0;\ncoex_core_release = 0x400018c4;\ncoex_core_request = 0x400018c8;\ncoex_core_status_get = 0x400018cc;\n/*coex_core_timer_idx_get = 0x400018d0;*/\ncoex_event_duration_get = 0x400018d4;\ncoex_hw_timer_disable = 0x400018d8;\ncoex_hw_timer_enable = 0x400018dc;\ncoex_hw_timer_set = 0x400018e0;\ncoex_schm_interval_set = 0x400018e4;\ncoex_schm_lock = 0x400018e8;\ncoex_schm_unlock = 0x400018ec;\ncoex_status_get = 0x400018f0;\ncoex_wifi_release = 0x400018f4;\nesp_coex_ble_conn_dynamic_prio_get = 0x400018f8;\n/* Data (.data, .bss, .rodata) */\ncoex_env_ptr = 0x3fcdf848;\ncoex_pti_tab_ptr = 0x3fcdf844;\ncoex_schm_env_ptr = 0x3fcdf840;\ncoexist_funcs = 0x3fcdf83c;\ng_coa_funcs_p = 0x3fcdf838;\ng_coex_param_ptr = 0x3fcdf834;\n\n\n/***************************************\n Group rom_phy\n ***************************************/\n\n/* Functions */\nphy_get_romfuncs = 0x400018fc;\nrom_abs_temp = 0x40001900;\nrom_bb_bss_cbw40_dig = 0x40001904;\nrom_bb_wdg_test_en = 0x40001908;\nrom_bb_wdt_get_status = 0x4000190c;\nrom_bb_wdt_int_enable = 0x40001910;\nrom_bb_wdt_rst_enable = 0x40001914;\nrom_bb_wdt_timeout_clear = 0x40001918;\nrom_cbw2040_cfg = 0x4000191c;\nrom_check_noise_floor = 0x40001920;\nrom_chip_i2c_readReg = 0x40001924;\nrom_chip_i2c_writeReg = 0x40001928;\nrom_correct_rf_ana_gain = 0x4000192c;\nrom_dc_iq_est = 0x40001930;\nrom_disable_agc = 0x40001934;\nrom_en_pwdet = 0x40001938;\nrom_enable_agc = 0x4000193c;\nrom_get_bbgain_db = 0x40001940;\nrom_get_data_sat = 0x40001944;\nrom_get_i2c_read_mask = 0x40001948;\nrom_get_pwctrl_correct = 0x4000194c;\nrom_get_rf_gain_qdb = 0x40001950;\nrom_i2c_readReg = 0x40001954;\nrom_i2c_readReg_Mask = 0x40001958;\nrom_i2c_writeReg = 0x4000195c;\nrom_i2c_writeReg_Mask = 0x40001960;\n/* rom_index_to_txbbgain = 0x40001964; */\nrom_iq_est_disable = 0x40001968;\nrom_iq_est_enable = 0x4000196c;\nrom_linear_to_db = 0x40001970;\nrom_loopback_mode_en = 0x40001974;\nrom_mhz2ieee = 0x40001978;\nrom_noise_floor_auto_set = 0x4000197c;\nrom_pbus_debugmode = 0x40001980;\nrom_pbus_force_mode = 0x40001984;\nrom_pbus_force_test = 0x40001988;\nrom_pbus_rd = 0x4000198c;\nrom_pbus_rd_addr = 0x40001990;\nrom_pbus_rd_shift = 0x40001994;\nrom_pbus_set_dco = 0x40001998;\nrom_pbus_set_rxgain = 0x4000199c;\nrom_pbus_workmode = 0x400019a0;\nrom_pbus_xpd_rx_off = 0x400019a4;\nrom_pbus_xpd_rx_on = 0x400019a8;\nrom_pbus_xpd_tx_off = 0x400019ac;\n/* rom_pbus_xpd_tx_on = 0x400019b0; */\nrom_phy_byte_to_word = 0x400019b4;\nrom_phy_disable_cca = 0x400019b8;\nrom_phy_enable_cca = 0x400019bc;\nrom_phy_get_noisefloor = 0x400019c0;\nrom_phy_get_rx_freq = 0x400019c4;\nrom_phy_set_bbfreq_init = 0x400019c8;\nrom_pow_usr = 0x400019cc;\nrom_pwdet_sar2_init = 0x400019d0;\nrom_read_hw_noisefloor = 0x400019d4;\nrom_read_sar_dout = 0x400019d8;\nrom_set_cal_rxdc = 0x400019dc;\nrom_set_chan_cal_interp = 0x400019e0;\nrom_set_loopback_gain = 0x400019e4;\nrom_set_noise_floor = 0x400019e8;\nrom_set_rxclk_en = 0x400019ec;\n/* rom_set_tx_dig_gain = 0x400019f0; */\n/* rom_set_txcap_reg = 0x400019f4; */\nrom_set_txclk_en = 0x400019f8;\nrom_spur_cal = 0x400019fc;\nrom_spur_reg_write_one_tone = 0x40001a00;\nrom_target_power_add_backoff = 0x40001a04;\nrom_tx_pwctrl_bg_init = 0x40001a08;\n/* rom_txbbgain_to_index = 0x40001a0c; */\nrom_wifi_11g_rate_chg = 0x40001a10;\nrom_write_gain_mem = 0x40001a14;\nchip726_phyrom_version = 0x40001a18;\nrom_disable_wifi_agc = 0x40001a1c;\nrom_enable_wifi_agc = 0x40001a20;\nrom_set_tx_gain_table = 0x40001a24;\nrom_bt_index_to_bb = 0x40001a28;\nrom_bt_bb_to_index = 0x40001a2c;\nrom_wr_bt_tx_atten = 0x40001a30;\nrom_wr_bt_tx_gain_mem = 0x40001a34;\nrom_spur_coef_cfg = 0x40001a38;\nrom_bb_bss_cbw40 = 0x40001a3c;\nrom_set_cca = 0x40001a40;\nrom_tx_paon_set = 0x40001a44;\nrom_i2cmst_reg_init = 0x40001a48;\nrom_iq_corr_enable = 0x40001a4c;\nrom_fe_reg_init = 0x40001a50;\n/* rom_agc_reg_init = 0x40001a54; */\n/* rom_bb_reg_init = 0x40001a58; */\nrom_mac_enable_bb = 0x40001a5c;\nrom_bb_wdg_cfg = 0x40001a60;\nrom_force_txon = 0x40001a64;\nrom_fe_txrx_reset = 0x40001a68;\nrom_set_rx_comp = 0x40001a6c;\n/* rom_set_pbus_reg = 0x40001a70; */\nrom_write_chan_freq = 0x40001a74;\n/* rom_phy_xpd_rf = 0x40001a78; */\nrom_set_xpd_sar = 0x40001a7c;\nrom_write_dac_gain2 = 0x40001a80;\nrom_rtc_sar2_init = 0x40001a84;\nrom_get_target_power_offset = 0x40001a88;\n/* rom_write_txrate_power_offset = 0x40001a8c; */\nrom_get_rate_fcc_index = 0x40001a90;\nrom_get_rate_target_power = 0x40001a94;\nrom_write_wifi_dig_gain = 0x40001a98;\nrom_bt_correct_rf_ana_gain = 0x40001a9c;\nrom_pkdet_vol_start = 0x40001aa0;\nrom_read_sar2_code = 0x40001aa4;\nrom_get_sar2_vol = 0x40001aa8;\nrom_get_pll_vol = 0x40001aac;\nrom_get_phy_target_power = 0x40001ab0;\n/* rom_temp_to_power = 0x40001ab4; */\nrom_phy_track_pll_cap = 0x40001ab8;\nrom_phy_pwdet_always_en = 0x40001abc;\nrom_phy_pwdet_onetime_en = 0x40001ac0;\nrom_get_i2c_mst0_mask = 0x40001ac4;\nrom_get_i2c_hostid = 0x40001ac8;\nrom_enter_critical_phy = 0x40001acc;\nrom_exit_critical_phy = 0x40001ad0;\nrom_chip_i2c_readReg_org = 0x40001ad4;\nrom_i2c_paral_set_mst0 = 0x40001ad8;\nrom_i2c_paral_set_read = 0x40001adc;\nrom_i2c_paral_read = 0x40001ae0;\nrom_i2c_paral_write = 0x40001ae4;\nrom_i2c_paral_write_num = 0x40001ae8;\nrom_i2c_paral_write_mask = 0x40001aec;\nrom_bb_bss_cbw40_ana = 0x40001af0;\nrom_chan_to_freq = 0x40001af4;\n/* rom_open_i2c_xpd = 0x40001af8; */\nrom_dac_rate_set = 0x40001afc;\n/* rom_tsens_read_init = 0x40001b00; */\n/* rom_tsens_code_read = 0x40001b04; */\nrom_tsens_index_to_dac = 0x40001b08;\nrom_tsens_index_to_offset = 0x40001b0c;\n/* rom_tsens_dac_cal = 0x40001b10; */\nrom_code_to_temp = 0x40001b14;\nrom_write_pll_cap_mem = 0x40001b18;\nrom_pll_correct_dcap = 0x40001b1c;\nrom_phy_en_hw_set_freq = 0x40001b20;\nrom_phy_dis_hw_set_freq = 0x40001b24;\n/* rom_pll_vol_cal = 0x40001b28; */\n"
  },
  {
    "path": "targets/esp32s3.json",
    "content": "{\n\t\"inherits\": [\"xtensa\"],\n\t\"cpu\": \"esp32s3\",\n\t\"features\": \"+atomctl,+bool,+clamps,+coprocessor,+debug,+density,+div32,+esp32s3,+exception,+fp,+highpriinterrupts,+interrupt,+loop,+mac16,+memctl,+minmax,+miscsr,+mul32,+mul32high,+nsa,+prid,+regprotect,+rvector,+s32c1i,+sext,+threadptr,+timerint,+windowed\",\n\t\"build-tags\": [\"esp32s3\", \"esp\"],\n\t\"scheduler\": \"tasks\",\n\t\"serial\": \"uart\",\n\t\"linker\": \"ld.lld\",\n\t\"default-stack-size\": 2048,\n\t\"rtlib\": \"compiler-rt\",\n\t\"libc\": \"picolibc\",\n\t\"linkerscript\": \"targets/esp32s3.ld\",\n\t\"extra-files\": [\n\t\t\"src/device/esp/esp32.S\",\n\t\t\"src/internal/task/task_stack_esp32.S\"\n\t],\n\t\"binary-format\": \"esp32s3\",\n\t\"flash-command\": \"esptool.py --chip=esp32s3 --port {port} write_flash 0x0000 {bin} -ff 80m -fm dout\",\n\t\"emulator\": \"qemu-system-xtensa -machine esp32 -nographic -drive file={img},if=mtd,format=raw\",\n\t\"gdb\": [\"xtensa-esp32-elf-gdb\"]\n}\n"
  },
  {
    "path": "targets/esp32s3.ld",
    "content": "/* Linker script for the ESP32-S3 */\n\n\nMEMORY\n{\n    /* Note: DRAM and IRAM below are actually in the same 416K address space. */\n    DRAM (rw) : ORIGIN = 0x3FC88000, LENGTH = 416K /* Internal SRAM 1 (data bus) */\n    IRAM (x)  : ORIGIN = 0x40370000, LENGTH = 416K /* Internal SRAM 1 (instruction bus) */\n\n    /* Note: DROM and IROM below are actually in the same 32M address space. */\n    DROM (r)  : ORIGIN = 0x3C000000, LENGTH = 32M /* Data bus (read-only) */\n    IROM (rx) : ORIGIN = 0x42000000, LENGTH = 32M /* Instruction bus */\n}\n\n/* The entry point. It is set in the image flashed to the chip, so must be\n * defined.\n */\nENTRY(call_start_cpu0)\n\nSECTIONS\n{\n    /* Put the stack at the bottom of DRAM, so that the application will\n     * crash on stack overflow instead of silently corrupting memory.\n     * See: http://blog.japaric.io/stack-overflow-protection/ */\n    .stack (NOLOAD) :\n    {\n        . = ALIGN(16);\n        . += _stack_size;\n        _stack_top = .;\n    } >DRAM\n\n    /* Constant literals and code. Loaded into IRAM for now. Eventually, most\n     * code should be executed directly from flash.\n     * Note that literals must be before code for the l32r instruction to work.\n     */\n.text.call_start_cpu0 : ALIGN(4)\n{\n    *(.literal.call_start_cpu0)\n    *(.text.call_start_cpu0)\n} >IRAM AT >DRAM\n\n/* All other code and literals */\n.text : ALIGN(4)\n{\n    *(.literal .text)\n    *(.literal.* .text.*)\n    *(.text)\n    *(.text.*)\n} >IRAM AT >DRAM\n\n    /* Constant global variables.\n     * They are loaded in DRAM for ease of use. Eventually they should be stored\n     * in flash and loaded directly from there but they're kept in RAM to make\n     * sure they can always be accessed (even in interrupts).\n     */\n    .rodata : ALIGN(4)\n    {\n        *(.rodata)\n        *(.rodata.*)\n    } >DRAM\n\n    /* Mutable global variables.\n     */\n    .data : ALIGN(4)\n    {\n        _sdata = ABSOLUTE(.);\n        *(.data)\n        *(.data.*)\n        _edata = ABSOLUTE(.);\n    } >DRAM\n\n    /* Check that the boot ROM stack (for the APP CPU) does not overlap with the\n     * data that is loaded by the boot ROM. There may be ways to avoid this\n     * issue if it occurs in practice.\n     * The magic value here is _stack_sentry in the boot ROM ELF file.\n     */\n    ASSERT(_edata < 0x3ffe1320, \"the .data section overlaps with the stack used by the boot ROM, possibly causing corruption at startup\")\n\n    /* Global variables that are mutable and zero-initialized.\n     * These must be zeroed at startup (unlike data, which is loaded by the\n     * bootloader).\n     */\n    .bss (NOLOAD) : ALIGN(4)\n    {\n        . = ALIGN (4);\n        _sbss = ABSOLUTE(.);\n        *(.bss)\n        *(.bss.*)\n        . = ALIGN (4);\n        _ebss = ABSOLUTE(.);\n    } >DRAM\n}\n\n/* For the garbage collector.\n */\n_globals_start = _sdata;\n_globals_end = _ebss;\n_heap_start = _ebss;\n_heap_end = ORIGIN(DRAM) + LENGTH(DRAM);\n\n_stack_size = 4K;\n\n/* From ESP-IDF:\n * components/esp_rom/esp32/ld/esp32.rom.newlib-funcs.ld\n * This is the subset that is sometimes used by LLVM during codegen, and thus\n * must always be present.\n */\nmemset = 0x400011e8;\nmemcpy = 0x400011f4;\nmemmove = 0x40001200;\nmemcmp = 0x4000120c;\n\n/* From ESP-IDF:\n * components/esp_rom/esp32/ld/esp32.rom.libgcc.ld\n * These are called from LLVM during codegen. The original license is Apache\n * 2.0, but I believe that a list of function names and addresses can't really\n * be copyrighted.\n */\n__absvdi2 = 0x4000216c;\n__absvsi2 = 0x40002178;\n__adddf3 = 0x40002184;\n__addsf3 = 0x40002190;\n__addvdi3 = 0x4000219c;\n__addvsi3 = 0x400021a8;\n__ashldi3 = 0x400021b4;\n__ashrdi3 = 0x400021c0;\n__bswapdi2 = 0x400021cc;\n__bswapsi2 = 0x400021d8;\n__clear_cache = 0x400021e4;\n__clrsbdi2 = 0x400021f0;\n__clrsbsi2 = 0x400021fc;\n__clzdi2 = 0x40002208;\n__clzsi2 = 0x40002214;\n__cmpdi2 = 0x40002220;\n__ctzdi2 = 0x4000222c;\n__ctzsi2 = 0x40002238;\n__divdc3 = 0x40002244;\n__divdf3 = 0x40002250;\n__divdi3 = 0x4000225c;\n__divsc3 = 0x40002268;\n__divsf3 = 0x40002274;\n__divsi3 = 0x40002280;\n__eqdf2 = 0x4000228c;\n__eqsf2 = 0x40002298;\n__extendsfdf2 = 0x400022a4;\n__ffsdi2 = 0x400022b0;\n__ffssi2 = 0x400022bc;\n__fixdfdi = 0x400022c8;\n__fixdfsi = 0x400022d4;\n__fixsfdi = 0x400022e0;\n__fixsfsi = 0x400022ec;\n__fixunsdfsi = 0x400022f8;\n__fixunssfdi = 0x40002304;\n__fixunssfsi = 0x40002310;\n__floatdidf = 0x4000231c;\n__floatdisf = 0x40002328;\n__floatsidf = 0x40002334;\n__floatsisf = 0x40002340;\n__floatundidf = 0x4000234c;\n__floatundisf = 0x40002358;\n__floatunsidf = 0x40002364;\n__floatunsisf = 0x40002370;\n__gcc_bcmp = 0x4000237c;\n__gedf2 = 0x40002388;\n__gesf2 = 0x40002394;\n__gtdf2 = 0x400023a0;\n__gtsf2 = 0x400023ac;\n__ledf2 = 0x400023b8;\n__lesf2 = 0x400023c4;\n__lshrdi3 = 0x400023d0;\n__ltdf2 = 0x400023dc;\n__ltsf2 = 0x400023e8;\n__moddi3 = 0x400023f4;\n__modsi3 = 0x40002400;\n__muldc3 = 0x4000240c;\n__muldf3 = 0x40002418;\n__muldi3 = 0x40002424;\n__mulsc3 = 0x40002430;\n__mulsf3 = 0x4000243c;\n__mulsi3 = 0x40002448;\n__mulvdi3 = 0x40002454;\n__mulvsi3 = 0x40002460;\n__nedf2 = 0x4000246c;\n__negdf2 = 0x40002478;\n__negdi2 = 0x40002484;\n__negsf2 = 0x40002490;\n__negvdi2 = 0x4000249c;\n__negvsi2 = 0x400024a8;\n__nesf2 = 0x400024b4;\n__paritysi2 = 0x400024c0;\n__popcountdi2 = 0x400024cc;\n__popcountsi2 = 0x400024d8;\n__powidf2 = 0x400024e4;\n__powisf2 = 0x400024f0;\n__subdf3 = 0x400024fc;\n__subsf3 = 0x40002508;\n__subvdi3 = 0x40002514;\n__subvsi3 = 0x40002520;\n__truncdfsf2 = 0x4000252c;\n__ucmpdi2 = 0x40002538;\n__udivdi3 = 0x40002544;\n__udivmoddi4 = 0x40002550;\n__udivsi3 = 0x4000255c;\n__udiv_w_sdiv = 0x40002568;\n__umoddi3 = 0x40002574;\n__umodsi3 = 0x40002580;\n__unorddf2 = 0x4000258c;\n__unordsf2 = 0x40002598;\n"
  },
  {
    "path": "targets/esp8266.json",
    "content": "{\n\t\"inherits\": [\"xtensa\"],\n\t\"cpu\": \"esp8266\",\n\t\"features\": \"+debug,+density,+exception,+extendedl32r,+highpriinterrupts,+interrupt,+mul32,+nsa,+prid,+regprotect,+rvector,+timerint\",\n\t\"build-tags\": [\"esp8266\", \"esp\"],\n\t\"scheduler\": \"tasks\",\n\t\"linker\": \"ld.lld\",\n\t\"default-stack-size\": 2048,\n\t\"rtlib\": \"compiler-rt\",\n\t\"libc\": \"picolibc\",\n\t\"linkerscript\": \"targets/esp8266.ld\",\n\t\"extra-files\": [\n\t\t\"src/device/esp/esp8266.S\",\n\t\t\"src/internal/task/task_stack_esp8266.S\"\n\t],\n\t\"binary-format\": \"esp8266\",\n\t\"flash-command\": \"esptool.py --chip=esp8266 --port {port} write_flash 0x00000 {bin} -fm qio\"\n}\n"
  },
  {
    "path": "targets/esp8266.ld",
    "content": "/* Linker script for the ESP8266 */\n\nMEMORY\n{\n    /* Data RAM. Allows byte access. */\n    DRAM  (rw) : ORIGIN = 0x3FFE8000, LENGTH = 80K\n    /* Instruction RAM. */\n    IRAM  (x)  : ORIGIN = 0x40100000, LENGTH = 32K\n}\n\n/* The entry point. It is set in the image flashed to the chip, so must be\n * defined.\n */\nENTRY(main)\n\nSECTIONS\n{\n    /* Mutable global variables.\n     */\n    .data : ALIGN(4)\n    {\n        _sdata = ABSOLUTE(.);\n        *(.data)\n        *(.data.*)\n    } >DRAM\n\n    /* Constant global variables.\n     * Note that they still need to be loaded in RAM because the ESP8266 doesn't\n     * allow byte access to flash.\n     */\n    .rodata : ALIGN(4)\n    {\n        *(.rodata)\n        *(.rodata.*)\n    } >DRAM\n\n    /* Global variables that are mutable and zero-initialized.\n     */\n    .bss (NOLOAD) : ALIGN(4)\n    {\n        . = ALIGN (4);\n        _sbss = ABSOLUTE(.);\n        *(.bss)\n        *(.bss.*)\n        . = ALIGN (4);\n        _ebss = ABSOLUTE(.);\n    } >DRAM\n\n    /* Constant literals and code. Loaded into IRAM for now. Eventually, most\n     * code should be executed directly from flash.\n     * Note that literals must be before code for the l32r instruction to work.\n     */\n    .text : ALIGN(4)\n    {\n        *(.literal .text)\n        *(.literal.* .text.*)\n    } >IRAM\n}\n\n_globals_start = _sdata;\n_globals_end = _ebss;\n_heap_start = _ebss;\n_heap_end = ORIGIN(DRAM) + LENGTH(DRAM);\n\n/* It appears that the stack is set to 0x3ffffff0 when main is called.\n * Be conservative and scan all the way up to the end of the RAM.\n */\n_stack_top = 0x40000000;\n\n/* Functions normally provided by a libc.\n * Source:\n * https://github.com/espressif/ESP8266_NONOS_SDK/blob/master/ld/eagle.rom.addr.v6.ld\n */\nmemcpy  = 0x4000df48;\nmemmove = 0x4000e04c;\nmemset  = 0x4000e190;\n\n/* Compiler runtime functions provided by the ROM.\n * Source:\n * https://github.com/espressif/ESP8266_NONOS_SDK/blob/master/ld/eagle.rom.addr.v6.ld\n */\n__adddf3      = 0x4000c538;\n__addsf3      = 0x4000c180;\n__divdf3      = 0x4000cb94;\n__divdi3      = 0x4000ce60;\n__divsi3      = 0x4000dc88;\n__extendsfdf2 = 0x4000cdfc;\n__fixdfsi     = 0x4000ccb8;\n__fixunsdfsi  = 0x4000cd00;\n__fixunssfsi  = 0x4000c4c4;\n__floatsidf   = 0x4000e2f0;\n__floatsisf   = 0x4000e2ac;\n__floatunsidf = 0x4000e2e8;\n__floatunsisf = 0x4000e2a4;\n__muldf3      = 0x4000c8f0;\n__muldi3      = 0x40000650;\n__mulsf3      = 0x4000c3dc;\n__subdf3      = 0x4000c688;\n__subsf3      = 0x4000c268;\n__truncdfsf2  = 0x4000cd5c;\n__udivdi3     = 0x4000d310;\n__udivsi3     = 0x4000e21c;\n__umoddi3     = 0x4000d770;\n__umodsi3     = 0x4000e268;\n__umulsidi3   = 0x4000dcf0;\n\n/* Proprietary ROM function needed for proper clock configuration.\n */\nrom_i2c_writeReg = 0x400072d8;\n"
  },
  {
    "path": "targets/fe310.json",
    "content": "{\n\t\"inherits\": [\"riscv32\"],\n\t\"cpu\": \"sifive-e31\",\n\t\"features\": \"+32bit,+a,+c,+m,+zaamo,+zalrsc,+zmmul,-b,-d,-e,-experimental-sdext,-experimental-sdtrig,-experimental-smctr,-experimental-ssctr,-experimental-svukte,-experimental-xqcia,-experimental-xqciac,-experimental-xqcicli,-experimental-xqcicm,-experimental-xqcics,-experimental-xqcicsr,-experimental-xqciint,-experimental-xqcilo,-experimental-xqcilsm,-experimental-xqcisls,-experimental-zalasr,-experimental-zicfilp,-experimental-zicfiss,-experimental-zvbc32e,-experimental-zvkgs,-f,-h,-relax,-sha,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smcdeleg,-smcsrind,-smdbltrp,-smepmp,-smmpm,-smnpm,-smrnmi,-smstateen,-ssaia,-ssccfg,-ssccptr,-sscofpmf,-sscounterenw,-sscsrind,-ssdbltrp,-ssnpm,-sspm,-ssqosid,-ssstateen,-ssstrict,-sstc,-sstvala,-sstvecd,-ssu64xl,-supm,-svade,-svadu,-svbare,-svinval,-svnapot,-svpbmt,-svvptc,-v,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xesppie,-xmipscmove,-xmipslsp,-xsfcease,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xsifivecdiscarddlone,-xsifivecflushdlone,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-xwchc,-za128rs,-za64rs,-zabha,-zacas,-zama16b,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmop,-zcmp,-zcmt,-zdinx,-zfa,-zfbfmin,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zicsr,-zifencei,-zihintntl,-zihintpause,-zihpm,-zimop,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-ztso,-zvbb,-zvbc,-zve32f,-zve32x,-zve64d,-zve64f,-zve64x,-zvfbfmin,-zvfbfwma,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl128b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl32b,-zvl4096b,-zvl512b,-zvl64b,-zvl65536b,-zvl8192b\",\n\t\"build-tags\": [\"fe310\", \"sifive\"]\n}\n"
  },
  {
    "path": "targets/feather-m0-express.json",
    "content": "{\n    \"inherits\": [\"atsamd21g18a\"],\n    \"build-tags\": [\"feather_m0_express\"],\n    \"serial\": \"usb\",\n    \"serial-port\": [\"239a:801b\"],\n    \"flash-1200-bps-reset\": \"true\",\n    \"flash-method\": \"msd\",\n    \"msd-volume-name\": [\"FEATHERBOOT\"],\n    \"msd-firmware-name\": \"firmware.uf2\"\n}\n"
  },
  {
    "path": "targets/feather-m0.json",
    "content": "{\n    \"inherits\": [\"atsamd21g18a\"],\n    \"build-tags\": [\"feather_m0\"],\n    \"serial\": \"usb\",\n    \"serial-port\": [\"239a:801b\", \"239a:800b\"],\n    \"flash-1200-bps-reset\": \"true\",\n    \"flash-method\": \"msd\",\n    \"msd-volume-name\": [\"FEATHERBOOT\"],\n    \"msd-firmware-name\": \"firmware.uf2\"\n}\n"
  },
  {
    "path": "targets/feather-m4-can.json",
    "content": "{\n    \"inherits\": [\"atsame51j19a\"],\n    \"build-tags\": [\"feather_m4_can\"],\n    \"serial\": \"usb\",\n    \"serial-port\": [\"239a:80cd\"],\n    \"flash-1200-bps-reset\": \"true\",\n    \"flash-method\": \"msd\",\n    \"msd-volume-name\": [\"FTHRCANBOOT\"],\n    \"msd-firmware-name\": \"firmware.uf2\"\n}\n"
  },
  {
    "path": "targets/feather-m4.json",
    "content": "{\n    \"inherits\": [\"atsamd51j19a\"],\n    \"build-tags\": [\"feather_m4\"],\n    \"serial\": \"usb\",\n    \"serial-port\": [\"239a:8022\"],\n    \"flash-1200-bps-reset\": \"true\",\n    \"flash-method\": \"msd\",\n    \"msd-volume-name\": [\"FEATHERBOOT\"],\n    \"msd-firmware-name\": \"firmware.uf2\"\n}\n"
  },
  {
    "path": "targets/feather-nrf52840-sense.json",
    "content": "{\n    \"inherits\": [\"nrf52840\", \"nrf52840-s140v6-uf2\"],\n    \"build-tags\": [\"feather_nrf52840_sense\"],\n    \"serial-port\": [\"239a:8087\", \"239a:8088\"],\n    \"msd-volume-name\": [\"FTHRSNSBOOT\"]\n}\n"
  },
  {
    "path": "targets/feather-nrf52840.json",
    "content": "{\n    \"inherits\": [\"nrf52840\", \"nrf52840-s140v6-uf2\"],\n    \"build-tags\": [\"feather_nrf52840\"],\n    \"serial-port\": [\"239a:8029\", \"239a:802a\"],\n    \"msd-volume-name\": [\"FTHR840BOOT\"]\n}\n"
  },
  {
    "path": "targets/feather-rp2040-boot-stage2.S",
    "content": "// Adafruit Feather RP2040 Stage 2 Bootloader\n\n//\n// This file defines the parameters specific to the flash-chip found\n// on the Adafruit Feather RP2040.  The generic implementation is in\n// rp2040-boot-stage2.S\n//\n\n#define BOARD_PICO_FLASH_SPI_CLKDIV   4\n#define BOARD_CMD_READ                0xe7\n#define BOARD_QUAD_OK                 1\n#define BOARD_QUAD_ENABLE_STATUS_BYTE 2\n#define BOARD_QUAD_ENABLE_BIT_MASK    2\n#define BOARD_SPLIT_STATUS_WRITE      1\n#define BOARD_WAIT_CYCLES             2\n\n#include \"rp2040-boot-stage2.S\"\n"
  },
  {
    "path": "targets/feather-rp2040.json",
    "content": "{\n    \"inherits\": [\n        \"rp2040\"\n    ],\n    \"serial-port\": [\"239a:80f1\"],\n    \"default-stack-size\": 8192,\n    \"build-tags\": [\"feather_rp2040\"],\n    \"ldflags\": [\n        \"--defsym=__flash_size=8192K\"\n    ],\n    \"extra-files\": [\n        \"targets/feather-rp2040-boot-stage2.S\"\n    ]\n}\n"
  },
  {
    "path": "targets/feather-stm32f405.json",
    "content": "{\n  \"inherits\": [\"cortex-m4\"],\n  \"build-tags\": [\"feather_stm32f405\", \"stm32f405\", \"stm32f4\", \"stm32\"],\n  \"serial\": \"uart\",\n  \"automatic-stack-size\": false,\n  \"linkerscript\": \"targets/stm32f405.ld\",\n  \"extra-files\": [\n    \"src/device/stm32/stm32f405.s\"\n  ],\n  \"flash-method\": \"command\",\n  \"flash-command\": \"dfu-util --alt 0 --dfuse-address 0x08000000 --download {bin}\",\n  \"openocd-transport\": \"swd\",\n  \"openocd-interface\": \"jlink\",\n  \"openocd-target\": \"stm32f4x\"\n}\n"
  },
  {
    "path": "targets/gameboy-advance.json",
    "content": "{\n\t\"llvm-target\": \"armv4t-unknown-unknown-eabi\",\n\t\"cpu\": \"arm7tdmi\",\n\t\"features\": \"+armv4t,+strict-align,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-thumb-mode,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp\",\n\t\"build-tags\": [\"gameboyadvance\", \"arm7tdmi\", \"baremetal\", \"linux\", \"arm\"],\n\t\"goos\": \"linux\",\n\t\"goarch\": \"arm\",\n\t\"linker\": \"ld.lld\",\n\t\"rtlib\": \"compiler-rt\",\n\t\"libc\": \"picolibc\",\n\t\"cflags\": [\n\t\t\"-Werror\",\n\t\t\"-fshort-enums\",\n\t\t\"-fomit-frame-pointer\",\n\t\t\"-fno-exceptions\", \"-fno-unwind-tables\", \"-fno-asynchronous-unwind-tables\",\n\t\t\"-ffunction-sections\", \"-fdata-sections\"\n\t],\n\t\"ldflags\": [\n\t\t\"--gc-sections\"\n\t],\n\t\"linkerscript\": \"targets/gameboy-advance.ld\",\n\t\"extra-files\": [\n\t\t\"targets/gameboy-advance.s\",\n\t\t\"src/runtime/asm_arm.S\"\n\t],\n\t\"gdb\": [\"gdb-multiarch\"],\n\t\"emulator\": \"mgba -3 {}\"\n}\n"
  },
  {
    "path": "targets/gameboy-advance.ld",
    "content": "OUTPUT_ARCH(arm)\nENTRY(_start)\n\n/* Note: iwram is reduced by 96 bytes because the last part of that RAM\n * (starting at 0x03007FA0) is used for interrupt handling.\n */\nMEMORY {\n    ewram   : ORIGIN = 0x02000000, LENGTH = 256K   /* on-board work RAM (2 wait states) */\n    iwram   : ORIGIN = 0x03000000, LENGTH = 32K-96 /* in-chip work RAM (faster) */\n    rom     : ORIGIN = 0x08000000, LENGTH = 32M    /* flash ROM */\n}\n\n__stack_size_irq = 1K;\n__stack_size_usr = 2K;\n\nSECTIONS\n{\n    .text :\n    {\n        KEEP (*(.init))\n        *(.text)\n        *(.text.*)\n        . = ALIGN(4);\n    } >rom\n\n    .rodata :\n    {\n        . = ALIGN(4);\n        *(.rodata)\n        *(.rodata.*)\n        . = ALIGN(4);\n    } >rom\n\n    /* Put the stack at the bottom of RAM, so that the application will\n     * crash on stack overflow instead of silently corrupting memory.\n     * See: http://blog.japaric.io/stack-overflow-protection/ */\n    .stack (NOLOAD) :\n    {\n        . = ALIGN(4);\n        _stack_top_irq = .;\n        . += __stack_size_irq;\n        _stack_top = .;\n        . += __stack_size_usr;\n    } >iwram\n\n    /* Start address (in flash) of .data, used by startup code. */\n    _sidata = LOADADDR(.data);\n\n    /* Globals with initial value */\n    .data :\n    {\n        . = ALIGN(4);\n        _sdata = .;        /* used by startup code */\n        *(.data)\n        *(.data.*)\n        *(.iwram .iwram.*)\n        . = ALIGN(4);\n        _edata = .;        /* used by startup code */\n    } >iwram AT>rom\n\n    /* Zero-initialized globals  */\n    .bss :\n    {\n        . = ALIGN(4);\n        _sbss = .;         /* used by startup code */\n        *(.bss)\n        *(.bss.*)\n        *(COMMON)\n        . = ALIGN(4);\n        _ebss = .;         /* used by startup code */\n    } >iwram\n\n    /DISCARD/ :\n    {\n        *(.ARM.exidx)      /* causes 'no memory region specified' error in lld */\n        *(.ARM.exidx.*)    /* causes spurious 'undefined reference' errors */\n    }\n}\n\n/* For the memory allocator. */\n_heap_start = ORIGIN(ewram);\n_heap_end = ORIGIN(ewram) + LENGTH(ewram);\n_globals_start = _sdata;\n_globals_end = _ebss;\n"
  },
  {
    "path": "targets/gameboy-advance.s",
    "content": ".section    .init\n.global     _start\n.align\n.arm\n\n_start:\n    b       start_vector\n\n    // ROM header\n    .byte 0x24,0xff,0xae,0x51,0x69,0x9a,0xa2,0x21,0x3d,0x84,0x82,0x0a,0x84,0xe4,0x09,0xad\n    .byte 0x11,0x24,0x8b,0x98,0xc0,0x81,0x7f,0x21,0xa3,0x52,0xbe,0x19,0x93,0x09,0xce,0x20\n    .byte 0x10,0x46,0x4a,0x4a,0xf8,0x27,0x31,0xec,0x58,0xc7,0xe8,0x33,0x82,0xe3,0xce,0xbf\n    .byte 0x85,0xf4,0xdf,0x94,0xce,0x4b,0x09,0xc1,0x94,0x56,0x8a,0xc0,0x13,0x72,0xa7,0xfc\n    .byte 0x9f,0x84,0x4d,0x73,0xa3,0xca,0x9a,0x61,0x58,0x97,0xa3,0x27,0xfc,0x03,0x98,0x76\n    .byte 0x23,0x1d,0xc7,0x61,0x03,0x04,0xae,0x56,0xbf,0x38,0x84,0x00,0x40,0xa7,0x0e,0xfd\n    .byte 0xff,0x52,0xfe,0x03,0x6f,0x95,0x30,0xf1,0x97,0xfb,0xc0,0x85,0x60,0xd6,0x80,0x25\n    .byte 0xa9,0x63,0xbe,0x03,0x01,0x4e,0x38,0xe2,0xf9,0xa2,0x34,0xff,0xbb,0x3e,0x03,0x44\n    .byte 0x78,0x00,0x90,0xcb,0x88,0x11,0x3a,0x94,0x65,0xc0,0x7c,0x63,0x87,0xf0,0x3c,0xaf\n    .byte 0xd6,0x25,0xe4,0x8b,0x38,0x0a,0xac,0x72,0x21,0xd4,0xf8,0x07\n\n    // Game title\n    .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n\n    // Game code\n    .byte 0x00,0x00,0x00,0x00\n\n    // Maker code\n    .byte 0x00,0x00\n\n    // Fixed value\n    .byte 0x96\n\n    // Main unit code\n    .byte 0x00\n\n    // Device type (0x00 retail, 0x80 debug)\n    .byte 0x00\n\n    // Reserved\n    .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00\n\n    // Software version\n    .byte 0x00\n\n    // Complement check\n    .byte 0x51\n\n    // Reserved area\n    .space 98\n\nstart_vector:\n    // Configure stacks\n    mov     r0, #0x12                      // Switch to IRQ Mode\n    msr     cpsr, r0\n    ldr     sp, =_stack_top_irq            // Set IRQ stack\n    mov     r0, #0x1f                      // Switch to System Mode\n    msr     cpsr, r0\n    ldr     sp, =_stack_top                // Set user stack\n\n    // Configure interrupt handler\n    mov     r0, #0x4000000                 // REG_BASE\n    ldr     r1, =handleInterruptARM\n    str     r1, [r0, #-4]                  // actually storing to 0x03007FFC due to mirroring\n\n    // Enable interrupts\n    mov     r1, #1\n    str     r1, [r0, #0x208]               // 0x04000208 Interrupt Master Enable\n\n    // Jump to user code (switching to Thumb mode)\n    ldr     r3, =main\n    bx      r3\n\n// Small interrupt handler that immediately jumps to a function defined in the\n// program (in Thumb) for further processing.\nhandleInterruptARM:\n    ldr     r0, =handleInterrupt\n    bx      r0\n"
  },
  {
    "path": "targets/gemma-m0.json",
    "content": "{\n    \"inherits\": [\"atsamd21e18a\"],\n    \"build-tags\": [\"gemma_m0\"],\n    \"serial\": \"usb\",\n    \"serial-port\": [\"239a:801e\"],\n    \"flash-1200-bps-reset\": \"true\",\n    \"flash-method\": \"msd\",\n    \"msd-volume-name\": [\"GEMMABOOT\"],\n    \"msd-firmware-name\": \"firmware.uf2\"\n}\n"
  },
  {
    "path": "targets/gnse.json",
    "content": "{\n\t\"inherits\": [\n\t\t\"stm32wl5x_cm4\"\n\t],\n\t\"build-tags\": [\n\t\t\"gnse\"\n\t],\n\t\"serial\": \"uart\",\n\t\"flash-method\": \"openocd\",\n\t\"openocd-interface\": \"stlink\",\n\t\"openocd-target\": \"stm32wlx\"\n}\n"
  },
  {
    "path": "targets/gobadge.json",
    "content": "{\n\t\"inherits\": [\"pybadge\"]\n}\n"
  },
  {
    "path": "targets/gopher-arcade.json",
    "content": "{\n\t\"inherits\": [\"attiny85\"],\n\t\"build-tags\": [\"gopher_arcade\"],\n\t\"ldflags\": [\n\t\t\"--defsym=_bootloader_size=2180\",\n\t\t\"--defsym=_stack_size=128\"\n\t],\n\t\"flash-command\": \"avrdude -c usbasp -p t85 -B 10 -U flash:w:{hex}:i\",\n\t\"emulator\": \"simavr -m attiny85 -f 16000000 {}\"\n}\n"
  },
  {
    "path": "targets/gopher-badge.json",
    "content": "{\n    \"inherits\": [\n        \"rp2040\"\n    ],\n    \"serial-port\": [\"2e8a:0003\"],\n    \"default-stack-size\": 8192,\n    \"build-tags\": [\"gopher_badge\"],\n    \"ldflags\": [\n        \"--defsym=__flash_size=8M\"\n    ],\n    \"extra-files\": [\n        \"targets/pico-boot-stage2.S\"\n    ]\n}\n"
  },
  {
    "path": "targets/gopherbot.json",
    "content": "{\n\t\"inherits\": [\"circuitplay-express\"]\n}\n"
  },
  {
    "path": "targets/gopherbot2.json",
    "content": "{\n\t\"inherits\": [\"circuitplay-bluefruit\"]\n}\n"
  },
  {
    "path": "targets/grandcentral-m4.json",
    "content": "{\n    \"inherits\": [\"atsamd51p20a\"],\n    \"build-tags\": [\"grandcentral_m4\"],\n    \"serial\": \"usb\",\n    \"serial-port\": [\"239a:8031\"],\n    \"flash-1200-bps-reset\": \"true\",\n    \"flash-method\": \"msd\",\n    \"msd-volume-name\": [\"GCM4BOOT\"],\n    \"msd-firmware-name\": \"firmware.uf2\",\n    \"openocd-interface\": \"jlink\"\n}\n"
  },
  {
    "path": "targets/hifive1b.json",
    "content": "{\n\t\"inherits\": [\"fe310\"],\n\t\"build-tags\": [\"hifive1b\"],\n\t\"serial\": \"uart\",\n\t\"linkerscript\": \"targets/hifive1b.ld\",\n\t\"flash-method\": \"msd\",\n\t\"msd-volume-name\": [\"HiFive\"],\n\t\"msd-firmware-name\": \"firmware.hex\",\n\t\"jlink-device\": \"fe310\"\n}\n"
  },
  {
    "path": "targets/hifive1b.ld",
    "content": "\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x20010000, LENGTH = 0x6a120\n    RAM (xrw)       : ORIGIN = 0x80000000, LENGTH = 0x4000\n}\n\n_stack_size = 2K;\n\nINCLUDE \"targets/riscv.ld\"\n"
  },
  {
    "path": "targets/hw-651-s110v8.json",
    "content": "{\n\t\"inherits\": [\"hw-651\", \"nrf51-s110v8\"]\n}\n"
  },
  {
    "path": "targets/hw-651.json",
    "content": "{\n\t\"inherits\": [\"nrf51\"],\n\t\"build-tags\": [\"hw_651\"],\n\t\"serial\": \"uart\",\n\t\"flash-method\": \"openocd\",\n\t\"openocd-interface\": \"cmsis-dap\"\n}\n"
  },
  {
    "path": "targets/itsybitsy-m0.json",
    "content": "{\n    \"inherits\": [\"atsamd21g18a\"],\n    \"build-tags\": [\"itsybitsy_m0\"],\n    \"serial\": \"usb\",\n    \"serial-port\": [\"239a:800f\", \"239a:8012\"],\n    \"flash-1200-bps-reset\": \"true\",\n    \"flash-method\": \"msd\",\n    \"msd-volume-name\": [\"ITSYBOOT\"],\n    \"msd-firmware-name\": \"firmware.uf2\"\n}\n"
  },
  {
    "path": "targets/itsybitsy-m4.json",
    "content": "{\n    \"inherits\": [\"atsamd51g19a\"],\n    \"build-tags\": [\"itsybitsy_m4\"],\n    \"serial\": \"usb\",\n    \"flash-1200-bps-reset\": \"true\",\n    \"flash-method\": \"msd\",\n    \"serial-port\": [\"239a:802b\"],\n    \"msd-volume-name\": [\"ITSYM4BOOT\"],\n    \"msd-firmware-name\": \"firmware.uf2\"\n}\n"
  },
  {
    "path": "targets/itsybitsy-nrf52840.json",
    "content": "{\n    \"inherits\": [\"nrf52840\", \"nrf52840-s140v6-uf2\"],\n    \"build-tags\": [\"itsybitsy_nrf52840\"],\n    \"serial-port\": [\"239A:8052\", \"239A:8051\"],\n    \"msd-volume-name\": [\"ITSY840BOOT\"]\n}\n"
  },
  {
    "path": "targets/k210.json",
    "content": "{\n\t\"inherits\": [\"riscv64\"],\n\t\"features\": \"+64bit,+a,+c,+d,+f,+m,+zaamo,+zalrsc,+zicsr,+zifencei,+zmmul,-b,-e,-experimental-sdext,-experimental-sdtrig,-experimental-smctr,-experimental-ssctr,-experimental-svukte,-experimental-xqcia,-experimental-xqciac,-experimental-xqcicli,-experimental-xqcicm,-experimental-xqcics,-experimental-xqcicsr,-experimental-xqciint,-experimental-xqcilo,-experimental-xqcilsm,-experimental-xqcisls,-experimental-zalasr,-experimental-zicfilp,-experimental-zicfiss,-experimental-zvbc32e,-experimental-zvkgs,-h,-relax,-sha,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smcdeleg,-smcsrind,-smdbltrp,-smepmp,-smmpm,-smnpm,-smrnmi,-smstateen,-ssaia,-ssccfg,-ssccptr,-sscofpmf,-sscounterenw,-sscsrind,-ssdbltrp,-ssnpm,-sspm,-ssqosid,-ssstateen,-ssstrict,-sstc,-sstvala,-sstvecd,-ssu64xl,-supm,-svade,-svadu,-svbare,-svinval,-svnapot,-svpbmt,-svvptc,-v,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xesppie,-xmipscmove,-xmipslsp,-xsfcease,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xsifivecdiscarddlone,-xsifivecflushdlone,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-xwchc,-za128rs,-za64rs,-zabha,-zacas,-zama16b,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmop,-zcmp,-zcmt,-zdinx,-zfa,-zfbfmin,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zihintntl,-zihintpause,-zihpm,-zimop,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-ztso,-zvbb,-zvbc,-zve32f,-zve32x,-zve64d,-zve64f,-zve64x,-zvfbfmin,-zvfbfwma,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl128b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl32b,-zvl4096b,-zvl512b,-zvl64b,-zvl65536b,-zvl8192b\",\n\t\"build-tags\": [\"k210\", \"kendryte\"],\n\t\"code-model\": \"medium\"\n}\n"
  },
  {
    "path": "targets/kb2040.json",
    "content": "{\n    \"inherits\": [\n        \"rp2040\"\n    ],\n    \"serial-port\": [\"239a:8106\"],\n    \"build-tags\": [\"kb2040\"],\n    \"ldflags\": [\n        \"--defsym=__flash_size=8192K\"\n    ],\n    \"extra-files\": [\n        \"targets/qtpy-rp2040-boot-stage2.S\"\n    ]\n}\n"
  },
  {
    "path": "targets/lgt92.json",
    "content": "{\n\t\"inherits\": [\n\t\t\"stm32l0x2\"\n\t],\n\t\"build-tags\": [\n\t\t\"lgt92\"\n\t],\n\t\"serial\": \"uart\",\n\t\"linkerscript\": \"targets/stm32l072czt6.ld\",\n\t\"flash-method\": \"openocd\",\n\t\"openocd-interface\": \"stlink\",\n\t\"openocd-target\": \"stm32l0\"\n}\n"
  },
  {
    "path": "targets/lm3s6965.ld",
    "content": "\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x00000000, LENGTH = 256K\n    RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 64K\n}\n\n_stack_size = 4K;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/lorae5.json",
    "content": "{\n\t\"inherits\": [\n\t\t\"stm32wle5\"\n\t],\n\t\"build-tags\": [\n\t\t\"lorae5\"\n\t],\n\t\"serial\": \"uart\",\n\t\"flash-method\": \"openocd\",\n\t\"openocd-interface\": \"stlink-v2\",\n\t\"openocd-target\": \"stm32wlx\"\n}"
  },
  {
    "path": "targets/m5paper.json",
    "content": "{\n\t\"inherits\": [\"esp32\"],\n\t\"build-tags\": [\"m5paper\"],\n\t\"serial-port\": [\"1a86:55d4\"]\n}\n"
  },
  {
    "path": "targets/m5stack-core2.json",
    "content": "{\n\t\"inherits\": [\"esp32\"],\n\t\"build-tags\": [\"m5stack_core2\"],\n\t\"serial-port\": [\"10c4:ea60\"]\n}\n"
  },
  {
    "path": "targets/m5stack.json",
    "content": "{\n\t\"inherits\": [\"esp32\"],\n\t\"build-tags\": [\"m5stack\"],\n\t\"serial-port\": [\"10c4:ea60\"]\n}\n"
  },
  {
    "path": "targets/m5stamp-c3.json",
    "content": "{\n\t\"inherits\": [\"esp32c3\"],\n\t\"build-tags\": [\"m5stamp_c3\"],\n\t\"serial\": \"uart\",\n\t\"serial-port\": [\"1a86:55d4\"]\n}\n\n"
  },
  {
    "path": "targets/m5stick-c.json",
    "content": "{\n\t\"inherits\": [\"esp32\"],\n\t\"build-tags\": [\"m5stick_c\"],\n\t\"serial-port\": [\"0403:6001\"]\n}\n"
  },
  {
    "path": "targets/macropad-rp2040-boot-stage2.S",
    "content": "// Adafruit MacroPad RP2040 Stage 2 Bootloader\n\n//\n// This file defines the parameters specific to the flash-chip found\n// on the Adafruit MacroPad RP2040.  The generic implementation is in\n// rp2040-boot-stage2.S\n//\n\n#define BOARD_PICO_FLASH_SPI_CLKDIV   4\n#define BOARD_CMD_READ                0xeb\n#define BOARD_QUAD_OK                 1\n#define BOARD_QUAD_ENABLE_STATUS_BYTE 2\n#define BOARD_QUAD_ENABLE_BIT_MASK    2\n#define BOARD_SPLIT_STATUS_WRITE      0\n#define BOARD_WAIT_CYCLES             4\n\n#include \"rp2040-boot-stage2.S\"\n"
  },
  {
    "path": "targets/macropad-rp2040.json",
    "content": "{\n    \"inherits\": [\n        \"rp2040\"\n    ],\n    \"build-tags\": [\"macropad_rp2040\"],\n    \"default-stack-size\": 8192,\n    \"serial-port\": [\"239a:8107\"],\n    \"ldflags\": [\n        \"--defsym=__flash_size=8M\"\n    ],\n    \"extra-files\": [\n        \"targets/macropad-rp2040-boot-stage2.S\"\n    ]\n}\n"
  },
  {
    "path": "targets/maixbit.json",
    "content": "{\n\t\"inherits\": [\"k210\"],\n\t\"build-tags\": [\"maixbit\"],\n\t\"serial\": \"uart\",\n\t\"linkerscript\": \"targets/maixbit.ld\",\n\t\"flash-command\": \"kflash -p {port} --noansi --verbose {bin}\"\n}\n"
  },
  {
    "path": "targets/maixbit.ld",
    "content": "\nMEMORY\n{\n    RAM (xrw) : ORIGIN = 0x80000000, LENGTH = 6M\n}\n\n_stack_size = 2K;\n\nSECTIONS\n{\n    .text :\n    {\n        . = ALIGN(16);\n        KEEP(*(.init))\n        . = ALIGN(16);\n        *(.text.handleInterruptASM)\n        *(.text)\n        *(.text.*)\n        *(.rodata)\n        *(.rodata.*)\n        . = ALIGN(16);\n    } >RAM\n\n\n    /* Start address (in flash) of .data, used by startup code. */\n    _sidata = LOADADDR(.data);\n\n    /* Globals with initial value */\n    .data :\n    {\n        . = ALIGN(16);\n        /* see https://gnu-mcu-eclipse.github.io/arch/riscv/programmer/#the-gp-global-pointer-register */\n        PROVIDE( __global_pointer$ = . + (4K / 2) );\n        _sdata = .;        /* used by startup code */\n        *(.sdata)\n        *(.data .data.*)\n        . = ALIGN(16);\n        _edata = .;        /* used by startup code */\n    } >RAM\n\n    /* Zero-initialized globals  */\n    .bss :\n    {\n        . = ALIGN(16);\n        _sbss = .;         /* used by startup code */\n        *(.sbss)\n        *(.bss .bss.*)\n        *(COMMON)\n        . = ALIGN(16);\n        _ebss = .;         /* used by startup code */\n    } >RAM\n\n    /DISCARD/ :\n    {\n        *(.eh_frame)       /* causes 'no memory region specified' error in lld */\n    }\n}\n\nPROVIDE(_stack_top = ORIGIN(RAM) + LENGTH(RAM));\n\n/* For the memory allocator. */\n_heap_start = _ebss;\n_heap_end = ORIGIN(RAM) + LENGTH(RAM) - _stack_size;\n_globals_start = _sdata;\n_globals_end = _ebss;\n"
  },
  {
    "path": "targets/makerfabs-esp32c3spi35.json",
    "content": "{\n\t\"inherits\": [\"esp32c3\"],\n\t\"build-tags\": [\"makerfabs_esp32c3spi35\"]\n}\n"
  },
  {
    "path": "targets/matrixportal-m4.json",
    "content": "{\n    \"inherits\": [\"atsamd51j19a\"],\n    \"build-tags\": [\"matrixportal_m4\", \"ninafw\"],\n    \"serial\": \"usb\",\n    \"serial-port\": [\"239a:80c9\", \"239a:80ca\"],\n    \"flash-1200-bps-reset\": \"true\",\n    \"flash-method\": \"msd\",\n    \"msd-volume-name\": [\"MATRIXBOOT\"],\n    \"msd-firmware-name\": \"firmware.uf2\",\n    \"openocd-transport\": \"swd\",\n    \"openocd-interface\": \"jlink\",\n    \"openocd-target\": \"atsame5x\"\n}\n"
  },
  {
    "path": "targets/mch2022.json",
    "content": "{\n\t\"inherits\": [\"esp32\"],\n\t\"build-tags\": [\"mch2022\"]\n}\n"
  },
  {
    "path": "targets/mdbt50qrx-uf2.json",
    "content": "{\n    \"inherits\": [\"nrf52840\", \"nrf52840-s140v6-uf2\"],\n    \"build-tags\": [\"mdbt50qrx\"],\n    \"serial-port\": [\"239a:810b\", \"239a:810c\"],\n    \"msd-volume-name\": [\"MDBT50QBOOT\"]\n}\n"
  },
  {
    "path": "targets/metro-m4-airlift.json",
    "content": "{\n    \"inherits\": [\"atsamd51j19a\"],\n    \"build-tags\": [\"metro_m4_airlift\", \"ninafw\"],\n    \"serial\": \"usb\",\n    \"serial-port\": [\"239A:8037\"],\n    \"flash-1200-bps-reset\": \"true\",\n    \"flash-method\": \"msd\",\n    \"msd-volume-name\": [\"METROM4BOOT\"],\n    \"msd-firmware-name\": \"firmware.uf2\"\n}\n"
  },
  {
    "path": "targets/metro-rp2350.json",
    "content": "{\n    \"inherits\": [\n        \"rp2350b\"\n    ],\n    \"build-tags\": [\"metro_rp2350\"],\n    \"serial-port\": [\"239a:814e\"],\n    \"default-stack-size\": 8192,\n    \"ldflags\": [\n        \"--defsym=__flash_size=16M\"\n    ]\n}\n"
  },
  {
    "path": "targets/microbit-s110v8.json",
    "content": "{\n\t\"inherits\": [\"microbit\", \"nrf51-s110v8\"],\n\t\"flash-method\": \"openocd\"\n}\n"
  },
  {
    "path": "targets/microbit-v2-s113v7.json",
    "content": "{\n\t\"inherits\": [\"microbit-v2\", \"nrf52833-s113v7\"],\n\t\"flash-method\": \"openocd\"\n}\n"
  },
  {
    "path": "targets/microbit-v2-s140v7.json",
    "content": "{\n\t\"inherits\": [\"microbit-v2\", \"nrf52833-s140v7\"],\n\t\"flash-method\": \"openocd\"\n}\n"
  },
  {
    "path": "targets/microbit-v2.json",
    "content": "{\n\t\"inherits\": [\"nrf52833\"],\n\t\"build-tags\": [\"microbit_v2\"],\n\t\"serial\": \"uart\",\n\t\"flash-method\": \"msd\",\n\t\"openocd-interface\": \"cmsis-dap\",\n\t\"msd-volume-name\": [\"MICROBIT\"],\n\t\"msd-firmware-name\": \"firmware.hex\"\n}\n"
  },
  {
    "path": "targets/microbit.json",
    "content": "{\n\t\"inherits\": [\"nrf51\"],\n\t\"build-tags\": [\"microbit\"],\n\t\"serial\": \"uart\",\n\t\"flash-method\": \"msd\",\n\t\"openocd-interface\": \"cmsis-dap\",\n\t\"msd-volume-name\": [\"MICROBIT\"],\n\t\"msd-firmware-name\": \"firmware.hex\"\n}\n"
  },
  {
    "path": "targets/mimxrt1062-teensy40.ld",
    "content": "MEMORY\n{\n  ITCM      (rwx): ORIGIN = 0x00000000, LENGTH = 0x00080000 /*  512 Kib */\n  DTCM      (rwx): ORIGIN = 0x20000000, LENGTH = 0x00080000 /*  512 Kib */\n  RAM       (rwx): ORIGIN = 0x20200000, LENGTH = 0x00080000 /*  512 Kib */\n  FLASH      (rx): ORIGIN = 0x60000000, LENGTH = 0x001FFFF0 /* 1984 Kib */\n}\n\nENTRY(Reset_Handler);\n\n_stack_size = 4K;\n\nSECTIONS\n{\n  .text : ALIGN(8) {\n\n    FILL(0xFFFFFFFF);\n\n    /* place flash config at beginning of flash device */\n    KEEP(*(.flash_config));\n\n    /* IVT must be located at +4 Kbyte offset from base address of flash. */\n    . = ORIGIN(FLASH) + 0x1000;\n    KEEP(*(.ivt));\n\n    . = ORIGIN(FLASH) + 0x1020;\n    KEEP(*(.boot_data));\n\n    . = ORIGIN(FLASH) + 0x2000;\n\n    _svectors = ABSOLUTE(.);\n    KEEP(*(.isr_vector));\n    . = ALIGN(8);\n\n    *(.text.Reset_Handler);\n    . = ALIGN(8);\n\n    _stext = .;\n    *(.text*);\n    *(.rodata* .constdata*);\n    . = ALIGN(8);\n    _etext = .;\n\n  } > FLASH\n\n  .tinygo_stacksizes : ALIGN(8) {\n\n    *(.tinygo_stacksizes);\n    . = ALIGN(8);\n\n  } > FLASH\n\n  .text.padding (NOLOAD) : {\n\n    . = ALIGN(32768);\n\n  } > ITCM\n\n  .stack (NOLOAD) : {\n\n    . = ALIGN(8);\n    . += _stack_size;\n    _stack_top = .;\n\n  } > DTCM\n\n  .data : ALIGN(8) {\n\n    FILL(0xFFFFFFFF);\n\n    _sdata = .;\n    *(.data*);\n    . = ALIGN(8);\n    _edata = .;\n\n  } > DTCM AT > FLASH\n\n  .bss : ALIGN(8) {\n\n    _sbss = .;\n    *(.bss*);\n    *(COMMON);\n    . = ALIGN(8);\n    _ebss = .;\n\n  } > DTCM AT > DTCM\n\n  /DISCARD/ : {\n\n    *(.ARM.exidx*); /* causes spurious 'undefined reference' errors */\n\n  }\n\n  _sidata = LOADADDR(.data);\n\n  _heap_start = ORIGIN(RAM);\n  _heap_end = ORIGIN(RAM) + LENGTH(RAM);\n\n  _globals_start = _sdata;\n  _globals_end = _ebss;\n\n  _image_size = SIZEOF(.text) + SIZEOF(.tinygo_stacksizes) + SIZEOF(.data);\n\n  /* TODO: link .text to ITCM */\n  _itcm_blocks = (0 + 0x7FFF) >> 15;\n  _flexram_cfg = 0xAAAAAAAA | ((1 << (_itcm_blocks * 2)) - 1);\n}\n"
  },
  {
    "path": "targets/mksnanov3.json",
    "content": "{\n  \"inherits\": [\"cortex-m4\"],\n  \"build-tags\": [\"mksnanov3\", \"stm32f407\", \"stm32f4\", \"stm32\"],\n  \"serial\": \"uart\",\n  \"linkerscript\": \"targets/stm32f407.ld\",\n  \"extra-files\": [\n    \"src/device/stm32/stm32f407.s\"\n  ],\n  \"flash-method\": \"openocd\",\n  \"openocd-interface\": \"stlink\",\n  \"openocd-target\": \"stm32f4x\",\n  \"openocd-commands\": [\"stm32f4x.cpu configure -event reset-init { adapter speed 1800 }\"]\n}\n"
  },
  {
    "path": "targets/nano-33-ble-s140v6-uf2.json",
    "content": "{\n\t\"inherits\": [\"nrf52840\", \"nrf52840-s140v6-uf2\"],\n\t\"build-tags\": [\"nano_33_ble\"],\n\t\"serial-port\": [\"239a:8063\", \"239a:0063\"],\n\t\"msd-volume-name\": [\"NANO33BOOT\"]\n}\n"
  },
  {
    "path": "targets/nano-33-ble-s140v7-uf2.json",
    "content": "{\n\t\"inherits\": [\"nrf52840\", \"nrf52840-s140v7-uf2\"],\n\t\"build-tags\": [\"nano_33_ble\"],\n\t\"serial-port\": [\"239a:8063\", \"239a:0063\"],\n\t\"msd-volume-name\": [\"NANO33BOOT\"]\n}\n"
  },
  {
    "path": "targets/nano-33-ble-s140v7.json",
    "content": "{\n\t\"inherits\": [\"nano-33-ble\", \"nrf52840-s140v7\"],\n\t\"flash-command\": \"nrfjprog -f nrf52 --sectorerase --program {hex} --reset\",\n\t\"flash-1200-bps-reset\": \"false\",\n\t\"openocd-interface\": \"jlink\"\n}\n"
  },
  {
    "path": "targets/nano-33-ble.json",
    "content": "{\n\t\"inherits\": [\"nrf52840\"],\n\t\"build-tags\": [\"nano_33_ble\", \"nrf52840_reset_bossa\"],\n\t\"flash-command\": \"bossac_arduino2 -d -i -e -w -v -R --port={port} {bin}\",\n\t\"serial-port\": [\"2341:805a\", \"2341:005a\"],\n\t\"serial\": \"usb\",\n\t\"flash-1200-bps-reset\": \"true\",\n\t\"linkerscript\": \"targets/nano-33-ble.ld\"\n}\n"
  },
  {
    "path": "targets/nano-33-ble.ld",
    "content": "\n/*\n  See also \n  https://github.com/arduino/ArduinoCore-mbed/blob/master/variants/ARDUINO_NANO33BLE/linker_script.ld\n*/\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x10000, LENGTH = 0xf0000\n    RAM (rwx)       : ORIGIN = 0x20000000, LENGTH = 0x40000\n}\n\n_stack_size = 4K;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/nano-rp2040.json",
    "content": "{\n    \"inherits\": [\n        \"rp2040\"\n    ],\n    \"serial-port\": [\"2341:005e\"],\n    \"default-stack-size\": 8192,\n    \"build-tags\": [\"nano_rp2040\", \"ninafw\", \"ninafw_machine_init\"],\n    \"ldflags\": [\n        \"--defsym=__flash_size=16M\"\n    ],\n    \"extra-files\": [\n        \"targets/pico-boot-stage2.S\"\n    ]\n}\n"
  },
  {
    "path": "targets/nicenano.json",
    "content": "{\n    \"inherits\": [\"nrf52840\", \"nrf52840-s140v6-uf2\"],\n    \"build-tags\": [\"nicenano\"],\n    \"msd-volume-name\": [\"NICENANO\"]\n}\n"
  },
  {
    "path": "targets/nintendoswitch.json",
    "content": "{\n  \"llvm-target\": \"aarch64\",\n  \"cpu\": \"cortex-a57\",\n  \"features\": \"+aes,+crc,+fp-armv8,+neon,+perfmon,+sha2,+v8a,-fmv\",\n  \"build-tags\": [\"nintendoswitch\", \"arm64\"],\n  \"scheduler\": \"tasks\",\n  \"goos\": \"linux\",\n  \"goarch\": \"arm64\",\n  \"linker\": \"ld.lld\",\n  \"rtlib\": \"compiler-rt\",\n  \"libc\": \"picolibc\",\n  \"gc\": \"conservative\",\n  \"relocation-model\": \"pic\",\n  \"default-stack-size\": 2048,\n  \"cflags\": [\n    \"-target\", \"aarch64-unknown-none\",\n    \"-fPIE\",\n    \"-Werror\",\n    \"-fshort-enums\",\n    \"-fomit-frame-pointer\",\n    \"-fno-exceptions\", \"-fno-unwind-tables\", \"-fno-asynchronous-unwind-tables\",\n    \"-ffunction-sections\", \"-fdata-sections\"\n  ],\n  \"ldflags\": [\n    \"-pie\",\n    \"-z\", \"notext\"\n  ],\n  \"linkerscript\": \"targets/nintendoswitch.ld\",\n  \"extra-files\": [\n    \"targets/nintendoswitch.s\",\n    \"src/internal/task/task_stack_arm64.S\",\n    \"src/runtime/asm_arm64.S\",\n    \"src/runtime/runtime_nintendoswitch.S\"\n  ]\n}\n"
  },
  {
    "path": "targets/nintendoswitch.ld",
    "content": "PHDRS\n{\n  text    PT_LOAD FLAGS(5) /* Read | Execute */;\n  rodata  PT_LOAD FLAGS(4) /* Read */;\n  data    PT_LOAD FLAGS(6) /* Read | Write */;\n  bss     PT_LOAD FLAGS(6) /* Read | Write */;\n  dynamic PT_DYNAMIC;\n}\n\nSECTIONS\n{\n  /* Code and file header */\n  . = 0;\n\n  .text : ALIGN(0x1000) {\n    HIDDEN(__text_start = .);\n    KEEP(*(.text.jmp))\n\n    . = 0x80;\n    KEEP(*(.text.start))\n\n    *(.text .text.*)\n    *(.plt .plt.*)\n\n    HIDDEN(__text_end = .);\n    HIDDEN(__text_size = . - __text_start);\n  }\n\n  /* Read-only sections */\n  . = ALIGN(0x1000);\n\n  HIDDEN(__rodata_start = .);\n  .rodata : { *(.rodata .rodata.*) }  :rodata\n\n  .mod0 : {\n    KEEP(crt0.nso.o(.data.mod0))\n    KEEP(crt0.nro.o(.data.mod0))\n    KEEP(crt0.lib.nro.o(.data.mod0))\n  }\n\n  .dynsym            : { *(.dynsym) } :rodata\n  .dynstr            : { *(.dynstr) } :rodata\n  .rela.dyn          : { *(.rela.*) } :rodata\n\n  HIDDEN(__rodata_end = .);\n  HIDDEN(__rodata_size = . - __rodata_start);\n\n  /* Read-write sections */\n  . = ALIGN(0x1000);\n\n  .data : {\n    HIDDEN(__data_start = .);\n\n    *(.data .data.*)\n    *(.got .got.*)\n    *(.got.plt .got.plt.*)\n\n    HIDDEN(__data_end = .);\n    HIDDEN(__data_size = . - __data_start);\n  } :data\n\n  .dynamic : {\n    HIDDEN(__dynamic_start = .);\n    *(.dynamic)\n  }\n\n  /* BSS section */\n  . = ALIGN(0x1000);\n  .bss : {\n    HIDDEN(__bss_start = .);\n\n    *(.bss .bss.*)\n    *(COMMON)\n    . = ALIGN(8);\n\n    HIDDEN(__bss_end = .);\n    HIDDEN(__bss_size = . - __bss_start);\n  } : bss\n\n  /DISCARD/ :\n  {\n    *(.eh_frame) /* This is probably unnecessary and bloats the binary. */\n    *(.eh_frame_hdr)\n  }\n}\n"
  },
  {
    "path": "targets/nintendoswitch.s",
    "content": "// For more information on the .nro file format, see:\n// https://switchbrew.org/wiki/NRO\n\n.section .text.jmp, \"x\"\n.global _start\n_start:\n    b start\n    .word _mod_header - _start\n    .ascii \"HOMEBREW\"\n\n    .ascii \"NRO0\"              // magic\n    .word 0                    // version (always 0)\n    .word __bss_start - _start // total NRO file size\n    .word 0                    // flags (unused)\n\n    // segment headers\n    .word __text_start - _start\n    .word __text_size\n    .word __rodata_start - _start\n    .word __rodata_size\n    .word __data_start - _start\n    .word __data_size\n    .word __bss_size\n    .word 0\n\n    // ModuleId (not supported)\n    . = 0x50; // skip 32 bytes\n\n    .word 0 // DSO Module Offset (unused)\n    .word 0 // reserved (unused)\n\n.section .data.mod0\n    .word 0, 8\n\n.global _mod_header\n_mod_header:\n    .ascii \"MOD0\"\n    .word __dynamic_start - _mod_header\n    .word __bss_start - _mod_header\n    .word __bss_end - _mod_header\n    .word 0, 0 // eh_frame_hdr start/end\n    .word 0 // runtime-generated module object offset\n\n.section .text.start, \"x\"\n.global start\nstart:\n    // save lr\n    mov  x7, x30\n\n    // get aslr base\n    bl   +4\n    sub  x6, x30, #0x88\n\n    // context ptr and main thread handle\n    mov  x25, x0\n    mov  x26, x1\n\n    // Save ASLR Base to use later\n    mov x0, x6\n\n    adrp x4, _saved_return_address\n    str  x7, [x4, #:lo12:_saved_return_address]\n\n    adrp x4, _context\n    str x25, [x4, #:lo12:_context]\n\n    adrp x4, _main_thread\n    str x26, [x4, #:lo12:_main_thread]\n\n    // store stack pointer\n    mov  x26, sp\n    adrp x4, _stack_top\n    str  x26, [x4, #:lo12:_stack_top]\n\n    // clear .bss\n    adrp x5, __bss_start\n    add x5, x5, #:lo12:__bss_start\n    adrp x6, __bss_end\n    add x6, x6, #:lo12:__bss_end\n\nbssloop:\n    cmp x5, x6\n    b.eq run\n    str xzr, [x5]\n    add x5, x5, 8\n    b bssloop\n\nrun:\n    // process .dynamic section\n    // ASLR base on x0\n    adrp x1, _DYNAMIC\n    add  x1, x1, #:lo12:_DYNAMIC\n    bl   __dynamic_loader\n\n    // call entrypoint\n    b    main\n\n.global __nx_exit\n.type   __nx_exit, %function\n__nx_exit:\n    // Exit code in x0\n\n    // restore stack pointer\n    mov sp, x1\n\n    // jump back to loader\n    br   x2\n\n.section .data.horizon\n.align 8\n.global _saved_return_address // Saved return address.\n                              // This might be different than null when coming from launcher\n_saved_return_address:\n    .dword 0\n.global _context // Homebrew Launcher Context\n                 // This might be different than null when not coming from launcher\n_context:\n    .dword 0\n\n.global _main_thread\n_main_thread:\n    .dword 0\n\n.global _stack_top\n_stack_top:\n    .dword 0\n"
  },
  {
    "path": "targets/nodemcu.json",
    "content": "{\n\t\"inherits\": [\"esp8266\"],\n\t\"build-tags\": [\"nodemcu\"],\n\t\"serial\": \"uart\"\n}\n"
  },
  {
    "path": "targets/nrf51-s110v8.json",
    "content": "{\n\t\"build-tags\": [\"softdevice\", \"s110v8\"],\n\t\"linkerscript\": \"targets/nrf51-s110v8.ld\"\n}\n"
  },
  {
    "path": "targets/nrf51-s110v8.ld",
    "content": "\nMEMORY\n{\n    /* This SoftDevice requires 96K flash and 8K RAM according to the release\n     * notes of version 8.0.0 */\n    FLASH_TEXT (rw) : ORIGIN = 0x00000000 + 96K, LENGTH = 256K - 96K\n    RAM (xrw)       : ORIGIN = 0x20000000 + 8K,  LENGTH = 16K  - 8K\n}\n\n_stack_size = 2K;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/nrf51.json",
    "content": "{\n\t\"inherits\": [\"cortex-m0\"],\n\t\"build-tags\": [\"nrf51822\", \"nrf51\", \"nrf\"],\n\t\"cflags\": [\n\t\t\"-DNRF51\",\n\t\t\"-I{root}/lib/CMSIS/CMSIS/Include\",\n\t\t\"-I{root}/lib/nrfx/mdk\"\n\t],\n\t\"linkerscript\": \"targets/nrf51.ld\",\n\t\"extra-files\": [\n\t\t\"lib/nrfx/mdk/system_nrf51.c\",\n\t\t\"src/device/nrf/nrf51.s\"\n\t],\n\t\"openocd-transport\": \"swd\",\n\t\"openocd-target\": \"nrf51\"\n}\n"
  },
  {
    "path": "targets/nrf51.ld",
    "content": "\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x00000000, LENGTH = 256K /* .text */\n    RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 16K\n}\n\n_stack_size = 2K;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/nrf52-s132v6.json",
    "content": "{\n\t\"build-tags\": [\"softdevice\", \"s132v6\"],\n\t\"linkerscript\": \"targets/nrf52-s132v6.ld\"\n}\n"
  },
  {
    "path": "targets/nrf52-s132v6.ld",
    "content": "\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x00000000 + 0x00026000 , LENGTH = 512K - 0x00026000 /* .text */\n    RAM (xrw)       : ORIGIN = 0x20000000 + 0x000039c0,  LENGTH = 64K  - 0x000039c0\n}\n\n_stack_size = 4K;\n\n/* This value is needed by the Nordic SoftDevice. */\n__app_ram_base = ORIGIN(RAM);\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/nrf52.json",
    "content": "{\n\t\"inherits\": [\"cortex-m4\"],\n\t\"build-tags\": [\"nrf52\", \"nrf\"],\n\t\"cflags\": [\n\t\t\"-DNRF52832_XXAA\",\n\t\t\"-I{root}/lib/CMSIS/CMSIS/Include\",\n\t\t\"-I{root}/lib/nrfx/mdk\"\n\t],\n\t\"linkerscript\": \"targets/nrf52.ld\",\n\t\"extra-files\": [\n\t\t\"lib/nrfx/mdk/system_nrf52.c\",\n\t\t\"src/device/nrf/nrf52.s\"\n\t],\n\t\"openocd-transport\": \"swd\",\n\t\"openocd-target\": \"nrf51\"\n}\n"
  },
  {
    "path": "targets/nrf52.ld",
    "content": "\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x00000000, LENGTH = 512K /* .text */\n    RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 64K\n}\n\n_stack_size = 2K;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/nrf52833-s113v7.json",
    "content": "{\n\t\"build-tags\": [\"softdevice\", \"s113v7\"],\n\t\"linkerscript\": \"targets/nrf52833-s113v7.ld\",\n\t\"ldflags\": [\n\t\t\"--defsym=__softdevice_stack=0x700\"\n\t]\n}\n"
  },
  {
    "path": "targets/nrf52833-s113v7.ld",
    "content": "\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x00000000 + 0x1C000, LENGTH = 0x80000 - 0x1C000\n    RAM (xrw)       : ORIGIN = 0x20000000 + 0x1e20,  LENGTH = 0x20000 - 0x1e20\n}\n\n_stack_size = 4K + __softdevice_stack;\n\n/* These values are needed for the Nordic SoftDevice. */\n__app_ram_base = ORIGIN(RAM);\n__softdevice_stack = DEFINED(__softdevice_stack) ? __softdevice_stack : 0;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/nrf52833-s140v7.json",
    "content": "{\n\t\"build-tags\": [\"softdevice\", \"s140v7\"],\n\t\"linkerscript\": \"targets/nrf52833-s140v7.ld\",\n\t\"ldflags\": [\n\t\t\"--defsym=__softdevice_stack=0x700\"\n\t]\n}\n"
  },
  {
    "path": "targets/nrf52833-s140v7.ld",
    "content": "\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x00000000 + 0x00027000, LENGTH = 0x80000 - 0x00027000\n    RAM (xrw)       : ORIGIN = 0x20000000 + 0x000039c0,  LENGTH = 0x20000 - 0x000039c0\n}\n\n_stack_size = 4K + __softdevice_stack;\n\n/* These values are needed for the Nordic SoftDevice. */\n__app_ram_base = ORIGIN(RAM);\n__softdevice_stack = DEFINED(__softdevice_stack) ? __softdevice_stack : 0;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/nrf52833.json",
    "content": "{\n\t\"inherits\": [\"cortex-m4\"],\n\t\"build-tags\": [\"nrf52833\", \"nrf\"],\n\t\"cflags\": [\n\t\t\"-DNRF52833_XXAA\",\n\t\t\"-I{root}/lib/CMSIS/CMSIS/Include\",\n\t\t\"-I{root}/lib/nrfx/mdk\"\n\t],\n\t\"linkerscript\": \"targets/nrf52833.ld\",\n\t\"extra-files\": [\n\t\t\"lib/nrfx/mdk/system_nrf52833.c\",\n\t\t\"src/device/nrf/nrf52833.s\"\n\t],\n\t\"openocd-transport\": \"swd\",\n\t\"openocd-target\": \"nrf52\"\n}\n"
  },
  {
    "path": "targets/nrf52833.ld",
    "content": "\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x00000000, LENGTH = 0x80000\n    RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 0x20000\n}\n\n_stack_size = 4K;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/nrf52840-mdk-usb-dongle.json",
    "content": "{\n    \"inherits\": [\"nrf52840\", \"nrf52840-s140v6-uf2\"],\n    \"build-tags\": [\"nrf52840_mdk_usb_dongle\"],\n    \"msd-volume-name\": [\"MDK-DONGLE\"]\n}\n"
  },
  {
    "path": "targets/nrf52840-mdk.json",
    "content": "{\n\t\"inherits\": [\"nrf52840\"],\n\t\"build-tags\": [\"nrf52840_mdk\"],\n\t\"serial\": \"usb\",\n\t\"flash-method\": \"openocd\",\n\t\"openocd-interface\": \"cmsis-dap\"\n}\n"
  },
  {
    "path": "targets/nrf52840-s140v6-uf2-generic.json",
    "content": "{\n  \"inherits\": [\"nrf52840\", \"nrf52840-s140v6-uf2\"],\n  \"build-tags\": [\"nrf52840_generic\"],\n  \"serial-port\": [\"1209:9090\"]\n}\n"
  },
  {
    "path": "targets/nrf52840-s140v6-uf2.json",
    "content": "{\n\t\"build-tags\": [\"nrf52840_reset_uf2\", \"softdevice\", \"s140v6\"],\n\t\"linkerscript\": \"targets/nrf52840-s140v6-uf2.ld\",\n\t\"serial\": \"usb\",\n\t\"flash-1200-bps-reset\": \"true\",\n\t\"flash-method\": \"msd\",\n\t\"msd-firmware-name\": \"firmware.uf2\",\n\t\"binary-format\": \"uf2\",\n\t\"uf2-family-id\": \"0xADA52840\"\n}\n"
  },
  {
    "path": "targets/nrf52840-s140v6-uf2.ld",
    "content": "\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x00000000+0x26000, LENGTH = 0xED000-0x26000 /* SoftDevice S140. See https://learn.adafruit.com/introducing-the-adafruit-nrf52840-feather/hathach-memory-map. Application starts at 0x26000; user data starts at 0xED000 */\n    RAM (xrw)       : ORIGIN = 0x20004180, LENGTH = 0x20040000-0x20004180\n}\n\n_stack_size = 2K;\n\n/* This value is needed by the Nordic SoftDevice. */\n__app_ram_base = ORIGIN(RAM);\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/nrf52840-s140v7-uf2.json",
    "content": "{\n\t\"inherits\": [\"nrf52840-s140v7\"],\n\t\"build-tags\": [\"nrf52840_reset_uf2\"],\n\t\"linkerscript\": \"targets/nrf52840-s140v7-uf2.ld\",\n\t\"serial\": \"usb\",\n\t\"flash-1200-bps-reset\": \"true\",\n\t\"flash-method\": \"msd\",\n\t\"msd-firmware-name\": \"firmware.uf2\",\n\t\"binary-format\": \"uf2\",\n\t\"uf2-family-id\": \"0xADA52840\"\n}\n"
  },
  {
    "path": "targets/nrf52840-s140v7-uf2.ld",
    "content": "/*\n  See also \n  https://github.com/Seeed-Studio/ArduinoCore-mbed/blob/master/variants/SEEED_XIAO_NRF52840_SENSE/linker_script.ld\n*/\nMEMORY\n{\n    FLASH_TEXT (rx) : ORIGIN = 0x27000, LENGTH = 0xED000 - 0x27000\n    RAM (rwx) : ORIGIN = 0x20006000, LENGTH = 0x3A000\n}\n\n_stack_size = 4K + __softdevice_stack;\n\n/* This value is needed by the Nordic SoftDevice. */\n__app_ram_base = ORIGIN(RAM);\n__softdevice_stack = DEFINED(__softdevice_stack) ? __softdevice_stack : 0;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/nrf52840-s140v7.json",
    "content": "{\n\t\"build-tags\": [\"softdevice\", \"s140v7\"],\n\t\"linkerscript\": \"targets/nrf52840-s140v7.ld\",\n\t\"ldflags\": [\n\t\t\"--defsym=__softdevice_stack=0x700\"\n\t]\n}\n"
  },
  {
    "path": "targets/nrf52840-s140v7.ld",
    "content": "\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x00000000 + 0x00027000, LENGTH = 1M - 0x00027000\n    RAM (xrw)       : ORIGIN = 0x20000000 + 0x000039c0, LENGTH = 256K - 0x000039c0\n}\n\n_stack_size = 4K + __softdevice_stack;\n\n/* This value is needed by the Nordic SoftDevice. */\n__app_ram_base = ORIGIN(RAM);\n__softdevice_stack = DEFINED(__softdevice_stack) ? __softdevice_stack : 0;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/nrf52840.json",
    "content": "{\n\t\"inherits\": [\"cortex-m4\"],\n\t\"build-tags\": [\"nrf52840\", \"nrf\"],\n\t\"cflags\": [\n\t\t\"-DNRF52840_XXAA\",\n\t\t\"-I{root}/lib/CMSIS/CMSIS/Include\",\n\t\t\"-I{root}/lib/nrfx/mdk\"\n\t],\n\t\"linkerscript\": \"targets/nrf52840.ld\",\n\t\"extra-files\": [\n\t\t\"lib/nrfx/mdk/system_nrf52840.c\",\n\t\t\"src/device/nrf/nrf52840.s\"\n\t],\n\t\"openocd-transport\": \"swd\",\n\t\"openocd-target\": \"nrf51\"\n}\n"
  },
  {
    "path": "targets/nrf52840.ld",
    "content": "\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x00000000, LENGTH = 1M\n    RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 256K\n}\n\n_stack_size = 4K;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/nucleo-f103rb.json",
    "content": "{\n  \"inherits\": [\"cortex-m3\"],\n  \"build-tags\": [\"nucleof103rb\", \"stm32f103\", \"stm32f1\",\"stm32\"],\n  \"serial\": \"uart\",\n  \"linkerscript\": \"targets/stm32f103rb.ld\",\n  \"extra-files\": [\n    \"src/device/stm32/stm32f103.s\"\n  ],\n  \"flash-method\": \"openocd\",\n  \"openocd-interface\": \"stlink-v2-1\",\n  \"openocd-target\": \"stm32f1x\"\n}\n"
  },
  {
    "path": "targets/nucleo-f722ze.json",
    "content": "{\n  \"inherits\": [\"cortex-m7\"],\n  \"build-tags\": [\"nucleof722ze\", \"stm32f7x2\", \"stm32f7\", \"stm32\"],\n  \"serial\": \"uart\",\n  \"linkerscript\": \"targets/stm32f7x2zetx.ld\",\n  \"extra-files\": [\n    \"src/device/stm32/stm32f7x2.s\"\n  ],\n  \"flash-method\": \"openocd\",\n  \"openocd-interface\": \"stlink-v2-1\",\n  \"openocd-target\": \"stm32f7x\"\n}\n"
  },
  {
    "path": "targets/nucleo-l031k6.json",
    "content": "{\n    \"inherits\": [\"cortex-m0\"],\n    \"build-tags\": [\"nucleol031k6\", \"stm32l031\", \"stm32l0x1\", \"stm32l0\", \"stm32\"],\n    \"serial\": \"uart\",\n    \"linkerscript\": \"targets/stm32l031k6.ld\",\n    \"extra-files\": [\n        \"src/device/stm32/stm32l0x1.s\"\n    ],\n    \"flash-method\": \"openocd\",\n    \"openocd-interface\": \"stlink\",\n    \"openocd-target\": \"stm32l0\"\n}"
  },
  {
    "path": "targets/nucleo-l432kc.json",
    "content": "{\n    \"inherits\": [\"cortex-m4\"],\n    \"build-tags\": [\"nucleol432kc\", \"stm32l432\", \"stm32l4x2\", \"stm32l4\", \"stm32\"],\n    \"serial\": \"uart\",\n    \"linkerscript\": \"targets/stm32l4x2.ld\",\n    \"extra-files\": [\n      \"src/device/stm32/stm32l4x2.s\"\n    ],\n    \"flash-method\": \"openocd\",\n    \"openocd-interface\": \"stlink-v2-1\",\n    \"openocd-target\": \"stm32l4x\"\n  }"
  },
  {
    "path": "targets/nucleo-l476rg.json",
    "content": "{\n    \"inherits\": [\"cortex-m4\"],\n    \"build-tags\": [\"nucleol476rg\", \"stm32l476\", \"stm32l4x6\", \"stm32l4\", \"stm32\"],\n    \"serial\": \"uart\",\n    \"linkerscript\": \"targets/stm32l4x6.ld\",\n    \"extra-files\": [\n      \"src/device/stm32/stm32l4x6.s\"\n    ],\n    \"flash-method\": \"openocd\",\n    \"openocd-interface\": \"stlink-v2-1\",\n    \"openocd-target\": \"stm32l4x\"\n  }\n"
  },
  {
    "path": "targets/nucleo-l552ze.json",
    "content": "{\n    \"inherits\": [\"cortex-m33\"],\n    \"build-tags\": [\"nucleol552ze\", \"stm32l552\", \"stm32l5x2\", \"stm32l5\", \"stm32\"],\n    \"serial\": \"uart\",\n    \"linkerscript\": \"targets/stm32l5x2xe.ld\",\n    \"extra-files\": [\n      \"src/device/stm32/stm32l552.s\"\n    ],\n    \"flash-method\": \"openocd\",\n    \"openocd-interface\": \"stlink\",\n    \"openocd-target\": \"stm32l5x\"\n  }"
  },
  {
    "path": "targets/nucleo-wl55jc.json",
    "content": "{\n\t\"inherits\": [\n\t\t\"stm32wl5x_cm4\"\n\t],\n\t\"build-tags\": [\n\t\t\"nucleowl55jc\"\n\t],\n\t\"serial\": \"uart\",\n\t\"flash-method\": \"openocd\",\n\t\"openocd-interface\": \"stlink\",\n\t\"openocd-target\": \"stm32wlx\"\n}\n"
  },
  {
    "path": "targets/nxpmk66f18.ld",
    "content": "\n/* Unused, but here to silence a linker warning. */\nENTRY(Reset_Handler)\n\n/* define memory layout */\nMEMORY\n{\n    FLASH_TEXT (rx) : ORIGIN = 0x00000000, LENGTH = 1024K\n    RAM (rwx)       : ORIGIN = 0x1FFF0000, LENGTH = 256K\n}\n\n_stack_size = 2K;\n\n/* define output sections */\nSECTIONS\n{\n    /* Program code and read-only data goes to FLASH_TEXT. */\n    .text :\n    {\n        /* vector table MUST start at 0x0 */\n        . = 0;\n        KEEP(*(.isr_vector))\n\n        /* flash configuration MUST be at 0x400 */\n        . = 0x400;\n        KEEP(*(.flash_config))\n\n        /* everything else */\n        *(.text)\n        *(.text.*)\n        *(.rodata)\n        *(.rodata.*)\n        . = ALIGN(4);\n\n    } >FLASH_TEXT = 0xFF\n}\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/p1am-100.json",
    "content": "{\n    \"inherits\": [\"atsamd21g18a\"],\n    \"build-tags\": [\"p1am_100\"],\n    \"flash-command\": \"bossac -d -i -e -w -v -R --port={port} --offset=0x2000 {bin}\",\n    \"flash-1200-bps-reset\": \"true\"\n}\n"
  },
  {
    "path": "targets/particle-3rd-gen.json",
    "content": "{\n\t\"inherits\": [\"nrf52840\"],\n\t\"build-tags\": [\"particle_3rd_gen\"],\n\t\"serial\": \"uart\",\n\t\"flash-method\": \"openocd\",\n\t\"openocd-interface\": \"cmsis-dap\"\n}\n"
  },
  {
    "path": "targets/particle-argon.json",
    "content": "{\n\t\"inherits\": [\"particle-3rd-gen\"],\n\t\"build-tags\": [\"particle_argon\"]\n}\n"
  },
  {
    "path": "targets/particle-boron.json",
    "content": "{\n\t\"inherits\": [\"particle-3rd-gen\"],\n\t\"build-tags\": [\"particle_boron\"]\n}\n"
  },
  {
    "path": "targets/particle-xenon.json",
    "content": "{\n\t\"inherits\": [\"particle-3rd-gen\"],\n\t\"build-tags\": [\"particle_xenon\"]\n}\n"
  },
  {
    "path": "targets/pca10031.json",
    "content": "{\n\t\"inherits\": [\"nrf51\"],\n\t\"build-tags\": [\"pca10031\"],\n\t\"serial\": \"uart\",\n\t\"flash-command\": \"nrfjprog -f nrf51 --sectorerase --program {hex} --reset\",\n\t\"openocd-interface\": \"cmsis-dap\"\n}\n"
  },
  {
    "path": "targets/pca10040-s132v6.json",
    "content": "{\n\t\"inherits\": [\"pca10040\", \"nrf52-s132v6\"]\n}\n"
  },
  {
    "path": "targets/pca10040.json",
    "content": "{\n\t\"inherits\": [\"nrf52\"],\n\t\"build-tags\": [\"pca10040\"],\n\t\"serial\": \"uart\",\n\t\"flash-method\": \"openocd\",\n\t\"flash-command\": \"nrfjprog -f nrf52 --sectorerase --program {hex} --reset\",\n\t\"openocd-interface\": \"jlink\",\n\t\"openocd-transport\": \"swd\"\n}\n"
  },
  {
    "path": "targets/pca10056-s140v6-uf2.json",
    "content": "{\n    \"inherits\": [\"nrf52840\", \"nrf52840-s140v6-uf2\"],\n    \"build-tags\": [\"pca10056\"],\n    \"serial-port\": [\"239a:0x0029\"],\n    \"msd-volume-name\": [\"NRF52BOOT\"]\n}\n"
  },
  {
    "path": "targets/pca10056-s140v7.json",
    "content": "{\n\t\"inherits\": [\"pca10056\", \"nrf52840-s140v7\"]\n}\n"
  },
  {
    "path": "targets/pca10056.json",
    "content": "{\n\t\"inherits\": [\"nrf52840\"],\n\t\"build-tags\": [\"pca10056\"],\n\t\"serial\": \"uart\",\n\t\"flash-method\": \"command\",\n\t\"flash-command\": \"nrfjprog -f nrf52 --sectorerase --program {hex} --reset\",\n\t\"msd-volume-name\": [\"JLINK\"],\n\t\"msd-firmware-name\": \"firmware.hex\",\n\t\"openocd-interface\": \"jlink\",\n\t\"openocd-transport\": \"swd\"\n}\n"
  },
  {
    "path": "targets/pca10059-s140v7.json",
    "content": "{\n\t\"inherits\": [\"pca10059\", \"nrf52840-s140v7\"]\n}\n"
  },
  {
    "path": "targets/pca10059.json",
    "content": "{\n\t\"inherits\": [\"nrf52840\"],\n\t\"build-tags\": [\"pca10059\"],\n\t\"serial\": \"usb\",\n\t\"linkerscript\": \"targets/pca10059.ld\",\n\t\"binary-format\": \"nrf-dfu\",\n\t\"flash-command\": \"nrfutil dfu usb-serial -pkg {zip} -p {port} -b 115200\"\n}\n"
  },
  {
    "path": "targets/pca10059.ld",
    "content": "\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x00001000, LENGTH = 0xDF000\n    RAM (xrw)       : ORIGIN = 0x20000008, LENGTH = 0x3FFF8\n}\n\n_stack_size = 2K;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/pga2350.json",
    "content": "{\n    \"inherits\": [\"rp2350b\"],\n    \"build-tags\": [\"pga2350\"],\n    \"ldflags\": [\n        \"--defsym=__flash_size=16M\"\n    ]\n}"
  },
  {
    "path": "targets/pico-boot-stage2.S",
    "content": "// Raspberry Pi Pico Stage 2 Bootloader\n\n//\n// This file defines the parameters specific to the flash-chip found\n// on the official Pico boards.  The generic implementation is in\n// rp2040-boot-stage2.S\n//\n\n#define BOARD_PICO_FLASH_SPI_CLKDIV   2\n#define BOARD_CMD_READ                0xeb\n#define BOARD_QUAD_OK                 1\n#define BOARD_QUAD_ENABLE_STATUS_BYTE 2\n#define BOARD_QUAD_ENABLE_BIT_MASK    2\n#define BOARD_SPLIT_STATUS_WRITE      0\n#define BOARD_WAIT_CYCLES             4\n\n#include \"rp2040-boot-stage2.S\""
  },
  {
    "path": "targets/pico-plus2.json",
    "content": "{\n    \"inherits\": [\n        \"rp2350b\"\n    ],\n    \"build-tags\": [\"pico_plus2\"],\n    \"ldflags\": [\n        \"--defsym=__flash_size=16M\"\n    ],\n    \"serial-port\": [\"2e8a:000F\"],\n    \"default-stack-size\": 8192\n}\n"
  },
  {
    "path": "targets/pico-w.json",
    "content": "{\n    \"inherits\": [\"pico\"],\n    \"build-tags\": [\"pico-w\", \"cyw43439\"]\n}\n"
  },
  {
    "path": "targets/pico.json",
    "content": "{\n    \"inherits\": [\n        \"rp2040\"\n    ],\n    \"build-tags\": [\"pico\"],\n    \"serial-port\": [\"2e8a:000A\"],\n    \"default-stack-size\": 8192,\n    \"ldflags\": [\n        \"--defsym=__flash_size=2048K\"\n    ],\n    \"extra-files\": [\n        \"targets/pico-boot-stage2.S\"\n    ]\n}\n"
  },
  {
    "path": "targets/pico2-ice.json",
    "content": "{\n    \"inherits\": [\n        \"rp2350b\"\n    ],\n    \"build-tags\": [\"pico2_ice\"],\n    \"serial-port\": [\"2e8a:000A\"],\n    \"default-stack-size\": 8192,\n    \"ldflags\": [\n        \"--defsym=__flash_size=4M\"\n    ]\n}\n"
  },
  {
    "path": "targets/pico2-w.json",
    "content": "{\n    \"inherits\": [\"pico2\"],\n    \"build-tags\": [\"pico2-w\", \"cyw43439\"]\n}\n"
  },
  {
    "path": "targets/pico2.json",
    "content": "{\n    \"inherits\": [\n        \"rp2350\"\n    ],\n    \"build-tags\": [\"pico2\"],\n    \"serial-port\": [\"2e8a:000A\"],\n    \"default-stack-size\": 8192,\n    \"ldflags\": [\n        \"--defsym=__flash_size=4M\"\n    ]\n}\n"
  },
  {
    "path": "targets/pinetime.json",
    "content": "{\n\t\"inherits\": [\"nrf52\"],\n\t\"build-tags\": [\"pinetime\"],\n\t\"serial\": \"none\",\n\t\"flash-method\": \"openocd\",\n\t\"flash-command\": \"nrfjprog -f nrf52 --sectorerase --program {hex} --reset\",\n\t\"openocd-interface\": \"jlink\",\n\t\"openocd-transport\": \"swd\"\n}\n"
  },
  {
    "path": "targets/pybadge.json",
    "content": "{\n    \"inherits\": [\"atsamd51j19a\"],\n    \"build-tags\": [\"pybadge\", \"ninafw\"],\n    \"serial\": \"usb\",\n    \"flash-1200-bps-reset\": \"true\",\n    \"flash-method\": \"msd\",\n    \"serial-port\": [\"239a:8033\"],\n    \"msd-volume-name\": [\"PYBADGEBOOT\"],\n    \"msd-firmware-name\": \"arcade.uf2\"\n}\n"
  },
  {
    "path": "targets/pygamer.json",
    "content": "{\n    \"inherits\": [\"atsamd51j19a\"],\n    \"build-tags\": [\"pygamer\"],\n    \"serial\": \"usb\",\n    \"serial-port\": [\"239a:803d\", \"239a:803e\"],\n    \"flash-1200-bps-reset\": \"true\",\n    \"flash-method\": \"msd\",\n    \"msd-volume-name\": [\"PYGAMERBOOT\"],\n    \"msd-firmware-name\": \"arcade.uf2\"\n}\n"
  },
  {
    "path": "targets/pyportal.json",
    "content": "{\n    \"inherits\": [\"atsamd51j20a\"],\n    \"build-tags\": [\"pyportal\", \"ninafw\", \"ninafw_machine_init\"],\n    \"serial\": \"usb\",\n    \"flash-1200-bps-reset\": \"true\",\n    \"flash-method\": \"msd\",\n    \"serial-port\": [\"239a:8035\", \"239a:8036\"],\n    \"msd-volume-name\": [\"PORTALBOOT\"],\n    \"msd-firmware-name\": \"firmware.uf2\"\n}\n"
  },
  {
    "path": "targets/qtpy-esp32c3.json",
    "content": "{\n\t\"inherits\": [\"esp32c3\"],\n\t\"build-tags\": [\"qtpy_esp32c3\"]\n}\n"
  },
  {
    "path": "targets/qtpy-rp2040-boot-stage2.S",
    "content": "// Adafruit QT Py RP2040 Stage 2 Bootloader\n\n//\n// This file defines the parameters specific to the flash-chip found\n// on the Adafruit QT Py RP2040.  The generic implementation is in\n// rp2040-boot-stage2.S\n//\n\n#define BOARD_PICO_FLASH_SPI_CLKDIV   2\n#define BOARD_CMD_READ                0xe7\n#define BOARD_QUAD_OK                 1\n#define BOARD_QUAD_ENABLE_STATUS_BYTE 2\n#define BOARD_QUAD_ENABLE_BIT_MASK    2\n#define BOARD_SPLIT_STATUS_WRITE      1\n#define BOARD_WAIT_CYCLES             2\n\n#include \"rp2040-boot-stage2.S\"\n"
  },
  {
    "path": "targets/qtpy-rp2040.json",
    "content": "{\n    \"inherits\": [\n        \"rp2040\"\n    ],\n    \"serial-port\": [\"239a:80f7\"],\n    \"default-stack-size\": 8192,\n    \"build-tags\": [\"qtpy_rp2040\"],\n    \"ldflags\": [\n        \"--defsym=__flash_size=8192K\"\n    ],\n    \"extra-files\": [\n        \"targets/qtpy-rp2040-boot-stage2.S\"\n    ]\n}\n"
  },
  {
    "path": "targets/qtpy.json",
    "content": "{\n    \"inherits\": [\"atsamd21e18a\"],\n    \"build-tags\": [\"qtpy\"],\n    \"serial\": \"usb\",\n    \"serial-port\": [\"239a:80cb\"],\n    \"flash-1200-bps-reset\": \"true\",\n    \"flash-method\": \"msd\",\n    \"msd-volume-name\": [\"QTPY_BOOT\"],\n    \"msd-firmware-name\": \"firmware.uf2\"\n}\n"
  },
  {
    "path": "targets/rak4631.json",
    "content": "{\n\t\"inherits\": [\"nrf52840\", \"nrf52840-s140v6-uf2\"],\n\t\"build-tags\": [\"rak4631\"],\n\t\"serial-port\": [\"239a:8029\"],\n\t\"msd-volume-name\": [\"RAK4631\"]\n}\n"
  },
  {
    "path": "targets/reelboard-s140v7.json",
    "content": "{\n\t\"inherits\": [\"reelboard\", \"nrf52840-s140v7\"],\n\t\"flash-method\": \"openocd\"\n}\n"
  },
  {
    "path": "targets/reelboard.json",
    "content": "{\n\t\"inherits\": [\"nrf52840\"],\n\t\"build-tags\": [\"reelboard\"],\n\t\"serial\": \"uart\",\n\t\"flash-method\": \"msd\",\n\t\"msd-volume-name\": [\"reel-board\"],\n\t\"msd-firmware-name\": \"firmware.hex\",\n\t\"openocd-interface\": \"cmsis-dap\"\n}\n"
  },
  {
    "path": "targets/riscv-qemu.json",
    "content": "{\n\t\"inherits\": [\n\t\t\"riscv32\"\n\t],\n\t\"features\": \"+32bit,+a,+c,+m,+zaamo,+zalrsc,+zihintpause,+zmmul,-b,-d,-e,-experimental-sdext,-experimental-sdtrig,-experimental-smctr,-experimental-ssctr,-experimental-svukte,-experimental-xqcia,-experimental-xqciac,-experimental-xqcicli,-experimental-xqcicm,-experimental-xqcics,-experimental-xqcicsr,-experimental-xqciint,-experimental-xqcilo,-experimental-xqcilsm,-experimental-xqcisls,-experimental-zalasr,-experimental-zicfilp,-experimental-zicfiss,-experimental-zvbc32e,-experimental-zvkgs,-f,-h,-relax,-sha,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smcdeleg,-smcsrind,-smdbltrp,-smepmp,-smmpm,-smnpm,-smrnmi,-smstateen,-ssaia,-ssccfg,-ssccptr,-sscofpmf,-sscounterenw,-sscsrind,-ssdbltrp,-ssnpm,-sspm,-ssqosid,-ssstateen,-ssstrict,-sstc,-sstvala,-sstvecd,-ssu64xl,-supm,-svade,-svadu,-svbare,-svinval,-svnapot,-svpbmt,-svvptc,-v,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xesppie,-xmipscmove,-xmipslsp,-xsfcease,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xsifivecdiscarddlone,-xsifivecflushdlone,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-xwchc,-za128rs,-za64rs,-zabha,-zacas,-zama16b,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmop,-zcmp,-zcmt,-zdinx,-zfa,-zfbfmin,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zicsr,-zifencei,-zihintntl,-zihpm,-zimop,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-ztso,-zvbb,-zvbc,-zve32f,-zve32x,-zve64d,-zve64f,-zve64x,-zvfbfmin,-zvfbfwma,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl128b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl32b,-zvl4096b,-zvl512b,-zvl64b,-zvl65536b,-zvl8192b\",\n\t\"build-tags\": [\n\t\t\"virt\",\n\t\t\"qemu\"\n\t],\n\t\"scheduler\": \"cores\",\n\t\"default-stack-size\": 16384,\n\t\"cflags\": [\n\t\t\"-march=rv32imaczihintpause\",\n\t\t\"-DTINYGO_CORES=4\"\n\t],\n\t\"ldflags\": [\n\t\t\"--defsym=__num_stacks=4\"\n\t],\n\t\"linkerscript\": \"targets/riscv-qemu.ld\",\n\t\"emulator\": \"qemu-system-riscv32 -machine virt,aclint=on -smp 4 -nographic -bios none -device virtio-rng-device -kernel {}\"\n}\n"
  },
  {
    "path": "targets/riscv-qemu.ld",
    "content": "\n/* Memory map:\n * https://github.com/qemu/qemu/blob/master/hw/riscv/virt.c\n * Looks like we can use any address starting from 0x80000000 (so 2GB of space).\n * However, using a large space slows down tests.\n */\nMEMORY\n{\n    RAM (rwx) : ORIGIN = 0x80000000, LENGTH = 100M\n}\n\nREGION_ALIAS(\"FLASH_TEXT\", RAM)\n\n_stack_size = 2K;\n\nINCLUDE \"targets/riscv.ld\"\n"
  },
  {
    "path": "targets/riscv.json",
    "content": "{\n\t\"goos\": \"linux\",\n\t\"goarch\": \"arm\",\n\t\"build-tags\": [\"tinygo.riscv\", \"baremetal\", \"linux\", \"arm\"],\n\t\"gc\": \"conservative\",\n\t\"linker\": \"ld.lld\",\n\t\"rtlib\": \"compiler-rt\",\n\t\"libc\": \"picolibc\",\n\t\"cflags\": [\n\t\t\"-Werror\",\n\t\t\"-mno-relax\",\n\t\t\"-fno-exceptions\", \"-fno-unwind-tables\", \"-fno-asynchronous-unwind-tables\",\n\t\t\"-ffunction-sections\", \"-fdata-sections\"\n\t],\n\t\"ldflags\": [\n\t\t\"--gc-sections\"\n\t],\n\t\"extra-files\": [\n\t\t\"src/device/riscv/start.S\",\n\t\t\"src/internal/task/task_stack_tinygoriscv.S\",\n\t\t\"src/runtime/asm_riscv.S\",\n\t\t\"src/device/riscv/handleinterrupt.S\"\n\t],\n\t\"gdb\": [\"riscv64-unknown-elf-gdb\"]\n}\n"
  },
  {
    "path": "targets/riscv.ld",
    "content": "SECTIONS\n{\n    .text :\n    {\n        . = ALIGN(4);\n        KEEP(*(.init))\n        . = ALIGN(4);\n        *(.text.handleInterruptASM)\n        *(.text)\n        *(.text.*)\n        *(.rodata)\n        *(.rodata.*)\n        . = ALIGN(4);\n    } >FLASH_TEXT\n\n    /* Put the stack at the bottom of RAM, so that the application will\n     * crash on stack overflow instead of silently corrupting memory.\n     * See: http://blog.japaric.io/stack-overflow-protection/ */\n    .stack0 (NOLOAD) :\n    {\n        . = ALIGN(16);\n        . += _stack_size;\n        _stack_top = .;\n    } >RAM\n\n    .stack1 (NOLOAD) :\n    {\n        . = ALIGN(16);\n        . += DEFINED(__num_stacks) && __num_stacks >= 2 ? _stack_size : 0;\n        _stack1_top = .;\n    } >RAM\n\n    .stack2 (NOLOAD) :\n    {\n        . = ALIGN(16);\n        . += DEFINED(__num_stacks) && __num_stacks >= 3 ? _stack_size : 0;\n        _stack2_top = .;\n    } >RAM\n\n    .stack3 (NOLOAD) :\n    {\n        . = ALIGN(16);\n        . += DEFINED(__num_stacks) && __num_stacks >= 4 ? _stack_size : 0;\n        _stack3_top = .;\n    } >RAM\n\n    /* Start address (in flash) of .data, used by startup code. */\n    _sidata = LOADADDR(.data);\n\n    /* Globals with initial value */\n    .data :\n    {\n        . = ALIGN(4);\n        /* see https://gnu-mcu-eclipse.github.io/arch/riscv/programmer/#the-gp-global-pointer-register */\n        PROVIDE( __global_pointer$ = . + (4K / 2) );\n        _sdata = .;        /* used by startup code */\n        *(.sdata)\n        *(.data .data.*)\n        . = ALIGN(4);\n        _edata = .;        /* used by startup code */\n    } >RAM AT>FLASH_TEXT\n\n    /* Zero-initialized globals  */\n    .bss :\n    {\n        . = ALIGN(4);\n        _sbss = .;         /* used by startup code */\n        *(.sbss)\n        *(.bss .bss.*)\n        *(COMMON)\n        . = ALIGN(4);\n        _ebss = .;         /* used by startup code */\n    } >RAM\n\n    /DISCARD/ :\n    {\n        *(.eh_frame)       /* causes 'no memory region specified' error in lld */\n    }\n}\n\n/* For the memory allocator. */\n_heap_start = ALIGN(_ebss, 16);\n_heap_end = ORIGIN(RAM) + LENGTH(RAM);\n_globals_start = _sdata;\n_globals_end = _ebss;\n"
  },
  {
    "path": "targets/riscv32.json",
    "content": "{\n\t\"inherits\": [\"riscv\"],\n\t\"llvm-target\": \"riscv32-unknown-none\",\n\t\"cpu\": \"generic-rv32\",\n\t\"target-abi\": \"ilp32\",\n\t\"build-tags\": [\"tinygo.riscv32\"],\n\t\"scheduler\": \"tasks\",\n\t\"default-stack-size\": 2048,\n\t\"cflags\": [\n\t\t\"-march=rv32imac\"\n\t],\n\t\"ldflags\": [\n\t\t\"-melf32lriscv\",\n\t\t\"-mllvm\", \"-enable-machine-outliner=never\"\n\t],\n\t\"gdb\": [\n\t\t\"gdb-multiarch\",\n\t\t\"gdb\"\n\t]\n}\n"
  },
  {
    "path": "targets/riscv64.json",
    "content": "{\n\t\"inherits\": [\"riscv\"],\n\t\"llvm-target\": \"riscv64-unknown-none\",\n\t\"cpu\": \"generic-rv64\",\n\t\"target-abi\": \"lp64\",\n\t\"build-tags\": [\"tinygo.riscv64\"],\n\t\"cflags\": [\n\t\t\"-march=rv64gc\"\n\t],\n\t\"ldflags\": [\n\t\t\"-melf64lriscv\"\n\t]\n}\n"
  },
  {
    "path": "targets/rp2040-boot-stage2.S",
    "content": "//\n// Implementation of RP2040 stage 2 boot loader.  This code is derived from the\n// Winbond W25Q080 implementation (as found in the Pico) in the official Pico SDK.\n//\n// This implementation has been made 'stand-alone' by including necessary code /\n// symbols from the included files in the reference implementation directly into\n// the source.  It has also been modified to include the conditional logic from\n// the CircuitPython implementation that supports additional flash chips.  The\n// CircuitPython source is here:\n//   https://github.com/adafruit/circuitpython/blob/main/ports/raspberrypi/stage2.c.jinja\n//\n// This file cannot be assembled directly, instead assemble the board-specific file\n// (such as pico-boot-stage2.S) which defines the parameters specific to the flash\n// chip included on that board.\n//\n// Care has been taken to preserve ordering and it has been verified the generated\n// binary is byte-for-byte identical to the reference code binary when assembled for\n// the Pico.\n//\n// Note: the stage 2 boot loader must be 256 bytes in length and have a checksum\n// present.  In TinyGo, the linker script is responsible for allocating 256 bytes\n// for the .boot2 section and the build logic patches the checksum into the\n// binary after linking, controlled by the '<target>.json' flag 'rp2040-boot-patch'.\n//\n// The stage 2 bootstrap section can be inspected in an elf file using this command:\n//     objdump -s -j .boot2 <binary>.elf\n//\n// Original Source:\n// https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/boot_stage2/boot2_w25q080.S\n//\n\n\n// ----------------------------------------------------------------------------\n// Second stage boot code\n// Copyright (c) 2019-2021 Raspberry Pi (Trading) Ltd.\n// SPDX-License-Identifier: BSD-3-Clause\n//\n// Device:      Winbond W25Q080\n//              Also supports W25Q16JV (which has some different SR instructions)\n//              Also supports AT25SF081\n//              Also supports S25FL132K0\n//\n// Description: Configures W25Q080 to run in Quad I/O continuous read XIP mode\n//\n// Details:     * Check status register 2 to determine if QSPI mode is enabled,\n//                and perform an SR2 programming cycle if necessary.\n//              * Use SSI to perform a dummy 0xEB read command, with the mode\n//                continuation bits set, so that the flash will not require\n//                0xEB instruction prefix on subsequent reads.\n//              * Configure SSI to write address, mode bits, but no instruction.\n//                SSI + flash are now jointly in a state where continuous reads\n//                can take place.\n//              * Jump to exit pointer passed in via lr. Bootrom passes null,\n//                in which case this code uses a default 256 byte flash offset\n//\n// Building:    * This code must be position-independent, and use stack only\n//              * The code will be padded to a size of 256 bytes, including a\n//                4-byte checksum. Therefore code size cannot exceed 252 bytes.\n// ----------------------------------------------------------------------------\n\n\n//\n// Expanded include files\n//\n#define CMD_WRITE_ENABLE 0x06\n#define CMD_READ_STATUS1 0x05\n#define CMD_READ_STATUS2 0x35\n#define CMD_WRITE_STATUS1 0x01\n#define CMD_WRITE_STATUS2 0x31\n#define SREG_DATA 0x02  // Enable quad-SPI mode\n\n#define XIP_BASE       0x10000000\n#define XIP_SSI_BASE   0x18000000\n#define PADS_QSPI_BASE 0x40020000\n#define PPB_BASE       0xe0000000\n\n#define M0PLUS_VTOR_OFFSET 0x0000ed08\n\n#define PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_LSB      4\n#define PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST_BITS  0x00000001\n#define PADS_QSPI_GPIO_QSPI_SCLK_OFFSET         0x00000004\n#define PADS_QSPI_GPIO_QSPI_SD0_OFFSET          0x00000008\n#define PADS_QSPI_GPIO_QSPI_SD0_SCHMITT_BITS    0x00000002\n#define PADS_QSPI_GPIO_QSPI_SD1_OFFSET          0x0000000c\n#define PADS_QSPI_GPIO_QSPI_SD2_OFFSET          0x00000010\n#define PADS_QSPI_GPIO_QSPI_SD3_OFFSET          0x00000014\n\n#define SSI_CTRLR0_OFFSET        0x00000000\n#define SSI_CTRLR1_OFFSET        0x00000004\n#define SSI_SSIENR_OFFSET        0x00000008\n#define SSI_BAUDR_OFFSET         0x00000014\n#define SSI_SR_OFFSET            0x00000028\n#define SSI_DR0_OFFSET           0x00000060\n#define SSI_RX_SAMPLE_DLY_OFFSET 0x000000f0\n\n#define SSI_CTRLR0_DFS_32_LSB 16\n\n#define SSI_CTRLR0_SPI_FRF_VALUE_QUAD 0x2\n#define SSI_CTRLR0_SPI_FRF_LSB        21\n\n#define SSI_CTRLR0_TMOD_VALUE_TX_AND_RX   0x0\n#define SSI_CTRLR0_TMOD_VALUE_EEPROM_READ 0x3\n#define SSI_CTRLR0_TMOD_LSB               8\n\n#define SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C2A 0x1\n#define SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_2C2A 0x2\n\n#define SSI_SPI_CTRLR0_OFFSET 0x000000f4\n\n#define SSI_SPI_CTRLR0_INST_L_VALUE_NONE 0x0\n#define SSI_SPI_CTRLR0_INST_L_VALUE_8B   0x2\n\n#define SSI_SPI_CTRLR0_TRANS_TYPE_LSB  0\n#define SSI_SPI_CTRLR0_ADDR_L_LSB      2\n#define SSI_SPI_CTRLR0_INST_L_LSB      8\n#define SSI_SPI_CTRLR0_WAIT_CYCLES_LSB 11\n#define SSI_SPI_CTRLR0_XIP_CMD_LSB     24\n\n#define SSI_SR_BUSY_BITS  0x00000001\n#define SSI_SR_TFE_BITS   0x00000004\n\n\n// ----------------------------------------------------------------------------\n// Config section\n// ----------------------------------------------------------------------------\n// It should be possible to support most flash devices by modifying this section\n\n// The serial flash interface will run at clk_sys/PICO_FLASH_SPI_CLKDIV.\n// This must be a positive, even integer.\n// The bootrom is very conservative with SPI frequency, but here we should be\n// as aggressive as possible.\n\n#define PICO_FLASH_SPI_CLKDIV BOARD_PICO_FLASH_SPI_CLKDIV\n#if PICO_FLASH_SPI_CLKDIV & 1\n#error PICO_FLASH_SPI_CLKDIV must be even\n#endif\n\n#if BOARD_QUAD_OK==1\n// Define interface width: single/dual/quad IO\n#define FRAME_FORMAT       SSI_CTRLR0_SPI_FRF_VALUE_QUAD\n#define TRANSACTION_TYPE   SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_2C2A\n// Note that the INST_L field is used to select what XIP data gets pushed into\n// the TX FIFO:\n//      INST_L_0_BITS   {ADDR[23:0],XIP_CMD[7:0]}       Load \"mode bits\" into XIP_CMD\n//      Anything else   {XIP_CMD[7:0],ADDR[23:0]}       Load SPI command into XIP_CMD\n#define INSTRUCTION_LENGTH SSI_SPI_CTRLR0_INST_L_VALUE_NONE\n#define READ_INSTRUCTION   MODE_CONTINUOUS_READ\n#define ADDR_L             8 // 6 for address, 2 for mode\n#else\n#define FRAME_FORMAT       SSI_CTRLR0_SPI_FRF_VALUE_STD\n#define TRANSACTION_TYPE   SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C1A\n#define INSTRUCTION_LENGTH SSI_SPI_CTRLR0_INST_L_VALUE_8B\n#define READ_INSTRUCTION   BOARD_CMD_READ\n#define ADDR_L             6 // * 4 = 24\n#endif\n\n// The flash-chip specific read isntruction\n#define CMD_READ BOARD_CMD_READ\n\n// \"Mode bits\" are 8 special bits sent immediately after\n// the address bits in a \"Read Data Fast Quad I/O\" command sequence. \n// On W25Q080, the four LSBs are don't care, and if MSBs == 0xa, the\n// next read does not require the 0xeb instruction prefix.\n#define MODE_CONTINUOUS_READ 0xa0\n\n// How many clocks of Hi-Z following the mode bits. For W25Q080, 4 dummy cycles\n// are required.\n#define WAIT_CYCLES BOARD_WAIT_CYCLES\n\n\n// If defined, we will read status reg, compare to SREG_DATA, and overwrite\n// with our value if the SR doesn't match.\n// We do a two-byte write to SR1 (01h cmd) rather than a one-byte write to\n// SR2 (31h cmd) as the latter command isn't supported by WX25Q080.\n// This isn't great because it will remove block protections.\n// A better solution is to use a volatile SR write if your device supports it.\n#define PROGRAM_STATUS_REG\n\n.syntax unified\n.cpu cortex-m0plus\n.thumb\n.section .boot2, \"ax\"\n\n// The exit point is passed in lr. If entered from bootrom, this will be the\n// flash address immediately following this second stage (0x10000100).\n// Otherwise it will be a return address -- second stage being called as a\n// function by user code, after copying out of XIP region. r3 holds SSI base,\n// r0...2 used as temporaries. Other GPRs not used.\n.global _stage2_boot\n.type _stage2_boot,%function\n.thumb_func\n_stage2_boot:\n    push {lr}\n\n    // Set pad configuration:\n    // - SCLK 8mA drive, no slew limiting\n    // - SDx disable input Schmitt to reduce delay\n\n    ldr r3, =PADS_QSPI_BASE\n    movs r0, #(2 << PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_LSB | PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST_BITS)\n    str r0, [r3, #PADS_QSPI_GPIO_QSPI_SCLK_OFFSET]\n    ldr r0, [r3, #PADS_QSPI_GPIO_QSPI_SD0_OFFSET]\n    movs r1, #PADS_QSPI_GPIO_QSPI_SD0_SCHMITT_BITS\n    bics r0, r1\n#if BOARD_QUAD_OK==1\n    str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD0_OFFSET]\n#endif\n    str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD1_OFFSET]\n#if BOARD_QUAD_OK==1\n    str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD2_OFFSET]\n    str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD3_OFFSET]\n#endif\n\n    ldr r3, =XIP_SSI_BASE\n\n    // Disable SSI to allow further config\n    movs r1, #0\n    str r1, [r3, #SSI_SSIENR_OFFSET]\n\n    // Set baud rate\n    movs r1, #PICO_FLASH_SPI_CLKDIV\n    str r1, [r3, #SSI_BAUDR_OFFSET]\n\n    // Set 1-cycle sample delay. If PICO_FLASH_SPI_CLKDIV == 2 then this means,\n    // if the flash launches data on SCLK posedge, we capture it at the time that\n    // the next SCLK posedge is launched. This is shortly before that posedge\n    // arrives at the flash, so data hold time should be ok. For\n    // PICO_FLASH_SPI_CLKDIV > 2 this pretty much has no effect.\n\n    movs r1, #1\n    movs r2, #SSI_RX_SAMPLE_DLY_OFFSET  // == 0xf0 so need 8 bits of offset significance\n    str r1, [r3, r2]\n\n// On QSPI parts we usually need a 01h SR-write command to enable QSPI mode\n// (i.e. turn WPn and HOLDn into IO2/IO3)\n#ifdef PROGRAM_STATUS_REG\nprogram_sregs:\n#define CTRL0_SPI_TXRX \\\n    (7 << SSI_CTRLR0_DFS_32_LSB) | /* 8 bits per data frame */ \\\n    (SSI_CTRLR0_TMOD_VALUE_TX_AND_RX << SSI_CTRLR0_TMOD_LSB)\n\n    ldr r1, =(CTRL0_SPI_TXRX)\n    str r1, [r3, #SSI_CTRLR0_OFFSET]\n\n     // Enable SSI and select slave 0\n    movs r1, #1\n    str r1, [r3, #SSI_SSIENR_OFFSET]\n\n    // Check whether SR needs updating\n#if BOARD_QUAD_OK==1\n# if BOARD_QUAD_ENABLE_STATUS_BYTE==1\n    movs r0, #CMD_READ_STATUS1\n# elif BOARD_QUAD_ENABLE_STATUS_BYTE==2\n    movs r0, #CMD_READ_STATUS2\n# endif\n\n    bl read_flash_sreg\n    movs r2, #BOARD_QUAD_ENABLE_BIT_MASK\n    cmp r0, r2\n    beq skip_sreg_programming\n\n    // Send write enable command\n    movs r1, #CMD_WRITE_ENABLE\n    str r1, [r3, #SSI_DR0_OFFSET]\n\n    // Poll for completion and discard RX\n    bl wait_ssi_ready\n    ldr r1, [r3, #SSI_DR0_OFFSET]\n\n    // Send status write command followed by data bytes\n# if BOARD_SPLIT_STATUS_WRITE==1\n#  if BOARD_QUAD_ENABLE_STATUS_BYTE==1\n    movs r1, #CMD_WRITE_STATUS1\n#  elif BOARD_QUAD_ENABLE_STATUS_BYTE==2\n    movs r1, #CMD_WRITE_STATUS2\n#  endif\n    str r1, [r3, #SSI_DR0_OFFSET]\n    str r2, [r3, #SSI_DR0_OFFSET]\n\n    bl wait_ssi_ready\n    //ldr r1, [r3, #SSI_DR0_OFFSET]\n    ldr r1, [r3, #SSI_DR0_OFFSET]\n    ldr r1, [r3, #SSI_DR0_OFFSET]\n\n# else \n    movs r1, #CMD_WRITE_STATUS1\n    str r1, [r3, #SSI_DR0_OFFSET]\n#  if BOARD_QUAD_ENABLE_STATUS_BYTE==2\n    movs r0, #0\n    str r0, [r3, #SSI_DR0_OFFSET]\n#  endif\n    str r2, [r3, #SSI_DR0_OFFSET]\n\n    bl wait_ssi_ready\n    ldr r1, [r3, #SSI_DR0_OFFSET]\n    ldr r1, [r3, #SSI_DR0_OFFSET]\n#  if BOARD_QUAD_ENABLE_STATUS_BYTE==2\n    ldr r1, [r3, #SSI_DR0_OFFSET]\n#  endif\n\n# endif\n    // Poll status register for write completion\n1:\n    movs r0, #CMD_READ_STATUS1\n    bl read_flash_sreg\n    movs r1, #1\n    tst r0, r1\n    bne 1b\n#endif\n\nskip_sreg_programming:\n\n    // Disable SSI again so that it can be reconfigured\n    movs r1, #0\n    str r1, [r3, #SSI_SSIENR_OFFSET]\n#endif\n\n// Currently the flash expects an 8 bit serial command prefix on every\n// transfer, which is a waste of cycles. Perform a dummy Fast Read Quad I/O\n// command, with mode bits set such that the flash will not expect a serial\n// command prefix on *subsequent* transfers. We don't care about the results\n// of the read, the important part is the mode bits.\n\ndummy_read:\n#define CTRLR0_ENTER_XIP \\\n    (FRAME_FORMAT                          /* Quad I/O mode */                \\\n        << SSI_CTRLR0_SPI_FRF_LSB) |                                          \\\n    (31 << SSI_CTRLR0_DFS_32_LSB)  |       /* 32 data bits */                 \\\n    (SSI_CTRLR0_TMOD_VALUE_EEPROM_READ     /* Send INST/ADDR, Receive Data */ \\\n        << SSI_CTRLR0_TMOD_LSB)\n\n    ldr r1, =(CTRLR0_ENTER_XIP)\n    str r1, [r3, #SSI_CTRLR0_OFFSET]\n\n    movs r1, #0x0                    // NDF=0 (single 32b read)\n    str r1, [r3, #SSI_CTRLR1_OFFSET]\n\n#if BOARD_QUAD_OK==1\n#define SPI_CTRLR0_ENTER_XIP \\\n    (ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) |     /* Address + mode bits */ \\\n    (WAIT_CYCLES << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z dummy clocks following address + mode */ \\\n    (SSI_SPI_CTRLR0_INST_L_VALUE_8B \\\n        << SSI_SPI_CTRLR0_INST_L_LSB) |        /* 8-bit instruction */ \\\n    (SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C2A      /* Send Command in serial mode then address in Quad I/O mode */ \\\n        << SSI_SPI_CTRLR0_TRANS_TYPE_LSB)\n\n    ldr r1, =(SPI_CTRLR0_ENTER_XIP)\n    ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET)  // SPI_CTRL0 Register\n    str r1, [r0]\n\n    movs r1, #1                      // Re-enable SSI\n    str r1, [r3, #SSI_SSIENR_OFFSET]\n\n    movs r1, #CMD_READ\n    str r1, [r3, #SSI_DR0_OFFSET]   // Push SPI command into TX FIFO\n    movs r1, #MODE_CONTINUOUS_READ   // 32-bit: 24 address bits (we don't care, so 0) and M[7:4]=1010\n    str r1, [r3, #SSI_DR0_OFFSET]   // Push Address into TX FIFO - this will trigger the transaction\n\n    // Poll for completion\n    bl wait_ssi_ready\n\n// The flash is in a state where we can blast addresses in parallel, and get\n// parallel data back. Now configure the SSI to translate XIP bus accesses\n// into QSPI transfers of this form.\n\n    movs r1, #0\n    str r1, [r3, #SSI_SSIENR_OFFSET]   // Disable SSI (and clear FIFO) to allow further config\n#endif\n\n// Note that the INST_L field is used to select what XIP data gets pushed into\n// the TX FIFO:\n//      INST_L_0_BITS   {ADDR[23:0],XIP_CMD[7:0]}       Load \"mode bits\" into XIP_CMD\n//      Anything else   {XIP_CMD[7:0],ADDR[23:0]}       Load SPI command into XIP_CMD\nconfigure_ssi:\n#define SPI_CTRLR0_XIP \\\n    (READ_INSTRUCTION                          /* Mode bits to keep flash in continuous read mode */ \\\n        << SSI_SPI_CTRLR0_XIP_CMD_LSB) | \\\n    (ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) |    /* Total number of address + mode bits */ \\\n    (WAIT_CYCLES << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) |    /* Hi-Z dummy clocks following address + mode */ \\\n    (INSTRUCTION_LENGTH                        /* Do not send a command, instead send XIP_CMD as mode bits after address */ \\\n        << SSI_SPI_CTRLR0_INST_L_LSB) | \\\n    (TRANSACTION_TYPE                          /* Send Address in Quad I/O mode (and Command but that is zero bits long) */ \\\n        << SSI_SPI_CTRLR0_TRANS_TYPE_LSB)\n\n    ldr r1, =(SPI_CTRLR0_XIP)\n\n    ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET)\n    str r1, [r0]\n\n    movs r1, #1\n    str r1, [r3, #SSI_SSIENR_OFFSET]   // Re-enable SSI\n\n// Bus accesses to the XIP window will now be transparently serviced by the\n// external flash on cache miss. We are ready to run code from flash.\n\n\n//\n// Helper Includes\n//\n\n//\n// #include \"boot2_helpers/exit_from_boot2.S\"\n//\n\n// If entered from the bootrom, lr (which we earlier pushed) will be 0,\n// and we vector through the table at the start of the main flash image.\n// Any regular function call will have a nonzero value for lr.\ncheck_return:\n    pop {r0}\n    cmp r0, #0\n    beq vector_into_flash\n    bx r0\nvector_into_flash:\n    ldr r0, =(XIP_BASE + 0x100)\n    ldr r1, =(PPB_BASE + M0PLUS_VTOR_OFFSET)\n    str r0, [r1]\n    ldmia r0, {r0, r1}\n    msr msp, r0\n    bx r1\n\n//\n// #include \"boot2_helpers/wait_ssi_ready.S\"\n//\nwait_ssi_ready:\n    push {r0, r1, lr}\n\n    // Command is complete when there is nothing left to send\n    // (TX FIFO empty) and SSI is no longer busy (CSn deasserted)\n1:\n    ldr r1, [r3, #SSI_SR_OFFSET]\n    movs r0, #SSI_SR_TFE_BITS\n    tst r1, r0\n    beq 1b\n    movs r0, #SSI_SR_BUSY_BITS\n    tst r1, r0\n    bne 1b\n\n    pop {r0, r1, pc}\n\n\n#ifdef PROGRAM_STATUS_REG\n\n//\n// #include \"boot2_helpers/read_flash_sreg.S\"\n//\n\n// Pass status read cmd into r0.\n// Returns status value in r0.\n.global read_flash_sreg\n.type read_flash_sreg,%function\n.thumb_func\nread_flash_sreg:\n    push {r1, lr}\n    str r0, [r3, #SSI_DR0_OFFSET]\n    // Dummy byte:\n    str r0, [r3, #SSI_DR0_OFFSET]\n    \n    bl wait_ssi_ready\n    // Discard first byte and combine the next two\n    ldr r0, [r3, #SSI_DR0_OFFSET]\n    ldr r0, [r3, #SSI_DR0_OFFSET]\n\n    pop {r1, pc}\n\n#endif\n\n.global literals\nliterals:\n.ltorg\n\n.end\n"
  },
  {
    "path": "targets/rp2040.json",
    "content": "{\n    \"inherits\": [\"cortex-m0plus\"],\n    \"build-tags\": [\"rp2040\", \"rp\"],\n    \"scheduler\": \"cores\",\n    \"flash-1200-bps-reset\": \"true\",\n    \"flash-method\": \"msd\",\n    \"serial\": \"usb\",\n    \"msd-volume-name\": [\"RPI-RP2\"],\n    \"msd-firmware-name\": \"firmware.uf2\",\n    \"binary-format\": \"uf2\",\n    \"uf2-family-id\": \"0xe48bff56\",\n    \"rp2040-boot-patch\": true,\n    \"extra-files\": [\n        \"src/device/rp/rp2040.s\"\n    ],\n    \"ldflags\": [\n        \"--defsym=__num_stacks=2\"\n    ],\n    \"linkerscript\": \"targets/rp2040.ld\",\n    \"openocd-interface\": \"picoprobe\",\n    \"openocd-transport\": \"swd\",\n    \"openocd-target\": \"rp2040\"\n}\n"
  },
  {
    "path": "targets/rp2040.ld",
    "content": "MEMORY\n{\n    /* Reserve exactly 256 bytes at start of flash for second stage bootloader */\n    BOOT2_TEXT (rx) : ORIGIN = 0x10000000, LENGTH = 256\n    FLASH_TEXT (rx) : ORIGIN = 0x10000000 + 256, LENGTH = __flash_size - 256\n    RAM (rwx)       : ORIGIN = 0x20000000, LENGTH = 256k\n}\n\n_stack_size = 2K;\n\nSECTIONS\n{\n    /* Second stage bootloader is prepended to the image. It must be 256 bytes\n       and checksummed.  The gap to the checksum is zero-padded.\n    */\n    .boot2 : {\n        __boot2_start__ = .;\n        KEEP (*(.boot2));\n\n        /* Explicitly allocate space for CRC32 checksum at end of second stage\n           bootloader\n        */\n        . = __boot2_start__ + 256 - 4;\n        LONG(0)\n    } > BOOT2_TEXT = 0x0\n\n    /* The second stage will always enter the image at the start of .text.\n       The debugger will use the ELF entry point, which is the _entry_point\n       symbol if present, otherwise defaults to start of .text.\n       This can be used to transfer control back to the bootrom on debugger\n       launches only, to perform proper flash setup.\n    */\n}\n\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/rp2350.json",
    "content": "{\n    \"inherits\": [\"cortex-m33\"],\n    \"build-tags\": [\"rp2350\", \"rp\"],\n    \"scheduler\": \"cores\",\n    \"flash-1200-bps-reset\": \"true\",\n    \"flash-method\": \"msd\",\n    \"serial\": \"usb\",\n    \"msd-volume-name\": [\"RP2350\"],\n    \"msd-firmware-name\": \"firmware.uf2\",\n    \"binary-format\": \"uf2\",\n    \"uf2-family-id\": \"0xe48bff59\",\"comment\":\"See page 393 of RP2350 datasheet: RP2350 Arm Secure image (i.e. one intended to be booted directly by the bootrom)\",\n    \"extra-files\": [\n        \"src/device/rp/rp2350.s\",\n        \"targets/rp2350_embedded_block.s\"\n    ],\n    \"ldflags\": [\n        \"--defsym=__flash_size=2M\",\n        \"--defsym=__num_stacks=2\"\n    ],\n    \"linkerscript\": \"targets/rp2350.ld\",\n    \"openocd-interface\": \"picoprobe\",\n    \"openocd-transport\": \"swd\",\n    \"openocd-target\": \"rp2350\"\n}\n"
  },
  {
    "path": "targets/rp2350.ld",
    "content": "/* See Rust for a more complete reference: https://github.com/rp-rs/rp-hal/blob/main/rp235x-hal-examples/memory.x */\nMEMORY\n{\n   /* 2MiB safe default.  */\n    FLASH : ORIGIN = 0x10000000, LENGTH = __flash_size\n    /* RAM consists of 8 banks, SRAM0..SRAM7 with striped mapping. */\n    SRAM : ORIGIN = 0x20000000, LENGTH = 512k\n    /* Banks 8 and 9 use direct mapping which can be\n       specailized for applications where predictable access time is beneficial.\n       i.e: Separate stacks for core0 and core1. */\n    SRAM4 : ORIGIN = 0x20080000, LENGTH = 4k\n    SRAM5 : ORIGIN = 0x20081000, LENGTH = 4k\n    FLASH_TEXT (rx) : ORIGIN = 0x10000000, LENGTH = __flash_size\n    RAM (rwx)       : ORIGIN = 0x20000000, LENGTH = 512k\n}\n\n_stack_size = 2K;\n\nSECTIONS\n{\n}\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/rp2350_embedded_block.s",
    "content": "// Minimum viable block image from datasheet section 5.9.5.1, \"Minimum Arm IMAGE_DEF\"\n.section .after_isr_vector, \"a\"\n.p2align 2\nembedded_block:\n.word 0xffffded3\n.word 0x10210142\n.word 0x000001ff\n.word 0x00000000\n.word 0xab123579\nembedded_block_end:\n"
  },
  {
    "path": "targets/rp2350b.json",
    "content": "{\n    \"inherits\": [\"rp2350\"],\n    \"build-tags\": [\"rp2350b\"],\n    \"serial-port\": [\"2e8a:000f\"]\n}"
  },
  {
    "path": "targets/simavr.json",
    "content": "{\n    \"inherits\": [\"atmega1284p\"],\n    \"scheduler\": \"tasks\",\n    \"default-stack-size\": 384\n}\n"
  },
  {
    "path": "targets/stm32.ld",
    "content": "\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x08000000, LENGTH = 64K\n    RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 20K\n}\n\n_stack_size = 2K;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/stm32f103rb.ld",
    "content": "\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x08000000, LENGTH = 128K\n    RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 20K\n}\n\n_stack_size = 2K;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/stm32f405.ld",
    "content": "MEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x08000000, LENGTH = 1M\n    RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 128K\n}\n\n_stack_size = 4K;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/stm32f407.ld",
    "content": "\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x08000000, LENGTH = 1M\n    RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 128K\n}\n\n_stack_size = 4K;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/stm32f469.ld",
    "content": "\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x08000000, LENGTH = 2M\n    RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 320K\n}\n\n_stack_size = 4K;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/stm32f469disco.json",
    "content": "{\n  \"inherits\": [\"cortex-m4\"],\n  \"build-tags\": [\"stm32f469disco\", \"stm32f469\", \"stm32f4\", \"stm32\"],\n  \"serial\": \"uart\",\n  \"linkerscript\": \"targets/stm32f469.ld\",\n  \"extra-files\": [\n    \"src/device/stm32/stm32f469.s\"\n  ],\n  \"flash-method\": \"openocd\",\n  \"openocd-interface\": \"stlink\",\n  \"openocd-target\": \"stm32f4x\"\n}\n"
  },
  {
    "path": "targets/stm32f4disco-1.json",
    "content": "{\n    \"inherits\": [\"stm32f4disco\"],\n    \"openocd-interface\": \"stlink-v2-1\"\n}\n"
  },
  {
    "path": "targets/stm32f4disco.json",
    "content": "{\n  \"inherits\": [\"cortex-m4\"],\n  \"build-tags\": [\"stm32f4disco\", \"stm32f407\", \"stm32f4\", \"stm32\"],\n  \"serial\": \"uart\",\n  \"linkerscript\": \"targets/stm32f407.ld\",\n  \"extra-files\": [\n    \"src/device/stm32/stm32f407.s\"\n  ],\n  \"flash-method\": \"openocd\",\n  \"openocd-interface\": \"stlink-v2\",\n  \"openocd-target\": \"stm32f4x\"\n}\n"
  },
  {
    "path": "targets/stm32f7x2zetx.ld",
    "content": "\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x08000000, LENGTH = 512K\n    RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 256K\n}\n\n_stack_size = 4K;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/stm32l031k6.ld",
    "content": "\nMEMORY\n{\n  FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 32K\n  RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 8K\n}\n\n_stack_size = 2K;\n\nINCLUDE \"targets/arm.ld\""
  },
  {
    "path": "targets/stm32l031x6.ld",
    "content": "\nMEMORY\n{\n  FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 32K\n  RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 8K\n}\n\n_stack_size = 2K;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/stm32l072czt6.ld",
    "content": "\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x08000000, LENGTH = 128K\n    RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 20K\n}\n\n_stack_size = 2K;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/stm32l0x1.json",
    "content": "{\n    \"inherits\": [\n        \"cortex-m0plus\"\n    ],\n    \"build-tags\": [\n        \"stm32l031\",\n        \"stm32l0x1\",\n        \"stm32l0\",\n        \"stm32\"\n    ],\n    \"linkerscript\": \"targets/stm32l031x6.ld\",\n    \"extra-files\": [\n        \"src/device/stm32/stm32l0x1.s\"\n    ],\n    \"flash-method\": \"openocd\",\n    \"openocd-interface\": \"cmsis-dap\",\n    \"openocd-target\": \"stm32l0\"\n}\n"
  },
  {
    "path": "targets/stm32l0x2.json",
    "content": "{\n    \"inherits\": [\n        \"cortex-m0plus\"\n    ],\n    \"build-tags\": [\n        \"stm32l0\",\n        \"stm32l0x2\",\n        \"stm32\"\n    ],\n    \"extra-files\": [\n        \"src/device/stm32/stm32l0x2.s\"\n    ]\n}"
  },
  {
    "path": "targets/stm32l4x2.ld",
    "content": "\nMEMORY\n{\n  FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 256K\n  RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 64K\n}\n\n_stack_size = 4K;\n\nINCLUDE \"targets/arm.ld\""
  },
  {
    "path": "targets/stm32l4x5.ld",
    "content": "\nMEMORY\n{\n  FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 2048K\n  RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 640K\n}\n\n_stack_size = 4K;\n\nINCLUDE \"targets/arm.ld\""
  },
  {
    "path": "targets/stm32l4x6.ld",
    "content": "\nMEMORY\n{\n  FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 1024K\n  RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 96K\n  RAM2 (xrw)      : ORIGIN = 0x10000000, LENGTH = 32K\n}\n\n_stack_size = 4K;\n\nINCLUDE \"targets/arm.ld\"\n"
  },
  {
    "path": "targets/stm32l5x2xe.ld",
    "content": "\nMEMORY\n{\n  FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 512K\n  RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 192K\n}\n\n_stack_size = 4K;\n\nINCLUDE \"targets/arm.ld\""
  },
  {
    "path": "targets/stm32wl5x_cm4.json",
    "content": "{\n    \"inherits\": [\"cortex-m4\"],\n    \"build-tags\": [ \"stm32wl5x_cm4\",\"stm32wlx\", \"stm32\"],\n    \"extra-files\": [\n      \"src/device/stm32/stm32wl5x_cm4.s\"\n    ],\n    \"linkerscript\": \"targets/stm32wlx.ld\"\n}\n"
  },
  {
    "path": "targets/stm32wle5.json",
    "content": "{\n    \"inherits\": [\"cortex-m4\"],\n    \"build-tags\": [ \"stm32wle5\",\"stm32wlx\", \"stm32\"],\n    \"extra-files\": [\n      \"src/device/stm32/stm32wle5.s\"\n    ],\n    \"linkerscript\": \"targets/stm32wlx.ld\"\n}\n"
  },
  {
    "path": "targets/stm32wlx.ld",
    "content": "\nMEMORY\n{\n    FLASH_TEXT (rw) : ORIGIN = 0x08000000, LENGTH = 256K\n    RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 64K\n}\n\n_stack_size = 4K;\n\nINCLUDE \"targets/arm.ld\""
  },
  {
    "path": "targets/swan.json",
    "content": "{\n    \"inherits\": [\"cortex-m4\"],\n    \"build-tags\": [\"swan\", \"stm32l4r5\", \"stm32l4x5\", \"stm32l4\", \"stm32\"],\n    \"serial\": \"uart\",\n    \"linkerscript\": \"targets/stm32l4x5.ld\",\n    \"extra-files\": [\n      \"src/device/stm32/stm32l4x5.s\"\n    ],\n    \"flash-method\": \"command\",\n    \"flash-command\": \"dfu-util --alt 0 --dfuse-address 0x08000000 --download {bin}\",\n    \"openocd-interface\": \"stlink\",\n    \"openocd-target\": \"stm32l4x\"\n  }"
  },
  {
    "path": "targets/teensy36.json",
    "content": "{\n\t\"inherits\": [\"cortex-m4\"],\n\t\"build-tags\": [\"teensy36\", \"teensy\", \"mk66f18\", \"nxp\"],\n\t\"serial\": \"uart\",\n\t\"linkerscript\": \"targets/nxpmk66f18.ld\",\n\t\"extra-files\": [\n\t\t\"src/device/nxp/mk66f18.s\",\n\t\t\"targets/teensy36.s\"\n\t],\n\t\"flash-command\": \"teensy_loader_cli -mmcu=mk66fx1m0 -v -w {hex}\"\n}\n\n"
  },
  {
    "path": "targets/teensy36.s",
    "content": ".section .flash_config\n.global  __flash_config\n__flash_config:\n    .byte 0xFF\n    .byte 0xFF\n    .byte 0xFF\n    .byte 0xFF\n    .byte 0xFF\n    .byte 0xFF\n    .byte 0xFF\n    .byte 0xFF\n    .byte 0xFF\n    .byte 0xFF\n    .byte 0xFF\n    .byte 0xFF\n    .byte 0xDE\n    .byte 0xF9\n    .byte 0xFF\n    .byte 0xFF\n"
  },
  {
    "path": "targets/teensy40.json",
    "content": "{\n  \"inherits\": [\"cortex-m7\"],\n  \"build-tags\": [\"teensy40\", \"teensy\", \"mimxrt1062\", \"nxp\"],\n  \"serial\": \"uart\",\n  \"automatic-stack-size\": false,\n  \"linkerscript\": \"targets/mimxrt1062-teensy40.ld\",\n  \"extra-files\": [\n    \"src/device/nxp/mimxrt1062.s\",\n    \"targets/teensy40.s\"\n  ],\n  \"flash-command\": \"teensy_loader_cli -mmcu=imxrt1062 -v -w {hex}\"\n}\n\n"
  },
  {
    "path": "targets/teensy40.s",
    "content": "// -----------------------------------------------------------------------------\n//  file: teensy40.s\n//  desc: various startup and configuration data for Teensy 4.0.\n// -----------------------------------------------------------------------------\n//  References\n//    i.MX RT1060 Processor Reference Manual\n//       - Section 9.7.1 \"Image Vector Table and Boot Data\"\n//    Teensyduino 1.53 by Paul Stoffregen (PJRC)\n//       - cores/teensy4/bootdata.c\n//       - cores/teensy4/startup.c\n// -----------------------------------------------------------------------------\n\n.section .boot_data\n.global  __boot_data\n__boot_data:\n    .word 0x60000000         // boot start location\n    .word _image_size        // flash size\n    .word 0                  // plugin flag, use 0 to indicate normal (non-plugin) ROM image\n\n.section .ivt\n.global  __ivt\n__ivt:\n    .word 0x402000D1         // header (version 4.0)\n    .word _svectors          // image entry function\n    .word 0                  // reserved\n    .word 0                  // DCD info (optional, set to 0|NULL if unused)\n    .word __boot_data        // boot data struct\n    .word __ivt              // self\n    .word 0                  // command sequence file (CSF) not provided in image\n    .word 0                  // reserved\n\n.section .flash_config\n.global  __flash_config\n__flash_config:\n    // 448 byte common FlexSPI configuration block, 8.6.3.1 page 223 (RT1060 rev 0)\n    // MCU_Flashloader_Reference_Manual.pdf, 8.2.1, Table 8-2, page 72-75\n    .word 0x42464346         // Tag                                       0x00\n    .word 0x56010000         // Version\n    .word 0                  // reserved\n    .word 0x00020101         // columnAdressWidth,dataSetupTime,dataHoldTime,readSampleClkSrc\n\n    .word 0x00000000         // waitTimeCfgCommands,-,deviceModeCfgEnable\n    .word 0                  // deviceModeSeq\n    .word 0                  // deviceModeArg\n    .word 0x00000000         // -,-,-,configCmdEnable\n\n    .word 0                  // configCmdSeqs                             0x20\n    .word 0\n    .word 0\n    .word 0\n\n    .word 0                  // cfgCmdArgs                                0x30\n    .word 0\n    .word 0\n    .word 0\n\n    .word 0x00000000         // controllerMiscOption                      0x40\n    .word 0x00030401         // lutCustomSeqEnable,serialClkFreq,sflashPadType,deviceType\n    .word 0                  // reserved\n    .word 0                  // reserved\n\n    .word 0x00200000         // sflashA1Size (Teensy 4.0)                 0x50\n    //.word 0x00800000         // sflashA1Size (Teensy 4.1)                 0x50\n\n    .word 0                  // sflashA2Size\n    .word 0                  // sflashB1Size\n    .word 0                  // sflashB2Size\n\n    .word 0                  // csPadSettingOverride                      0x60\n    .word 0                  // sclkPadSettingOverride\n    .word 0                  // dataPadSettingOverride\n    .word 0                  // dqsPadSettingOverride\n\n    .word 0                  // timeoutInMs                               0x70\n    .word 0                  // commandInterval\n    .word 0                  // dataValidTime\n    .word 0x00000000         // busyBitPolarity,busyOffset\n\n    .word 0x0A1804EB         // lookupTable[0]                            0x80\n    .word 0x26043206         // lookupTable[1]\n    .word 0                  // lookupTable[2]\n    .word 0                  // lookupTable[3]\n\n    .word 0x24040405         // lookupTable[4]                            0x90\n    .word 0                  // lookupTable[5]\n    .word 0                  // lookupTable[6]\n    .word 0                  // lookupTable[7]\n\n    .word 0                  // lookupTable[8]                            0xA0\n    .word 0                  // lookupTable[9]\n    .word 0                  // lookupTable[10]\n    .word 0                  // lookupTable[11]\n\n    .word 0x00000406         // lookupTable[12]                           0xB0\n    .word 0                  // lookupTable[13]\n    .word 0                  // lookupTable[14]\n    .word 0                  // lookupTable[15]\n\n    .word 0                  // lookupTable[16]                           0xC0\n    .word 0                  // lookupTable[17]\n    .word 0                  // lookupTable[18]\n    .word 0                  // lookupTable[19]\n\n    .word 0x08180420         // lookupTable[20]                           0xD0\n    .word 0                  // lookupTable[21]\n    .word 0                  // lookupTable[22]\n    .word 0                  // lookupTable[23]\n\n    .word 0                  // lookupTable[24]                           0xE0\n    .word 0                  // lookupTable[25]\n    .word 0                  // lookupTable[26]\n    .word 0                  // lookupTable[27]\n\n    .word 0                  // lookupTable[28]                           0xF0\n    .word 0                  // lookupTable[29]\n    .word 0                  // lookupTable[30]\n    .word 0                  // lookupTable[31]\n\n    .word 0x081804D8         // lookupTable[32]                           0x100\n    .word 0                  // lookupTable[33]\n    .word 0                  // lookupTable[34]\n    .word 0                  // lookupTable[35]\n\n    .word 0x08180402         // lookupTable[36]                           0x110\n    .word 0x00002004         // lookupTable[37]\n    .word 0                  // lookupTable[38]\n    .word 0                  // lookupTable[39]\n\n    .word 0                  // lookupTable[40]                           0x120\n    .word 0                  // lookupTable[41]\n    .word 0                  // lookupTable[42]\n    .word 0                  // lookupTable[43]\n\n    .word 0x00000460         // lookupTable[44]                           0x130\n    .word 0                  // lookupTable[45]\n    .word 0                  // lookupTable[46]\n    .word 0                  // lookupTable[47]\n\n    .word 0                  // lookupTable[48]                           0x140\n    .word 0                  // lookupTable[49]\n    .word 0                  // lookupTable[50]\n    .word 0                  // lookupTable[51]\n\n    .word 0                  // lookupTable[52]                           0x150\n    .word 0                  // lookupTable[53]\n    .word 0                  // lookupTable[54]\n    .word 0                  // lookupTable[55]\n\n    .word 0                  // lookupTable[56]                           0x160\n    .word 0                  // lookupTable[57]\n    .word 0                  // lookupTable[58]\n    .word 0                  // lookupTable[59]\n\n    .word 0                  // lookupTable[60]                           0x170\n    .word 0                  // lookupTable[61]\n    .word 0                  // lookupTable[62]\n    .word 0                  // lookupTable[63]\n\n    .word 0                  // LUT 0: Read                               0x180\n    .word 0                  // LUT 1: ReadStatus\n    .word 0                  // LUT 3: WriteEnable\n    .word 0                  // LUT 5: EraseSector\n\n    .word 0                  // LUT 9: PageProgram                        0x190\n    .word 0                  // LUT 11: ChipErase\n    .word 0                  // LUT 15: Dummy\n    .word 0                  // LUT unused?\n\n    .word 0                  // LUT unused?                               0x1A0\n    .word 0                  // LUT unused?\n    .word 0                  // LUT unused?\n    .word 0                  // LUT unused?\n\n    .word 0                  // reserved                                  0x1B0\n    .word 0                  // reserved\n    .word 0                  // reserved\n    .word 0                  // reserved\n\n    // 64 byte Serial NOR configuration block (8.6.3.2, page 346)\n\n    .word 256                // pageSize                                  0x1C0\n    .word 4096               // sectorSize\n    .word 1                  // ipCmdSerialClkFreq\n    .word 0                  // reserved\n\n    .word 0x00010000         // block size                                0x1D0\n    .word 0                  // reserved\n    .word 0                  // reserved\n    .word 0                  // reserved\n\n    .word 0                  // reserved                                  0x1E0\n    .word 0                  // reserved\n    .word 0                  // reserved\n    .word 0                  // reserved\n\n    .word 0                  // reserved                                  0x1F0\n    .word 0                  // reserved\n    .word 0                  // reserved\n    .word 0                  // reserved\n"
  },
  {
    "path": "targets/teensy41.json",
    "content": "{\n  \"inherits\": [\"cortex-m7\"],\n  \"build-tags\": [\"teensy41\", \"teensy\", \"mimxrt1062\", \"nxp\"],\n  \"serial\": \"uart\",\n  \"automatic-stack-size\": false,\n  \"linkerscript\": \"targets/mimxrt1062-teensy40.ld\",\n  \"extra-files\": [\n    \"src/device/nxp/mimxrt1062.s\",\n    \"targets/teensy40.s\"\n  ],\n  \"flash-command\": \"teensy_loader_cli -mmcu=imxrt1062 -v -w {hex}\"\n}\n"
  },
  {
    "path": "targets/thingplus-rp2040.json",
    "content": "{\n    \"inherits\": [\n        \"rp2040\"\n    ],\n    \"serial-port\": [\"1b4f:0026\"],\n    \"build-tags\": [\"thingplus_rp2040\"],\n    \"ldflags\": [\n        \"--defsym=__flash_size=16M\"\n    ],\n    \"extra-files\": [\n        \"targets/pico-boot-stage2.S\"\n    ]\n}\n"
  },
  {
    "path": "targets/thumby.json",
    "content": "{\n    \"inherits\": [\n        \"rp2040\"\n    ],\n    \"serial-port\": [\"2e8a:0005\"],\n    \"build-tags\": [\"thumby\"],\n    \"default-stack-size\": 8192,\n    \"ldflags\": [\n        \"--defsym=__flash_size=2048K\"\n    ],\n    \"extra-files\": [\n        \"targets/pico-boot-stage2.S\"\n    ]\n}\n"
  },
  {
    "path": "targets/tiny2350.json",
    "content": "{\n    \"inherits\": [\n        \"rp2350\"\n    ],\n    \"build-tags\": [\"tiny2350\"],\n    \"ldflags\": [\n        \"--defsym=__flash_size=4M\"\n    ],\n    \"serial-port\": [\"2e8a:000f\"],\n    \"default-stack-size\": 8192\n}\n"
  },
  {
    "path": "targets/tkey.json",
    "content": "{\n    \"inherits\": [\"riscv32\"],\n    \"build-tags\": [\"tkey\"],\n    \"features\": \"+32bit,+c,+zmmul,-a,-b,-d,-e,-experimental-sdext,-experimental-sdtrig,-experimental-smctr,-experimental-ssctr,-experimental-svukte,-experimental-xqcia,-experimental-xqciac,-experimental-xqcicli,-experimental-xqcicm,-experimental-xqcics,-experimental-xqcicsr,-experimental-xqciint,-experimental-xqcilo,-experimental-xqcilsm,-experimental-xqcisls,-experimental-zalasr,-experimental-zicfilp,-experimental-zicfiss,-experimental-zvbc32e,-experimental-zvkgs,-f,-h,-m,-relax,-sha,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smcdeleg,-smcsrind,-smdbltrp,-smepmp,-smmpm,-smnpm,-smrnmi,-smstateen,-ssaia,-ssccfg,-ssccptr,-sscofpmf,-sscounterenw,-sscsrind,-ssdbltrp,-ssnpm,-sspm,-ssqosid,-ssstateen,-ssstrict,-sstc,-sstvala,-sstvecd,-ssu64xl,-supm,-svade,-svadu,-svbare,-svinval,-svnapot,-svpbmt,-svvptc,-v,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xesppie,-xmipscmove,-xmipslsp,-xsfcease,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xsifivecdiscarddlone,-xsifivecflushdlone,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-xwchc,-za128rs,-za64rs,-zaamo,-zabha,-zacas,-zalrsc,-zama16b,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmop,-zcmp,-zcmt,-zdinx,-zfa,-zfbfmin,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zicsr,-zifencei,-zihintntl,-zihintpause,-zihpm,-zimop,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-ztso,-zvbb,-zvbc,-zve32f,-zve32x,-zve64d,-zve64f,-zve64x,-zvfbfmin,-zvfbfwma,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl128b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl32b,-zvl4096b,-zvl512b,-zvl64b,-zvl65536b,-zvl8192b\",\n    \"cflags\": [\n        \"-march=rv32iczmmul\"\n    ],\n    \"linkerscript\": \"targets/tkey.ld\",\n    \"scheduler\": \"none\",\n    \"gc\": \"conservative\",\n    \"flash-command\": \"tkey-runapp {bin}\",\n    \"serial\": \"uart\"\n}\n"
  },
  {
    "path": "targets/tkey.ld",
    "content": "\nMEMORY\n{\n    RAM (rwx)       : ORIGIN = 0x40000000, LENGTH = 0x20000 /* 128 KB */\n}\n\nREGION_ALIAS(\"FLASH_TEXT\", RAM);\n\n_stack_size = 2K;\n\nINCLUDE \"targets/riscv.ld\"\n"
  },
  {
    "path": "targets/trinket-m0.json",
    "content": "{\n    \"inherits\": [\"atsamd21e18a\"],\n    \"build-tags\": [\"trinket_m0\"],\n    \"serial\": \"usb\",\n    \"serial-port\": [\"239a:801e\"],\n    \"flash-1200-bps-reset\": \"true\",\n    \"flash-method\": \"msd\",\n    \"msd-volume-name\": [\"TRINKETBOOT\"],\n    \"msd-firmware-name\": \"firmware.uf2\"\n}\n"
  },
  {
    "path": "targets/trinkey-qt2040-boot-stage2.S",
    "content": "// Adafruit Trinkey QT2040 Stage 2 Bootloader\n\n//\n// This file defines the parameters specific to the flash-chip found\n// on the Adafruit Trinkey QT2040.  The generic implementation is in\n// rp2040-boot-stage2.S\n//\n\n#define BOARD_PICO_FLASH_SPI_CLKDIV   4\n#define BOARD_CMD_READ                0xe7\n#define BOARD_QUAD_OK                 1\n#define BOARD_QUAD_ENABLE_STATUS_BYTE 2\n#define BOARD_QUAD_ENABLE_BIT_MASK    2\n#define BOARD_SPLIT_STATUS_WRITE      1\n#define BOARD_WAIT_CYCLES             2\n\n#include \"rp2040-boot-stage2.S\"\n"
  },
  {
    "path": "targets/trinkey-qt2040.json",
    "content": "{\n    \"inherits\": [\n        \"rp2040\"\n    ],\n    \"serial-port\": [\"239a:8109\"],\n    \"default-stack-size\": 8192,\n    \"build-tags\": [\"trinkey_qt2040\"],\n    \"ldflags\": [\n        \"--defsym=__flash_size=8192K\"\n    ],\n    \"extra-files\": [\n        \"targets/trinkey-qt2040-boot-stage2.S\"\n    ]\n}\n"
  },
  {
    "path": "targets/tufty2040.json",
    "content": "{\n    \"inherits\": [\n        \"rp2040\"\n    ],\n    \"serial-port\": [\"2e8a:0003\"],\n    \"default-stack-size\": 8192,\n    \"build-tags\": [\"tufty2040\"],\n    \"ldflags\": [\n        \"--defsym=__flash_size=1020K\"\n    ],\n    \"extra-files\": [\n        \"targets/pico-boot-stage2.S\"\n    ]\n}\n"
  },
  {
    "path": "targets/wasi.json",
    "content": "{\n    \"inherits\": [\"wasip1\"]\n}\n"
  },
  {
    "path": "targets/wasip1.json",
    "content": "{\n\t\"llvm-target\":   \"wasm32-unknown-wasi\",\n\t\"cpu\":           \"generic\",\n\t\"features\":      \"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\",\n\t\"build-tags\":    [\"tinygo.wasm\"],\n\t\"goos\":          \"wasip1\",\n\t\"goarch\":        \"wasm\",\n\t\"linker\":        \"wasm-ld\",\n\t\"libc\":          \"wasi-libc\",\n\t\"rtlib\":         \"compiler-rt\",\n\t\"gc\":            \"precise\",\n\t\"scheduler\":     \"asyncify\",\n\t\"default-stack-size\": 65536,\n\t\"cflags\": [\n\t\t\"-mbulk-memory\",\n\t\t\"-mnontrapping-fptoint\",\n\t\t\"-mno-multivalue\",\n\t\t\"-mno-reference-types\",\n\t\t\"-msign-ext\"\n\t],\n\t\"ldflags\": [\n\t\t\"--stack-first\",\n\t\t\"--no-demangle\"\n\t],\n\t\"extra-files\": [\n\t\t\"src/runtime/asm_tinygowasm.S\",\n\t\t\"src/runtime/gc_boehm.c\"\n\t],\n\t\"emulator\":      \"wasmtime run --dir={tmpDir}::/tmp {}\"\n}\n"
  },
  {
    "path": "targets/wasip2.json",
    "content": "{\n\t\"llvm-target\":   \"wasm32-unknown-wasi\",\n\t\"cpu\":           \"generic\",\n\t\"features\":      \"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\",\n\t\"build-tags\":    [\"tinygo.wasm\", \"wasip2\"],\n\t\"buildmode\":     \"c-shared\",\n\t\"goos\":          \"linux\",\n\t\"goarch\":        \"arm\",\n\t\"linker\":        \"wasm-ld\",\n\t\"libc\":          \"wasmbuiltins\",\n\t\"rtlib\":         \"compiler-rt\",\n\t\"gc\":            \"precise\",\n\t\"scheduler\":     \"asyncify\",\n\t\"default-stack-size\": 65536,\n\t\"cflags\": [\n\t\t\"-mbulk-memory\",\n\t\t\"-mnontrapping-fptoint\",\n\t\t\"-mno-multivalue\",\n\t\t\"-mno-reference-types\",\n\t\t\"-msign-ext\"\n\t],\n\t\"ldflags\": [\n\t\t\"--stack-first\",\n\t\t\"--no-demangle\",\n\t\t\"--no-entry\"\n\t],\n\t\"extra-files\": [\n\t\t\"src/runtime/asm_tinygowasm.S\"\n\t],\n\t\"emulator\": \"wasmtime run --wasm component-model -Sinherit-network -Sallow-ip-name-lookup --dir={tmpDir}::/tmp {}\",\n\t\"wit-package\": \"{root}/lib/wasi-cli/wit/\",\n\t\"wit-world\": \"wasi:cli/command\"\n}\n"
  },
  {
    "path": "targets/wasm-undefined.txt",
    "content": "syscall/js.copyBytesToGo\nsyscall/js.copyBytesToJS\nsyscall/js.finalizeRef\nsyscall/js.stringVal\nsyscall/js.valueCall\nsyscall/js.valueDelete\nsyscall/js.valueGet\nsyscall/js.valueIndex\nsyscall/js.valueInstanceOf\nsyscall/js.valueInvoke\nsyscall/js.valueLength\nsyscall/js.valueLoadString\nsyscall/js.valueNew\nsyscall/js.valuePrepareString\nsyscall/js.valueSet\nsyscall/js.valueSetIndex\n"
  },
  {
    "path": "targets/wasm-unknown.json",
    "content": "{\n\t\"llvm-target\":   \"wasm32-unknown-unknown\",\n\t\"cpu\":           \"mvp\",\n\t\"features\":      \"+nontrapping-fptoint,+sign-ext,-bulk-memory,-multivalue,-reference-types\",\n\t\"build-tags\":    [\"tinygo.wasm\", \"wasm_unknown\"],\n\t\"buildmode\":    \"c-shared\",\n\t\"goos\":          \"linux\",\n\t\"goarch\":        \"arm\",\n\t\"linker\":        \"wasm-ld\",\n\t\"rtlib\":         \"compiler-rt\",\n\t\"libc\":          \"wasmbuiltins\",\n\t\"scheduler\":     \"none\",\n\t\"gc\":            \"leaking\",\n\t\"default-stack-size\": 4096,\n\t\"cflags\": [\n\t\t\"-mnontrapping-fptoint\",\n\t\t\"-mno-bulk-memory\",\n\t\t\"-mno-multivalue\",\n\t\t\"-mno-reference-types\",\n\t\t\"-msign-ext\"\n\t],\n\t\"ldflags\": [\n\t\t\"--stack-first\",\n\t\t\"--no-demangle\",\n\t\t\"--no-entry\"\n\t],\n\t\"extra-files\": [\n\t\t\"src/runtime/asm_tinygowasm.S\"\n\t],\n\t\"emulator\":      \"wasmtime run --dir={tmpDir}::/tmp {}\"\n}\n"
  },
  {
    "path": "targets/wasm.json",
    "content": "{\n\t\"llvm-target\":   \"wasm32-unknown-wasi\",\n\t\"cpu\":           \"generic\",\n\t\"features\":      \"+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types\",\n\t\"build-tags\":    [\"tinygo.wasm\"],\n\t\"goos\":          \"js\",\n\t\"goarch\":        \"wasm\",\n\t\"linker\":        \"wasm-ld\",\n\t\"libc\":          \"wasi-libc\",\n\t\"rtlib\":         \"compiler-rt\",\n\t\"gc\":            \"precise\",\n\t\"scheduler\":     \"asyncify\",\n\t\"default-stack-size\": 65536,\n\t\"cflags\": [\n\t\t\"-mbulk-memory\",\n\t\t\"-mnontrapping-fptoint\",\n\t\t\"-mno-multivalue\",\n\t\t\"-mno-reference-types\",\n\t\t\"-msign-ext\"\n\t],\n\t\"ldflags\": [\n\t\t\"--allow-undefined-file={root}/targets/wasm-undefined.txt\",\n\t\t\"--stack-first\",\n\t\t\"--no-demangle\"\n\t],\n\t\"extra-files\": [\n\t\t\"src/runtime/asm_tinygowasm.S\",\n\t\t\"src/runtime/gc_boehm.c\"\n\t],\n\t\"emulator\":      \"node {root}/targets/wasm_exec.js {}\"\n}\n"
  },
  {
    "path": "targets/wasm_exec.js",
    "content": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n//\n// This file has been modified for use by the TinyGo compiler.\n\n(() => {\n\t// Map multiple JavaScript environments to a single common API,\n\t// preferring web standards over Node.js API.\n\t//\n\t// Environments considered:\n\t// - Browsers\n\t// - Node.js\n\t// - Electron\n\t// - Parcel\n\n\tif (typeof global !== \"undefined\") {\n\t\t// global already exists\n\t} else if (typeof window !== \"undefined\") {\n\t\twindow.global = window;\n\t} else if (typeof self !== \"undefined\") {\n\t\tself.global = self;\n\t} else {\n\t\tthrow new Error(\"cannot export Go (neither global, window nor self is defined)\");\n\t}\n\n\tif (!global.require && typeof require !== \"undefined\") {\n\t\tglobal.require = require;\n\t}\n\n\tif (!global.fs && global.require) {\n\t\tglobal.fs = require(\"node:fs\");\n\t}\n\n\tconst enosys = () => {\n\t\tconst err = new Error(\"not implemented\");\n\t\terr.code = \"ENOSYS\";\n\t\treturn err;\n\t};\n\n\tif (!global.fs) {\n\t\tlet outputBuf = \"\";\n\t\tglobal.fs = {\n\t\t\tconstants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, // unused\n\t\t\twriteSync(fd, buf) {\n\t\t\t\toutputBuf += decoder.decode(buf);\n\t\t\t\tconst nl = outputBuf.lastIndexOf(\"\\n\");\n\t\t\t\tif (nl != -1) {\n\t\t\t\t\tconsole.log(outputBuf.substr(0, nl));\n\t\t\t\t\toutputBuf = outputBuf.substr(nl + 1);\n\t\t\t\t}\n\t\t\t\treturn buf.length;\n\t\t\t},\n\t\t\twrite(fd, buf, offset, length, position, callback) {\n\t\t\t\tif (offset !== 0 || length !== buf.length || position !== null) {\n\t\t\t\t\tcallback(enosys());\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst n = this.writeSync(fd, buf);\n\t\t\t\tcallback(null, n);\n\t\t\t},\n\t\t\tchmod(path, mode, callback) { callback(enosys()); },\n\t\t\tchown(path, uid, gid, callback) { callback(enosys()); },\n\t\t\tclose(fd, callback) { callback(enosys()); },\n\t\t\tfchmod(fd, mode, callback) { callback(enosys()); },\n\t\t\tfchown(fd, uid, gid, callback) { callback(enosys()); },\n\t\t\tfstat(fd, callback) { callback(enosys()); },\n\t\t\tfsync(fd, callback) { callback(null); },\n\t\t\tftruncate(fd, length, callback) { callback(enosys()); },\n\t\t\tlchown(path, uid, gid, callback) { callback(enosys()); },\n\t\t\tlink(path, link, callback) { callback(enosys()); },\n\t\t\tlstat(path, callback) { callback(enosys()); },\n\t\t\tmkdir(path, perm, callback) { callback(enosys()); },\n\t\t\topen(path, flags, mode, callback) { callback(enosys()); },\n\t\t\tread(fd, buffer, offset, length, position, callback) { callback(enosys()); },\n\t\t\treaddir(path, callback) { callback(enosys()); },\n\t\t\treadlink(path, callback) { callback(enosys()); },\n\t\t\trename(from, to, callback) { callback(enosys()); },\n\t\t\trmdir(path, callback) { callback(enosys()); },\n\t\t\tstat(path, callback) { callback(enosys()); },\n\t\t\tsymlink(path, link, callback) { callback(enosys()); },\n\t\t\ttruncate(path, length, callback) { callback(enosys()); },\n\t\t\tunlink(path, callback) { callback(enosys()); },\n\t\t\tutimes(path, atime, mtime, callback) { callback(enosys()); },\n\t\t};\n\t}\n\n\tif (!global.process) {\n\t\tglobal.process = {\n\t\t\tgetuid() { return -1; },\n\t\t\tgetgid() { return -1; },\n\t\t\tgeteuid() { return -1; },\n\t\t\tgetegid() { return -1; },\n\t\t\tgetgroups() { throw enosys(); },\n\t\t\tpid: -1,\n\t\t\tppid: -1,\n\t\t\tumask() { throw enosys(); },\n\t\t\tcwd() { throw enosys(); },\n\t\t\tchdir() { throw enosys(); },\n\t\t}\n\t}\n\n\tif (!global.crypto) {\n\t\tconst nodeCrypto = require(\"node:crypto\");\n\t\tglobal.crypto = {\n\t\t\tgetRandomValues(b) {\n\t\t\t\tnodeCrypto.randomFillSync(b);\n\t\t\t},\n\t\t};\n\t}\n\n\tif (!global.performance) {\n\t\tglobal.performance = {\n\t\t\tnow() {\n\t\t\t\tconst [sec, nsec] = process.hrtime();\n\t\t\t\treturn sec * 1000 + nsec / 1000000;\n\t\t\t},\n\t\t};\n\t}\n\n\tif (!global.TextEncoder) {\n\t\tglobal.TextEncoder = require(\"node:util\").TextEncoder;\n\t}\n\n\tif (!global.TextDecoder) {\n\t\tglobal.TextDecoder = require(\"node:util\").TextDecoder;\n\t}\n\n\t// End of polyfills for common API.\n\n\tconst encoder = new TextEncoder(\"utf-8\");\n\tconst decoder = new TextDecoder(\"utf-8\");\n\tlet reinterpretBuf = new DataView(new ArrayBuffer(8));\n\tvar logLine = [];\n\tconst wasmExit = {}; // thrown to exit via proc_exit (not an error)\n\n\tglobal.Go = class {\n\t\tconstructor() {\n\t\t\tthis._callbackTimeouts = new Map();\n\t\t\tthis._nextCallbackTimeoutID = 1;\n\n\t\t\tconst mem = () => {\n\t\t\t\t// The buffer may change when requesting more memory.\n\t\t\t\treturn new DataView(this._inst.exports.memory.buffer);\n\t\t\t}\n\n\t\t\tconst unboxValue = (v_ref) => {\n\t\t\t\treinterpretBuf.setBigInt64(0, v_ref, true);\n\t\t\t\tconst f = reinterpretBuf.getFloat64(0, true);\n\t\t\t\tif (f === 0) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t\tif (!isNaN(f)) {\n\t\t\t\t\treturn f;\n\t\t\t\t}\n\n\t\t\t\tconst id = v_ref & 0xffffffffn;\n\t\t\t\treturn this._values[id];\n\t\t\t}\n\n\n\t\t\tconst loadValue = (addr) => {\n\t\t\t\tlet v_ref = mem().getBigUint64(addr, true);\n\t\t\t\treturn unboxValue(v_ref);\n\t\t\t}\n\n\t\t\tconst boxValue = (v) => {\n\t\t\t\tconst nanHead = 0x7FF80000n;\n\n\t\t\t\tif (typeof v === \"number\") {\n\t\t\t\t\tif (isNaN(v)) {\n\t\t\t\t\t\treturn nanHead << 32n;\n\t\t\t\t\t}\n\t\t\t\t\tif (v === 0) {\n\t\t\t\t\t\treturn (nanHead << 32n) | 1n;\n\t\t\t\t\t}\n\t\t\t\t\treinterpretBuf.setFloat64(0, v, true);\n\t\t\t\t\treturn reinterpretBuf.getBigInt64(0, true);\n\t\t\t\t}\n\n\t\t\t\tswitch (v) {\n\t\t\t\t\tcase undefined:\n\t\t\t\t\t\treturn 0n;\n\t\t\t\t\tcase null:\n\t\t\t\t\t\treturn (nanHead << 32n) | 2n;\n\t\t\t\t\tcase true:\n\t\t\t\t\t\treturn (nanHead << 32n) | 3n;\n\t\t\t\t\tcase false:\n\t\t\t\t\t\treturn (nanHead << 32n) | 4n;\n\t\t\t\t}\n\n\t\t\t\tlet id = this._ids.get(v);\n\t\t\t\tif (id === undefined) {\n\t\t\t\t\tid = this._idPool.pop();\n\t\t\t\t\tif (id === undefined) {\n\t\t\t\t\t\tid = BigInt(this._values.length);\n\t\t\t\t\t}\n\t\t\t\t\tthis._values[id] = v;\n\t\t\t\t\tthis._goRefCounts[id] = 0;\n\t\t\t\t\tthis._ids.set(v, id);\n\t\t\t\t}\n\t\t\t\tthis._goRefCounts[id]++;\n\t\t\t\tlet typeFlag = 1n;\n\t\t\t\tswitch (typeof v) {\n\t\t\t\t\tcase \"string\":\n\t\t\t\t\t\ttypeFlag = 2n;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"symbol\":\n\t\t\t\t\t\ttypeFlag = 3n;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"function\":\n\t\t\t\t\t\ttypeFlag = 4n;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\treturn id | ((nanHead | typeFlag) << 32n);\n\t\t\t}\n\n\t\t\tconst storeValue = (addr, v) => {\n\t\t\t\tlet v_ref = boxValue(v);\n\t\t\t\tmem().setBigUint64(addr, v_ref, true);\n\t\t\t}\n\n\t\t\tconst loadSlice = (array, len, cap) => {\n\t\t\t\treturn new Uint8Array(this._inst.exports.memory.buffer, array, len);\n\t\t\t}\n\n\t\t\tconst loadSliceOfValues = (array, len, cap) => {\n\t\t\t\tconst a = new Array(len);\n\t\t\t\tfor (let i = 0; i < len; i++) {\n\t\t\t\t\ta[i] = loadValue(array + i * 8);\n\t\t\t\t}\n\t\t\t\treturn a;\n\t\t\t}\n\n\t\t\tconst loadString = (ptr, len) => {\n\t\t\t\treturn decoder.decode(new DataView(this._inst.exports.memory.buffer, ptr, len));\n\t\t\t}\n\n\t\t\tconst timeOrigin = Date.now() - performance.now();\n\t\t\tthis.importObject = {\n\t\t\t\twasi_snapshot_preview1: {\n\t\t\t\t\t// https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#fd_write\n\t\t\t\t\tfd_write: function(fd, iovs_ptr, iovs_len, nwritten_ptr) {\n\t\t\t\t\t\tlet nwritten = 0;\n\t\t\t\t\t\tif (fd == 1) {\n\t\t\t\t\t\t\tfor (let iovs_i=0; iovs_i<iovs_len;iovs_i++) {\n\t\t\t\t\t\t\t\tlet iov_ptr = iovs_ptr+iovs_i*8; // assuming wasm32\n\t\t\t\t\t\t\t\tlet ptr = mem().getUint32(iov_ptr + 0, true);\n\t\t\t\t\t\t\t\tlet len = mem().getUint32(iov_ptr + 4, true);\n\t\t\t\t\t\t\t\tnwritten += len;\n\t\t\t\t\t\t\t\tfor (let i=0; i<len; i++) {\n\t\t\t\t\t\t\t\t\tlet c = mem().getUint8(ptr+i);\n\t\t\t\t\t\t\t\t\tif (c == 13) { // CR\n\t\t\t\t\t\t\t\t\t\t// ignore\n\t\t\t\t\t\t\t\t\t} else if (c == 10) { // LF\n\t\t\t\t\t\t\t\t\t\t// write line\n\t\t\t\t\t\t\t\t\t\tlet line = decoder.decode(new Uint8Array(logLine));\n\t\t\t\t\t\t\t\t\t\tlogLine = [];\n\t\t\t\t\t\t\t\t\t\tconsole.log(line);\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tlogLine.push(c);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconsole.error('invalid file descriptor:', fd);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmem().setUint32(nwritten_ptr, nwritten, true);\n\t\t\t\t\t\treturn 0;\n\t\t\t\t\t},\n\t\t\t\t\tfd_close: () => 0,      // dummy\n\t\t\t\t\tfd_fdstat_get: () => 0, // dummy\n\t\t\t\t\tfd_seek: () => 0,       // dummy\n\t\t\t\t\tproc_exit: (code) => {\n\t\t\t\t\t\tthis.exited = true;\n\t\t\t\t\t\tthis.exitCode = code;\n\t\t\t\t\t\tthis._resolveExitPromise();\n\t\t\t\t\t\tthrow wasmExit;\n\t\t\t\t\t},\n\t\t\t\t\trandom_get: (bufPtr, bufLen) => {\n\t\t\t\t\t\tcrypto.getRandomValues(loadSlice(bufPtr, bufLen));\n\t\t\t\t\t\treturn 0;\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tgojs: {\n\t\t\t\t\t// func ticks() int64\n\t\t\t\t\t\"runtime.ticks\": () => {\n\t\t\t\t\t\treturn BigInt((timeOrigin + performance.now()) * 1e6);\n\t\t\t\t\t},\n\n\t\t\t\t\t// func sleepTicks(timeout int64)\n\t\t\t\t\t\"runtime.sleepTicks\": (timeout) => {\n\t\t\t\t\t\t// Do not sleep, only reactivate scheduler after the given timeout.\n\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\tif (this.exited) return;\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tthis._inst.exports.go_scheduler();\n\t\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t\tif (e !== wasmExit) throw e;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, Number(timeout)/1e6);\n\t\t\t\t\t},\n\n\t\t\t\t\t// func finalizeRef(v ref)\n\t\t\t\t\t\"syscall/js.finalizeRef\": (v_ref) => {\n\t\t\t\t\t\t// Note: TinyGo does not support finalizers so this is only called\n\t\t\t\t\t\t// for one specific case, by js.go:jsString. and can/might leak memory.\n\t\t\t\t\t\tconst id = v_ref & 0xffffffffn;\n\t\t\t\t\t\tif (this._goRefCounts?.[id] !== undefined) {\n\t\t\t\t\t\t\tthis._goRefCounts[id]--;\n\t\t\t\t\t\t\tif (this._goRefCounts[id] === 0) {\n\t\t\t\t\t\t\t\tconst v = this._values[id];\n\t\t\t\t\t\t\t\tthis._values[id] = null;\n\t\t\t\t\t\t\t\tthis._ids.delete(v);\n\t\t\t\t\t\t\t\tthis._idPool.push(id);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconsole.error(\"syscall/js.finalizeRef: unknown id\", id);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\n\t\t\t\t\t// func stringVal(value string) ref\n\t\t\t\t\t\"syscall/js.stringVal\": (value_ptr, value_len) => {\n\t\t\t\t\t\tvalue_ptr >>>= 0;\n\t\t\t\t\t\tconst s = loadString(value_ptr, value_len);\n\t\t\t\t\t\treturn boxValue(s);\n\t\t\t\t\t},\n\n\t\t\t\t\t// func valueGet(v ref, p string) ref\n\t\t\t\t\t\"syscall/js.valueGet\": (v_ref, p_ptr, p_len) => {\n\t\t\t\t\t\tlet prop = loadString(p_ptr, p_len);\n\t\t\t\t\t\tlet v = unboxValue(v_ref);\n\t\t\t\t\t\tlet result = Reflect.get(v, prop);\n\t\t\t\t\t\treturn boxValue(result);\n\t\t\t\t\t},\n\n\t\t\t\t\t// func valueSet(v ref, p string, x ref)\n\t\t\t\t\t\"syscall/js.valueSet\": (v_ref, p_ptr, p_len, x_ref) => {\n\t\t\t\t\t\tconst v = unboxValue(v_ref);\n\t\t\t\t\t\tconst p = loadString(p_ptr, p_len);\n\t\t\t\t\t\tconst x = unboxValue(x_ref);\n\t\t\t\t\t\tReflect.set(v, p, x);\n\t\t\t\t\t},\n\n\t\t\t\t\t// func valueDelete(v ref, p string)\n\t\t\t\t\t\"syscall/js.valueDelete\": (v_ref, p_ptr, p_len) => {\n\t\t\t\t\t\tconst v = unboxValue(v_ref);\n\t\t\t\t\t\tconst p = loadString(p_ptr, p_len);\n\t\t\t\t\t\tReflect.deleteProperty(v, p);\n\t\t\t\t\t},\n\n\t\t\t\t\t// func valueIndex(v ref, i int) ref\n\t\t\t\t\t\"syscall/js.valueIndex\": (v_ref, i) => {\n\t\t\t\t\t\treturn boxValue(Reflect.get(unboxValue(v_ref), i));\n\t\t\t\t\t},\n\n\t\t\t\t\t// valueSetIndex(v ref, i int, x ref)\n\t\t\t\t\t\"syscall/js.valueSetIndex\": (v_ref, i, x_ref) => {\n\t\t\t\t\t\tReflect.set(unboxValue(v_ref), i, unboxValue(x_ref));\n\t\t\t\t\t},\n\n\t\t\t\t\t// func valueCall(v ref, m string, args []ref) (ref, bool)\n\t\t\t\t\t\"syscall/js.valueCall\": (ret_addr, v_ref, m_ptr, m_len, args_ptr, args_len, args_cap) => {\n\t\t\t\t\t\tconst v = unboxValue(v_ref);\n\t\t\t\t\t\tconst name = loadString(m_ptr, m_len);\n\t\t\t\t\t\tconst args = loadSliceOfValues(args_ptr, args_len, args_cap);\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst m = Reflect.get(v, name);\n\t\t\t\t\t\t\tstoreValue(ret_addr, Reflect.apply(m, v, args));\n\t\t\t\t\t\t\tmem().setUint8(ret_addr + 8, 1);\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\tstoreValue(ret_addr, err);\n\t\t\t\t\t\t\tmem().setUint8(ret_addr + 8, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\n\t\t\t\t\t// func valueInvoke(v ref, args []ref) (ref, bool)\n\t\t\t\t\t\"syscall/js.valueInvoke\": (ret_addr, v_ref, args_ptr, args_len, args_cap) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst v = unboxValue(v_ref);\n\t\t\t\t\t\t\tconst args = loadSliceOfValues(args_ptr, args_len, args_cap);\n\t\t\t\t\t\t\tstoreValue(ret_addr, Reflect.apply(v, undefined, args));\n\t\t\t\t\t\t\tmem().setUint8(ret_addr + 8, 1);\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\tstoreValue(ret_addr, err);\n\t\t\t\t\t\t\tmem().setUint8(ret_addr + 8, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\n\t\t\t\t\t// func valueNew(v ref, args []ref) (ref, bool)\n\t\t\t\t\t\"syscall/js.valueNew\": (ret_addr, v_ref, args_ptr, args_len, args_cap) => {\n\t\t\t\t\t\tconst v = unboxValue(v_ref);\n\t\t\t\t\t\tconst args = loadSliceOfValues(args_ptr, args_len, args_cap);\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tstoreValue(ret_addr, Reflect.construct(v, args));\n\t\t\t\t\t\t\tmem().setUint8(ret_addr + 8, 1);\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\tstoreValue(ret_addr, err);\n\t\t\t\t\t\t\tmem().setUint8(ret_addr+ 8, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\n\t\t\t\t\t// func valueLength(v ref) int\n\t\t\t\t\t\"syscall/js.valueLength\": (v_ref) => {\n\t\t\t\t\t\treturn unboxValue(v_ref).length;\n\t\t\t\t\t},\n\n\t\t\t\t\t// valuePrepareString(v ref) (ref, int)\n\t\t\t\t\t\"syscall/js.valuePrepareString\": (ret_addr, v_ref) => {\n\t\t\t\t\t\tconst s = String(unboxValue(v_ref));\n\t\t\t\t\t\tconst str = encoder.encode(s);\n\t\t\t\t\t\tstoreValue(ret_addr, str);\n\t\t\t\t\t\tmem().setInt32(ret_addr + 8, str.length, true);\n\t\t\t\t\t},\n\n\t\t\t\t\t// valueLoadString(v ref, b []byte)\n\t\t\t\t\t\"syscall/js.valueLoadString\": (v_ref, slice_ptr, slice_len, slice_cap) => {\n\t\t\t\t\t\tconst str = unboxValue(v_ref);\n\t\t\t\t\t\tloadSlice(slice_ptr, slice_len, slice_cap).set(str);\n\t\t\t\t\t},\n\n\t\t\t\t\t// func valueInstanceOf(v ref, t ref) bool\n\t\t\t\t\t\"syscall/js.valueInstanceOf\": (v_ref, t_ref) => {\n \t\t\t\t\t\treturn unboxValue(v_ref) instanceof unboxValue(t_ref);\n\t\t\t\t\t},\n\n\t\t\t\t\t// func copyBytesToGo(dst []byte, src ref) (int, bool)\n\t\t\t\t\t\"syscall/js.copyBytesToGo\": (ret_addr, dest_addr, dest_len, dest_cap, src_ref) => {\n\t\t\t\t\t\tlet num_bytes_copied_addr = ret_addr;\n\t\t\t\t\t\tlet returned_status_addr = ret_addr + 4; // Address of returned boolean status variable\n\n\t\t\t\t\t\tconst dst = loadSlice(dest_addr, dest_len);\n\t\t\t\t\t\tconst src = unboxValue(src_ref);\n\t\t\t\t\t\tif (!(src instanceof Uint8Array || src instanceof Uint8ClampedArray)) {\n\t\t\t\t\t\t\tmem().setUint8(returned_status_addr, 0); // Return \"not ok\" status\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst toCopy = src.subarray(0, dst.length);\n\t\t\t\t\t\tdst.set(toCopy);\n\t\t\t\t\t\tmem().setUint32(num_bytes_copied_addr, toCopy.length, true);\n\t\t\t\t\t\tmem().setUint8(returned_status_addr, 1); // Return \"ok\" status\n\t\t\t\t\t},\n\n\t\t\t\t\t// copyBytesToJS(dst ref, src []byte) (int, bool)\n\t\t\t\t\t// Originally copied from upstream Go project, then modified:\n\t\t\t\t\t//   https://github.com/golang/go/blob/3f995c3f3b43033013013e6c7ccc93a9b1411ca9/misc/wasm/wasm_exec.js#L404-L416\n\t\t\t\t\t\"syscall/js.copyBytesToJS\": (ret_addr, dst_ref, src_addr, src_len, src_cap) => {\n\t\t\t\t\t\tlet num_bytes_copied_addr = ret_addr;\n\t\t\t\t\t\tlet returned_status_addr = ret_addr + 4; // Address of returned boolean status variable\n\n\t\t\t\t\t\tconst dst = unboxValue(dst_ref);\n\t\t\t\t\t\tconst src = loadSlice(src_addr, src_len);\n\t\t\t\t\t\tif (!(dst instanceof Uint8Array || dst instanceof Uint8ClampedArray)) {\n\t\t\t\t\t\t\tmem().setUint8(returned_status_addr, 0); // Return \"not ok\" status\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst toCopy = src.subarray(0, dst.length);\n\t\t\t\t\t\tdst.set(toCopy);\n\t\t\t\t\t\tmem().setUint32(num_bytes_copied_addr, toCopy.length, true);\n\t\t\t\t\t\tmem().setUint8(returned_status_addr, 1); // Return \"ok\" status\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// Go 1.20 uses 'env'. Go 1.21 uses 'gojs'.\n\t\t\t// For compatibility, we use both as long as Go 1.20 is supported.\n\t\t\tthis.importObject.env = this.importObject.gojs;\n\t\t}\n\n\t\tasync run(instance) {\n\t\t\tthis._inst = instance;\n\t\t\tthis._values = [ // JS values that Go currently has references to, indexed by reference id\n\t\t\t\tNaN,\n\t\t\t\t0,\n\t\t\t\tnull,\n\t\t\t\ttrue,\n\t\t\t\tfalse,\n\t\t\t\tglobal,\n\t\t\t\tthis,\n\t\t\t];\n\t\t\tthis._goRefCounts = []; // number of references that Go has to a JS value, indexed by reference id\n\t\t\tthis._ids = new Map();  // mapping from JS values to reference ids\n\t\t\tthis._idPool = [];      // unused ids that have been garbage collected\n\t\t\tthis.exited = false;    // whether the Go program has exited\n\t\t\tthis.exitCode = 0;\n\n\t\t\tif (this._inst.exports._start) {\n\t\t\t\tlet exitPromise = new Promise((resolve, reject) => {\n\t\t\t\t\tthis._resolveExitPromise = resolve;\n\t\t\t\t});\n\n\t\t\t\t// Run program, but catch the wasmExit exception that's thrown\n\t\t\t\t// to return back here.\n\t\t\t\ttry {\n\t\t\t\t\tthis._inst.exports._start();\n\t\t\t\t} catch (e) {\n\t\t\t\t\tif (e !== wasmExit) throw e;\n\t\t\t\t}\n\n\t\t\t\tawait exitPromise;\n\t\t\t\treturn this.exitCode;\n\t\t\t} else {\n\t\t\t\tthis._inst.exports._initialize();\n\t\t\t}\n\t\t}\n\n\t\t_resume() {\n\t\t\tif (this.exited) {\n\t\t\t\tthrow new Error(\"Go program has already exited\");\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tthis._inst.exports.resume();\n\t\t\t} catch (e) {\n\t\t\t\tif (e !== wasmExit) throw e;\n\t\t\t}\n\t\t\tif (this.exited) {\n\t\t\t\tthis._resolveExitPromise();\n\t\t\t}\n\t\t}\n\n\t\t_makeFuncWrapper(id) {\n\t\t\tconst go = this;\n\t\t\treturn function () {\n\t\t\t\tconst event = { id: id, this: this, args: arguments };\n\t\t\t\tgo._pendingEvent = event;\n\t\t\t\tgo._resume();\n\t\t\t\treturn event.result;\n\t\t\t};\n\t\t}\n\t}\n\n\tif (\n\t\tglobal.require &&\n\t\tglobal.require.main === module &&\n\t\tglobal.process &&\n\t\tglobal.process.versions &&\n\t\t!global.process.versions.electron\n\t) {\n\t\tif (process.argv.length != 3) {\n\t\t\tconsole.error(\"usage: go_js_wasm_exec [wasm binary] [arguments]\");\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconst go = new Go();\n\t\tWebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then(async (result) => {\n\t\t\tlet exitCode = await go.run(result.instance);\n\t\t\tprocess.exit(exitCode);\n\t\t}).catch((err) => {\n\t\t\tconsole.error(err);\n\t\t\tprocess.exit(1);\n\t\t});\n\t}\n})();\n"
  },
  {
    "path": "targets/waveshare-rp2040-tiny.json",
    "content": "{\n    \"inherits\": [\n        \"rp2040\"\n    ],\n    \"serial-port\": [\"2e8a:0003\"],\n    \"default-stack-size\": 8192,\n    \"build-tags\": [\"waveshare_rp2040_tiny\"],\n    \"ldflags\": [\n        \"--defsym=__flash_size=1020K\"\n    ],\n    \"extra-files\": [\n        \"targets/pico-boot-stage2.S\"\n    ]\n}\n"
  },
  {
    "path": "targets/waveshare-rp2040-zero.json",
    "content": "{\n    \"inherits\": [\n        \"rp2040\"\n    ],\n    \"serial-port\": [\"2e8a:0003\"],\n    \"default-stack-size\": 8192,\n    \"build-tags\": [\"waveshare_rp2040_zero\"],\n    \"ldflags\": [\n        \"--defsym=__flash_size=1020K\"\n    ],\n    \"extra-files\": [\n        \"targets/pico-boot-stage2.S\"\n    ]\n}\n"
  },
  {
    "path": "targets/wioterminal.json",
    "content": "{\n    \"inherits\": [\"atsamd51p19a\"],\n    \"build-tags\": [\"wioterminal\"],\n    \"serial\": \"usb\",\n    \"serial-port\": [\"2886:802d\"],\n    \"flash-1200-bps-reset\": \"true\",\n    \"flash-method\": \"msd\",\n    \"msd-volume-name\": [\"Arduino\"],\n    \"msd-firmware-name\": \"firmware.uf2\",\n    \"openocd-verify\": true\n}\n"
  },
  {
    "path": "targets/x9pro.json",
    "content": "{\n\t\"inherits\": [\"nrf52\"],\n\t\"build-tags\": [\"x9pro\"],\n\t\"serial\": \"uart\",\n\t\"flash-method\": \"openocd\",\n\t\"flash-command\": \"nrfjprog -f nrf52 --sectorerase --program {hex} --reset\",\n\t\"openocd-interface\": \"jlink\",\n\t\"openocd-transport\": \"swd\"\n}\n"
  },
  {
    "path": "targets/xiao-ble.json",
    "content": "{\n\t\"inherits\": [\"nrf52840\", \"nrf52840-s140v7-uf2\"],\n\t\"build-tags\": [\"xiao_ble\"],\n\t\"serial-port\": [\"2886:8045\"],\n\t\"msd-volume-name\": [\"XIAO-SENSE\"]\n}\n"
  },
  {
    "path": "targets/xiao-esp32c3.json",
    "content": "{\n\t\"inherits\": [\"esp32c3\"],\n\t\"build-tags\": [\"xiao_esp32c3\"]\n}\n"
  },
  {
    "path": "targets/xiao-esp32s3.json",
    "content": "{\n\t\"inherits\": [\"esp32s3\"],\n\t\"build-tags\": [\"xiao_esp32s3\"]\n}\n"
  },
  {
    "path": "targets/xiao-rp2040.json",
    "content": "{\n    \"inherits\": [\n        \"rp2040\"\n    ],\n    \"serial-port\": [\"2e8a:000a\"],\n    \"default-stack-size\": 8192,\n    \"build-tags\": [\"xiao_rp2040\"],\n    \"ldflags\": [\n        \"--defsym=__flash_size=1020K\"\n    ],\n    \"extra-files\": [\n        \"targets/pico-boot-stage2.S\"\n    ]\n}\n"
  },
  {
    "path": "targets/xiao.json",
    "content": "{\n    \"inherits\": [\"atsamd21g18a\"],\n    \"build-tags\": [\"xiao\"],\n    \"serial\": \"usb\",\n    \"serial-port\": [\"2886:802f\"],\n    \"flash-1200-bps-reset\": \"true\",\n    \"flash-method\": \"msd\",\n    \"msd-volume-name\": [\"Arduino\",\"Seeed XIAO\"],\n    \"msd-firmware-name\": \"firmware.uf2\"\n}\n"
  },
  {
    "path": "targets/xtensa.json",
    "content": "{\n\t\"llvm-target\": \"xtensa\",\n\t\"goos\": \"linux\",\n\t\"goarch\": \"arm\",\n\t\"build-tags\": [\"xtensa\", \"baremetal\", \"linux\", \"arm\"],\n\t\"gc\": \"conservative\",\n\t\"scheduler\": \"none\",\n\t\"cflags\": [\n\t\t\"-Werror\",\n\t\t\"-fshort-enums\",\n\t\t\"-Wno-macro-redefined\",\n\t\t\"-fno-exceptions\", \"-fno-unwind-tables\", \"-fno-asynchronous-unwind-tables\",\n\t\t\"-ffunction-sections\", \"-fdata-sections\"\n\t],\n\t\"ldflags\": [\n\t\t\"--gc-sections\"\n\t]\n}\n"
  },
  {
    "path": "testdata/alias.go",
    "content": "package main\n\ntype x struct{}\n\nfunc (x x) name() string {\n\treturn \"x\"\n}\n\ntype y = x\n\ntype a struct {\n\tn int\n}\n\nfunc (a a) fruit() string {\n\treturn \"apple\"\n}\n\ntype b = a\n\ntype fruit interface {\n\tfruit() string\n}\n\ntype f = fruit\n\nfunc main() {\n\t// test a basic alias\n\tprintln(y{}.name())\n\n\t// test using a type alias value as an interface\n\tvar v f = b{}\n\tprintln(v.fruit())\n\n\t// test comparing an alias interface with the referred-to type\n\tprintln(a{} == b{})\n\tprintln(a{2} == b{3})\n}\n"
  },
  {
    "path": "testdata/alias.txt",
    "content": "x\napple\ntrue\nfalse\n"
  },
  {
    "path": "testdata/atomic.go",
    "content": "package main\n\nimport (\n\t\"sync/atomic\"\n\t\"unsafe\"\n\n\t\"runtime/volatile\"\n)\n\nfunc main() {\n\ti32 := int32(-5)\n\tprintln(\"AddInt32:\", atomic.AddInt32(&i32, 8), i32)\n\n\ti64 := int64(-5)\n\tprintln(\"AddInt64:\", atomic.AddInt64(&i64, 8), i64)\n\n\tu32 := uint32(5)\n\tprintln(\"AddUint32:\", atomic.AddUint32(&u32, 8), u32)\n\n\tu64 := uint64(5)\n\tprintln(\"AddUint64:\", atomic.AddUint64(&u64, 8), u64)\n\n\tuptr := uintptr(5)\n\tprintln(\"AddUintptr:\", uint64(atomic.AddUintptr(&uptr, 8)), uint64(uptr))\n\n\tprintln(\"SwapInt32:\", atomic.SwapInt32(&i32, 33), i32)\n\tprintln(\"SwapInt64:\", atomic.SwapInt64(&i64, 33), i64)\n\tprintln(\"SwapUint32:\", atomic.SwapUint32(&u32, 33), u32)\n\tprintln(\"SwapUint64:\", atomic.SwapUint64(&u64, 33), u64)\n\tprintln(\"SwapUintptr:\", uint64(atomic.SwapUintptr(&uptr, 33)), uint64(uptr))\n\tptr := unsafe.Pointer(&i32)\n\tprintln(\"SwapPointer:\", atomic.SwapPointer(&ptr, unsafe.Pointer(&u32)) == unsafe.Pointer(&i32), ptr == unsafe.Pointer(&u32))\n\n\ti32 = int32(-5)\n\tprintln(\"CompareAndSwapInt32:\", atomic.CompareAndSwapInt32(&i32, 5, 3), i32)\n\tprintln(\"CompareAndSwapInt32:\", atomic.CompareAndSwapInt32(&i32, -5, 3), i32)\n\n\ti64 = int64(-5)\n\tprintln(\"CompareAndSwapInt64:\", atomic.CompareAndSwapInt64(&i64, 5, 3), i64)\n\tprintln(\"CompareAndSwapInt64:\", atomic.CompareAndSwapInt64(&i64, -5, 3), i64)\n\n\tu32 = uint32(5)\n\tprintln(\"CompareAndSwapUint32:\", atomic.CompareAndSwapUint32(&u32, 4, 3), u32)\n\tprintln(\"CompareAndSwapUint32:\", atomic.CompareAndSwapUint32(&u32, 5, 3), u32)\n\n\tu64 = uint64(5)\n\tprintln(\"CompareAndSwapUint64:\", atomic.CompareAndSwapUint64(&u64, 4, 3), u64)\n\tprintln(\"CompareAndSwapUint64:\", atomic.CompareAndSwapUint64(&u64, 5, 3), u64)\n\n\tuptr = uintptr(5)\n\tprintln(\"CompareAndSwapUintptr:\", atomic.CompareAndSwapUintptr(&uptr, 4, 3), uint64(uptr))\n\tprintln(\"CompareAndSwapUintptr:\", atomic.CompareAndSwapUintptr(&uptr, 5, 3), uint64(uptr))\n\n\tptr = unsafe.Pointer(&i32)\n\tprintln(\"CompareAndSwapPointer:\", atomic.CompareAndSwapPointer(&ptr, unsafe.Pointer(&u32), unsafe.Pointer(&i64)), ptr == unsafe.Pointer(&i32))\n\tprintln(\"CompareAndSwapPointer:\", atomic.CompareAndSwapPointer(&ptr, unsafe.Pointer(&i32), unsafe.Pointer(&i64)), ptr == unsafe.Pointer(&i64))\n\n\tprintln(\"LoadInt32:\", atomic.LoadInt32(&i32))\n\tprintln(\"LoadInt64:\", atomic.LoadInt64(&i64))\n\tprintln(\"LoadUint32:\", atomic.LoadUint32(&u32))\n\tprintln(\"LoadUint64:\", atomic.LoadUint64(&u64))\n\tprintln(\"LoadUintptr:\", uint64(atomic.LoadUintptr(&uptr)))\n\tprintln(\"LoadPointer:\", atomic.LoadPointer(&ptr) == unsafe.Pointer(&i64))\n\n\tatomic.StoreInt32(&i32, -20)\n\tprintln(\"StoreInt32:\", i32)\n\n\tatomic.StoreInt64(&i64, -20)\n\tprintln(\"StoreInt64:\", i64)\n\n\tatomic.StoreUint32(&u32, 20)\n\tprintln(\"StoreUint32:\", u32)\n\n\tatomic.StoreUint64(&u64, 20)\n\tprintln(\"StoreUint64:\", u64)\n\n\tatomic.StoreUintptr(&uptr, 20)\n\tprintln(\"StoreUintptr:\", uint64(uptr))\n\n\tatomic.StorePointer(&ptr, unsafe.Pointer(&uptr))\n\tprintln(\"StorePointer:\", ptr == unsafe.Pointer(&uptr))\n\n\t// test atomic.Value load/store operations\n\ttestValue(int(3), int(-2))\n\ttestValue(\"\", \"foobar\", \"baz\")\n\n\t// Test atomic and volatile operations as deferred values.\n\ttestDefer()\n}\n\nfunc testValue(values ...interface{}) {\n\tvar av atomic.Value\n\tfor _, val := range values {\n\t\tav.Store(val)\n\t\tloadedVal := av.Load()\n\t\tif loadedVal != val {\n\t\t\tprintln(\"val store/load didn't work, expected\", val, \"but got\", loadedVal)\n\t\t}\n\t}\n}\n\nfunc testDefer() {\n\tn1 := int32(5)\n\tn2 := uint32(6)\n\tdefer func() {\n\t\tprintln(\"deferred atomic add:\", n1)\n\t\tprintln(\"deferred volatile store:\", n2)\n\t}()\n\tdefer atomic.AddInt32(&n1, 3)\n\tdefer volatile.StoreUint32(&n2, 22)\n}\n"
  },
  {
    "path": "testdata/atomic.txt",
    "content": "AddInt32: 3 3\nAddInt64: 3 3\nAddUint32: 13 13\nAddUint64: 13 13\nAddUintptr: 13 13\nSwapInt32: 3 33\nSwapInt64: 3 33\nSwapUint32: 13 33\nSwapUint64: 13 33\nSwapUintptr: 13 33\nSwapPointer: true true\nCompareAndSwapInt32: false -5\nCompareAndSwapInt32: true 3\nCompareAndSwapInt64: false -5\nCompareAndSwapInt64: true 3\nCompareAndSwapUint32: false 5\nCompareAndSwapUint32: true 3\nCompareAndSwapUint64: false 5\nCompareAndSwapUint64: true 3\nCompareAndSwapUintptr: false 5\nCompareAndSwapUintptr: true 3\nCompareAndSwapPointer: false true\nCompareAndSwapPointer: true true\nLoadInt32: 3\nLoadInt64: 3\nLoadUint32: 3\nLoadUint64: 3\nLoadUintptr: 3\nLoadPointer: true\nStoreInt32: -20\nStoreInt64: -20\nStoreUint32: 20\nStoreUint64: 20\nStoreUintptr: 20\nStorePointer: true\ndeferred atomic add: 8\ndeferred volatile store: 22\n"
  },
  {
    "path": "testdata/binop.go",
    "content": "package main\n\nfunc main() {\n\tprintln(\"string equality\")\n\tprintln(a == \"a\")\n\tprintln(a == \"b\")\n\tprintln(a != \"a\")\n\tprintln(a != \"b\")\n\tprintln(\"string inequality\")\n\tprintln(a > \"b\")\n\tprintln(\"b\" > a)\n\tprintln(\"b\" > \"b\")\n\tprintln(a <= \"b\")\n\tprintln(\"b\" <= a)\n\tprintln(\"b\" <= \"b\")\n\tprintln(a > \"b\")\n\tprintln(\"b\" > a)\n\tprintln(\"b\" > \"b\")\n\tprintln(a <= \"b\")\n\tprintln(\"b\" <= a)\n\tprintln(\"b\" <= \"b\")\n\tprintln(a < \"aa\")\n\tprintln(\"aa\" < a)\n\tprintln(\"ab\" < \"aa\")\n\tprintln(\"aa\" < \"ab\")\n\n\th := \"hello\"\n\tprintln(\"h < h\", h < h)\n\tprintln(\"h <= h\", h <= h)\n\tprintln(\"h == h\", h == h)\n\tprintln(\"h >= h\", h >= h)\n\tprintln(\"h > h\", h > h)\n\n\tprintln(\"array equality\")\n\tprintln(a1 == [2]int{1, 2})\n\tprintln(a1 != [2]int{1, 2})\n\tprintln(a1 == [2]int{1, 3})\n\tprintln(a1 == [2]int{2, 2})\n\tprintln(a1 == [2]int{2, 1})\n\tprintln(a1 != [2]int{2, 1})\n\n\tprintln(\"struct equality\")\n\tprintln(s1 == Struct1{3, true})\n\tprintln(s1 == Struct1{4, true})\n\tprintln(s1 == Struct1{3, false})\n\tprintln(s1 == Struct1{4, false})\n\tprintln(s1 != Struct1{3, true})\n\tprintln(s1 != Struct1{4, true})\n\tprintln(s1 != Struct1{3, false})\n\tprintln(s1 != Struct1{4, false})\n\n\tprintln(\"blank fields in structs\")\n\tprintln(s2 == Struct2{\"foo\", 0.0, 5})\n\tprintln(s2 == Struct2{\"foo\", 0.0, 7})\n\tprintln(s2 == Struct2{\"foo\", 1.0, 5})\n\tprintln(s2 == Struct2{\"foo\", 1.0, 7})\n\n\tprintln(\"complex numbers\")\n\tprintln(c64 == 3+2i)\n\tprintln(c64 == 4+2i)\n\tprintln(c64 == 3+3i)\n\tprintln(c64 != 3+2i)\n\tprintln(c64 != 4+2i)\n\tprintln(c64 != 3+3i)\n\tprintln(c128 == 3+2i)\n\tprintln(c128 == 4+2i)\n\tprintln(c128 == 3+3i)\n\tprintln(c128 != 3+2i)\n\tprintln(c128 != 4+2i)\n\tprintln(c128 != 3+3i)\n\n\tprintln(\"shifts\")\n\tprintln(shlSimple == 4)\n\tprintln(shlOverflow == 0)\n\tprintln(shrSimple == 1)\n\tprintln(shrOverflow == 0)\n\tprintln(ashrNeg == -1)\n\tprintln(ashrOverflow == 0)\n\tprintln(ashrNegOverflow == -1)\n\n\t// fix for a bug in constant numbers\n\tprintln(\"constant number\")\n\tx := uint32(5)\n\tprintln(uint32(x) / (20e0 / 1))\n\n\t// check for signed integer overflow\n\tprintln(\"-2147483648 / -1:\", sdiv32(-2147483648, -1))\n\tprintln(\"-2147483648 % -1:\", srem32(-2147483648, -1))\n\n\ttype foo struct {\n\t\tn   int\n\t\titf interface{}\n\t}\n\n\tvar a interface{} = foo{3, float32(5)}\n\tvar b interface{} = foo{3, float32(3)}\n\tvar b2 interface{} = foo{3, float32(3)}\n\tprintln(\"interface equality\")\n\tprintln(\"a==b\", a == b)\n\tprintln(\"b==b2\", b == b2)\n}\n\nvar x = true\nvar y = false\n\nvar a = \"a\"\nvar s1 = Struct1{3, true}\nvar s2 = Struct2{\"foo\", 0.0, 5}\n\nvar a1 = [2]int{1, 2}\n\nvar c64 = 3 + 2i\nvar c128 = 4 + 3i\n\ntype Int int\n\ntype Struct1 struct {\n\ti Int\n\tb bool\n}\n\ntype Struct2 struct {\n\ts string\n\t_ float64\n\ti int\n}\n\nfunc shl(x uint, y uint) uint {\n\treturn x << y\n}\n\nfunc shr(x uint, y uint) uint {\n\treturn x >> y\n}\n\nfunc ashr(x int, y uint) int {\n\treturn x >> y\n}\n\nfunc sdiv32(x, y int32) int32 {\n\treturn x / y\n}\n\nfunc srem32(x, y int32) int32 {\n\treturn x % y\n}\n\nvar shlSimple = shl(2, 1)\nvar shlOverflow = shl(2, 1000)\nvar shrSimple = shr(2, 1)\nvar shrOverflow = shr(2, 1000000)\nvar ashrNeg = ashr(-1, 1)\nvar ashrOverflow = ashr(1, 1000000)\nvar ashrNegOverflow = ashr(-1, 1000000)\n"
  },
  {
    "path": "testdata/binop.txt",
    "content": "string equality\ntrue\nfalse\nfalse\ntrue\nstring inequality\nfalse\ntrue\nfalse\ntrue\nfalse\ntrue\nfalse\ntrue\nfalse\ntrue\nfalse\ntrue\ntrue\nfalse\nfalse\ntrue\nh < h false\nh <= h true\nh == h true\nh >= h true\nh > h false\narray equality\ntrue\nfalse\nfalse\nfalse\nfalse\ntrue\nstruct equality\ntrue\nfalse\nfalse\nfalse\nfalse\ntrue\ntrue\ntrue\nblank fields in structs\ntrue\nfalse\ntrue\nfalse\ncomplex numbers\ntrue\nfalse\nfalse\nfalse\ntrue\ntrue\nfalse\nfalse\nfalse\ntrue\ntrue\ntrue\nshifts\ntrue\ntrue\ntrue\ntrue\ntrue\ntrue\ntrue\nconstant number\n0\n-2147483648 / -1: -2147483648\n-2147483648 % -1: 0\ninterface equality\na==b false\nb==b2 true\n"
  },
  {
    "path": "testdata/calls.go",
    "content": "package main\n\ntype Thing struct {\n\tname string\n}\n\ntype ThingOption func(*Thing)\n\nfunc WithName(name string) ThingOption {\n\treturn func(t *Thing) {\n\t\tt.name = name\n\t}\n}\n\nfunc NewThing(opts ...ThingOption) *Thing {\n\tt := &Thing{}\n\tfor _, opt := range opts {\n\t\topt(t)\n\t}\n\treturn t\n}\n\nfunc (t Thing) String() string {\n\treturn t.name\n}\n\nfunc (t Thing) Print(arg string) {\n\tprintln(\"Thing.Print:\", t.name, \"arg:\", arg)\n}\n\ntype Printer interface {\n\tPrint(string)\n}\n\nfunc main() {\n\tthing := &Thing{\"foo\"}\n\n\t// function pointers\n\trunFunc(hello, 5) // must be indirect to avoid obvious inlining\n\n\t// deferred functions\n\ttestDefer()\n\n\t// defers in loop\n\ttestDeferLoop()\n\n\t//defer func variable call\n\ttestDeferFuncVar()\n\n\t//More complicated func variable call\n\ttestMultiFuncVar()\n\n\t// Take a bound method and use it as a function pointer.\n\t// This function pointer needs a context pointer.\n\ttestBound(thing.String)\n\n\t// closures\n\tfunc() {\n\t\tprintln(\"thing inside closure:\", thing.String())\n\t}()\n\trunFunc(func(i int) {\n\t\tprintln(\"inside fp closure:\", thing.String(), i)\n\t}, 3)\n\n\t// functional arguments\n\tthingFunctionalArgs1 := NewThing()\n\tthingFunctionalArgs1.Print(\"functional args 1\")\n\tthingFunctionalArgs2 := NewThing(WithName(\"named thing\"))\n\tthingFunctionalArgs2.Print(\"functional args 2\")\n\n\t// regression testing\n\tregression1033()\n\n\t//Test deferred builtins\n\ttestDeferBuiltinClose()\n\ttestDeferBuiltinDelete()\n\n\t// Check for issue 1304.\n\t// There are two fields in this struct, one of which is zero-length so the\n\t// other covers the entire struct. This led to a verification error for\n\t// debug info, which used DW_OP_LLVM_fragment for a field that practically\n\t// covered the entire variable.\n\tvar x issue1304\n\tx.call()\n\n\tif testDeferElse(false) != 0 {\n\t\tprintln(\"else defer returned wrong value\")\n\t}\n}\n\nfunc runFunc(f func(int), arg int) {\n\tf(arg)\n}\n\nfunc hello(n int) {\n\tprintln(\"hello from function pointer:\", n)\n}\n\nfunc testDefer() {\n\tdefer exportedDefer()\n\n\ti := 1\n\tdefer deferred(\"...run as defer\", i)\n\ti++\n\tdefer func() {\n\t\tprintln(\"...run closure deferred:\", i)\n\t}()\n\ti++\n\tdefer deferred(\"...run as defer\", i)\n\ti++\n\n\tvar t Printer = &Thing{\"foo\"}\n\tdefer t.Print(\"bar\")\n\n\tprintln(\"deferring...\")\n\td := dumb{}\n\tdefer d.Value(0)\n}\n\nfunc testDeferLoop() {\n\tfor j := 0; j < 4; j++ {\n\t\tdefer deferred(\"loop\", j)\n\t}\n}\n\nfunc testDeferFuncVar() {\n\tdummy, f := deferFunc()\n\tdummy++\n\tdefer f(1)\n}\n\nfunc testMultiFuncVar() {\n\tf := multiFuncDefer()\n\tdefer f(1)\n}\n\nfunc testDeferBuiltinClose() {\n\ti := make(chan int)\n\tfunc() {\n\t\tdefer close(i)\n\t}()\n\tif n, ok := <-i; n != 0 || ok {\n\t\tprintln(\"expected to read 0 from closed channel\")\n\t}\n}\n\nfunc testDeferBuiltinDelete() {\n\tm := map[int]int{3: 30, 5: 50}\n\tfunc() {\n\t\tdefer delete(m, 3)\n\t\tif m[3] != 30 {\n\t\t\tprintln(\"expected m[3] to be 30\")\n\t\t}\n\t}()\n\tif m[3] != 0 {\n\t\tprintln(\"expected m[3] to be 0\")\n\t}\n}\n\ntype dumb struct {\n}\n\nfunc (*dumb) Value(key interface{}) interface{} {\n\treturn nil\n}\n\nfunc deferred(msg string, i int) {\n\tprintln(msg, i)\n}\n\n//export __exportedDefer\nfunc exportedDefer() {\n\tprintln(\"...exported defer\")\n}\n\nfunc deferFunc() (int, func(int)) {\n\treturn 0, func(i int) { println(\"...extracted defer func \", i) }\n}\n\nfunc multiFuncDefer() func(int) {\n\ti := 0\n\n\tif i > 0 {\n\t\treturn func(i int) { println(\"Should not have gotten here. i = \", i) }\n\t}\n\n\treturn func(i int) { println(\"Called the correct function. i = \", i) }\n}\n\nfunc testBound(f func() string) {\n\tprintln(\"bound method:\", f())\n}\n\n// regression1033 is a regression test for https://github.com/tinygo-org/tinygo/issues/1033.\n// In previous versions of the compiler, a deferred call to an interface would create an instruction that did not dominate its uses.\nfunc regression1033() {\n\tfoo(&Bar{})\n}\n\ntype Bar struct {\n\tempty bool\n}\n\nfunc (b *Bar) Close() error {\n\treturn nil\n}\n\ntype Closer interface {\n\tClose() error\n}\n\nfunc foo(bar *Bar) error {\n\tvar a int\n\tif !bar.empty {\n\t\ta = 10\n\t\tif a != 5 {\n\t\t\treturn nil\n\t\t}\n\t}\n\n\tvar c Closer = bar\n\tdefer c.Close()\n\n\treturn nil\n}\n\ntype issue1304 struct {\n\ta [0]int // zero-length field\n\tb int    // field 'b' covers entire struct\n}\n\nfunc (x issue1304) call() {\n\t// nothing to do\n}\n\ntype recursiveFuncType func(recursiveFuncType)\n\nvar recursiveFunction recursiveFuncType\n\n//go:noinline\nfunc testDeferElse(b bool) (r int) {\n\tif !b {\n\t\tdefer func() {\n\t\t\tr = 0\n\n\t\t}()\n\t}\n\n\treturn 1\n}\n"
  },
  {
    "path": "testdata/calls.txt",
    "content": "hello from function pointer: 5\ndeferring...\nThing.Print: foo arg: bar\n...run as defer 3\n...run closure deferred: 4\n...run as defer 1\n...exported defer\nloop 3\nloop 2\nloop 1\nloop 0\n...extracted defer func  1\nCalled the correct function. i =  1\nbound method: foo\nthing inside closure: foo\ninside fp closure: foo 3\nThing.Print:  arg: functional args 1\nThing.Print: named thing arg: functional args 2\n"
  },
  {
    "path": "testdata/cgo/extra.go",
    "content": "package main\n\n// Make sure CGo supports multiple files.\n\n// #include \"test.h\"\n// int fortytwo(void);\n// static float headerfunc_static(float a) { return a - 1; }\n// static void headerfunc_void(int a, int *ptr) { *ptr = a; }\nimport \"C\"\n\nfunc headerfunc_2() {\n\t// Call headerfunc_static that is different from the headerfunc_static in\n\t// the main.go file.\n\t// The upstream CGo implementation does not handle this case correctly.\n\tprintln(\"static headerfunc 2:\", C.headerfunc_static(5))\n\n\t// Test function without return value.\n\tvar n C.int\n\tC.headerfunc_void(3, &n)\n\tprintln(\"static headerfunc void:\", n)\n\n\t// anonymous structs and enums in multiple Go files\n\tvar _ C.teststruct\n\tvar _ C.testenum\n}\n"
  },
  {
    "path": "testdata/cgo/main.c",
    "content": "#include <math.h>\n#include \"main.h\"\n#include <stdio.h>\n\nint global = 3;\nbool globalBool = 1;\nbool globalBool2 = 10; // test narrowing\nfloat globalFloat = 3.1;\ndouble globalDouble = 3.2;\n_Complex float globalComplexFloat = 4.1+3.3i;\n_Complex double globalComplexDouble = 4.2+3.4i;\n_Complex double globalComplexLongDouble = 4.3+3.5i;\nchar globalChar = 100;\nvoid *globalVoidPtrSet = &global;\nvoid *globalVoidPtrNull;\nint64_t globalInt64 = -(2LL << 40);\ncollection_t globalStruct = {256, -123456, 3.14, 88};\nint globalStructSize = sizeof(globalStruct);\nshort globalArray[3] = {5, 6, 7};\njoined_t globalUnion;\nint globalUnionSize = sizeof(globalUnion);\noption_t globalOption = optionG;\nbitfield_t globalBitfield = {244, 15, 1, 2, 47, 5};\n\nint cflagsConstant = SOME_CONSTANT;\n\nint smallEnumWidth = sizeof(option2_t);\n\nchar globalChars[] = {2, 0, 4, 8};\n\nint fortytwo() {\n\treturn 42;\n}\n\nint add(int a, int b) {\n\treturn a + b;\n}\n\nint doCallback(int a, int b, binop_t callback) {\n\treturn callback(a, b);\n}\n\nint variadic0() {\n\treturn 1;\n}\n\nint variadic2(int x, int y, ...) {\n\treturn x * y;\n}\n\nvoid store(int value, int *ptr) {\n\t*ptr = value;\n}\n\nvoid unionSetShort(short s) {\n\tglobalUnion.s = s;\n}\n\nvoid unionSetFloat(float f) {\n\tglobalUnion.f = f;\n}\n\nvoid unionSetData(short f0, short f1, short f2) {\n\tglobalUnion.data[0] = 5;\n\tglobalUnion.data[1] = 8;\n\tglobalUnion.data[2] = 1;\n}\n\nvoid arraydecay(int buf1[5], int buf2[3][8], int buf3[4][7][2]) {\n\t// Do nothing.\n}\n\ndouble doSqrt(double x) {\n\treturn sqrt(x);\n}\n\nvoid printf_single_int(char *format, int arg) {\n\tprintf(format, arg);\n}\n\nint set_errno(int err) {\n\terrno = err;\n\treturn -1;\n}\n"
  },
  {
    "path": "testdata/cgo/main.go",
    "content": "package main\n\n/*\n#include <stdio.h>\n#include <math.h>\nint fortytwo(void);\n#include \"main.h\"\n#include \"test.h\"\nint mul(int, int);\n#include <string.h>\n#cgo CFLAGS: -DSOME_CONSTANT=17\n#define someDefine -5 + 2 * 7\nbool someBool;\n*/\nimport \"C\"\n\n// int headerfunc(int a) { return a + 1; }\n// static int headerfunc_static(int a) { return a - 1; }\nimport \"C\"\n\nimport (\n\t\"syscall\"\n\t\"unsafe\"\n)\n\nfunc main() {\n\tprintln(\"fortytwo:\", C.fortytwo())\n\tprintln(\"add:\", C.add(C.int(3), 5))\n\tvar x C.myint = 3\n\tprintln(\"myint:\", x, C.myint(5))\n\tprintln(\"myint size:\", int(unsafe.Sizeof(x)))\n\tvar y C.longlong = -(1 << 40)\n\tprintln(\"longlong:\", y)\n\tprintln(\"global:\", C.global)\n\tprintln(\"defined ints:\", C.CONST_INT, C.CONST_INT2)\n\tprintln(\"defined floats:\", C.CONST_FLOAT, C.CONST_FLOAT2)\n\tprintln(\"defined string:\", C.CONST_STRING)\n\tprintln(\"defined char:\", C.CONST_CHAR)\n\tprintln(\"defined expr:\", C.someDefine)\n\tvar ptr C.intPointer\n\tvar n C.int = 15\n\tptr = C.intPointer(&n)\n\tprintln(\"15:\", *ptr)\n\tC.store(25, &n)\n\tprintln(\"25:\", *ptr)\n\tcb := C.binop_t(C.add)\n\tprintln(\"callback 1:\", C.doCallback(20, 30, cb))\n\tcb = C.binop_t(C.mul)\n\tprintln(\"callback 2:\", C.doCallback(20, 30, cb))\n\tgenericCallbackCall[int]()\n\n\t// variadic functions\n\tprintln(\"variadic0:\", C.variadic0())\n\tprintln(\"variadic2:\", C.variadic2(3, 5))\n\n\t// functions in the header C snippet\n\tprintln(\"headerfunc:\", C.headerfunc(5))\n\tprintln(\"static headerfunc:\", C.headerfunc_static(5))\n\theaderfunc_2()\n\n\t// equivalent types\n\tvar goInt8 int8 = 5\n\tvar _ C.int8_t = goInt8\n\n\tvar _ bool = C.someBool\n\tvar _ C._Bool = C.someBool\n\n\t// more globals\n\tprintln(\"bool:\", C.globalBool, C.globalBool2 == true)\n\tprintln(\"float:\", C.globalFloat)\n\tprintln(\"double:\", C.globalDouble)\n\tprintln(\"complex float:\", C.globalComplexFloat)\n\tprintln(\"complex double:\", C.globalComplexDouble)\n\tprintln(\"complex long double:\", C.globalComplexLongDouble)\n\tprintln(\"char match:\", C.globalChar == 100)\n\tvar voidPtr unsafe.Pointer = C.globalVoidPtrNull\n\tprintln(\"void* match:\", voidPtr == nil, C.globalVoidPtrNull == nil, (*C.int)(C.globalVoidPtrSet) == &C.global)\n\tprintln(\"int64_t match:\", C.globalInt64 == C.int64_t(-(2<<40)))\n\n\t// complex types\n\tprintln(\"struct:\", C.int(unsafe.Sizeof(C.globalStruct)) == C.globalStructSize, C.globalStruct.s, C.globalStruct.l, C.globalStruct.f)\n\tvar _ [3]C.short = C.globalArray\n\tprintln(\"array:\", C.globalArray[0], C.globalArray[1], C.globalArray[2])\n\tprintln(\"union:\", C.int(unsafe.Sizeof(C.globalUnion)) == C.globalUnionSize)\n\tC.unionSetShort(22)\n\tprintln(\"union s:\", *C.globalUnion.unionfield_s())\n\tC.unionSetFloat(C.float(6.28))\n\tprintln(\"union f (C.float):\", *C.globalUnion.unionfield_f())\n\tC.unionSetFloat(float32(3.14))\n\tprintln(\"union f (float32):\", *C.globalUnion.unionfield_f())\n\tC.unionSetData(5, 8, 1)\n\tdata := C.globalUnion.unionfield_data()\n\tprintln(\"union global data:\", data[0], data[1], data[2])\n\treturnedUnion := printUnion(C.globalUnion)\n\tprintln(\"union field:\", *returnedUnion.unionfield_f())\n\tvar _ C.union_joined = C.globalUnion\n\tprintBitfield(&C.globalBitfield)\n\tC.globalBitfield.set_bitfield_a(7)\n\tC.globalBitfield.set_bitfield_b(0)\n\tC.globalBitfield.set_bitfield_c(0xff)\n\tprintBitfield(&C.globalBitfield)\n\n\t// elaborated type\n\tp := C.struct_point2d{x: 3, y: 5}\n\tprintln(\"struct:\", p.x, p.y)\n\n\t// multiple anonymous structs (inside a typedef)\n\tvar _ C.point2d_t = C.point2d_t{x: 3, y: 5}\n\tvar _ C.point3d_t = C.point3d_t{x: 3, y: 5, z: 7}\n\n\t// nested structs/unions\n\tvar _ C.tagged_union_t\n\tvar _ C.nested_struct_t\n\tvar _ C.nested_union_t\n\n\t// recursive types, test using a linked list\n\tlist := &C.list_t{n: 3, next: &C.struct_list_t{n: 6, next: &C.list_t{n: 7, next: nil}}}\n\tfor list != nil {\n\t\tprintln(\"n in chain:\", list.n)\n\t\tlist = (*C.list_t)(list.next)\n\t}\n\n\t// named enum\n\tvar _ C.enum_option = C.optionA\n\tvar _ C.option_t = C.optionA\n\tprintln(\"option:\", C.globalOption)\n\tprintln(\"option A:\", C.optionA)\n\tprintln(\"option B:\", C.optionB)\n\tprintln(\"option C:\", C.optionC)\n\tprintln(\"option D:\", C.optionD)\n\tprintln(\"option E:\", C.optionE)\n\tprintln(\"option F:\", C.optionF)\n\tprintln(\"option G:\", C.optionG)\n\n\t// anonymous enum\n\tvar _ C.option2_t = C.option2A\n\tvar _ C.option3_t = C.option3A\n\tprintln(\"option 2A:\", C.option2A)\n\tprintln(\"option 3A:\", C.option3A)\n\n\t// anonymous structs and enums in multiple Go files\n\tvar _ C.teststruct\n\tvar _ C.testenum\n\n\t// Check that enums are considered the same width in C and CGo.\n\tprintln(\"enum width matches:\", unsafe.Sizeof(C.option2_t(0)) == uintptr(C.smallEnumWidth))\n\n\t// Check whether CFLAGS are correctly passed on to compiled C files.\n\tprintln(\"CFLAGS value:\", C.cflagsConstant)\n\n\t// Check array-to-pointer decaying. This signature:\n\t//   void arraydecay(int buf1[5], int buf2[3][8], int buf3[4][7][2]);\n\t// decays to:\n\t//   void arraydecay(int *buf1, int *buf2[8], int *buf3[7][2]);\n\tC.arraydecay((*C.int)(nil), (*[8]C.int)(nil), (*[7][2]C.int)(nil))\n\n\t// Test CGo builtins like C.CString.\n\tcstr := C.CString(\"string passed to C\")\n\tprintln(\"cstr length:\", C.strlen(cstr))\n\tgostr := C.GoString(cstr)\n\tprintln(\"C.CString:\", gostr)\n\tcharBuf := C.GoBytes(unsafe.Pointer(&C.globalChars[0]), 4)\n\tprintln(\"C.charBuf:\", charBuf[0], charBuf[1], charBuf[2], charBuf[3])\n\tbinaryString := C.GoStringN(&C.globalChars[0], 4)\n\tprintln(\"C.CStringN:\", len(binaryString), binaryString[0], binaryString[1], binaryString[2], binaryString[3])\n\n\t// Test whether those builtins also work with zero length data.\n\tprintln(\"C.GoString(nil):\", C.GoString(nil))\n\tprintln(\"len(C.GoStringN(nil, 0)):\", len(C.GoStringN(nil, 0)))\n\tprintln(\"len(C.GoBytes(nil, 0)):\", len(C.GoBytes(nil, 0)))\n\tprintln(\"len(C.GoBytes(C.CBytes(nil),0)):\", len(C.GoBytes(C.CBytes(nil), 0)))\n\tprintln(`rountrip CBytes:`, C.GoString((*C.char)(C.CBytes([]byte(\"hello\\000\")))))\n\n\t// Check that errno is returned from the second return value, and that it\n\t// matches the errno value that was just set.\n\t_, errno := C.set_errno(C.EINVAL)\n\tprintln(\"EINVAL:\", errno == syscall.EINVAL)\n\t_, errno = C.set_errno(C.EAGAIN)\n\tprintln(\"EAGAIN:\", errno == syscall.EAGAIN)\n\n\t// libc: test whether C functions work at all.\n\tbuf1 := []byte(\"foobar\\x00\")\n\tbuf2 := make([]byte, len(buf1))\n\tC.strcpy((*C.char)(unsafe.Pointer(&buf2[0])), (*C.char)(unsafe.Pointer(&buf1[0])))\n\tprintln(\"copied string:\", string(buf2[:C.strlen((*C.char)(unsafe.Pointer(&buf2[0])))]))\n\n\t// libc: test libm functions (normally bundled in libc)\n\tprintln(\"CGo sqrt(3):\", C.sqrt(3))\n\tprintln(\"C   sqrt(3):\", C.doSqrt(3))\n\n\t// libc: test basic stdio functionality\n\tputsBuf := []byte(\"line written using C puts\\x00\")\n\tC.puts((*C.char)(unsafe.Pointer(&putsBuf[0])))\n\n\t// libc: test whether printf works in C.\n\tprintfBuf := []byte(\"line written using C printf with value=%d\\n\\x00\")\n\tC.printf_single_int((*C.char)(unsafe.Pointer(&printfBuf[0])), -21)\n}\n\nfunc printUnion(union C.joined_t) C.joined_t {\n\tdata := union.unionfield_data()\n\tprintln(\"union local data: \", data[0], data[1], data[2])\n\t*union.unionfield_s() = -33\n\tprintln(\"union s:\", data[0] == -33)\n\t*union.unionfield_f() = 6.28\n\tprintln(\"union f:\", *union.unionfield_f())\n\treturn union\n}\n\n//export mul\nfunc mul(a, b C.int) C.int {\n\treturn a * b\n}\n\nfunc printBitfield(bitfield *C.bitfield_t) {\n\tprintln(\"bitfield a:\", bitfield.bitfield_a())\n\tprintln(\"bitfield b:\", bitfield.bitfield_b())\n\tprintln(\"bitfield c:\", bitfield.bitfield_c())\n\tprintln(\"bitfield d:\", bitfield.d)\n\tprintln(\"bitfield e:\", bitfield.e)\n}\n\ntype Int interface {\n\tint | uint\n}\n\nfunc genericCallbackCall[T Int]() {\n\tprintln(\"callback inside generic function:\", C.doCallback(20, 30, C.binop_t(C.add)))\n}\n"
  },
  {
    "path": "testdata/cgo/main.h",
    "content": "#include <stdbool.h>\n#include <stdint.h>\n#include <errno.h>\n\ntypedef short myint;\ntypedef short unusedTypedef;\nint add(int a, int b);\nint unusedFunction(void);\ntypedef int (*binop_t) (int, int);\nint doCallback(int a, int b, binop_t cb);\ntypedef int * intPointer;\nvoid store(int value, int *ptr);\n\nint variadic0();\nint variadic2(int x, int y, ...);\n\n# define CONST_INT 5\n# define CONST_INT2 5llu\n# define CONST_FLOAT 5.8\n# define CONST_FLOAT2 5.8f\n# define CONST_CHAR 'c'\n# define CONST_STRING \"defined string\"\n\n// this signature should not be included by CGo\nvoid unusedFunction2(int x, __builtin_va_list args);\n\ntypedef struct collection {\n\tshort         s;\n\tlong          l;\n\tfloat         f;\n\tunsigned char c;\n} collection_t;\n\nstruct point2d {\n\tint x;\n\tint y;\n};\n\ntypedef struct {\n\tint x;\n\tint y;\n} point2d_t;\n\ntypedef struct {\n\tint x;\n\tint y;\n\tint z;\n} point3d_t;\n\ntypedef struct {\n\tint tag;\n\tunion {\n\t\tint a;\n\t\tint b;\n\t} u;\n} tagged_union_t;\n\ntypedef struct {\n\tint x;\n\tstruct {\n\t\tchar red;\n\t\tchar green;\n\t\tchar blue;\n\t} color;\n} nested_struct_t;\n\ntypedef union {\n\tint x;\n\tstruct {\n\t\tchar a;\n\t\tchar b;\n\t};\n} nested_union_t;\n\n// linked list\ntypedef struct list_t {\n\tint           n;\n\tstruct list_t *next;\n} list_t;\n\ntypedef union joined {\n\tmyint s;\n\tfloat f;\n\tshort data[3];\n} joined_t;\nvoid unionSetShort(short s);\nvoid unionSetFloat(float f);\nvoid unionSetData(short f0, short f1, short f2);\n\ntypedef enum option {\n\toptionA,\n\toptionB,\n\toptionC = -5,\n\toptionD,\n\toptionE = 10,\n\toptionF,\n\toptionG,\n} option_t;\n\ntypedef enum {\n\toption2A = 20,\n} option2_t;\n\ntypedef enum {\n\toption3A = 21,\n} option3_t;\n\ntypedef struct {\n\tunsigned char start;\n\tunsigned char a : 5;\n\tunsigned char b : 1;\n\tunsigned char c : 2;\n\tunsigned char :0; // new field\n\tunsigned char d : 6;\n\tunsigned char e : 3;\n\t// Note that C++ allows bitfields bigger than the underlying type.\n} bitfield_t;\n\n// test globals and datatypes\nextern int global;\nextern int unusedGlobal;\nextern bool globalBool;\nextern bool globalBool2;\nextern float globalFloat;\nextern double globalDouble;\nextern _Complex float globalComplexFloat;\nextern _Complex double globalComplexDouble;\nextern _Complex double globalComplexLongDouble;\nextern char globalChar;\nextern void *globalVoidPtrSet;\nextern void *globalVoidPtrNull;\nextern int64_t globalInt64;\nextern collection_t globalStruct;\nextern int globalStructSize;\nextern short globalArray[3];\nextern joined_t globalUnion;\nextern int globalUnionSize;\nextern option_t globalOption;\nextern bitfield_t globalBitfield;\n\nextern int smallEnumWidth;\n\nextern int cflagsConstant;\n\nextern char globalChars[4];\n\n// test duplicate definitions\nint add(int a, int b);\nextern int global;\n\n// Test array decaying into a pointer.\ntypedef int arraydecay_buf3[4][7][2];\nvoid arraydecay(int buf1[5], int buf2[3][8], arraydecay_buf3 buf3);\n\ndouble doSqrt(double);\n\nvoid printf_single_int(char *format, int arg);\n\nint set_errno(int err);\n"
  },
  {
    "path": "testdata/cgo/out.txt",
    "content": "fortytwo: 42\nadd: 8\nmyint: 3 5\nmyint size: 2\nlonglong: -1099511627776\nglobal: 3\ndefined ints: 5 5\ndefined floats: +5.800000e+000 +5.800000e+000\ndefined string: defined string\ndefined char: 99\ndefined expr: 9\n15: 15\n25: 25\ncallback 1: 50\ncallback 2: 600\ncallback inside generic function: 50\nvariadic0: 1\nvariadic2: 15\nheaderfunc: 6\nstatic headerfunc: 4\nstatic headerfunc 2: +4.000000e+000\nstatic headerfunc void: 3\nbool: true true\nfloat: +3.100000e+000\ndouble: +3.200000e+000\ncomplex float: (+4.100000e+000+3.300000e+000i)\ncomplex double: (+4.200000e+000+3.400000e+000i)\ncomplex long double: (+4.300000e+000+3.500000e+000i)\nchar match: true\nvoid* match: true true true\nint64_t match: true\nstruct: true 256 -123456 +3.140000e+000\narray: 5 6 7\nunion: true\nunion s: 22\nunion f (C.float): +6.280000e+000\nunion f (float32): +3.140000e+000\nunion global data: 5 8 1\nunion local data:  5 8 1\nunion s: true\nunion f: +6.280000e+000\nunion field: +6.280000e+000\nbitfield a: 15\nbitfield b: 1\nbitfield c: 2\nbitfield d: 47\nbitfield e: 5\nbitfield a: 7\nbitfield b: 0\nbitfield c: 3\nbitfield d: 47\nbitfield e: 5\nstruct: 3 5\nn in chain: 3\nn in chain: 6\nn in chain: 7\noption: 12\noption A: 0\noption B: 1\noption C: -5\noption D: -4\noption E: 10\noption F: 11\noption G: 12\noption 2A: 20\noption 3A: 21\nenum width matches: true\nCFLAGS value: 17\ncstr length: 18\nC.CString: string passed to C\nC.charBuf: 2 0 4 8\nC.CStringN: 4 2 0 4 8\nC.GoString(nil): \nlen(C.GoStringN(nil, 0)): 0\nlen(C.GoBytes(nil, 0)): 0\nlen(C.GoBytes(C.CBytes(nil),0)): 0\nrountrip CBytes: hello\nEINVAL: true\nEAGAIN: true\ncopied string: foobar\nCGo sqrt(3): +1.732051e+000\nC   sqrt(3): +1.732051e+000\nline written using C puts\nline written using C printf with value=-21\n"
  },
  {
    "path": "testdata/cgo/test.h",
    "content": "#pragma once\n\ntypedef struct {\n    int a;\n    int b;\n} teststruct;\n\ntypedef enum {\n    v0,\n    v1\n} testenum;\n"
  },
  {
    "path": "testdata/channel.go",
    "content": "package main\n\nimport (\n\t\"runtime\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n)\n\nvar wg sync.WaitGroup\n\ntype intchan chan int\n\nfunc main() {\n\tch := make(chan int, 2)\n\tch <- 1\n\tprintln(\"len, cap of channel:\", len(ch), cap(ch), ch == nil)\n\n\tch = make(chan int)\n\tprintln(\"len, cap of channel:\", len(ch), cap(ch), ch == nil)\n\n\twg.Add(1)\n\tgo sender(ch)\n\n\tn, ok := <-ch\n\tprintln(\"recv from open channel:\", n, ok)\n\n\tfor n := range ch {\n\t\tprintln(\"received num:\", n)\n\t}\n\n\twg.Wait()\n\tn, ok = <-ch\n\tprintln(\"recv from closed channel:\", n, ok)\n\n\t// Test various channel size types.\n\t_ = make(chan int, int8(2))\n\t_ = make(chan int, int16(2))\n\t_ = make(chan int, int32(2))\n\t_ = make(chan int, int64(2))\n\t_ = make(chan int, uint8(2))\n\t_ = make(chan int, uint16(2))\n\t_ = make(chan int, uint32(2))\n\t_ = make(chan int, uint64(2))\n\n\t// Test that named channels don't crash the compiler.\n\tnamed := make(intchan, 1)\n\tnamed <- 3\n\t<-named\n\tselect {\n\tcase <-named:\n\tdefault:\n\t}\n\n\t// Test bigger values\n\tch2 := make(chan complex128)\n\twg.Add(1)\n\tgo sendComplex(ch2)\n\tprintln(\"complex128:\", <-ch2)\n\twg.Wait()\n\n\t// Test multi-sender.\n\tch = make(chan int)\n\twg.Add(3)\n\tgo fastsender(ch, 10)\n\tgo fastsender(ch, 23)\n\tgo fastsender(ch, 40)\n\tslowreceiver(ch)\n\twg.Wait()\n\n\t// Test multi-receiver.\n\tch = make(chan int)\n\twg.Add(3)\n\tvar result atomic.Uint32\n\tgo fastreceiveradd(ch, &result)\n\tgo fastreceiveradd(ch, &result)\n\tgo fastreceiveradd(ch, &result)\n\tslowsender(ch)\n\twg.Wait()\n\tprintln(\"sum of sums:\", result.Load())\n\n\t// Test iterator style channel.\n\tch = make(chan int)\n\twg.Add(1)\n\tgo iterator(ch, 100)\n\tsum := 0\n\tfor i := range ch {\n\t\tsum += i\n\t}\n\twg.Wait()\n\tprintln(\"sum(100):\", sum)\n\n\t// Test simple selects.\n\twg.Add(1)\n\tgo selectDeadlock()\n\twg.Wait()\n\n\twg.Add(1)\n\tgo selectNoOp()\n\twg.Wait()\n\n\t// Test select with a single send operation (transformed into chan send).\n\tch = make(chan int)\n\twg.Add(1)\n\tgo fastreceiver(ch)\n\tselect {\n\tcase ch <- 5:\n\t}\n\tclose(ch)\n\twg.Wait()\n\tprintln(\"did send one\")\n\n\t// Test select with a single recv operation (transformed into chan recv).\n\tselect {\n\tcase n := <-ch:\n\t\tprintln(\"select one n:\", n)\n\t}\n\n\t// Test select recv with channel that has one entry.\n\tch = make(chan int)\n\twg.Add(1)\n\tgo func(ch chan int) {\n\t\truntime.Gosched()\n\t\tch <- 55\n\t\twg.Done()\n\t}(ch)\n\tselect {\n\tcase make(chan int) <- 3:\n\t\tprintln(\"unreachable\")\n\tcase <-(chan int)(nil):\n\t\tprintln(\"unreachable\")\n\tcase n := <-ch:\n\t\tprintln(\"select n from chan:\", n)\n\tcase n := <-make(chan int):\n\t\tprintln(\"unreachable:\", n)\n\t}\n\twg.Wait()\n\n\t// Test select recv with closed channel.\n\tclose(ch)\n\tselect {\n\tcase make(chan int) <- 3:\n\t\tprintln(\"unreachable\")\n\tcase n := <-ch:\n\t\tprintln(\"select n from closed chan:\", n)\n\tcase n := <-make(chan int):\n\t\tprintln(\"unreachable:\", n)\n\t}\n\n\t// Test select send.\n\tch = make(chan int)\n\twg.Add(1)\n\tgo fastreceiver(ch)\n\tselect {\n\tcase ch <- 235:\n\t\tprintln(\"select send\")\n\tcase n := <-make(chan int):\n\t\tprintln(\"unreachable:\", n)\n\t}\n\tclose(ch)\n\twg.Wait()\n\n\t// test non-concurrent buffered channels\n\tch = make(chan int, 2)\n\tch <- 1\n\tch <- 2\n\tprintln(\"non-concurrent channel receive:\", <-ch)\n\tprintln(\"non-concurrent channel receive:\", <-ch)\n\n\t// test closing channels with buffered data\n\tch <- 3\n\tch <- 4\n\tclose(ch)\n\tprintln(\"closed buffered channel receive:\", <-ch)\n\tprintln(\"closed buffered channel receive:\", <-ch)\n\tprintln(\"closed buffered channel receive:\", <-ch)\n\n\t// test using buffered channels as regular channels with special properties\n\twg.Add(6)\n\tch = make(chan int, 2)\n\tgo send(ch)\n\tgo send(ch)\n\tgo send(ch)\n\tgo send(ch)\n\tgo receive(ch)\n\tgo receive(ch)\n\twg.Wait()\n\tclose(ch)\n\tvar count int\n\tfor range ch {\n\t\tcount++\n\t}\n\tprintln(\"hybrid buffered channel receive:\", count)\n\n\t// test blocking selects\n\tch = make(chan int)\n\tsch1 := make(chan int)\n\tsch2 := make(chan int)\n\tsch3 := make(chan int)\n\twg.Add(3)\n\tgo func() {\n\t\tdefer wg.Done()\n\t\ttime.Sleep(time.Millisecond)\n\t\tsch1 <- 1\n\t}()\n\tgo func() {\n\t\tdefer wg.Done()\n\t\ttime.Sleep(time.Millisecond)\n\t\tsch2 <- 2\n\t}()\n\tgo func() {\n\t\tdefer wg.Done()\n\t\t// merge sch2 and sch3 into ch\n\t\tfor i := 0; i < 2; i++ {\n\t\t\tvar v int\n\t\t\tselect {\n\t\t\tcase v = <-sch1:\n\t\t\tcase v = <-sch2:\n\t\t\t}\n\t\t\tselect {\n\t\t\tcase sch3 <- v:\n\t\t\t\tpanic(\"sent to unused channel\")\n\t\t\tcase ch <- v:\n\t\t\t}\n\t\t}\n\t}()\n\tsum = 0\n\tfor i := 0; i < 2; i++ {\n\t\tselect {\n\t\tcase sch3 <- sum:\n\t\t\tpanic(\"sent to unused channel\")\n\t\tcase v := <-ch:\n\t\t\tsum += v\n\t\t}\n\t}\n\twg.Wait()\n\tprintln(\"blocking select sum:\", sum)\n}\n\nfunc send(ch chan<- int) {\n\tch <- 1\n\twg.Done()\n}\n\nfunc receive(ch <-chan int) {\n\t<-ch\n\twg.Done()\n}\n\nfunc sender(ch chan int) {\n\tfor i := 1; i <= 8; i++ {\n\t\tif i == 4 {\n\t\t\ttime.Sleep(time.Millisecond)\n\t\t\tprintln(\"slept\")\n\t\t}\n\t\tch <- i\n\t}\n\tclose(ch)\n\twg.Done()\n}\n\nfunc sendComplex(ch chan complex128) {\n\tch <- 7 + 10.5i\n\twg.Done()\n}\n\nfunc fastsender(ch chan int, n int) {\n\tch <- n\n\tch <- n + 1\n\twg.Done()\n}\n\nfunc slowreceiver(ch chan int) {\n\tsum := 0\n\tfor i := 0; i < 6; i++ {\n\t\tsum += <-ch\n\t\ttime.Sleep(time.Microsecond)\n\t}\n\tprintln(\"sum of n:\", sum)\n}\n\nfunc slowsender(ch chan int) {\n\tfor n := 0; n < 6; n++ {\n\t\ttime.Sleep(time.Microsecond)\n\t\tch <- 12 + n\n\t}\n}\n\nfunc fastreceiver(ch chan int) {\n\tsum := 0\n\tfor i := 0; i < 2; i++ {\n\t\tn := <-ch\n\t\tsum += n\n\t}\n\tprintln(\"sum:\", sum)\n\twg.Done()\n}\n\nfunc fastreceiveradd(ch chan int, result *atomic.Uint32) {\n\tsum := 0\n\tfor i := 0; i < 2; i++ {\n\t\tn := <-ch\n\t\tsum += n\n\t}\n\tresult.Add(uint32(sum))\n\twg.Done()\n}\n\nfunc iterator(ch chan int, top int) {\n\tfor i := 0; i < top; i++ {\n\t\tch <- i\n\t}\n\tclose(ch)\n\twg.Done()\n}\n\nfunc selectDeadlock() {\n\tprintln(\"deadlocking\")\n\twg.Done()\n\tselect {}\n\tprintln(\"unreachable\")\n}\n\nfunc selectNoOp() {\n\tprintln(\"select no-op\")\n\tselect {\n\tdefault:\n\t}\n\tprintln(\"after no-op\")\n\twg.Done()\n}\n"
  },
  {
    "path": "testdata/channel.txt",
    "content": "len, cap of channel: 1 2 false\nlen, cap of channel: 0 0 false\nrecv from open channel: 1 true\nreceived num: 2\nreceived num: 3\nslept\nreceived num: 4\nreceived num: 5\nreceived num: 6\nreceived num: 7\nreceived num: 8\nrecv from closed channel: 0 false\ncomplex128: (+7.000000e+000+1.050000e+001i)\nsum of n: 149\nsum of sums: 87\nsum(100): 4950\ndeadlocking\nselect no-op\nafter no-op\nsum: 5\ndid send one\nselect one n: 0\nselect n from chan: 55\nselect n from closed chan: 0\nselect send\nsum: 235\nnon-concurrent channel receive: 1\nnon-concurrent channel receive: 2\nclosed buffered channel receive: 3\nclosed buffered channel receive: 4\nclosed buffered channel receive: 0\nhybrid buffered channel receive: 2\nblocking select sum: 3\n"
  },
  {
    "path": "testdata/corpus.yaml",
    "content": "# This contains code from https://github.com/dgryski/tinygo-test-corpus\n\n# The MIT License (MIT)\n\n# Copyright (c) 2020 Damian Gryski <damian@gryski.com>\n\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n\n- repo: github.com/buger/jsonparser\n- repo: github.com/dgryski/go-bloomindex\n  tags: noasm\n- repo: github.com/dgryski/go-arc\n- repo: github.com/dgryski/go-camellia\n- repo: github.com/dgryski/go-change\n- repo: github.com/dgryski/go-chaskey\n  tags: appengine noasm\n  skipwasi: true # siphash has build tag issues\n- repo: github.com/dgryski/go-clefia\n- repo: github.com/dgryski/go-clockpro\n- repo: github.com/dgryski/go-cobs\n- repo: github.com/dgryski/go-cuckoof\n  tags: pureno noasm\n- repo: github.com/dgryski/go-discreterand\n- repo: github.com/dgryski/go-expirecache\n- repo: github.com/dgryski/go-factor\n- repo: github.com/dgryski/go-farm\n  tags: noasm\n- repo: github.com/dgryski/go-fuzzstr\n- repo: github.com/dgryski/go-hollow\n- repo: github.com/dgryski/go-idea\n- repo: github.com/dgryski/go-interp\n  skipwasi: true # too slow on wasi\n  slow: true\n- repo: github.com/dgryski/go-intpat\n- repo: github.com/dgryski/go-jump\n- repo: github.com/dgryski/go-kcipher2\n- repo: github.com/dgryski/go-ketama\n- repo: github.com/dgryski/go-krcrypt\n- repo: github.com/dgryski/go-linebreak\n- repo: github.com/dgryski/go-linlog\n- repo: github.com/dgryski/go-maglev\n  tags: appengine # for dchest/siphash\n  skipwasi: true\n- repo: github.com/dgryski/go-marvin32\n- repo: github.com/dgryski/go-md5crypt\n- repo: github.com/dgryski/go-metro\n  tags: noasm\n- repo: github.com/dgryski/go-misty1\n- repo: github.com/dgryski/go-mph\n  tags: noasm\n- repo: github.com/dgryski/go-mpchash\n  tags: appengine # for dchest/siphash\n  skipwasi: true\n- repo: github.com/dgryski/go-neeva\n- repo: github.com/dgryski/go-nibz\n- repo: github.com/dgryski/go-nibblesort\n- repo: github.com/dgryski/go-pcgr\n- repo: github.com/dgryski/go-present\n- repo: github.com/dgryski/go-quicklz\n  skipwasi: true # not 32-bit compliant\n- repo: github.com/dgryski/go-radixsort\n- repo: github.com/dgryski/go-rbo\n- repo: github.com/dgryski/go-rc5\n- repo: github.com/dgryski/go-rc6\n- repo: github.com/dgryski/go-s4lru\n- repo: github.com/dgryski/go-sequitur\n- repo: github.com/dgryski/go-sip13\n  tags: noasm\n- repo: github.com/dgryski/go-skinny\n- repo: github.com/dgryski/go-skip32\n- repo: github.com/dgryski/go-skipjack\n- repo: github.com/dgryski/go-sparx\n- repo: github.com/dgryski/go-spooky\n- repo: github.com/dgryski/go-spritz\n- repo: github.com/dgryski/go-timewindow\n- repo: github.com/dgryski/go-tinylz\n- repo: github.com/dgryski/go-tinymap\n- repo: github.com/dgryski/go-trigram\n- repo: github.com/dgryski/go-twine\n- repo: github.com/dgryski/go-xoroshiro\n- repo: github.com/dgryski/go-xoshiro\n- repo: github.com/dgryski/go-zlatlong\n- repo: github.com/dgryski/go-postings\n  tags: noasm\n- repo: golang.org/x/crypto\n  tags: noasm\n  subdirs:\n  - pkg: argon2\n  - pkg: bcrypt\n  - pkg: blake2b\n  - pkg: blake2s\n  - pkg: blowfish\n  - pkg: bn256\n  - pkg: cast5\n  - pkg: chacha20\n    skipwasi: true # needs recover\n  - pkg: chacha20poly1305\n  - pkg: curve25519\n  - pkg: ed25519\n  - pkg: hkdf\n  - pkg: md4\n  - pkg: nacl/auth\n  - pkg: nacl/box\n  - pkg: nacl/secretbox\n  - pkg: nacl/sign\n  - pkg: openpgp/armor\n  - pkg: openpgp/elgamal\n  - pkg: openpgp/s2k\n  - pkg: pbkdf2\n  - pkg: pkcs12/internal/rc2\n  - pkg: ripemd160\n  - pkg: salsa20\n  - pkg: scrypt\n  - pkg: ssh/internal/bcrypt_pbkdf\n  - pkg: tea\n  - pkg: twofish\n  - pkg: xtea\n  #- pkg: cryptobyte # panic: unimplemented: reflect.OverflowInt()\n  #- pkg: salsa20/salsa # panic: runtime error: index out of range\n  #- pkg: sha3 # panic: unimplemented: (reflect.Type).NumMethod()\n- repo: github.com/google/shlex\n- repo: github.com/google/btree\n- repo: github.com/google/der-ascii\n  subdirs:\n  - pkg: cmd/ascii2der\n  - pkg: cmd/der2ascii\n  - pkg: internal\n- repo: github.com/google/hilbert\n- repo: github.com/google/go-intervals\n  subdirs:\n    - pkg: intervalset\n    - pkg: timespanset\n      skipwasi: true # needs timezone stuff\n- repo: github.com/google/okay\n- repo: github.com/google/go-patchutils\n  skipwasi: true # needs os.readdir\n- repo: golang.org/x/text\n  subdirs:\n  - pkg: encoding\n  - pkg: encoding/charmap\n  - pkg: encoding/htmlindex\n  - pkg: encoding/ianaindex\n  - pkg: encoding/japanese\n  - pkg: encoding/korean\n  - pkg: encoding/simplifiedchinese\n  - pkg: encoding/traditionalchinese\n  - pkg: encoding/unicode\n  - pkg: encoding/unicode/utf32\n  - pkg: internal/format\n  - pkg: internal/ucd\n  - pkg: internal/tag\n  - pkg: search\n  - pkg: unicode/rangetable\n  - pkg: message/catalog\n  #- pkg: collate/build # panic: (reflect.Value).Interface: unexported\n  #- pkg: feature/plural # TestSelect, TestOrdinal, TestCardinal fail\n  #- pkg: internal/catmsg  # TestCodec fails\n  #- pkg: internal/gen/bitfield # panic: unimplemented: (reflect.Type).Name()\n  #- pkg: number # fails due to printf %T formatting\n- repo: golang.org/x/image\n  tags: noasm\n  subdirs:\n  #- pkg: bmp # needs  _time.startTimer\n  - pkg: ccitt\n  - pkg: colornames\n  - pkg: draw\n  - pkg: font\n  - pkg: font/basicfont\n  - pkg: font/opentype\n  - pkg: font/plan9font\n  - pkg: math/fixed\n  - pkg: riff\n  - pkg: webp\n  - pkg: tiff\n- repo: github.com/golang/geo\n  subdirs:\n  - pkg: r1\n  - pkg: r2\n  - pkg: r3\n  - pkg: s1\n  #- pkg: s2 # reflect.DeepEqual() -> MapKeys\n- repo: github.com/golang/groupcache\n  subdirs:\n  - pkg: consistenthash\n  - pkg: lru\n- repo: github.com/armon/go-radix\n- repo: github.com/armon/circbuf\n- repo: github.com/VividCortex/gohistogram\n- repo: github.com/cespare/xxhash\n  tags: appengine\n- repo: gonum.org/v1/gonum\n- repo: gonum.org/v1/gonum\n  tags: noasm appengine\n  subdirs:\n  - pkg: blas/blas32\n  - pkg: blas/blas64\n    skipwasi: true # needs recover\n  - pkg: blas/cblas64\n  - pkg: blas/cblas128\n  - pkg: blas/gonum\n    skipwasi: true # needs recover\n  - pkg: cmplxs\n    skipwasi: true # needs recover\n  - pkg: cmplxs/cscalar\n  - pkg: diff/fd\n    skipwasi: true # needs recover\n  - pkg: dsp/window\n  - pkg: floats\n    skipwasi: true # needs recover\n  - pkg: floats/scalar\n  - pkg: integrate\n  - pkg: integrate/quad\n  - pkg: internal/cmplx64\n  - pkg: internal/testrand\n  - pkg: interp\n    skipwasi: true # needs recover\n  - pkg: lapack/gonum\n    skipwasi: true # takes too long\n    slow: true\n  - pkg: mathext\n  - pkg: mathext/prng\n  - pkg: optimize/convex/lp\n    skipwasi: true # takes too long\n  - pkg: optimize/functions\n  - pkg: spatial/r2\n  - pkg: spatial/r3\n  - pkg: stat/distmat\n  - pkg: stat/mds\n  - pkg: stat/spatial\n  - pkg: stat/distmv\n    skipwasi: true # takes too long\n    slow: true\n  - pkg: stat/samplemv\n    skipwasi: true # takes too long\n  #- pkg: graph # ld.lld-11:  -- error: undefined symbol: reflect.mapiterkey (among other reflect errors)\n  #- pkg: graph/topo # -- Reflect: Same as above\n  #- pkg: internal/math32 # -- /usr/local/go/src/testing/quick/quick.go:273:11: fType.NumOut undefined (type reflect.Type has no field or method NumOut)\n  #- pkg: mat # -- panic: mat: row index out of range\n  #- pkg: num/dual # TestFormat unexpected result for fmt.Sprintf(\"%#v\", T{Real:1.1, Emag:2.1}): got:\"T{Real:1.1, Emag:2.1}\", want:\"dual.Number{Real:1.1, Emag:2.1}\"    unexpected result for fmt.Sprintf(\"%#v\", T{Real:-1.1, Emag:-2.1}): got:\"T{Real:-1.1, Emag:-2.1}\", want:\"dual.Number{Real:-1.1, Emag:-2.1}\"\n  #- pkg: num/dualcmplx # TestFormat (similar to above)\n  #- pkg: num/dualquat # TestFormat (similar to above)\n  #- pkg: num/hyperdual # TestFormat (similar to above)\n  #- pkg: num/quat # TestFormat (similar to above)\n  #- pkg: optimize', # ld.lld-11: error: undefined symbol: golang.org/x/tools/container/intsets.havePOPCNT error: failed to link ...\n  #- pkg: spatial/barneshut # panic: unimplemented: (reflect.Value).MapKeys()\n  #- pkg: spatial/kdtree # panic: unimplemented: (reflect.Value).MapKeys()\n  #- pkg: spatial/vptree # panic: unimplemented: (reflect.Value).MapKeys()\n  #- pkg: stat # panic: stat: slice length mismatch\n  #- pkg: stat/card # /usr/local/go/src/encoding/gob/decode.go:562:21: MakeMapWithSize not declared by package reflect\n  #- pkg: stat/distuv # panic: distuv: cannot compute Mode for Beta != 0\\\n  #- pkg: stat/sampleuv # TestWeightedTimeSeeded requires t.Skip(), otherwise passes\n  #- pkg: unit # All Format tests fail. Similar to `num` subpackages.\n\n- repo: github.com/cloudflare/bm\n- repo: github.com/cloudflare/bn256\n  tags: generic\n- repo: github.com/cloudflare/ahocorasick\n#- repo: github.com/google/open-location-code # unfortunately, Go discards the test files\n#  version: master\n#  skipwasi: true # needs file access\n#  subdirs:\n#  - pkg: go\n- repo: github.com/chewxy/math32\n  version: master\n- repo: github.com/russross/blackfriday\n  version: v2\n- repo: github.com/soypat/mu8\n- repo: github.com/brandondube/pctl\n- repo: github.com/julienschmidt/httprouter\n- repo: github.com/openhistogram/circonusllhist\n  skipwasi: true #  math.MaxInt64 (untyped int constant 9223372036854775807) overflows int\n"
  },
  {
    "path": "testdata/embed/a/b/.hidden",
    "content": ""
  },
  {
    "path": "testdata/embed/a/b/bar.txt",
    "content": "bar\n"
  },
  {
    "path": "testdata/embed/a/b/foo.txt",
    "content": "foo\n"
  },
  {
    "path": "testdata/embed/embed.go",
    "content": "package main\n\nimport (\n\t\"embed\"\n\t\"strings\"\n)\n\n//go:embed a hello.txt\nvar files embed.FS\n\nvar (\n\t//go:embed \"hello.*\"\n\thelloString string\n\n\t//go:embed hello.txt\n\thelloBytes []byte\n)\n\n// A test to check that hidden files are not included when matching a directory.\n//go:embed a/b/.hidden\nvar hidden string\n\nvar helloStringBytes = []byte(helloString)\n\nfunc main() {\n\tprintln(\"string:\", strings.TrimSpace(helloString))\n\tprintln(\"bytes:\", strings.TrimSpace(string(helloBytes)))\n\tprintln(\"[]byte(string):\", strings.TrimSpace(string(helloStringBytes)))\n\tprintln(\"files:\")\n\treadFiles(\".\")\n}\n\nfunc readFiles(dir string) {\n\tentries, err := files.ReadDir(dir)\n\tif err != nil {\n\t\tprintln(err.Error())\n\t\treturn\n\t}\n\tfor _, entry := range entries {\n\t\tentryPath := entry.Name()\n\t\tif dir != \".\" {\n\t\t\tentryPath = dir + \"/\" + entryPath\n\t\t}\n\t\tprintln(\"-\", entryPath)\n\t\tif entry.IsDir() {\n\t\t\treadFiles(entryPath)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "testdata/embed/hello.txt",
    "content": "hello world!\n"
  },
  {
    "path": "testdata/embed/out.txt",
    "content": "string: hello world!\nbytes: hello world!\n[]byte(string): hello world!\nfiles:\n- a\n- a/b\n- a/b/bar.txt\n- a/b/foo.txt\n- hello.txt\n"
  },
  {
    "path": "testdata/env.go",
    "content": "package main\n\nimport (\n\t\"os\"\n)\n\nfunc main() {\n\t// Check for environment variables (set by the test runner).\n\tprintln(\"ENV1:\", os.Getenv(\"ENV1\"))\n\tv, ok := os.LookupEnv(\"ENV2\")\n\tif !ok {\n\t\tprintln(\"ENV2 not found\")\n\t}\n\tprintln(\"ENV2:\", v)\n\n\tfound := false\n\texpected := \"ENV1=\" + os.Getenv(\"ENV1\")\n\tfor _, envVar := range os.Environ() {\n\t\tif envVar == expected {\n\t\t\tfound = true\n\t\t}\n\t}\n\tif !found {\n\t\tprintln(\"could not find \" + expected + \" in os.Environ()\")\n\t}\n\n\t// Check for command line arguments.\n\t// Argument 0 is skipped because it is the program name, which varies by\n\t// test run.\n\tprintln()\n\tfor _, arg := range os.Args[1:] {\n\t\tprintln(\"arg:\", arg)\n\t}\n}\n"
  },
  {
    "path": "testdata/env.txt",
    "content": "ENV1: VALUE1\nENV2: VALUE2\n\narg: first\narg: second\n"
  },
  {
    "path": "testdata/errors/cgo.go",
    "content": "package main\n\n// #error hello\n// )))\nimport \"C\"\n\nfunc main() {\n}\n\n// ERROR: # command-line-arguments\n// ERROR: cgo.go:3:5: error: hello\n// ERROR: cgo.go:4:4: error: expected identifier or '('\n"
  },
  {
    "path": "testdata/errors/compiler.go",
    "content": "package main\n\n//go:wasmimport foo bar\nfunc foo() {\n}\n\n//go:align 7\nvar global int\n\n// Test for https://github.com/tinygo-org/tinygo/issues/4486\ntype genericType[T any] struct{}\n\nfunc (genericType[T]) methodWithoutBody()\n\nfunc callMethodWithoutBody() {\n\tmsg := &genericType[int]{}\n\tmsg.methodWithoutBody()\n}\n\n// ERROR: # command-line-arguments\n// ERROR: compiler.go:4:6: can only use //go:wasmimport on declarations\n// ERROR: compiler.go:8:5: global variable alignment must be a positive power of two\n// ERROR: compiler.go:13:23: missing function body\n"
  },
  {
    "path": "testdata/errors/importcycle/cycle.go",
    "content": "package importcycle\n\nimport _ \"github.com/tinygo-org/tinygo/testdata/errors/importcycle\"\n"
  },
  {
    "path": "testdata/errors/interp.go",
    "content": "package main\n\nimport _ \"unsafe\"\n\nfunc init() {\n\tfoo()\n}\n\nfunc foo() {\n\tinterp_test_error()\n}\n\n// This is a function that always causes an error in interp, for testing.\n//\n//go:linkname interp_test_error __tinygo_interp_raise_test_error\nfunc interp_test_error()\n\nfunc main() {\n}\n\n// ERROR: # main\n// ERROR: {{.*testdata[\\\\/]errors[\\\\/]interp\\.go}}:10:19: test error\n// ERROR:   call void @__tinygo_interp_raise_test_error{{.*}}\n// ERROR: {{}}\n// ERROR: traceback:\n// ERROR: {{.*testdata[\\\\/]errors[\\\\/]interp\\.go}}:10:19:\n// ERROR:   call void @__tinygo_interp_raise_test_error{{.*}}\n// ERROR: {{.*testdata[\\\\/]errors[\\\\/]interp\\.go}}:6:5:\n// ERROR:   call void @main.foo{{.*}}\n// ERROR: {{.*testdata[\\\\/]errors}}:\n// ERROR:   call void @\"main.init#1\"{{.*}}\n"
  },
  {
    "path": "testdata/errors/invaliddep/invaliddep.go",
    "content": "ppackage // syntax error\n"
  },
  {
    "path": "testdata/errors/invalidmain.go",
    "content": "// some comment to move the first line\n\npackage foobar\n\n// ERROR: # command-line-arguments\n// ERROR: invalidmain.go:3:9: expected main package to have name \"main\", not \"foobar\"\n"
  },
  {
    "path": "testdata/errors/invalidname/invalidname.go",
    "content": "// some comment to move the 'package' line\n\npackage _\n"
  },
  {
    "path": "testdata/errors/invalidname.go",
    "content": "package main\n\nimport _ \"github.com/tinygo-org/tinygo/testdata/errors/invalidname\"\n\n// ERROR: # github.com/tinygo-org/tinygo/testdata/errors/invalidname\n// ERROR: invalidname{{[\\\\/]}}invalidname.go:3:9: invalid package name _\n"
  },
  {
    "path": "testdata/errors/linker-flashoverflow.go",
    "content": "package main\n\nimport \"unsafe\"\n\nconst (\n\ta = \"0123456789abcdef\"            // 16 bytes\n\tb = a + a + a + a + a + a + a + a // 128 bytes\n\tc = b + b + b + b + b + b + b + b // 1024 bytes\n\td = c + c + c + c + c + c + c + c // 8192 bytes\n\te = d + d + d + d + d + d + d + d // 65536 bytes\n\tf = e + e + e + e + e + e + e + e // 524288 bytes\n)\n\nvar s = f\n\nfunc main() {\n\tprintln(unsafe.StringData(s))\n}\n\n// ERROR: program too large for this chip (flash overflowed by {{[0-9]+}} bytes)\n// ERROR: \toptimization guide: https://tinygo.org/docs/guides/optimizing-binaries/\n"
  },
  {
    "path": "testdata/errors/linker-ramoverflow.go",
    "content": "package main\n\nvar b [64 << 10]byte // 64kB\n\nfunc main() {\n\tprintln(\"ptr:\", &b[0])\n}\n\n// ERROR: program uses too much static RAM on this chip (RAM overflowed by {{[0-9]+}} bytes)\n"
  },
  {
    "path": "testdata/errors/linker-undefined.go",
    "content": "package main\n\nfunc foo()\n\nfunc main() {\n\tfoo()\n\tfoo()\n}\n\n// ERROR: linker-undefined.go:6: linker could not find symbol {{_?}}main.foo\n// ERROR: linker-undefined.go:7: linker could not find symbol {{_?}}main.foo\n"
  },
  {
    "path": "testdata/errors/loader-importcycle.go",
    "content": "package main\n\nimport _ \"github.com/tinygo-org/tinygo/testdata/errors/importcycle\"\n\nfunc main() {\n}\n\n// ERROR: package command-line-arguments\n// ERROR: \timports github.com/tinygo-org/tinygo/testdata/errors/importcycle\n// ERROR: \timports github.com/tinygo-org/tinygo/testdata/errors/importcycle: import cycle not allowed\n"
  },
  {
    "path": "testdata/errors/loader-invaliddep.go",
    "content": "package main\n\nimport _ \"github.com/tinygo-org/tinygo/testdata/errors/invaliddep\"\n\nfunc main() {\n}\n\n// ERROR: invaliddep{{[\\\\/]}}invaliddep.go:1:1: expected 'package', found ppackage\n"
  },
  {
    "path": "testdata/errors/loader-invalidpackage.go",
    "content": "ppackage // syntax error\n\n// ERROR: loader-invalidpackage.go:1:1: expected 'package', found ppackage\n"
  },
  {
    "path": "testdata/errors/loader-nopackage.go",
    "content": "package main\n\nimport (\n\t_ \"github.com/tinygo-org/tinygo/testdata/errors/non-existing-package\"\n\t_ \"github.com/tinygo-org/tinygo/testdata/errors/non-existing-package-2\"\n)\n\nfunc main() {\n}\n\n// ERROR: loader-nopackage.go:4:2: no required module provides package github.com/tinygo-org/tinygo/testdata/errors/non-existing-package; to add it:\n// ERROR: \tgo get github.com/tinygo-org/tinygo/testdata/errors/non-existing-package\n// ERROR: loader-nopackage.go:5:2: no required module provides package github.com/tinygo-org/tinygo/testdata/errors/non-existing-package-2; to add it:\n// ERROR: \tgo get github.com/tinygo-org/tinygo/testdata/errors/non-existing-package-2\n"
  },
  {
    "path": "testdata/errors/optimizer.go",
    "content": "package main\n\nimport \"runtime/interrupt\"\n\nvar num = 5\n\nfunc main() {\n\t// Error coming from LowerInterrupts.\n\tinterrupt.New(num, func(interrupt.Interrupt) {\n\t})\n\n\t// 2nd error\n\tinterrupt.New(num, func(interrupt.Interrupt) {\n\t})\n}\n\n// ERROR: # command-line-arguments\n// ERROR: optimizer.go:9:15: interrupt ID is not a constant\n// ERROR: optimizer.go:13:15: interrupt ID is not a constant\n"
  },
  {
    "path": "testdata/errors/syntax.go",
    "content": "package main\n\nfunc main(var) { // syntax error\n}\n\n// ERROR: # command-line-arguments\n// ERROR: syntax.go:3:11: expected ')', found 'var'\n"
  },
  {
    "path": "testdata/errors/types.go",
    "content": "package main\n\nfunc main() {\n\tvar a int\n\ta = \"foobar\"\n\tnonexisting()\n}\n\n// ERROR: # command-line-arguments\n// ERROR: types.go:4:6: declared and not used: a\n// ERROR: types.go:5:6: cannot use \"foobar\" (untyped string constant) as int value in assignment\n// ERROR: types.go:6:2: undefined: nonexisting\n"
  },
  {
    "path": "testdata/filesystem.go",
    "content": "package main\n\nimport (\n\t\"errors\"\n\t\"io\"\n\t\"io/fs\"\n\t\"os\"\n)\n\nfunc main() {\n\t_, err := os.Open(\"non-exist\")\n\tif !errors.Is(err, fs.ErrNotExist) {\n\t\tpanic(\"should be non exist error\")\n\t}\n\n\tf, err := os.Open(\"testdata/filesystem.txt\")\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tdefer func() {\n\t\tif err := f.Close(); err != nil {\n\t\t\tpanic(err)\n\t\t}\n\n\t\t// read after close: error should be returned\n\t\t_, err := f.Read(make([]byte, 10))\n\t\tif err == nil {\n\t\t\tpanic(\"error expected for reading after closing files\")\n\t\t}\n\t}()\n\n\tdata, err := io.ReadAll(f)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tos.Stdout.Write(data)\n\n\tpath, err := os.Getwd()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tif path == \"\" {\n\t\tpanic(\"path is empty\")\n\t}\n}\n"
  },
  {
    "path": "testdata/filesystem.txt",
    "content": "abcdefg\n1\n2\n3\n4\n5\n"
  },
  {
    "path": "testdata/float.go",
    "content": "package main\n\nfunc main() {\n\t// sanity\n\tprintln(3.14159265358979323846)\n\n\t// float64\n\tf64 := float64(2) / float64(3)\n\tprintln(f64)\n\tprintln(f64 + 1.0)\n\tprintln(f64 - 1.0)\n\tprintln(f64 * 2.0)\n\tprintln(f64 / 2.0)\n\n\t// float32\n\tf32 := float32(2) / float32(3)\n\tprintln(f32)\n\tprintln(f32 + 1.0)\n\tprintln(f32 - 1.0)\n\tprintln(f32 * 2.0)\n\tprintln(f32 / 2.0)\n\n\t// casting\n\tprintln(float32(f64))\n\tprintln(float64(f32))\n\n\t// float -> int\n\tvar f1 float32 = 3.3\n\tvar f2 float32 = 5.7\n\tvar f3 float32 = -2.3\n\tvar f4 float32 = -11.8\n\tprintln(int32(f1), int32(f2), int32(f3), int32(f4))\n\n\t// float -> int saturating behavior\n\tvar f5 float32 = -1\n\tvar f6 float32 = 256\n\tvar f7 float32 = -129\n\tf8 := float32(^uint32(0))\n\tf9 := float32(int32(-2147483648))\n\tf10 := float32(int32(2147483647))\n\tvar inf float32 = 1\n\tinf /= 0\n\tvar nan float32 = 0\n\tnan /= 0\n\tprintln(uint8(f5), uint8(f6), int8(f7), int8(f6), uint32(f8), int32(f9), int32(f10),\n\t\tuint8(inf), uint8(-inf), int8(inf), int8(-inf), uint8(nan), int64(nan))\n\n\t// int -> float\n\tvar i1 int32 = 53\n\tvar i2 int32 = -8\n\tvar i3 uint32 = 20\n\tprintln(float32(i1), float32(i2), float32(i3))\n\n\t// complex64\n\tc64 := complex(f32, 1.2)\n\tprintln(c64)\n\tprintln(real(c64))\n\tprintln(imag(c64))\n\n\t// complex128\n\tc128 := complex(f64, -2.0)\n\tprintln(c128)\n\tprintln(real(c128))\n\tprintln(imag(c128))\n\n\t// untyped complex\n\tprintln(2 + 1i)\n\tprintln(complex(2, -2))\n\n\t// cast complex\n\tprintln(complex64(c128))\n\tprintln(complex128(c64))\n\n\t// binops and negate on complex numbers\n\tc64 = 5 + 2i\n\tprintln(\"complex64 add: \", c64+-3+8i)\n\tprintln(\"complex64 sub: \", c64 - -3 + 8i)\n\tprintln(\"complex64 mul: \", c64*-3+8i)\n\tprintln(\"complex64 div: \", c64/-3+8i)\n\tprintln(\"complex64 neg: \", -c64)\n\tc128 = -5 + 2i\n\tprintln(\"complex128 add:\", c128+2+6i)\n\tprintln(\"complex128 sub:\", c128-2+6i)\n\tprintln(\"complex128 mul:\", c128*2+6i)\n\tprintln(\"complex128 div:\", c128/2+6i)\n\tprintln(\"complex128 neg:\", -c128)\n}\n"
  },
  {
    "path": "testdata/float.txt",
    "content": "+3.141593e+000\n+6.666667e-001\n+1.666667e+000\n-3.333333e-001\n+1.333333e+000\n+3.333333e-001\n+6.666667e-001\n+1.666667e+000\n-3.333333e-001\n+1.333333e+000\n+3.333333e-001\n+6.666667e-001\n+6.666667e-001\n3 5 -2 -11\n0 255 -128 127 4294967295 -2147483648 2147483647 255 0 127 -128 0 0\n+5.300000e+001 -8.000000e+000 +2.000000e+001\n(+6.666667e-001+1.200000e+000i)\n+6.666667e-001\n+1.200000e+000\n(+6.666667e-001-2.000000e+000i)\n+6.666667e-001\n-2.000000e+000\n(+2.000000e+000+1.000000e+000i)\n(+2.000000e+000-2.000000e+000i)\n(+6.666667e-001-2.000000e+000i)\n(+6.666667e-001+1.200000e+000i)\ncomplex64 add:  (+2.000000e+000+1.000000e+001i)\ncomplex64 sub:  (+8.000000e+000+1.000000e+001i)\ncomplex64 mul:  (-1.500000e+001+2.000000e+000i)\ncomplex64 div:  (-1.666667e+000+7.333333e+000i)\ncomplex64 neg:  (-5.000000e+000-2.000000e+000i)\ncomplex128 add: (-3.000000e+000+8.000000e+000i)\ncomplex128 sub: (-7.000000e+000+8.000000e+000i)\ncomplex128 mul: (-1.000000e+001+1.000000e+001i)\ncomplex128 div: (-2.500000e+000+7.000000e+000i)\ncomplex128 neg: (+5.000000e+000-2.000000e+000i)\n"
  },
  {
    "path": "testdata/gc.go",
    "content": "package main\n\nimport \"runtime\"\n\nvar xorshift32State uint32 = 1\n\nfunc xorshift32(x uint32) uint32 {\n\t// Algorithm \"xor\" from p. 4 of Marsaglia, \"Xorshift RNGs\"\n\tx ^= x << 13\n\tx ^= x >> 17\n\tx ^= x << 5\n\treturn x\n}\n\nfunc randuint32() uint32 {\n\txorshift32State = xorshift32(xorshift32State)\n\treturn xorshift32State\n}\n\nfunc main() {\n\ttestNonPointerHeap()\n\ttestKeepAlive()\n}\n\nvar scalarSlices [4][]byte\nvar randSeeds [4]uint32\n\nfunc testNonPointerHeap() {\n\tmaxSliceSize := uint32(1024)\n\tif ^uintptr(0) <= 0xffff {\n\t\t// 16-bit and lower devices, such as AVR.\n\t\t// Heap size is a real issue there, while it is still useful to run\n\t\t// these tests. Therefore, lower the max slice size.\n\t\tmaxSliceSize = 64\n\t}\n\t// Allocate roughly 0.5MB of memory.\n\tfor i := 0; i < 1000; i++ {\n\t\t// Pick a random index that the optimizer can't predict.\n\t\tindex := randuint32() % 4\n\n\t\t// Check whether the contents of the previous allocation was correct.\n\t\trand := randSeeds[index]\n\t\tfor _, b := range scalarSlices[index] {\n\t\t\trand = xorshift32(rand)\n\t\t\tif b != byte(rand) {\n\t\t\t\tpanic(\"memory was overwritten!\")\n\t\t\t}\n\t\t}\n\n\t\t// Allocate a randomly-sized slice, randomly sliced to be smaller.\n\t\tsliceLen := randuint32() % maxSliceSize\n\t\tslice := make([]byte, sliceLen)\n\t\tcutLen := randuint32() % maxSliceSize\n\t\tif cutLen < sliceLen {\n\t\t\tslice = slice[cutLen:]\n\t\t}\n\t\tscalarSlices[index] = slice\n\n\t\t// Fill the slice with a pattern that looks random but is easily\n\t\t// calculated and verified.\n\t\trand = randuint32() + 1\n\t\trandSeeds[index] = rand\n\t\tfor i := 0; i < len(slice); i++ {\n\t\t\trand = xorshift32(rand)\n\t\t\tslice[i] = byte(rand)\n\t\t}\n\t}\n\tprintln(\"ok\")\n}\n\nfunc testKeepAlive() {\n\t// There isn't much we can test, but at least we can test that\n\t// runtime.KeepAlive compiles correctly.\n\tvar x int\n\truntime.KeepAlive(&x)\n}\n"
  },
  {
    "path": "testdata/gc.txt",
    "content": "ok\n"
  },
  {
    "path": "testdata/generics/testa/testa.go",
    "content": "package testa\n\nimport (\n\t\"github.com/tinygo-org/tinygo/testdata/generics/value\"\n)\n\nfunc Test() {\n\tv := value.New(1)\n\tvm := value.Map(v, Plus100)\n\tvm.Get(callback, callback)\n}\n\nfunc callback(v int) {\n\tprintln(\"value:\", v)\n}\n\n// Plus100 is a `Transform` that adds 100 to `value`.\nfunc Plus100(value int) int {\n\treturn value + 100\n}\n"
  },
  {
    "path": "testdata/generics/testb/testb.go",
    "content": "package testb\n\nimport (\n\t\"github.com/tinygo-org/tinygo/testdata/generics/value\"\n)\n\nfunc Test() {\n\tv := value.New(1)\n\tvm := value.Map(v, Plus500)\n\tvm.Get(callback, callback)\n}\n\nfunc callback(v int) {\n\tprintln(\"value:\", v)\n}\n\n// Plus500 is a `Transform` that adds 500 to `value`.\nfunc Plus500(value int) int {\n\treturn value + 500\n}\n"
  },
  {
    "path": "testdata/generics/value/value.go",
    "content": "package value\n\ntype (\n\tValue[T any] interface {\n\t\tGet(Callback[T], Callback[T])\n\t}\n\n\tCallback[T any] func(T)\n\n\tTransform[S any, D any] func(S) D\n)\n\nfunc New[T any](v T) Value[T] {\n\treturn &value[T]{\n\t\tv: v,\n\t}\n}\n\ntype value[T any] struct {\n\tv T\n}\n\nfunc (v *value[T]) Get(fn1, fn2 Callback[T]) {\n\t// For example purposes.\n\t// Normally would be asynchronous callback.\n\tfn1(v.v)\n\tfn2(v.v)\n}\n\nfunc Map[S, D any](v Value[S], tx Transform[S, D]) Value[D] {\n\treturn &mapper[S, D]{\n\t\tv:  v,\n\t\ttx: tx,\n\t}\n}\n\ntype mapper[S, D any] struct {\n\tv  Value[S]\n\ttx Transform[S, D]\n}\n\nfunc (m *mapper[S, D]) Get(fn1, fn2 Callback[D]) {\n\t// two callbacks are passed to generate more than\n\t// one anonymous function symbol name.\n\tm.v.Get(func(v S) {\n\t\t// anonymous function inside of anonymous function.\n\t\tfunc() {\n\t\t\tfn1(m.tx(v))\n\t\t}()\n\t}, func(v S) {\n\t\tfn2(m.tx(v))\n\t})\n}\n"
  },
  {
    "path": "testdata/generics.go",
    "content": "package main\n\nimport (\n\t\"github.com/tinygo-org/tinygo/testdata/generics/testa\"\n\t\"github.com/tinygo-org/tinygo/testdata/generics/testb\"\n)\n\nfunc main() {\n\tprintln(\"add:\", Add(3, 5))\n\tprintln(\"add:\", Add(int8(3), 5))\n\n\tvar c C[int]\n\tc.F() // issue 2951\n\n\tSliceOp([]int(nil)) // issue 3002\n\n\ttesta.Test()\n\ttestb.Test()\n}\n\ntype Integer interface {\n\tint | int8 | int16 | int32 | int64\n}\n\nfunc Add[T Integer](a, b T) T {\n\treturn a + b\n}\n\n// Test for https://github.com/tinygo-org/tinygo/issues/2951\ntype C[V any] struct{}\n\nfunc (c *C[V]) F() {}\n\n// Test for https://github.com/tinygo-org/tinygo/issues/3002\nfunc SliceOp[S ~[]E, E any](s S) {}\n"
  },
  {
    "path": "testdata/generics.txt",
    "content": "add: 8\nadd: 8\nvalue: 101\nvalue: 101\nvalue: 501\nvalue: 501\n"
  },
  {
    "path": "testdata/go1.21.go",
    "content": "package main\n\nfunc main() {\n\t// The new min/max builtins.\n\tia := 1\n\tib := 5\n\tic := -3\n\tfa := 1.0\n\tfb := 5.0\n\tfc := -3.0\n\tprintln(\"min/max:\", min(ia, ib, ic), max(ia, ib, ic))\n\tprintln(\"min/max:\", min(fa, fb, fc), max(fa, fb, fc))\n\n\t// The clear builtin, for slices.\n\ts := []int{1, 2, 3, 4, 5}\n\tclear(s[:3])\n\tprintln(\"cleared s[:3]:\", s[0], s[1], s[2], s[3], s[4])\n\n\t// The clear builtin, for maps.\n\tm := map[int]string{\n\t\t1: \"one\",\n\t\t2: \"two\",\n\t\t3: \"three\",\n\t}\n\tclear(m)\n\tprintln(\"cleared map:\", m[1], m[2], m[3], len(m))\n\tm[4] = \"four\"\n\tprintln(\"added to cleared map:\", m[1], m[2], m[3], m[4], len(m))\n}\n"
  },
  {
    "path": "testdata/go1.21.txt",
    "content": "min/max: -3 5\nmin/max: -3.000000e+000 +5.000000e+000\ncleared s[:3]: 0 0 0 4 5\ncleared map:    0\nadded to cleared map:    four 1\n"
  },
  {
    "path": "testdata/go1.22/go.mod",
    "content": "module github.com/tinygo-org/tinygo/testdata/go1.22\n\ngo 1.22\n"
  },
  {
    "path": "testdata/go1.22/main.go",
    "content": "package main\n\nfunc main() {\n\ttestIntegerRange()\n\ttestLoopVar()\n}\n\nfunc testIntegerRange() {\n\tfor i := range 10 {\n\t\tprintln(10 - i)\n\t}\n\tprintln(\"go1.22 has lift-off!\")\n}\n\nfunc testLoopVar() {\n\tvar f func() int\n\tfor i := 0; i < 1; i++ {\n\t\tif i == 0 {\n\t\t\tf = func() int { return i }\n\t\t}\n\t}\n\t// Variable n is 1 in Go 1.21, or 0 in Go 1.22.\n\tn := f()\n\tif n == 0 {\n\t\tprintln(\"loops behave like Go 1.22\")\n\t} else if n == 1 {\n\t\tprintln(\"loops behave like Go 1.21\")\n\t} else {\n\t\tprintln(\"unknown loop behavior\")\n\t}\n}\n"
  },
  {
    "path": "testdata/go1.22/out.txt",
    "content": "10\n9\n8\n7\n6\n5\n4\n3\n2\n1\ngo1.22 has lift-off!\nloops behave like Go 1.22\n"
  },
  {
    "path": "testdata/go1.23/go.mod",
    "content": "module github.com/tinygo-org/tinygo/testdata/go1.23\n\ngo 1.23\n"
  },
  {
    "path": "testdata/go1.23/main.go",
    "content": "package main\n\nimport \"iter\"\n\nfunc main() {\n\ttestFuncRange(counter)\n\ttestIterPull(counter)\n\tprintln(\"go1.23 has lift-off!\")\n}\n\nfunc testFuncRange(it iter.Seq[int]) {\n\tfor i := range it {\n\t\tprintln(i)\n\t}\n}\n\nfunc testIterPull(it iter.Seq[int]) {\n\tnext, stop := iter.Pull(it)\n\tdefer stop()\n\tfor {\n\t\ti, ok := next()\n\t\tif !ok {\n\t\t\tbreak\n\t\t}\n\t\tprintln(i)\n\t}\n}\n\nfunc counter(yield func(int) bool) {\n\tfor i := 10; i >= 1; i-- {\n\t\tyield(i)\n\t}\n}\n"
  },
  {
    "path": "testdata/go1.23/out.txt",
    "content": "10\n9\n8\n7\n6\n5\n4\n3\n2\n1\n10\n9\n8\n7\n6\n5\n4\n3\n2\n1\ngo1.23 has lift-off!\n"
  },
  {
    "path": "testdata/goroutines.go",
    "content": "package main\n\nimport (\n\t\"sync\"\n\t\"time\"\n)\n\nfunc init() {\n\tprintln(\"init\")\n\tgo println(\"goroutine in init\")\n\ttime.Sleep(1 * time.Millisecond)\n}\n\nfunc main() {\n\tprintln(\"main 1\")\n\tgo sub()\n\ttime.Sleep(100 * time.Millisecond)\n\tprintln(\"main 2\")\n\ttime.Sleep(200 * time.Millisecond)\n\tprintln(\"main 3\")\n\n\t// Await a blocking call.\n\tprintln(\"wait:\")\n\twait()\n\tprintln(\"end waiting\")\n\n\tvalue := delayedValue()\n\tprintln(\"value produced after some time:\", value)\n\n\t// Run a non-blocking call in a goroutine. This should be turned into a\n\t// regular call, so should be equivalent to calling nowait() without 'go'\n\t// prefix.\n\tgo nowait()\n\ttime.Sleep(time.Millisecond)\n\tprintln(\"done with non-blocking goroutine\")\n\n\tvar printer Printer\n\tprinter = &myPrinter{}\n\tprinter.Print()\n\n\tsleepFuncValue(func(x int) {\n\t\ttime.Sleep(1 * time.Millisecond)\n\t\tprintln(\"slept inside func pointer\", x)\n\t})\n\ttime.Sleep(1 * time.Millisecond)\n\tn := 20\n\tsleepFuncValue(func(x int) {\n\t\ttime.Sleep(1 * time.Millisecond)\n\t\tprintln(\"slept inside closure, with value:\", n, x)\n\t})\n\n\ttime.Sleep(2 * time.Millisecond)\n\n\tvar x int\n\tgo func() {\n\t\ttime.Sleep(2 * time.Millisecond)\n\t\tx = 1\n\t}()\n\ttime.Sleep(time.Second / 2)\n\tprintln(\"closure go call result:\", x)\n\n\ttime.Sleep(2 * time.Millisecond)\n\n\tvar m sync.Mutex\n\tvar wg sync.WaitGroup\n\tm.Lock()\n\tprintln(\"pre-acquired mutex\")\n\twg.Add(1)\n\tgo acquire(&m, &wg)\n\ttime.Sleep(2 * time.Millisecond)\n\tprintln(\"releasing mutex\")\n\tm.Unlock()\n\twg.Wait()\n\ttime.Sleep(2 * time.Millisecond)\n\tm.Lock()\n\tprintln(\"re-acquired mutex\")\n\tm.Unlock()\n\tprintln(\"done\")\n\n\tstartSimpleFunc(emptyFunc)\n\n\ttime.Sleep(2 * time.Millisecond)\n\n\ttestGoOnBuiltins()\n\n\ttestGoOnInterface(Foo(0))\n\n\ttestIssue1790()\n\n\tdone := make(chan int)\n\tgo testPaddedParameters(paddedStruct{x: 5, y: 7}, done)\n\t<-done\n}\n\nfunc acquire(m *sync.Mutex, wg *sync.WaitGroup) {\n\tm.Lock()\n\twg.Done()\n\tprintln(\"acquired mutex from goroutine\")\n\ttime.Sleep(2 * time.Millisecond)\n\tprintln(\"releasing mutex from goroutine\")\n\tm.Unlock()\n}\n\nfunc sub() {\n\tprintln(\"sub 1\")\n\ttime.Sleep(200 * time.Millisecond)\n\tprintln(\"sub 2\")\n}\n\nfunc wait() {\n\tprintln(\"  wait start\")\n\ttime.Sleep(time.Millisecond)\n\tprintln(\"  wait end\")\n}\n\nfunc delayedValue() int {\n\ttime.Sleep(time.Millisecond)\n\treturn 42\n}\n\nfunc sleepFuncValue(fn func(int)) {\n\tgo fn(8)\n}\n\nfunc startSimpleFunc(fn simpleFunc) {\n\t// Test that named function types don't crash the compiler.\n\tgo fn()\n}\n\nfunc nowait() {\n\tprintln(\"non-blocking goroutine\")\n}\n\ntype Printer interface {\n\tPrint()\n}\n\ntype myPrinter struct {\n}\n\nfunc (i *myPrinter) Print() {\n\ttime.Sleep(time.Millisecond)\n\tprintln(\"async interface method call\")\n}\n\ntype simpleFunc func()\n\nfunc emptyFunc() {\n}\n\nfunc testGoOnBuiltins() {\n\t// Test copy builtin (there is no non-racy practical use of this).\n\tgo copy(make([]int, 8), []int{2, 5, 8, 4})\n\n\t// Test recover builtin (no-op).\n\tgo recover()\n\n\t// Test close builtin.\n\tch := make(chan int)\n\tgo close(ch)\n\tn, ok := <-ch\n\tif n != 0 || ok != false {\n\t\tprintln(\"error: expected closed channel to return 0, false\")\n\t}\n\n\t// Test delete builtin.\n\tm := map[string]int{\"foo\": 3}\n\tgo delete(m, \"foo\")\n\ttime.Sleep(time.Millisecond)\n\tv, ok := m[\"foo\"]\n\tif v != 0 || ok != false {\n\t\tprintln(\"error: expected deleted map entry to be 0, false\")\n\t}\n}\n\nvar once sync.Once\n\nvar waitChan = make(chan struct{})\n\nfunc testGoOnInterface(f Itf) {\n\tgo f.Nowait()\n\ttime.Sleep(time.Millisecond)\n\tgo f.Wait()\n\t<-waitChan\n\ttime.Sleep(time.Millisecond * 2)\n\tprintln(\"done with 'go on interface'\")\n}\n\n// This tests a fix for issue 1790:\n// https://github.com/tinygo-org/tinygo/issues/1790\nfunc testIssue1790() *int {\n\tonce.Do(func() {})\n\ti := 0\n\treturn &i\n}\n\ntype Itf interface {\n\tNowait()\n\tWait()\n}\n\ntype Foo string\n\nfunc (f Foo) Nowait() {\n\tprintln(\"called: Foo.Nowait\")\n}\n\nfunc (f Foo) Wait() {\n\tprintln(\"called: Foo.Wait\")\n\tclose(waitChan)\n\ttime.Sleep(time.Microsecond)\n\tprintln(\"  ...waited\")\n}\n\ntype paddedStruct struct {\n\tx uint8\n\t_ [0]int64\n\ty uint8\n}\n\n// Structs with interesting padding used to crash.\nfunc testPaddedParameters(s paddedStruct, done chan int) {\n\tprintln(\"paddedStruct:\", s.x, s.y)\n\tclose(done)\n}\n"
  },
  {
    "path": "testdata/goroutines.txt",
    "content": "init\ngoroutine in init\nmain 1\nsub 1\nmain 2\nsub 2\nmain 3\nwait:\n  wait start\n  wait end\nend waiting\nvalue produced after some time: 42\nnon-blocking goroutine\ndone with non-blocking goroutine\nasync interface method call\nslept inside func pointer 8\nslept inside closure, with value: 20 8\nclosure go call result: 1\npre-acquired mutex\nreleasing mutex\nacquired mutex from goroutine\nreleasing mutex from goroutine\nre-acquired mutex\ndone\ncalled: Foo.Nowait\ncalled: Foo.Wait\n  ...waited\ndone with 'go on interface'\npaddedStruct: 5 7\n"
  },
  {
    "path": "testdata/init.go",
    "content": "package main\n\nfunc init() {\n\tprintln(\"init\")\n}\n\nfunc main() {\n\tprintln(\"main\")\n\tprintln(\"v1:\", v1)\n\tprintln(\"v2:\", v2.x, v2.y)\n\tprintln(\"v3:\", len(v3), cap(v3), v3[0], v3[3])\n\tprintln(\"v4:\", len(v4), v4 == nil)\n\tprintln(\"v5:\", len(v5), v5 == nil)\n\tprintln(\"v6:\", v6)\n\tprintln(\"v7:\", cap(v7), string(v7))\n\tprintln(\"v8:\", v8)\n\tprintln(\"v9:\", len(v9), v9[0], v9[1], v9[2])\n\n\tprintln(uint8SliceSrc[0])\n\tprintln(uint8SliceDst[0])\n\tprintln(intSliceSrc[0])\n\tprintln(intSliceDst[0])\n}\n\ntype (\n\tt2 struct {\n\t\tx int\n\t\ty int\n\t}\n)\n\nvar (\n\tv1 = 3\n\tv2 = t2{2, 5}\n\tv3 = []int{2, 3, 5, 7}\n\tv4 map[string]int\n\tv5 = map[string]int{}\n\tv6 = float64(v1) < 2.6\n\tv7 = []byte(\"foo\")\n\tv8 string\n\tv9 []int\n\n\tuint8SliceSrc = []uint8{3, 100}\n\tuint8SliceDst []uint8\n\tintSliceSrc   = []int16{5, 123, 1024}\n\tintSliceDst   []int16\n\n\tsomeList    *linkedList\n\tsomeBigList *bigLinkedList\n)\n\ntype linkedList struct {\n\tprev *linkedList\n\tnext *linkedList\n\tv    int // arbitrary value (don't care)\n}\n\nfunc init() {\n\tsomeList = &linkedList{\n\t\tv: -1,\n\t}\n\tfor i := 0; i < 3; i++ {\n\t\tprev := someList\n\t\tsomeList = &linkedList{\n\t\t\tv:    i,\n\t\t\tprev: prev,\n\t\t}\n\t\tprev.next = someList\n\t}\n}\n\ntype bigLinkedList struct {\n\tprev *bigLinkedList\n\tnext *bigLinkedList\n\tv    int\n\tbuf  [100]*int\n}\n\nfunc init() {\n\t// Create a circular reference.\n\tsomeBigList = &bigLinkedList{\n\t\tv: -1,\n\t}\n\tfor i := 0; i < 3; i++ {\n\t\tprev := someBigList\n\t\tsomeBigList = &bigLinkedList{\n\t\t\tv:    i,\n\t\t\tprev: prev,\n\t\t}\n\t\tprev.next = someBigList\n\t}\n}\n\nfunc init() {\n\tuint8SliceDst = make([]uint8, len(uint8SliceSrc))\n\tcopy(uint8SliceDst, uint8SliceSrc)\n\n\tintSliceDst = make([]int16, len(intSliceSrc))\n\tcopy(intSliceDst, intSliceSrc)\n\n\tv8 = sliceString(\"foobarbaz\", 3, 8)\n\tv9 = sliceSlice([]int{0, 1, 2, 3, 4, 5}, 2, 5)\n}\n\nfunc sliceString(s string, start, end int) string {\n\treturn s[start:end]\n}\n\nfunc sliceSlice(s []int, start, end int) []int {\n\treturn s[start:end]\n}\n\ntype outside struct{}\n\nfunc init() {\n\t_, _ = any(0).(interface{ DoesNotExist() })\n\t_, _ = any(\"\").(interface{ DoesNotExist() })\n\t_, _ = any(outside{}).(interface{ DoesNotExist() })\n\n\ttype inside struct{}\n\t_, _ = any(inside{}).(interface{ DoesNotExist() })\n}\n"
  },
  {
    "path": "testdata/init.txt",
    "content": "init\nmain\nv1: 3\nv2: 2 5\nv3: 4 4 2 7\nv4: 0 true\nv5: 0 false\nv6: false\nv7: 3 foo\nv8: barba\nv9: 3 2 3 4\n3\n3\n5\n5\n"
  },
  {
    "path": "testdata/init_multi.go",
    "content": "package main\n\nfunc init() {\n\tprintln(\"init1\")\n}\n\nfunc init() {\n\tprintln(\"init2\")\n}\n\nfunc main() {\n\tprintln(\"main\")\n}\n"
  },
  {
    "path": "testdata/init_multi.txt",
    "content": "init1\ninit2\nmain\n"
  },
  {
    "path": "testdata/interface.go",
    "content": "package main\n\nimport \"time\"\n\nfunc main() {\n\tthing := &Thing{\"foo\"}\n\tprintln(\"thing:\", thing.String())\n\tthing.Print()\n\tprintItf(5)\n\tprintItf(byte('x'))\n\tprintItf(\"foo\")\n\tprintItf(Foo(18))\n\tprintItf(*thing)\n\tprintItf(thing)\n\tprintItf(Stringer(thing))\n\tprintItf(struct{ n int }{})\n\tprintItf(struct {\n\t\tn int `foo:\"bar\"`\n\t}{})\n\tprintItf(Number(3))\n\tarray := Array([4]uint32{1, 7, 11, 13})\n\tprintItf(array)\n\tprintItf(ArrayStruct{3, array})\n\tprintItf(SmallPair{3, 5})\n\ts := Stringer(thing)\n\tprintln(\"Stringer.String():\", s.String())\n\tvar itf interface{} = s\n\tprintln(\"Stringer.(*Thing).String():\", itf.(Stringer).String())\n\tif s, ok := s.(interface{ String() string }); ok {\n\t\tprintln(\"s has String() method:\", s.String())\n\t}\n\n\tprintln(\"nested switch:\", nestedSwitch('v', 3))\n\n\t// Try putting a linked list in an interface:\n\t// https://github.com/tinygo-org/tinygo/issues/309\n\titf = linkedList{}\n\n\t// Test bugfix for assertion on named empty interface:\n\t// https://github.com/tinygo-org/tinygo/issues/453\n\t_, _ = itf.(Empty)\n\n\tvar v Byter = FooByte(3)\n\tprintln(\"Byte(): \", v.Byte())\n\n\tvar n int\n\tvar f float32\n\tvar interfaceEqualTests = []struct {\n\t\tequal bool\n\t\tlhs   interface{}\n\t\trhs   interface{}\n\t}{\n\t\t{true, true, true},\n\t\t{true, int(1), int(1)},\n\t\t{true, int8(1), int8(1)},\n\t\t{true, int16(1), int16(1)},\n\t\t{true, int32(1), int32(1)},\n\t\t{true, int64(1), int64(1)},\n\t\t{true, uint(1), uint(1)},\n\t\t{false, uint(1), uint(2)},\n\t\t{true, uint8(1), uint8(1)},\n\t\t{true, uint16(1), uint16(1)},\n\t\t{true, uint32(1), uint32(1)},\n\t\t{true, uint64(1), uint64(1)},\n\t\t{true, uintptr(1), uintptr(1)},\n\t\t{true, float32(1.1), float32(1.1)},\n\t\t{true, float64(1.1), float64(1.1)},\n\t\t{true, complex(100, 8), complex(100, 8)},\n\t\t{false, complex(100, 8), complex(101, 8)},\n\t\t{false, complex(100, 8), complex(100, 9)},\n\t\t{true, complex64(8), complex64(8)},\n\t\t{true, complex128(8), complex128(8)},\n\t\t{true, \"string\", \"string\"},\n\t\t{false, \"string\", \"stringx\"},\n\t\t{true, [2]int16{-5, 201}, [2]int16{-5, 201}},\n\t\t{false, [2]int16{-5, 201}, [2]int16{-5, 202}},\n\t\t{false, [2]int16{-5, 201}, [2]int16{5, 201}},\n\t\t{true, &n, &n},\n\t\t{false, &n, new(int)},\n\t\t{false, new(int), new(int)},\n\t\t{false, &n, &f},\n\t\t{true, struct {\n\t\t\ta int\n\t\t\tb int\n\t\t}{3, 5}, struct {\n\t\t\ta int\n\t\t\tb int\n\t\t}{3, 5}},\n\t\t{false, struct {\n\t\t\ta int\n\t\t\tb int\n\t\t}{3, 5}, struct {\n\t\t\ta int\n\t\t\tb int\n\t\t}{3, 6}},\n\t\t{true, named1(), named1()},\n\t\t{true, named2(), named2()},\n\t\t{false, named1(), named2()},\n\t\t{false, named2(), named3()},\n\t\t{true, namedptr1(), namedptr1()},\n\t\t{false, namedptr1(), namedptr2()},\n\t}\n\tfor i, tc := range interfaceEqualTests {\n\t\tif (tc.lhs == tc.rhs) != tc.equal {\n\t\t\tprintln(\"test\", i, \"of interfaceEqualTests failed\")\n\t\t}\n\t}\n\n\t// test interface blocking\n\tblockDynamic(NonBlocker{})\n\tprintln(\"non-blocking call on sometimes-blocking interface\")\n\tblockDynamic(SleepBlocker(time.Millisecond))\n\tprintln(\"slept 1ms\")\n\tblockStatic(SleepBlocker(time.Millisecond))\n\tprintln(\"slept 1ms\")\n\n\t// check that pointer-to-pointer type switches work\n\tptrptrswitch()\n\n\t// check that type asserts to interfaces with no methods work\n\temptyintfcrash()\n}\n\nfunc printItf(val interface{}) {\n\tswitch val := val.(type) {\n\tcase Unmatched:\n\t\tpanic(\"matched the unmatchable\")\n\tcase Doubler:\n\t\tprintln(\"is Doubler:\", val.Double())\n\tcase Tuple:\n\t\tprintln(\"is Tuple:\", val.Nth(0), val.Nth(1), val.Nth(2), val.Nth(3))\n\t\tval.Print()\n\tcase int:\n\t\tprintln(\"is int:\", val)\n\tcase byte:\n\t\tprintln(\"is byte:\", val)\n\tcase string:\n\t\tprintln(\"is string:\", val)\n\tcase Thing:\n\t\tprintln(\"is Thing:\", val.String())\n\tcase *Thing:\n\t\tprintln(\"is *Thing:\", val.String())\n\tcase struct{ i int }:\n\t\tprintln(\"is struct{i int}\")\n\tcase struct{ n int }:\n\t\tprintln(\"is struct{n int}\")\n\tcase struct {\n\t\tn int `foo:\"bar\"`\n\t}:\n\t\tprintln(\"is struct{n int `foo:\\\"bar\\\"`}\")\n\tcase Foo:\n\t\tprintln(\"is Foo:\", val)\n\tdefault:\n\t\tprintln(\"is ?\")\n\t}\n}\n\nvar (\n\t// Test for type assert support in the interp package.\n\tglobalThing interface{} = Foo(3)\n\t_                       = globalThing.(Foo)\n)\n\nfunc nestedSwitch(verb rune, arg interface{}) bool {\n\tswitch verb {\n\tcase 'v', 's':\n\t\tswitch arg.(type) {\n\t\tcase int:\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc blockDynamic(blocker DynamicBlocker) {\n\tblocker.Block()\n}\n\nfunc blockStatic(blocker StaticBlocker) {\n\tblocker.Sleep()\n}\n\ntype Thing struct {\n\tname string\n}\n\nfunc (t Thing) String() string {\n\treturn t.name\n}\n\nfunc (t Thing) Print() {\n\tprintln(\"Thing.Print:\", t.name)\n}\n\ntype Stringer interface {\n\tString() string\n}\n\ntype Foo int\n\ntype Number int\n\nfunc (n Number) Double() int {\n\treturn int(n) * 2\n}\n\ntype Doubler interface {\n\tDouble() int\n}\n\ntype Tuple interface {\n\tNth(int) uint32\n\tPrint()\n}\n\ntype Array [4]uint32\n\nfunc (a Array) Nth(n int) uint32 {\n\treturn a[n]\n}\n\nfunc (a Array) Print() {\n\tprintln(\"Array len:\", len(a))\n}\n\ntype ArrayStruct struct {\n\tn int\n\ta Array\n}\n\nfunc (a ArrayStruct) Nth(n int) uint32 {\n\treturn a.a[n]\n}\n\nfunc (a ArrayStruct) Print() {\n\tprintln(\"ArrayStruct.Print:\", len(a.a), a.n)\n}\n\ntype SmallPair struct {\n\ta byte\n\tb byte\n}\n\nfunc (p SmallPair) Nth(n int) uint32 {\n\treturn uint32(int(p.a)*n + int(p.b)*n)\n}\n\nfunc (p SmallPair) Print() {\n\tprintln(\"SmallPair.Print:\", p.a, p.b)\n}\n\n// There is no type that matches this method.\ntype Unmatched interface {\n\tNeverImplementedMethod()\n}\n\ntype linkedList struct {\n\taddr *linkedList\n}\n\ntype DynamicBlocker interface {\n\tBlock()\n}\n\ntype NonBlocker struct{}\n\nfunc (b NonBlocker) Block() {}\n\ntype SleepBlocker time.Duration\n\nfunc (s SleepBlocker) Block() {\n\ttime.Sleep(time.Duration(s))\n}\n\nfunc (s SleepBlocker) Sleep() {\n\ts.Block()\n}\n\ntype StaticBlocker interface {\n\tSleep()\n}\n\ntype Empty interface{}\n\ntype FooByte int\n\nfunc (f FooByte) Byte() byte { return byte(f) }\n\ntype Byter interface {\n\tByte() uint8\n}\n\n// Make sure that named types inside functions do not alias with any other named\n// functions.\n\ntype named int\n\nfunc named1() any {\n\treturn named(0)\n}\n\nfunc named2() any {\n\ttype named int\n\treturn named(0)\n}\n\nfunc named3() any {\n\ttype named int\n\treturn named(0)\n}\n\nfunc namedptr1() interface{} {\n\ttype Test int\n\treturn (*Test)(nil)\n}\n\nfunc namedptr2() interface{} {\n\ttype Test byte\n\treturn (*Test)(nil)\n}\n\nfunc ptrptrswitch() {\n\tidentify(0)\n\tidentify(new(int))\n\tidentify(new(*int))\n}\n\nfunc identify(itf any) {\n\tswitch itf.(type) {\n\tcase int:\n\t\tprintln(\"type is int\")\n\tcase *int:\n\t\tprintln(\"type is *int\")\n\tcase **int:\n\t\tprintln(\"type is **int\")\n\tdefault:\n\t\tprintln(\"other type??\")\n\t}\n}\n\nfunc emptyintfcrash() {\n\tif x, ok := any(5).(any); ok {\n\t\tprintln(\"x is\", x.(int))\n\t}\n}\n"
  },
  {
    "path": "testdata/interface.txt",
    "content": "thing: foo\nThing.Print: foo\nis int: 5\nis byte: 120\nis string: foo\nis Foo: 18\nis Thing: foo\nis *Thing: foo\nis *Thing: foo\nis struct{n int}\nis struct{n int `foo:\"bar\"`}\nis Doubler: 6\nis Tuple: 1 7 11 13\nArray len: 4\nis Tuple: 1 7 11 13\nArrayStruct.Print: 4 3\nis Tuple: 0 8 16 24\nSmallPair.Print: 3 5\nStringer.String(): foo\nStringer.(*Thing).String(): foo\ns has String() method: foo\nnested switch: true\nByte():  3\nnon-blocking call on sometimes-blocking interface\nslept 1ms\nslept 1ms\ntype is int\ntype is *int\ntype is **int\nx is 5\n"
  },
  {
    "path": "testdata/json.go",
    "content": "package main\n\nimport (\n\t\"encoding/json\"\n)\n\nfunc main() {\n\tprintln(\"int:\", encode(3))\n\tprintln(\"float64:\", encode(3.14))\n\tprintln(\"string:\", encode(\"foo\"))\n\tprintln(\"slice of strings:\", encode([]string{\"foo\", \"bar\"}))\n}\n\nfunc encode(itf interface{}) string {\n\tbuf, err := json.Marshal(itf)\n\tif err != nil {\n\t\tpanic(\"failed to JSON encode: \" + err.Error())\n\t}\n\treturn string(buf)\n}\n"
  },
  {
    "path": "testdata/json.txt",
    "content": "int: 3\nfloat64: 3.14\nstring: \"foo\"\nslice of strings: [\"foo\",\"bar\"]\n"
  },
  {
    "path": "testdata/ldflags.go",
    "content": "package main\n\n// These globals can be changed using -ldflags=\"-X main.someGlobal=value\".\n// At the moment, only globals without an initializer can be replaced this way.\nvar someGlobal string\n\nfunc main() {\n\tprintln(\"someGlobal:\", someGlobal)\n}\n"
  },
  {
    "path": "testdata/ldflags.txt",
    "content": "someGlobal: foobar\n"
  },
  {
    "path": "testdata/map.go",
    "content": "package main\n\nimport (\n\t\"sort\"\n\t\"unsafe\"\n)\n\nvar testmap1 = map[string]int{\"data\": 3}\nvar testmap2 = map[string]int{\n\t\"one\":    1,\n\t\"two\":    2,\n\t\"three\":  3,\n\t\"four\":   4,\n\t\"five\":   5,\n\t\"six\":    6,\n\t\"seven\":  7,\n\t\"eight\":  8,\n\t\"nine\":   9,\n\t\"ten\":    10,\n\t\"eleven\": 11,\n\t\"twelve\": 12,\n}\n\ntype ArrayKey [4]byte\n\nvar testMapArrayKey = map[ArrayKey]int{\n\tArrayKey([4]byte{1, 2, 3, 4}): 1234,\n\tArrayKey([4]byte{4, 3, 2, 1}): 4321,\n}\nvar testmapIntInt = map[int]int{1: 1, 2: 4, 3: 9}\n\ntype namedFloat struct {\n\ts string\n\tf float32\n}\n\nfunc main() {\n\tm := map[string]int{\"answer\": 42, \"foo\": 3}\n\treadMap(m, \"answer\")\n\treadMap(testmap1, \"data\")\n\treadMap(testmap2, \"three\")\n\treadMap(testmap2, \"ten\")\n\tdelete(testmap2, \"six\")\n\treadMap(testmap2, \"seven\")\n\tlookup(testmap2, \"eight\")\n\tlookup(testmap2, \"nokey\")\n\n\t// operations on nil maps\n\tvar nilmap map[string]int\n\tprintln(m == nil, m != nil, len(m))\n\tprintln(nilmap == nil, nilmap != nil, len(nilmap))\n\tdelete(nilmap, \"foo\")\n\tprintln(\"nilmap:\", nilmap[\"bar\"])\n\tprintln(testmapIntInt[2])\n\ttestmapIntInt[2] = 42\n\tprintln(testmapIntInt[2])\n\tfor k := range nilmap {\n\t\tprintln(k) // unreachable\n\t}\n\n\tvar nilbinmap map[uint16]int\n\tdelete(nilbinmap, 4)\n\tprintln(\"nilbinmap:\", nilbinmap[5])\n\n\tarrKey := ArrayKey([4]byte{4, 3, 2, 1})\n\tprintln(testMapArrayKey[arrKey])\n\ttestMapArrayKey[arrKey] = 5555\n\tprintln(testMapArrayKey[arrKey])\n\n\t// test maps with interface keys\n\titfMap := map[interface{}]int{\n\t\t3.14:         3,\n\t\t8:            8,\n\t\tuint8(8):     80,\n\t\t\"eight\":      800,\n\t\t[2]int{5, 2}: 52,\n\t\ttrue:         1,\n\t}\n\tprintln(\"itfMap[3]:\", itfMap[3]) // doesn't exist\n\tprintln(\"itfMap[3.14]:\", itfMap[3.14])\n\tprintln(\"itfMap[8]:\", itfMap[8])\n\tprintln(\"itfMap[uint8(8)]:\", itfMap[uint8(8)])\n\tprintln(`itfMap[\"eight\"]:`, itfMap[\"eight\"])\n\tprintln(`itfMap[[2]int{5, 2}]:`, itfMap[[2]int{5, 2}])\n\tprintln(\"itfMap[true]:\", itfMap[true])\n\tdelete(itfMap, 8)\n\tprintln(\"itfMap[8]:\", itfMap[8])\n\tfor key, value := range itfMap {\n\t\tif key == \"eight\" {\n\t\t\tprintln(\"itfMap: found key \\\"eight\\\":\", value)\n\t\t}\n\t}\n\n\t// test map with float keys\n\tfloatMap := map[float32]int{\n\t\t42:   84,\n\t\t3.14: 6,\n\t}\n\tprintln(\"floatMap[42]:\", floatMap[42])\n\tprintln(\"floatMap[43]:\", floatMap[43])\n\tdelete(floatMap, 42)\n\tprintln(\"floatMap[42]:\", floatMap[42])\n\tfor k, v := range floatMap {\n\t\tprintln(\"floatMap key, value:\", k, v)\n\t}\n\n\t// test maps with struct keys\n\tstructMap := map[namedFloat]int{\n\t\tnamedFloat{\"tau\", 6.28}: 5,\n\t}\n\tprintln(`structMap[{\"tau\", 6.28}]:`, structMap[namedFloat{\"tau\", 6.28}])\n\tprintln(`structMap[{\"Tau\", 6.28}]:`, structMap[namedFloat{\"Tau\", 6.28}])\n\tprintln(`structMap[{\"tau\", 3.14}]:`, structMap[namedFloat{\"tau\", 3.14}])\n\tdelete(structMap, namedFloat{\"tau\", 6.28})\n\tprintln(`structMap[{\"tau\", 6.28}]:`, structMap[namedFloat{\"tau\", 6.28}])\n\n\t// test preallocated map\n\tsquares := make(map[int]int, 200)\n\ttestBigMap(squares, 100)\n\tprintln(\"tested preallocated map\")\n\n\t// test growing maps\n\tsquares = make(map[int]int, 0)\n\ttestBigMap(squares, 10)\n\tsquares = make(map[int]int, 20)\n\ttestBigMap(squares, 40)\n\tprintln(\"tested growing of a map\")\n\n\tfloatcmplx()\n\n\tmapgrow()\n\n\tinterfacerehash()\n}\n\nfunc floatcmplx() {\n\n\tvar zero float64\n\tvar negz float64 = -zero\n\n\t// test that zero and negative zero hash to the same thing\n\tm := make(map[float64]int)\n\tm[zero]++\n\tm[negz]++\n\tprintln(m[negz])\n\n\tcmap := make(map[complex128]int)\n\n\tvar c complex128\n\tc = complex(zero, zero)\n\tcmap[c]++\n\n\tc = complex(negz, negz)\n\tcmap[c]++\n\n\tc = complex(0, 0)\n\tprintln(cmap[c])\n\n\tc = complex(1, negz)\n\tcmap[c]++\n\n\tc = complex(1, zero)\n\tcmap[c]++\n\n\tprintln(cmap[c])\n\n\tc = complex(negz, 2)\n\tcmap[c]++\n\n\tc = complex(zero, 2)\n\tcmap[c]++\n\n\tprintln(cmap[c])\n}\n\nfunc readMap(m map[string]int, key string) {\n\tprintln(\"map length:\", len(m))\n\tprintln(\"map read:\", key, \"=\", m[key])\n\tkeys := make([]string, 0, len(m))\n\tfor k := range m {\n\t\tkeys = append(keys, k)\n\t}\n\tsort.Strings(keys)\n\tfor _, k := range keys {\n\t\tv := m[k]\n\t\tprintln(\" \", k, \"=\", v)\n\t}\n}\n\nfunc lookup(m map[string]int, key string) {\n\tvalue, ok := m[key]\n\tprintln(\"lookup with comma-ok:\", key, value, ok)\n}\n\nfunc testBigMap(squares map[int]int, n int) {\n\tfor i := 0; i < n; i++ {\n\t\tif len(squares) != i {\n\t\t\tprintln(\"unexpected length:\", len(squares), \"at i =\", i)\n\t\t}\n\t\tsquares[i] = i * i\n\t\tfor j := 0; j <= i; j++ {\n\t\t\tif v, ok := squares[j]; !ok || v != j*j {\n\t\t\t\tif !ok {\n\t\t\t\t\tprintln(\"key not found in squares map:\", j)\n\t\t\t\t} else {\n\t\t\t\t\tprintln(\"unexpected value read back from squares map:\", j, v)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc mapgrow() {\n\tm := make(map[int]int)\n\n\tvar Delete = 500\n\tif unsafe.Sizeof(uintptr(0)) < 4 {\n\t\t// Reduce the number of iterations on low-memory devices like AVR.\n\t\tDelete = 20\n\t}\n\tvar N = Delete * 2\n\n\tfor i := 0; i < Delete; i++ {\n\t\tm[i] = i\n\t}\n\n\tvar deleted bool\n\tfor k, v := range m {\n\t\tif k == 0 {\n\t\t\t// grow map\n\t\t\tfor i := Delete; i < N; i++ {\n\t\t\t\tm[i] = i\n\t\t\t}\n\n\t\t\t// delete some elements\n\t\t\tfor i := 0; i < Delete; i++ {\n\t\t\t\tdelete(m, i)\n\t\t\t}\n\t\t\tdeleted = true\n\t\t\tcontinue\n\t\t}\n\n\t\t// make sure we never see a deleted element later in our iteration\n\t\tif deleted && v < Delete {\n\t\t\tprintln(\"saw deleted element\", v)\n\t\t}\n\t}\n\n\tif len(m) != N-Delete {\n\t\tprintln(\"bad length post grow/delete\", len(m))\n\t}\n\n\tseen := make([]bool, Delete)\n\n\tvar mcount int\n\tfor k, v := range m {\n\t\tif k != v {\n\t\t\tprintln(\"element mismatch\", k, v)\n\t\t}\n\t\tif k < Delete {\n\t\t\tprintln(\"saw deleted element post-grow\", k)\n\t\t}\n\t\tseen[v-Delete] = true\n\t\tmcount++\n\t}\n\n\tfor _, v := range seen {\n\t\tif !v {\n\t\t\tprintln(\"missing key\", v)\n\t\t}\n\t}\n\n\tif mcount != N-Delete {\n\t\tprintln(\"bad number of elements post-grow:\", mcount)\n\t}\n\tprintln(\"done\")\n}\n\ntype Counter interface {\n\tcount() int\n}\n\ntype counter struct {\n\ti int\n}\n\nfunc (c *counter) count() int {\n\treturn c.i\n}\n\nfunc interfacerehash() {\n\tm := make(map[Counter]int)\n\n\tfor i := 0; i < 20; i++ {\n\t\tc := &counter{i}\n\t\tm[c] = i\n\t}\n\n\tvar failures int\n\tfor k, v := range m {\n\t\tif got := m[k]; got != v {\n\t\t\tprintln(\"lookup failure got\", got, \"want\", v)\n\t\t\tfailures++\n\t\t}\n\t}\n\tif failures == 0 {\n\t\tprintln(\"no interface lookup failures\")\n\t}\n}\n"
  },
  {
    "path": "testdata/map.txt",
    "content": "map length: 2\nmap read: answer = 42\n  answer = 42\n  foo = 3\nmap length: 1\nmap read: data = 3\n  data = 3\nmap length: 12\nmap read: three = 3\n  eight = 8\n  eleven = 11\n  five = 5\n  four = 4\n  nine = 9\n  one = 1\n  seven = 7\n  six = 6\n  ten = 10\n  three = 3\n  twelve = 12\n  two = 2\nmap length: 12\nmap read: ten = 10\n  eight = 8\n  eleven = 11\n  five = 5\n  four = 4\n  nine = 9\n  one = 1\n  seven = 7\n  six = 6\n  ten = 10\n  three = 3\n  twelve = 12\n  two = 2\nmap length: 11\nmap read: seven = 7\n  eight = 8\n  eleven = 11\n  five = 5\n  four = 4\n  nine = 9\n  one = 1\n  seven = 7\n  ten = 10\n  three = 3\n  twelve = 12\n  two = 2\nlookup with comma-ok: eight 8 true\nlookup with comma-ok: nokey 0 false\nfalse true 2\ntrue false 0\nnilmap: 0\n4\n42\nnilbinmap: 0\n4321\n5555\nitfMap[3]: 0\nitfMap[3.14]: 3\nitfMap[8]: 8\nitfMap[uint8(8)]: 80\nitfMap[\"eight\"]: 800\nitfMap[[2]int{5, 2}]: 52\nitfMap[true]: 1\nitfMap[8]: 0\nitfMap: found key \"eight\": 800\nfloatMap[42]: 84\nfloatMap[43]: 0\nfloatMap[42]: 0\nfloatMap key, value: +3.140000e+000 6\nstructMap[{\"tau\", 6.28}]: 5\nstructMap[{\"Tau\", 6.28}]: 0\nstructMap[{\"tau\", 3.14}]: 0\nstructMap[{\"tau\", 6.28}]: 0\ntested preallocated map\ntested growing of a map\n2\n2\n2\n2\ndone\nno interface lookup failures\n"
  },
  {
    "path": "testdata/math.go",
    "content": "package main\n\nimport \"math\"\n\nfunc main() {\n\tfor _, n := range []float64{0.3, 1.5, 2.6, -1.1, -3.1, -3.8} {\n\t\tprintln(\"n:\", n)\n\t\tprintln(\"  asin:     \", math.Asin(n))\n\t\tprintln(\"  asinh:    \", math.Asinh(n))\n\t\tprintln(\"  acos:     \", math.Acos(n))\n\t\tprintln(\"  acosh:    \", math.Acosh(n))\n\t\tprintln(\"  atan:     \", math.Atan(n))\n\t\tprintln(\"  atanh:    \", math.Atanh(n))\n\t\tprintln(\"  atan2:    \", math.Atan2(n, 0.2))\n\t\tprintln(\"  cbrt:     \", math.Cbrt(n))\n\t\tprintln(\"  ceil:     \", math.Ceil(n))\n\t\tprintln(\"  cos:      \", math.Cos(n))\n\t\tprintln(\"  cosh:     \", math.Cosh(n))\n\t\tprintln(\"  erf:      \", math.Erf(n))\n\t\tprintln(\"  erfc:     \", math.Erfc(n))\n\t\tprintln(\"  exp:      \", math.Exp(n))\n\t\tprintln(\"  expm1:    \", math.Expm1(n))\n\t\tprintln(\"  exp2:     \", math.Exp2(n))\n\t\tprintln(\"  floor:    \", math.Floor(n))\n\t\tf, e := math.Frexp(n)\n\t\tprintln(\"  frexp:    \", f, e)\n\t\tprintln(\"  hypot:    \", math.Hypot(n, n*2))\n\t\tprintln(\"  ldexp:    \", math.Ldexp(n, 2))\n\t\tprintln(\"  log:      \", math.Log(n))\n\t\tprintln(\"  log1p:    \", math.Log1p(n))\n\t\tprintln(\"  log10:    \", math.Log10(n))\n\t\tprintln(\"  log2:     \", math.Log2(n))\n\t\tprintln(\"  max:      \", math.Max(n, n+1))\n\t\tprintln(\"  min:      \", math.Min(n, n+1))\n\t\tprintln(\"  mod:      \", math.Mod(n, n+1))\n\t\ti, f := math.Modf(n)\n\t\tprintln(\"  modf:     \", i, f)\n\t\tprintln(\"  pow:      \", math.Pow(n, n))\n\t\tprintln(\"  remainder:\", math.Remainder(n, n+0.2))\n\t\tprintln(\"  sin:      \", math.Sin(n))\n\t\tprintln(\"  sinh:     \", math.Sinh(n))\n\t\tprintln(\"  sqrt:     \", float32(math.Sqrt(float64(n))))\n\t\tprintln(\"  tan:      \", math.Tan(n))\n\t\tprintln(\"  tanh:     \", math.Tanh(n))\n\t\tprintln(\"  trunc:    \", math.Trunc(n))\n\t}\n}\n"
  },
  {
    "path": "testdata/math.txt",
    "content": "n: +3.000000e-001\n  asin:      +3.046927e-001\n  asinh:     +2.956730e-001\n  acos:      +1.266104e+000\n  acosh:     NaN\n  atan:      +2.914568e-001\n  atanh:     +3.095196e-001\n  atan2:     +9.827937e-001\n  cbrt:      +6.694330e-001\n  ceil:      +1.000000e+000\n  cos:       +9.553365e-001\n  cosh:      +1.045339e+000\n  erf:       +3.286268e-001\n  erfc:      +6.713732e-001\n  exp:       +1.349859e+000\n  expm1:     +3.498588e-001\n  exp2:      +1.231144e+000\n  floor:     +0.000000e+000\n  frexp:     +6.000000e-001 -1\n  hypot:     +6.708204e-001\n  ldexp:     +1.200000e+000\n  log:       -1.203973e+000\n  log1p:     +2.623643e-001\n  log10:     -5.228787e-001\n  log2:      -1.736966e+000\n  max:       +1.300000e+000\n  min:       +3.000000e-001\n  mod:       +3.000000e-001\n  modf:      +0.000000e+000 +3.000000e-001\n  pow:       +6.968453e-001\n  remainder: -2.000000e-001\n  sin:       +2.955202e-001\n  sinh:      +3.045203e-001\n  sqrt:      +5.477226e-001\n  tan:       +3.093362e-001\n  tanh:      +2.913126e-001\n  trunc:     +0.000000e+000\nn: +1.500000e+000\n  asin:      NaN\n  asinh:     +1.194763e+000\n  acos:      NaN\n  acosh:     +9.624237e-001\n  atan:      +9.827937e-001\n  atanh:     NaN\n  atan2:     +1.438245e+000\n  cbrt:      +1.144714e+000\n  ceil:      +2.000000e+000\n  cos:       +7.073720e-002\n  cosh:      +2.352410e+000\n  erf:       +9.661051e-001\n  erfc:      +3.389485e-002\n  exp:       +4.481689e+000\n  expm1:     +3.481689e+000\n  exp2:      +2.828427e+000\n  floor:     +1.000000e+000\n  frexp:     +7.500000e-001 1\n  hypot:     +3.354102e+000\n  ldexp:     +6.000000e+000\n  log:       +4.054651e-001\n  log1p:     +9.162907e-001\n  log10:     +1.760913e-001\n  log2:      +5.849625e-001\n  max:       +2.500000e+000\n  min:       +1.500000e+000\n  mod:       +1.500000e+000\n  modf:      +1.000000e+000 +5.000000e-001\n  pow:       +1.837117e+000\n  remainder: -2.000000e-001\n  sin:       +9.974950e-001\n  sinh:      +2.129279e+000\n  sqrt:      +1.224745e+000\n  tan:       +1.410142e+001\n  tanh:      +9.051483e-001\n  trunc:     +1.000000e+000\nn: +2.600000e+000\n  asin:      NaN\n  asinh:     +1.683743e+000\n  acos:      NaN\n  acosh:     +1.609438e+000\n  atan:      +1.203622e+000\n  atanh:     NaN\n  atan2:     +1.494024e+000\n  cbrt:      +1.375069e+000\n  ceil:      +3.000000e+000\n  cos:       -8.568888e-001\n  cosh:      +6.769006e+000\n  erf:       +9.997640e-001\n  erfc:      +2.360344e-004\n  exp:       +1.346374e+001\n  expm1:     +1.246374e+001\n  exp2:      +6.062866e+000\n  floor:     +2.000000e+000\n  frexp:     +6.500000e-001 2\n  hypot:     +5.813777e+000\n  ldexp:     +1.040000e+001\n  log:       +9.555114e-001\n  log1p:     +1.280934e+000\n  log10:     +4.149733e-001\n  log2:      +1.378512e+000\n  max:       +3.600000e+000\n  min:       +2.600000e+000\n  mod:       +2.600000e+000\n  modf:      +2.000000e+000 +6.000000e-001\n  pow:       +1.199308e+001\n  remainder: -2.000000e-001\n  sin:       +5.155014e-001\n  sinh:      +6.694732e+000\n  sqrt:      +1.612452e+000\n  tan:       -6.015966e-001\n  tanh:      +9.890274e-001\n  trunc:     +2.000000e+000\nn: -1.100000e+000\n  asin:      NaN\n  asinh:     -9.503469e-001\n  acos:      NaN\n  acosh:     NaN\n  atan:      -8.329813e-001\n  atanh:     NaN\n  atan2:     -1.390943e+000\n  cbrt:      -1.032280e+000\n  ceil:      -1.000000e+000\n  cos:       +4.535961e-001\n  cosh:      +1.668519e+000\n  erf:       -8.802051e-001\n  erfc:      +1.880205e+000\n  exp:       +3.328711e-001\n  expm1:     -6.671289e-001\n  exp2:      +4.665165e-001\n  floor:     -2.000000e+000\n  frexp:     -5.500000e-001 1\n  hypot:     +2.459675e+000\n  ldexp:     -4.400000e+000\n  log:       NaN\n  log1p:     NaN\n  log10:     NaN\n  log2:      NaN\n  max:       -1.000000e-001\n  min:       -1.100000e+000\n  mod:       -1.000000e-001\n  modf:      -1.000000e+000 -1.000000e-001\n  pow:       NaN\n  remainder: -2.000000e-001\n  sin:       -8.912074e-001\n  sinh:      -1.335647e+000\n  sqrt:      NaN\n  tan:       -1.964760e+000\n  tanh:      -8.004990e-001\n  trunc:     -1.000000e+000\nn: -3.100000e+000\n  asin:      NaN\n  asinh:     -1.849604e+000\n  acos:      NaN\n  acosh:     NaN\n  atan:      -1.258754e+000\n  atanh:     NaN\n  atan2:     -1.506369e+000\n  cbrt:      -1.458100e+000\n  ceil:      -3.000000e+000\n  cos:       -9.991352e-001\n  cosh:      +1.112150e+001\n  erf:       -9.999884e-001\n  erfc:      +1.999988e+000\n  exp:       +4.504920e-002\n  expm1:     -9.549508e-001\n  exp2:      +1.166291e-001\n  floor:     -4.000000e+000\n  frexp:     -7.750000e-001 2\n  hypot:     +6.931811e+000\n  ldexp:     -1.240000e+001\n  log:       NaN\n  log1p:     NaN\n  log10:     NaN\n  log2:      NaN\n  max:       -2.100000e+000\n  min:       -3.100000e+000\n  mod:       -1.000000e+000\n  modf:      -3.000000e+000 -1.000000e-001\n  pow:       NaN\n  remainder: -2.000000e-001\n  sin:       -4.158066e-002\n  sinh:      -1.107645e+001\n  sqrt:      NaN\n  tan:       +4.161665e-002\n  tanh:      -9.959494e-001\n  trunc:     -3.000000e+000\nn: -3.800000e+000\n  asin:      NaN\n  asinh:     -2.045028e+000\n  acos:      NaN\n  acosh:     NaN\n  atan:      -1.313473e+000\n  atanh:     NaN\n  atan2:     -1.518213e+000\n  cbrt:      -1.560491e+000\n  ceil:      -3.000000e+000\n  cos:       -7.909677e-001\n  cosh:      +2.236178e+001\n  erf:       -9.999999e-001\n  erfc:      +2.000000e+000\n  exp:       +2.237077e-002\n  expm1:     -9.776292e-001\n  exp2:      +7.179365e-002\n  floor:     -4.000000e+000\n  frexp:     -9.500000e-001 2\n  hypot:     +8.497058e+000\n  ldexp:     -1.520000e+001\n  log:       NaN\n  log1p:     NaN\n  log10:     NaN\n  log2:      NaN\n  max:       -2.800000e+000\n  min:       -3.800000e+000\n  mod:       -1.000000e+000\n  modf:      -3.000000e+000 -8.000000e-001\n  pow:       NaN\n  remainder: -2.000000e-001\n  sin:       +6.118579e-001\n  sinh:      -2.233941e+001\n  sqrt:      NaN\n  tan:       -7.735561e-001\n  tanh:      -9.989996e-001\n  trunc:     -3.000000e+000\n"
  },
  {
    "path": "testdata/oldgo/go.mod",
    "content": "module github.com/tinygo-org/tinygo/testdata/oldgo\n\n// Go version doesn't matter much, as long as it's old.\n\ngo 1.15\n"
  },
  {
    "path": "testdata/oldgo/main.go",
    "content": "package main\n\n// This package verifies that the Go language version is correctly picked up\n// from the go.mod file.\n\nfunc main() {\n\ttestLoopVar()\n}\n\nfunc testLoopVar() {\n\tvar f func() int\n\tfor i := 0; i < 1; i++ {\n\t\tif i == 0 {\n\t\t\tf = func() int { return i }\n\t\t}\n\t}\n\t// Variable n is 1 in Go 1.21, or 0 in Go 1.22.\n\tn := f()\n\tif n == 0 {\n\t\tprintln(\"loops behave like Go 1.22\")\n\t} else if n == 1 {\n\t\tprintln(\"loops behave like Go 1.21\")\n\t} else {\n\t\tprintln(\"unknown loop behavior\")\n\t}\n}\n"
  },
  {
    "path": "testdata/oldgo/out.txt",
    "content": "loops behave like Go 1.21\n"
  },
  {
    "path": "testdata/print.go",
    "content": "package main\n\nfunc main() {\n\t// test basic printing\n\tprintln(\"hello world!\")\n\tprintln(42)\n\tprintln(100000000)\n\n\t// check that this one doesn't print an extra space between args\n\tprint(\"a\", \"b\", \"c\")\n\tprintln()\n\t// ..but this one does\n\tprintln(\"a\", \"b\", \"c\")\n\n\t// print integers\n\tprintln(uint8(123))\n\tprintln(int8(123))\n\tprintln(int8(-123))\n\tprintln(uint16(12345))\n\tprintln(int16(12345))\n\tprintln(int16(-12345))\n\tprintln(uint32(12345678))\n\tprintln(int32(12345678))\n\tprintln(int32(-12345678))\n\tprintln(uint64(123456789012))\n\tprintln(int64(123456789012))\n\tprintln(int64(-123456789012))\n\n\t// print float64\n\tprintln(3.14)\n\n\t// print float32\n\tprintln(float32(3.14))\n\n\t// print complex128\n\tprintln(5 + 1.2345i)\n\n\t// print interface\n\tprintln(interface{}(nil))\n\tprintln(interface{}(true))\n\tprintln(interface{}(\"foobar\"))\n\tprintln(interface{}(int64(-3)))\n\tprintln(interface{}(uint64(3)))\n\tprintln(interface{}(int(-3)))\n\tprintln(interface{}(uint(3)))\n\n\t// print map\n\tprintln(map[string]int{\"three\": 3, \"five\": 5})\n\n\t// TODO: print pointer\n\n\t// print bool\n\tprintln(true, false)\n\n\t// print slice\n\tprintln([]byte(nil))\n\tprintln([]int(nil))\n}\n"
  },
  {
    "path": "testdata/print.txt",
    "content": "hello world!\n42\n100000000\nabc\na b c\n123\n123\n-123\n12345\n12345\n-12345\n12345678\n12345678\n-12345678\n123456789012\n123456789012\n-123456789012\n+3.140000e+000\n+3.140000e+000\n(+5.000000e+000+1.234500e+000i)\n(0:nil)\ntrue\nfoobar\n-3\n3\n-3\n3\nmap[2]\ntrue false\n[0/0]nil\n[0/0]nil\n"
  },
  {
    "path": "testdata/rand.go",
    "content": "package main\n\nimport \"crypto/rand\"\n\n// TODO: make this a test in the crypto/rand package.\n\nfunc main() {\n\tbuf := make([]byte, 500)\n\tn, err := rand.Read(buf)\n\tif n != len(buf) || err != nil {\n\t\tprintln(\"could not read random numbers:\", err)\n\t}\n\n\t// Very simple test that random numbers are at least somewhat random.\n\tsum := 0\n\tfor _, b := range buf {\n\t\tsum += int(b)\n\t}\n\tif sum < 95*len(buf) || sum > 159*len(buf) {\n\t\tprintln(\"random numbers don't seem that random, the average byte is\", sum/len(buf))\n\t} else {\n\t\tprintln(\"random number check was successful\")\n\t}\n}\n"
  },
  {
    "path": "testdata/rand.txt",
    "content": "random number check was successful\n"
  },
  {
    "path": "testdata/recover.go",
    "content": "package main\n\nimport (\n\t\"runtime\"\n\t\"sync\"\n)\n\nvar wg sync.WaitGroup\n\nfunc main() {\n\tprintln(\"# simple recover\")\n\trecoverSimple()\n\n\tprintln(\"\\n# recover with result\")\n\tresult := recoverWithResult()\n\tprintln(\"result:\", result)\n\n\tprintln(\"\\n# nested defer frame\")\n\tnestedDefer()\n\n\tprintln(\"\\n# nested panic: panic inside recover\")\n\tnestedPanic()\n\n\tprintln(\"\\n# panic inside defer\")\n\tpanicInsideDefer()\n\n\tprintln(\"\\n# panic replace\")\n\tpanicReplace()\n\n\tprintln(\"\\n# defer panic\")\n\tdeferPanic()\n\n\tprintln(\"\\n# runtime.Goexit\")\n\truntimeGoexit()\n}\n\nfunc recoverSimple() {\n\tdefer func() {\n\t\tprintln(\"recovering...\")\n\t\tprintitf(\"recovered:\", recover())\n\t}()\n\tprintln(\"running panic...\")\n\tpanic(\"panic\")\n}\n\nfunc recoverWithResult() (result int) {\n\tdefer func() {\n\t\tprintitf(\"recovered:\", recover())\n\t}()\n\tresult = 3\n\tprintln(\"running panic...\")\n\tpanic(\"panic\")\n}\n\nfunc nestedDefer() {\n\tdefer func() {\n\t\tprintitf(\"recovered:\", recover())\n\t}()\n\n\tfunc() {\n\t\t// The defer here doesn't catch the panic using recover(), so the outer\n\t\t// panic should do that.\n\t\tdefer func() {\n\t\t\tprintln(\"deferred nested function\")\n\t\t}()\n\t\tpanic(\"panic\")\n\t}()\n\tprintln(\"unreachable\")\n}\n\nfunc nestedPanic() {\n\tdefer func() {\n\t\tprintitf(\"recovered 1:\", recover())\n\n\t\tdefer func() {\n\t\t\tprintitf(\"recovered 2:\", recover())\n\t\t}()\n\n\t\tpanic(\"foo\")\n\t}()\n\tpanic(\"panic\")\n}\n\nfunc panicInsideDefer() {\n\tdefer func() {\n\t\tprintitf(\"recovered:\", recover())\n\t}()\n\tdefer func() {\n\t\tpanic(\"panic\")\n\t}()\n}\n\nfunc panicReplace() {\n\tdefer func() {\n\t\tprintitf(\"recovered:\", recover())\n\t}()\n\tdefer func() {\n\t\tprintln(\"panic 2\")\n\t\tpanic(\"panic 2\")\n\t}()\n\tprintln(\"panic 1\")\n\tpanic(\"panic 1\")\n}\n\nfunc deferPanic() {\n\tdefer func() {\n\t\tprintitf(\"recovered from deferred call:\", recover())\n\t}()\n\n\t// This recover should not do anything.\n\tdefer recover()\n\n\tdefer panic(\"deferred panic\")\n\tprintln(\"defer panic\")\n}\n\nfunc runtimeGoexit() {\n\twg.Add(1)\n\tgo func() {\n\t\tdefer func() {\n\t\t\tprintln(\"Goexit deferred function, recover is nil:\", recover() == nil)\n\t\t\twg.Done()\n\t\t}()\n\n\t\truntime.Goexit()\n\t}()\n\twg.Wait()\n}\n\nfunc printitf(msg string, itf interface{}) {\n\tswitch itf := itf.(type) {\n\tcase string:\n\t\tprintln(msg, itf)\n\tdefault:\n\t\tprintln(msg, itf)\n\t}\n}\n"
  },
  {
    "path": "testdata/recover.txt",
    "content": "# simple recover\nrunning panic...\nrecovering...\nrecovered: panic\n\n# recover with result\nrunning panic...\nrecovered: panic\nresult: 3\n\n# nested defer frame\ndeferred nested function\nrecovered: panic\n\n# nested panic: panic inside recover\nrecovered 1: panic\nrecovered 2: foo\n\n# panic inside defer\nrecovered: panic\n\n# panic replace\npanic 1\npanic 2\nrecovered: panic 2\n\n# defer panic\ndefer panic\nrecovered from deferred call: deferred panic\n\n# runtime.Goexit\nGoexit deferred function, recover is nil: true\n"
  },
  {
    "path": "testdata/reflect.go",
    "content": "package main\n\nimport (\n\t\"errors\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"unsafe\"\n)\n\ntype (\n\tmyint    int\n\tmyslice  []byte\n\tmyslice2 []myint\n\tmychan   chan int\n\tmyptr    *int\n\tpoint    struct {\n\t\tX int16\n\t\tY int16\n\t}\n\tmystruct struct {\n\t\tn    int   `foo:\"bar\"`\n\t\tsome point \"some\\x00tag\"\n\t\tzero struct{}\n\t\tbuf  []byte\n\t\tBuf  []byte\n\t}\n\tlinkedList struct {\n\t\tnext *linkedList `description:\"chain\"`\n\t\tfoo  int\n\t}\n\tselfref struct {\n\t\tx *selfref\n\t}\n)\n\nvar (\n\terrorValue   = errors.New(\"test error\")\n\terrorType    = reflect.TypeOf((*error)(nil)).Elem()\n\tstringerType = reflect.TypeOf((*interface {\n\t\tString() string\n\t})(nil)).Elem()\n)\n\nfunc main() {\n\tprintln(\"matching types\")\n\tprintln(reflect.TypeOf(int(3)) == reflect.TypeOf(int(5)))\n\tprintln(reflect.TypeOf(int(3)) == reflect.TypeOf(uint(5)))\n\tprintln(reflect.TypeOf(myint(3)) == reflect.TypeOf(int(5)))\n\tprintln(reflect.TypeOf(myslice{}) == reflect.TypeOf([]byte{}))\n\tprintln(reflect.TypeOf(myslice2{}) == reflect.TypeOf([]myint{}))\n\tprintln(reflect.TypeOf(myslice2{}) == reflect.TypeOf([]int{}))\n\n\tprintln(\"\\nvalues of interfaces\")\n\tvar zeroSlice []byte\n\tvar zeroFunc func()\n\t// by embedding a 0-array func type in your struct, it is not comparable\n\ttype doNotCompare [0]func()\n\ttype notComparable struct {\n\t\tdoNotCompare\n\t\tdata *int32\n\t}\n\tvar zeroMap map[string]int\n\tvar zeroChan chan int\n\tn := 42\n\tfor _, v := range []interface{}{\n\t\t// basic types\n\t\ttrue,\n\t\tfalse,\n\t\tint(2000),\n\t\tint(-2000),\n\t\tuint(2000),\n\t\tint8(-3),\n\t\tint8(3),\n\t\tuint8(200),\n\t\tint16(-300),\n\t\tint16(300),\n\t\tuint16(50000),\n\t\tint32(7 << 20),\n\t\tint32(-7 << 20),\n\t\tuint32(7 << 20),\n\t\tint64(9 << 40),\n\t\tint64(-9 << 40),\n\t\tuint64(9 << 40),\n\t\tuintptr(12345),\n\t\tfloat32(3.14),\n\t\tfloat64(3.14),\n\t\tcomplex64(1.2 + 0.3i),\n\t\tcomplex128(1.3 + 0.4i),\n\t\tmyint(32),\n\t\t\"foo\",\n\t\tunsafe.Pointer(new(int)),\n\t\t// channels\n\t\tzeroChan,\n\t\tmychan(zeroChan),\n\t\t// pointers\n\t\tnew(int),\n\t\tnew(error),\n\t\t&n,\n\t\tmyptr(new(int)),\n\t\t// slices\n\t\t[]byte{1, 2, 3},\n\t\tmake([]uint8, 2, 5),\n\t\t[]rune{3, 5},\n\t\t[]string{\"xyz\", \"Z\"},\n\t\tzeroSlice,\n\t\t[]byte{},\n\t\t[]float32{1, 1.32},\n\t\t[]float64{1, 1.64},\n\t\t[]complex64{1, 1.64 + 0.3i},\n\t\t[]complex128{1, 1.128 + 0.4i},\n\t\tmyslice{5, 3, 11},\n\t\t// array\n\t\t[3]int64{5, 8, 2},\n\t\t[2]uint8{3, 5},\n\t\t// functions\n\t\tzeroFunc,\n\t\temptyFunc,\n\t\t// maps\n\t\tzeroMap,\n\t\tmap[string]int{},\n\t\t// structs\n\t\tstruct{}{},\n\t\tstruct{ error }{},\n\t\tstruct {\n\t\t\ta uint8\n\t\t\tb int16\n\t\t\tc int8\n\t\t}{42, 321, 123},\n\t\tmystruct{5, point{-5, 3}, struct{}{}, []byte{'G', 'o'}, []byte{'X'}},\n\t\t&linkedList{\n\t\t\tfoo: 42,\n\t\t},\n\t\tstruct{ A, B uintptr }{2, 3},\n\t\t// interfaces\n\t\t[]interface{}{3, \"str\", -4 + 2.5i},\n\t} {\n\t\tshowValue(reflect.ValueOf(v), \"\")\n\t}\n\n\t// Test reflect.New().\n\tnewInt8 := reflect.New(reflect.TypeOf(int8(0)))\n\tnewInt8.Elem().SetInt(5)\n\tnewInt16 := reflect.New(reflect.TypeOf(int16(0)))\n\tnewInt16.Elem().SetInt(-800)\n\tnewInt32 := reflect.New(reflect.TypeOf(int32(0)))\n\tnewInt32.Elem().SetInt(1e8)\n\tnewInt64 := reflect.New(reflect.TypeOf(int64(0)))\n\tnewInt64.Elem().SetInt(-1e12)\n\tnewComplex128 := reflect.New(reflect.TypeOf(0 + 0i))\n\tnewComplex128.Elem().SetComplex(-8 - 20e5i)\n\tfor _, val := range []reflect.Value{newInt8, newInt16, newInt32, newInt64, newComplex128} {\n\t\tshowValue(val, \"\")\n\t}\n\n\t// test sizes\n\tprintln(\"\\nsizes:\")\n\tfor _, tc := range []struct {\n\t\tname string\n\t\trt   reflect.Type\n\t}{\n\t\t{\"int8\", reflect.TypeOf(int8(0))},\n\t\t{\"int16\", reflect.TypeOf(int16(0))},\n\t\t{\"int32\", reflect.TypeOf(int32(0))},\n\t\t{\"int64\", reflect.TypeOf(int64(0))},\n\t\t{\"uint8\", reflect.TypeOf(uint8(0))},\n\t\t{\"uint16\", reflect.TypeOf(uint16(0))},\n\t\t{\"uint32\", reflect.TypeOf(uint32(0))},\n\t\t{\"uint64\", reflect.TypeOf(uint64(0))},\n\t\t{\"float32\", reflect.TypeOf(float32(0))},\n\t\t{\"float64\", reflect.TypeOf(float64(0))},\n\t\t{\"complex64\", reflect.TypeOf(complex64(0))},\n\t\t{\"complex128\", reflect.TypeOf(complex128(0))},\n\t} {\n\t\tprintln(tc.name, int(tc.rt.Size()), tc.rt.Bits())\n\t}\n\tassertSize(reflect.TypeOf(uintptr(0)).Size() == unsafe.Sizeof(uintptr(0)), \"uintptr\")\n\tassertSize(reflect.TypeOf(\"\").Size() == unsafe.Sizeof(\"\"), \"string\")\n\tassertSize(reflect.TypeOf(new(int)).Size() == unsafe.Sizeof(new(int)), \"*int\")\n\tassertSize(reflect.TypeOf(zeroFunc).Size() == unsafe.Sizeof(zeroFunc), \"func()\")\n\tassertSize(reflect.TypeOf(zeroChan).Size() == unsafe.Sizeof(zeroChan), \"chan int\")\n\tassertSize(reflect.TypeOf(zeroMap).Size() == unsafe.Sizeof(zeroMap), \"map[string]int\")\n\n\t// make sure embedding a zero-sized \"not comparable\" struct does not add size to a struct\n\tassertSize(reflect.TypeOf(doNotCompare{}).Size() == unsafe.Sizeof(doNotCompare{}), \"[0]func()\")\n\tassertSize(unsafe.Sizeof(notComparable{}) == unsafe.Sizeof((*int32)(nil)), \"struct{[0]func(); *int32}\")\n\n\t// Test that offset is correctly calculated.\n\t// This doesn't just test reflect but also (indirectly) that unsafe.Alignof\n\t// works correctly.\n\ts := struct {\n\t\tsmall1 byte\n\t\tbig1   int64\n\t\tsmall2 byte\n\t\tbig2   int64\n\t}{}\n\tst := reflect.TypeOf(s)\n\tprintln(\"offset for int64 matches:\", st.Field(1).Offset-st.Field(0).Offset == uintptr(unsafe.Pointer(&s.big1))-uintptr(unsafe.Pointer(&s.small1)))\n\tprintln(\"offset for complex128 matches:\", st.Field(3).Offset-st.Field(2).Offset == uintptr(unsafe.Pointer(&s.big2))-uintptr(unsafe.Pointer(&s.small2)))\n\n\t// SetBool\n\trv := reflect.ValueOf(new(bool)).Elem()\n\trv.SetBool(true)\n\tif rv.Bool() != true {\n\t\tpanic(\"could not set bool with SetBool()\")\n\t}\n\n\t// SetInt\n\tfor _, v := range []interface{}{\n\t\tnew(int),\n\t\tnew(int8),\n\t\tnew(int16),\n\t\tnew(int32),\n\t\tnew(int64),\n\t} {\n\t\trv := reflect.ValueOf(v).Elem()\n\t\trv.SetInt(99)\n\t\tif rv.Int() != 99 {\n\t\t\tpanic(\"could not set integer with SetInt()\")\n\t\t}\n\t}\n\n\t// SetUint\n\tfor _, v := range []interface{}{\n\t\tnew(uint),\n\t\tnew(uint8),\n\t\tnew(uint16),\n\t\tnew(uint32),\n\t\tnew(uint64),\n\t\tnew(uintptr),\n\t} {\n\t\trv := reflect.ValueOf(v).Elem()\n\t\trv.SetUint(99)\n\t\tif rv.Uint() != 99 {\n\t\t\tpanic(\"could not set integer with SetUint()\")\n\t\t}\n\t}\n\n\t// SetFloat\n\tfor _, v := range []interface{}{\n\t\tnew(float32),\n\t\tnew(float64),\n\t} {\n\t\trv := reflect.ValueOf(v).Elem()\n\t\trv.SetFloat(2.25)\n\t\tif rv.Float() != 2.25 {\n\t\t\tpanic(\"could not set float with SetFloat()\")\n\t\t}\n\t}\n\n\t// SetComplex\n\tfor _, v := range []interface{}{\n\t\tnew(complex64),\n\t\tnew(complex128),\n\t} {\n\t\trv := reflect.ValueOf(v).Elem()\n\t\trv.SetComplex(3 + 2i)\n\t\tif rv.Complex() != 3+2i {\n\t\t\tpanic(\"could not set complex with SetComplex()\")\n\t\t}\n\t}\n\n\t// SetString\n\trv = reflect.ValueOf(new(string)).Elem()\n\trv.SetString(\"foo\")\n\tif rv.String() != \"foo\" {\n\t\tpanic(\"could not set string with SetString()\")\n\t}\n\n\t// Set int\n\trv = reflect.ValueOf(new(int)).Elem()\n\trv.SetInt(33)\n\trv.Set(reflect.ValueOf(22))\n\tif rv.Int() != 22 {\n\t\tpanic(\"could not set int with Set()\")\n\t}\n\n\t// Set uint8\n\trv = reflect.ValueOf(new(uint8)).Elem()\n\trv.SetUint(33)\n\trv.Set(reflect.ValueOf(uint8(22)))\n\tif rv.Uint() != 22 {\n\t\tpanic(\"could not set uint8 with Set()\")\n\t}\n\n\t// Set string\n\trv = reflect.ValueOf(new(string)).Elem()\n\trv.SetString(\"foo\")\n\trv.Set(reflect.ValueOf(\"bar\"))\n\tif rv.String() != \"bar\" {\n\t\tpanic(\"could not set string with Set()\")\n\t}\n\n\t// Set complex128\n\trv = reflect.ValueOf(new(complex128)).Elem()\n\trv.SetComplex(3 + 2i)\n\trv.Set(reflect.ValueOf(4 + 8i))\n\tif rv.Complex() != 4+8i {\n\t\tpanic(\"could not set complex128 with Set()\")\n\t}\n\n\t// Set to slice\n\trv = reflect.ValueOf([]int{3, 5})\n\trv.Index(1).SetInt(7)\n\tif rv.Index(1).Int() != 7 {\n\t\tpanic(\"could not set int in slice\")\n\t}\n\trv.Index(1).Set(reflect.ValueOf(8))\n\tif rv.Index(1).Int() != 8 {\n\t\tpanic(\"could not set int in slice\")\n\t}\n\tif rv.Len() != 2 || rv.Index(0).Int() != 3 {\n\t\tpanic(\"slice was changed while setting part of it\")\n\t}\n\n\ttestAppendSlice()\n\n\t// Test types that are created in reflect and never created elsewhere in a\n\t// value-to-interface conversion.\n\tv := reflect.ValueOf(new(unreferencedType))\n\tswitch v.Elem().Interface().(type) {\n\tcase unreferencedType:\n\t\tprintln(\"type assertion succeeded for unreferenced type\")\n\tdefault:\n\t\tprintln(\"type assertion failed (but should succeed)\")\n\t}\n\n\t// Test type that is not referenced at all: not when creating the\n\t// reflect.Value (except through the field) and not with a type assert.\n\t// Previously this would result in a type assert failure because the Int()\n\t// method wasn't picked up.\n\tv = reflect.ValueOf(struct {\n\t\tX totallyUnreferencedType\n\t}{})\n\tif v.Field(0).Interface().(interface {\n\t\tInt() int\n\t}).Int() != 42 {\n\t\tprintln(\"could not call method on totally unreferenced type\")\n\t}\n\n\tif reflect.TypeOf(new(myint)) != reflect.PtrTo(reflect.TypeOf(myint(0))) {\n\t\tprintln(\"PtrTo failed for type myint\")\n\t}\n\tif reflect.TypeOf(new(myslice)) != reflect.PtrTo(reflect.TypeOf(make(myslice, 0))) {\n\t\tprintln(\"PtrTo failed for type myslice\")\n\t}\n\n\tif reflect.TypeOf(errorValue).Implements(errorType) != true {\n\t\tprintln(\"errorValue.Implements(errorType) was false, expected true\")\n\t}\n\tif reflect.TypeOf(errorValue).Implements(stringerType) != false {\n\t\tprintln(\"errorValue.Implements(errorType) was true, expected false\")\n\t}\n\n\tprintln(\"\\nalignment / offset:\")\n\tv2 := struct {\n\t\tnoCompare [0]func()\n\t\tdata      byte\n\t}{}\n\tprintln(\"struct{[0]func(); byte}:\", unsafe.Offsetof(v2.data) == uintptr(unsafe.Pointer(&v2.data))-uintptr(unsafe.Pointer(&v2)))\n\n\tprintln(\"\\nstruct tags\")\n\tTestStructTag()\n\n\tprintln(\"\\nv.Interface() method\")\n\ttestInterfaceMethod()\n\n\t// Test reflect.DeepEqual.\n\tvar selfref1, selfref2 selfref\n\tselfref1.x = &selfref1\n\tselfref2.x = &selfref2\n\tfor i, tc := range []struct {\n\t\tv1, v2 interface{}\n\t\tequal  bool\n\t}{\n\t\t{int(5), int(5), true},\n\t\t{int(3), int(5), false},\n\t\t{int(5), uint(5), false},\n\t\t{struct {\n\t\t\ta int\n\t\t\tb string\n\t\t}{3, \"x\"}, struct {\n\t\t\ta int\n\t\t\tb string\n\t\t}{3, \"x\"}, true},\n\t\t{struct {\n\t\t\ta int\n\t\t\tb string\n\t\t}{3, \"x\"}, struct {\n\t\t\ta int\n\t\t\tb string\n\t\t}{3, \"y\"}, false},\n\t\t{selfref1, selfref2, true},\n\t} {\n\t\tresult := reflect.DeepEqual(tc.v1, tc.v2)\n\t\tif result != tc.equal {\n\t\t\tif tc.equal {\n\t\t\t\tprintln(\"reflect.DeepEqual() test\", i, \"not equal while it should be\")\n\t\t\t} else {\n\t\t\t\tprintln(\"reflect.DeepEqual() test\", i, \"equal while it should not be\")\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc emptyFunc() {\n}\n\nfunc showValue(rv reflect.Value, indent string) {\n\trt := rv.Type()\n\tif rt.Kind() != rv.Kind() {\n\t\tpanic(\"type kind is different from value kind\")\n\t}\n\tprint(indent+\"reflect type: \", rt.Kind().String())\n\tif rv.CanSet() {\n\t\tprint(\" settable=true\")\n\t}\n\tif rv.CanAddr() {\n\t\tprint(\" addrable=true\")\n\t}\n\tif !rv.CanInterface() {\n\t\tprint(\" caninterface=false\")\n\t}\n\tif !rt.Comparable() {\n\t\tprint(\" comparable=false\")\n\t}\n\tif name := rt.Name(); name != \"\" {\n\t\tprint(\" name=\", name)\n\t}\n\tprintln()\n\tswitch rt.Kind() {\n\tcase reflect.Bool:\n\t\tprintln(indent+\"  bool:\", rv.Bool())\n\tcase reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:\n\t\tprintln(indent+\"  int:\", rv.Int())\n\tcase reflect.Uint, reflect.Uintptr, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:\n\t\tprintln(indent+\"  uint:\", rv.Uint())\n\tcase reflect.Float32, reflect.Float64:\n\t\tprintln(indent+\"  float:\", rv.Float())\n\tcase reflect.Complex64, reflect.Complex128:\n\t\tprintln(indent+\"  complex:\", rv.Complex())\n\tcase reflect.String:\n\t\tprintln(indent+\"  string:\", rv.String(), rv.Len())\n\t\tfor i := 0; i < rv.Len(); i++ {\n\t\t\tshowValue(rv.Index(i), indent+\"  \")\n\t\t}\n\tcase reflect.UnsafePointer:\n\t\tprintln(indent+\"  pointer:\", rv.Pointer() != 0)\n\tcase reflect.Array:\n\t\tprintln(indent+\"  array:\", rt.Len(), rt.Elem().Kind().String(), int(rt.Size()))\n\t\tfor i := 0; i < rv.Len(); i++ {\n\t\t\tshowValue(rv.Index(i), indent+\"  \")\n\t\t}\n\tcase reflect.Chan:\n\t\tprintln(indent+\"  chan:\", rt.Elem().Kind().String())\n\t\tprintln(indent+\"  nil:\", rv.IsNil())\n\tcase reflect.Func:\n\t\tprintln(indent + \"  func\")\n\t\tprintln(indent+\"  nil:\", rv.IsNil())\n\tcase reflect.Interface:\n\t\tprintln(indent + \"  interface\")\n\t\tprintln(indent+\"  nil:\", rv.IsNil())\n\t\tprintln(indent+\"  NumMethod:\", rv.NumMethod())\n\t\tif !rv.IsNil() {\n\t\t\tshowValue(rv.Elem(), indent+\"  \")\n\t\t}\n\tcase reflect.Map:\n\t\tprintln(indent + \"  map\")\n\t\tprintln(indent+\"  nil:\", rv.IsNil())\n\tcase reflect.Ptr:\n\t\tprintln(indent+\"  pointer:\", rv.Pointer() != 0, rt.Elem().Kind().String())\n\t\tprintln(indent+\"  nil:\", rv.IsNil())\n\t\tif !rv.IsNil() {\n\t\t\tshowValue(rv.Elem(), indent+\"  \")\n\t\t}\n\tcase reflect.Slice:\n\t\tprintln(indent+\"  slice:\", rt.Elem().Kind().String(), rv.Len(), rv.Cap())\n\t\tprintln(indent+\"  pointer:\", rv.Pointer() != 0)\n\t\tprintln(indent+\"  nil:\", rv.IsNil())\n\t\tfor i := 0; i < rv.Len(); i++ {\n\t\t\tprintln(indent+\"  indexing:\", i)\n\t\t\tshowValue(rv.Index(i), indent+\"  \")\n\t\t}\n\tcase reflect.Struct:\n\t\tprintln(indent+\"  struct:\", rt.NumField())\n\t\tfor i := 0; i < rv.NumField(); i++ {\n\t\t\tfield := rt.Field(i)\n\t\t\tprintln(indent+\"  field:\", i, field.Name)\n\t\t\tprintln(indent+\"  pkg:\", field.PkgPath)\n\t\t\tprintln(indent+\"  tag:\", strconv.Quote(string(field.Tag)))\n\t\t\tprintln(indent+\"  embedded:\", field.Anonymous)\n\t\t\tprintln(indent+\"  exported:\", field.IsExported())\n\t\t\tshowValue(rv.Field(i), indent+\"  \")\n\t\t}\n\tdefault:\n\t\tprintln(indent + \"  unknown type kind!\")\n\t}\n}\n\nfunc assertSize(ok bool, typ string) {\n\tif !ok {\n\t\tpanic(\"size mismatch for type \" + typ)\n\t}\n}\n\n// Test whether appending to a slice is equivalent between reflect and native\n// slice append.\nfunc testAppendSlice() {\n\tfor i := 0; i < 100; i++ {\n\t\tdst := makeRandomSlice(i)\n\t\tsrc := makeRandomSlice(i)\n\t\tresult1 := append(dst, src...)\n\t\tresult2 := reflect.AppendSlice(reflect.ValueOf(dst), reflect.ValueOf(src)).Interface().([]uint32)\n\t\tif !sliceEqual(result1, result2) {\n\t\t\tprintln(\"slice: mismatch after runtime.SliceAppend with\", len(dst), cap(dst), len(src), cap(src))\n\t\t}\n\t}\n}\n\nfunc makeRandomSlice(max int) []uint32 {\n\tcap := randuint32() % uint32(max+1)\n\tlen := randuint32() % (cap + 1)\n\ts := make([]uint32, len, cap)\n\tfor i := uint32(0); i < len; i++ {\n\t\ts[i] = randuint32()\n\t}\n\treturn s\n}\n\nfunc sliceEqual(s1, s2 []uint32) bool {\n\tif len(s1) != len(s2) {\n\t\treturn false\n\t}\n\tfor i, val := range s1 {\n\t\tif s2[i] != val {\n\t\t\treturn false\n\t\t}\n\t}\n\t// Note: can't compare cap because the Go implementation has a different\n\t// behavior between the built-in append function and\n\t// reflect.AppendSlice.\n\treturn true\n}\n\ntype unreferencedType int\n\ntype totallyUnreferencedType int\n\nfunc (totallyUnreferencedType) Int() int {\n\treturn 42\n}\n\nfunc TestStructTag() {\n\ttype S struct {\n\t\tF string `species:\"gopher\" color:\"blue\"`\n\t}\n\n\ts := S{}\n\tst := reflect.TypeOf(s)\n\tfield := st.Field(0)\n\tprintln(field.Tag.Get(\"color\"), field.Tag.Get(\"species\"))\n}\n\n// Test Interface() call: it should never return an interface itself.\nfunc testInterfaceMethod() {\n\tv := reflect.ValueOf(struct{ X interface{} }{X: 5})\n\tprintln(\"kind:\", v.Field(0).Kind().String())\n\titf := v.Field(0).Interface()\n\tswitch n := itf.(type) {\n\tcase int:\n\t\tprintln(\"int\", n) // correct\n\tdefault:\n\t\tprintln(\"something else\") // incorrect\n\t}\n}\n\nvar xorshift32State uint32 = 1\n\nfunc xorshift32(x uint32) uint32 {\n\t// Algorithm \"xor\" from p. 4 of Marsaglia, \"Xorshift RNGs\"\n\tx ^= x << 13\n\tx ^= x >> 17\n\tx ^= x << 5\n\treturn x\n}\n\nfunc randuint32() uint32 {\n\txorshift32State = xorshift32(xorshift32State)\n\treturn xorshift32State\n}\n"
  },
  {
    "path": "testdata/reflect.txt",
    "content": "matching types\ntrue\nfalse\nfalse\nfalse\nfalse\nfalse\n\nvalues of interfaces\nreflect type: bool name=bool\n  bool: true\nreflect type: bool name=bool\n  bool: false\nreflect type: int name=int\n  int: 2000\nreflect type: int name=int\n  int: -2000\nreflect type: uint name=uint\n  uint: 2000\nreflect type: int8 name=int8\n  int: -3\nreflect type: int8 name=int8\n  int: 3\nreflect type: uint8 name=uint8\n  uint: 200\nreflect type: int16 name=int16\n  int: -300\nreflect type: int16 name=int16\n  int: 300\nreflect type: uint16 name=uint16\n  uint: 50000\nreflect type: int32 name=int32\n  int: 7340032\nreflect type: int32 name=int32\n  int: -7340032\nreflect type: uint32 name=uint32\n  uint: 7340032\nreflect type: int64 name=int64\n  int: 9895604649984\nreflect type: int64 name=int64\n  int: -9895604649984\nreflect type: uint64 name=uint64\n  uint: 9895604649984\nreflect type: uintptr name=uintptr\n  uint: 12345\nreflect type: float32 name=float32\n  float: +3.140000e+000\nreflect type: float64 name=float64\n  float: +3.140000e+000\nreflect type: complex64 name=complex64\n  complex: (+1.200000e+000+3.000000e-001i)\nreflect type: complex128 name=complex128\n  complex: (+1.300000e+000+4.000000e-001i)\nreflect type: int name=myint\n  int: 32\nreflect type: string name=string\n  string: foo 3\n  reflect type: uint8 name=uint8\n    uint: 102\n  reflect type: uint8 name=uint8\n    uint: 111\n  reflect type: uint8 name=uint8\n    uint: 111\nreflect type: unsafe.Pointer name=Pointer\n  pointer: true\nreflect type: chan\n  chan: int\n  nil: true\nreflect type: chan name=mychan\n  chan: int\n  nil: true\nreflect type: ptr\n  pointer: true int\n  nil: false\n  reflect type: int settable=true addrable=true name=int\n    int: 0\nreflect type: ptr\n  pointer: true interface\n  nil: false\n  reflect type: interface settable=true addrable=true name=error\n    interface\n    nil: true\n    NumMethod: 1\nreflect type: ptr\n  pointer: true int\n  nil: false\n  reflect type: int settable=true addrable=true name=int\n    int: 42\nreflect type: ptr name=myptr\n  pointer: true int\n  nil: false\n  reflect type: int settable=true addrable=true name=int\n    int: 0\nreflect type: slice comparable=false\n  slice: uint8 3 3\n  pointer: true\n  nil: false\n  indexing: 0\n  reflect type: uint8 settable=true addrable=true name=uint8\n    uint: 1\n  indexing: 1\n  reflect type: uint8 settable=true addrable=true name=uint8\n    uint: 2\n  indexing: 2\n  reflect type: uint8 settable=true addrable=true name=uint8\n    uint: 3\nreflect type: slice comparable=false\n  slice: uint8 2 5\n  pointer: true\n  nil: false\n  indexing: 0\n  reflect type: uint8 settable=true addrable=true name=uint8\n    uint: 0\n  indexing: 1\n  reflect type: uint8 settable=true addrable=true name=uint8\n    uint: 0\nreflect type: slice comparable=false\n  slice: int32 2 2\n  pointer: true\n  nil: false\n  indexing: 0\n  reflect type: int32 settable=true addrable=true name=int32\n    int: 3\n  indexing: 1\n  reflect type: int32 settable=true addrable=true name=int32\n    int: 5\nreflect type: slice comparable=false\n  slice: string 2 2\n  pointer: true\n  nil: false\n  indexing: 0\n  reflect type: string settable=true addrable=true name=string\n    string: xyz 3\n    reflect type: uint8 name=uint8\n      uint: 120\n    reflect type: uint8 name=uint8\n      uint: 121\n    reflect type: uint8 name=uint8\n      uint: 122\n  indexing: 1\n  reflect type: string settable=true addrable=true name=string\n    string: Z 1\n    reflect type: uint8 name=uint8\n      uint: 90\nreflect type: slice comparable=false\n  slice: uint8 0 0\n  pointer: false\n  nil: true\nreflect type: slice comparable=false\n  slice: uint8 0 0\n  pointer: true\n  nil: false\nreflect type: slice comparable=false\n  slice: float32 2 2\n  pointer: true\n  nil: false\n  indexing: 0\n  reflect type: float32 settable=true addrable=true name=float32\n    float: +1.000000e+000\n  indexing: 1\n  reflect type: float32 settable=true addrable=true name=float32\n    float: +1.320000e+000\nreflect type: slice comparable=false\n  slice: float64 2 2\n  pointer: true\n  nil: false\n  indexing: 0\n  reflect type: float64 settable=true addrable=true name=float64\n    float: +1.000000e+000\n  indexing: 1\n  reflect type: float64 settable=true addrable=true name=float64\n    float: +1.640000e+000\nreflect type: slice comparable=false\n  slice: complex64 2 2\n  pointer: true\n  nil: false\n  indexing: 0\n  reflect type: complex64 settable=true addrable=true name=complex64\n    complex: (+1.000000e+000+0.000000e+000i)\n  indexing: 1\n  reflect type: complex64 settable=true addrable=true name=complex64\n    complex: (+1.640000e+000+3.000000e-001i)\nreflect type: slice comparable=false\n  slice: complex128 2 2\n  pointer: true\n  nil: false\n  indexing: 0\n  reflect type: complex128 settable=true addrable=true name=complex128\n    complex: (+1.000000e+000+0.000000e+000i)\n  indexing: 1\n  reflect type: complex128 settable=true addrable=true name=complex128\n    complex: (+1.128000e+000+4.000000e-001i)\nreflect type: slice comparable=false name=myslice\n  slice: uint8 3 3\n  pointer: true\n  nil: false\n  indexing: 0\n  reflect type: uint8 settable=true addrable=true name=uint8\n    uint: 5\n  indexing: 1\n  reflect type: uint8 settable=true addrable=true name=uint8\n    uint: 3\n  indexing: 2\n  reflect type: uint8 settable=true addrable=true name=uint8\n    uint: 11\nreflect type: array\n  array: 3 int64 24\n  reflect type: int64 name=int64\n    int: 5\n  reflect type: int64 name=int64\n    int: 8\n  reflect type: int64 name=int64\n    int: 2\nreflect type: array\n  array: 2 uint8 2\n  reflect type: uint8 name=uint8\n    uint: 3\n  reflect type: uint8 name=uint8\n    uint: 5\nreflect type: func comparable=false\n  func\n  nil: true\nreflect type: func comparable=false\n  func\n  nil: false\nreflect type: map comparable=false\n  map\n  nil: true\nreflect type: map comparable=false\n  map\n  nil: false\nreflect type: struct\n  struct: 0\nreflect type: struct\n  struct: 1\n  field: 0 error\n  pkg: main\n  tag: \"\"\n  embedded: true\n  exported: false\n  reflect type: interface caninterface=false name=error\n    interface\n    nil: true\n    NumMethod: 1\nreflect type: struct\n  struct: 3\n  field: 0 a\n  pkg: main\n  tag: \"\"\n  embedded: false\n  exported: false\n  reflect type: uint8 caninterface=false name=uint8\n    uint: 42\n  field: 1 b\n  pkg: main\n  tag: \"\"\n  embedded: false\n  exported: false\n  reflect type: int16 caninterface=false name=int16\n    int: 321\n  field: 2 c\n  pkg: main\n  tag: \"\"\n  embedded: false\n  exported: false\n  reflect type: int8 caninterface=false name=int8\n    int: 123\nreflect type: struct comparable=false name=mystruct\n  struct: 5\n  field: 0 n\n  pkg: main\n  tag: \"foo:\\\"bar\\\"\"\n  embedded: false\n  exported: false\n  reflect type: int caninterface=false name=int\n    int: 5\n  field: 1 some\n  pkg: main\n  tag: \"some\\x00tag\"\n  embedded: false\n  exported: false\n  reflect type: struct caninterface=false name=point\n    struct: 2\n    field: 0 X\n    pkg: \n    tag: \"\"\n    embedded: false\n    exported: true\n    reflect type: int16 caninterface=false name=int16\n      int: -5\n    field: 1 Y\n    pkg: \n    tag: \"\"\n    embedded: false\n    exported: true\n    reflect type: int16 caninterface=false name=int16\n      int: 3\n  field: 2 zero\n  pkg: main\n  tag: \"\"\n  embedded: false\n  exported: false\n  reflect type: struct caninterface=false\n    struct: 0\n  field: 3 buf\n  pkg: main\n  tag: \"\"\n  embedded: false\n  exported: false\n  reflect type: slice caninterface=false comparable=false\n    slice: uint8 2 2\n    pointer: true\n    nil: false\n    indexing: 0\n    reflect type: uint8 addrable=true caninterface=false name=uint8\n      uint: 71\n    indexing: 1\n    reflect type: uint8 addrable=true caninterface=false name=uint8\n      uint: 111\n  field: 4 Buf\n  pkg: \n  tag: \"\"\n  embedded: false\n  exported: true\n  reflect type: slice comparable=false\n    slice: uint8 1 1\n    pointer: true\n    nil: false\n    indexing: 0\n    reflect type: uint8 settable=true addrable=true name=uint8\n      uint: 88\nreflect type: ptr\n  pointer: true struct\n  nil: false\n  reflect type: struct settable=true addrable=true name=linkedList\n    struct: 2\n    field: 0 next\n    pkg: main\n    tag: \"description:\\\"chain\\\"\"\n    embedded: false\n    exported: false\n    reflect type: ptr addrable=true caninterface=false\n      pointer: false struct\n      nil: true\n    field: 1 foo\n    pkg: main\n    tag: \"\"\n    embedded: false\n    exported: false\n    reflect type: int addrable=true caninterface=false name=int\n      int: 42\nreflect type: struct\n  struct: 2\n  field: 0 A\n  pkg: \n  tag: \"\"\n  embedded: false\n  exported: true\n  reflect type: uintptr name=uintptr\n    uint: 2\n  field: 1 B\n  pkg: \n  tag: \"\"\n  embedded: false\n  exported: true\n  reflect type: uintptr name=uintptr\n    uint: 3\nreflect type: slice comparable=false\n  slice: interface 3 3\n  pointer: true\n  nil: false\n  indexing: 0\n  reflect type: interface settable=true addrable=true\n    interface\n    nil: false\n    NumMethod: 0\n    reflect type: int name=int\n      int: 3\n  indexing: 1\n  reflect type: interface settable=true addrable=true\n    interface\n    nil: false\n    NumMethod: 0\n    reflect type: string name=string\n      string: str 3\n      reflect type: uint8 name=uint8\n        uint: 115\n      reflect type: uint8 name=uint8\n        uint: 116\n      reflect type: uint8 name=uint8\n        uint: 114\n  indexing: 2\n  reflect type: interface settable=true addrable=true\n    interface\n    nil: false\n    NumMethod: 0\n    reflect type: complex128 name=complex128\n      complex: (-4.000000e+000+2.500000e+000i)\nreflect type: ptr\n  pointer: true int8\n  nil: false\n  reflect type: int8 settable=true addrable=true name=int8\n    int: 5\nreflect type: ptr\n  pointer: true int16\n  nil: false\n  reflect type: int16 settable=true addrable=true name=int16\n    int: -800\nreflect type: ptr\n  pointer: true int32\n  nil: false\n  reflect type: int32 settable=true addrable=true name=int32\n    int: 100000000\nreflect type: ptr\n  pointer: true int64\n  nil: false\n  reflect type: int64 settable=true addrable=true name=int64\n    int: -1000000000000\nreflect type: ptr\n  pointer: true complex128\n  nil: false\n  reflect type: complex128 settable=true addrable=true name=complex128\n    complex: (-8.000000e+000-2.000000e+006i)\n\nsizes:\nint8 1 8\nint16 2 16\nint32 4 32\nint64 8 64\nuint8 1 8\nuint16 2 16\nuint32 4 32\nuint64 8 64\nfloat32 4 32\nfloat64 8 64\ncomplex64 8 64\ncomplex128 16 128\noffset for int64 matches: true\noffset for complex128 matches: true\ntype assertion succeeded for unreferenced type\n\nalignment / offset:\nstruct{[0]func(); byte}: true\n\nstruct tags\nblue gopher\n\nv.Interface() method\nkind: interface\nint 5\n"
  },
  {
    "path": "testdata/signal.go",
    "content": "package main\n\n// Test POSIX signals.\n// TODO: run `tinygo test os/signal` instead, once CGo errno return values are\n// supported.\n\nimport (\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n\t\"time\"\n)\n\nfunc main() {\n\tc := make(chan os.Signal, 1)\n\tsignal.Notify(c, syscall.SIGUSR1)\n\n\t// Wait for signals to arrive.\n\tgo func() {\n\t\tfor sig := range c {\n\t\t\tif sig == syscall.SIGUSR1 {\n\t\t\t\tprintln(\"got expected signal\")\n\t\t\t} else {\n\t\t\t\tprintln(\"got signal:\", sig.String())\n\t\t\t}\n\t\t}\n\t}()\n\n\t// Send the signal.\n\tsyscall.Kill(syscall.Getpid(), syscall.SIGUSR1)\n\n\ttime.Sleep(time.Millisecond * 100)\n\n\t// Stop notifying.\n\t// (This is just a smoke test, it's difficult to test the default behavior\n\t// in a unit test).\n\tsignal.Ignore(syscall.SIGUSR1)\n\n\tsignal.Stop(c)\n\n\tprintln(\"exiting signal program\")\n}\n"
  },
  {
    "path": "testdata/signal.txt",
    "content": "got expected signal\nexiting signal program\n"
  },
  {
    "path": "testdata/slice.go",
    "content": "package main\n\nimport \"unsafe\"\n\ntype MySlice [32]byte\n\ntype myUint8 uint8\n\ntype RecursiveSlice []RecursiveSlice\n\n// Indexing into slice with named type (regression test).\nvar array = [4]int{\n\tmyUint8(2): 3,\n}\n\nfunc main() {\n\tl := 5\n\tfoo := []int{1, 2, 4, 5}\n\tbar := make([]int, l-2, l)\n\tprintln(\"foo is nil?\", foo == nil, nil == foo)\n\tprintslice(\"foo\", foo)\n\tprintslice(\"bar\", bar)\n\tprintslice(\"foo[1:2]\", foo[1:2])\n\tprintln(\"sum foo:\", sum(foo))\n\n\t// creating a slice of uncommon base type\n\tassert(len(make([]struct{}, makeInt(4))) == 4)\n\n\t// creating a slice with uncommon len, cap types\n\tassert(len(make([]int, makeInt(2), makeInt(3))) == 2)\n\tassert(len(make([]int, makeInt8(2), makeInt8(3))) == 2)\n\tassert(len(make([]int, makeInt16(2), makeInt16(3))) == 2)\n\tassert(len(make([]int, makeInt32(2), makeInt32(3))) == 2)\n\tassert(len(make([]int, makeInt64(2), makeInt64(3))) == 2)\n\tassert(len(make([]int, makeUint(2), makeUint(3))) == 2)\n\tassert(len(make([]int, makeUint8(2), makeUint8(3))) == 2)\n\tassert(len(make([]int, makeUint16(2), makeUint16(3))) == 2)\n\tassert(len(make([]int, makeUint32(2), makeUint32(3))) == 2)\n\tassert(len(make([]int, makeUint64(2), makeUint64(3))) == 2)\n\tassert(len(make([]int, makeUintptr(2), makeUintptr(3))) == 2)\n\tassert(len(make([]int, makeMyUint8(2), makeMyUint8(3))) == 2)\n\n\t// indexing into a slice with uncommon index types\n\tassert(foo[int(2)] == 4)\n\tassert(foo[int8(2)] == 4)\n\tassert(foo[int16(2)] == 4)\n\tassert(foo[int32(2)] == 4)\n\tassert(foo[int64(2)] == 4)\n\tassert(foo[uint(2)] == 4)\n\tassert(foo[uint8(2)] == 4)\n\tassert(foo[uint16(2)] == 4)\n\tassert(foo[uint32(2)] == 4)\n\tassert(foo[uint64(2)] == 4)\n\tassert(foo[uintptr(2)] == 4)\n\n\t// slicing with uncommon low, high types\n\tassert(len(foo[int(1):int(3)]) == 2)\n\tassert(len(foo[int8(1):int8(3)]) == 2)\n\tassert(len(foo[int16(1):int16(3)]) == 2)\n\tassert(len(foo[int32(1):int32(3)]) == 2)\n\tassert(len(foo[int64(1):int64(3)]) == 2)\n\tassert(len(foo[uint(1):uint(3)]) == 2)\n\tassert(len(foo[uint8(1):uint8(3)]) == 2)\n\tassert(len(foo[uint16(1):uint16(3)]) == 2)\n\tassert(len(foo[uint32(1):uint32(3)]) == 2)\n\tassert(len(foo[uint64(1):uint64(3)]) == 2)\n\tassert(len(foo[uintptr(1):uintptr(3)]) == 2)\n\n\t// slicing an array with uncommon low, high types\n\tarr := [4]int{1, 2, 4, 5}\n\tassert(len(arr[int(1):int(3)]) == 2)\n\tassert(len(arr[int8(1):int8(3)]) == 2)\n\tassert(len(arr[int16(1):int16(3)]) == 2)\n\tassert(len(arr[int32(1):int32(3)]) == 2)\n\tassert(len(arr[int64(1):int64(3)]) == 2)\n\tassert(len(arr[uint(1):uint(3)]) == 2)\n\tassert(len(arr[uint8(1):uint8(3)]) == 2)\n\tassert(len(arr[uint16(1):uint16(3)]) == 2)\n\tassert(len(arr[uint32(1):uint32(3)]) == 2)\n\tassert(len(arr[uint64(1):uint64(3)]) == 2)\n\tassert(len(arr[uintptr(1):uintptr(3)]) == 2)\n\n\t// slicing with max parameter (added in Go 1.2)\n\tlongfoo := []int{1, 2, 4, 5, 10, 11}\n\tassert(cap(longfoo[int(1):int(3):int(5)]) == 4)\n\tassert(cap(longfoo[int8(1):int8(3):int8(5)]) == 4)\n\tassert(cap(longfoo[int16(1):int16(3):int16(5)]) == 4)\n\tassert(cap(longfoo[int32(1):int32(3):int32(5)]) == 4)\n\tassert(cap(longfoo[int64(1):int64(3):int64(5)]) == 4)\n\tassert(cap(longfoo[uint(1):uint(3):uint(5)]) == 4)\n\tassert(cap(longfoo[uint8(1):uint8(3):uint8(5)]) == 4)\n\tassert(cap(longfoo[uint16(1):uint16(3):uint16(5)]) == 4)\n\tassert(cap(longfoo[uint32(1):uint32(3):uint32(5)]) == 4)\n\tassert(cap(longfoo[uint64(1):uint64(3):uint64(5)]) == 4)\n\tassert(cap(longfoo[uintptr(1):uintptr(3):uintptr(5)]) == 4)\n\n\t// slicing an array with max parameter (added in Go 1.2)\n\tassert(cap(arr[int(1):int(2):int(4)]) == 3)\n\tassert(cap(arr[int8(1):int8(2):int8(4)]) == 3)\n\tassert(cap(arr[int16(1):int16(2):int16(4)]) == 3)\n\tassert(cap(arr[int32(1):int32(2):int32(4)]) == 3)\n\tassert(cap(arr[int64(1):int64(2):int64(4)]) == 3)\n\tassert(cap(arr[uint(1):uint(2):uint(4)]) == 3)\n\tassert(cap(arr[uint8(1):uint8(2):uint8(4)]) == 3)\n\tassert(cap(arr[uint16(1):uint16(2):uint16(4)]) == 3)\n\tassert(cap(arr[uint32(1):uint32(2):uint32(4)]) == 3)\n\tassert(cap(arr[uint64(1):uint64(2):uint64(4)]) == 3)\n\tassert(cap(arr[uintptr(1):uintptr(2):uintptr(4)]) == 3)\n\n\t// copy\n\tprintln(\"copy foo -> bar:\", copy(bar, foo))\n\tprintslice(\"bar\", bar)\n\n\t// append\n\tvar grow []int\n\tprintln(\"slice is nil?\", grow == nil, nil == grow)\n\tprintslice(\"grow\", grow)\n\tgrow = append(grow, 42)\n\tprintslice(\"grow\", grow)\n\tgrow = append(grow, -1, -2)\n\tprintslice(\"grow\", grow)\n\tgrow = append(grow, foo...)\n\tprintslice(\"grow\", grow)\n\tgrow = append(grow)\n\tprintslice(\"grow\", grow)\n\tgrow = append(grow, grow...)\n\tprintslice(\"grow\", grow)\n\n\t// append string to []bytes\n\tbytes := append([]byte{1, 2, 3}, \"foo\"...)\n\tprint(\"bytes: len=\", len(bytes), \" cap=\", cap(bytes), \" data:\")\n\tfor _, n := range bytes {\n\t\tprint(\" \", n)\n\t}\n\tprintln()\n\n\t// Test conversion from array to slice.\n\tslice1 := []int{1, 2, 3, 4}\n\tarr1 := (*[4]int)(slice1)\n\tarr1[1] = -2\n\tarr1[2] = 20\n\tprintln(\"slice to array pointer:\", arr1[0], arr1[1], arr1[2], arr1[3])\n\n\t// Test unsafe.Add.\n\tarr2 := [...]int{1, 2, 3, 4}\n\t*(*int)(unsafe.Add(unsafe.Pointer(&arr2[0]), unsafe.Sizeof(int(1))*1)) = 5\n\t*addInt(&arr2[0], 2) = 8\n\tprintln(\"unsafe.Add array:\", arr2[0], arr2[1], arr2[2], arr2[3])\n\n\t// Test unsafe.Slice.\n\tarr3 := [...]int{1, 2, 3, 4}\n\tslice3 := unsafe.Slice(&arr3[1], 3)\n\tslice3[0] = 9\n\tslice3[1] = 15\n\tprintln(\"unsafe.Slice array:\", len(slice3), cap(slice3), slice3[0], slice3[1], slice3[2])\n\n\t// Verify the fix in https://github.com/tinygo-org/tinygo/pull/119\n\tvar unnamed [32]byte\n\tvar named MySlice\n\tassert(len(unnamed[:]) == 32)\n\tassert(len(named[:]) == 32)\n\tfor _, c := range named {\n\t\tassert(c == 0)\n\t}\n\n\t// Test recursive slices.\n\trs := []RecursiveSlice(nil)\n\tprintln(\"len:\", len(rs))\n}\n\nfunc printslice(name string, s []int) {\n\tprint(name, \": len=\", len(s), \" cap=\", cap(s), \" data:\")\n\tfor _, n := range s {\n\t\tprint(\" \", n)\n\t}\n\tprintln()\n}\n\nfunc sum(l []int) int {\n\tsum := 0\n\tfor _, n := range l {\n\t\tsum += n\n\t}\n\treturn sum\n}\n\nfunc assert(ok bool) {\n\tif !ok {\n\t\tpanic(\"assert failed\")\n\t}\n}\n\n// Helper functions used to hide const values from the compiler during IR\n// construction.\n\nfunc makeInt(x int) int             { return x }\nfunc makeInt8(x int8) int8          { return x }\nfunc makeInt16(x int16) int16       { return x }\nfunc makeInt32(x int32) int32       { return x }\nfunc makeInt64(x int64) int64       { return x }\nfunc makeUint(x uint) uint          { return x }\nfunc makeUint8(x uint8) uint8       { return x }\nfunc makeUint16(x uint16) uint16    { return x }\nfunc makeUint32(x uint32) uint32    { return x }\nfunc makeUint64(x uint64) uint64    { return x }\nfunc makeUintptr(x uintptr) uintptr { return x }\nfunc makeMyUint8(x myUint8) myUint8 { return x }\n\nfunc addInt(ptr *int, index uintptr) *int {\n\treturn (*int)(unsafe.Add(unsafe.Pointer(ptr), unsafe.Sizeof(int(1))*index))\n}\n"
  },
  {
    "path": "testdata/slice.txt",
    "content": "foo is nil? false false\nfoo: len=4 cap=4 data: 1 2 4 5\nbar: len=3 cap=5 data: 0 0 0\nfoo[1:2]: len=1 cap=3 data: 2\nsum foo: 12\ncopy foo -> bar: 3\nbar: len=3 cap=5 data: 1 2 4\nslice is nil? true true\ngrow: len=0 cap=0 data:\ngrow: len=1 cap=2 data: 42\ngrow: len=3 cap=4 data: 42 -1 -2\ngrow: len=7 cap=8 data: 42 -1 -2 1 2 4 5\ngrow: len=7 cap=8 data: 42 -1 -2 1 2 4 5\ngrow: len=14 cap=16 data: 42 -1 -2 1 2 4 5 42 -1 -2 1 2 4 5\nbytes: len=6 cap=8 data: 1 2 3 102 111 111\nslice to array pointer: 1 -2 20 4\nunsafe.Add array: 1 5 8 4\nunsafe.Slice array: 3 3 9 15 4\nlen: 0\n"
  },
  {
    "path": "testdata/sort.go",
    "content": "package main\n\nimport \"sort\"\n\n// sort.Slice implicitly uses reflect.Swapper\n\nfunc strings() {\n\tdata := []string{\"aaaa\", \"cccc\", \"bbb\", \"fff\", \"ggg\"}\n\tsort.Slice(data, func(i, j int) bool {\n\t\treturn data[i] > data[j]\n\t})\n\tprintln(\"strings\")\n\tfor _, d := range data {\n\t\tprintln(d)\n\t}\n}\n\nfunc int64s() {\n\tsd := []int64{1, 6, 3, 2, 1923, 123, -123, -29, 3, 0, 1}\n\tsort.Slice(sd, func(i, j int) bool {\n\t\treturn sd[i] > sd[j]\n\t})\n\tprintln(\"int64s\")\n\tfor _, d := range sd {\n\t\tprintln(d)\n\t}\n\n\tud := []uint64{1, 6, 3, 2, 1923, 123, 29, 3, 0, 1}\n\tsort.Slice(ud, func(i, j int) bool {\n\t\treturn ud[i] > ud[j]\n\t})\n\tprintln(\"uint64s\")\n\tfor _, d := range ud {\n\t\tprintln(d)\n\t}\n}\n\nfunc int32s() {\n\tsd := []int32{1, 6, 3, 2, 1923, 123, -123, -29, 3, 0, 1}\n\tsort.Slice(sd, func(i, j int) bool {\n\t\treturn sd[i] > sd[j]\n\t})\n\tprintln(\"int32s\")\n\tfor _, d := range sd {\n\t\tprintln(d)\n\t}\n\n\tud := []uint32{1, 6, 3, 2, 1923, 123, 29, 3, 0, 1}\n\tsort.Slice(ud, func(i, j int) bool {\n\t\treturn ud[i] > ud[j]\n\t})\n\tprintln(\"uint32s\")\n\tfor _, d := range ud {\n\t\tprintln(d)\n\t}\n}\n\nfunc int16s() {\n\tsd := []int16{1, 6, 3, 2, 1923, 123, -123, -29, 3, 0, 1}\n\tsort.Slice(sd, func(i, j int) bool {\n\t\treturn sd[i] > sd[j]\n\t})\n\tprintln(\"int16s\")\n\tfor _, d := range sd {\n\t\tprintln(d)\n\t}\n\n\tud := []uint16{1, 6, 3, 2, 1923, 123, 29, 3, 0, 1}\n\tsort.Slice(ud, func(i, j int) bool {\n\t\treturn ud[i] > ud[j]\n\t})\n\tprintln(\"uint16s\")\n\tfor _, d := range ud {\n\t\tprintln(d)\n\t}\n}\n\nfunc int8s() {\n\tsd := []int8{1, 6, 3, 2, 123, -123, -29, 3, 0, 1}\n\tsort.Slice(sd, func(i, j int) bool {\n\t\treturn sd[i] > sd[j]\n\t})\n\tprintln(\"int8s\")\n\tfor _, d := range sd {\n\t\tprintln(d)\n\t}\n\n\tud := []uint8{1, 6, 3, 2, 123, 29, 3, 0, 1}\n\tsort.Slice(ud, func(i, j int) bool {\n\t\treturn ud[i] > ud[j]\n\t})\n\tprintln(\"uint8s\")\n\tfor _, d := range ud {\n\t\tprintln(d)\n\t}\n}\n\nfunc ints() {\n\tsd := []int{1, 6, 3, 2, 123, -123, -29, 3, 0, 1}\n\tsort.Slice(sd, func(i, j int) bool {\n\t\treturn sd[i] > sd[j]\n\t})\n\tprintln(\"ints\")\n\tfor _, d := range sd {\n\t\tprintln(d)\n\t}\n\n\tud := []uint{1, 6, 3, 2, 123, 29, 3, 0, 1}\n\tsort.Slice(ud, func(i, j int) bool {\n\t\treturn ud[i] > ud[j]\n\t})\n\tprintln(\"uints\")\n\tfor _, d := range ud {\n\t\tprintln(d)\n\t}\n}\n\nfunc structs() {\n\ttype s struct {\n\t\tname string\n\t\ta    uint64\n\t\tb    uint32\n\t\tc    uint16\n\t\td    int\n\t\te    *struct {\n\t\t\taa uint16\n\t\t\tbb int\n\t\t}\n\t}\n\n\tdata := []s{\n\t\t{\n\t\t\tname: \"struct 1\",\n\t\t\td:    100,\n\t\t\te: &struct {\n\t\t\t\taa uint16\n\t\t\t\tbb int\n\t\t\t}{aa: 123, bb: -10},\n\t\t},\n\t\t{\n\t\t\tname: \"struct 2\",\n\t\t\td:    1,\n\t\t\te: &struct {\n\t\t\t\taa uint16\n\t\t\t\tbb int\n\t\t\t}{aa: 15, bb: 10},\n\t\t},\n\t\t{\n\t\t\tname: \"struct 3\",\n\t\t\td:    10,\n\t\t\te: &struct {\n\t\t\t\taa uint16\n\t\t\t\tbb int\n\t\t\t}{aa: 31, bb: -1030},\n\t\t},\n\t\t{\n\t\t\tname: \"struct 4\",\n\t\t\te: &struct {\n\t\t\t\taa uint16\n\t\t\t\tbb int\n\t\t\t}{},\n\t\t},\n\t}\n\tsort.Slice(data, func(i, j int) bool {\n\t\tdi := data[i]\n\t\tdj := data[j]\n\t\treturn di.d*di.e.bb > dj.d*dj.e.bb\n\t})\n\tprintln(\"structs\")\n\tfor _, d := range data {\n\t\tprintln(d.name)\n\t}\n}\n\nfunc main() {\n\tstrings()\n\tint64s()\n\tint32s()\n\tint16s()\n\tint8s()\n\tints()\n\tstructs()\n}\n"
  },
  {
    "path": "testdata/sort.txt",
    "content": "strings\nggg\nfff\ncccc\nbbb\naaaa\nint64s\n1923\n123\n6\n3\n3\n2\n1\n1\n0\n-29\n-123\nuint64s\n1923\n123\n29\n6\n3\n3\n2\n1\n1\n0\nint32s\n1923\n123\n6\n3\n3\n2\n1\n1\n0\n-29\n-123\nuint32s\n1923\n123\n29\n6\n3\n3\n2\n1\n1\n0\nint16s\n1923\n123\n6\n3\n3\n2\n1\n1\n0\n-29\n-123\nuint16s\n1923\n123\n29\n6\n3\n3\n2\n1\n1\n0\nint8s\n123\n6\n3\n3\n2\n1\n1\n0\n-29\n-123\nuint8s\n123\n29\n6\n3\n3\n2\n1\n1\n0\nints\n123\n6\n3\n3\n2\n1\n1\n0\n-29\n-123\nuints\n123\n29\n6\n3\n3\n2\n1\n1\n0\nstructs\nstruct 2\nstruct 4\nstruct 1\nstruct 3\n"
  },
  {
    "path": "testdata/stdlib.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"math/rand\"\n\t\"os\"\n\t\"strings\"\n\t\"syscall\"\n\t\"time\"\n)\n\nfunc main() {\n\t// package os, fmt\n\tfmt.Println(\"stdin: \", os.Stdin.Name())\n\tfmt.Println(\"stdout:\", os.Stdout.Name())\n\tfmt.Println(\"stderr:\", os.Stderr.Name())\n\n\t// Package syscall, this mostly checks whether the calls don't trigger an error.\n\tsyscall.Getuid()\n\tsyscall.Geteuid()\n\tsyscall.Getgid()\n\tsyscall.Getegid()\n\tsyscall.Getpid()\n\tsyscall.Getppid()\n\n\t// package math/rand\n\tfmt.Println(\"pseudorandom number:\", rand.New(rand.NewSource(1)).Int31())\n\n\t// package strings\n\tfmt.Println(\"strings.IndexByte:\", strings.IndexByte(\"asdf\", 'd'))\n\tfmt.Println(\"strings.Replace:\", strings.Replace(\"An example string\", \" \", \"-\", -1))\n\n\t// package time\n\ttime.Sleep(time.Millisecond)\n\ttime.Sleep(-1) // negative sleep should return immediately\n\n\t// Exit the program normally.\n\tos.Exit(0)\n}\n"
  },
  {
    "path": "testdata/stdlib.txt",
    "content": "stdin:  /dev/stdin\nstdout: /dev/stdout\nstderr: /dev/stderr\npseudorandom number: 1298498081\nstrings.IndexByte: 2\nstrings.Replace: An-example-string\n"
  },
  {
    "path": "testdata/string.go",
    "content": "package main\n\nfunc testRangeString() {\n\tfor i, c := range \"abcü¢€𐍈°x\" {\n\t\tprintln(i, c)\n\t}\n}\n\nfunc testStringToRunes() {\n\tvar s = \"abcü¢€𐍈°x\"\n\tfor i, c := range []rune(s) {\n\t\tprintln(i, c)\n\t}\n}\n\nfunc testRunesToString(r []rune) {\n\tprintln(\"string from runes:\", string(r))\n}\n\ntype myString string\n\nfunc main() {\n\ttestRangeString()\n\ttestStringToRunes()\n\ttestRunesToString([]rune{97, 98, 99, 252, 162, 8364, 66376, 176, 120})\n\tvar _ = len([]byte(myString(\"foobar\"))) // issue 1246\n}\n"
  },
  {
    "path": "testdata/string.txt",
    "content": "0 97\n1 98\n2 99\n3 252\n5 162\n7 8364\n10 66376\n14 176\n16 120\n0 97\n1 98\n2 99\n3 252\n4 162\n5 8364\n6 66376\n7 176\n8 120\nstring from runes: abcü¢€𐍈°x\n"
  },
  {
    "path": "testdata/structs.go",
    "content": "package main\n\n// TODO: add .ll test files to check the output\n\ntype s0 struct {\n}\n\ntype s1 struct {\n\ta byte\n}\n\ntype s2 struct {\n\ta byte\n\tb byte\n}\n\ntype s3 struct {\n\ta byte\n\tb byte\n\tc byte\n}\n\n// should not be expanded\ntype s4 struct {\n\ta byte\n\tb byte\n\tc byte\n\td byte\n}\n\n// same struct, different type\ntype s4b struct {\n\ta byte\n\tb byte\n\tc byte\n\td byte\n}\n\ntype s5 struct {\n\ta struct {\n\t\taa byte\n\t\tab byte\n\t}\n\tb byte\n}\n\ntype s6 struct {\n\ta string\n\tb byte\n}\n\ntype s7 struct {\n\ta interface{}\n\tb byte\n}\n\n// should not be expanded\ntype s8 struct {\n\ta []byte // 3 elements\n\tb byte   // 1 element\n}\n\n// linked list (recursive type)\ntype s9 struct {\n\tn    int\n\tnext *s9\n\ts    []*s9\n}\n\nfunc test0(s s0) {\n\tprintln(\"test0\")\n}\n\nfunc test1(s s1) {\n\tprintln(\"test1\", s.a)\n}\n\nfunc test2(s s2) {\n\tprintln(\"test2\", s.a, s.b)\n}\n\nfunc test3(s s3) {\n\tprintln(\"test3\", s.a, s.b, s.c)\n}\n\nfunc test4(s s4) {\n\tprintln(\"test4\", s.a, s.b, s.c, s.d)\n\ttest4b(s4b(s))\n\ttest4bp((*s4b)(&s))\n}\n\nfunc test4b(s s4b) {\n\tprintln(\"test4b\", s.a, s.b, s.c, s.d)\n}\n\nfunc test4bp(s *s4b) {\n\tprintln(\"test4bp\", s.a, s.b, s.c, s.d)\n}\n\nfunc test5(s s5) {\n\tprintln(\"test5\", s.a.aa, s.a.ab, s.b)\n}\n\nfunc test6(s s6) {\n\tprintln(\"test6\", s.a, len(s.a), s.b)\n}\n\nfunc test7(s s7) {\n\tprintln(\"test7\", s.a, s.b)\n}\n\nfunc test8(s s8) {\n\tprintln(\"test8\", len(s.a), cap(s.a), s.a[0], s.a[1], s.b)\n}\n\nfunc test9(s s9) {\n\tprintln(\"test9\", s.next.next)\n}\n\nfunc main() {\n\ttest0(s0{})\n\ttest1(s1{1})\n\ttest2(s2{1, 2})\n\ttest3(s3{1, 2, 3})\n\ttest4(s4{1, 2, 3, 4})\n\ttest5(s5{a: struct {\n\t\taa byte\n\t\tab byte\n\t}{1, 2}, b: 3})\n\ttest6(s6{\"foo\", 5})\n\ttest7(s7{a: nil, b: 8})\n\ttest8(s8{[]byte{12, 13, 14}[:2], 6})\n\ttest9(s9{next: &s9{}})\n}\n"
  },
  {
    "path": "testdata/structs.txt",
    "content": "test0\ntest1 1\ntest2 1 2\ntest3 1 2 3\ntest4 1 2 3 4\ntest4b 1 2 3 4\ntest4bp 1 2 3 4\ntest5 1 2 3\ntest6 foo 3 5\ntest7 (0:nil) 8\ntest8 2 3 12 13 6\ntest9 nil\n"
  },
  {
    "path": "testdata/testing.go",
    "content": "package main\n\n// TODO: also test the verbose version.\n\nimport (\n\t\"errors\"\n\t\"flag\"\n\t\"io\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestFoo(t *testing.T) {\n\tt.Log(\"log Foo.a\")\n\tt.Log(\"log Foo.b\")\n}\n\nfunc TestBar(t *testing.T) {\n\tt.Log(\"log Bar\")\n\tt.Log(\"log g\\nh\\ni\\n\")\n\tt.Run(\"Bar1\", func(t *testing.T) {})\n\tt.Run(\"Bar2\", func(t *testing.T) {\n\t\tt.Log(\"log Bar2\\na\\nb\\nc\")\n\t\tt.Error(\"failed\")\n\t\tt.Log(\"after failed\")\n\t})\n\tt.Run(\"Bar3\", func(t *testing.T) {})\n\tt.Log(\"log Bar end\")\n}\n\nfunc TestAllLowercase(t *testing.T) {\n\tnames := []string {\n\t\t\"alpha\",\n\t\t\"BETA\",\n\t\t\"gamma\",\n\t\t\"BELTA\",\n\t}\n\n\tfor _, name := range names {\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\tif 'a' <= name[0] && name[0] <= 'a' {\n\t\t\t\tt.Logf(\"expected lowercase name, and got one, so I'm happy\")\n\t\t\t} else {\n\t\t\t\tt.Errorf(\"expected lowercase name, got %s\", name)\n\t\t\t}\n\t\t})\n\t}\n}\n\nvar tests = []testing.InternalTest{\n\t{\"TestFoo\", TestFoo},\n\t{\"TestBar\", TestBar},\n\t{\"TestAllLowercase\", TestAllLowercase},\n}\n\nvar benchmarks = []testing.InternalBenchmark{}\n\nvar fuzzes = []testing.InternalFuzzTarget{}\n\nvar examples = []testing.InternalExample{}\n\n// A fake regexp matcher.\n// Inflexible, but saves 50KB of flash and 50KB of RAM per -size full,\n// and lets tests pass on cortex-m.\n// Must match the one in src/testing/match.go that is substituted on bare-metal platforms,\n// or \"make test\" will fail there.\nfunc fakeMatchString(pat, str string) (bool, error) {\n\tif pat == \".*\" {\n\t\treturn true, nil\n\t}\n\tmatched := strings.Contains(str, pat)\n\treturn matched, nil\n}\n\nfunc main() {\n\tif testing.Testing() {\n\t\tprintln(\"not running a test at the moment, testing.Testing() should return false\")\n\t}\n\ttesting.Init()\n\tflag.Set(\"test.run\", \".*/B\")\n\tm := testing.MainStart(matchStringOnly(fakeMatchString /*regexp.MatchString*/), tests, benchmarks, fuzzes, examples)\n\n\texitcode := m.Run()\n\tif exitcode != 0 {\n\t\tprintln(\"exitcode:\", exitcode)\n\t}\n}\n\nvar errMain = errors.New(\"testing: unexpected use of func Main\")\n\n// matchStringOnly is part of upstream, and is used below to provide a dummy deps to pass to MainStart\n// so it can be run with go (tested with go 1.16) to provide a baseline for the regression test.\n// See c56cc9b3b57276.  Unfortunately, testdeps is internal, so we can't just use &testdeps.TestDeps{}.\ntype matchStringOnly func(pat, str string) (bool, error)\n\nfunc (f matchStringOnly) MatchString(pat, str string) (bool, error)   { return f(pat, str) }\nfunc (f matchStringOnly) StartCPUProfile(w io.Writer) error           { return errMain }\nfunc (f matchStringOnly) StopCPUProfile()                             {}\nfunc (f matchStringOnly) WriteProfileTo(string, io.Writer, int) error { return errMain }\nfunc (f matchStringOnly) ImportPath() string                          { return \"\" }\nfunc (f matchStringOnly) StartTestLog(io.Writer)                      {}\nfunc (f matchStringOnly) StopTestLog() error                          { return errMain }\nfunc (f matchStringOnly) SetPanicOnExit0(bool)                        {}\n"
  },
  {
    "path": "testdata/testing.txt",
    "content": "--- FAIL: TestBar (0.00s)\n    log Bar\n    log g\n        h\n        i\n        \n    --- FAIL: TestBar/Bar2 (0.00s)\n        log Bar2\n            a\n            b\n            c\n        failed\n        after failed\n    log Bar end\n--- FAIL: TestAllLowercase (0.00s)\n    --- FAIL: TestAllLowercase/BETA (0.00s)\n        expected lowercase name, got BETA\n    --- FAIL: TestAllLowercase/BELTA (0.00s)\n        expected lowercase name, got BELTA\nFAIL\nexitcode: 1\n"
  },
  {
    "path": "testdata/timers.go",
    "content": "package main\n\nimport \"time\"\n\nvar timer = time.NewTimer(time.Millisecond)\n\nfunc main() {\n\t// Test ticker.\n\tticker := time.NewTicker(time.Millisecond * 500)\n\tprintln(\"waiting on ticker\")\n\tgo func() {\n\t\ttime.Sleep(time.Millisecond * 150)\n\t\tprintln(\" - after 150ms\")\n\t\ttime.Sleep(time.Millisecond * 200)\n\t\tprintln(\" - after 200ms\")\n\t\ttime.Sleep(time.Millisecond * 300)\n\t\tprintln(\" - after 300ms\")\n\t}()\n\t<-ticker.C\n\tprintln(\"waited on ticker at 500ms\")\n\t<-ticker.C\n\tprintln(\"waited on ticker at 1000ms\")\n\tticker.Stop()\n\ttime.Sleep(time.Millisecond * 750)\n\tselect {\n\tcase <-ticker.C:\n\t\tprintln(\"fail: ticker should have stopped!\")\n\tdefault:\n\t\tprintln(\"ticker was stopped (didn't send anything after 750ms)\")\n\t}\n\n\ttimer := time.NewTimer(time.Millisecond * 750)\n\tprintln(\"waiting on timer\")\n\tgo func() {\n\t\ttime.Sleep(time.Millisecond * 200)\n\t\tprintln(\" - after 200ms\")\n\t\ttime.Sleep(time.Millisecond * 400)\n\t\tprintln(\" - after 400ms\")\n\t}()\n\t<-timer.C\n\tprintln(\"waited on timer at 750ms\")\n\ttime.Sleep(time.Millisecond * 500)\n\n\treset := timer.Reset(time.Millisecond * 750)\n\tprintln(\"timer reset:\", reset)\n\tprintln(\"waiting on timer\")\n\tgo func() {\n\t\ttime.Sleep(time.Millisecond * 200)\n\t\tprintln(\" - after 200ms\")\n\t\ttime.Sleep(time.Millisecond * 400)\n\t\tprintln(\" - after 400ms\")\n\t}()\n\t<-timer.C\n\tprintln(\"waited on timer at 750ms\")\n\ttime.Sleep(time.Millisecond * 500)\n}\n"
  },
  {
    "path": "testdata/timers.txt",
    "content": "waiting on ticker\n - after 150ms\n - after 200ms\nwaited on ticker at 500ms\n - after 300ms\nwaited on ticker at 1000ms\nticker was stopped (didn't send anything after 750ms)\nwaiting on timer\n - after 200ms\n - after 400ms\nwaited on timer at 750ms\ntimer reset: false\nwaiting on timer\n - after 200ms\n - after 400ms\nwaited on timer at 750ms\n"
  },
  {
    "path": "testdata/trivialpanic.go",
    "content": "package main\n\nvar n *int\n\nfunc main() {\n\tprintln(*n) // this will panic\n}\n"
  },
  {
    "path": "testdata/wasmexit.go",
    "content": "package main\n\nimport (\n\t\"os\"\n\t\"time\"\n)\n\nfunc main() {\n\tprintln(\"wasmexit test:\", os.Args[1])\n\tswitch os.Args[1] {\n\tcase \"normal\":\n\t\treturn\n\tcase \"exit-0\":\n\t\tos.Exit(0)\n\tcase \"exit-0-sleep\":\n\t\ttime.Sleep(time.Millisecond)\n\t\tprintln(\"slept\")\n\t\tos.Exit(0)\n\tcase \"exit-1\":\n\t\tos.Exit(1)\n\tcase \"exit-1-sleep\":\n\t\ttime.Sleep(time.Millisecond)\n\t\tprintln(\"slept\")\n\t\tos.Exit(1)\n\t}\n\tprintln(\"unknown wasmexit test\")\n}\n"
  },
  {
    "path": "testdata/wasmexit.js",
    "content": "require('../targets/wasm_exec.js');\n\nfunction runTests() {\n    let testCall = (name, params, expected) => {\n        let result = go._inst.exports[name].apply(null, params);\n        if (result !== expected) {\n            console.error(`${name}(...${params}): expected result ${expected}, got ${result}`);\n        }\n    }\n\n    // These are the same tests as in TestWasmExport.\n    testCall('hello', [], undefined);\n    testCall('add', [3, 5], 8);\n    testCall('add', [7, 9], 16);\n    testCall('add', [6, 1], 7);\n    testCall('reentrantCall', [2, 3], 5);\n    testCall('reentrantCall', [1, 8], 9);\n}\n\nlet go = new Go();\ngo.importObject.tester = {\n    callOutside: (a, b) => {\n        return go._inst.exports.add(a, b);\n    },\n    callTestMain: () => {\n        runTests();\n    },\n};\nWebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then(async (result) => {\n    let value = await go.run(result.instance);\n    console.log('exit code:', value);\n}).catch((err) => {\n    console.error(err);\n    process.exit(1);\n});\n"
  },
  {
    "path": "testdata/wasmexport-noscheduler.go",
    "content": "package main\n\nimport \"time\"\n\nfunc init() {\n\tprintln(\"called init\")\n}\n\n//go:wasmimport tester callTestMain\nfunc callTestMain()\n\nfunc main() {\n\t// Check that exported functions can still be called after calling\n\t// time.Sleep.\n\ttime.Sleep(time.Millisecond)\n\n\t// main.main is not used when using -buildmode=c-shared.\n\tcallTestMain()\n}\n\n//go:wasmexport hello\nfunc hello() {\n\tprintln(\"hello!\")\n}\n\n//go:wasmexport add\nfunc add(a, b int32) int32 {\n\tprintln(\"called add:\", a, b)\n\treturn a + b\n}\n\n//go:wasmimport tester callOutside\nfunc callOutside(a, b int32) int32\n\n//go:wasmexport reentrantCall\nfunc reentrantCall(a, b int32) int32 {\n\tprintln(\"reentrantCall:\", a, b)\n\tresult := callOutside(a, b)\n\tprintln(\"reentrantCall result:\", result)\n\treturn result\n}\n\n//go:wasmexport goroutineExit\nfunc goroutineExit() {\n\t// Dummy, not a real test (since we have no scheduler).\n\tprintln(\"goroutineExit: exit\")\n}\n"
  },
  {
    "path": "testdata/wasmexport.go",
    "content": "package main\n\nimport (\n\t\"runtime\"\n\t\"time\"\n)\n\nfunc init() {\n\tprintln(\"called init\")\n\tgo adder()\n}\n\n//go:wasmimport tester callTestMain\nfunc callTestMain()\n\nfunc main() {\n\t// main.main is not used when using -buildmode=c-shared.\n\tcallTestMain()\n}\n\n//go:wasmexport hello\nfunc hello() {\n\tprintln(\"hello!\")\n}\n\n//go:wasmexport add\nfunc add(a, b int32) int32 {\n\tprintln(\"called add:\", a, b)\n\taddInputs <- a\n\taddInputs <- b\n\treturn <-addOutput\n}\n\nvar addInputs = make(chan int32)\nvar addOutput = make(chan int32)\n\nfunc adder() {\n\tfor {\n\t\ta := <-addInputs\n\t\tb := <-addInputs\n\t\ttime.Sleep(time.Millisecond)\n\t\taddOutput <- a + b\n\t}\n}\n\n//go:wasmimport tester callOutside\nfunc callOutside(a, b int32) int32\n\n//go:wasmexport reentrantCall\nfunc reentrantCall(a, b int32) int32 {\n\tprintln(\"reentrantCall:\", a, b)\n\tresult := callOutside(a, b)\n\tprintln(\"reentrantCall result:\", result)\n\treturn result\n}\n\n// Test for bug: https://github.com/tinygo-org/tinygo/issues/4874\n//\n//go:wasmexport goroutineExit\nfunc goroutineExit() {\n\tgo func() {\n\t\ttime.Sleep(time.Second * 10)\n\t\tprintln(\"goroutineExit: exiting goroutine\")\n\t}()\n\truntime.Gosched()\n\tprintln(\"goroutineExit: exit\")\n}\n"
  },
  {
    "path": "testdata/wasmexport.js",
    "content": "require('../targets/wasm_exec.js');\n\nfunction runTests() {\n    let testCall = (name, params, expected) => {\n        let result = go._inst.exports[name].apply(null, params);\n        if (result !== expected) {\n            console.error(`${name}(...${params}): expected result ${expected}, got ${result}`);\n        }\n    }\n\n    // These are the same tests as in TestWasmExport.\n    testCall('hello', [], undefined);\n    testCall('add', [3, 5], 8);\n    testCall('add', [7, 9], 16);\n    testCall('add', [6, 1], 7);\n    testCall('reentrantCall', [2, 3], 5);\n    testCall('reentrantCall', [1, 8], 9);\n    testCall('goroutineExit', [], undefined);\n}\n\nlet go = new Go();\ngo.importObject.tester = {\n    callOutside: (a, b) => {\n        return go._inst.exports.add(a, b);\n    },\n    callTestMain: () => {\n        runTests();\n    },\n};\nWebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then((result) => {\n    let buildMode = process.argv[3];\n    if (buildMode === 'default') {\n        go.run(result.instance);\n    } else if (buildMode === 'c-shared') {\n        go.run(result.instance);\n        runTests();\n    }\n}).catch((err) => {\n    console.error(err);\n    process.exit(1);\n});\n"
  },
  {
    "path": "testdata/wasmexport.txt",
    "content": "called init\nhello!\ncalled add: 3 5\ncalled add: 7 9\ncalled add: 6 1\nreentrantCall: 2 3\ncalled add: 2 3\nreentrantCall result: 5\nreentrantCall: 1 8\ncalled add: 1 8\nreentrantCall result: 9\ngoroutineExit: exit\n"
  },
  {
    "path": "testdata/wasmfunc.go",
    "content": "package main\n\nimport \"syscall/js\"\n\nfunc main() {\n\tjs.Global().Call(\"setCallback\", js.FuncOf(func(this js.Value, args []js.Value) any {\n\t\tprintln(\"inside callback! parameters:\")\n\t\tsum := 0\n\t\tfor _, value := range args {\n\t\t\tn := value.Int()\n\t\t\tprintln(\"  parameter:\", n)\n\t\t\tsum += n\n\t\t}\n\t\treturn sum\n\t}))\n\tjs.Global().Call(\"callCallback\")\n}\n"
  },
  {
    "path": "testdata/wasmfunc.js",
    "content": "require('../targets/wasm_exec.js');\n\nvar callback;\n\nglobal.setCallback = (cb) => {\n    callback = cb;\n};\n\nglobal.callCallback = () => {\n    console.log('calling callback!');\n    let result = callback(1, 2, 3, 4);\n    console.log('result from callback:', result);\n};\n\nlet go = new Go();\nWebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then((result) => {\n    go.run(result.instance);\n}).catch((err) => {\n    console.error(err);\n    process.exit(1);\n});\n"
  },
  {
    "path": "testdata/wasmfunc.txt",
    "content": "calling callback!\ninside callback! parameters:\n  parameter: 1\n  parameter: 2\n  parameter: 3\n  parameter: 4\nresult from callback: 10\n"
  },
  {
    "path": "testdata/zeroalloc.go",
    "content": "package main\n\nfunc main() {\n\tp := []byte{}\n\tfor len(p) >= 1 {\n\t\tp = p[1:]\n\t}\n}\n"
  },
  {
    "path": "testdata/zeroalloc.txt",
    "content": ""
  },
  {
    "path": "tests/os/smoke/smoke_test.go",
    "content": "package os_smoke_test\n\n// Simple smoke tests for the os package or things that depend on it.\n// Intended to catch build tag mistakes affecting bare metal targets.\n\nimport (\n\t\"crypto/rand\"\n\t\"crypto/rsa\"\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"testing\"\n)\n\n// Regression test for https://github.com/tinygo-org/tinygo/issues/2563\nfunc TestFilepath(t *testing.T) {\n\tif filepath.Base(\"foo/bar\") != \"bar\" {\n\t\tt.Errorf(\"filepath.Base is very confused\")\n\t}\n}\n\n// Regression test for https://github.com/tinygo-org/tinygo/issues/2530\nfunc TestFmt(t *testing.T) {\n\tn, err := fmt.Printf(\"Hello, world!\\n\")\n\tif err != nil {\n\t\tt.Errorf(\"printf returned error %s\", err)\n\t} else if n != 14 {\n\t\tt.Errorf(\"printf returned %d, expected 14\", n)\n\t}\n}\n\n// Regression test for https://github.com/tinygo-org/tinygo/issues/4921\nfunc TestRand(t *testing.T) {\n\tif _, err := rsa.GenerateKey(rand.Reader, 2048); err != nil {\n\t\tt.Error(err)\n\t}\n}\n"
  },
  {
    "path": "tests/runtime/memhash_test.go",
    "content": "package main\n\nimport (\n\t\"hash/maphash\"\n\t\"strconv\"\n\t\"testing\"\n)\n\nvar buf [8192]byte\n\nfunc BenchmarkMaphash(b *testing.B) {\n\tvar h maphash.Hash\n\tbenchmarkHash(b, \"maphash\", h)\n}\n\nfunc benchmarkHash(b *testing.B, str string, h maphash.Hash) {\n\tvar sizes = []int{1, 2, 3, 4, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 1024, 8192}\n\tfor _, n := range sizes {\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) { benchmarkHashn(b, int64(n), h) })\n\t}\n}\n\nvar total uint64\n\nfunc benchmarkHashn(b *testing.B, size int64, h maphash.Hash) {\n\tb.SetBytes(size)\n\n\tsum := make([]byte, 4)\n\n\tfor i := 0; i < b.N; i++ {\n\t\th.Reset()\n\t\th.Write(buf[:size])\n\t\tsum = h.Sum(sum[:0])\n\t\ttotal += uint64(sum[0])\n\t}\n}\n"
  },
  {
    "path": "tests/runtime_wasi/malloc_test.go",
    "content": "//go:build tinygo.wasm\n\npackage runtime_wasi\n\nimport (\n\t\"reflect\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"testing\"\n\t\"unsafe\"\n)\n\n//export malloc\nfunc libc_malloc(size uintptr) unsafe.Pointer\n\n//export free\nfunc libc_free(ptr unsafe.Pointer)\n\n//export calloc\nfunc libc_calloc(nmemb, size uintptr) unsafe.Pointer\n\n//export realloc\nfunc libc_realloc(ptr unsafe.Pointer, size uintptr) unsafe.Pointer\n\nfunc getFilledBuffer_malloc() uintptr {\n\tptr := libc_malloc(5)\n\tfillPanda(ptr)\n\treturn uintptr(ptr)\n}\n\nfunc getFilledBuffer_calloc() uintptr {\n\tptr := libc_calloc(2, 5)\n\tfillPanda(ptr)\n\t*(*byte)(unsafe.Add(ptr, 5)) = 'b'\n\t*(*byte)(unsafe.Add(ptr, 6)) = 'e'\n\t*(*byte)(unsafe.Add(ptr, 7)) = 'a'\n\t*(*byte)(unsafe.Add(ptr, 8)) = 'r'\n\t*(*byte)(unsafe.Add(ptr, 9)) = 's'\n\treturn uintptr(ptr)\n}\n\nfunc getFilledBuffer_realloc() uintptr {\n\torigPtr := getFilledBuffer_malloc()\n\tptr := libc_realloc(unsafe.Pointer(origPtr), 9)\n\t*(*byte)(unsafe.Add(ptr, 5)) = 'b'\n\t*(*byte)(unsafe.Add(ptr, 6)) = 'e'\n\t*(*byte)(unsafe.Add(ptr, 7)) = 'a'\n\t*(*byte)(unsafe.Add(ptr, 8)) = 'r'\n\treturn uintptr(ptr)\n}\n\nfunc getFilledBuffer_reallocNil() uintptr {\n\tptr := libc_realloc(nil, 5)\n\tfillPanda(ptr)\n\treturn uintptr(ptr)\n}\n\nfunc fillPanda(ptr unsafe.Pointer) {\n\t*(*byte)(unsafe.Add(ptr, 0)) = 'p'\n\t*(*byte)(unsafe.Add(ptr, 1)) = 'a'\n\t*(*byte)(unsafe.Add(ptr, 2)) = 'n'\n\t*(*byte)(unsafe.Add(ptr, 3)) = 'd'\n\t*(*byte)(unsafe.Add(ptr, 4)) = 'a'\n}\n\nfunc checkFilledBuffer(t *testing.T, ptr uintptr, content string) {\n\tt.Helper()\n\tbuf := *(*string)(unsafe.Pointer(&reflect.StringHeader{\n\t\tData: ptr,\n\t\tLen:  len(content),\n\t}))\n\tif buf != content {\n\t\tt.Errorf(\"expected %q, got %q\", content, buf)\n\t}\n}\n\nfunc TestMallocFree(t *testing.T) {\n\ttests := []struct {\n\t\tname      string\n\t\tgetBuffer func() uintptr\n\t\tcontent   string\n\t}{\n\t\t{\n\t\t\tname:      \"malloc\",\n\t\t\tgetBuffer: getFilledBuffer_malloc,\n\t\t\tcontent:   \"panda\",\n\t\t},\n\t\t{\n\t\t\tname:      \"calloc\",\n\t\t\tgetBuffer: getFilledBuffer_calloc,\n\t\t\tcontent:   \"pandabears\",\n\t\t},\n\t\t{\n\t\t\tname:      \"realloc\",\n\t\t\tgetBuffer: getFilledBuffer_realloc,\n\t\t\tcontent:   \"pandabear\",\n\t\t},\n\t\t{\n\t\t\tname:      \"realloc nil\",\n\t\t\tgetBuffer: getFilledBuffer_reallocNil,\n\t\t\tcontent:   \"panda\",\n\t\t},\n\t}\n\n\tfor _, tc := range tests {\n\t\ttt := tc\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tbufPtr := tt.getBuffer()\n\t\t\t// Don't use defer to free the buffer as it seems to cause the GC to track it.\n\n\t\t\t// Churn GC, the pointer should still be valid until free is called.\n\t\t\tfor i := 0; i < 1000; i++ {\n\t\t\t\ta := \"hello\" + strconv.Itoa(i)\n\t\t\t\t// Some conditional logic to ensure optimization doesn't remove the loop completely.\n\t\t\t\tif len(a) < 0 {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\truntime.GC()\n\t\t\t}\n\n\t\t\tcheckFilledBuffer(t, bufPtr, tt.content)\n\n\t\t\tlibc_free(unsafe.Pointer(bufPtr))\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "tests/testing/builderr/builderr.go",
    "content": "package builderr\n\nimport _ \"unsafe\"\n\n//go:linkname x notARealFunction\nfunc x()\n\nfunc Thing() {\n\tx()\n}\n"
  },
  {
    "path": "tests/testing/builderr/builderr_test.go",
    "content": "package builderr_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/tinygo-org/tinygo/tests/testing/builderr\"\n)\n\nfunc TestThing(t *testing.T) {\n\tbuilderr.Thing()\n}\n"
  },
  {
    "path": "tests/testing/chdir/chdir.go",
    "content": "package main\n\nimport (\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n)\n\n/*\nTest that this program is 'run' in expected directory. 'run' with expected\nworking-directory in 'EXPECT_DIR' environment variable' with{,out} a -C\nargument.\n*/\nfunc main() {\n\texpectDir := os.Getenv(\"EXPECT_DIR\")\n\tcwd, err := os.Getwd()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tif runtime.GOOS == \"windows\" {\n\t\tcwd = filepath.ToSlash(cwd)\n\t}\n\tif cwd != expectDir {\n\t\tlog.Fatalf(\"expected:\\\"%v\\\" != os.Getwd():\\\"%v\\\"\", expectDir, cwd)\n\t}\n}\n"
  },
  {
    "path": "tests/testing/fail/fail_test.go",
    "content": "package fail_test\n\nimport \"testing\"\n\nfunc TestFail(t *testing.T) {\n\tt.Error(\"fail\")\n}\n"
  },
  {
    "path": "tests/testing/nothing/nothing.go",
    "content": "package nothing\n\n// This package has no tests.\n"
  },
  {
    "path": "tests/testing/pass/pass_test.go",
    "content": "package pass_test\n\nimport \"testing\"\n\nfunc TestPass(t *testing.T) {\n\t// This test passes.\n}\n"
  },
  {
    "path": "tests/testing/recurse/subdir/subdir_test.go",
    "content": "package subdir\n\nimport \"testing\"\n\nfunc TestSubdir(t *testing.T) {\n}\n"
  },
  {
    "path": "tests/testing/recurse/top_test.go",
    "content": "package top\n\nimport \"testing\"\n\nfunc TestTop(t *testing.T) {\n}\n"
  },
  {
    "path": "tests/text/template/smoke/empty.go",
    "content": "package template_smoke\n\nfunc Function() {\n}\n"
  },
  {
    "path": "tests/text/template/smoke/smoke_test.go",
    "content": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\npackage template_smoke_test\n\nimport (\n\t\"os\"\n\t\"strings\"\n\t\"testing\"\n\t\"text/template\"\n)\n\nfunc TestExampleTemplate(tt *testing.T) {\n\t// Define a template.\n\tconst letter = `\nDear {{.Name}},\n{{if .Attended}}\nIt was a pleasure to see you at the wedding.\n{{- else}}\nIt is a shame you couldn't make it to the wedding.\n{{- end}}\n{{with .Gift -}}\nThank you for the lovely {{.}}.\n{{end}}\nBest wishes,\nJosie\n`\n\n\t// Prepare some data to insert into the template.\n\ttype Recipient struct {\n\t\tName, Gift string\n\t\tAttended   bool\n\t}\n\tvar recipients = []Recipient{\n\t\t{\"Aunt Mildred\", \"bone china tea set\", true},\n\t\t{\"Uncle John\", \"moleskin pants\", false},\n\t\t{\"Cousin Rodney\", \"\", false},\n\t}\n\n\t// Create a new template and parse the letter into it.\n\tt := template.Must(template.New(\"letter\").Parse(letter))\n\n\t// Execute the template for each recipient.\n\tfor _, r := range recipients {\n\t\terr := t.Execute(os.Stdout, r)\n\t\tif err != nil {\n\t\t\ttt.Log(\"executing template:\", err)\n\t\t}\n\t}\n\n\t// Output:\n\t// Dear Aunt Mildred,\n\t//\n\t// It was a pleasure to see you at the wedding.\n\t// Thank you for the lovely bone china tea set.\n\t//\n\t// Best wishes,\n\t// Josie\n\t//\n\t// Dear Uncle John,\n\t//\n\t// It is a shame you couldn't make it to the wedding.\n\t// Thank you for the lovely moleskin pants.\n\t//\n\t// Best wishes,\n\t// Josie\n\t//\n\t// Dear Cousin Rodney,\n\t//\n\t// It is a shame you couldn't make it to the wedding.\n\t//\n\t// Best wishes,\n\t// Josie\n}\n\n// The following example is duplicated in html/template; keep them in sync.\n\nfunc TestExampleTemplate_block(tt *testing.T) {\n\tconst (\n\t\tmaster  = `Names:{{block \"list\" .}}{{\"\\n\"}}{{range .}}{{println \"-\" .}}{{end}}{{end}}`\n\t\toverlay = `{{define \"list\"}} {{join . \", \"}}{{end}} `\n\t)\n\tvar (\n\t\tfuncs     = template.FuncMap{\"join\": strings.Join}\n\t\tguardians = []string{\"Gamora\", \"Groot\", \"Nebula\", \"Rocket\", \"Star-Lord\"}\n\t)\n\tmasterTmpl, err := template.New(\"master\").Funcs(funcs).Parse(master)\n\tif err != nil {\n\t\ttt.Fatal(err)\n\t}\n\toverlayTmpl, err := template.Must(masterTmpl.Clone()).Parse(overlay)\n\tif err != nil {\n\t\ttt.Fatal(err)\n\t}\n\tif err := masterTmpl.Execute(os.Stdout, guardians); err != nil {\n\t\ttt.Fatal(err)\n\t}\n\tif err := overlayTmpl.Execute(os.Stdout, guardians); err != nil {\n\t\ttt.Fatal(err)\n\t}\n\t// Output:\n\t// Names:\n\t// - Gamora\n\t// - Groot\n\t// - Nebula\n\t// - Rocket\n\t// - Star-Lord\n\t// Names: Gamora, Groot, Nebula, Rocket, Star-Lord\n}\n"
  },
  {
    "path": "tests/tinygotest/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc main() {\n\tThing()\n\tfmt.Println(\"normal main\")\n}\n\nfunc Thing() {\n\tfmt.Println(\"THING\")\n}\n"
  },
  {
    "path": "tests/tinygotest/main_test.go",
    "content": "package main\n\nimport (\n\t\"testing\" // This is the tinygo testing package\n)\n\nfunc TestFail1(t *testing.T) {\n\tt.Error(\"TestFail1 failed because of stuff and things\")\n}\n\nfunc TestFail2(t *testing.T) {\n\tt.Fatalf(\"TestFail2 failed for %v \", \"reasons\")\n}\n\nfunc TestFail3(t *testing.T) {\n\tt.Fail()\n\tt.Logf(\"TestFail3 failed for %v \", \"reasons\")\n}\n\nfunc TestPass(t *testing.T) {\n\tt.Log(\"TestPass passed\")\n}\n\nfunc BenchmarkNotImplemented(b *testing.B) {\n}\n"
  },
  {
    "path": "tests/wasm/chan_test.go",
    "content": "package wasm\n\nimport (\n\t\"testing\"\n\n\t\"github.com/chromedp/chromedp\"\n)\n\nfunc TestChan(t *testing.T) {\n\n\twasmTmpDir, server := startServer(t)\n\n\terr := run(t, \"tinygo build -o \"+wasmTmpDir+\"/chan.wasm -target wasm testdata/chan.go\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tctx := chromectx(t)\n\n\terr = chromedp.Run(ctx,\n\t\tchromedp.Navigate(server.URL+\"/run?file=chan.wasm\"),\n\t\twaitLog(`1\n4\n2\n3\ntrue`),\n\t)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n}\n"
  },
  {
    "path": "tests/wasm/event_test.go",
    "content": "package wasm\n\nimport (\n\t\"testing\"\n\n\t\"github.com/chromedp/chromedp\"\n)\n\nfunc TestEvent(t *testing.T) {\n\n\twasmTmpDir, server := startServer(t)\n\n\terr := run(t, \"tinygo build -o \"+wasmTmpDir+\"/event.wasm -target wasm testdata/event.go\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tctx := chromectx(t)\n\n\tvar log1, log2 string\n\terr = chromedp.Run(ctx,\n\t\tchromedp.Navigate(server.URL+\"/run?file=event.wasm\"),\n\t\tchromedp.WaitVisible(\"#log\"),\n\t\tchromedp.InnerHTML(\"#log\", &log1),\n\t\twaitLog(`1\n4`),\n\t\tchromedp.Click(\"#testbtn\"),\n\t\tchromedp.InnerHTML(\"#log\", &log2),\n\t\twaitLog(`1\n4\n2\n3\ntrue`),\n\t)\n\tt.Logf(\"log1: %s\", log1)\n\tt.Logf(\"log2: %s\", log2)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n}\n"
  },
  {
    "path": "tests/wasm/fmt_test.go",
    "content": "package wasm\n\nimport (\n\t\"testing\"\n\n\t\"github.com/chromedp/chromedp\"\n)\n\nfunc TestFmt(t *testing.T) {\n\n\twasmTmpDir, server := startServer(t)\n\n\terr := run(t, \"tinygo build -o \"+wasmTmpDir+\"/fmt.wasm -target wasm testdata/fmt.go\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tctx := chromectx(t)\n\n\tvar log1 string\n\terr = chromedp.Run(ctx,\n\t\tchromedp.Navigate(server.URL+\"/run?file=fmt.wasm\"),\n\t\tchromedp.InnerHTML(\"#log\", &log1),\n\t\twaitLog(`did not panic`),\n\t)\n\tt.Logf(\"log1: %s\", log1)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n}\n"
  },
  {
    "path": "tests/wasm/fmtprint_test.go",
    "content": "package wasm\n\nimport (\n\t\"testing\"\n\n\t\"github.com/chromedp/chromedp\"\n)\n\nfunc TestFmtprint(t *testing.T) {\n\n\twasmTmpDir, server := startServer(t)\n\n\terr := run(t, \"tinygo build -o \"+wasmTmpDir+\"/fmtprint.wasm -target wasm testdata/fmtprint.go\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tctx := chromectx(t)\n\n\tvar log1 string\n\terr = chromedp.Run(ctx,\n\t\tchromedp.Navigate(server.URL+\"/run?file=fmtprint.wasm\"),\n\t\tchromedp.InnerHTML(\"#log\", &log1),\n\t\twaitLog(`test from fmtprint 1\ntest from fmtprint 2\ntest from fmtprint 3\ntest from fmtprint 4`),\n\t)\n\tt.Logf(\"log1: %s\", log1)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n}\n"
  },
  {
    "path": "tests/wasm/go.mod",
    "content": "module github.com/tinygo-org/tinygo/tests/wasm\n\ngo 1.24\n\nrequire (\n\tgithub.com/chromedp/cdproto v0.0.0-20250803210736-d308e07a266d\n\tgithub.com/chromedp/chromedp v0.14.1\n)\n\nrequire (\n\tgithub.com/chromedp/sysutil v1.1.0 // indirect\n\tgithub.com/go-json-experiment/json v0.0.0-20250725192818-e39067aee2d2 // indirect\n\tgithub.com/gobwas/httphead v0.1.0 // indirect\n\tgithub.com/gobwas/pool v0.2.1 // indirect\n\tgithub.com/gobwas/ws v1.4.0 // indirect\n\tgolang.org/x/sys v0.34.0 // indirect\n)\n"
  },
  {
    "path": "tests/wasm/go.sum",
    "content": "github.com/chromedp/cdproto v0.0.0-20250803210736-d308e07a266d h1:ZtA1sedVbEW7EW80Iz2GR3Ye6PwbJAJXjv7D74xG6HU=\ngithub.com/chromedp/cdproto v0.0.0-20250803210736-d308e07a266d/go.mod h1:NItd7aLkcfOA/dcMXvl8p1u+lQqioRMq/SqDp71Pb/k=\ngithub.com/chromedp/chromedp v0.14.1 h1:0uAbnxewy/Q+Bg7oafVePE/6EXEho9hnaC38f+TTENg=\ngithub.com/chromedp/chromedp v0.14.1/go.mod h1:rHzAv60xDE7VNy/MYtTUrYreSc0ujt2O1/C3bzctYBo=\ngithub.com/chromedp/sysutil v1.1.0 h1:PUFNv5EcprjqXZD9nJb9b/c9ibAbxiYo4exNWZyipwM=\ngithub.com/chromedp/sysutil v1.1.0/go.mod h1:WiThHUdltqCNKGc4gaU50XgYjwjYIhKWoHGPTUfWTJ8=\ngithub.com/go-json-experiment/json v0.0.0-20250725192818-e39067aee2d2 h1:iizUGZ9pEquQS5jTGkh4AqeeHCMbfbjeb0zMt0aEFzs=\ngithub.com/go-json-experiment/json v0.0.0-20250725192818-e39067aee2d2/go.mod h1:TiCD2a1pcmjd7YnhGH0f/zKNcCD06B029pHhzV23c2M=\ngithub.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=\ngithub.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=\ngithub.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=\ngithub.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=\ngithub.com/gobwas/ws v1.4.0 h1:CTaoG1tojrh4ucGPcoJFiAQUAsEWekEWvLy7GsVNqGs=\ngithub.com/gobwas/ws v1.4.0/go.mod h1:G3gNqMNtPppf5XUz7O4shetPpcZ1VJ7zt18dlUeakrc=\ngithub.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kULo2bwGEkFvCePZ3qHDDTC3/J9Swo=\ngithub.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=\ngithub.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde h1:x0TT0RDC7UhAVbbWWBzr41ElhJx5tXPWkIHA2HWPRuw=\ngithub.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=\ngolang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=\ngolang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=\n"
  },
  {
    "path": "tests/wasm/log_test.go",
    "content": "package wasm\n\nimport (\n\t\"testing\"\n\n\t\"github.com/chromedp/chromedp\"\n)\n\nfunc TestLog(t *testing.T) {\n\n\twasmTmpDir, server := startServer(t)\n\n\terr := run(t, \"tinygo build -o \"+wasmTmpDir+\"/log.wasm -target wasm testdata/log.go\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tctx := chromectx(t)\n\n\tvar log1 string\n\terr = chromedp.Run(ctx,\n\t\tchromedp.Navigate(server.URL+\"/run?file=log.wasm\"),\n\t\tchromedp.InnerHTML(\"#log\", &log1),\n\t\twaitLogRe(`^..../../.. ..:..:.. log 1\n..../../.. ..:..:.. log 2\n..../../.. ..:..:.. log 3\nprintln 4\nfmt.Println 5\n..../../.. ..:..:.. log 6\nin func 1\n..../../.. ..:..:.. in func 2\n$`),\n\t)\n\tt.Logf(\"log1: %s\", log1)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n}\n"
  },
  {
    "path": "tests/wasm/setup_test.go",
    "content": "package wasm\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"os/exec\"\n\t\"regexp\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/chromedp/cdproto/cdp\"\n\t\"github.com/chromedp/cdproto/runtime\"\n\t\"github.com/chromedp/chromedp\"\n)\n\nfunc run(t *testing.T, cmdline string) error {\n\targs := strings.Fields(cmdline)\n\treturn runargs(t, args...)\n}\n\nfunc runargs(t *testing.T, args ...string) error {\n\tcmd := exec.Command(args[0], args[1:]...)\n\tb, err := cmd.CombinedOutput()\n\tt.Logf(\"Command: %s; err=%v; full output:\\n%s\", strings.Join(args, \" \"), err, b)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc chromectx(t *testing.T) context.Context {\n\t// see https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.md\n\topts := append(chromedp.DefaultExecAllocatorOptions[:],\n\t\tchromedp.NoSandbox,\n\t\tchromedp.Flag(\"disable-web-security\", true),\n\t\tchromedp.Flag(\"safebrowsing-disable-auto-update\", true),\n\t\tchromedp.IgnoreCertErrors,\n\t\tchromedp.Flag(\"disable-sync\", true),\n\t\tchromedp.Flag(\"disable-default-apps\", true),\n\t\tchromedp.NoFirstRun,\n\t\tchromedp.Headless,\n\t\tchromedp.WSURLReadTimeout(45*time.Second),\n\t)\n\n\tallocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)\n\tt.Cleanup(cancel)\n\n\t// looks for locally installed Chrome\n\tctx, ccancel := chromedp.NewContext(allocCtx, chromedp.WithErrorf(t.Errorf), chromedp.WithDebugf(t.Logf), chromedp.WithLogf(t.Logf))\n\tt.Cleanup(ccancel)\n\n\t// Wait for browser to be ready.\n\terr := chromedp.Run(ctx)\n\tif err != nil {\n\t\tt.Fatalf(\"failed to start browser: %s\", err.Error())\n\t}\n\n\tctx, tcancel := context.WithTimeout(ctx, 30*time.Second)\n\tt.Cleanup(tcancel)\n\n\treturn ctx\n}\n\nfunc startServer(t *testing.T) (string, *httptest.Server) {\n\ttmpDir := t.TempDir()\n\n\tfsh := http.FileServer(http.Dir(tmpDir))\n\th := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\n\t\tif r.URL.Path == \"/wasm_exec.js\" {\n\t\t\thttp.ServeFile(w, r, \"../../targets/wasm_exec.js\")\n\t\t\treturn\n\t\t}\n\n\t\tif r.URL.Path == \"/run\" {\n\t\t\tfmt.Fprintf(w, `<!doctype html>\n<html>\n<head>\n<title>Test</title>\n<meta charset=\"utf-8\"/>\n<link rel=\"icon\" href=\"data:,\">\n</head>\n<body>\n<div id=\"main\"></div>\n<pre id=\"log\"></pre>\n<script>\nwindow.wasmLogOutput  = [];\n(function() {\n\tvar logdiv = document.getElementById('log');\n\tvar cl = console.log;\n\tconsole.log = function() {\n\t\tvar a = [];\n\t\tfor (var i = 0; i < arguments.length; i++) {\n\t\t\ta.push(arguments[i]);\n\t\t}\n\t\tvar line = a.join(' ') + \"\\n\";\n\t\twindow.wasmLogOutput.push(line);\n\t\tvar ret = cl.apply(console, arguments)\n\t\tvar el = document.createElement('span');\n\t\tel.innerText = line;\n\t\tlogdiv.appendChild(el);\n\t\treturn ret\n\t}\n})()\n</script>\n<script src=\"/wasm_exec.js\"></script>\n<script>\nvar wasmSupported = (typeof WebAssembly === \"object\");\nif (wasmSupported) {\n\tvar mainWasmReq = fetch(\"/%s\").then(function(res) {\n\t\tif (res.ok) {\n\t\t\tconst go = new Go();\n\t\t\tWebAssembly.instantiateStreaming(res, go.importObject).then((result) => {\n\t\t\t\tgo.run(result.instance);\n\t\t\t});\t\t\n\t\t} else {\n\t\t\tres.text().then(function(txt) {\n\t\t\t\tvar el = document.getElementById(\"main\");\n\t\t\t\tel.style = 'font-family: monospace; background: black; color: red; padding: 10px';\n\t\t\t\tel.innerText = txt;\n\t\t\t})\n\t\t}\n\t})\n} else {\n\tdocument.getElementById(\"main\").innerHTML = 'This application requires WebAssembly support.  Please upgrade your browser.';\n}\n</script>\n</body>\n</html>`, r.FormValue(\"file\"))\n\t\t\treturn\n\t\t}\n\n\t\tfsh.ServeHTTP(w, r)\n\t})\n\n\tserver := httptest.NewServer(h)\n\tt.Logf(\"Started server at %q for dir: %s\", server.URL, tmpDir)\n\tt.Cleanup(server.Close)\n\n\treturn tmpDir, server\n}\n\n// waitLog blocks until the log output equals the text provided (ignoring whitespace before and after)\nfunc waitLog(logText string) chromedp.QueryAction {\n\treturn waitInnerTextTrimEq(\"#log\", strings.TrimSpace(logText))\n}\n\n// waitLogRe blocks until the log output matches this regular expression\nfunc waitLogRe(restr string) chromedp.QueryAction {\n\treturn waitInnerTextMatch(\"#log\", regexp.MustCompile(restr))\n}\n\n// waitInnerTextTrimEq will wait for the innerText of the specified element to match a specific text pattern (ignoring whitespace before and after)\nfunc waitInnerTextTrimEq(sel string, innerText string) chromedp.QueryAction {\n\treturn waitInnerTextMatch(sel, regexp.MustCompile(`^\\s*`+regexp.QuoteMeta(innerText)+`\\s*$`))\n}\n\n// waitInnerTextMatch will wait for the innerText of the specified element to match a specific regexp pattern\nfunc waitInnerTextMatch(sel string, re *regexp.Regexp) chromedp.QueryAction {\n\n\treturn chromedp.Query(sel, func(s *chromedp.Selector) {\n\n\t\tchromedp.WaitFunc(func(ctx context.Context, cur *cdp.Frame, execCtx runtime.ExecutionContextID, ids ...cdp.NodeID) ([]*cdp.Node, error) {\n\n\t\t\tnodes := make([]*cdp.Node, len(ids))\n\t\t\tcur.RLock()\n\t\t\tfor i, id := range ids {\n\t\t\t\tnodes[i] = cur.Nodes[id]\n\t\t\t\tif nodes[i] == nil {\n\t\t\t\t\tcur.RUnlock()\n\t\t\t\t\t// not yet ready\n\t\t\t\t\treturn nil, nil\n\t\t\t\t}\n\t\t\t}\n\t\t\tcur.RUnlock()\n\n\t\t\tvar ret string\n\t\t\terr := chromedp.EvaluateAsDevTools(\"document.querySelector('\"+sel+\"').innerText\", &ret).Do(ctx)\n\t\t\tif err != nil {\n\t\t\t\treturn nodes, err\n\t\t\t}\n\t\t\tif !re.MatchString(ret) {\n\t\t\t\t// log.Printf(\"found text: %s\", ret)\n\t\t\t\treturn nodes, errors.New(\"unexpected value: \" + ret)\n\t\t\t}\n\n\t\t\t// log.Printf(\"NodeValue: %#v\", nodes[0])\n\n\t\t\t// return nil, errors.New(\"not ready yet\")\n\t\t\treturn nodes, nil\n\t\t})(s)\n\n\t})\n\n}\n"
  },
  {
    "path": "tests/wasm/testdata/chan.go",
    "content": "package main\n\nfunc main() {\n\n\tch := make(chan bool, 1)\n\tprintln(\"1\")\n\tgo func() {\n\t\tprintln(\"2\")\n\t\tch <- true\n\t\tprintln(\"3\")\n\t}()\n\tprintln(\"4\")\n\tv := <-ch\n\tprintln(v)\n\n}\n"
  },
  {
    "path": "tests/wasm/testdata/event.go",
    "content": "package main\n\nimport \"syscall/js\"\n\nfunc main() {\n\n\tch := make(chan bool, 1)\n\n\tprintln(\"1\")\n\n\tjs.Global().\n\t\tGet(\"document\").\n\t\tCall(\"querySelector\", \"#main\").\n\t\tSet(\"innerHTML\", `<button id=\"testbtn\">Test</button>`)\n\n\tjs.Global().\n\t\tGet(\"document\").\n\t\tCall(\"querySelector\", \"#testbtn\").\n\t\tCall(\"addEventListener\", \"click\",\n\t\t\tjs.FuncOf(func(this js.Value, args []js.Value) interface{} {\n\t\t\t\tprintln(\"2\")\n\t\t\t\tch <- true\n\t\t\t\tprintln(\"3\")\n\t\t\t\treturn nil\n\t\t\t}))\n\n\tprintln(\"4\")\n\tv := <-ch\n\tprintln(v)\n\n}\n"
  },
  {
    "path": "tests/wasm/testdata/fmt.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tvar _ fmt.Stringer\n\tprintln(\"did not panic\")\n}\n"
  },
  {
    "path": "tests/wasm/testdata/fmtprint.go",
    "content": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"test from fmtprint 1\")\n\tfmt.Print(\"test from fmtprint 2\\n\")\n\tfmt.Print(\"test from fmtp\")\n\tfmt.Print(\"rint 3\\n\")\n\tfmt.Printf(\"test from fmtprint %d\\n\", 4)\n}\n"
  },
  {
    "path": "tests/wasm/testdata/log.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"syscall/js\"\n)\n\nfunc main() {\n\n\t// try various log and other output directly\n\tlog.Println(\"log 1\")\n\tlog.Print(\"log 2\")\n\tlog.Printf(\"log %d\\n\", 3)\n\tprintln(\"println 4\")\n\tfmt.Println(\"fmt.Println 5\")\n\tlog.Printf(\"log %s\", \"6\")\n\n\t// now set up some log output in a button click callback\n\tjs.Global().\n\t\tGet(\"document\").\n\t\tCall(\"querySelector\", \"#main\").\n\t\tSet(\"innerHTML\", `<button id=\"testbtn\">Test</button>`)\n\n\tjs.Global().\n\t\tGet(\"document\").\n\t\tCall(\"querySelector\", \"#testbtn\").\n\t\tCall(\"addEventListener\", \"click\",\n\t\t\tjs.FuncOf(func(this js.Value, args []js.Value) interface{} {\n\t\t\t\tprintln(\"in func 1\")\n\t\t\t\tlog.Printf(\"in func 2\")\n\t\t\t\treturn nil\n\t\t\t}))\n\n\t// click the button\n\tjs.Global().\n\t\tGet(\"document\").\n\t\tCall(\"querySelector\", \"#testbtn\").\n\t\tCall(\"click\")\n\n}\n"
  },
  {
    "path": "tools/gen-critical-atomics/gen-critical-atomics.go",
    "content": "package main\n\nimport (\n\t\"bytes\"\n\t\"flag\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strings\"\n\t\"text/template\"\n)\n\nvar tmpl = template.Must(template.New(\"go\").Funcs(template.FuncMap{\n\t\"mul\": func(x, y int) int {\n\t\treturn x * y\n\t},\n\t\"tuple\": func(v ...interface{}) []interface{} {\n\t\treturn v\n\t},\n\t\"title\": strings.Title,\n}).Parse(`//go:build baremetal && !tinygo.wasm\n\n// Automatically generated file. DO NOT EDIT.\n// This file implements standins for non-native atomics using critical sections.\n\npackage runtime\n\nimport (\n\t_ \"unsafe\"\n)\n\n// Documentation:\n// * https://llvm.org/docs/Atomics.html\n// * https://gcc.gnu.org/onlinedocs/gcc/_005f_005fsync-Builtins.html\n//\n// Some atomic operations are emitted inline while others are emitted as libcalls.\n// How many are emitted as libcalls depends on the MCU arch and core variant.\n\n{{- define \"load\"}}{{$bits := mul . 8 -}}\n//export __atomic_load_{{.}}\nfunc __atomic_load_{{.}}(ptr *uint{{$bits}}, ordering uintptr) uint{{$bits}} {\n\t// The LLVM docs for this say that there is a val argument after the pointer.\n\t// That is a typo, and the GCC docs omit it.\n\tmask := lockAtomics()\n\tval := *ptr\n\tunlockAtomics(mask)\n\treturn val\n}\n{{end}}\n{{- define \"store\"}}{{$bits := mul . 8 -}}\n//export __atomic_store_{{.}}\nfunc __atomic_store_{{.}}(ptr *uint{{$bits}}, val uint{{$bits}}, ordering uintptr) {\n\tmask := lockAtomics()\n\t*ptr = val\n\tunlockAtomics(mask)\n}\n{{end}}\n{{- define \"cas\"}}{{$bits := mul . 8 -}}\n//go:inline\nfunc doAtomicCAS{{$bits}}(ptr *uint{{$bits}}, expected, desired uint{{$bits}}) uint{{$bits}} {\n\tmask := lockAtomics()\n\told := *ptr\n\tif old == expected {\n\t\t*ptr = desired\n\t}\n\tunlockAtomics(mask)\n\treturn old\n}\n\n//export __sync_val_compare_and_swap_{{.}}\nfunc __sync_val_compare_and_swap_{{.}}(ptr *uint{{$bits}}, expected, desired uint{{$bits}}) uint{{$bits}} {\n\treturn doAtomicCAS{{$bits}}(ptr, expected, desired)\n}\n\n//export __atomic_compare_exchange_{{.}}\nfunc __atomic_compare_exchange_{{.}}(ptr, expected *uint{{$bits}}, desired uint{{$bits}}, successOrder, failureOrder uintptr) bool {\n\texp := *expected\n\told := doAtomicCAS{{$bits}}(ptr, exp, desired)\n\treturn old == exp\n}\n{{end}}\n{{- define \"swap\"}}{{$bits := mul . 8 -}}\n//go:inline\nfunc doAtomicSwap{{$bits}}(ptr *uint{{$bits}}, new uint{{$bits}}) uint{{$bits}} {\n\tmask := lockAtomics()\n\told := *ptr\n\t*ptr = new\n\tunlockAtomics(mask)\n\treturn old\n}\n\n//export __sync_lock_test_and_set_{{.}}\nfunc __sync_lock_test_and_set_{{.}}(ptr *uint{{$bits}}, new uint{{$bits}}) uint{{$bits}} {\n\treturn doAtomicSwap{{$bits}}(ptr, new)\n}\n\n//export __atomic_exchange_{{.}}\nfunc __atomic_exchange_{{.}}(ptr *uint{{$bits}}, new uint{{$bits}}, ordering uintptr) uint{{$bits}} {\n\treturn doAtomicSwap{{$bits}}(ptr, new)\n}\n{{end}}\n{{- define \"rmw\"}}\n\t{{- $opname := index . 0}}\n\t{{- $bytes := index . 1}}{{$bits := mul $bytes 8}}\n\t{{- $signed := index . 2}}\n\t{{- $opdef := index . 3}}\n\n{{- $type := printf \"int%d\" $bits}}\n{{- if not $signed}}{{$type = printf \"u%s\" $type}}{{end -}}\n{{- $opfn := printf \"doAtomic%s%d\" (title $opname) $bits}}\n\n//go:inline\nfunc {{$opfn}}(ptr *{{$type}}, value {{$type}}) (old, new {{$type}}) {\n\tmask := lockAtomics()\n\told = *ptr\n\t{{$opdef}}\n\t*ptr = new\n\tunlockAtomics(mask)\n\treturn old, new\n}\n\n//export __atomic_fetch_{{$opname}}_{{$bytes}}\nfunc __atomic_fetch_{{$opname}}_{{$bytes}}(ptr *{{$type}}, value {{$type}}, ordering uintptr) {{$type}} {\n\told, _ := {{$opfn}}(ptr, value)\n\treturn old\n}\n\n//export __sync_fetch_and_{{$opname}}_{{$bytes}}\nfunc __sync_fetch_and_{{$opname}}_{{$bytes}}(ptr *{{$type}}, value {{$type}}) {{$type}} {\n\told, _ := {{$opfn}}(ptr, value)\n\treturn old\n}\n\n//export __atomic_{{$opname}}_fetch_{{$bytes}}\nfunc __atomic_{{$opname}}_fetch_{{$bytes}}(ptr *{{$type}}, value {{$type}}, ordering uintptr) {{$type}} {\n\t_, new := {{$opfn}}(ptr, value)\n\treturn new\n}\n{{end}}\n{{- define \"atomics\"}}\n// {{mul . 8}}-bit atomics.\n\n{{/* These atomics are accessible directly from sync/atomic. */ -}}\n{{template \"load\" .}}\n{{template \"store\" .}}\n{{template \"cas\" .}}\n{{template \"swap\" .}}\n{{template \"rmw\" (tuple \"add\" . false \"new = old + value\")}}\n\n{{- end}}\n{{template \"atomics\" 2 -}}\n{{template \"atomics\" 4 -}}\n{{template \"atomics\" 8}}\n`))\n\nfunc main() {\n\tvar out string\n\tflag.StringVar(&out, \"out\", \"-\", \"output path\")\n\tflag.Parse()\n\tf := os.Stdout\n\tif out != \"-\" {\n\t\tvar err error\n\t\tf, err = os.Create(out)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\tdefer f.Close()\n\t}\n\tvar buf bytes.Buffer\n\terr := tmpl.Execute(&buf, nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tcmd := exec.Command(\"gofmt\")\n\tcmd.Stdin = &buf\n\tcmd.Stdout = f\n\tcmd.Stderr = os.Stderr\n\terr = cmd.Run()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n}\n"
  },
  {
    "path": "tools/gen-device-avr/gen-device-avr.go",
    "content": "package main\n\nimport (\n\t\"bufio\"\n\t\"encoding/xml\"\n\t\"fmt\"\n\t\"html/template\"\n\t\"math/bits\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n)\n\ntype AVRToolsDeviceFile struct {\n\tXMLName xml.Name `xml:\"avr-tools-device-file\"`\n\tDevices []struct {\n\t\tName          string `xml:\"name,attr\"`\n\t\tArchitecture  string `xml:\"architecture,attr\"`\n\t\tFamily        string `xml:\"family,attr\"`\n\t\tAddressSpaces []struct {\n\t\t\tName           string `xml:\"name,attr\"`\n\t\t\tSize           string `xml:\"size,attr\"`\n\t\t\tMemorySegments []struct {\n\t\t\t\tName  string `xml:\"name,attr\"`\n\t\t\t\tStart string `xml:\"start,attr\"`\n\t\t\t\tSize  string `xml:\"size,attr\"`\n\t\t\t} `xml:\"memory-segment\"`\n\t\t} `xml:\"address-spaces>address-space\"`\n\t\tPeripheralInstances []struct {\n\t\t\tName          string `xml:\"name,attr\"`\n\t\t\tCaption       string `xml:\"caption,attr\"`\n\t\t\tRegisterGroup struct {\n\t\t\t\tNameInModule string `xml:\"name-in-module,attr\"`\n\t\t\t\tOffset       string `xml:\"offset,attr\"`\n\t\t\t} `xml:\"register-group\"`\n\t\t} `xml:\"peripherals>module>instance\"`\n\t\tInterrupts []*XMLInterrupt `xml:\"interrupts>interrupt\"`\n\t} `xml:\"devices>device\"`\n\tPeripheralRegisterGroups []struct {\n\t\tName      string `xml:\"name,attr\"`\n\t\tCaption   string `xml:\"caption,attr\"`\n\t\tRegisters []struct {\n\t\t\tName      string `xml:\"name,attr\"`\n\t\t\tCaption   string `xml:\"caption,attr\"`\n\t\t\tOffset    string `xml:\"offset,attr\"`\n\t\t\tSize      uint64 `xml:\"size,attr\"`\n\t\t\tBitfields []struct {\n\t\t\t\tName    string `xml:\"name,attr\"`\n\t\t\t\tCaption string `xml:\"caption,attr\"`\n\t\t\t\tMask    string `xml:\"mask,attr\"`\n\t\t\t} `xml:\"bitfield\"`\n\t\t} `xml:\"register\"`\n\t} `xml:\"modules>module>register-group\"`\n}\n\ntype XMLInterrupt struct {\n\tIndex    int    `xml:\"index,attr\"`\n\tName     string `xml:\"name,attr\"`\n\tInstance string `xml:\"module-instance,attr\"`\n\tCaption  string `xml:\"caption,attr\"`\n}\n\ntype Device struct {\n\tmetadata   map[string]interface{}\n\tinterrupts []Interrupt\n\ttypes      []*PeripheralType\n\tinstances  []*PeripheralInstance\n\toldStyle   bool\n}\n\n// AddressSpace is the Go version of an XML element like the following:\n//\n//\t<address-space endianness=\"little\" name=\"data\" id=\"data\" start=\"0x0000\" size=\"0x0900\">\n//\n// It describes one address space in an AVR microcontroller. One address space\n// may have multiple memory segments.\ntype AddressSpace struct {\n\tSize     string\n\tSegments map[string]MemorySegment\n}\n\n// MemorySegment is the Go version of an XML element like the following:\n//\n//\t<memory-segment name=\"IRAM\" start=\"0x0100\" size=\"0x0800\" type=\"ram\" external=\"false\"/>\n//\n// It describes a single contiguous area of memory in a particular address space\n// (see AddressSpace).\ntype MemorySegment struct {\n\tstart int64\n\tsize  int64\n}\n\ntype Interrupt struct {\n\tIndex   int\n\tName    string\n\tCaption string\n}\n\n// Peripheral instance, for example PORTB\ntype PeripheralInstance struct {\n\tName    string\n\tCaption string\n\tAddress uint64\n\tType    *PeripheralType\n}\n\n// Peripheral type, for example PORT (if it's shared between different\n// instances, which is the case for new-style ATDF files).\ntype PeripheralType struct {\n\tName      string\n\tCaption   string\n\tRegisters []*Register\n\tInstances []*PeripheralInstance\n}\n\n// Single register or struct field in a peripheral type.\ntype Register struct {\n\tCaption   string\n\tName      string\n\tType      string\n\tOffset    uint64 // offset, only for old-style ATDF files\n\tBitfields []Bitfield\n}\n\ntype Bitfield struct {\n\tName    string\n\tCaption string\n\tMask    uint\n}\n\nfunc readATDF(path string) (*Device, error) {\n\t// Read Atmel device descriptor files.\n\t// See: http://packs.download.atmel.com\n\n\t// Open the XML file.\n\tf, err := os.Open(path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer f.Close()\n\tdecoder := xml.NewDecoder(f)\n\txml := &AVRToolsDeviceFile{}\n\terr = decoder.Decode(xml)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tdevice := xml.Devices[0]\n\n\tmemorySizes := make(map[string]*AddressSpace, len(device.AddressSpaces))\n\tfor _, el := range device.AddressSpaces {\n\t\tmemorySizes[el.Name] = &AddressSpace{\n\t\t\tSize:     el.Size,\n\t\t\tSegments: make(map[string]MemorySegment),\n\t\t}\n\t\tfor _, segmentEl := range el.MemorySegments {\n\t\t\tstart, err := strconv.ParseInt(segmentEl.Start, 0, 32)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tsize, err := strconv.ParseInt(segmentEl.Size, 0, 32)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tmemorySizes[el.Name].Segments[segmentEl.Name] = MemorySegment{\n\t\t\t\tstart: start,\n\t\t\t\tsize:  size,\n\t\t\t}\n\t\t}\n\t}\n\n\t// There appear to be two kinds of devices and ATDF files: those before\n\t// ~2017 and those introduced as part of the tinyAVR (1 and 2 series).\n\t// The newer devices are structured slightly differently, with peripherals\n\t// laid out more like Cortex-M chips and one or more instances per chip.\n\t// Older designs basically just have a bunch of registers with little\n\t// structure in them.\n\t// The code generated for these chips is quite different:\n\t//   * For old-style chips we'll generate a bunch of registers without\n\t//     peripherals (e.g. PORTB, DDRB, etc).\n\t//   * For new-style chips we'll generate proper peripheral structs like we\n\t//     do for Cortex-M chips.\n\toldStyle := true\n\tfor _, instanceEl := range device.PeripheralInstances {\n\t\tif instanceEl.RegisterGroup.NameInModule == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\toffset, err := strconv.ParseUint(instanceEl.RegisterGroup.Offset, 0, 16)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to parse offset %#v of peripheral %s: %v\", instanceEl.RegisterGroup.Offset, instanceEl.Name, err)\n\t\t}\n\t\tif offset != 0 {\n\t\t\toldStyle = false\n\t\t}\n\t}\n\n\t// Read all peripheral types.\n\tvar types []*PeripheralType\n\ttypeMap := make(map[string]*PeripheralType)\n\tallRegisters := map[string]*Register{}\n\tfor _, registerGroupEl := range xml.PeripheralRegisterGroups {\n\t\tvar regs []*Register\n\t\tregEls := registerGroupEl.Registers\n\t\tif !oldStyle {\n\t\t\t// We only need to sort registers when we're generating peripheral\n\t\t\t// structs.\n\t\t\tsort.SliceStable(regEls, func(i, j int) bool {\n\t\t\t\treturn regEls[i].Offset < regEls[j].Offset\n\t\t\t})\n\t\t}\n\t\taddReg := func(reg *Register) {\n\t\t\tif oldStyle {\n\t\t\t\t// Check for duplicate registers (they happen).\n\t\t\t\tif reg2 := allRegisters[reg.Name]; reg2 != nil {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tallRegisters[reg.Name] = reg\n\t\t\t}\n\t\t\tregs = append(regs, reg)\n\t\t}\n\t\toffset := uint64(0)\n\t\tfor _, regEl := range regEls {\n\t\t\tregOffset, err := strconv.ParseUint(regEl.Offset, 0, 64)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to parse offset %#v of register %s: %v\", regEl.Offset, regEl.Name, err)\n\t\t\t}\n\t\t\tif !oldStyle {\n\t\t\t\t// Add some padding to the gap in the struct, if needed.\n\t\t\t\tif offset < regOffset {\n\t\t\t\t\tregs = append(regs, &Register{\n\t\t\t\t\t\tName: \"_\",\n\t\t\t\t\t\tType: fmt.Sprintf(\"[%d]volatile.Register8\", regOffset-offset),\n\t\t\t\t\t})\n\t\t\t\t\toffset = regOffset\n\t\t\t\t}\n\n\t\t\t\t// Check for overlapping registers.\n\t\t\t\tif offset > regOffset {\n\t\t\t\t\treturn nil, fmt.Errorf(\"register %s in peripheral %s overlaps with another register\", regEl.Name, registerGroupEl.Name)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar bitfields []Bitfield\n\t\t\tfor _, bitfieldEl := range regEl.Bitfields {\n\t\t\t\tmaskString := bitfieldEl.Mask\n\t\t\t\tif len(maskString) == 2 {\n\t\t\t\t\t// Two devices (ATtiny102 and ATtiny104) appear to have an\n\t\t\t\t\t// error in the bitfields, leaving out the '0x' prefix.\n\t\t\t\t\tmaskString = \"0x\" + maskString\n\t\t\t\t}\n\t\t\t\tmask, err := strconv.ParseUint(maskString, 0, 32)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, fmt.Errorf(\"failed to parse mask %#v of bitfield %s: %v\", maskString, bitfieldEl.Name, err)\n\t\t\t\t}\n\t\t\t\tname := regEl.Name + \"_\" + bitfieldEl.Name\n\t\t\t\tif !oldStyle {\n\t\t\t\t\tname = registerGroupEl.Name + \"_\" + name\n\t\t\t\t}\n\t\t\t\tbitfields = append(bitfields, Bitfield{\n\t\t\t\t\tName:    name,\n\t\t\t\t\tCaption: bitfieldEl.Caption,\n\t\t\t\t\tMask:    uint(mask),\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tswitch regEl.Size {\n\t\t\tcase 1:\n\t\t\t\taddReg(&Register{\n\t\t\t\t\tName:      regEl.Name,\n\t\t\t\t\tType:      \"volatile.Register8\",\n\t\t\t\t\tCaption:   regEl.Caption,\n\t\t\t\t\tOffset:    regOffset,\n\t\t\t\t\tBitfields: bitfields,\n\t\t\t\t})\n\t\t\tcase 2:\n\t\t\t\taddReg(&Register{\n\t\t\t\t\tName:    regEl.Name + \"L\",\n\t\t\t\t\tType:    \"volatile.Register8\",\n\t\t\t\t\tCaption: regEl.Caption + \" (lower bits)\",\n\t\t\t\t\tOffset:  regOffset + 0,\n\t\t\t\t})\n\t\t\t\taddReg(&Register{\n\t\t\t\t\tName:    regEl.Name + \"H\",\n\t\t\t\t\tType:    \"volatile.Register8\",\n\t\t\t\t\tCaption: regEl.Caption + \" (upper bits)\",\n\t\t\t\t\tOffset:  regOffset + 1,\n\t\t\t\t})\n\t\t\tdefault:\n\t\t\t\tpanic(\"todo: unknown size\")\n\t\t\t}\n\t\t\toffset += regEl.Size\n\t\t}\n\t\tperiphType := &PeripheralType{\n\t\t\tName:      registerGroupEl.Name,\n\t\t\tCaption:   registerGroupEl.Caption,\n\t\t\tRegisters: regs,\n\t\t}\n\t\ttypes = append(types, periphType)\n\t\ttypeMap[periphType.Name] = periphType\n\t}\n\n\t// Read all peripheral instances.\n\tvar instances []*PeripheralInstance\n\tfor _, instanceEl := range device.PeripheralInstances {\n\t\tif instanceEl.RegisterGroup.NameInModule == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\toffset, err := strconv.ParseUint(instanceEl.RegisterGroup.Offset, 0, 16)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to parse offset %#v of peripheral %s: %v\", instanceEl.RegisterGroup.Offset, instanceEl.Name, err)\n\t\t}\n\t\tperiphType := typeMap[instanceEl.RegisterGroup.NameInModule]\n\t\tinstance := &PeripheralInstance{\n\t\t\tName:    instanceEl.Name,\n\t\t\tCaption: instanceEl.Caption,\n\t\t\tAddress: offset,\n\t\t\tType:    periphType,\n\t\t}\n\t\tinstances = append(instances, instance)\n\t\tperiphType.Instances = append(periphType.Instances, instance)\n\t}\n\n\tramStart := int64(0)\n\tramSize := int64(0) // for devices with no RAM\n\tfor _, ramSegmentName := range []string{\"IRAM\", \"INTERNAL_SRAM\", \"SRAM\"} {\n\t\tif segment, ok := memorySizes[\"data\"].Segments[ramSegmentName]; ok {\n\t\t\tramStart = segment.start\n\t\t\tramSize = segment.size\n\t\t}\n\t}\n\n\t// Flash that is mapped into the data address space (attiny10, attiny1616,\n\t// etc).\n\tmappedFlashStart := int64(0)\n\tfor _, name := range []string{\"MAPPED_PROGMEM\", \"MAPPED_FLASH\"} {\n\t\tif segment, ok := memorySizes[\"data\"].Segments[name]; ok {\n\t\t\tmappedFlashStart = segment.start\n\t\t}\n\t}\n\n\tflashSize, err := strconv.ParseInt(memorySizes[\"prog\"].Size, 0, 32)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Process the interrupts to clean up inconsistencies between ATDF files.\n\tvar interrupts []Interrupt\n\thasResetInterrupt := false\n\tfor _, intr := range device.Interrupts {\n\t\tname := intr.Name\n\t\tif intr.Instance != \"\" {\n\t\t\t// ATDF files for newer chips also have an instance name, which must\n\t\t\t// be specified to make the interrupt name unique.\n\t\t\tname = intr.Instance + \"_\" + name\n\t\t}\n\t\tif name == \"RESET\" {\n\t\t\thasResetInterrupt = true\n\t\t}\n\t\tinterrupts = append(interrupts, Interrupt{\n\t\t\tIndex:   intr.Index,\n\t\t\tName:    name,\n\t\t\tCaption: intr.Caption,\n\t\t})\n\t}\n\tif !hasResetInterrupt {\n\t\tinterrupts = append(interrupts, Interrupt{\n\t\t\tIndex: 0,\n\t\t\tName:  \"RESET\",\n\t\t})\n\t}\n\tsort.SliceStable(interrupts, func(i, j int) bool {\n\t\treturn interrupts[i].Index < interrupts[j].Index\n\t})\n\n\treturn &Device{\n\t\tmetadata: map[string]interface{}{\n\t\t\t\"file\":             filepath.Base(path),\n\t\t\t\"descriptorSource\": \"http://packs.download.atmel.com/\",\n\t\t\t\"name\":             device.Name,\n\t\t\t\"nameLower\":        strings.ToLower(device.Name),\n\t\t\t\"description\":      fmt.Sprintf(\"Device information for the %s.\", device.Name),\n\t\t\t\"arch\":             device.Architecture,\n\t\t\t\"family\":           device.Family,\n\t\t\t\"flashSize\":        int(flashSize),\n\t\t\t\"ramStart\":         ramStart,\n\t\t\t\"ramSize\":          ramSize,\n\t\t\t\"mappedFlashStart\": mappedFlashStart,\n\t\t\t\"numInterrupts\":    len(device.Interrupts),\n\t\t},\n\t\tinterrupts: interrupts,\n\t\ttypes:      types,\n\t\tinstances:  instances,\n\t\toldStyle:   oldStyle,\n\t}, nil\n}\n\nfunc writeGo(outdir string, device *Device) error {\n\t// The Go module for this device.\n\toutf, err := os.Create(outdir + \"/\" + device.metadata[\"nameLower\"].(string) + \".go\")\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer outf.Close()\n\tw := bufio.NewWriter(outf)\n\n\tmaxInterruptNum := 0\n\tfor _, intr := range device.interrupts {\n\t\tif intr.Index > maxInterruptNum {\n\t\t\tmaxInterruptNum = intr.Index\n\t\t}\n\t}\n\n\tt := template.Must(template.New(\"go\").Parse(`// Automatically generated file. DO NOT EDIT.\n// Generated by gen-device-avr.go from {{.metadata.file}}, see {{.metadata.descriptorSource}}\n\n//go:build {{.pkgName}} && {{.metadata.nameLower}}\n\n// {{.metadata.description}}\npackage {{.pkgName}}\n\nimport (\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\n// Some information about this device.\nconst (\n\tDEVICE = \"{{.metadata.name}}\"\n\tARCH   = \"{{.metadata.arch}}\"\n\tFAMILY = \"{{.metadata.family}}\"\n)\n\n// Interrupts\nconst ({{range .interrupts}}\n\tIRQ_{{.Name}} = {{.Index}} // {{.Caption}}{{end}}\n\tIRQ_max = {{.interruptMax}} // Highest interrupt number on this device.\n)\n\n// Pseudo function call that is replaced by the compiler with the actual\n// functions registered through interrupt.New.\n//go:linkname callHandlers runtime/interrupt.callHandlers\nfunc callHandlers(num int)\n\n{{- range .interrupts}}\n//export __vector_{{.Name}}\n//go:interrupt\nfunc interrupt{{.Name}}() {\n\tcallHandlers(IRQ_{{.Name}})\n}\n{{- end}}\n\n{{if .oldStyle -}}\n// Peripherals.\nvar (\n{{- range .instances}}\n\t// {{.Caption}}\n\t{{range .Type.Registers -}}\n\t{{if ne .Name \"_\" -}}\n\t{{.Name}} = (*{{.Type}})(unsafe.Pointer(uintptr(0x{{printf \"%x\" .Offset}})))\n\t{{end -}}\n\t{{end -}}\n{{end}})\n{{else}}\n// Peripherals instances.\nvar (\n{{- range .instances -}}\n\t{{.Name}} = (*{{.Type.Name}}_Type)(unsafe.Pointer(uintptr(0x{{printf \"%x\" .Address}})))\n\t{{- if .Caption}}// {{.Caption}}{{end}}\n{{end -}}\n)\n\n// Peripheral type definitions.\n\n{{range .types}}\ntype {{.Name}}_Type struct {\n{{range .Registers -}}\n\t{{.Name}} {{.Type}} {{if .Caption}} // {{.Caption}} {{end}}\n{{end -}}\n}\n{{end}}\n{{end}}\n`))\n\terr = t.Execute(w, map[string]interface{}{\n\t\t\"metadata\":     device.metadata,\n\t\t\"pkgName\":      filepath.Base(strings.TrimRight(outdir, \"/\")),\n\t\t\"interrupts\":   device.interrupts,\n\t\t\"interruptMax\": maxInterruptNum,\n\t\t\"instances\":    device.instances,\n\t\t\"types\":        device.types,\n\t\t\"oldStyle\":     device.oldStyle,\n\t})\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Write bitfields.\n\tfor _, peripheral := range device.types {\n\t\t// Only write bitfields when there are any.\n\t\tnumFields := 0\n\t\tfor _, r := range peripheral.Registers {\n\t\t\tnumFields += len(r.Bitfields)\n\t\t}\n\t\tif numFields == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\tfmt.Fprintf(w, \"\\n// Bitfields for %s: %s\\nconst(\", peripheral.Name, peripheral.Caption)\n\t\tfor _, register := range peripheral.Registers {\n\t\t\tif len(register.Bitfields) == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfmt.Fprintf(w, \"\\n\\t// %s\", register.Name)\n\t\t\tif register.Caption != \"\" {\n\t\t\t\tfmt.Fprintf(w, \": %s\", register.Caption)\n\t\t\t}\n\t\t\tfmt.Fprintf(w, \"\\n\")\n\t\t\tallBits := map[string]interface{}{}\n\t\t\tfor _, bitfield := range register.Bitfields {\n\t\t\t\tif bits.OnesCount(bitfield.Mask) == 1 {\n\t\t\t\t\tfmt.Fprintf(w, \"\\t%s = 0x%x\", bitfield.Name, bitfield.Mask)\n\t\t\t\t\tif len(bitfield.Caption) != 0 {\n\t\t\t\t\t\tfmt.Fprintf(w, \" // %s\", bitfield.Caption)\n\t\t\t\t\t}\n\t\t\t\t\tfmt.Fprintf(w, \"\\n\")\n\t\t\t\t\tfmt.Fprintf(w, \"\\t%s_Msk = 0x%x\", bitfield.Name, bitfield.Mask)\n\t\t\t\t\tif len(bitfield.Caption) != 0 {\n\t\t\t\t\t\tfmt.Fprintf(w, \" // %s\", bitfield.Caption)\n\t\t\t\t\t}\n\t\t\t\t\tfmt.Fprintf(w, \"\\n\")\n\t\t\t\t\tallBits[bitfield.Name] = nil\n\t\t\t\t} else {\n\t\t\t\t\tn := 0\n\t\t\t\t\tfor i := uint(0); i < 8; i++ {\n\t\t\t\t\t\tif (bitfield.Mask>>i)&1 == 0 {\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t\tname := fmt.Sprintf(\"%s%d\", bitfield.Name, n)\n\t\t\t\t\t\tif _, ok := allBits[name]; !ok {\n\t\t\t\t\t\t\tfmt.Fprintf(w, \"\\t%s = 0x%x\", name, 1<<i)\n\t\t\t\t\t\t\tif len(bitfield.Caption) != 0 {\n\t\t\t\t\t\t\t\tfmt.Fprintf(w, \" // %s\", bitfield.Caption)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfmt.Fprintf(w, \"\\n\")\n\t\t\t\t\t\t\tallBits[name] = nil\n\t\t\t\t\t\t}\n\t\t\t\t\t\tn++\n\t\t\t\t\t}\n\t\t\t\t\tfmt.Fprintf(w, \"\\t%s_Msk = 0x%x\", bitfield.Name, bitfield.Mask)\n\t\t\t\t\tif len(bitfield.Caption) != 0 {\n\t\t\t\t\t\tfmt.Fprintf(w, \" // %s\", bitfield.Caption)\n\t\t\t\t\t}\n\t\t\t\t\tfmt.Fprintf(w, \"\\n\")\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfmt.Fprintf(w, \")\\n\")\n\t}\n\treturn w.Flush()\n}\n\nfunc writeAsm(outdir string, device *Device) error {\n\t// The interrupt vector, which is hard to write directly in Go.\n\tout, err := os.Create(outdir + \"/\" + device.metadata[\"nameLower\"].(string) + \".s\")\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer out.Close()\n\tt := template.Must(template.New(\"asm\").Parse(\n\t\t`; Automatically generated file. DO NOT EDIT.\n; Generated by gen-device-avr.go from {{.file}}, see {{.descriptorSource}}\n\n; This is the default handler for interrupts, if triggered but not defined.\n; Sleep inside so that an accidentally triggered interrupt won't drain the\n; battery of a battery-powered device.\n.section .text.__vector_default\n.global  __vector_default\n__vector_default:\n    sleep\n    rjmp __vector_default\n\n; Avoid the need for repeated .weak and .set instructions.\n.macro IRQ handler\n    .weak  \\handler\n    .set   \\handler, __vector_default\n.endm\n\n; The interrupt vector of this device. Must be placed at address 0 by the linker.\n.section .vectors, \"a\", %progbits\n.global  __vectors\n`))\n\terr = t.Execute(out, device.metadata)\n\tif err != nil {\n\t\treturn err\n\t}\n\tnum := 0\n\tfor _, intr := range device.interrupts {\n\t\tjmp := \"jmp\"\n\t\tif device.metadata[\"flashSize\"].(int) <= 8*1024 {\n\t\t\t// When a device has 8kB or less flash, rjmp (2 bytes) must be used\n\t\t\t// instead of jmp (4 bytes).\n\t\t\t// https://www.avrfreaks.net/forum/rjmp-versus-jmp\n\t\t\tjmp = \"rjmp\"\n\t\t}\n\t\tif intr.Index < num {\n\t\t\t// Some devices have duplicate interrupts, probably for historical\n\t\t\t// reasons.\n\t\t\tcontinue\n\t\t}\n\t\tfor intr.Index > num {\n\t\t\tfmt.Fprintf(out, \"    %s __vector_default\\n\", jmp)\n\t\t\tnum++\n\t\t}\n\t\tnum++\n\t\tfmt.Fprintf(out, \"    %s __vector_%s\\n\", jmp, intr.Name)\n\t}\n\n\tfmt.Fprint(out, `\n    ; Define default implementations for interrupts, redirecting to\n    ; __vector_default when not implemented.\n`)\n\tfor _, intr := range device.interrupts {\n\t\tfmt.Fprintf(out, \"    IRQ __vector_%s\\n\", intr.Name)\n\t}\n\treturn nil\n}\n\nfunc writeLD(outdir string, device *Device) error {\n\t// Variables for the linker script.\n\tout, err := os.Create(outdir + \"/\" + device.metadata[\"nameLower\"].(string) + \".ld\")\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer out.Close()\n\tt := template.Must(template.New(\"ld\").Parse(`/* Automatically generated file. DO NOT EDIT. */\n/* Generated by gen-device-avr.go from {{.file}}, see {{.descriptorSource}} */\n\n__flash_size = 0x{{printf \"%x\" .flashSize}};\n{{if .mappedFlashStart -}}\n__mapped_flash_start = 0x{{printf \"%x\" .mappedFlashStart}};\n{{end -}}\n__ram_start = 0x{{printf \"%x\" .ramStart}};\n__ram_size   = 0x{{printf \"%x\" .ramSize}};\n__num_isrs   = {{.numInterrupts}};\n`))\n\treturn t.Execute(out, device.metadata)\n}\n\nfunc processFile(filepath, outdir string) error {\n\tdevice, err := readATDF(filepath)\n\tif err != nil {\n\t\treturn err\n\t}\n\terr = writeGo(outdir, device)\n\tif err != nil {\n\t\treturn err\n\t}\n\terr = writeAsm(outdir, device)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn writeLD(outdir, device)\n}\n\nfunc generate(indir, outdir string) error {\n\t// Read list of ATDF files to process.\n\tmatches, err := filepath.Glob(indir + \"/*.atdf\")\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Start worker goroutines.\n\tvar wg sync.WaitGroup\n\tworkChan := make(chan string)\n\terrChan := make(chan error, 1)\n\tfor i := 0; i < runtime.NumCPU(); i++ {\n\t\tgo func() {\n\t\t\tfor filepath := range workChan {\n\t\t\t\terr := processFile(filepath, outdir)\n\t\t\t\twg.Done()\n\t\t\t\tif err != nil {\n\t\t\t\t\t// Store error to errChan if no error was stored before.\n\t\t\t\t\tselect {\n\t\t\t\t\tcase errChan <- err:\n\t\t\t\t\tdefault:\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}()\n\t}\n\n\t// Submit all jobs to the goroutines.\n\twg.Add(len(matches))\n\tfor _, filepath := range matches {\n\t\tfmt.Println(filepath)\n\t\tworkChan <- filepath\n\t}\n\tclose(workChan)\n\n\t// Wait until all workers have finished.\n\twg.Wait()\n\n\t// Check for an error.\n\tselect {\n\tcase err := <-errChan:\n\t\treturn err\n\tdefault:\n\t\treturn nil\n\t}\n}\n\nfunc main() {\n\tindir := os.Args[1]  // directory with register descriptor files (*.atdf)\n\toutdir := os.Args[2] // output directory\n\terr := generate(indir, outdir)\n\tif err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\tos.Exit(1)\n\t}\n}\n"
  },
  {
    "path": "tools/gen-device-svd/gen-device-svd.go",
    "content": "package main\n\nimport (\n\t\"bufio\"\n\t\"encoding/xml\"\n\t\"errors\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io/fs\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\t\"text/template\"\n\t\"unicode\"\n)\n\nvar validName = regexp.MustCompile(\"^[a-zA-Z0-9_]+$\")\nvar enumBitSpecifier = regexp.MustCompile(\"^#x*[01]+[01x]*$\")\n\ntype SVDFile struct {\n\tXMLName     xml.Name `xml:\"device\"`\n\tName        string   `xml:\"name\"`\n\tDescription string   `xml:\"description\"`\n\tLicenseText string   `xml:\"licenseText\"`\n\tCPU         *struct {\n\t\tName         string `xml:\"name\"`\n\t\tFPUPresent   bool   `xml:\"fpuPresent\"`\n\t\tNVICPrioBits int    `xml:\"nvicPrioBits\"`\n\t} `xml:\"cpu\"`\n\tPeripherals []SVDPeripheral `xml:\"peripherals>peripheral\"`\n}\n\ntype SVDPeripheral struct {\n\tName        string `xml:\"name\"`\n\tDescription string `xml:\"description\"`\n\tBaseAddress string `xml:\"baseAddress\"`\n\tGroupName   string `xml:\"groupName\"`\n\tDerivedFrom string `xml:\"derivedFrom,attr\"`\n\tInterrupts  []struct {\n\t\tName  string `xml:\"name\"`\n\t\tIndex int    `xml:\"value\"`\n\t} `xml:\"interrupt\"`\n\tRegisters []*SVDRegister `xml:\"registers>register\"`\n\tClusters  []*SVDCluster  `xml:\"registers>cluster\"`\n}\n\ntype SVDRegister struct {\n\tName          string      `xml:\"name\"`\n\tDescription   string      `xml:\"description\"`\n\tDim           *string     `xml:\"dim\"`\n\tDimIndex      *string     `xml:\"dimIndex\"`\n\tDimIncrement  string      `xml:\"dimIncrement\"`\n\tSize          *string     `xml:\"size\"`\n\tFields        []*SVDField `xml:\"fields>field\"`\n\tOffset        *string     `xml:\"offset\"`\n\tAddressOffset *string     `xml:\"addressOffset\"`\n}\n\ntype SVDField struct {\n\tName             string  `xml:\"name\"`\n\tDescription      string  `xml:\"description\"`\n\tLsb              *uint32 `xml:\"lsb\"`\n\tMsb              *uint32 `xml:\"msb\"`\n\tBitOffset        *uint32 `xml:\"bitOffset\"`\n\tBitWidth         *uint32 `xml:\"bitWidth\"`\n\tBitRange         *string `xml:\"bitRange\"`\n\tEnumeratedValues struct {\n\t\tDerivedFrom     string `xml:\"derivedFrom,attr\"`\n\t\tName            string `xml:\"name\"`\n\t\tEnumeratedValue []struct {\n\t\t\tName        string `xml:\"name\"`\n\t\t\tDescription string `xml:\"description\"`\n\t\t\tValue       string `xml:\"value\"`\n\t\t} `xml:\"enumeratedValue\"`\n\t} `xml:\"enumeratedValues\"`\n}\n\ntype SVDCluster struct {\n\tDim           *int           `xml:\"dim\"`\n\tDimIncrement  string         `xml:\"dimIncrement\"`\n\tDimIndex      *string        `xml:\"dimIndex\"`\n\tName          string         `xml:\"name\"`\n\tDescription   string         `xml:\"description\"`\n\tRegisters     []*SVDRegister `xml:\"register\"`\n\tClusters      []*SVDCluster  `xml:\"cluster\"`\n\tAddressOffset string         `xml:\"addressOffset\"`\n}\n\ntype Device struct {\n\tMetadata       *Metadata\n\tInterrupts     []*Interrupt\n\tPeripherals    []*Peripheral\n\tPeripheralDict map[string]*Peripheral\n}\n\ntype Metadata struct {\n\tFile             string\n\tDescriptorSource string\n\tName             string\n\tNameLower        string\n\tDescription      string\n\tLicenseBlock     string\n\n\tHasCPUInfo   bool // set if the following fields are populated\n\tCPUName      string\n\tFPUPresent   bool\n\tNVICPrioBits int\n}\n\ntype Interrupt struct {\n\tName            string\n\tHandlerName     string\n\tPeripheralIndex int\n\tValue           int // interrupt number\n\tDescription     string\n}\n\ntype Peripheral struct {\n\tName        string\n\tGroupName   string\n\tBaseAddress uint64\n\tDescription string\n\tClusterName string\n\tRegisters   []*PeripheralField\n\tSubtypes    []*Peripheral\n}\n\n// A PeripheralField is a single field in a peripheral type. It may be a full\n// peripheral or a cluster within a peripheral.\ntype PeripheralField struct {\n\tName         string\n\tAddress      uint64\n\tDescription  string\n\tRegisters    []*PeripheralField // contains fields if this is a cluster\n\tArray        int\n\tElementSize  int\n\tConstants    []Constant\n\tShortName    string     // name stripped of \"spaced array\" suffix\n\tBitfields    []Bitfield // set of bit-fields provided by this\n\tHasBitfields bool       // set true when Bitfields was set for a first PeripheralField of \"spaced array\".\n}\n\ntype Constant struct {\n\tName        string\n\tDescription string\n\tValue       uint64\n}\n\ntype Bitfield struct {\n\tName   string\n\tOffset uint32\n\tMask   uint32\n}\n\nfunc formatText(text string) string {\n\ttext = regexp.MustCompile(`[ \\t\\n]+`).ReplaceAllString(text, \" \") // Collapse whitespace (like in HTML)\n\ttext = strings.ReplaceAll(text, \"\\\\n \", \"\\n\")\n\ttext = strings.TrimSpace(text)\n\treturn text\n}\n\nfunc isMultiline(s string) bool {\n\treturn strings.Index(s, \"\\n\") >= 0\n}\n\nfunc splitLine(s string) []string {\n\treturn strings.Split(s, \"\\n\")\n}\n\n// Replace characters that are not allowed in a symbol name with a '_'. This is\n// useful to be able to process SVD files with errors.\nfunc cleanName(text string) string {\n\tif !validName.MatchString(text) {\n\t\tresult := make([]rune, 0, len(text))\n\t\tfor _, c := range text {\n\t\t\tif validName.MatchString(string(c)) {\n\t\t\t\tresult = append(result, c)\n\t\t\t} else {\n\t\t\t\tresult = append(result, '_')\n\t\t\t}\n\t\t}\n\t\ttext = string(result)\n\t}\n\tif len(text) != 0 && (text[0] >= '0' && text[0] <= '9') {\n\t\t// Identifiers may not start with a number.\n\t\t// Add an underscore instead.\n\t\ttext = \"_\" + text\n\t}\n\treturn text\n}\n\nfunc processSubCluster(p *Peripheral, cluster *SVDCluster, clusterOffset uint64, clusterName string, peripheralDict map[string]*Peripheral) []*Peripheral {\n\tvar peripheralsList []*Peripheral\n\tclusterPrefix := clusterName + \"_\"\n\tcpRegisters := []*PeripheralField{}\n\n\tfor _, regEl := range cluster.Registers {\n\t\tcpRegisters = append(cpRegisters, parseRegister(p.GroupName, regEl, p.BaseAddress+clusterOffset, clusterPrefix)...)\n\t}\n\t// handle sub-clusters of registers\n\tfor _, subClusterEl := range cluster.Clusters {\n\t\tsubclusterName := strings.ReplaceAll(subClusterEl.Name, \"[%s]\", \"\")\n\t\tsubclusterPrefix := subclusterName + \"_\"\n\t\tsubclusterOffset, err := strconv.ParseUint(subClusterEl.AddressOffset, 0, 32)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\tsubdim := *subClusterEl.Dim\n\t\tsubdimIncrement, err := strconv.ParseInt(subClusterEl.DimIncrement, 0, 32)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\n\t\tif subdim > 1 {\n\t\t\tsubcpRegisters := []*PeripheralField{}\n\t\t\tfor _, regEl := range subClusterEl.Registers {\n\t\t\t\tsubcpRegisters = append(subcpRegisters, parseRegister(p.GroupName, regEl, p.BaseAddress+clusterOffset+subclusterOffset, subclusterPrefix)...)\n\t\t\t}\n\n\t\t\tcpRegisters = append(cpRegisters, &PeripheralField{\n\t\t\t\tName:        subclusterName,\n\t\t\t\tAddress:     p.BaseAddress + clusterOffset + subclusterOffset,\n\t\t\t\tDescription: subClusterEl.Description,\n\t\t\t\tRegisters:   subcpRegisters,\n\t\t\t\tArray:       subdim,\n\t\t\t\tElementSize: int(subdimIncrement),\n\t\t\t\tShortName:   clusterPrefix + subclusterName,\n\t\t\t})\n\t\t} else {\n\t\t\tfor _, regEl := range subClusterEl.Registers {\n\t\t\t\tcpRegisters = append(cpRegisters, parseRegister(regEl.Name, regEl, p.BaseAddress+clusterOffset+subclusterOffset, subclusterPrefix)...)\n\t\t\t}\n\t\t}\n\t}\n\n\tsort.SliceStable(cpRegisters, func(i, j int) bool {\n\t\treturn cpRegisters[i].Address < cpRegisters[j].Address\n\t})\n\tclusterPeripheral := &Peripheral{\n\t\tName:        p.Name + \"_\" + clusterName,\n\t\tGroupName:   p.GroupName + \"_\" + clusterName,\n\t\tDescription: p.Description + \" - \" + clusterName,\n\t\tClusterName: clusterName,\n\t\tBaseAddress: p.BaseAddress + clusterOffset,\n\t\tRegisters:   cpRegisters,\n\t}\n\tperipheralsList = append(peripheralsList, clusterPeripheral)\n\tperipheralDict[clusterPeripheral.Name] = clusterPeripheral\n\tp.Subtypes = append(p.Subtypes, clusterPeripheral)\n\n\treturn peripheralsList\n}\n\nfunc processCluster(p *Peripheral, clusters []*SVDCluster, peripheralDict map[string]*Peripheral) []*Peripheral {\n\tvar peripheralsList []*Peripheral\n\tfor _, cluster := range clusters {\n\t\tclusterName := strings.ReplaceAll(cluster.Name, \"[%s]\", \"\")\n\t\tif cluster.DimIndex != nil {\n\t\t\tclusterName = strings.ReplaceAll(clusterName, \"%s\", \"\")\n\t\t}\n\t\tclusterPrefix := clusterName + \"_\"\n\t\tclusterOffset, err := strconv.ParseUint(cluster.AddressOffset, 0, 32)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\tvar dim, dimIncrement int\n\t\tif cluster.Dim == nil {\n\t\t\t// Nordic SVD have sub-clusters with another sub-clusters.\n\t\t\tif clusterOffset == 0 || len(cluster.Clusters) > 0 {\n\t\t\t\tperipheralsList = append(peripheralsList, processSubCluster(p, cluster, clusterOffset, clusterName, peripheralDict)...)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tdim = -1\n\t\t\tdimIncrement = -1\n\t\t} else {\n\t\t\tdim = *cluster.Dim\n\t\t\tif dim == 1 {\n\t\t\t\tdimIncrement = -1\n\t\t\t} else {\n\t\t\t\tinc, err := strconv.ParseUint(cluster.DimIncrement, 0, 32)\n\t\t\t\tif err != nil {\n\t\t\t\t\tpanic(err)\n\t\t\t\t}\n\t\t\t\tdimIncrement = int(inc)\n\t\t\t}\n\t\t}\n\t\tclusterRegisters := []*PeripheralField{}\n\t\tfor _, regEl := range cluster.Registers {\n\t\t\tregName := p.GroupName\n\t\t\tif regName == \"\" {\n\t\t\t\tregName = p.Name\n\t\t\t}\n\t\t\tclusterRegisters = append(clusterRegisters, parseRegister(regName, regEl, p.BaseAddress+clusterOffset, clusterPrefix)...)\n\t\t}\n\t\tsort.SliceStable(clusterRegisters, func(i, j int) bool {\n\t\t\treturn clusterRegisters[i].Address < clusterRegisters[j].Address\n\t\t})\n\t\tif dimIncrement == -1 && len(clusterRegisters) > 0 {\n\t\t\tlastReg := clusterRegisters[len(clusterRegisters)-1]\n\t\t\tlastAddress := lastReg.Address\n\t\t\tif lastReg.Array != -1 {\n\t\t\t\tlastAddress = lastReg.Address + uint64(lastReg.Array*lastReg.ElementSize)\n\t\t\t}\n\t\t\tfirstAddress := clusterRegisters[0].Address\n\t\t\tdimIncrement = int(lastAddress - firstAddress)\n\t\t}\n\n\t\tif !unicode.IsUpper(rune(clusterName[0])) && !unicode.IsDigit(rune(clusterName[0])) {\n\t\t\tclusterName = strings.ToUpper(clusterName)\n\t\t}\n\n\t\tp.Registers = append(p.Registers, &PeripheralField{\n\t\t\tName:        clusterName,\n\t\t\tAddress:     p.BaseAddress + clusterOffset,\n\t\t\tDescription: cluster.Description,\n\t\t\tRegisters:   clusterRegisters,\n\t\t\tArray:       dim,\n\t\t\tElementSize: dimIncrement,\n\t\t\tShortName:   clusterName,\n\t\t})\n\t}\n\tsort.SliceStable(p.Registers, func(i, j int) bool {\n\t\treturn p.Registers[i].Address < p.Registers[j].Address\n\t})\n\treturn peripheralsList\n}\n\n// Read ARM SVD files.\nfunc readSVD(path, sourceURL string) (*Device, error) {\n\t// Open the XML file.\n\tf, err := os.Open(path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer f.Close()\n\tdecoder := xml.NewDecoder(f)\n\tdevice := &SVDFile{}\n\terr = decoder.Decode(device)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tperipheralDict := map[string]*Peripheral{}\n\tgroups := map[string]*Peripheral{}\n\n\tinterrupts := make(map[string]*Interrupt)\n\tvar peripheralsList []*Peripheral\n\n\t// Some SVD files have peripheral elements derived from a peripheral that\n\t// comes later in the file. To make sure this works, sort the peripherals if\n\t// needed.\n\torderedPeripherals := orderPeripherals(device.Peripherals)\n\n\tfor _, periphEl := range orderedPeripherals {\n\t\tdescription := formatText(periphEl.Description)\n\t\tbaseAddress, err := strconv.ParseUint(periphEl.BaseAddress, 0, 64)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid base address: %w\", err)\n\t\t}\n\t\t// Some group names (for example the STM32H7A3x) have an invalid\n\t\t// group name. Replace invalid characters with \"_\".\n\t\tgroupName := cleanName(periphEl.GroupName)\n\t\tif groupName == \"\" {\n\t\t\tgroupName = cleanName(periphEl.Name)\n\t\t}\n\n\t\tfor _, interrupt := range periphEl.Interrupts {\n\t\t\taddInterrupt(interrupts, interrupt.Name, interrupt.Name, interrupt.Index, description)\n\t\t\t// As a convenience, also use the peripheral name as the interrupt\n\t\t\t// name. Only do that for the nrf for now, as the stm32 .svd files\n\t\t\t// don't always put interrupts in the correct peripheral...\n\t\t\tif len(periphEl.Interrupts) == 1 && strings.HasPrefix(device.Name, \"nrf\") {\n\t\t\t\taddInterrupt(interrupts, periphEl.Name, interrupt.Name, interrupt.Index, description)\n\t\t\t}\n\t\t}\n\n\t\tif _, ok := groups[groupName]; ok || periphEl.DerivedFrom != \"\" {\n\t\t\tvar derivedFrom *Peripheral\n\t\t\tif periphEl.DerivedFrom != \"\" {\n\t\t\t\tderivedFrom = peripheralDict[periphEl.DerivedFrom]\n\t\t\t} else {\n\t\t\t\tderivedFrom = groups[groupName]\n\t\t\t}\n\t\t\tp := &Peripheral{\n\t\t\t\tName:        periphEl.Name,\n\t\t\t\tGroupName:   derivedFrom.GroupName,\n\t\t\t\tDescription: description,\n\t\t\t\tBaseAddress: baseAddress,\n\t\t\t}\n\t\t\tif p.Description == \"\" {\n\t\t\t\tp.Description = derivedFrom.Description\n\t\t\t}\n\t\t\tperipheralsList = append(peripheralsList, p)\n\t\t\tperipheralDict[p.Name] = p\n\t\t\tfor _, subtype := range derivedFrom.Subtypes {\n\t\t\t\tperipheralsList = append(peripheralsList, &Peripheral{\n\t\t\t\t\tName:        periphEl.Name + \"_\" + subtype.ClusterName,\n\t\t\t\t\tGroupName:   subtype.GroupName,\n\t\t\t\t\tDescription: subtype.Description,\n\t\t\t\t\tBaseAddress: baseAddress,\n\t\t\t\t})\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\tp := &Peripheral{\n\t\t\tName:        periphEl.Name,\n\t\t\tGroupName:   groupName,\n\t\t\tDescription: description,\n\t\t\tBaseAddress: baseAddress,\n\t\t\tRegisters:   []*PeripheralField{},\n\t\t}\n\t\tif p.GroupName == \"\" {\n\t\t\tp.GroupName = periphEl.Name\n\t\t}\n\t\tperipheralsList = append(peripheralsList, p)\n\t\tperipheralDict[periphEl.Name] = p\n\n\t\tif _, ok := groups[groupName]; !ok && groupName != \"\" {\n\t\t\tgroups[groupName] = p\n\t\t}\n\n\t\tfor _, register := range periphEl.Registers {\n\t\t\tregName := groupName // preferably use the group name\n\t\t\tif regName == \"\" {\n\t\t\t\tregName = periphEl.Name // fall back to peripheral name\n\t\t\t}\n\t\t\tp.Registers = append(p.Registers, parseRegister(regName, register, baseAddress, \"\")...)\n\t\t}\n\t\tperipheralsList = append(peripheralsList, processCluster(p, periphEl.Clusters, peripheralDict)...)\n\t}\n\n\t// Make a sorted list of interrupts.\n\tinterruptList := make([]*Interrupt, 0, len(interrupts))\n\tfor _, intr := range interrupts {\n\t\tinterruptList = append(interruptList, intr)\n\t}\n\tsort.SliceStable(interruptList, func(i, j int) bool {\n\t\tif interruptList[i].Value != interruptList[j].Value {\n\t\t\treturn interruptList[i].Value < interruptList[j].Value\n\t\t}\n\t\treturn interruptList[i].PeripheralIndex < interruptList[j].PeripheralIndex\n\t})\n\n\t// Properly format the description, with comments.\n\tdescription := \"\"\n\tif text := device.Description; text != \"\" {\n\t\tdescription = \"// \" + strings.ReplaceAll(text, \"\\n\", \"\\n// \")\n\t\tdescription = regexp.MustCompile(`\\s+\\n`).ReplaceAllString(description, \"\\n\")\n\t}\n\n\t// Properly format the license block, with comments.\n\tlicenseBlock := \"\"\n\tif text := formatText(device.LicenseText); text != \"\" {\n\t\tlicenseBlock = \"//     \" + strings.ReplaceAll(text, \"\\n\", \"\\n//     \")\n\t\tlicenseBlock = regexp.MustCompile(`\\s+\\n`).ReplaceAllString(licenseBlock, \"\\n\")\n\t}\n\n\t// Remove \"-\" characters from the device name because such characters cannot\n\t// be used in build tags. Necessary for the ESP32-C3 for example.\n\tnameLower := strings.ReplaceAll(strings.ToLower(device.Name), \"-\", \"\")\n\tmetadata := &Metadata{\n\t\tFile:             filepath.Base(path),\n\t\tDescriptorSource: sourceURL,\n\t\tName:             device.Name,\n\t\tNameLower:        nameLower,\n\t\tDescription:      description,\n\t\tLicenseBlock:     licenseBlock,\n\t}\n\tif device.CPU != nil {\n\t\tmetadata.HasCPUInfo = true\n\t\tmetadata.CPUName = device.CPU.Name\n\t\tmetadata.FPUPresent = device.CPU.FPUPresent\n\t\tmetadata.NVICPrioBits = device.CPU.NVICPrioBits\n\t}\n\treturn &Device{\n\t\tMetadata:       metadata,\n\t\tInterrupts:     interruptList,\n\t\tPeripherals:    peripheralsList,\n\t\tPeripheralDict: peripheralDict,\n\t}, nil\n}\n\n// orderPeripherals sorts the peripherals so that derived peripherals come after\n// base peripherals. This is necessary for some SVD files.\nfunc orderPeripherals(input []SVDPeripheral) []*SVDPeripheral {\n\tvar sortedPeripherals []*SVDPeripheral\n\tvar missingBasePeripherals []*SVDPeripheral\n\tknownBasePeripherals := map[string]struct{}{}\n\tfor i := range input {\n\t\tp := &input[i]\n\t\tgroupName := p.GroupName\n\t\tif groupName == \"\" {\n\t\t\tgroupName = p.Name\n\t\t}\n\t\tknownBasePeripherals[groupName] = struct{}{}\n\t\tif p.DerivedFrom != \"\" {\n\t\t\tif _, ok := knownBasePeripherals[p.DerivedFrom]; !ok {\n\t\t\t\tmissingBasePeripherals = append(missingBasePeripherals, p)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tsortedPeripherals = append(sortedPeripherals, p)\n\t}\n\n\t// Let's hope all base peripherals are now included.\n\tsortedPeripherals = append(sortedPeripherals, missingBasePeripherals...)\n\n\treturn sortedPeripherals\n}\n\nfunc addInterrupt(interrupts map[string]*Interrupt, name, interruptName string, index int, description string) {\n\tif _, ok := interrupts[name]; ok {\n\t\tif interrupts[name].Value != index {\n\t\t\t// Note: some SVD files like the one for STM32H7x7 contain mistakes.\n\t\t\t// Instead of throwing an error, simply log it.\n\t\t\tfmt.Fprintf(os.Stderr, \"interrupt with the same name has different indexes: %s (%d vs %d)\\n\",\n\t\t\t\tname, interrupts[name].Value, index)\n\t\t}\n\t\tparts := strings.Split(interrupts[name].Description, \" // \")\n\t\thasDescription := false\n\t\tfor _, part := range parts {\n\t\t\tif part == description {\n\t\t\t\thasDescription = true\n\t\t\t}\n\t\t}\n\t\tif !hasDescription {\n\t\t\tinterrupts[name].Description += \" // \" + description\n\t\t}\n\t} else {\n\t\tinterrupts[name] = &Interrupt{\n\t\t\tName:            name,\n\t\t\tHandlerName:     interruptName + \"_IRQHandler\",\n\t\t\tPeripheralIndex: len(interrupts),\n\t\t\tValue:           index,\n\t\t\tDescription:     description,\n\t\t}\n\t}\n}\n\nfunc parseBitfields(groupName, regName string, fieldEls []*SVDField, bitfieldPrefix string) ([]Constant, []Bitfield) {\n\tvar fields []Constant\n\tvar bitfields []Bitfield\n\tenumSeen := map[string]int64{}\n\tfor _, fieldEl := range fieldEls {\n\t\t// Some bitfields (like the STM32H7x7) contain invalid bitfield\n\t\t// names like \"CNT[31]\". Replace invalid characters with \"_\" when\n\t\t// needed.\n\t\tfieldName := cleanName(fieldEl.Name)\n\t\tif !unicode.IsUpper(rune(fieldName[0])) && !unicode.IsDigit(rune(fieldName[0])) {\n\t\t\tfieldName = strings.ToUpper(fieldName)\n\t\t}\n\n\t\t// Find the lsb/msb that is encoded in various ways.\n\t\t// Standards are great, that's why there are so many to choose from!\n\t\tvar lsb, msb uint32\n\t\tif fieldEl.Lsb != nil && fieldEl.Msb != nil {\n\t\t\t// try to use lsb/msb tags\n\t\t\tlsb = *fieldEl.Lsb\n\t\t\tmsb = *fieldEl.Msb\n\t\t} else if fieldEl.BitOffset != nil && fieldEl.BitWidth != nil {\n\t\t\t// try to use bitOffset/bitWidth tags\n\t\t\tlsb = *fieldEl.BitOffset\n\t\t\tmsb = *fieldEl.BitWidth + lsb - 1\n\t\t} else if fieldEl.BitRange != nil {\n\t\t\t// try use bitRange\n\t\t\t// example string: \"[20:16]\"\n\t\t\tparts := strings.Split(strings.Trim(*fieldEl.BitRange, \"[]\"), \":\")\n\t\t\tl, err := strconv.ParseUint(parts[1], 0, 32)\n\t\t\tif err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\t\t\tlsb = uint32(l)\n\t\t\tm, err := strconv.ParseUint(parts[0], 0, 32)\n\t\t\tif err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\t\t\tmsb = uint32(m)\n\t\t} else {\n\t\t\t// this is an error. what to do?\n\t\t\tfmt.Fprintln(os.Stderr, \"unable to find lsb/msb in field:\", fieldName)\n\t\t\tcontinue\n\t\t}\n\n\t\t// The enumerated values can be the same as another field, so to avoid\n\t\t// duplication SVD files can simply refer to another set of enumerated\n\t\t// values in the same register.\n\t\t// See: https://www.keil.com/pack/doc/CMSIS/SVD/html/elem_registers.html#elem_enumeratedValues\n\t\tenumeratedValues := fieldEl.EnumeratedValues\n\t\tif enumeratedValues.DerivedFrom != \"\" {\n\t\t\tparts := strings.Split(enumeratedValues.DerivedFrom, \".\")\n\t\t\tif len(parts) == 1 {\n\t\t\t\tfound := false\n\t\t\t\tfor _, otherFieldEl := range fieldEls {\n\t\t\t\t\tif otherFieldEl.EnumeratedValues.Name == parts[0] {\n\t\t\t\t\t\tfound = true\n\t\t\t\t\t\tenumeratedValues = otherFieldEl.EnumeratedValues\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif !found {\n\t\t\t\t\tfmt.Fprintf(os.Stderr, \"Warning: could not find enumeratedValue.derivedFrom of %s for register field %s\\n\", enumeratedValues.DerivedFrom, fieldName)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// The derivedFrom attribute may also point to enumerated values\n\t\t\t\t// in other registers and even peripherals, but this feature\n\t\t\t\t// isn't often used in SVD files.\n\t\t\t\tfmt.Fprintf(os.Stderr, \"TODO: enumeratedValue.derivedFrom to a different register: %s\\n\", enumeratedValues.DerivedFrom)\n\t\t\t}\n\t\t}\n\n\t\tbitfields = append(bitfields, Bitfield{\n\t\t\tName:   fieldName,\n\t\t\tOffset: lsb,\n\t\t\tMask:   (0xffffffff >> (31 - (msb - lsb))) << lsb,\n\t\t})\n\t\tfields = append(fields, Constant{\n\t\t\tName:        fmt.Sprintf(\"%s_%s%s_%s_Pos\", groupName, bitfieldPrefix, regName, fieldName),\n\t\t\tDescription: fmt.Sprintf(\"Position of %s field.\", fieldName),\n\t\t\tValue:       uint64(lsb),\n\t\t})\n\t\tfields = append(fields, Constant{\n\t\t\tName:        fmt.Sprintf(\"%s_%s%s_%s_Msk\", groupName, bitfieldPrefix, regName, fieldName),\n\t\t\tDescription: fmt.Sprintf(\"Bit mask of %s field.\", fieldName),\n\t\t\tValue:       (0xffffffffffffffff >> (63 - (msb - lsb))) << lsb,\n\t\t})\n\t\tif lsb == msb { // single bit\n\t\t\tfields = append(fields, Constant{\n\t\t\t\tName:        fmt.Sprintf(\"%s_%s%s_%s\", groupName, bitfieldPrefix, regName, fieldName),\n\t\t\t\tDescription: fmt.Sprintf(\"Bit %s.\", fieldName),\n\t\t\t\tValue:       1 << lsb,\n\t\t\t})\n\t\t}\n\t\tfor _, enumEl := range enumeratedValues.EnumeratedValue {\n\t\t\tenumName := enumEl.Name\n\t\t\t// Renesas has enum without actual values that we have to skip\n\t\t\tif enumEl.Value == \"\" {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif strings.EqualFold(enumName, \"reserved\") || !validName.MatchString(enumName) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif !unicode.IsUpper(rune(enumName[0])) && !unicode.IsDigit(rune(enumName[0])) {\n\t\t\t\tenumName = strings.ToUpper(enumName)\n\t\t\t}\n\t\t\tenumDescription := formatText(enumEl.Description)\n\t\t\tvar enumValue uint64\n\t\t\tvar err error\n\t\t\tif strings.HasPrefix(enumEl.Value, \"0b\") {\n\t\t\t\tval := strings.TrimPrefix(enumEl.Value, \"0b\")\n\t\t\t\tenumValue, err = strconv.ParseUint(val, 2, 64)\n\t\t\t} else {\n\t\t\t\tenumValue, err = strconv.ParseUint(enumEl.Value, 0, 64)\n\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\tif enumBitSpecifier.MatchString(enumEl.Value) {\n\t\t\t\t\t// NXP and Renesas SVDs use the form #xx1x, #x0xx, etc for values\n\t\t\t\t\tenumValue, err = strconv.ParseUint(strings.ReplaceAll(enumEl.Value[1:], \"x\", \"0\"), 2, 64)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tpanic(err)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tpanic(err)\n\t\t\t\t}\n\t\t\t}\n\t\t\tenumName = fmt.Sprintf(\"%s_%s%s_%s_%s\", groupName, bitfieldPrefix, regName, fieldName, enumName)\n\n\t\t\t// Avoid duplicate values. Duplicate names with the same value are\n\t\t\t// allowed, but the same name with a different value is not. Instead\n\t\t\t// of trying to work around those cases, remove the value entirely\n\t\t\t// as there is probably not one correct answer in such a case.\n\t\t\t// For example, SVD files from NXP have enums limited to 20\n\t\t\t// characters, leading to lots of duplicates when these enum names\n\t\t\t// are long. Nothing here can really fix those cases.\n\t\t\tpreviousEnumValue, seenBefore := enumSeen[enumName]\n\t\t\tif seenBefore {\n\t\t\t\tif previousEnumValue < 0 {\n\t\t\t\t\t// There was a mismatch before, ignore all equally named fields.\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif int64(enumValue) != previousEnumValue {\n\t\t\t\t\t// There is a mismatch. Mark it as such, and remove the\n\t\t\t\t\t// existing enum bitfield value.\n\t\t\t\t\tenumSeen[enumName] = -1\n\t\t\t\t\tfor i, field := range fields {\n\t\t\t\t\t\tif field.Name == enumName {\n\t\t\t\t\t\t\tfields = append(fields[:i], fields[i+1:]...)\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tenumSeen[enumName] = int64(enumValue)\n\n\t\t\tfields = append(fields, Constant{\n\t\t\t\tName:        enumName,\n\t\t\t\tDescription: enumDescription,\n\t\t\t\tValue:       enumValue,\n\t\t\t})\n\t\t}\n\t}\n\treturn fields, bitfields\n}\n\ntype Register struct {\n\telement     *SVDRegister\n\tbaseAddress uint64\n}\n\nfunc NewRegister(element *SVDRegister, baseAddress uint64) *Register {\n\treturn &Register{\n\t\telement:     element,\n\t\tbaseAddress: baseAddress,\n\t}\n}\n\nfunc (r *Register) name() string {\n\treturn strings.ReplaceAll(r.element.Name, \"[%s]\", \"\")\n}\n\nfunc (r *Register) description() string {\n\treturn formatText(r.element.Description)\n}\n\nfunc (r *Register) address() uint64 {\n\toffsetString := r.element.Offset\n\tif offsetString == nil {\n\t\toffsetString = r.element.AddressOffset\n\t}\n\taddr, err := strconv.ParseUint(*offsetString, 0, 32)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn r.baseAddress + addr\n}\n\nfunc (r *Register) dim() int {\n\tif r.element.Dim == nil {\n\t\treturn -1 // no dim elements\n\t}\n\tdim, err := strconv.ParseInt(*r.element.Dim, 0, 32)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn int(dim)\n}\n\nfunc (r *Register) dimIndex() []string {\n\tdefer func() {\n\t\tif err := recover(); err != nil {\n\t\t\tfmt.Println(\"register\", r.name())\n\t\t\tpanic(err)\n\t\t}\n\t}()\n\n\tdim := r.dim()\n\tif r.element.DimIndex == nil {\n\t\tif dim <= 0 {\n\t\t\treturn nil\n\t\t}\n\n\t\tidx := make([]string, dim)\n\t\tfor i := range idx {\n\t\t\tidx[i] = strconv.FormatInt(int64(i), 10)\n\t\t}\n\t\treturn idx\n\t}\n\n\tt := strings.Split(*r.element.DimIndex, \"-\")\n\tif len(t) == 2 {\n\t\t// renesas uses hex letters e.g. A-B\n\t\tif strings.Contains(\"ABCDEFabcdef\", t[0]) {\n\t\t\tt[0] = \"0x\" + t[0]\n\t\t}\n\t\tif strings.Contains(\"ABCDEFabcdef\", t[1]) {\n\t\t\tt[1] = \"0x\" + t[1]\n\t\t}\n\n\t\tx, err := strconv.ParseInt(t[0], 0, 32)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\ty, err := strconv.ParseInt(t[1], 0, 32)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\n\t\tif x < 0 || y < x || y-x != int64(dim-1) {\n\t\t\tpanic(\"invalid dimIndex\")\n\t\t}\n\n\t\tidx := make([]string, dim)\n\t\tfor i := x; i <= y; i++ {\n\t\t\tidx[i-x] = strconv.FormatInt(i, 10)\n\t\t}\n\t\treturn idx\n\t} else if len(t) > 2 {\n\t\tpanic(\"invalid dimIndex\")\n\t}\n\n\ts := strings.Split(*r.element.DimIndex, \",\")\n\tif len(s) != dim {\n\t\tpanic(\"invalid dimIndex\")\n\t}\n\n\treturn s\n}\n\nfunc (r *Register) size() int {\n\tif r.element.Size != nil {\n\t\tsize, err := strconv.ParseInt(*r.element.Size, 0, 32)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\treturn int(size) / 8\n\t}\n\treturn 4\n}\n\nfunc parseRegister(groupName string, regEl *SVDRegister, baseAddress uint64, bitfieldPrefix string) []*PeripheralField {\n\treg := NewRegister(regEl, baseAddress)\n\n\tif reg.dim() != -1 {\n\t\tdimIncrement, err := strconv.ParseUint(regEl.DimIncrement, 0, 32)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\tif strings.Contains(reg.name(), \"%s\") {\n\t\t\t// a \"spaced array\" of registers, special processing required\n\t\t\t// we need to generate a separate register for each \"element\"\n\t\t\tvar results []*PeripheralField\n\t\t\tshortName := strings.ToUpper(strings.ReplaceAll(strings.ReplaceAll(reg.name(), \"_%s\", \"\"), \"%s\", \"\"))\n\t\t\tfor i, j := range reg.dimIndex() {\n\t\t\t\tregAddress := reg.address() + (uint64(i) * dimIncrement)\n\t\t\t\tresults = append(results, &PeripheralField{\n\t\t\t\t\tName:        strings.ToUpper(strings.ReplaceAll(reg.name(), \"%s\", j)),\n\t\t\t\t\tAddress:     regAddress,\n\t\t\t\t\tDescription: reg.description(),\n\t\t\t\t\tArray:       -1,\n\t\t\t\t\tElementSize: reg.size(),\n\t\t\t\t\tShortName:   shortName,\n\t\t\t\t})\n\t\t\t}\n\t\t\t// set first result bitfield\n\t\t\tresults[0].Constants, results[0].Bitfields = parseBitfields(groupName, shortName, regEl.Fields, bitfieldPrefix)\n\t\t\tresults[0].HasBitfields = len(results[0].Bitfields) > 0\n\t\t\tfor i := 1; i < len(results); i++ {\n\t\t\t\tresults[i].Bitfields = results[0].Bitfields\n\t\t\t\tresults[i].HasBitfields = results[0].HasBitfields\n\t\t\t}\n\t\t\treturn results\n\t\t}\n\t}\n\tregName := reg.name()\n\tif !unicode.IsUpper(rune(regName[0])) && !unicode.IsDigit(rune(regName[0])) {\n\t\tregName = strings.ToUpper(regName)\n\t}\n\tregName = cleanName(regName)\n\n\tconstants, bitfields := parseBitfields(groupName, regName, regEl.Fields, bitfieldPrefix)\n\treturn []*PeripheralField{&PeripheralField{\n\t\tName:         regName,\n\t\tAddress:      reg.address(),\n\t\tDescription:  reg.description(),\n\t\tConstants:    constants,\n\t\tArray:        reg.dim(),\n\t\tElementSize:  reg.size(),\n\t\tShortName:    regName,\n\t\tBitfields:    bitfields,\n\t\tHasBitfields: len(bitfields) > 0,\n\t}}\n}\n\n// The Go module for this device.\nfunc writeGo(outdir string, device *Device, interruptSystem string) error {\n\toutf, err := os.Create(filepath.Join(outdir, device.Metadata.NameLower+\".go\"))\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer outf.Close()\n\tw := bufio.NewWriter(outf)\n\n\tmaxInterruptValue := 0\n\tfor _, intr := range device.Interrupts {\n\t\tif intr.Value > maxInterruptValue {\n\t\t\tmaxInterruptValue = intr.Value\n\t\t}\n\t}\n\n\tinterruptHandlerMap := make(map[string]*Interrupt)\n\tvar interruptHandlers []*Interrupt\n\tfor _, intr := range device.Interrupts {\n\t\tif _, ok := interruptHandlerMap[intr.HandlerName]; !ok {\n\t\t\tinterruptHandlerMap[intr.HandlerName] = intr\n\t\t\tinterruptHandlers = append(interruptHandlers, intr)\n\t\t}\n\t}\n\n\tt := template.Must(template.New(\"go\").Funcs(template.FuncMap{\n\t\t\"bytesNeeded\": func(i, j uint64) uint64 { return j - i },\n\t\t\"isMultiline\": isMultiline,\n\t\t\"splitLine\":   splitLine,\n\t}).Parse(`// Automatically generated file. DO NOT EDIT.\n// Generated by gen-device-svd.go from {{.device.Metadata.File}}, see {{.device.Metadata.DescriptorSource}}\n\n//go:build {{.pkgName}} && {{.device.Metadata.NameLower}}\n\n/*\n{{.device.Metadata.Description}}\n*/\n{{.device.Metadata.LicenseBlock}}\npackage {{.pkgName}}\n\nimport (\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\n// Some information about this device.\nconst (\n\tDevice       = \"{{.device.Metadata.Name}}\"\n{{- if .device.Metadata.HasCPUInfo }}\n\tCPU          = \"{{.device.Metadata.CPUName}}\"\n\tFPUPresent   = {{.device.Metadata.FPUPresent}}\n\tNVICPrioBits = {{.device.Metadata.NVICPrioBits}}\n{{- end }}\n)\n\n// Interrupt numbers.\nconst (\n{{- range .device.Interrupts}}\n\t{{- if .Description}}\n\t\t{{- range .Description|splitLine}}\n\t// {{.}}\n\t\t{{- end}}\n\t{{- end}}\n\tIRQ_{{.Name}} = {{.Value}}\n\t{{- \"\\n\"}}\n{{- end}}\n\t// Highest interrupt number on this device.\n\tIRQ_max = {{.interruptMax}} \n)\n\n// Pseudo function call that is replaced by the compiler with the actual\n// functions registered through interrupt.New.\n//go:linkname callHandlers runtime/interrupt.callHandlers\nfunc callHandlers(num int)\n\n{{- if eq .interruptSystem \"hardware\"}}\n{{- range .interruptHandlers}}\n//export {{.HandlerName}}\nfunc interrupt{{.Name}}() {\n\tcallHandlers(IRQ_{{.Name}})\n}\n{{- end}}\n{{- end}}\n\n{{- if eq .interruptSystem \"software\"}}\nfunc HandleInterrupt(num int) {\n\tswitch num {\n\t{{- range .interruptHandlers}}\n\tcase IRQ_{{.Name}}:\n\t\tcallHandlers(IRQ_{{.Name}})\n\t{{- end}}\n\t}\n}\n{{- end}}\n\n// Peripherals.\nvar (\n{{- range .device.Peripherals}}\n\t{{- if .Description}}\n\t\t{{- range .Description|splitLine}}\n\t// {{.}}\n\t\t{{- end}}\n\t{{- end}}\n\t{{.Name}} = (*{{.GroupName}}_Type)(unsafe.Pointer(uintptr(0x{{printf \"%x\" .BaseAddress}})))\n\t{{- \"\\n\"}}\n{{- end}}\n)\n\n`))\n\terr = t.Execute(w, map[string]interface{}{\n\t\t\"device\":            device,\n\t\t\"pkgName\":           filepath.Base(strings.TrimRight(outdir, \"/\")),\n\t\t\"interruptMax\":      maxInterruptValue,\n\t\t\"interruptSystem\":   interruptSystem,\n\t\t\"interruptHandlers\": interruptHandlers,\n\t})\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Define peripheral struct types.\n\tfor _, peripheral := range device.Peripherals {\n\t\tif peripheral.Registers == nil {\n\t\t\t// This peripheral was derived from another peripheral. No new type\n\t\t\t// needs to be defined for it.\n\t\t\tcontinue\n\t\t}\n\t\tfmt.Fprintln(w)\n\t\tif peripheral.Description != \"\" {\n\t\t\tfor _, l := range splitLine(peripheral.Description) {\n\t\t\t\tfmt.Fprintf(w, \"// %s\\n\", l)\n\t\t\t}\n\t\t}\n\t\tfmt.Fprintf(w, \"type %s_Type struct {\\n\", peripheral.GroupName)\n\n\t\taddress := peripheral.BaseAddress\n\t\ttype clusterInfo struct {\n\t\t\tname        string\n\t\t\tdescription string\n\t\t\taddress     uint64\n\t\t\tsize        uint64\n\t\t\tregisters   []*PeripheralField\n\t\t}\n\t\tclusters := []clusterInfo{}\n\t\tfor _, register := range peripheral.Registers {\n\t\t\tif register.Registers == nil && address > register.Address {\n\t\t\t\t// In Nordic SVD files, these registers are deprecated or\n\t\t\t\t// duplicates, so can be ignored.\n\t\t\t\t//fmt.Fprintf(os.Stderr, \"skip: %s.%s 0x%x - 0x%x %d\\n\", peripheral.Name, register.name, address, register.address, register.elementSize)\n\t\t\t\t// remove bit fields from such register\n\t\t\t\tregister.Bitfields = nil\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tvar regType string\n\t\t\tswitch register.ElementSize {\n\t\t\tcase 8:\n\t\t\t\tregType = \"volatile.Register64\"\n\t\t\tcase 4:\n\t\t\t\tregType = \"volatile.Register32\"\n\t\t\tcase 2:\n\t\t\t\tregType = \"volatile.Register16\"\n\t\t\tcase 1:\n\t\t\t\tregType = \"volatile.Register8\"\n\t\t\tdefault:\n\t\t\t\tregType = \"volatile.Register32\"\n\t\t\t}\n\n\t\t\t// insert padding, if needed\n\t\t\tif address < register.Address {\n\t\t\t\tbytesNeeded := register.Address - address\n\t\t\t\tif bytesNeeded == 1 {\n\t\t\t\t\tw.WriteString(\"\\t_ byte\\n\")\n\t\t\t\t} else {\n\t\t\t\t\tfmt.Fprintf(w, \"\\t_ [%d]byte\\n\", bytesNeeded)\n\t\t\t\t}\n\t\t\t\taddress = register.Address\n\t\t\t}\n\n\t\t\tlastCluster := false\n\t\t\tif register.Registers != nil {\n\t\t\t\t// This is a cluster, not a register. Create the cluster type.\n\t\t\t\tregType = peripheral.GroupName + \"_\" + register.Name\n\t\t\t\tclusters = append(clusters, clusterInfo{regType, register.Description, register.Address, uint64(register.ElementSize), register.Registers})\n\t\t\t\tregType = regType + \"_Type\"\n\t\t\t\tsubaddress := register.Address\n\t\t\t\tfor _, subregister := range register.Registers {\n\n\t\t\t\t\tif subaddress != subregister.Address {\n\t\t\t\t\t\tbytesNeeded := subregister.Address - subaddress\n\t\t\t\t\t\tsubaddress += bytesNeeded\n\t\t\t\t\t}\n\t\t\t\t\tvar subregSize uint64\n\t\t\t\t\tif subregister.Array != -1 {\n\t\t\t\t\t\tsubregSize = uint64(subregister.Array * subregister.ElementSize)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsubregSize = uint64(subregister.ElementSize)\n\t\t\t\t\t}\n\t\t\t\t\tsubaddress += subregSize\n\t\t\t\t}\n\t\t\t\tif register.Array == -1 {\n\t\t\t\t\tlastCluster = true\n\t\t\t\t}\n\t\t\t\taddress = subaddress\n\t\t\t}\n\n\t\t\tif register.Array != -1 {\n\t\t\t\tregType = fmt.Sprintf(\"[%d]%s\", register.Array, regType)\n\t\t\t}\n\t\t\tfmt.Fprintf(w, \"\\t%s %s // 0x%X\\n\", register.Name, regType, register.Address-peripheral.BaseAddress)\n\n\t\t\t// next address\n\t\t\tif lastCluster {\n\t\t\t\tlastCluster = false\n\t\t\t} else if register.Array != -1 {\n\t\t\t\taddress = register.Address + uint64(register.ElementSize*register.Array)\n\t\t\t} else {\n\t\t\t\taddress = register.Address + uint64(register.ElementSize)\n\t\t\t}\n\t\t}\n\t\tw.WriteString(\"}\\n\")\n\n\t\tfor _, register := range peripheral.Registers {\n\t\t\tregName := register.Name\n\t\t\twriteGoRegisterBitfieldType(w, register, peripheral.GroupName, regName)\n\t\t}\n\n\t\t// Define clusters\n\t\tfor i := 0; i < len(clusters); i++ {\n\t\t\tcluster := clusters[i]\n\t\t\tif len(cluster.registers) == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif _, ok := device.PeripheralDict[cluster.name]; ok {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tfmt.Fprintln(w)\n\t\t\tif cluster.description != \"\" {\n\t\t\t\tfor _, l := range splitLine(cluster.description) {\n\t\t\t\t\tfmt.Fprintf(w, \"// %s\\n\", l)\n\t\t\t\t}\n\t\t\t}\n\t\t\tfmt.Fprintf(w, \"type %s_Type struct {\\n\", cluster.name)\n\n\t\t\taddress := cluster.address\n\n\t\t\tfor _, register := range cluster.registers {\n\t\t\t\tif register.Registers == nil && address > register.Address {\n\t\t\t\t\t// In Nordic SVD files, these registers are deprecated or\n\t\t\t\t\t// duplicates, so can be ignored.\n\t\t\t\t\t//fmt.Fprintf(os.Stderr, \"skip: %s.%s 0x%x - 0x%x %d\\n\", peripheral.Name, register.name, address, register.address, register.elementSize)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tvar regType string\n\t\t\t\tswitch register.ElementSize {\n\t\t\t\tcase 8:\n\t\t\t\t\tregType = \"volatile.Register64\"\n\t\t\t\tcase 4:\n\t\t\t\t\tregType = \"volatile.Register32\"\n\t\t\t\tcase 2:\n\t\t\t\t\tregType = \"volatile.Register16\"\n\t\t\t\tcase 1:\n\t\t\t\t\tregType = \"volatile.Register8\"\n\t\t\t\tdefault:\n\t\t\t\t\tregType = \"volatile.Register32\"\n\t\t\t\t}\n\n\t\t\t\t// insert padding, if needed\n\t\t\t\tif address < register.Address {\n\t\t\t\t\tbytesNeeded := register.Address - address\n\t\t\t\t\tif bytesNeeded == 1 {\n\t\t\t\t\t\tw.WriteString(\"\\t_ byte\\n\")\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfmt.Fprintf(w, \"\\t_ [%d]byte\\n\", bytesNeeded)\n\t\t\t\t\t}\n\t\t\t\t\taddress = register.Address\n\t\t\t\t}\n\n\t\t\t\tlastCluster := false\n\t\t\t\tif register.Registers != nil {\n\t\t\t\t\t// This is a cluster, not a register. Create the cluster type.\n\t\t\t\t\tregType = peripheral.GroupName + \"_\" + register.Name\n\t\t\t\t\tclusters = append(clusters, clusterInfo{regType, register.Description, register.Address, uint64(register.ElementSize), register.Registers})\n\t\t\t\t\tregType = regType + \"_Type\"\n\n\t\t\t\t\tsubaddress := register.Address\n\t\t\t\t\tfor _, subregister := range register.Registers {\n\t\t\t\t\t\tif subaddress != subregister.Address {\n\t\t\t\t\t\t\tbytesNeeded := subregister.Address - subaddress\n\t\t\t\t\t\t\tsubaddress += bytesNeeded\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar subregSize uint64\n\t\t\t\t\t\tif subregister.Array != -1 {\n\t\t\t\t\t\t\tsubregSize = uint64(subregister.Array * subregister.ElementSize)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsubregSize = uint64(subregister.ElementSize)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsubaddress += subregSize\n\t\t\t\t\t}\n\t\t\t\t\tif register.Array == -1 {\n\t\t\t\t\t\tlastCluster = true\n\t\t\t\t\t}\n\t\t\t\t\taddress = subaddress\n\t\t\t\t}\n\n\t\t\t\tif register.Array != -1 {\n\t\t\t\t\tregType = fmt.Sprintf(\"[%d]%s\", register.Array, regType)\n\t\t\t\t}\n\t\t\t\tfmt.Fprintf(w, \"\\t%s %s // 0x%X\\n\", register.Name, regType, register.Address-peripheral.BaseAddress)\n\n\t\t\t\t// next address\n\t\t\t\tif lastCluster {\n\t\t\t\t\tlastCluster = false\n\t\t\t\t} else if register.Array != -1 {\n\t\t\t\t\taddress = register.Address + uint64(register.ElementSize*register.Array)\n\t\t\t\t} else {\n\t\t\t\t\taddress = register.Address + uint64(register.ElementSize)\n\t\t\t\t}\n\t\t\t}\n\t\t\t// make sure the structure is full\n\t\t\tif cluster.size > (address - cluster.registers[0].Address) {\n\t\t\t\tbytesNeeded := cluster.size - (address - cluster.registers[0].Address)\n\t\t\t\tif bytesNeeded == 1 {\n\t\t\t\t\tw.WriteString(\"\\t_ byte\\n\")\n\t\t\t\t} else {\n\t\t\t\t\tfmt.Fprintf(w, \"\\t_ [%d]byte\\n\", bytesNeeded)\n\t\t\t\t}\n\t\t\t} else if cluster.size != (address - cluster.registers[0].Address) {\n\t\t\t\tprintln(\"peripheral:\", peripheral.Name, \"cluster:\", cluster.name, \"size:\", cluster.size, \"struct size:\", (address - cluster.registers[0].Address))\n\t\t\t}\n\t\t\tw.WriteString(\"}\\n\")\n\n\t\t\tfor _, register := range cluster.registers {\n\t\t\t\tregName := register.Name\n\t\t\t\tif register.Array == -1 {\n\t\t\t\t\twriteGoRegisterBitfieldType(w, register, cluster.name, regName)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Define bitfields.\n\tfor _, peripheral := range device.Peripherals {\n\t\tif peripheral.Registers == nil {\n\t\t\t// This peripheral was derived from another peripheral. Constants are\n\t\t\t// already defined.\n\t\t\tcontinue\n\t\t}\n\t\tfmt.Fprintf(w, \"\\n// Constants for %s\", peripheral.Name)\n\t\tif isMultiline(peripheral.Description) {\n\t\t\tfor _, l := range splitLine(peripheral.Description) {\n\t\t\t\tfmt.Fprintf(w, \"\\n// %s\", l)\n\t\t\t}\n\t\t} else if peripheral.Description != \"\" {\n\t\t\tfmt.Fprintf(w, \": %s\", peripheral.Description)\n\t\t}\n\n\t\tfmt.Fprint(w, \"\\nconst(\")\n\t\tfor _, register := range peripheral.Registers {\n\t\t\tif len(register.Constants) != 0 {\n\t\t\t\twriteGoRegisterConstants(w, register, register.Name)\n\t\t\t}\n\t\t\tif register.Registers == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfor _, subregister := range register.Registers {\n\t\t\t\twriteGoRegisterConstants(w, subregister, register.Name+\".\"+subregister.Name)\n\t\t\t}\n\t\t}\n\t\tw.WriteString(\")\\n\")\n\t}\n\n\treturn w.Flush()\n}\n\nfunc writeGoRegisterConstants(w *bufio.Writer, register *PeripheralField, name string) {\n\tw.WriteString(\"\\n\\t// \" + name)\n\tif register.Description != \"\" {\n\t\tif isMultiline(register.Description) {\n\t\t\tfor _, l := range splitLine(register.Description) {\n\t\t\t\tw.WriteString(\"\\n\\t// \" + l)\n\t\t\t}\n\t\t} else {\n\t\t\tw.WriteString(\": \" + register.Description)\n\t\t}\n\t}\n\tw.WriteByte('\\n')\n\tfor _, bitfield := range register.Constants {\n\t\tif bitfield.Description != \"\" {\n\t\t\tfor _, l := range splitLine(bitfield.Description) {\n\t\t\t\tw.WriteString(\"\\t// \" + l + \"\\n\")\n\t\t\t}\n\t\t}\n\t\tfmt.Fprintf(w, \"\\t%s = 0x%x\\n\", bitfield.Name, bitfield.Value)\n\t}\n}\n\nfunc writeGoRegisterBitfieldType(w *bufio.Writer, register *PeripheralField, peripheralName, registerName string) {\n\tif len(register.Bitfields) == 0 {\n\t\treturn\n\t}\n\tw.WriteString(\"\\n// \" + peripheralName + \".\" + registerName)\n\tif register.Description != \"\" {\n\t\tif isMultiline(register.Description) {\n\t\t\tfor _, l := range splitLine(register.Description) {\n\t\t\t\tw.WriteString(\"\\n\\t// \" + l)\n\t\t\t}\n\t\t} else {\n\t\t\tw.WriteString(\": \" + register.Description)\n\t\t}\n\t}\n\tw.WriteByte('\\n')\n\tvar bitSize int\n\tvar maxMask uint32\n\tswitch register.ElementSize {\n\tcase 8:\n\t\tbitSize = 64\n\t\tmaxMask = 0xffffffff\n\t\t// maxMask = 0xffffffffffffffff // TODO how to handle 64-bit fields\n\tcase 4:\n\t\tbitSize = 32\n\t\tmaxMask = 0xffffffff\n\tcase 2:\n\t\tbitSize = 16\n\t\tmaxMask = 0xffff\n\tcase 1:\n\t\tbitSize = 8\n\t\tmaxMask = 0xff\n\tdefault:\n\t\tbitSize = 32\n\t\tmaxMask = 0xffffffff\n\t}\n\n\ttypeName := fmt.Sprintf(\"%s_Type\", peripheralName)\n\n\tfor _, bitfield := range register.Bitfields {\n\t\tidxArg := \"\"\n\t\tregAccess := \"&o.\" + registerName + \".Reg\"\n\t\tif register.Array != -1 {\n\t\t\tidxArg = \"idx int, \"\n\t\t\tregAccess = \"&o.\" + registerName + \"[idx].Reg\"\n\t\t}\n\t\tvar funcSuffix string\n\t\tif maxMask == bitfield.Mask || registerName == bitfield.Name {\n\t\t\tfuncSuffix = registerName\n\t\t} else {\n\t\t\tfuncSuffix = registerName + \"_\" + bitfield.Name\n\t\t}\n\t\tfmt.Fprintf(w, \"func (o *%s) Set%s(%s value uint%d) {\\n\", typeName, funcSuffix, idxArg, bitSize)\n\t\tif maxMask == bitfield.Mask {\n\t\t\tfmt.Fprintf(w, \"\\tvolatile.StoreUint%d(%s, value)\\n\", bitSize, regAccess)\n\t\t} else if bitfield.Offset > 0 {\n\t\t\tfmt.Fprintf(w, \"\\tvolatile.StoreUint%d(%s, volatile.LoadUint%d(%s)&^(0x%x)|value<<%d)\\n\", bitSize, regAccess, bitSize, regAccess, bitfield.Mask, bitfield.Offset)\n\t\t} else {\n\t\t\tfmt.Fprintf(w, \"\\tvolatile.StoreUint%d(%s, volatile.LoadUint%d(%s)&^(0x%x)|value)\\n\", bitSize, regAccess, bitSize, regAccess, bitfield.Mask)\n\t\t}\n\t\tw.WriteString(\"}\\n\")\n\t\tfmt.Fprintf(w, \"func (o *%s) Get%s(%s) uint%d {\\n\", typeName, funcSuffix, idxArg, bitSize)\n\t\tif maxMask == bitfield.Mask {\n\t\t\tfmt.Fprintf(w, \"\\treturn volatile.LoadUint%d(%s)\\n\", bitSize, regAccess)\n\t\t} else if bitfield.Offset > 0 {\n\t\t\tfmt.Fprintf(w, \"\\treturn (volatile.LoadUint%d(%s)&0x%x) >> %d\\n\", bitSize, regAccess, bitfield.Mask, bitfield.Offset)\n\t\t} else {\n\t\t\tfmt.Fprintf(w, \"\\treturn volatile.LoadUint%d(%s)&0x%x\\n\", bitSize, regAccess, bitfield.Mask)\n\t\t}\n\t\tw.WriteString(\"}\\n\")\n\t}\n}\n\n// The interrupt vector, which is hard to write directly in Go.\nfunc writeAsm(outdir string, device *Device) error {\n\toutf, err := os.Create(filepath.Join(outdir, device.Metadata.NameLower+\".s\"))\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer outf.Close()\n\tw := bufio.NewWriter(outf)\n\n\tt := template.Must(template.New(\"go\").Parse(`// Automatically generated file. DO NOT EDIT.\n// Generated by gen-device-svd.go from {{.File}}, see {{.DescriptorSource}}\n\n/*\n{{.Description}}\n*/\n\n{{.LicenseBlock}}\n\n.syntax unified\n\n// This is the default handler for interrupts, if triggered but not defined.\n.section .text.Default_Handler\n.global  Default_Handler\n.type    Default_Handler, %function\nDefault_Handler:\n    wfe\n    b    Default_Handler\n.size Default_Handler, .-Default_Handler\n\n// Avoid the need for repeated .weak and .set instructions.\n.macro IRQ handler\n    .weak  \\handler\n    .set   \\handler, Default_Handler\n.endm\n\n// Must set the \"a\" flag on the section:\n// https://svnweb.freebsd.org/base/stable/11/sys/arm/arm/locore-v4.S?r1=321049&r2=321048&pathrev=321049\n// https://sourceware.org/binutils/docs/as/Section.html#ELF-Version\n.section .isr_vector, \"a\", %progbits\n.global  __isr_vector\n__isr_vector:\n    // Interrupt vector as defined by Cortex-M, starting with the stack top.\n    // On reset, SP is initialized with *0x0 and PC is loaded with *0x4, loading\n    // _stack_top and Reset_Handler.\n    .long _stack_top\n    .long Reset_Handler\n    .long NMI_Handler\n    .long HardFault_Handler\n    .long MemoryManagement_Handler\n    .long BusFault_Handler\n    .long UsageFault_Handler\n    .long 0\n    .long 0\n    .long 0\n    .long 0\n    .long SVC_Handler\n    .long DebugMon_Handler\n    .long 0\n    .long PendSV_Handler\n    .long SysTick_Handler\n\n    // Extra interrupts for peripherals defined by the hardware vendor.\n`))\n\terr = t.Execute(w, device.Metadata)\n\tif err != nil {\n\t\treturn err\n\t}\n\tnum := 0\n\tfor _, intr := range device.Interrupts {\n\t\tif intr.Value == num-1 {\n\t\t\tcontinue\n\t\t}\n\t\tif intr.Value < num {\n\t\t\tpanic(\"interrupt numbers are not sorted\")\n\t\t}\n\t\tfor intr.Value > num {\n\t\t\tw.WriteString(\"    .long 0\\n\")\n\t\t\tnum++\n\t\t}\n\t\tnum++\n\t\tfmt.Fprintf(w, \"    .long %s\\n\", intr.HandlerName)\n\t}\n\n\tw.WriteString(`\n    // Define default implementations for interrupts, redirecting to\n    // Default_Handler when not implemented.\n    IRQ NMI_Handler\n    IRQ HardFault_Handler\n    IRQ MemoryManagement_Handler\n    IRQ BusFault_Handler\n    IRQ UsageFault_Handler\n    IRQ SVC_Handler\n    IRQ DebugMon_Handler\n    IRQ PendSV_Handler\n    IRQ SysTick_Handler\n`)\n\tfor _, intr := range device.Interrupts {\n\t\tfmt.Fprintf(w, \"    IRQ %s_IRQHandler\\n\", intr.Name)\n\t}\n\tw.WriteString(`\n.size __isr_vector, .-__isr_vector\n`)\n\treturn w.Flush()\n}\n\nfunc generate(indir, outdir, sourceURL, interruptSystem string) error {\n\tif _, err := os.Stat(indir); errors.Is(err, fs.ErrNotExist) {\n\t\tfmt.Fprintln(os.Stderr, \"cannot find input directory:\", indir)\n\t\tos.Exit(1)\n\t}\n\tos.MkdirAll(outdir, 0777)\n\n\tinfiles, err := filepath.Glob(filepath.Join(indir, \"*.svd\"))\n\tif err != nil {\n\t\tfmt.Fprintln(os.Stderr, \"could not read .svd files:\", err)\n\t\tos.Exit(1)\n\t}\n\tsort.Strings(infiles)\n\tfor _, infile := range infiles {\n\t\tfmt.Println(infile)\n\t\tdevice, err := readSVD(infile, sourceURL)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to read: %w\", err)\n\t\t}\n\t\terr = writeGo(outdir, device, interruptSystem)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to write Go file: %w\", err)\n\t\t}\n\t\tswitch interruptSystem {\n\t\tcase \"software\":\n\t\t\t// Nothing to do.\n\t\tcase \"hardware\":\n\t\t\terr = writeAsm(outdir, device)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to write assembly file: %w\", err)\n\t\t\t}\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"unknown interrupt system: %s\", interruptSystem)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc main() {\n\tsourceURL := flag.String(\"source\", \"<unknown>\", \"source SVD file\")\n\tinterruptSystem := flag.String(\"interrupts\", \"hardware\", \"interrupt system in use (software, hardware)\")\n\tflag.Parse()\n\tif flag.NArg() != 2 {\n\t\tfmt.Fprintln(os.Stderr, \"provide exactly two arguments: input directory (with .svd files) and output directory for generated files\")\n\t\tflag.PrintDefaults()\n\t\treturn\n\t}\n\tindir := flag.Arg(0)\n\toutdir := flag.Arg(1)\n\terr := generate(indir, outdir, *sourceURL, *interruptSystem)\n\tif err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\tos.Exit(1)\n\t}\n}\n"
  },
  {
    "path": "tools/sizediff",
    "content": "#!/usr/bin/env python3\n\n# Small tool to compare code size between TinyGo runs (with the -size=short flag).\n\nimport sys\n\nclass Comparison:\n    def __init__(self, command, flash0, ram0, flash1, ram1):\n        self.command = command\n        self.flash0 = flash0\n        self.ram0 = ram0\n        self.flash1 = flash1\n        self.ram1 = ram1\n\n    @property\n    def ramdiff(self):\n        return self.ram1 - self.ram0\n\n    @property\n    def flashdiff(self):\n        return self.flash1 - self.flash0\n\ndef readSizes(path):\n    sizes = []\n    lines = open(path).readlines()\n    for i in range(len(lines)):\n        if not lines[i].strip().startswith('code '):\n            continue\n        # found a size header\n        code, data, bss, flash, ram = map(int, lines[i+1].replace(\"|\", \"\").split())\n        command = lines[i-1].strip()\n        sizes.append({\n            'command': command,\n            'flash':   flash,\n            'ram':     ram\n        })\n    return sizes\n\ndef main():\n    path0 = sys.argv[1]\n    path1 = sys.argv[2]\n    sizes0 = readSizes(path0)\n    sizes1 = readSizes(path1)\n    comparisons = []\n    for i in range(len(sizes0)):\n        if i >= len(sizes1):\n            print('%s has more commands than %s' % (path0, path1))\n            print('   ', sizes0[i]['command'])\n            break\n        if sizes0[i]['command'] != sizes1[i]['command']:\n            print('not the same command!')\n            print('   ', sizes0[i]['command'])\n            print('   ', sizes1[i]['command'])\n        comparisons.append(Comparison(sizes0[i]['command'], sizes0[i]['flash'], sizes0[i]['ram'], sizes1[i]['flash'], sizes1[i]['ram']))\n    if len(sizes0) < len(sizes1):\n        print('%s has more commands than %s' % (path1, path0))\n        print('   ', sizes1[len(sizes0)]['command'])\n    comparisons.sort(key=lambda x: x.flashdiff)\n    totalFlash0 = 0\n    totalFlash1 = 0\n    totalRam0 = 0\n    totalRam1 = 0\n    totalDiff = 0\n    totalRamDiff = 0\n    totalProduct = 1\n    totalRamProduct = 1\n    print(' flash                          ram')\n    print(' before   after   diff          before   after   diff')\n    for comparison in comparisons:\n        diffPct = comparison.flashdiff / comparison.flash0\n        diffRamPct = comparison.ramdiff / comparison.ram0\n        print('%7d %7d %6d %6.2f%% %7d %7d %6d %6.2f%% %s' % (comparison.flash0, comparison.flash1, comparison.flashdiff, diffPct * 100, comparison.ram0, comparison.ram1, comparison.ramdiff, diffRamPct * 100, comparison.command))\n        totalFlash0 += comparison.flash0\n        totalFlash1 += comparison.flash1\n        totalDiff += comparison.flashdiff\n        totalProduct *= (1 + diffPct)\n        totalRam0 += comparison.ram0\n        totalRam1 += comparison.ram1\n        totalRamDiff += comparison.ramdiff\n        totalRamProduct *= (1 + diffRamPct)\n    geomean = totalProduct ** (1.0 / float(len(comparisons)))\n    geomeanRam = totalRamProduct ** (1.0 / float(len(comparisons)))\n    print('%7d %7d %6d %6.2f%% %7d %7d %6d %6.2f%%' % (totalFlash0, totalFlash1, totalDiff, geomean - 1, totalRam0, totalRam1, totalRamDiff, geomeanRam - 1))\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "tools/tgtestjson.sh",
    "content": "#!/usr/bin/env bash\n\n# Run tests and convert output to json with go tool test2json.\n# This is a workaround for the lack of -json output in tinygo test.\n# Some variables must be set in the environment beforehand.\n# TODO: let's just add -json support to tinygo test.\n\nTINYGO=\"${TINYGO:-tinygo}\"\nPACKAGES=\"${PACKAGES:-\"./tests\"}\"\nTARGET=\"${TARGET:-wasip2}\"\nTESTOPTS=\"${TESTOPTS:-\"-x -work\"}\"\n\n# go clean -testcache\nfor pkg in $PACKAGES; do\n    # Example invocation with test2json in BigGo:\n    # go test -test.v=test2json ./$pkg 2>&1 | go tool test2json -p $pkg\n\n    # Uncomment to see resolved commands in output\n    # >&2 echo \"${TINYGO} test -v -target $TARGET $TESTOPTS $pkg 2>&1 | go tool test2json -p $pkg\"\n    \"${TINYGO}\" test -v -target $TARGET $TESTOPTS $pkg 2>&1 | go tool test2json -p $pkg\n\ndone\n"
  },
  {
    "path": "transform/allocs.go",
    "content": "package transform\n\n// This file implements an escape analysis pass. It looks for calls to\n// runtime.alloc and replaces these calls with a stack allocation if the\n// allocated value does not escape. It uses the LLVM nocapture flag for\n// interprocedural escape analysis.\n\nimport (\n\t\"fmt\"\n\t\"go/token\"\n\t\"regexp\"\n\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// OptimizeAllocs tries to replace heap allocations with stack allocations\n// whenever possible. It relies on the LLVM 'nocapture' flag for interprocedural\n// escape analysis, and within a function looks whether an allocation can escape\n// to the heap.\n// If printAllocs is non-nil, it indicates the regexp of functions for which a\n// heap allocation explanation should be printed (why the object can't be stack\n// allocated).\nfunc OptimizeAllocs(mod llvm.Module, printAllocs *regexp.Regexp, maxStackAlloc uint64, logger func(token.Position, string)) {\n\tallocator := mod.NamedFunction(\"runtime.alloc\")\n\tif allocator.IsNil() {\n\t\t// nothing to optimize\n\t\treturn\n\t}\n\n\ttargetData := llvm.NewTargetData(mod.DataLayout())\n\tdefer targetData.Dispose()\n\tctx := mod.Context()\n\tbuilder := ctx.NewBuilder()\n\tdefer builder.Dispose()\n\n\t// Determine the maximum alignment on this platform.\n\tcomplex128Type := ctx.StructType([]llvm.Type{ctx.DoubleType(), ctx.DoubleType()}, false)\n\tmaxAlign := int64(targetData.ABITypeAlignment(complex128Type))\n\n\tfor _, heapalloc := range getUses(allocator) {\n\t\tlogAllocs := printAllocs != nil && printAllocs.MatchString(heapalloc.InstructionParent().Parent().Name())\n\t\tif heapalloc.Operand(0).IsAConstantInt().IsNil() {\n\t\t\t// Do not allocate variable length arrays on the stack.\n\t\t\tif logAllocs {\n\t\t\t\tlogAlloc(logger, heapalloc, \"size is not constant\")\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\tsize := heapalloc.Operand(0).ZExtValue()\n\t\tif size > maxStackAlloc {\n\t\t\t// The maximum size for a stack allocation.\n\t\t\tif logAllocs {\n\t\t\t\tlogAlloc(logger, heapalloc, fmt.Sprintf(\"object size %d exceeds maximum stack allocation size %d\", size, maxStackAlloc))\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\tif size == 0 {\n\t\t\t// If the size is 0, the pointer is allowed to alias other\n\t\t\t// zero-sized pointers. Use the pointer to the global that would\n\t\t\t// also be returned by runtime.alloc.\n\t\t\tzeroSizedAlloc := mod.NamedGlobal(\"runtime.zeroSizedAlloc\")\n\t\t\tif !zeroSizedAlloc.IsNil() {\n\t\t\t\theapalloc.ReplaceAllUsesWith(zeroSizedAlloc)\n\t\t\t\theapalloc.EraseFromParentAsInstruction()\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// In general the pattern is:\n\t\t//     %0 = call i8* @runtime.alloc(i32 %size, i8* null)\n\t\t//     %1 = bitcast i8* %0 to type*\n\t\t//     (use %1 only)\n\t\t// But the bitcast might sometimes be dropped when allocating an *i8.\n\t\t// The 'bitcast' variable below is thus usually a bitcast of the\n\t\t// heapalloc but not always.\n\t\tbitcast := heapalloc // instruction that creates the value\n\t\tif uses := getUses(heapalloc); len(uses) == 1 && !uses[0].IsABitCastInst().IsNil() {\n\t\t\t// getting only bitcast use\n\t\t\tbitcast = uses[0]\n\t\t}\n\n\t\tif at := valueEscapesAt(bitcast); !at.IsNil() {\n\t\t\tif logAllocs {\n\t\t\t\tatPos := getPosition(at)\n\t\t\t\tmsg := \"escapes at unknown line\"\n\t\t\t\tif atPos.Line != 0 {\n\t\t\t\t\tmsg = fmt.Sprintf(\"escapes at line %d\", atPos.Line)\n\t\t\t\t}\n\t\t\t\tlogAlloc(logger, heapalloc, msg)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\t// The pointer value does not escape.\n\n\t\t// Determine the appropriate alignment of the alloca.\n\t\tattr := heapalloc.GetCallSiteEnumAttribute(0, llvm.AttributeKindID(\"align\"))\n\t\talignment := int(maxAlign)\n\t\tif !attr.IsNil() {\n\t\t\t// 'align' return value attribute is set, so use it.\n\t\t\t// This is basically always the case, but to be sure we'll default\n\t\t\t// to maxAlign if it isn't.\n\t\t\talignment = int(attr.GetEnumValue())\n\t\t}\n\n\t\t// Insert alloca in the entry block. Do it here so that mem2reg can\n\t\t// promote it to a SSA value.\n\t\tfn := bitcast.InstructionParent().Parent()\n\t\tbuilder.SetInsertPointBefore(fn.EntryBasicBlock().FirstInstruction())\n\t\tallocaType := llvm.ArrayType(mod.Context().Int8Type(), int(size))\n\t\talloca := builder.CreateAlloca(allocaType, \"stackalloc\")\n\t\talloca.SetAlignment(alignment)\n\n\t\t// Zero the allocation inside the block where the value was originally allocated.\n\t\tzero := llvm.ConstNull(alloca.AllocatedType())\n\t\tbuilder.SetInsertPointBefore(bitcast)\n\t\tstore := builder.CreateStore(zero, alloca)\n\t\tstore.SetAlignment(alignment)\n\n\t\t// Replace heap alloc bitcast with stack alloc bitcast.\n\t\tbitcast.ReplaceAllUsesWith(alloca)\n\t\tif heapalloc != bitcast {\n\t\t\tbitcast.EraseFromParentAsInstruction()\n\t\t}\n\t\theapalloc.EraseFromParentAsInstruction()\n\t}\n}\n\n// valueEscapesAt returns the instruction where the given value may escape and a\n// nil llvm.Value if it definitely doesn't. The value must be an instruction.\nfunc valueEscapesAt(value llvm.Value) llvm.Value {\n\tuses := getUses(value)\n\tfor _, use := range uses {\n\t\tif use.IsAInstruction().IsNil() {\n\t\t\tpanic(\"expected instruction use\")\n\t\t}\n\t\tswitch use.InstructionOpcode() {\n\t\tcase llvm.GetElementPtr:\n\t\t\tif at := valueEscapesAt(use); !at.IsNil() {\n\t\t\t\treturn at\n\t\t\t}\n\t\tcase llvm.BitCast:\n\t\t\t// A bitcast escapes if the casted-to value escapes.\n\t\t\tif at := valueEscapesAt(use); !at.IsNil() {\n\t\t\t\treturn at\n\t\t\t}\n\t\tcase llvm.Load:\n\t\t\t// Load does not escape.\n\t\tcase llvm.Store:\n\t\t\t// Store only escapes when the value is stored to, not when the\n\t\t\t// value is stored into another value.\n\t\t\tif use.Operand(0) == value {\n\t\t\t\treturn use\n\t\t\t}\n\t\tcase llvm.Call:\n\t\t\tif !hasFlag(use, value, \"nocapture\") {\n\t\t\t\treturn use\n\t\t\t}\n\t\tcase llvm.ICmp:\n\t\t\t// Comparing pointers don't let the pointer escape.\n\t\t\t// This is often a compiler-inserted nil check.\n\t\tdefault:\n\t\t\t// Unknown instruction, might escape.\n\t\t\treturn use\n\t\t}\n\t}\n\n\t// Checked all uses, and none let the pointer value escape.\n\treturn llvm.Value{}\n}\n\n// logAlloc prints a message to stderr explaining why the given object had to be\n// allocated on the heap.\nfunc logAlloc(logger func(token.Position, string), allocCall llvm.Value, reason string) {\n\tlogger(getPosition(allocCall), \"object allocated on the heap: \"+reason)\n}\n"
  },
  {
    "path": "transform/allocs_test.go",
    "content": "package transform_test\n\nimport (\n\t\"go/token\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/tinygo-org/tinygo/transform\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\nfunc TestAllocs(t *testing.T) {\n\tt.Parallel()\n\ttestTransform(t, \"testdata/allocs\", func(mod llvm.Module) {\n\t\ttransform.OptimizeAllocs(mod, nil, 256, nil)\n\t})\n}\n\ntype allocsTestOutput struct {\n\tfilename string\n\tline     int\n\tmsg      string\n}\n\nfunc (out allocsTestOutput) String() string {\n\treturn out.filename + \":\" + strconv.Itoa(out.line) + \": \" + out.msg\n}\n\n// Test with a Go file as input (for more accurate tests).\nfunc TestAllocs2(t *testing.T) {\n\tt.Parallel()\n\n\tmod := compileGoFileForTesting(t, \"./testdata/allocs2.go\")\n\n\t// Run functionattrs pass, which is necessary for escape analysis.\n\tpo := llvm.NewPassBuilderOptions()\n\tdefer po.Dispose()\n\terr := mod.RunPasses(\"function(instcombine),function-attrs\", llvm.TargetMachine{}, po)\n\tif err != nil {\n\t\tt.Error(\"failed to run passes:\", err)\n\t}\n\n\t// Run heap to stack transform.\n\tvar testOutputs []allocsTestOutput\n\ttransform.OptimizeAllocs(mod, regexp.MustCompile(\".\"), 256, func(pos token.Position, msg string) {\n\t\ttestOutputs = append(testOutputs, allocsTestOutput{\n\t\t\tfilename: filepath.Base(pos.Filename),\n\t\t\tline:     pos.Line,\n\t\t\tmsg:      msg,\n\t\t})\n\t})\n\tsort.Slice(testOutputs, func(i, j int) bool {\n\t\treturn testOutputs[i].line < testOutputs[j].line\n\t})\n\ttestOutput := \"\"\n\tfor _, out := range testOutputs {\n\t\ttestOutput += out.String() + \"\\n\"\n\t}\n\n\t// Load expected test output (the OUT: lines).\n\ttestInput, err := os.ReadFile(\"./testdata/allocs2.go\")\n\tif err != nil {\n\t\tt.Fatal(\"could not read test input:\", err)\n\t}\n\tvar expectedTestOutput string\n\tfor i, line := range strings.Split(strings.ReplaceAll(string(testInput), \"\\r\\n\", \"\\n\"), \"\\n\") {\n\t\tif idx := strings.Index(line, \" // OUT: \"); idx > 0 {\n\t\t\tmsg := line[idx+len(\" // OUT: \"):]\n\t\t\texpectedTestOutput += \"allocs2.go:\" + strconv.Itoa(i+1) + \": \" + msg + \"\\n\"\n\t\t}\n\t}\n\n\tif testOutput != expectedTestOutput {\n\t\tt.Errorf(\"output does not match expected output:\\n%s\", testOutput)\n\t}\n}\n"
  },
  {
    "path": "transform/errors.go",
    "content": "package transform\n\nimport (\n\t\"go/scanner\"\n\t\"go/token\"\n\t\"path/filepath\"\n\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// errorAt returns an error value at the location of the value.\n// The location information may not be complete as it depends on debug\n// information in the IR.\nfunc errorAt(val llvm.Value, msg string) scanner.Error {\n\treturn scanner.Error{\n\t\tPos: getPosition(val),\n\t\tMsg: msg,\n\t}\n}\n\n// getPosition returns the position information for the given value, as far as\n// it is available.\nfunc getPosition(val llvm.Value) token.Position {\n\tif !val.IsAInstruction().IsNil() {\n\t\tloc := val.InstructionDebugLoc()\n\t\tif loc.IsNil() {\n\t\t\treturn token.Position{}\n\t\t}\n\t\tfile := loc.LocationScope().ScopeFile()\n\t\treturn token.Position{\n\t\t\tFilename: filepath.Join(file.FileDirectory(), file.FileFilename()),\n\t\t\tLine:     int(loc.LocationLine()),\n\t\t\tColumn:   int(loc.LocationColumn()),\n\t\t}\n\t} else if !val.IsAFunction().IsNil() {\n\t\tloc := val.Subprogram()\n\t\tif loc.IsNil() {\n\t\t\treturn token.Position{}\n\t\t}\n\t\tfile := loc.ScopeFile()\n\t\treturn token.Position{\n\t\t\tFilename: filepath.Join(file.FileDirectory(), file.FileFilename()),\n\t\t\tLine:     int(loc.SubprogramLine()),\n\t\t}\n\t} else {\n\t\treturn token.Position{}\n\t}\n}\n\n// ErrMissingIntrinsic is an error indicating that a required intrinsic was not found in the module.\ntype ErrMissingIntrinsic struct {\n\tName string\n}\n\nfunc (err ErrMissingIntrinsic) Error() string {\n\treturn \"missing intrinsic: \" + err.Name\n}\n"
  },
  {
    "path": "transform/gc.go",
    "content": "package transform\n\nimport (\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// This is somewhat ugly to access through the API.\n// https://github.com/llvm/llvm-project/blob/94ebcfd16dac67486bae624f74e1c5c789448bae/llvm/include/llvm/Support/ModRef.h#L62\n// https://github.com/llvm/llvm-project/blob/94ebcfd16dac67486bae624f74e1c5c789448bae/llvm/include/llvm/Support/ModRef.h#L87\nconst shiftExcludeArgMem = 2\n\n// MakeGCStackSlots converts all calls to runtime.trackPointer to explicit\n// stores to stack slots that are scannable by the GC.\nfunc MakeGCStackSlots(mod llvm.Module) bool {\n\t// Check whether there are allocations at all.\n\talloc := mod.NamedFunction(\"runtime.alloc\")\n\tif alloc.IsNil() {\n\t\t// Nothing to. Make sure all remaining bits and pieces for stack\n\t\t// chains are neutralized.\n\t\tfor _, call := range getUses(mod.NamedFunction(\"runtime.trackPointer\")) {\n\t\t\tcall.EraseFromParentAsInstruction()\n\t\t}\n\t\tstackChainStart := mod.NamedGlobal(\"runtime.stackChainStart\")\n\t\tif !stackChainStart.IsNil() {\n\t\t\tstackChainStart.SetLinkage(llvm.InternalLinkage)\n\t\t\tstackChainStart.SetInitializer(llvm.ConstNull(stackChainStart.GlobalValueType()))\n\t\t\tstackChainStart.SetGlobalConstant(true)\n\t\t}\n\t\treturn false\n\t}\n\n\ttrackPointer := mod.NamedFunction(\"runtime.trackPointer\")\n\tif trackPointer.IsNil() || trackPointer.FirstUse().IsNil() {\n\t\treturn false // nothing to do\n\t}\n\n\tctx := mod.Context()\n\tbuilder := ctx.NewBuilder()\n\tdefer builder.Dispose()\n\ttargetData := llvm.NewTargetData(mod.DataLayout())\n\tdefer targetData.Dispose()\n\tuintptrType := ctx.IntType(targetData.PointerSize() * 8)\n\n\t// All functions that call runtime.alloc needs stack objects.\n\ttrackFuncs := map[llvm.Value]struct{}{}\n\tmarkParentFunctions(trackFuncs, alloc)\n\n\t// External functions may indirectly suspend the goroutine or perform a heap allocation.\n\t// Their callers should get stack objects.\n\tmemAttr := llvm.AttributeKindID(\"memory\")\n\tfor fn := mod.FirstFunction(); !fn.IsNil(); fn = llvm.NextFunction(fn) {\n\t\tif _, ok := trackFuncs[fn]; ok {\n\t\t\tcontinue // already found\n\t\t}\n\t\tif !fn.FirstBasicBlock().IsNil() {\n\t\t\t// This is not an external function.\n\t\t\tcontinue\n\t\t}\n\t\tif fn == trackPointer {\n\t\t\t// Manually exclude trackPointer.\n\t\t\tcontinue\n\t\t}\n\n\t\tmem := fn.GetEnumFunctionAttribute(memAttr)\n\t\tif !mem.IsNil() && mem.GetEnumValue()>>shiftExcludeArgMem == 0 {\n\t\t\t// This does not access non-argument memory.\n\t\t\t// Exclude it.\n\t\t\tcontinue\n\t\t}\n\n\t\t// The callers need stack objects.\n\t\tmarkParentFunctions(trackFuncs, fn)\n\t}\n\n\t// Look at all other functions to see whether they contain function pointer\n\t// calls.\n\t// This takes less than 5ms for ~100kB of WebAssembly but would perhaps be\n\t// faster when written in C++ (to avoid the CGo overhead).\n\tfor fn := mod.FirstFunction(); !fn.IsNil(); fn = llvm.NextFunction(fn) {\n\t\tif _, ok := trackFuncs[fn]; ok {\n\t\t\tcontinue // already found\n\t\t}\n\n\tscanBody:\n\t\tfor bb := fn.FirstBasicBlock(); !bb.IsNil(); bb = llvm.NextBasicBlock(bb) {\n\t\t\tfor call := bb.FirstInstruction(); !call.IsNil(); call = llvm.NextInstruction(call) {\n\t\t\t\tif call.IsACallInst().IsNil() {\n\t\t\t\t\tcontinue // only looking at calls\n\t\t\t\t}\n\t\t\t\tcalled := call.CalledValue()\n\t\t\t\tif !called.IsAFunction().IsNil() {\n\t\t\t\t\tcontinue // only looking for function pointers\n\t\t\t\t}\n\t\t\t\ttrackFuncs[fn] = struct{}{}\n\t\t\t\tmarkParentFunctions(trackFuncs, fn)\n\t\t\t\tbreak scanBody\n\t\t\t}\n\t\t}\n\t}\n\n\t// Collect some variables used below in the loop.\n\tstackChainStart := mod.NamedGlobal(\"runtime.stackChainStart\")\n\tif stackChainStart.IsNil() {\n\t\t// This may be reached in a weird scenario where we call runtime.alloc but the garbage collector is unreachable.\n\t\t// This can be accomplished by allocating 0 bytes.\n\t\t// There is no point in tracking anything.\n\t\tfor _, use := range getUses(trackPointer) {\n\t\t\tuse.EraseFromParentAsInstruction()\n\t\t}\n\t\treturn false\n\t}\n\tstackChainStart.SetLinkage(llvm.InternalLinkage)\n\tstackChainStartType := stackChainStart.GlobalValueType()\n\tstackChainStart.SetInitializer(llvm.ConstNull(stackChainStartType))\n\n\t// Iterate until runtime.trackPointer has no uses left.\n\tfor use := trackPointer.FirstUse(); !use.IsNil(); use = trackPointer.FirstUse() {\n\t\t// Pick the first use of runtime.trackPointer.\n\t\tcall := use.User()\n\t\tif call.IsACallInst().IsNil() {\n\t\t\tpanic(\"expected runtime.trackPointer use to be a call\")\n\t\t}\n\n\t\t// Pick the parent function.\n\t\tfn := call.InstructionParent().Parent()\n\n\t\tif _, ok := trackFuncs[fn]; !ok {\n\t\t\t// This function nor any of the functions it calls (recursively)\n\t\t\t// allocate anything from the heap, so it will not trigger a garbage\n\t\t\t// collection cycle. Thus, it does not need to track local pointer\n\t\t\t// values.\n\t\t\t// This is a useful optimization but not as big as you might guess,\n\t\t\t// as described above (it avoids stack objects for ~12% of\n\t\t\t// functions).\n\t\t\tcall.EraseFromParentAsInstruction()\n\t\t\tcontinue\n\t\t}\n\n\t\t// Find all calls to runtime.trackPointer in this function.\n\t\tvar calls []llvm.Value\n\t\tvar returns []llvm.Value\n\t\tfor bb := fn.FirstBasicBlock(); !bb.IsNil(); bb = llvm.NextBasicBlock(bb) {\n\t\t\tfor inst := bb.FirstInstruction(); !inst.IsNil(); inst = llvm.NextInstruction(inst) {\n\t\t\t\tswitch inst.InstructionOpcode() {\n\t\t\t\tcase llvm.Call:\n\t\t\t\t\tif inst.CalledValue() == trackPointer {\n\t\t\t\t\t\tcalls = append(calls, inst)\n\t\t\t\t\t}\n\t\t\t\tcase llvm.Ret:\n\t\t\t\t\treturns = append(returns, inst)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Determine what to do with each call.\n\t\tvar pointers []llvm.Value\n\t\tfor _, call := range calls {\n\t\t\tptr := call.Operand(0)\n\t\t\tcall.EraseFromParentAsInstruction()\n\n\t\t\t// Some trivial optimizations.\n\t\t\tif ptr.IsAInstruction().IsNil() {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tswitch ptr.InstructionOpcode() {\n\t\t\tcase llvm.GetElementPtr:\n\t\t\t\t// Check for all zero offsets.\n\t\t\t\t// Sometimes LLVM rewrites bitcasts to zero-index GEPs, and we still need to track the GEP.\n\t\t\t\tn := ptr.OperandsCount()\n\t\t\t\tvar hasOffset bool\n\t\t\t\tfor i := 1; i < n; i++ {\n\t\t\t\t\toffset := ptr.Operand(i)\n\t\t\t\t\tif offset.IsAConstantInt().IsNil() || offset.ZExtValue() != 0 {\n\t\t\t\t\t\thasOffset = true\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif hasOffset {\n\t\t\t\t\t// These values do not create new values: the values already\n\t\t\t\t\t// existed locally in this function so must have been tracked\n\t\t\t\t\t// already.\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\tcase llvm.PHI:\n\t\t\t\t// While the value may have already been tracked, it may be overwritten in a loop.\n\t\t\t\t// Therefore, a second copy must be created to ensure that it is tracked over the entirety of its lifetime.\n\t\t\tcase llvm.ExtractValue, llvm.BitCast:\n\t\t\t\t// These instructions do not create new values, but their\n\t\t\t\t// original value may not be tracked. So keep tracking them for\n\t\t\t\t// now.\n\t\t\t\t// With more analysis, it should be possible to optimize a\n\t\t\t\t// significant chunk of these away.\n\t\t\tcase llvm.Call, llvm.Load, llvm.IntToPtr:\n\t\t\t\t// These create new values so must be stored locally. But\n\t\t\t\t// perhaps some of these can be fused when they actually refer\n\t\t\t\t// to the same value.\n\t\t\tdefault:\n\t\t\t\t// Ambiguous. These instructions are uncommon, but perhaps could\n\t\t\t\t// be optimized if needed.\n\t\t\t}\n\n\t\t\tif ptr := stripPointerCasts(ptr); !ptr.IsAAllocaInst().IsNil() {\n\t\t\t\t// Allocas don't need to be tracked because they are allocated\n\t\t\t\t// on the C stack which is scanned separately.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpointers = append(pointers, ptr)\n\t\t}\n\n\t\tif len(pointers) == 0 {\n\t\t\t// This function does not need to keep track of stack pointers.\n\t\t\tcontinue\n\t\t}\n\n\t\t// Determine the type of the required stack slot.\n\t\tfields := []llvm.Type{\n\t\t\tstackChainStartType, // Pointer to parent frame.\n\t\t\tuintptrType,         // Number of elements in this frame.\n\t\t}\n\t\tfor _, ptr := range pointers {\n\t\t\tfields = append(fields, ptr.Type())\n\t\t}\n\t\tstackObjectType := ctx.StructType(fields, false)\n\n\t\t// Create the stack object at the function entry.\n\t\tbuilder.SetInsertPointBefore(fn.EntryBasicBlock().FirstInstruction())\n\t\tstackObject := builder.CreateAlloca(stackObjectType, \"gc.stackobject\")\n\t\tinitialStackObject := llvm.ConstNull(stackObjectType)\n\t\tnumSlots := (targetData.TypeAllocSize(stackObjectType) - uint64(targetData.PointerSize())*2) / uint64(targetData.ABITypeAlignment(uintptrType))\n\t\tnumSlotsValue := llvm.ConstInt(uintptrType, numSlots, false)\n\t\tinitialStackObject = builder.CreateInsertValue(initialStackObject, numSlotsValue, 1, \"\")\n\t\tbuilder.CreateStore(initialStackObject, stackObject)\n\n\t\t// Update stack start.\n\t\tparent := builder.CreateLoad(stackChainStartType, stackChainStart, \"\")\n\t\tgep := builder.CreateGEP(stackObjectType, stackObject, []llvm.Value{\n\t\t\tllvm.ConstInt(ctx.Int32Type(), 0, false),\n\t\t\tllvm.ConstInt(ctx.Int32Type(), 0, false),\n\t\t}, \"\")\n\t\tbuilder.CreateStore(parent, gep)\n\t\tbuilder.CreateStore(stackObject, stackChainStart)\n\n\t\t// Do a store to the stack object after each new pointer that is created.\n\t\tpointerStores := make(map[llvm.Value]struct{})\n\t\tfor i, ptr := range pointers {\n\t\t\t// Insert the store after the pointer value is created.\n\t\t\tinsertionPoint := llvm.NextInstruction(ptr)\n\t\t\tfor !insertionPoint.IsAPHINode().IsNil() {\n\t\t\t\t// PHI nodes are required to be at the start of the block.\n\t\t\t\t// Insert after the last PHI node.\n\t\t\t\tinsertionPoint = llvm.NextInstruction(insertionPoint)\n\t\t\t}\n\t\t\tbuilder.SetInsertPointBefore(insertionPoint)\n\n\t\t\t// Extract a pointer to the appropriate section of the stack object.\n\t\t\tgep := builder.CreateGEP(stackObjectType, stackObject, []llvm.Value{\n\t\t\t\tllvm.ConstInt(ctx.Int32Type(), 0, false),\n\t\t\t\tllvm.ConstInt(ctx.Int32Type(), uint64(2+i), false),\n\t\t\t}, \"\")\n\n\t\t\t// Store the pointer into the stack slot.\n\t\t\tstore := builder.CreateStore(ptr, gep)\n\t\t\tpointerStores[store] = struct{}{}\n\t\t}\n\n\t\t// Make sure this stack object is popped from the linked list of stack\n\t\t// objects at return.\n\t\tfor _, ret := range returns {\n\t\t\t// Check for any tail calls at this return.\n\t\t\tprev := llvm.PrevInstruction(ret)\n\t\t\tif !prev.IsNil() && !prev.IsABitCastInst().IsNil() {\n\t\t\t\t// A bitcast can appear before a tail call, so skip backwards more.\n\t\t\t\tprev = llvm.PrevInstruction(prev)\n\t\t\t}\n\t\t\tif !prev.IsNil() && !prev.IsACallInst().IsNil() {\n\t\t\t\t// This is no longer a tail call.\n\t\t\t\tprev.SetTailCall(false)\n\t\t\t}\n\t\t\tbuilder.SetInsertPointBefore(ret)\n\t\t\tbuilder.CreateStore(parent, stackChainStart)\n\t\t}\n\t}\n\n\treturn true\n}\n\n// markParentFunctions traverses all parent function calls (recursively) and\n// adds them to the set of marked functions. It only considers function calls:\n// any other uses of such a function is ignored.\nfunc markParentFunctions(marked map[llvm.Value]struct{}, fn llvm.Value) {\n\tworklist := []llvm.Value{fn}\n\tfor len(worklist) != 0 {\n\t\tfn := worklist[len(worklist)-1]\n\t\tworklist = worklist[:len(worklist)-1]\n\t\tfor _, use := range getUses(fn) {\n\t\t\tif use.IsACallInst().IsNil() || use.CalledValue() != fn {\n\t\t\t\t// Not the parent function.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tparent := use.InstructionParent().Parent()\n\t\t\tif _, ok := marked[parent]; !ok {\n\t\t\t\tmarked[parent] = struct{}{}\n\t\t\t\tworklist = append(worklist, parent)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "transform/gc_test.go",
    "content": "package transform_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/tinygo-org/tinygo/transform\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\nfunc TestMakeGCStackSlots(t *testing.T) {\n\tt.Parallel()\n\ttestTransform(t, \"testdata/gc-stackslots\", func(mod llvm.Module) {\n\t\ttransform.MakeGCStackSlots(mod)\n\t})\n}\n"
  },
  {
    "path": "transform/interface-lowering.go",
    "content": "package transform\n\n// This file provides function to lower interface intrinsics to their final LLVM\n// form, optimizing them in the process.\n//\n// During SSA construction, the following pseudo-call is created (see\n// src/runtime/interface.go):\n//     runtime.typeAssert(typecode, assertedType)\n// Additionally, interface type asserts and interface invoke functions are\n// declared but not defined, so the optimizer will leave them alone.\n//\n// This pass lowers these functions to their final form:\n//\n// typeAssert:\n//     Replaced with an icmp instruction so it can be directly used in a type\n//     switch.\n//\n// interface type assert:\n//     These functions are defined by creating a big type switch over all the\n//     concrete types implementing this interface.\n//\n// interface invoke:\n//     These functions are defined with a similar type switch, but instead of\n//     checking for the appropriate type, these functions will call the\n//     underlying method instead.\n//\n// Note that this way of implementing interfaces is very different from how the\n// main Go compiler implements them. For more details on how the main Go\n// compiler does it: https://research.swtch.com/interfaces\n\nimport (\n\t\"sort\"\n\t\"strings\"\n\n\t\"github.com/tinygo-org/tinygo/compileopts\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// signatureInfo is a Go signature of an interface method. It does not represent\n// any method in particular.\ntype signatureInfo struct {\n\tname       string\n\tmethods    []*methodInfo\n\tinterfaces []*interfaceInfo\n}\n\n// methodInfo describes a single method on a concrete type.\ntype methodInfo struct {\n\t*signatureInfo\n\tfunction llvm.Value\n}\n\n// typeInfo describes a single concrete Go type, which can be a basic or a named\n// type. If it is a named type, it may have methods.\ntype typeInfo struct {\n\tname        string\n\ttypecode    llvm.Value\n\ttypecodeGEP llvm.Value\n\tmethodSet   llvm.Value\n\tmethods     []*methodInfo\n}\n\n// getMethod looks up the method on this type with the given signature and\n// returns it. The method must exist on this type, otherwise getMethod will\n// panic.\nfunc (t *typeInfo) getMethod(signature *signatureInfo) *methodInfo {\n\tfor _, method := range t.methods {\n\t\tif method.signatureInfo == signature {\n\t\t\treturn method\n\t\t}\n\t}\n\tpanic(\"could not find method\")\n}\n\n// interfaceInfo keeps information about a Go interface type, including all\n// methods it has.\ntype interfaceInfo struct {\n\tname       string                    // \"tinygo-methods\" attribute\n\tsignatures map[string]*signatureInfo // method set\n\ttypes      []*typeInfo               // types this interface implements\n}\n\n// lowerInterfacesPass keeps state related to the interface lowering pass. The\n// pass has been implemented as an object type because of its complexity, but\n// should be seen as a regular function call (see LowerInterfaces).\ntype lowerInterfacesPass struct {\n\tmod         llvm.Module\n\tconfig      *compileopts.Config\n\tbuilder     llvm.Builder\n\tdibuilder   *llvm.DIBuilder\n\tdifiles     map[string]llvm.Metadata\n\tctx         llvm.Context\n\tuintptrType llvm.Type\n\ttargetData  llvm.TargetData\n\tptrType     llvm.Type\n\ttypes       map[string]*typeInfo\n\tsignatures  map[string]*signatureInfo\n\tinterfaces  map[string]*interfaceInfo\n}\n\n// LowerInterfaces lowers all intermediate interface calls and globals that are\n// emitted by the compiler as higher-level intrinsics. They need some lowering\n// before LLVM can work on them. This is done so that a few cleanup passes can\n// run before assigning the final type codes.\nfunc LowerInterfaces(mod llvm.Module, config *compileopts.Config) error {\n\tctx := mod.Context()\n\ttargetData := llvm.NewTargetData(mod.DataLayout())\n\tdefer targetData.Dispose()\n\tp := &lowerInterfacesPass{\n\t\tmod:         mod,\n\t\tconfig:      config,\n\t\tbuilder:     ctx.NewBuilder(),\n\t\tctx:         ctx,\n\t\ttargetData:  targetData,\n\t\tuintptrType: mod.Context().IntType(targetData.PointerSize() * 8),\n\t\tptrType:     llvm.PointerType(ctx.Int8Type(), 0),\n\t\ttypes:       make(map[string]*typeInfo),\n\t\tsignatures:  make(map[string]*signatureInfo),\n\t\tinterfaces:  make(map[string]*interfaceInfo),\n\t}\n\tdefer p.builder.Dispose()\n\n\tif config.Debug() {\n\t\tp.dibuilder = llvm.NewDIBuilder(mod)\n\t\tdefer p.dibuilder.Destroy()\n\t\tdefer p.dibuilder.Finalize()\n\t\tp.difiles = make(map[string]llvm.Metadata)\n\t}\n\n\treturn p.run()\n}\n\n// run runs the pass itself.\nfunc (p *lowerInterfacesPass) run() error {\n\tif p.dibuilder != nil {\n\t\tp.dibuilder.CreateCompileUnit(llvm.DICompileUnit{\n\t\t\tLanguage:  0xb, // DW_LANG_C99 (0xc, off-by-one?)\n\t\t\tFile:      \"<unknown>\",\n\t\t\tDir:       \"\",\n\t\t\tProducer:  \"TinyGo\",\n\t\t\tOptimized: true,\n\t\t})\n\t}\n\n\t// Collect all type codes.\n\tfor global := p.mod.FirstGlobal(); !global.IsNil(); global = llvm.NextGlobal(global) {\n\t\tif strings.HasPrefix(global.Name(), \"reflect/types.type:\") {\n\t\t\t// Retrieve Go type information based on an opaque global variable.\n\t\t\t// Only the name of the global is relevant, the object itself is\n\t\t\t// discarded afterwards.\n\t\t\tname := strings.TrimPrefix(global.Name(), \"reflect/types.type:\")\n\t\t\tif _, ok := p.types[name]; !ok {\n\t\t\t\tt := &typeInfo{\n\t\t\t\t\tname:     name,\n\t\t\t\t\ttypecode: global,\n\t\t\t\t}\n\t\t\t\tp.types[name] = t\n\t\t\t\tinitializer := global.Initializer()\n\t\t\t\tfirstField := p.builder.CreateExtractValue(initializer, 0, \"\")\n\t\t\t\tif firstField.Type() != p.ctx.Int8Type() {\n\t\t\t\t\t// This type has a method set at index 0. Change the GEP to\n\t\t\t\t\t// point to index 1 (the meta byte).\n\t\t\t\t\tt.typecodeGEP = llvm.ConstGEP(global.GlobalValueType(), global, []llvm.Value{\n\t\t\t\t\t\tllvm.ConstInt(p.ctx.Int32Type(), 0, false),\n\t\t\t\t\t\tllvm.ConstInt(p.ctx.Int32Type(), 1, false),\n\t\t\t\t\t})\n\t\t\t\t\tmethodSet := stripPointerCasts(firstField)\n\t\t\t\t\tif !strings.HasSuffix(methodSet.Name(), \"$methodset\") {\n\t\t\t\t\t\tpanic(\"expected method set\")\n\t\t\t\t\t}\n\t\t\t\t\tp.addTypeMethods(t, methodSet)\n\t\t\t\t} else {\n\t\t\t\t\t// This type has no method set.\n\t\t\t\t\tt.typecodeGEP = llvm.ConstGEP(global.GlobalValueType(), global, []llvm.Value{\n\t\t\t\t\t\tllvm.ConstInt(p.ctx.Int32Type(), 0, false),\n\t\t\t\t\t\tllvm.ConstInt(p.ctx.Int32Type(), 0, false),\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Find all interface type asserts and interface method thunks.\n\tvar interfaceAssertFunctions []llvm.Value\n\tvar interfaceInvokeFunctions []llvm.Value\n\tfor fn := p.mod.FirstFunction(); !fn.IsNil(); fn = llvm.NextFunction(fn) {\n\t\tmethodsAttr := fn.GetStringAttributeAtIndex(-1, \"tinygo-methods\")\n\t\tif methodsAttr.IsNil() {\n\t\t\tcontinue\n\t\t}\n\t\tif !hasUses(fn) {\n\t\t\t// Don't bother defining this function.\n\t\t\tcontinue\n\t\t}\n\t\tp.addInterface(methodsAttr.GetStringValue())\n\t\tinvokeAttr := fn.GetStringAttributeAtIndex(-1, \"tinygo-invoke\")\n\t\tif invokeAttr.IsNil() {\n\t\t\t// Type assert.\n\t\t\tinterfaceAssertFunctions = append(interfaceAssertFunctions, fn)\n\t\t} else {\n\t\t\t// Interface invoke.\n\t\t\tinterfaceInvokeFunctions = append(interfaceInvokeFunctions, fn)\n\t\t}\n\t}\n\n\t// Find all the interfaces that are implemented per type.\n\tfor _, t := range p.types {\n\t\t// This type has no methods, so don't spend time calculating them.\n\t\tif len(t.methods) == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Pre-calculate a set of signatures that this type has, for easy\n\t\t// lookup/check.\n\t\ttypeSignatureSet := make(map[*signatureInfo]struct{})\n\t\tfor _, method := range t.methods {\n\t\t\ttypeSignatureSet[method.signatureInfo] = struct{}{}\n\t\t}\n\n\t\t// A set of interfaces, mapped from the name to the info.\n\t\t// When the name maps to a nil pointer, one of the methods of this type\n\t\t// exists in the given interface but not all of them so this type\n\t\t// doesn't implement the interface.\n\t\tsatisfiesInterfaces := make(map[string]*interfaceInfo)\n\n\t\tfor _, method := range t.methods {\n\t\t\tfor _, itf := range method.interfaces {\n\t\t\t\tif _, ok := satisfiesInterfaces[itf.name]; ok {\n\t\t\t\t\t// interface already checked with a different method\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t// check whether this interface satisfies this type\n\t\t\t\tsatisfies := true\n\t\t\t\tfor _, itfSignature := range itf.signatures {\n\t\t\t\t\tif _, ok := typeSignatureSet[itfSignature]; !ok {\n\t\t\t\t\t\tsatisfiesInterfaces[itf.name] = nil // does not satisfy\n\t\t\t\t\t\tsatisfies = false\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif !satisfies {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tsatisfiesInterfaces[itf.name] = itf\n\t\t\t}\n\t\t}\n\n\t\t// Add this type to all interfaces that satisfy this type.\n\t\tfor _, itf := range satisfiesInterfaces {\n\t\t\tif itf == nil {\n\t\t\t\t// Interface does not implement this type, but one of the\n\t\t\t\t// methods on this type also exists on the interface.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\titf.types = append(itf.types, t)\n\t\t}\n\t}\n\n\t// Sort all types added to the interfaces.\n\tfor _, itf := range p.interfaces {\n\t\tsort.Slice(itf.types, func(i, j int) bool {\n\t\t\treturn itf.types[i].name > itf.types[j].name\n\t\t})\n\t}\n\n\t// Define all interface invoke thunks.\n\tfor _, fn := range interfaceInvokeFunctions {\n\t\tmethodsAttr := fn.GetStringAttributeAtIndex(-1, \"tinygo-methods\")\n\t\tinvokeAttr := fn.GetStringAttributeAtIndex(-1, \"tinygo-invoke\")\n\t\titf := p.interfaces[methodsAttr.GetStringValue()]\n\t\tsignature := itf.signatures[invokeAttr.GetStringValue()]\n\t\tp.defineInterfaceMethodFunc(fn, itf, signature)\n\t}\n\n\t// Define all interface type assert functions.\n\tfor _, fn := range interfaceAssertFunctions {\n\t\tmethodsAttr := fn.GetStringAttributeAtIndex(-1, \"tinygo-methods\")\n\t\titf := p.interfaces[methodsAttr.GetStringValue()]\n\t\tp.defineInterfaceImplementsFunc(fn, itf)\n\t}\n\n\t// Replace each type assert with an actual type comparison or (if the type\n\t// assert is impossible) the constant false.\n\tllvmFalse := llvm.ConstInt(p.ctx.Int1Type(), 0, false)\n\tfor _, use := range getUses(p.mod.NamedFunction(\"runtime.typeAssert\")) {\n\t\tactualType := use.Operand(0)\n\t\tname := strings.TrimPrefix(use.Operand(1).Name(), \"reflect/types.typeid:\")\n\t\tgepOffset := uint64(0)\n\t\tfor strings.HasPrefix(name, \"pointer:pointer:\") {\n\t\t\t// This is a type like **int, which has the name pointer:pointer:int\n\t\t\t// but is encoded using pointer tagging.\n\t\t\t// Calculate the pointer tag, which is emitted as a GEP instruction.\n\t\t\tname = name[len(\"pointer:\"):]\n\t\t\tgepOffset++\n\t\t}\n\n\t\tif t, ok := p.types[name]; ok {\n\t\t\t// The type exists in the program, so lower to a regular pointer\n\t\t\t// comparison.\n\t\t\tp.builder.SetInsertPointBefore(use)\n\t\t\ttypecodeGEP := t.typecodeGEP\n\t\t\tif gepOffset != 0 {\n\t\t\t\t// This is a tagged pointer.\n\t\t\t\ttypecodeGEP = llvm.ConstInBoundsGEP(p.ctx.Int8Type(), typecodeGEP, []llvm.Value{\n\t\t\t\t\tllvm.ConstInt(p.ctx.Int64Type(), gepOffset, false),\n\t\t\t\t})\n\t\t\t}\n\t\t\tcommaOk := p.builder.CreateICmp(llvm.IntEQ, typecodeGEP, actualType, \"typeassert.ok\")\n\t\t\tuse.ReplaceAllUsesWith(commaOk)\n\t\t} else {\n\t\t\t// The type does not exist in the program, so lower to a constant\n\t\t\t// false. This is trivially further optimized.\n\t\t\t// TODO: eventually it'll be necessary to handle reflect.PtrTo and\n\t\t\t// reflect.New calls which create new types not present in the\n\t\t\t// original program.\n\t\t\tuse.ReplaceAllUsesWith(llvmFalse)\n\t\t}\n\t\tuse.EraseFromParentAsInstruction()\n\t}\n\n\t// Create a sorted list of type names, for predictable iteration.\n\tvar typeNames []string\n\tfor name := range p.types {\n\t\ttypeNames = append(typeNames, name)\n\t}\n\tsort.Strings(typeNames)\n\n\t// Remove all method sets, which are now unnecessary and inhibit later\n\t// optimizations if they are left in place.\n\tzero := llvm.ConstInt(p.ctx.Int32Type(), 0, false)\n\tfor _, name := range typeNames {\n\t\tt := p.types[name]\n\t\tif !t.methodSet.IsNil() {\n\t\t\tinitializer := t.typecode.Initializer()\n\t\t\tvar newInitializerFields []llvm.Value\n\t\t\tfor i := 1; i < initializer.Type().StructElementTypesCount(); i++ {\n\t\t\t\tnewInitializerFields = append(newInitializerFields, p.builder.CreateExtractValue(initializer, i, \"\"))\n\t\t\t}\n\t\t\tnewInitializer := p.ctx.ConstStruct(newInitializerFields, false)\n\t\t\ttypecodeName := t.typecode.Name()\n\t\t\tnewGlobal := llvm.AddGlobal(p.mod, newInitializer.Type(), typecodeName+\".tmp\")\n\t\t\tnewGlobal.SetInitializer(newInitializer)\n\t\t\tnewGlobal.SetLinkage(t.typecode.Linkage())\n\t\t\tnewGlobal.SetGlobalConstant(true)\n\t\t\tnewGlobal.SetAlignment(t.typecode.Alignment())\n\t\t\tfor _, use := range getUses(t.typecode) {\n\t\t\t\tif !use.IsAConstantExpr().IsNil() {\n\t\t\t\t\topcode := use.Opcode()\n\t\t\t\t\tif opcode == llvm.GetElementPtr && use.OperandsCount() == 3 {\n\t\t\t\t\t\tif use.Operand(1).ZExtValue() == 0 && use.Operand(2).ZExtValue() == 1 {\n\t\t\t\t\t\t\tgep := p.builder.CreateInBoundsGEP(newGlobal.GlobalValueType(), newGlobal, []llvm.Value{zero, zero}, \"\")\n\t\t\t\t\t\t\tuse.ReplaceAllUsesWith(gep)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Fallback.\n\t\t\tif hasUses(t.typecode) {\n\t\t\t\tnegativeOffset := -int64(p.targetData.TypeAllocSize(p.ptrType))\n\t\t\t\tgep := p.builder.CreateInBoundsGEP(p.ctx.Int8Type(), newGlobal, []llvm.Value{llvm.ConstInt(p.ctx.Int32Type(), uint64(negativeOffset), true)}, \"\")\n\t\t\t\tt.typecode.ReplaceAllUsesWith(gep)\n\t\t\t}\n\t\t\tt.typecode.EraseFromParentAsGlobal()\n\t\t\tnewGlobal.SetName(typecodeName)\n\t\t\tt.typecode = newGlobal\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// addTypeMethods reads the method set of the given type info struct. It\n// retrieves the signatures and the references to the method functions\n// themselves for later type<->interface matching.\nfunc (p *lowerInterfacesPass) addTypeMethods(t *typeInfo, methodSet llvm.Value) {\n\tif !t.methodSet.IsNil() {\n\t\t// no methods or methods already read\n\t\treturn\n\t}\n\n\t// This type has methods, collect all methods of this type.\n\tt.methodSet = methodSet\n\tset := methodSet.Initializer() // get value from global\n\tsignatures := p.builder.CreateExtractValue(set, 1, \"\")\n\twrappers := p.builder.CreateExtractValue(set, 2, \"\")\n\tnumMethods := signatures.Type().ArrayLength()\n\tfor i := 0; i < numMethods; i++ {\n\t\tsignatureGlobal := p.builder.CreateExtractValue(signatures, i, \"\")\n\t\tfunction := p.builder.CreateExtractValue(wrappers, i, \"\")\n\t\tfunction = stripPointerCasts(function) // strip bitcasts\n\t\tsignatureName := signatureGlobal.Name()\n\t\tsignature := p.getSignature(signatureName)\n\t\tmethod := &methodInfo{\n\t\t\tfunction:      function,\n\t\t\tsignatureInfo: signature,\n\t\t}\n\t\tsignature.methods = append(signature.methods, method)\n\t\tt.methods = append(t.methods, method)\n\t}\n}\n\n// addInterface reads information about an interface, which is the\n// fully-qualified name and the signatures of all methods it has.\nfunc (p *lowerInterfacesPass) addInterface(methodsString string) {\n\tif _, ok := p.interfaces[methodsString]; ok {\n\t\treturn\n\t}\n\tt := &interfaceInfo{\n\t\tname:       methodsString,\n\t\tsignatures: make(map[string]*signatureInfo),\n\t}\n\tp.interfaces[methodsString] = t\n\tfor _, method := range strings.Split(methodsString, \"; \") {\n\t\tsignature := p.getSignature(method)\n\t\tsignature.interfaces = append(signature.interfaces, t)\n\t\tt.signatures[method] = signature\n\t}\n}\n\n// getSignature returns a new *signatureInfo, creating it if it doesn't already\n// exist.\nfunc (p *lowerInterfacesPass) getSignature(name string) *signatureInfo {\n\tif _, ok := p.signatures[name]; !ok {\n\t\tp.signatures[name] = &signatureInfo{\n\t\t\tname: name,\n\t\t}\n\t}\n\treturn p.signatures[name]\n}\n\n// defineInterfaceImplementsFunc defines the interface type assert function. It\n// checks whether the given interface type (passed as an argument) is one of the\n// types it implements.\n//\n// The type match is implemented using an if/else chain over all possible types.\n// This if/else chain is easily converted to a big switch over all possible\n// types by the LLVM simplifycfg pass.\nfunc (p *lowerInterfacesPass) defineInterfaceImplementsFunc(fn llvm.Value, itf *interfaceInfo) {\n\t// Create the function and function signature.\n\tfn.Param(0).SetName(\"actualType\")\n\tfn.SetLinkage(llvm.InternalLinkage)\n\tfn.SetUnnamedAddr(true)\n\tAddStandardAttributes(fn, p.config)\n\n\t// Start the if/else chain at the entry block.\n\tentry := p.ctx.AddBasicBlock(fn, \"entry\")\n\tthenBlock := p.ctx.AddBasicBlock(fn, \"then\")\n\tp.builder.SetInsertPointAtEnd(entry)\n\n\tif p.dibuilder != nil {\n\t\tdifile := p.getDIFile(\"<Go interface assert>\")\n\t\tdiFuncType := p.dibuilder.CreateSubroutineType(llvm.DISubroutineType{\n\t\t\tFile: difile,\n\t\t})\n\t\tdifunc := p.dibuilder.CreateFunction(difile, llvm.DIFunction{\n\t\t\tName:         \"(Go interface assert)\",\n\t\t\tFile:         difile,\n\t\t\tLine:         0,\n\t\t\tType:         diFuncType,\n\t\t\tLocalToUnit:  true,\n\t\t\tIsDefinition: true,\n\t\t\tScopeLine:    0,\n\t\t\tFlags:        llvm.FlagPrototyped,\n\t\t\tOptimized:    true,\n\t\t})\n\t\tfn.SetSubprogram(difunc)\n\t\tp.builder.SetCurrentDebugLocation(0, 0, difunc, llvm.Metadata{})\n\t}\n\n\t// Iterate over all possible types.  Each iteration creates a new branch\n\t// either to the 'then' block (success) or the .next block, for the next\n\t// check.\n\tactualType := fn.Param(0)\n\tfor _, typ := range itf.types {\n\t\tnextBlock := p.ctx.AddBasicBlock(fn, typ.name+\".next\")\n\t\tcmp := p.builder.CreateICmp(llvm.IntEQ, actualType, typ.typecodeGEP, typ.name+\".icmp\")\n\t\tp.builder.CreateCondBr(cmp, thenBlock, nextBlock)\n\t\tp.builder.SetInsertPointAtEnd(nextBlock)\n\t}\n\n\t// The builder is now inserting at the last *.next block.  Once we reach\n\t// this point, all types have been checked so the type assert will have\n\t// failed.\n\tp.builder.CreateRet(llvm.ConstInt(p.ctx.Int1Type(), 0, false))\n\n\t// Fill 'then' block (type assert was successful).\n\tp.builder.SetInsertPointAtEnd(thenBlock)\n\tp.builder.CreateRet(llvm.ConstInt(p.ctx.Int1Type(), 1, false))\n}\n\n// defineInterfaceMethodFunc defines this thunk by calling the concrete method\n// of the type that implements this interface.\n//\n// Matching the actual type is implemented using an if/else chain over all\n// possible types.  This is later converted to a switch statement by the LLVM\n// simplifycfg pass.\nfunc (p *lowerInterfacesPass) defineInterfaceMethodFunc(fn llvm.Value, itf *interfaceInfo, signature *signatureInfo) {\n\tcontext := fn.LastParam()\n\tactualType := llvm.PrevParam(context)\n\treturnType := fn.GlobalValueType().ReturnType()\n\tcontext.SetName(\"context\")\n\tactualType.SetName(\"actualType\")\n\tfn.SetLinkage(llvm.InternalLinkage)\n\tfn.SetUnnamedAddr(true)\n\tAddStandardAttributes(fn, p.config)\n\n\t// Collect the params that will be passed to the functions to call.\n\t// These params exclude the receiver (which may actually consist of multiple\n\t// parts).\n\tparams := make([]llvm.Value, fn.ParamsCount()-3)\n\tfor i := range params {\n\t\tparams[i] = fn.Param(i + 1)\n\t}\n\tparams = append(params,\n\t\tllvm.Undef(p.ptrType),\n\t)\n\n\t// Start chain in the entry block.\n\tentry := p.ctx.AddBasicBlock(fn, \"entry\")\n\tp.builder.SetInsertPointAtEnd(entry)\n\n\tif p.dibuilder != nil {\n\t\tdifile := p.getDIFile(\"<Go interface method>\")\n\t\tdiFuncType := p.dibuilder.CreateSubroutineType(llvm.DISubroutineType{\n\t\t\tFile: difile,\n\t\t})\n\t\tdifunc := p.dibuilder.CreateFunction(difile, llvm.DIFunction{\n\t\t\tName:         \"(Go interface method)\",\n\t\t\tFile:         difile,\n\t\t\tLine:         0,\n\t\t\tType:         diFuncType,\n\t\t\tLocalToUnit:  true,\n\t\t\tIsDefinition: true,\n\t\t\tScopeLine:    0,\n\t\t\tFlags:        llvm.FlagPrototyped,\n\t\t\tOptimized:    true,\n\t\t})\n\t\tfn.SetSubprogram(difunc)\n\t\tp.builder.SetCurrentDebugLocation(0, 0, difunc, llvm.Metadata{})\n\t}\n\n\t// Define all possible functions that can be called.\n\tfor _, typ := range itf.types {\n\t\t// Create type check (if/else).\n\t\tbb := p.ctx.AddBasicBlock(fn, typ.name)\n\t\tnext := p.ctx.AddBasicBlock(fn, typ.name+\".next\")\n\t\tcmp := p.builder.CreateICmp(llvm.IntEQ, actualType, typ.typecodeGEP, typ.name+\".icmp\")\n\t\tp.builder.CreateCondBr(cmp, bb, next)\n\n\t\t// The function we will redirect to when the interface has this type.\n\t\tfunction := typ.getMethod(signature).function\n\n\t\tp.builder.SetInsertPointAtEnd(bb)\n\t\treceiver := fn.FirstParam()\n\n\t\tparamTypes := []llvm.Type{receiver.Type()}\n\t\tfor _, param := range params {\n\t\t\tparamTypes = append(paramTypes, param.Type())\n\t\t}\n\t\tfunctionType := llvm.FunctionType(returnType, paramTypes, false)\n\t\tretval := p.builder.CreateCall(functionType, function, append([]llvm.Value{receiver}, params...), \"\")\n\t\tif retval.Type().TypeKind() == llvm.VoidTypeKind {\n\t\t\tp.builder.CreateRetVoid()\n\t\t} else {\n\t\t\tp.builder.CreateRet(retval)\n\t\t}\n\n\t\t// Start next comparison in the 'next' block (which is jumped to when\n\t\t// the type doesn't match).\n\t\tp.builder.SetInsertPointAtEnd(next)\n\t}\n\n\t// The builder now points to the last *.then block, after all types have\n\t// been checked. Call runtime.nilPanic here.\n\t// The only other possible value remaining is nil for nil interfaces. We\n\t// could panic with a different message here such as \"nil interface\" but\n\t// that would increase code size and \"nil panic\" is close enough. Most\n\t// importantly, it avoids undefined behavior when accidentally calling a\n\t// method on a nil interface.\n\tnilPanic := p.mod.NamedFunction(\"runtime.nilPanic\")\n\tp.builder.CreateCall(nilPanic.GlobalValueType(), nilPanic, []llvm.Value{\n\t\tllvm.Undef(p.ptrType),\n\t}, \"\")\n\tp.builder.CreateUnreachable()\n}\n\nfunc (p *lowerInterfacesPass) getDIFile(file string) llvm.Metadata {\n\tdifile, ok := p.difiles[file]\n\tif !ok {\n\t\tdifile = p.dibuilder.CreateFile(file, \"\")\n\t\tp.difiles[file] = difile\n\t}\n\treturn difile\n}\n"
  },
  {
    "path": "transform/interface-lowering_test.go",
    "content": "package transform_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/tinygo-org/tinygo/transform\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\nfunc TestInterfaceLowering(t *testing.T) {\n\tt.Parallel()\n\ttestTransform(t, \"testdata/interface\", func(mod llvm.Module) {\n\t\terr := transform.LowerInterfaces(mod, defaultTestConfig)\n\t\tif err != nil {\n\t\t\tt.Error(err)\n\t\t}\n\n\t\tpo := llvm.NewPassBuilderOptions()\n\t\tdefer po.Dispose()\n\t\terr = mod.RunPasses(\"globaldce\", llvm.TargetMachine{}, po)\n\t\tif err != nil {\n\t\t\tt.Error(\"failed to run passes:\", err)\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "transform/interrupt.go",
    "content": "package transform\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// LowerInterrupts creates interrupt handlers for the interrupts created by\n// runtime/interrupt.New.\n//\n// The operation is as follows. The compiler creates the following during IR\n// generation:\n//   - calls to runtime/interrupt.callHandlers with an interrupt number.\n//   - runtime/interrupt.handle objects that store the (constant) interrupt ID and\n//     interrupt handler func value.\n//\n// This pass then replaces those callHandlers calls with calls to the actual\n// interrupt handlers. If there are no interrupt handlers for the given call,\n// the interrupt handler is removed. For hardware vectoring, that means that the\n// entire function is removed. For software vectoring, that means that the call\n// is replaced with an 'unreachable' instruction.\n// This might seem like it causes extra overhead, but in fact inlining and const\n// propagation will eliminate most if not all of that.\nfunc LowerInterrupts(mod llvm.Module) []error {\n\tvar errs []error\n\n\tctx := mod.Context()\n\tbuilder := ctx.NewBuilder()\n\tdefer builder.Dispose()\n\n\t// Collect a map of interrupt handle objects. The fact that they still\n\t// exist in the IR indicates that they could not be optimized away,\n\t// therefore we need to make real interrupt handlers for them.\n\thandleMap := map[int64][]llvm.Value{}\n\thandleType := mod.GetTypeByName(\"runtime/interrupt.handle\")\n\tif !handleType.IsNil() {\n\t\tfor global := mod.FirstGlobal(); !global.IsNil(); global = llvm.NextGlobal(global) {\n\t\t\tif global.GlobalValueType() != handleType {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Get the interrupt number from the initializer\n\t\t\tinitializer := global.Initializer()\n\t\t\tinterrupt := builder.CreateExtractValue(initializer, 2, \"\")\n\t\t\tnum := builder.CreateExtractValue(interrupt, 0, \"\").SExtValue()\n\t\t\tpkg := packageFromInterruptHandle(global)\n\n\t\t\thandles, exists := handleMap[num]\n\n\t\t\t// If there is an existing interrupt handler, ensure it is in the same package\n\t\t\t// as the new one.  This is to prevent any assumptions in code that a single\n\t\t\t// compiler pass can see all packages to chain interrupt handlers. When packages are\n\t\t\t// compiled to separate object files, the linker should spot the duplicate symbols\n\t\t\t// for the wrapper function, failing the build.\n\t\t\tif exists && packageFromInterruptHandle(handles[0]) != pkg {\n\t\t\t\terrs = append(errs, errorAt(global,\n\t\t\t\t\tfmt.Sprintf(\"handlers for interrupt %d in multiple packages: %s and %s\",\n\t\t\t\t\t\tnum, pkg, packageFromInterruptHandle(handles[0]))))\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\thandleMap[num] = append(handles, global)\n\t\t}\n\t}\n\n\t// Discover interrupts. The runtime/interrupt.callHandlers call is a\n\t// compiler intrinsic that is replaced with the handlers for the given\n\t// function.\n\tfor _, call := range getUses(mod.NamedFunction(\"runtime/interrupt.callHandlers\")) {\n\t\tif call.IsACallInst().IsNil() {\n\t\t\terrs = append(errs, errorAt(call, \"expected a call to runtime/interrupt.callHandlers?\"))\n\t\t\tcontinue\n\t\t}\n\n\t\tnum := call.Operand(0)\n\t\tif num.IsAConstantInt().IsNil() {\n\t\t\terrs = append(errs, errorAt(call, \"non-constant interrupt number?\"))\n\t\t\tcall.InstructionParent().Parent().Dump()\n\t\t\tcontinue\n\t\t}\n\n\t\thandlers := handleMap[num.SExtValue()]\n\t\tif len(handlers) != 0 {\n\t\t\t// This interrupt has at least one handler.\n\t\t\t// Replace the callHandlers call with (possibly multiple) calls to\n\t\t\t// these handlers.\n\t\t\tbuilder.SetInsertPointBefore(call)\n\t\t\tfor _, handler := range handlers {\n\t\t\t\tinitializer := handler.Initializer()\n\t\t\t\tcontext := builder.CreateExtractValue(initializer, 0, \"\")\n\t\t\t\tfuncPtr := builder.CreateExtractValue(initializer, 1, \"\").Operand(0)\n\t\t\t\tbuilder.CreateCall(funcPtr.GlobalValueType(), funcPtr, []llvm.Value{\n\t\t\t\t\tnum,\n\t\t\t\t\tcontext,\n\t\t\t\t}, \"\")\n\t\t\t}\n\t\t\tcall.EraseFromParentAsInstruction()\n\t\t} else {\n\t\t\t// No handlers. Remove the call.\n\t\t\tfn := call.InstructionParent().Parent()\n\t\t\tif fn.Linkage() == llvm.ExternalLinkage {\n\t\t\t\t// Hardware vectoring. Remove the function entirely (redirecting\n\t\t\t\t// it to the default handler).\n\t\t\t\tfn.ReplaceAllUsesWith(llvm.Undef(fn.Type()))\n\t\t\t\tfn.EraseFromParentAsFunction()\n\t\t\t} else {\n\t\t\t\t// Software vectoring. Erase the instruction and replace it with\n\t\t\t\t// 'unreachable'.\n\t\t\t\tbuilder.SetInsertPointBefore(call)\n\t\t\t\tbuilder.CreateUnreachable()\n\t\t\t\t// Erase all instructions that follow the unreachable\n\t\t\t\t// instruction (which is a block terminator).\n\t\t\t\tinst := call\n\t\t\t\tfor !inst.IsNil() {\n\t\t\t\t\tnext := llvm.NextInstruction(inst)\n\t\t\t\t\tinst.EraseFromParentAsInstruction()\n\t\t\t\t\tinst = next\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Replace all ptrtoint uses of the interrupt handler globals with the real\n\t// interrupt ID.\n\t// This can now be safely done after interrupts have been lowered, doing it\n\t// earlier may result in this interrupt handler being optimized away\n\t// entirely (which is not what we want).\n\tfor num, handlers := range handleMap {\n\t\tfor _, handler := range handlers {\n\t\t\tfor _, user := range getUses(handler) {\n\t\t\t\tif user.IsAConstantExpr().IsNil() || user.Opcode() != llvm.PtrToInt {\n\t\t\t\t\terrs = append(errs, errorAt(handler, \"internal error: expected a ptrtoint\"))\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tuser.ReplaceAllUsesWith(llvm.ConstInt(user.Type(), uint64(num), true))\n\t\t\t}\n\n\t\t\t// The runtime/interrupt.handle struct can finally be removed.\n\t\t\t// It would probably be eliminated anyway by a globaldce pass but it's\n\t\t\t// better to do it now to be sure.\n\t\t\thandler.EraseFromParentAsGlobal()\n\t\t}\n\t}\n\n\t// Remove now-useless runtime/interrupt.use calls. These are used for some\n\t// platforms like AVR that do not need to enable interrupts to use them, so\n\t// need another way to keep them alive.\n\t// After interrupts have been lowered, this call is useless and would cause\n\t// a linker error so must be removed.\n\tfor _, call := range getUses(mod.NamedFunction(\"runtime/interrupt.use\")) {\n\t\tif call.IsACallInst().IsNil() {\n\t\t\terrs = append(errs, errorAt(call, \"internal error: expected call to runtime/interrupt.use\"))\n\t\t\tcontinue\n\t\t}\n\n\t\tcall.EraseFromParentAsInstruction()\n\t}\n\n\treturn errs\n}\n\nfunc packageFromInterruptHandle(handle llvm.Value) string {\n\treturn strings.Split(handle.Name(), \"$\")[0]\n}\n"
  },
  {
    "path": "transform/interrupt_test.go",
    "content": "package transform_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/tinygo-org/tinygo/transform\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\nfunc TestInterruptLowering(t *testing.T) {\n\tt.Parallel()\n\ttestTransform(t, \"testdata/interrupt\", func(mod llvm.Module) {\n\t\terrs := transform.LowerInterrupts(mod)\n\t\tif len(errs) != 0 {\n\t\t\tt.Fail()\n\t\t\tfor _, err := range errs {\n\t\t\t\tt.Error(err)\n\t\t\t}\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "transform/llvm.go",
    "content": "package transform\n\nimport (\n\t\"reflect\"\n\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// Return a list of values (actually, instructions) where this value is used as\n// an operand.\nfunc getUses(value llvm.Value) []llvm.Value {\n\tif value.IsNil() {\n\t\treturn nil\n\t}\n\tvar uses []llvm.Value\n\tuse := value.FirstUse()\n\tfor !use.IsNil() {\n\t\tuses = append(uses, use.User())\n\t\tuse = use.NextUse()\n\t}\n\treturn uses\n}\n\n// hasUses returns whether the given value has any uses. It is equivalent to\n// getUses(value) != nil but faster.\nfunc hasUses(value llvm.Value) bool {\n\tif value.IsNil() {\n\t\treturn false\n\t}\n\treturn !value.FirstUse().IsNil()\n}\n\n// makeGlobalArray creates a new LLVM global with the given name and integers as\n// contents, and returns the global and initializer type.\n// Note that it is left with the default linkage etc., you should set\n// linkage/constant/etc properties yourself.\nfunc makeGlobalArray(mod llvm.Module, bufItf interface{}, name string, elementType llvm.Type) (llvm.Type, llvm.Value) {\n\tbuf := reflect.ValueOf(bufItf)\n\tvar values []llvm.Value\n\tfor i := 0; i < buf.Len(); i++ {\n\t\tch := buf.Index(i).Uint()\n\t\tvalues = append(values, llvm.ConstInt(elementType, ch, false))\n\t}\n\tvalue := llvm.ConstArray(elementType, values)\n\tglobal := llvm.AddGlobal(mod, value.Type(), name)\n\tglobal.SetInitializer(value)\n\treturn value.Type(), global\n}\n\n// getGlobalBytes returns the slice contained in the array of the provided\n// global. It can recover the bytes originally created using makeGlobalArray, if\n// makeGlobalArray was given a byte slice.\n//\n// The builder parameter is only used for constant operations.\nfunc getGlobalBytes(global llvm.Value, builder llvm.Builder) []byte {\n\tvalue := global.Initializer()\n\tbuf := make([]byte, value.Type().ArrayLength())\n\tfor i := range buf {\n\t\tbuf[i] = byte(builder.CreateExtractValue(value, i, \"\").ZExtValue())\n\t}\n\treturn buf\n}\n\n// replaceGlobalByteWithArray replaces a global integer type in the module with\n// an integer array, using a GEP to make the types match. It is a convenience\n// function used for creating reflection sidetables, for example.\nfunc replaceGlobalIntWithArray(mod llvm.Module, name string, buf interface{}) llvm.Value {\n\toldGlobal := mod.NamedGlobal(name)\n\tglobalType, global := makeGlobalArray(mod, buf, name+\".tmp\", oldGlobal.GlobalValueType())\n\tgep := llvm.ConstGEP(globalType, global, []llvm.Value{\n\t\tllvm.ConstInt(mod.Context().Int32Type(), 0, false),\n\t\tllvm.ConstInt(mod.Context().Int32Type(), 0, false),\n\t})\n\toldGlobal.ReplaceAllUsesWith(gep)\n\toldGlobal.EraseFromParentAsGlobal()\n\tglobal.SetName(name)\n\treturn global\n}\n\n// stripPointerCasts strips instruction pointer casts (getelementptr and\n// bitcast) and returns the original value without the casts.\nfunc stripPointerCasts(value llvm.Value) llvm.Value {\n\tif !value.IsAConstantExpr().IsNil() {\n\t\tswitch value.Opcode() {\n\t\tcase llvm.GetElementPtr, llvm.BitCast:\n\t\t\treturn stripPointerCasts(value.Operand(0))\n\t\t}\n\t}\n\tif !value.IsAInstruction().IsNil() {\n\t\tswitch value.InstructionOpcode() {\n\t\tcase llvm.GetElementPtr, llvm.BitCast:\n\t\t\treturn stripPointerCasts(value.Operand(0))\n\t\t}\n\t}\n\treturn value\n}\n"
  },
  {
    "path": "transform/maps.go",
    "content": "package transform\n\nimport (\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// OptimizeMaps eliminates created but unused maps.\n//\n// In the future, this should statically allocate created but never modified\n// maps. This has not yet been implemented, however.\nfunc OptimizeMaps(mod llvm.Module) {\n\thashmapMake := mod.NamedFunction(\"runtime.hashmapMake\")\n\tif hashmapMake.IsNil() {\n\t\t// nothing to optimize\n\t\treturn\n\t}\n\n\thashmapBinarySet := mod.NamedFunction(\"runtime.hashmapBinarySet\")\n\thashmapStringSet := mod.NamedFunction(\"runtime.hashmapStringSet\")\n\n\tfor _, makeInst := range getUses(hashmapMake) {\n\t\tupdateInsts := []llvm.Value{}\n\t\tunknownUses := false // are there any uses other than setting a value?\n\n\t\tfor _, use := range getUses(makeInst) {\n\t\t\tif use := use.IsACallInst(); !use.IsNil() {\n\t\t\t\tswitch use.CalledValue() {\n\t\t\t\tcase hashmapBinarySet, hashmapStringSet:\n\t\t\t\t\tupdateInsts = append(updateInsts, use)\n\t\t\t\tdefault:\n\t\t\t\t\tunknownUses = true\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tunknownUses = true\n\t\t\t}\n\t\t}\n\n\t\tif !unknownUses {\n\t\t\t// This map can be entirely removed, as it is only created but never\n\t\t\t// used.\n\t\t\tfor _, inst := range updateInsts {\n\t\t\t\tinst.EraseFromParentAsInstruction()\n\t\t\t}\n\t\t\tmakeInst.EraseFromParentAsInstruction()\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "transform/maps_test.go",
    "content": "package transform_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/tinygo-org/tinygo/transform\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\nfunc TestOptimizeMaps(t *testing.T) {\n\tt.Parallel()\n\ttestTransform(t, \"testdata/maps\", func(mod llvm.Module) {\n\t\t// Run optimization pass.\n\t\ttransform.OptimizeMaps(mod)\n\n\t\t// Run an optimization pass, to clean up the result.\n\t\t// This shows that all code related to the map is really eliminated.\n\t\tpo := llvm.NewPassBuilderOptions()\n\t\tdefer po.Dispose()\n\t\terr := mod.RunPasses(\"dse,adce\", llvm.TargetMachine{}, po)\n\t\tif err != nil {\n\t\t\tt.Error(\"failed to run passes:\", err)\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "transform/optimizer.go",
    "content": "package transform\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"go/token\"\n\t\"os\"\n\n\t\"github.com/tinygo-org/tinygo/compileopts\"\n\t\"github.com/tinygo-org/tinygo/compiler/ircheck\"\n\t\"github.com/tinygo-org/tinygo/compiler/llvmutil\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// OptimizePackage runs optimization passes over the LLVM module for the given\n// Go package.\nfunc OptimizePackage(mod llvm.Module, config *compileopts.Config) {\n\t_, speedLevel, _ := config.OptLevel()\n\n\t// Run TinyGo-specific optimization passes.\n\tif speedLevel > 0 {\n\t\tOptimizeMaps(mod)\n\t}\n}\n\n// Optimize runs a number of optimization and transformation passes over the\n// given module. Some passes are specific to TinyGo, others are generic LLVM\n// passes.\n//\n// Please note that some optimizations are not optional, thus Optimize must\n// always be run before emitting machine code.\nfunc Optimize(mod llvm.Module, config *compileopts.Config) []error {\n\toptLevel, speedLevel, _ := config.OptLevel()\n\n\t// Make sure these functions are kept in tact during TinyGo transformation passes.\n\tfor _, name := range functionsUsedInTransforms {\n\t\tfn := mod.NamedFunction(name)\n\t\tif fn.IsNil() {\n\t\t\tpanic(fmt.Errorf(\"missing core function %q\", name))\n\t\t}\n\t\tfn.SetLinkage(llvm.ExternalLinkage)\n\t}\n\n\t// run a check of all of our code\n\tif config.VerifyIR() {\n\t\terrs := ircheck.Module(mod)\n\t\tif errs != nil {\n\t\t\treturn errs\n\t\t}\n\t}\n\n\tif speedLevel > 0 {\n\t\t// Run some preparatory passes for the Go optimizer.\n\t\tpo := llvm.NewPassBuilderOptions()\n\t\tdefer po.Dispose()\n\t\toptPasses := \"globaldce,globalopt,ipsccp,instcombine<no-verify-fixpoint>,adce,function-attrs\"\n\t\tif llvmutil.Version() < 18 {\n\t\t\t// LLVM 17 doesn't have the no-verify-fixpoint flag.\n\t\t\toptPasses = \"globaldce,globalopt,ipsccp,instcombine,adce,function-attrs\"\n\t\t}\n\t\terr := mod.RunPasses(optPasses, llvm.TargetMachine{}, po)\n\t\tif err != nil {\n\t\t\treturn []error{fmt.Errorf(\"could not build pass pipeline: %w\", err)}\n\t\t}\n\n\t\t// Run TinyGo-specific optimization passes.\n\t\tOptimizeStringToBytes(mod)\n\t\tOptimizeReflectImplements(mod)\n\t\tmaxStackSize := config.MaxStackAlloc()\n\t\tOptimizeAllocs(mod, nil, maxStackSize, nil)\n\t\terr = LowerInterfaces(mod, config)\n\t\tif err != nil {\n\t\t\treturn []error{err}\n\t\t}\n\n\t\terrs := LowerInterrupts(mod)\n\t\tif len(errs) > 0 {\n\t\t\treturn errs\n\t\t}\n\n\t\t// After interfaces are lowered, there are many more opportunities for\n\t\t// interprocedural optimizations. To get them to work, function\n\t\t// attributes have to be updated first.\n\t\terr = mod.RunPasses(optPasses, llvm.TargetMachine{}, po)\n\t\tif err != nil {\n\t\t\treturn []error{fmt.Errorf(\"could not build pass pipeline: %w\", err)}\n\t\t}\n\n\t\t// Run TinyGo-specific interprocedural optimizations.\n\t\tOptimizeAllocs(mod, config.Options.PrintAllocs, maxStackSize, func(pos token.Position, msg string) {\n\t\t\tfmt.Fprintln(os.Stderr, pos.String()+\": \"+msg)\n\t\t})\n\t\tOptimizeStringToBytes(mod)\n\t\tOptimizeStringEqual(mod)\n\n\t} else {\n\t\t// Must be run at any optimization level.\n\t\terr := LowerInterfaces(mod, config)\n\t\tif err != nil {\n\t\t\treturn []error{err}\n\t\t}\n\t\terrs := LowerInterrupts(mod)\n\t\tif len(errs) > 0 {\n\t\t\treturn errs\n\t\t}\n\n\t\t// Clean up some leftover symbols of the previous transformations.\n\t\tpo := llvm.NewPassBuilderOptions()\n\t\tdefer po.Dispose()\n\t\terr = mod.RunPasses(\"globaldce\", llvm.TargetMachine{}, po)\n\t\tif err != nil {\n\t\t\treturn []error{fmt.Errorf(\"could not build pass pipeline: %w\", err)}\n\t\t}\n\t}\n\n\tif config.Scheduler() == \"none\" {\n\t\t// Check for any goroutine starts.\n\t\tif start := mod.NamedFunction(\"internal/task.start\"); !start.IsNil() && len(getUses(start)) > 0 {\n\t\t\terrs := []error{}\n\t\t\tfor _, call := range getUses(start) {\n\t\t\t\terrs = append(errs, errorAt(call, \"attempted to start a goroutine without a scheduler\"))\n\t\t\t}\n\t\t\treturn errs\n\t\t}\n\t}\n\n\tif config.VerifyIR() {\n\t\tif errs := ircheck.Module(mod); errs != nil {\n\t\t\treturn errs\n\t\t}\n\t}\n\tif err := llvm.VerifyModule(mod, llvm.PrintMessageAction); err != nil {\n\t\treturn []error{errors.New(\"optimizations caused a verification failure\")}\n\t}\n\n\t// After TinyGo-specific transforms have finished, undo exporting these functions.\n\tfor _, name := range functionsUsedInTransforms {\n\t\tfn := mod.NamedFunction(name)\n\t\tif fn.IsNil() || fn.IsDeclaration() {\n\t\t\tcontinue\n\t\t}\n\t\tfn.SetLinkage(llvm.InternalLinkage)\n\t}\n\n\t// Run the ThinLTO pre-link passes, meant to be run on each individual\n\t// module. This saves compilation time compared to \"default<#>\" and is meant\n\t// to better match the optimization passes that are happening during\n\t// ThinLTO.\n\tpo := llvm.NewPassBuilderOptions()\n\tdefer po.Dispose()\n\tpasses := fmt.Sprintf(\"thinlto-pre-link<%s>\", optLevel)\n\terr := mod.RunPasses(passes, llvm.TargetMachine{}, po)\n\tif err != nil {\n\t\treturn []error{fmt.Errorf(\"could not build pass pipeline: %w\", err)}\n\t}\n\n\thasGCPass := MakeGCStackSlots(mod)\n\tif hasGCPass {\n\t\tif err := llvm.VerifyModule(mod, llvm.PrintMessageAction); err != nil {\n\t\t\treturn []error{errors.New(\"GC pass caused a verification failure\")}\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// functionsUsedInTransform is a list of function symbols that may be used\n// during TinyGo optimization passes so they have to be marked as external\n// linkage until all TinyGo passes have finished.\nvar functionsUsedInTransforms = []string{\n\t\"runtime.alloc\",\n\t\"runtime.free\",\n\t\"runtime.nilPanic\",\n}\n"
  },
  {
    "path": "transform/rtcalls.go",
    "content": "package transform\n\n// This file implements several small optimizations of runtime and reflect\n// calls.\n\nimport (\n\t\"strings\"\n\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// OptimizeStringToBytes transforms runtime.stringToBytes(...) calls into const\n// []byte slices whenever possible. This optimizes the following pattern:\n//\n//\tw.Write([]byte(\"foo\"))\n//\n// where Write does not store to the slice.\nfunc OptimizeStringToBytes(mod llvm.Module) {\n\tstringToBytes := mod.NamedFunction(\"runtime.stringToBytes\")\n\tif stringToBytes.IsNil() {\n\t\t// nothing to optimize\n\t\treturn\n\t}\n\n\tfor _, call := range getUses(stringToBytes) {\n\t\tstrptr := call.Operand(0)\n\t\tstrlen := call.Operand(1)\n\n\t\t// strptr is always constant because strings are always constant.\n\n\t\tvar pointerUses []llvm.Value\n\t\tcanConvertPointer := true\n\t\tfor _, use := range getUses(call) {\n\t\t\tif use.IsAExtractValueInst().IsNil() {\n\t\t\t\t// Expected an extractvalue, but this is something else.\n\t\t\t\tcanConvertPointer = false\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tswitch use.Type().TypeKind() {\n\t\t\tcase llvm.IntegerTypeKind:\n\t\t\t\t// A length (len or cap). Propagate the length value.\n\t\t\t\t// This can always be done because the byte slice is always the\n\t\t\t\t// same length as the original string.\n\t\t\t\tuse.ReplaceAllUsesWith(strlen)\n\t\t\t\tuse.EraseFromParentAsInstruction()\n\t\t\tcase llvm.PointerTypeKind:\n\t\t\t\t// The string pointer itself.\n\t\t\t\tif !isReadOnly(use) {\n\t\t\t\t\t// There is a store to the byte slice. This means that none\n\t\t\t\t\t// of the pointer uses can't be propagated.\n\t\t\t\t\tcanConvertPointer = false\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\t// It may be that the pointer value can be propagated, if all of\n\t\t\t\t// the pointer uses are readonly.\n\t\t\t\tpointerUses = append(pointerUses, use)\n\t\t\tdefault:\n\t\t\t\t// should not happen\n\t\t\t\tpanic(\"unknown return type of runtime.stringToBytes: \" + use.Type().String())\n\t\t\t}\n\t\t}\n\t\tif canConvertPointer {\n\t\t\t// All pointer uses are readonly, so they can be converted.\n\t\t\tfor _, use := range pointerUses {\n\t\t\t\tuse.ReplaceAllUsesWith(strptr)\n\t\t\t\tuse.EraseFromParentAsInstruction()\n\t\t\t}\n\n\t\t\t// Call to runtime.stringToBytes can be eliminated: both the input\n\t\t\t// and the output is constant.\n\t\t\tcall.EraseFromParentAsInstruction()\n\t\t}\n\t}\n}\n\n// OptimizeStringEqual transforms runtime.stringEqual(...) calls into simple\n// integer comparisons if at least one of the sides of the comparison is zero.\n// Ths converts str == \"\" into len(str) == 0 and \"\" == \"\" into false.\nfunc OptimizeStringEqual(mod llvm.Module) {\n\tstringEqual := mod.NamedFunction(\"runtime.stringEqual\")\n\tif stringEqual.IsNil() {\n\t\t// nothing to optimize\n\t\treturn\n\t}\n\n\tbuilder := mod.Context().NewBuilder()\n\tdefer builder.Dispose()\n\n\tfor _, call := range getUses(stringEqual) {\n\t\tstr1len := call.Operand(1)\n\t\tstr2len := call.Operand(3)\n\n\t\tzero := llvm.ConstInt(str1len.Type(), 0, false)\n\t\tif str1len == zero || str2len == zero {\n\t\t\tbuilder.SetInsertPointBefore(call)\n\t\t\ticmp := builder.CreateICmp(llvm.IntEQ, str1len, str2len, \"\")\n\t\t\tcall.ReplaceAllUsesWith(icmp)\n\t\t\tcall.EraseFromParentAsInstruction()\n\t\t\tcontinue\n\t\t}\n\t}\n}\n\n// OptimizeReflectImplements optimizes the following code:\n//\n//\timplements := someType.Implements(someInterfaceType)\n//\n// where someType is an arbitrary reflect.Type and someInterfaceType is a\n// reflect.Type of interface kind, to the following code:\n//\n//\t_, implements := someType.(interfaceType)\n//\n// if the interface type is known at compile time (that is, someInterfaceType is\n// a LLVM constant aggregate). This optimization is especially important for the\n// encoding/json package, which uses this method.\n//\n// As of this writing, the (reflect.Type).Interface method has not yet been\n// implemented so this optimization is critical for the encoding/json package.\nfunc OptimizeReflectImplements(mod llvm.Module) {\n\timplementsSignature1 := mod.NamedGlobal(\"reflect/methods.Implements(reflect.Type) bool\")\n\timplementsSignature2 := mod.NamedGlobal(\"reflect/methods.Implements(internal/reflectlite.Type) bool\")\n\tif implementsSignature1.IsNil() && implementsSignature2.IsNil() {\n\t\treturn\n\t}\n\n\tbuilder := mod.Context().NewBuilder()\n\tdefer builder.Dispose()\n\n\t// Look up the (reflect.Value).Implements() method.\n\tvar implementsFunc llvm.Value\n\tfor fn := mod.FirstFunction(); !fn.IsNil(); fn = llvm.NextFunction(fn) {\n\t\tattr := fn.GetStringAttributeAtIndex(-1, \"tinygo-invoke\")\n\t\tif attr.IsNil() {\n\t\t\tcontinue\n\t\t}\n\t\tval := attr.GetStringValue()\n\t\tif val == \"reflect/methods.Implements(reflect.Type) bool\" || val == \"reflect/methods.Implements(internal/reflectlite.Type) bool\" {\n\t\t\timplementsFunc = fn\n\t\t\tbreak\n\t\t}\n\t}\n\tif implementsFunc.IsNil() {\n\t\t// Doesn't exist in the program, so nothing to do.\n\t\treturn\n\t}\n\n\tfor _, call := range getUses(implementsFunc) {\n\t\tif call.IsACallInst().IsNil() {\n\t\t\tcontinue\n\t\t}\n\t\tinterfaceType := stripPointerCasts(call.Operand(2))\n\t\tif interfaceType.IsAGlobalVariable().IsNil() {\n\t\t\t// Interface is unknown at compile time. This can't be optimized.\n\t\t\tcontinue\n\t\t}\n\n\t\tif strings.HasPrefix(interfaceType.Name(), \"reflect/types.type:named:\") {\n\t\t\t// Get the underlying type.\n\t\t\tinterfaceType = stripPointerCasts(builder.CreateExtractValue(interfaceType.Initializer(), 3, \"\"))\n\t\t}\n\t\tif !strings.HasPrefix(interfaceType.Name(), \"reflect/types.type:interface:\") {\n\t\t\t// This is an error. The Type passed to Implements should be of\n\t\t\t// interface type. Ignore it here (don't report it), it will be\n\t\t\t// reported at runtime.\n\t\t\tcontinue\n\t\t}\n\t\ttypeAssertFunction := mod.NamedFunction(strings.TrimPrefix(interfaceType.Name(), \"reflect/types.type:\") + \".$typeassert\")\n\t\tif typeAssertFunction.IsNil() {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Replace Implements call with the type assert call.\n\t\tbuilder.SetInsertPointBefore(call)\n\t\timplements := builder.CreateCall(typeAssertFunction.GlobalValueType(), typeAssertFunction, []llvm.Value{\n\t\t\tcall.Operand(0), // typecode to check\n\t\t}, \"\")\n\t\tcall.ReplaceAllUsesWith(implements)\n\t\tcall.EraseFromParentAsInstruction()\n\t}\n}\n"
  },
  {
    "path": "transform/rtcalls_test.go",
    "content": "package transform_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/tinygo-org/tinygo/transform\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\nfunc TestOptimizeStringToBytes(t *testing.T) {\n\tt.Parallel()\n\ttestTransform(t, \"testdata/stringtobytes\", func(mod llvm.Module) {\n\t\t// Run optimization pass.\n\t\ttransform.OptimizeStringToBytes(mod)\n\t})\n}\n\nfunc TestOptimizeStringEqual(t *testing.T) {\n\tt.Parallel()\n\ttestTransform(t, \"testdata/stringequal\", func(mod llvm.Module) {\n\t\t// Run optimization pass.\n\t\ttransform.OptimizeStringEqual(mod)\n\t})\n}\n\nfunc TestOptimizeReflectImplements(t *testing.T) {\n\tt.Parallel()\n\ttestTransform(t, \"testdata/reflect-implements\", func(mod llvm.Module) {\n\t\t// Run optimization pass.\n\t\ttransform.OptimizeReflectImplements(mod)\n\t})\n}\n"
  },
  {
    "path": "transform/stacksize.go",
    "content": "package transform\n\nimport (\n\t\"path/filepath\"\n\n\t\"github.com/tinygo-org/tinygo/compileopts\"\n\t\"github.com/tinygo-org/tinygo/compiler/llvmutil\"\n\t\"github.com/tinygo-org/tinygo/goenv\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// CreateStackSizeLoads replaces internal/task.getGoroutineStackSize calls with\n// loads from internal/task.stackSizes that will be updated after linking. This\n// way the stack sizes are loaded from a separate section and can easily be\n// modified after linking.\nfunc CreateStackSizeLoads(mod llvm.Module, config *compileopts.Config) []string {\n\tfunctionMap := map[llvm.Value][]llvm.Value{}\n\tvar functions []llvm.Value // ptrtoint values of functions\n\tvar functionNames []string\n\tvar functionValues []llvm.Value // direct references to functions\n\tfor _, use := range getUses(mod.NamedFunction(\"internal/task.getGoroutineStackSize\")) {\n\t\tif use.FirstUse().IsNil() {\n\t\t\t// Apparently this stack size isn't used.\n\t\t\tuse.EraseFromParentAsInstruction()\n\t\t\tcontinue\n\t\t}\n\t\tptrtoint := use.Operand(0)\n\t\tif _, ok := functionMap[ptrtoint]; !ok {\n\t\t\tfunctions = append(functions, ptrtoint)\n\t\t\tfunctionNames = append(functionNames, ptrtoint.Operand(0).Name())\n\t\t\tfunctionValues = append(functionValues, ptrtoint.Operand(0))\n\t\t}\n\t\tfunctionMap[ptrtoint] = append(functionMap[ptrtoint], use)\n\t}\n\n\tif len(functions) == 0 {\n\t\t// Nothing to do.\n\t\treturn nil\n\t}\n\n\tctx := mod.Context()\n\ttargetData := llvm.NewTargetData(mod.DataLayout())\n\tdefer targetData.Dispose()\n\tuintptrType := ctx.IntType(targetData.PointerSize() * 8)\n\n\t// Create the new global with stack sizes, that will be put in a new section\n\t// just for itself.\n\tstackSizesGlobalType := llvm.ArrayType(functions[0].Type(), len(functions))\n\tstackSizesGlobal := llvm.AddGlobal(mod, stackSizesGlobalType, \"internal/task.stackSizes\")\n\tstackSizesGlobal.SetSection(\".tinygo_stacksizes\")\n\tdefaultStackSizes := make([]llvm.Value, len(functions))\n\tdefaultStackSize := llvm.ConstInt(functions[0].Type(), config.StackSize(), false)\n\talignment := targetData.ABITypeAlignment(functions[0].Type())\n\tfor i := range defaultStackSizes {\n\t\tdefaultStackSizes[i] = defaultStackSize\n\t}\n\tstackSizesGlobal.SetInitializer(llvm.ConstArray(functions[0].Type(), defaultStackSizes))\n\tstackSizesGlobal.SetAlignment(alignment)\n\t// TODO: make this a constant. For some reason, that incrases code size though.\n\tif config.Debug() {\n\t\tdibuilder := llvm.NewDIBuilder(mod)\n\t\tdibuilder.CreateCompileUnit(llvm.DICompileUnit{\n\t\t\tLanguage:  0xb, // DW_LANG_C99 (0xc, off-by-one?)\n\t\t\tFile:      \"<unknown>\",\n\t\t\tDir:       \"\",\n\t\t\tProducer:  \"TinyGo\",\n\t\t\tOptimized: true,\n\t\t})\n\t\tditype := dibuilder.CreateArrayType(llvm.DIArrayType{\n\t\t\tSizeInBits:  targetData.TypeAllocSize(stackSizesGlobalType) * 8,\n\t\t\tAlignInBits: uint32(alignment * 8),\n\t\t\tElementType: dibuilder.CreateBasicType(llvm.DIBasicType{\n\t\t\t\tName:       \"uintptr\",\n\t\t\t\tSizeInBits: targetData.TypeAllocSize(functions[0].Type()) * 8,\n\t\t\t\tEncoding:   llvm.DW_ATE_unsigned,\n\t\t\t}),\n\t\t\tSubscripts: []llvm.DISubrange{\n\t\t\t\t{\n\t\t\t\t\tLo:    0,\n\t\t\t\t\tCount: int64(len(functions)),\n\t\t\t\t},\n\t\t\t},\n\t\t})\n\t\tdiglobal := dibuilder.CreateGlobalVariableExpression(llvm.Metadata{}, llvm.DIGlobalVariableExpression{\n\t\t\tName: \"internal/task.stackSizes\",\n\t\t\tFile: dibuilder.CreateFile(\"internal/task/task_stack.go\", filepath.Join(goenv.Get(\"TINYGOROOT\"), \"src\")),\n\t\t\tLine: 1,\n\t\t\tType: ditype,\n\t\t\tExpr: dibuilder.CreateExpression(nil),\n\t\t})\n\t\tstackSizesGlobal.AddMetadata(0, diglobal)\n\n\t\tdibuilder.Finalize()\n\t\tdibuilder.Destroy()\n\t}\n\n\t// Add all relevant values to llvm.used (for LTO).\n\tllvmutil.AppendToGlobal(mod, \"llvm.used\", append([]llvm.Value{stackSizesGlobal}, functionValues...)...)\n\n\t// Replace the calls with loads from the new global with stack sizes.\n\tirbuilder := ctx.NewBuilder()\n\tdefer irbuilder.Dispose()\n\tfor i, function := range functions {\n\t\tfor _, use := range functionMap[function] {\n\t\t\tptr := llvm.ConstGEP(stackSizesGlobalType, stackSizesGlobal, []llvm.Value{\n\t\t\t\tllvm.ConstInt(ctx.Int32Type(), 0, false),\n\t\t\t\tllvm.ConstInt(ctx.Int32Type(), uint64(i), false),\n\t\t\t})\n\t\t\tirbuilder.SetInsertPointBefore(use)\n\t\t\tstacksize := irbuilder.CreateLoad(uintptrType, ptr, \"stacksize\")\n\t\t\tuse.ReplaceAllUsesWith(stacksize)\n\t\t\tuse.EraseFromParentAsInstruction()\n\t\t}\n\t}\n\n\treturn functionNames\n}\n"
  },
  {
    "path": "transform/stacksize_test.go",
    "content": "package transform_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/tinygo-org/tinygo/compileopts\"\n\t\"github.com/tinygo-org/tinygo/transform\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\nfunc TestCreateStackSizeLoads(t *testing.T) {\n\tt.Parallel()\n\ttestTransform(t, \"testdata/stacksize\", func(mod llvm.Module) {\n\t\t// Run optimization pass.\n\t\ttransform.CreateStackSizeLoads(mod, &compileopts.Config{\n\t\t\tOptions: &compileopts.Options{},\n\t\t\tTarget: &compileopts.TargetSpec{\n\t\t\t\tDefaultStackSize: 1024,\n\t\t\t},\n\t\t})\n\t})\n}\n"
  },
  {
    "path": "transform/testdata/allocs.ll",
    "content": "target datalayout = \"e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64\"\ntarget triple = \"armv7m-none-eabi\"\n\n@runtime.zeroSizedAlloc = internal global i8 0, align 1\n\ndeclare nonnull ptr @runtime.alloc(i32, ptr)\n\n; Test allocating a single int (i32) that should be allocated on the stack.\ndefine void @testInt() {\n  %alloc = call align 4 ptr @runtime.alloc(i32 4, ptr null)\n  store i32 5, ptr %alloc\n  ret void\n}\n\n; Test allocating an array of 3 i16 values that should be allocated on the\n; stack.\ndefine i16 @testArray() {\n  %alloc = call align 2 ptr @runtime.alloc(i32 6, ptr null)\n  %alloc.1 = getelementptr i16, ptr %alloc, i32 1\n  store i16 5, ptr %alloc.1\n  %alloc.2 = getelementptr i16, ptr %alloc, i32 2\n  %val = load i16, ptr %alloc.2\n  ret i16 %val\n}\n\n; Test allocating objects with an unknown alignment.\ndefine void @testUnknownAlign() {\n  %alloc32 = call ptr @runtime.alloc(i32 32, ptr null)\n  store i8 5, ptr %alloc32\n  %alloc24 = call ptr @runtime.alloc(i32 24, ptr null)\n  store i16 5, ptr %alloc24\n  %alloc12 = call ptr @runtime.alloc(i32 12, ptr null)\n  store i16 5, ptr %alloc12\n  %alloc6 = call ptr @runtime.alloc(i32 6, ptr null)\n  store i16 5, ptr %alloc6\n  %alloc3 = call ptr @runtime.alloc(i32 3, ptr null)\n  store i16 5, ptr %alloc3\n  ret void\n}\n\n; Call a function that will let the pointer escape, so the heap-to-stack\n; transform shouldn't be applied.\ndefine void @testEscapingCall() {\n  %alloc = call align 4 ptr @runtime.alloc(i32 4, ptr null)\n  %val = call ptr @escapeIntPtr(ptr %alloc)\n  ret void\n}\n\ndefine void @testEscapingCall2() {\n  %alloc = call align 4 ptr @runtime.alloc(i32 4, ptr null)\n  %val = call ptr @escapeIntPtrSometimes(ptr %alloc, ptr %alloc)\n  ret void\n}\n\n; Call a function that doesn't let the pointer escape.\ndefine void @testNonEscapingCall() {\n  %alloc = call align 4 ptr @runtime.alloc(i32 4, ptr null)\n  %val = call ptr @noescapeIntPtr(ptr %alloc)\n  ret void\n}\n\n; Return the allocated value, which lets it escape.\ndefine ptr @testEscapingReturn() {\n  %alloc = call align 4 ptr @runtime.alloc(i32 4, ptr null)\n  ret ptr %alloc\n}\n\n; Do a non-escaping allocation in a loop.\ndefine void @testNonEscapingLoop() {\nentry:\n  br label %loop\nloop:\n  %alloc = call align 4 ptr @runtime.alloc(i32 4, ptr null)\n  %ptr = call ptr @noescapeIntPtr(ptr %alloc)\n  %result = icmp eq ptr null, %ptr\n  br i1 %result, label %loop, label %end\nend:\n  ret void\n}\n\n; Test a zero-sized allocation.\ndefine void @testZeroSizedAlloc() {\n  %alloc = call align 1 ptr @runtime.alloc(i32 0, ptr null)\n  %ptr = call ptr @noescapeIntPtr(ptr %alloc)\n  ret void\n}\n\ndeclare ptr @escapeIntPtr(ptr)\n\ndeclare ptr @noescapeIntPtr(ptr nocapture)\n\ndeclare ptr @escapeIntPtrSometimes(ptr nocapture, ptr)\n"
  },
  {
    "path": "transform/testdata/allocs.out.ll",
    "content": "target datalayout = \"e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64\"\ntarget triple = \"armv7m-none-eabi\"\n\n@runtime.zeroSizedAlloc = internal global i8 0, align 1\n\ndeclare nonnull ptr @runtime.alloc(i32, ptr)\n\ndefine void @testInt() {\n  %stackalloc = alloca [4 x i8], align 4\n  store [4 x i8] zeroinitializer, ptr %stackalloc, align 4\n  store i32 5, ptr %stackalloc, align 4\n  ret void\n}\n\ndefine i16 @testArray() {\n  %stackalloc = alloca [6 x i8], align 2\n  store [6 x i8] zeroinitializer, ptr %stackalloc, align 2\n  %alloc.1 = getelementptr i16, ptr %stackalloc, i32 1\n  store i16 5, ptr %alloc.1, align 2\n  %alloc.2 = getelementptr i16, ptr %stackalloc, i32 2\n  %val = load i16, ptr %alloc.2, align 2\n  ret i16 %val\n}\n\ndefine void @testUnknownAlign() {\n  %stackalloc4 = alloca [32 x i8], align 8\n  %stackalloc3 = alloca [24 x i8], align 8\n  %stackalloc2 = alloca [12 x i8], align 8\n  %stackalloc1 = alloca [6 x i8], align 8\n  %stackalloc = alloca [3 x i8], align 8\n  store [32 x i8] zeroinitializer, ptr %stackalloc4, align 8\n  store i8 5, ptr %stackalloc4, align 1\n  store [24 x i8] zeroinitializer, ptr %stackalloc3, align 8\n  store i16 5, ptr %stackalloc3, align 2\n  store [12 x i8] zeroinitializer, ptr %stackalloc2, align 8\n  store i16 5, ptr %stackalloc2, align 2\n  store [6 x i8] zeroinitializer, ptr %stackalloc1, align 8\n  store i16 5, ptr %stackalloc1, align 2\n  store [3 x i8] zeroinitializer, ptr %stackalloc, align 8\n  store i16 5, ptr %stackalloc, align 2\n  ret void\n}\n\ndefine void @testEscapingCall() {\n  %alloc = call align 4 ptr @runtime.alloc(i32 4, ptr null)\n  %val = call ptr @escapeIntPtr(ptr %alloc)\n  ret void\n}\n\ndefine void @testEscapingCall2() {\n  %alloc = call align 4 ptr @runtime.alloc(i32 4, ptr null)\n  %val = call ptr @escapeIntPtrSometimes(ptr %alloc, ptr %alloc)\n  ret void\n}\n\ndefine void @testNonEscapingCall() {\n  %stackalloc = alloca [4 x i8], align 4\n  store [4 x i8] zeroinitializer, ptr %stackalloc, align 4\n  %val = call ptr @noescapeIntPtr(ptr %stackalloc)\n  ret void\n}\n\ndefine ptr @testEscapingReturn() {\n  %alloc = call align 4 ptr @runtime.alloc(i32 4, ptr null)\n  ret ptr %alloc\n}\n\ndefine void @testNonEscapingLoop() {\nentry:\n  %stackalloc = alloca [4 x i8], align 4\n  br label %loop\n\nloop:                                             ; preds = %loop, %entry\n  store [4 x i8] zeroinitializer, ptr %stackalloc, align 4\n  %ptr = call ptr @noescapeIntPtr(ptr %stackalloc)\n  %result = icmp eq ptr null, %ptr\n  br i1 %result, label %loop, label %end\n\nend:                                              ; preds = %loop\n  ret void\n}\n\ndefine void @testZeroSizedAlloc() {\n  %ptr = call ptr @noescapeIntPtr(ptr @runtime.zeroSizedAlloc)\n  ret void\n}\n\ndeclare ptr @escapeIntPtr(ptr)\n\ndeclare ptr @noescapeIntPtr(ptr nocapture)\n\ndeclare ptr @escapeIntPtrSometimes(ptr nocapture, ptr)\n"
  },
  {
    "path": "transform/testdata/allocs2.go",
    "content": "package main\n\nimport (\n\t\"runtime/volatile\"\n\t\"unsafe\"\n)\n\nfunc main() {\n\tn1 := 5\n\tderefInt(&n1)\n\n\t// This should eventually be modified to not escape.\n\tn2 := 6 // OUT: object allocated on the heap: escapes at line 14\n\treturnIntPtr(&n2)\n\n\ts1 := make([]int, 3)\n\treadIntSlice(s1)\n\n\ts2 := [3]int{}\n\treadIntSlice(s2[:])\n\n\t// This should also be modified to not escape.\n\ts3 := make([]int, 3) // OUT: object allocated on the heap: escapes at line 24\n\treturnIntSlice(s3)\n\n\tuseSlice(make([]int, getUnknownNumber())) // OUT: object allocated on the heap: size is not constant\n\n\ts4 := make([]byte, 300) // OUT: object allocated on the heap: object size 300 exceeds maximum stack allocation size 256\n\treadByteSlice(s4)\n\n\ts5 := make([]int, 4) // OUT: object allocated on the heap: escapes at line 32\n\t_ = append(s5, 5)\n\n\ts6 := make([]int, 3)\n\ts7 := []int{1, 2, 3}\n\tcopySlice(s6, s7)\n\n\tc1 := getComplex128() // OUT: object allocated on the heap: escapes at line 39\n\tuseInterface(c1)\n\n\tn3 := 5\n\tfunc() int {\n\t\treturn n3\n\t}()\n\n\tcallVariadic(3, 5, 8) // OUT: object allocated on the heap: escapes at line 46\n\n\ts8 := []int{3, 5, 8} // OUT: object allocated on the heap: escapes at line 49\n\tcallVariadic(s8...)\n\n\tn4 := 3 // OUT: object allocated on the heap: escapes at line 53\n\tn5 := 7 // OUT: object allocated on the heap: escapes at line 53\n\tfunc() {\n\t\tn4 = n5\n\t}()\n\tprintln(n4, n5)\n\n\t// This shouldn't escape.\n\tvar buf [32]byte\n\ts := string(buf[:])\n\tprintln(len(s))\n\n\tvar rbuf [5]rune\n\ts = string(rbuf[:])\n\tprintln(s)\n\n\t// Unsafe usage of DMA buffers: the compiler thinks this buffer won't be\n\t// used anymore after the volatile store.\n\tvar dmaBuf1 [4]byte\n\tpseudoVolatile.Set(uint32(unsafeNoEscape(unsafe.Pointer(&dmaBuf1[0]))))\n\n\t// Safe usage of DMA buffers: keep the buffer alive until it is no longer\n\t// needed, but don't mark it as needing to be heap allocated. The compiler\n\t// will keep the buffer stack allocated if possible.\n\tvar dmaBuf2 [4]byte\n\tpseudoVolatile.Set(uint32(unsafeNoEscape(unsafe.Pointer(&dmaBuf2[0]))))\n\t// ...use the buffer in the DMA peripheral\n\tkeepAliveNoEscape(unsafe.Pointer(&dmaBuf2[0]))\n}\n\nfunc derefInt(x *int) int {\n\treturn *x\n}\n\nfunc returnIntPtr(x *int) *int {\n\treturn x\n}\n\nfunc readIntSlice(s []int) int {\n\treturn s[1]\n}\n\nfunc readByteSlice(s []byte) byte {\n\treturn s[1]\n}\n\nfunc returnIntSlice(s []int) []int {\n\treturn s\n}\n\nfunc getUnknownNumber() int\n\nfunc copySlice(out, in []int) {\n\tcopy(out, in)\n}\n\nfunc getComplex128() complex128\n\nfunc useInterface(interface{})\n\nfunc callVariadic(...int)\n\nfunc useSlice([]int)\n\n// See the function with the same name in the machine package.\n//\n//go:linkname unsafeNoEscape machine.unsafeNoEscape\nfunc unsafeNoEscape(ptr unsafe.Pointer) uintptr\n\n//go:linkname keepAliveNoEscape machine.keepAliveNoEscape\nfunc keepAliveNoEscape(ptr unsafe.Pointer)\n\nvar pseudoVolatile volatile.Register32\n"
  },
  {
    "path": "transform/testdata/gc-stackslots.ll",
    "content": "target datalayout = \"e-m:e-p:32:32-i64:64-n32:64-S128\"\ntarget triple = \"wasm32-unknown-unknown-wasm\"\n\n@runtime.stackChainStart = external global ptr\n@someGlobal = global i8 3\n@ptrGlobal = global ptr null\n@arrGlobal = global [8 x i8] zeroinitializer\n\ndeclare void @runtime.trackPointer(ptr nocapture readonly)\n\ndeclare noalias nonnull ptr @runtime.alloc(i32, ptr)\n\n; Generic function that returns a pointer (that must be tracked).\ndefine ptr @getPointer() {\n    ret ptr @someGlobal\n}\n\ndefine ptr @needsStackSlots() {\n  ; Tracked pointer. Although, in this case the value is immediately returned\n  ; so tracking it is not really necessary.\n  %ptr = call ptr @runtime.alloc(i32 4, ptr null)\n  call void @runtime.trackPointer(ptr %ptr)\n  call void @someArbitraryFunction()\n  %val = load i8, ptr @someGlobal\n  ret ptr %ptr\n}\n\n; Check some edge cases of pointer tracking.\ndefine ptr @needsStackSlots2() {\n  ; Only one stack slot should be created for this (but at the moment, one is\n  ; created for each call to runtime.trackPointer).\n  %ptr1 = call ptr @getPointer()\n  call void @runtime.trackPointer(ptr %ptr1)\n  call void @runtime.trackPointer(ptr %ptr1)\n  call void @runtime.trackPointer(ptr %ptr1)\n\n  ; Create a pointer that does not need to be tracked (but is tracked).\n  %ptr2 = getelementptr i8, ptr @someGlobal, i32 0\n  call void @runtime.trackPointer(ptr %ptr2)\n\n  ; Here is finally the point where an allocation happens.\n  %unused = call ptr @runtime.alloc(i32 4, ptr null)\n  call void @runtime.trackPointer(ptr %unused)\n\n  ret ptr %ptr1\n}\n\n; Return a pointer from a caller. Because it doesn't allocate, no stack objects\n; need to be created.\ndefine ptr @noAllocatingFunction() {\n  %ptr = call ptr @getPointer()\n  call void @runtime.trackPointer(ptr %ptr)\n  ret ptr %ptr\n}\n\ndefine ptr @fibNext(ptr %x, ptr %y) {\n  %x.val = load i8, ptr %x\n  %y.val = load i8, ptr %y\n  %out.val = add i8 %x.val, %y.val\n  %out.alloc = call ptr @runtime.alloc(i32 1, ptr null)\n  call void @runtime.trackPointer(ptr %out.alloc)\n  store i8 %out.val, ptr %out.alloc\n  ret ptr %out.alloc\n}\n\ndefine ptr @allocLoop() {\nentry:\n  %entry.x = call ptr @runtime.alloc(i32 1, ptr null)\n  call void @runtime.trackPointer(ptr %entry.x)\n  %entry.y = call ptr @runtime.alloc(i32 1, ptr null)\n  call void @runtime.trackPointer(ptr %entry.y)\n  store i8 1, ptr %entry.y\n  br label %loop\n\nloop:\n  %prev.y = phi ptr [ %entry.y, %entry ], [ %prev.x, %loop ]\n  %prev.x = phi ptr [ %entry.x, %entry ], [ %next.x, %loop ]\n  call void @runtime.trackPointer(ptr %prev.x)\n  call void @runtime.trackPointer(ptr %prev.y)\n  %next.x = call ptr @fibNext(ptr %prev.x, ptr %prev.y)\n  call void @runtime.trackPointer(ptr %next.x)\n  %next.x.val = load i8, ptr %next.x\n  %loop.done = icmp ult i8 40, %next.x.val\n  br i1 %loop.done, label %end, label %loop\n\nend:\n  ret ptr %next.x\n}\n\ndeclare ptr @arrayAlloc()\n\ndefine void @testGEPBitcast() {\n  %arr = call ptr @arrayAlloc()\n  %arr.bitcast = getelementptr [32 x i8], ptr %arr, i32 0, i32 0\n  call void @runtime.trackPointer(ptr %arr.bitcast)\n  %other = call ptr @runtime.alloc(i32 1, ptr null)\n  call void @runtime.trackPointer(ptr %other)\n  ret void\n}\n\ndefine void @someArbitraryFunction() {\n  ret void\n}\n\ndefine void @earlyPopRegression() {\n  %x.alloc = call ptr @runtime.alloc(i32 4, ptr null)\n  call void @runtime.trackPointer(ptr %x.alloc)\n  ; At this point the pass used to pop the stack chain, resulting in a potential use-after-free during allocAndSave.\n  musttail call void @allocAndSave(ptr %x.alloc)\n  ret void\n}\n\ndefine void @allocAndSave(ptr %x) {\n  %y = call ptr @runtime.alloc(i32 4, ptr null)\n  call void @runtime.trackPointer(ptr %y)\n  store ptr %y, ptr %x\n  store ptr %x, ptr @ptrGlobal\n  ret void\n}\n\ndeclare void @\"(internal/task).Pause\"()\n\ndefine ptr @getAndPause() {\n\t%ptr = call ptr @getPointer()\n\tcall void @runtime.trackPointer(ptr %ptr)\n\t; Calling a function with unknown memory access forces stack slot creation.\n\tcall void @\"(internal/task).Pause\"()\n\tret ptr %ptr\n}\n\n; Function Attrs: memory(readwrite)\ndeclare void @externCallWithMemAttr() #0\n\ndefine ptr @getAndCallWithMemAttr() {\n\t%ptr = call ptr @getPointer()\n\tcall void @runtime.trackPointer(ptr %ptr)\n\t; Calling an external function which may access non-arg memory forces stack slot creation.\n\tcall void @externCallWithMemAttr()\n\tret ptr %ptr\n}\n\n; Generic function that returns a slice (that must be tracked).\ndefine {ptr, i32, i32} @getSlice() {\n  ret {ptr, i32, i32} {ptr @someGlobal, i32 8, i32 8}\n}\n\ndefine i32 @copyToSlice(ptr %src.ptr, i32 %src.len, i32 %src.cap) {\n  %dst = call {ptr, i32, i32} @getSlice()\n  %dst.ptr = extractvalue {ptr, i32, i32} %dst, 0\n  call void @runtime.trackPointer(ptr %dst.ptr)\n  %dst.len = extractvalue {ptr, i32, i32} %dst, 1\n  ; Math intrinsics do not need stack slots.\n  %minLen = call i32 @llvm.umin.i32(i32 %dst.len, i32 %src.len)\n  ; Intrinsics which only access argument memory do not need stack slots.\n  call void @llvm.memmove.p0.p0.i32(ptr %dst.ptr, ptr %src.ptr, i32 %minLen, i1 false)\n  ret i32 %minLen\n}\n\n; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)\ndeclare i32 @llvm.umin.i32(i32, i32) #1\n\n; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)\ndeclare void @llvm.memmove.p0.p0.i32(ptr nocapture writeonly, ptr nocapture readonly, i32, i1 immarg) #2\n\nattributes #0 = { memory(readwrite) }\nattributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }\nattributes #2 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }\n"
  },
  {
    "path": "transform/testdata/gc-stackslots.out.ll",
    "content": "target datalayout = \"e-m:e-p:32:32-i64:64-n32:64-S128\"\ntarget triple = \"wasm32-unknown-unknown-wasm\"\n\n@runtime.stackChainStart = internal global ptr null\n@someGlobal = global i8 3\n@ptrGlobal = global ptr null\n@arrGlobal = global [8 x i8] zeroinitializer\n\ndeclare void @runtime.trackPointer(ptr nocapture readonly)\n\ndeclare noalias nonnull ptr @runtime.alloc(i32, ptr)\n\ndefine ptr @getPointer() {\n  ret ptr @someGlobal\n}\n\ndefine ptr @needsStackSlots() {\n  %gc.stackobject = alloca { ptr, i32, ptr }, align 8\n  store { ptr, i32, ptr } { ptr null, i32 1, ptr null }, ptr %gc.stackobject, align 4\n  %1 = load ptr, ptr @runtime.stackChainStart, align 4\n  %2 = getelementptr { ptr, i32, ptr }, ptr %gc.stackobject, i32 0, i32 0\n  store ptr %1, ptr %2, align 4\n  store ptr %gc.stackobject, ptr @runtime.stackChainStart, align 4\n  %ptr = call ptr @runtime.alloc(i32 4, ptr null)\n  %3 = getelementptr { ptr, i32, ptr }, ptr %gc.stackobject, i32 0, i32 2\n  store ptr %ptr, ptr %3, align 4\n  call void @someArbitraryFunction()\n  %val = load i8, ptr @someGlobal, align 1\n  store ptr %1, ptr @runtime.stackChainStart, align 4\n  ret ptr %ptr\n}\n\ndefine ptr @needsStackSlots2() {\n  %gc.stackobject = alloca { ptr, i32, ptr, ptr, ptr, ptr, ptr }, align 8\n  store { ptr, i32, ptr, ptr, ptr, ptr, ptr } { ptr null, i32 5, ptr null, ptr null, ptr null, ptr null, ptr null }, ptr %gc.stackobject, align 4\n  %1 = load ptr, ptr @runtime.stackChainStart, align 4\n  %2 = getelementptr { ptr, i32, ptr, ptr, ptr, ptr, ptr }, ptr %gc.stackobject, i32 0, i32 0\n  store ptr %1, ptr %2, align 4\n  store ptr %gc.stackobject, ptr @runtime.stackChainStart, align 4\n  %ptr1 = call ptr @getPointer()\n  %3 = getelementptr { ptr, i32, ptr, ptr, ptr, ptr, ptr }, ptr %gc.stackobject, i32 0, i32 4\n  store ptr %ptr1, ptr %3, align 4\n  %4 = getelementptr { ptr, i32, ptr, ptr, ptr, ptr, ptr }, ptr %gc.stackobject, i32 0, i32 3\n  store ptr %ptr1, ptr %4, align 4\n  %5 = getelementptr { ptr, i32, ptr, ptr, ptr, ptr, ptr }, ptr %gc.stackobject, i32 0, i32 2\n  store ptr %ptr1, ptr %5, align 4\n  %ptr2 = getelementptr i8, ptr @someGlobal, i32 0\n  %6 = getelementptr { ptr, i32, ptr, ptr, ptr, ptr, ptr }, ptr %gc.stackobject, i32 0, i32 5\n  store ptr %ptr2, ptr %6, align 4\n  %unused = call ptr @runtime.alloc(i32 4, ptr null)\n  %7 = getelementptr { ptr, i32, ptr, ptr, ptr, ptr, ptr }, ptr %gc.stackobject, i32 0, i32 6\n  store ptr %unused, ptr %7, align 4\n  store ptr %1, ptr @runtime.stackChainStart, align 4\n  ret ptr %ptr1\n}\n\ndefine ptr @noAllocatingFunction() {\n  %ptr = call ptr @getPointer()\n  ret ptr %ptr\n}\n\ndefine ptr @fibNext(ptr %x, ptr %y) {\n  %gc.stackobject = alloca { ptr, i32, ptr }, align 8\n  store { ptr, i32, ptr } { ptr null, i32 1, ptr null }, ptr %gc.stackobject, align 4\n  %1 = load ptr, ptr @runtime.stackChainStart, align 4\n  %2 = getelementptr { ptr, i32, ptr }, ptr %gc.stackobject, i32 0, i32 0\n  store ptr %1, ptr %2, align 4\n  store ptr %gc.stackobject, ptr @runtime.stackChainStart, align 4\n  %x.val = load i8, ptr %x, align 1\n  %y.val = load i8, ptr %y, align 1\n  %out.val = add i8 %x.val, %y.val\n  %out.alloc = call ptr @runtime.alloc(i32 1, ptr null)\n  %3 = getelementptr { ptr, i32, ptr }, ptr %gc.stackobject, i32 0, i32 2\n  store ptr %out.alloc, ptr %3, align 4\n  store i8 %out.val, ptr %out.alloc, align 1\n  store ptr %1, ptr @runtime.stackChainStart, align 4\n  ret ptr %out.alloc\n}\n\ndefine ptr @allocLoop() {\nentry:\n  %gc.stackobject = alloca { ptr, i32, ptr, ptr, ptr, ptr, ptr }, align 8\n  store { ptr, i32, ptr, ptr, ptr, ptr, ptr } { ptr null, i32 5, ptr null, ptr null, ptr null, ptr null, ptr null }, ptr %gc.stackobject, align 4\n  %0 = load ptr, ptr @runtime.stackChainStart, align 4\n  %1 = getelementptr { ptr, i32, ptr, ptr, ptr, ptr, ptr }, ptr %gc.stackobject, i32 0, i32 0\n  store ptr %0, ptr %1, align 4\n  store ptr %gc.stackobject, ptr @runtime.stackChainStart, align 4\n  %entry.x = call ptr @runtime.alloc(i32 1, ptr null)\n  %2 = getelementptr { ptr, i32, ptr, ptr, ptr, ptr, ptr }, ptr %gc.stackobject, i32 0, i32 2\n  store ptr %entry.x, ptr %2, align 4\n  %entry.y = call ptr @runtime.alloc(i32 1, ptr null)\n  %3 = getelementptr { ptr, i32, ptr, ptr, ptr, ptr, ptr }, ptr %gc.stackobject, i32 0, i32 3\n  store ptr %entry.y, ptr %3, align 4\n  store i8 1, ptr %entry.y, align 1\n  br label %loop\n\nloop:                                             ; preds = %loop, %entry\n  %prev.y = phi ptr [ %entry.y, %entry ], [ %prev.x, %loop ]\n  %prev.x = phi ptr [ %entry.x, %entry ], [ %next.x, %loop ]\n  %4 = getelementptr { ptr, i32, ptr, ptr, ptr, ptr, ptr }, ptr %gc.stackobject, i32 0, i32 5\n  store ptr %prev.y, ptr %4, align 4\n  %5 = getelementptr { ptr, i32, ptr, ptr, ptr, ptr, ptr }, ptr %gc.stackobject, i32 0, i32 4\n  store ptr %prev.x, ptr %5, align 4\n  %next.x = call ptr @fibNext(ptr %prev.x, ptr %prev.y)\n  %6 = getelementptr { ptr, i32, ptr, ptr, ptr, ptr, ptr }, ptr %gc.stackobject, i32 0, i32 6\n  store ptr %next.x, ptr %6, align 4\n  %next.x.val = load i8, ptr %next.x, align 1\n  %loop.done = icmp ult i8 40, %next.x.val\n  br i1 %loop.done, label %end, label %loop\n\nend:                                              ; preds = %loop\n  store ptr %0, ptr @runtime.stackChainStart, align 4\n  ret ptr %next.x\n}\n\ndeclare ptr @arrayAlloc()\n\ndefine void @testGEPBitcast() {\n  %gc.stackobject = alloca { ptr, i32, ptr, ptr }, align 8\n  store { ptr, i32, ptr, ptr } { ptr null, i32 2, ptr null, ptr null }, ptr %gc.stackobject, align 4\n  %1 = load ptr, ptr @runtime.stackChainStart, align 4\n  %2 = getelementptr { ptr, i32, ptr, ptr }, ptr %gc.stackobject, i32 0, i32 0\n  store ptr %1, ptr %2, align 4\n  store ptr %gc.stackobject, ptr @runtime.stackChainStart, align 4\n  %arr = call ptr @arrayAlloc()\n  %arr.bitcast = getelementptr [32 x i8], ptr %arr, i32 0, i32 0\n  %3 = getelementptr { ptr, i32, ptr, ptr }, ptr %gc.stackobject, i32 0, i32 2\n  store ptr %arr.bitcast, ptr %3, align 4\n  %other = call ptr @runtime.alloc(i32 1, ptr null)\n  %4 = getelementptr { ptr, i32, ptr, ptr }, ptr %gc.stackobject, i32 0, i32 3\n  store ptr %other, ptr %4, align 4\n  store ptr %1, ptr @runtime.stackChainStart, align 4\n  ret void\n}\n\ndefine void @someArbitraryFunction() {\n  ret void\n}\n\ndefine void @earlyPopRegression() {\n  %gc.stackobject = alloca { ptr, i32, ptr }, align 8\n  store { ptr, i32, ptr } { ptr null, i32 1, ptr null }, ptr %gc.stackobject, align 4\n  %1 = load ptr, ptr @runtime.stackChainStart, align 4\n  %2 = getelementptr { ptr, i32, ptr }, ptr %gc.stackobject, i32 0, i32 0\n  store ptr %1, ptr %2, align 4\n  store ptr %gc.stackobject, ptr @runtime.stackChainStart, align 4\n  %x.alloc = call ptr @runtime.alloc(i32 4, ptr null)\n  %3 = getelementptr { ptr, i32, ptr }, ptr %gc.stackobject, i32 0, i32 2\n  store ptr %x.alloc, ptr %3, align 4\n  call void @allocAndSave(ptr %x.alloc)\n  store ptr %1, ptr @runtime.stackChainStart, align 4\n  ret void\n}\n\ndefine void @allocAndSave(ptr %x) {\n  %gc.stackobject = alloca { ptr, i32, ptr }, align 8\n  store { ptr, i32, ptr } { ptr null, i32 1, ptr null }, ptr %gc.stackobject, align 4\n  %1 = load ptr, ptr @runtime.stackChainStart, align 4\n  %2 = getelementptr { ptr, i32, ptr }, ptr %gc.stackobject, i32 0, i32 0\n  store ptr %1, ptr %2, align 4\n  store ptr %gc.stackobject, ptr @runtime.stackChainStart, align 4\n  %y = call ptr @runtime.alloc(i32 4, ptr null)\n  %3 = getelementptr { ptr, i32, ptr }, ptr %gc.stackobject, i32 0, i32 2\n  store ptr %y, ptr %3, align 4\n  store ptr %y, ptr %x, align 4\n  store ptr %x, ptr @ptrGlobal, align 4\n  store ptr %1, ptr @runtime.stackChainStart, align 4\n  ret void\n}\n\ndeclare void @\"(internal/task).Pause\"()\n\ndefine ptr @getAndPause() {\n  %gc.stackobject = alloca { ptr, i32, ptr }, align 8\n  store { ptr, i32, ptr } { ptr null, i32 1, ptr null }, ptr %gc.stackobject, align 4\n  %1 = load ptr, ptr @runtime.stackChainStart, align 4\n  %2 = getelementptr { ptr, i32, ptr }, ptr %gc.stackobject, i32 0, i32 0\n  store ptr %1, ptr %2, align 4\n  store ptr %gc.stackobject, ptr @runtime.stackChainStart, align 4\n  %ptr = call ptr @getPointer()\n  %3 = getelementptr { ptr, i32, ptr }, ptr %gc.stackobject, i32 0, i32 2\n  store ptr %ptr, ptr %3, align 4\n  call void @\"(internal/task).Pause\"()\n  store ptr %1, ptr @runtime.stackChainStart, align 4\n  ret ptr %ptr\n}\n\n; Function Attrs: memory(readwrite)\ndeclare void @externCallWithMemAttr() #0\n\ndefine ptr @getAndCallWithMemAttr() {\n  %gc.stackobject = alloca { ptr, i32, ptr }, align 8\n  store { ptr, i32, ptr } { ptr null, i32 1, ptr null }, ptr %gc.stackobject, align 4\n  %1 = load ptr, ptr @runtime.stackChainStart, align 4\n  %2 = getelementptr { ptr, i32, ptr }, ptr %gc.stackobject, i32 0, i32 0\n  store ptr %1, ptr %2, align 4\n  store ptr %gc.stackobject, ptr @runtime.stackChainStart, align 4\n  %ptr = call ptr @getPointer()\n  %3 = getelementptr { ptr, i32, ptr }, ptr %gc.stackobject, i32 0, i32 2\n  store ptr %ptr, ptr %3, align 4\n  call void @externCallWithMemAttr()\n  store ptr %1, ptr @runtime.stackChainStart, align 4\n  ret ptr %ptr\n}\n\ndefine { ptr, i32, i32 } @getSlice() {\n  ret { ptr, i32, i32 } { ptr @someGlobal, i32 8, i32 8 }\n}\n\ndefine i32 @copyToSlice(ptr %src.ptr, i32 %src.len, i32 %src.cap) {\n  %dst = call { ptr, i32, i32 } @getSlice()\n  %dst.ptr = extractvalue { ptr, i32, i32 } %dst, 0\n  %dst.len = extractvalue { ptr, i32, i32 } %dst, 1\n  %minLen = call i32 @llvm.umin.i32(i32 %dst.len, i32 %src.len)\n  call void @llvm.memmove.p0.p0.i32(ptr %dst.ptr, ptr %src.ptr, i32 %minLen, i1 false)\n  ret i32 %minLen\n}\n\n; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)\ndeclare i32 @llvm.umin.i32(i32, i32) #1\n\n; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)\ndeclare void @llvm.memmove.p0.p0.i32(ptr nocapture writeonly, ptr nocapture readonly, i32, i1 immarg) #2\n\nattributes #0 = { memory(readwrite) }\nattributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }\nattributes #2 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }\n"
  },
  {
    "path": "transform/testdata/interface.ll",
    "content": "target datalayout = \"e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64\"\ntarget triple = \"armv7m-none-eabi\"\n\n@\"reflect/types.type:basic:uint8\" = linkonce_odr constant { i8, ptr } { i8 8, ptr @\"reflect/types.type:pointer:basic:uint8\" }, align 4\n@\"reflect/types.type:pointer:basic:uint8\" = linkonce_odr constant { i8, ptr } { i8 21, ptr @\"reflect/types.type:basic:uint8\" }, align 4\n@\"reflect/types.typeid:basic:uint8\" = external constant i8\n@\"reflect/types.typeid:basic:int16\" = external constant i8\n@\"reflect/types.type:basic:int\" = linkonce_odr constant { i8, ptr } { i8 2, ptr @\"reflect/types.type:pointer:basic:int\" }, align 4\n@\"reflect/types.type:pointer:basic:int\" = linkonce_odr constant { i8, ptr } { i8 21, ptr @\"reflect/types.type:basic:int\" }, align 4\n@\"reflect/methods.NeverImplementedMethod()\" = linkonce_odr constant i8 0\n@\"reflect/methods.Double() int\" = linkonce_odr constant i8 0\n@\"Number$methodset\" = linkonce_odr unnamed_addr constant { i32, [1 x ptr], { ptr } } { i32 1, [1 x ptr] [ptr @\"reflect/methods.Double() int\"], { ptr } { ptr @\"(Number).Double$invoke\" } }\n@\"reflect/types.type:named:Number\" = linkonce_odr constant { ptr, i8, ptr, ptr } { ptr @\"Number$methodset\", i8 34, ptr @\"reflect/types.type:pointer:named:Number\", ptr @\"reflect/types.type:basic:int\" }, align 4\n@\"reflect/types.type:pointer:named:Number\" = linkonce_odr constant { i8, ptr } { i8 21, ptr getelementptr inbounds ({ ptr, i8, ptr, ptr }, ptr @\"reflect/types.type:named:Number\", i32 0, i32 1) }, align 4\n\ndeclare i1 @runtime.typeAssert(ptr, ptr)\ndeclare void @runtime.printuint8(i8)\ndeclare void @runtime.printint16(i16)\ndeclare void @runtime.printint32(i32)\ndeclare void @runtime.printptr(i32)\ndeclare void @runtime.printnl()\ndeclare void @runtime.nilPanic(ptr)\n\ndefine void @printInterfaces() {\n  call void @printInterface(ptr @\"reflect/types.type:basic:int\", ptr inttoptr (i32 5 to ptr))\n  call void @printInterface(ptr @\"reflect/types.type:basic:uint8\", ptr inttoptr (i8 120 to ptr))\n  call void @printInterface(ptr getelementptr inbounds ({ ptr, i8, ptr, ptr }, ptr @\"reflect/types.type:named:Number\", i32 0, i32 1), ptr inttoptr (i32 3 to ptr))\n\n  ret void\n}\n\ndefine void @printInterface(ptr %typecode, ptr %value) {\n  %isUnmatched = call i1 @Unmatched$typeassert(ptr %typecode)\n  br i1 %isUnmatched, label %typeswitch.Unmatched, label %typeswitch.notUnmatched\n\ntypeswitch.Unmatched:\n  %unmatched = ptrtoint ptr %value to i32\n  call void @runtime.printptr(i32 %unmatched)\n  call void @runtime.printnl()\n  ret void\n\ntypeswitch.notUnmatched:\n  %isDoubler = call i1 @Doubler$typeassert(ptr %typecode)\n  br i1 %isDoubler, label %typeswitch.Doubler, label %typeswitch.notDoubler\n\ntypeswitch.Doubler:\n  %doubler.result = call i32 @\"Doubler.Double$invoke\"(ptr %value, ptr %typecode, ptr undef)\n  call void @runtime.printint32(i32 %doubler.result)\n  ret void\n\ntypeswitch.notDoubler:\n  %isByte = call i1 @runtime.typeAssert(ptr %typecode, ptr nonnull @\"reflect/types.typeid:basic:uint8\")\n  br i1 %isByte, label %typeswitch.byte, label %typeswitch.notByte\n\ntypeswitch.byte:\n  %byte = ptrtoint ptr %value to i8\n  call void @runtime.printuint8(i8 %byte)\n  call void @runtime.printnl()\n  ret void\n\ntypeswitch.notByte:\n  ; this is a type assert that always fails\n  %isInt16 = call i1 @runtime.typeAssert(ptr %typecode, ptr nonnull @\"reflect/types.typeid:basic:int16\")\n  br i1 %isInt16, label %typeswitch.int16, label %typeswitch.notInt16\n\ntypeswitch.int16:\n  %int16 = ptrtoint ptr %value to i16\n  call void @runtime.printint16(i16 %int16)\n  call void @runtime.printnl()\n  ret void\n\ntypeswitch.notInt16:\n  ret void\n}\n\ndefine i32 @\"(Number).Double\"(i32 %receiver, ptr %context) {\n  %ret = mul i32 %receiver, 2\n  ret i32 %ret\n}\n\ndefine i32 @\"(Number).Double$invoke\"(ptr %receiverPtr, ptr %context) {\n  %receiver = ptrtoint ptr %receiverPtr to i32\n  %ret = call i32 @\"(Number).Double\"(i32 %receiver, ptr undef)\n  ret i32 %ret\n}\n\ndeclare i32 @\"Doubler.Double$invoke\"(ptr %receiver, ptr %typecode, ptr %context) #0\n\ndeclare i1 @Doubler$typeassert(ptr %typecode) #1\n\ndeclare i1 @Unmatched$typeassert(ptr %typecode) #2\n\nattributes #0 = { \"tinygo-invoke\"=\"reflect/methods.Double() int\" \"tinygo-methods\"=\"reflect/methods.Double() int\" }\nattributes #1 = { \"tinygo-methods\"=\"reflect/methods.Double() int\" }\nattributes #2 = { \"tinygo-methods\"=\"reflect/methods.NeverImplementedMethod()\" }\n"
  },
  {
    "path": "transform/testdata/interface.out.ll",
    "content": "target datalayout = \"e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64\"\ntarget triple = \"armv7m-none-eabi\"\n\n@\"reflect/types.type:basic:uint8\" = linkonce_odr constant { i8, ptr } { i8 8, ptr @\"reflect/types.type:pointer:basic:uint8\" }, align 4\n@\"reflect/types.type:pointer:basic:uint8\" = linkonce_odr constant { i8, ptr } { i8 21, ptr @\"reflect/types.type:basic:uint8\" }, align 4\n@\"reflect/types.type:basic:int\" = linkonce_odr constant { i8, ptr } { i8 2, ptr @\"reflect/types.type:pointer:basic:int\" }, align 4\n@\"reflect/types.type:pointer:basic:int\" = linkonce_odr constant { i8, ptr } { i8 21, ptr @\"reflect/types.type:basic:int\" }, align 4\n@\"reflect/types.type:pointer:named:Number\" = linkonce_odr constant { i8, ptr } { i8 21, ptr @\"reflect/types.type:named:Number\" }, align 4\n@\"reflect/types.type:named:Number\" = linkonce_odr constant { i8, ptr, ptr } { i8 34, ptr @\"reflect/types.type:pointer:named:Number\", ptr @\"reflect/types.type:basic:int\" }, align 4\n\ndeclare void @runtime.printuint8(i8)\n\ndeclare void @runtime.printint16(i16)\n\ndeclare void @runtime.printint32(i32)\n\ndeclare void @runtime.printptr(i32)\n\ndeclare void @runtime.printnl()\n\ndeclare void @runtime.nilPanic(ptr)\n\ndefine void @printInterfaces() {\n  call void @printInterface(ptr @\"reflect/types.type:basic:int\", ptr inttoptr (i32 5 to ptr))\n  call void @printInterface(ptr @\"reflect/types.type:basic:uint8\", ptr inttoptr (i8 120 to ptr))\n  call void @printInterface(ptr @\"reflect/types.type:named:Number\", ptr inttoptr (i32 3 to ptr))\n  ret void\n}\n\ndefine void @printInterface(ptr %typecode, ptr %value) {\n  %isUnmatched = call i1 @\"Unmatched$typeassert\"(ptr %typecode)\n  br i1 %isUnmatched, label %typeswitch.Unmatched, label %typeswitch.notUnmatched\n\ntypeswitch.Unmatched:                             ; preds = %0\n  %unmatched = ptrtoint ptr %value to i32\n  call void @runtime.printptr(i32 %unmatched)\n  call void @runtime.printnl()\n  ret void\n\ntypeswitch.notUnmatched:                          ; preds = %0\n  %isDoubler = call i1 @\"Doubler$typeassert\"(ptr %typecode)\n  br i1 %isDoubler, label %typeswitch.Doubler, label %typeswitch.notDoubler\n\ntypeswitch.Doubler:                               ; preds = %typeswitch.notUnmatched\n  %doubler.result = call i32 @\"Doubler.Double$invoke\"(ptr %value, ptr %typecode, ptr undef)\n  call void @runtime.printint32(i32 %doubler.result)\n  ret void\n\ntypeswitch.notDoubler:                            ; preds = %typeswitch.notUnmatched\n  %typeassert.ok = icmp eq ptr @\"reflect/types.type:basic:uint8\", %typecode\n  br i1 %typeassert.ok, label %typeswitch.byte, label %typeswitch.notByte\n\ntypeswitch.byte:                                  ; preds = %typeswitch.notDoubler\n  %byte = ptrtoint ptr %value to i8\n  call void @runtime.printuint8(i8 %byte)\n  call void @runtime.printnl()\n  ret void\n\ntypeswitch.notByte:                               ; preds = %typeswitch.notDoubler\n  br i1 false, label %typeswitch.int16, label %typeswitch.notInt16\n\ntypeswitch.int16:                                 ; preds = %typeswitch.notByte\n  %int16 = ptrtoint ptr %value to i16\n  call void @runtime.printint16(i16 %int16)\n  call void @runtime.printnl()\n  ret void\n\ntypeswitch.notInt16:                              ; preds = %typeswitch.notByte\n  ret void\n}\n\ndefine i32 @\"(Number).Double\"(i32 %receiver, ptr %context) {\n  %ret = mul i32 %receiver, 2\n  ret i32 %ret\n}\n\ndefine i32 @\"(Number).Double$invoke\"(ptr %receiverPtr, ptr %context) {\n  %receiver = ptrtoint ptr %receiverPtr to i32\n  %ret = call i32 @\"(Number).Double\"(i32 %receiver, ptr undef)\n  ret i32 %ret\n}\n\ndefine internal i32 @\"Doubler.Double$invoke\"(ptr %receiver, ptr %actualType, ptr %context) unnamed_addr #0 {\nentry:\n  %\"named:Number.icmp\" = icmp eq ptr %actualType, @\"reflect/types.type:named:Number\"\n  br i1 %\"named:Number.icmp\", label %\"named:Number\", label %\"named:Number.next\"\n\n\"named:Number\":                                   ; preds = %entry\n  %0 = call i32 @\"(Number).Double$invoke\"(ptr %receiver, ptr undef)\n  ret i32 %0\n\n\"named:Number.next\":                              ; preds = %entry\n  call void @runtime.nilPanic(ptr undef)\n  unreachable\n}\n\ndefine internal i1 @\"Doubler$typeassert\"(ptr %actualType) unnamed_addr #1 {\nentry:\n  %\"named:Number.icmp\" = icmp eq ptr %actualType, @\"reflect/types.type:named:Number\"\n  br i1 %\"named:Number.icmp\", label %then, label %\"named:Number.next\"\n\nthen:                                             ; preds = %entry\n  ret i1 true\n\n\"named:Number.next\":                              ; preds = %entry\n  ret i1 false\n}\n\ndefine internal i1 @\"Unmatched$typeassert\"(ptr %actualType) unnamed_addr #2 {\nentry:\n  ret i1 false\n\nthen:                                             ; No predecessors!\n  ret i1 true\n}\n\nattributes #0 = { \"tinygo-invoke\"=\"reflect/methods.Double() int\" \"tinygo-methods\"=\"reflect/methods.Double() int\" }\nattributes #1 = { \"tinygo-methods\"=\"reflect/methods.Double() int\" }\nattributes #2 = { \"tinygo-methods\"=\"reflect/methods.NeverImplementedMethod()\" }\n"
  },
  {
    "path": "transform/testdata/interrupt.ll",
    "content": "target datalayout = \"e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64\"\ntarget triple = \"armv7em-none-eabi\"\n\n%machine.UART = type { ptr }\n%machine.RingBuffer = type { [128 x %\"runtime/volatile.Register8\"], %\"runtime/volatile.Register8\", %\"runtime/volatile.Register8\" }\n%\"runtime/volatile.Register8\" = type { i8 }\n%\"runtime/interrupt.handle\" = type { ptr, i32, %\"runtime/interrupt.Interrupt\" }\n%\"runtime/interrupt.Interrupt\" = type { i32 }\n\n@\"runtime/interrupt.$interrupt2\" = private unnamed_addr constant %\"runtime/interrupt.handle\" { ptr @machine.UART0, i32 ptrtoint (ptr @\"(*machine.UART).handleInterrupt$bound\" to i32), %\"runtime/interrupt.Interrupt\" { i32 2 } }\n@machine.UART0 = internal global %machine.UART { ptr @\"machine$alloc.335\" }\n@\"machine$alloc.335\" = internal global %machine.RingBuffer zeroinitializer\n\ndeclare void @\"runtime/interrupt.callHandlers\"(i32, ptr) local_unnamed_addr\n\ndeclare void @\"device/arm.EnableIRQ\"(i32, ptr nocapture readnone)\n\ndeclare void @\"device/arm.SetPriority\"(i32, i32, ptr nocapture readnone)\n\ndeclare void @\"runtime/interrupt.use\"(%\"runtime/interrupt.Interrupt\")\n\ndefine void @runtime.initAll(ptr nocapture readnone) unnamed_addr {\nentry:\n  call void @\"device/arm.SetPriority\"(i32 ptrtoint (ptr @\"runtime/interrupt.$interrupt2\" to i32), i32 192, ptr undef)\n  call void @\"device/arm.EnableIRQ\"(i32 ptrtoint (ptr @\"runtime/interrupt.$interrupt2\" to i32), ptr undef)\n  call void @\"runtime/interrupt.use\"(%\"runtime/interrupt.Interrupt\" { i32 ptrtoint (ptr @\"runtime/interrupt.$interrupt2\" to i32) })\n  ret void\n}\n\ndefine void @UARTE0_UART0_IRQHandler() {\n  call void @\"runtime/interrupt.callHandlers\"(i32 2, ptr undef)\n  ret void\n}\n\ndefine void @NFCT_IRQHandler() {\n  call void @\"runtime/interrupt.callHandlers\"(i32 5, ptr undef)\n  ret void\n}\n\ndefine internal void @interruptSWVector(i32 %num) {\nentry:\n  switch i32 %num, label %switch.done [\n    i32 2, label %switch.body2\n    i32 5, label %switch.body5\n  ]\n\nswitch.body2:\n  call void @\"runtime/interrupt.callHandlers\"(i32 2, ptr undef)\n  ret void\n\nswitch.body5:\n  call void @\"runtime/interrupt.callHandlers\"(i32 5, ptr undef)\n  ret void\n\nswitch.done:\n  ret void\n}\n\ndefine internal void @\"(*machine.UART).handleInterrupt$bound\"(i32, ptr nocapture %context) {\nentry:\n  call void @\"(*machine.UART).handleInterrupt\"(ptr %context, i32 %0, ptr undef)\n  ret void\n}\n\ndeclare void @\"(*machine.UART).handleInterrupt\"(ptr nocapture, i32, ptr nocapture readnone)\n"
  },
  {
    "path": "transform/testdata/interrupt.out.ll",
    "content": "target datalayout = \"e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64\"\ntarget triple = \"armv7em-none-eabi\"\n\n%machine.UART = type { ptr }\n%machine.RingBuffer = type { [128 x %\"runtime/volatile.Register8\"], %\"runtime/volatile.Register8\", %\"runtime/volatile.Register8\" }\n%\"runtime/volatile.Register8\" = type { i8 }\n%\"runtime/interrupt.Interrupt\" = type { i32 }\n\n@machine.UART0 = internal global %machine.UART { ptr @\"machine$alloc.335\" }\n@\"machine$alloc.335\" = internal global %machine.RingBuffer zeroinitializer\n\ndeclare void @\"runtime/interrupt.callHandlers\"(i32, ptr) local_unnamed_addr\n\ndeclare void @\"device/arm.EnableIRQ\"(i32, ptr nocapture readnone)\n\ndeclare void @\"device/arm.SetPriority\"(i32, i32, ptr nocapture readnone)\n\ndeclare void @\"runtime/interrupt.use\"(%\"runtime/interrupt.Interrupt\")\n\ndefine void @runtime.initAll(ptr nocapture readnone %0) unnamed_addr {\nentry:\n  call void @\"device/arm.SetPriority\"(i32 2, i32 192, ptr undef)\n  call void @\"device/arm.EnableIRQ\"(i32 2, ptr undef)\n  ret void\n}\n\ndefine void @UARTE0_UART0_IRQHandler() {\n  call void @\"(*machine.UART).handleInterrupt$bound\"(i32 2, ptr @machine.UART0)\n  ret void\n}\n\ndefine internal void @interruptSWVector(i32 %num) {\nentry:\n  switch i32 %num, label %switch.done [\n    i32 2, label %switch.body2\n    i32 5, label %switch.body5\n  ]\n\nswitch.body2:                                     ; preds = %entry\n  call void @\"(*machine.UART).handleInterrupt$bound\"(i32 2, ptr @machine.UART0)\n  ret void\n\nswitch.body5:                                     ; preds = %entry\n  unreachable\n\nswitch.done:                                      ; preds = %entry\n  ret void\n}\n\ndefine internal void @\"(*machine.UART).handleInterrupt$bound\"(i32 %0, ptr nocapture %context) {\nentry:\n  call void @\"(*machine.UART).handleInterrupt\"(ptr %context, i32 %0, ptr undef)\n  ret void\n}\n\ndeclare void @\"(*machine.UART).handleInterrupt\"(ptr nocapture, i32, ptr nocapture readnone)\n"
  },
  {
    "path": "transform/testdata/maps.ll",
    "content": "target datalayout = \"e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64\"\ntarget triple = \"armv7m-none-eabi\"\n\n@answer = constant [6 x i8] c\"answer\"\n\n; func(keySize, valueSize uint8, sizeHint uintptr) *runtime.hashmap\ndeclare nonnull ptr @runtime.hashmapMake(i8, i8, i32)\n\n; func(map[string]int, string, unsafe.Pointer)\ndeclare void @runtime.hashmapStringSet(ptr nocapture, ptr, i32, ptr nocapture readonly)\n\n; func(map[string]int, string, unsafe.Pointer)\ndeclare i1 @runtime.hashmapStringGet(ptr nocapture, ptr, i32, ptr nocapture)\n\ndefine void @testUnused() {\n    ; create the map\n    %map = call ptr @runtime.hashmapMake(i8 4, i8 4, i32 0)\n    ; create the value to be stored\n    %hashmap.value = alloca i32\n    store i32 42, ptr %hashmap.value\n    ; store the value\n    call void @runtime.hashmapStringSet(ptr %map, ptr @answer, i32 6, ptr %hashmap.value)\n    ret void\n}\n\n; Note that the following function should ideally be optimized (it could simply\n; return 42), but isn't at the moment.\ndefine i32 @testReadonly() {\n    ; create the map\n    %map = call ptr @runtime.hashmapMake(i8 4, i8 4, i32 0)\n\n    ; create the value to be stored\n    %hashmap.value = alloca i32\n    store i32 42, ptr %hashmap.value\n\n    ; store the value\n    call void @runtime.hashmapStringSet(ptr %map, ptr @answer, i32 6, ptr %hashmap.value)\n\n    ; load the value back\n    %hashmap.value2 = alloca i32\n    %commaOk = call i1 @runtime.hashmapStringGet(ptr %map, ptr @answer, i32 6, ptr %hashmap.value2)\n    %loadedValue = load i32, ptr %hashmap.value2\n\n    ret i32 %loadedValue\n}\n\ndefine ptr @testUsed() {\n    %1 = call ptr @runtime.hashmapMake(i8 4, i8 4, i32 0)\n    ret ptr %1\n}\n"
  },
  {
    "path": "transform/testdata/maps.out.ll",
    "content": "target datalayout = \"e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64\"\ntarget triple = \"armv7m-none-eabi\"\n\n@answer = constant [6 x i8] c\"answer\"\n\ndeclare nonnull ptr @runtime.hashmapMake(i8, i8, i32)\n\ndeclare void @runtime.hashmapStringSet(ptr nocapture, ptr, i32, ptr nocapture readonly)\n\ndeclare i1 @runtime.hashmapStringGet(ptr nocapture, ptr, i32, ptr nocapture)\n\ndefine void @testUnused() {\n  ret void\n}\n\ndefine i32 @testReadonly() {\n  %map = call ptr @runtime.hashmapMake(i8 4, i8 4, i32 0)\n  %hashmap.value = alloca i32, align 4\n  store i32 42, ptr %hashmap.value, align 4\n  call void @runtime.hashmapStringSet(ptr %map, ptr @answer, i32 6, ptr %hashmap.value)\n  %hashmap.value2 = alloca i32, align 4\n  %commaOk = call i1 @runtime.hashmapStringGet(ptr %map, ptr @answer, i32 6, ptr %hashmap.value2)\n  %loadedValue = load i32, ptr %hashmap.value2, align 4\n  ret i32 %loadedValue\n}\n\ndefine ptr @testUsed() {\n  %1 = call ptr @runtime.hashmapMake(i8 4, i8 4, i32 0)\n  ret ptr %1\n}\n"
  },
  {
    "path": "transform/testdata/reflect-implements.ll",
    "content": "target datalayout = \"e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-f80:32-n8:16:32-S128\"\ntarget triple = \"i686--linux\"\n\n%runtime._interface = type { ptr, ptr }\n\n@\"reflect/types.type:named:error\" = internal constant { i8, i16, ptr, ptr } { i8 52, i16 0, ptr @\"reflect/types.type:pointer:named:error\", ptr @\"reflect/types.type:interface:{Error:func:{}{basic:string}}\" }, align 4\n@\"reflect/types.type:interface:{Error:func:{}{basic:string}}\" = internal constant { i8, ptr } { i8 20, ptr @\"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}\" }, align 4\n@\"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}\" = internal constant { i8, ptr } { i8 21, ptr @\"reflect/types.type:interface:{Error:func:{}{basic:string}}\" }, align 4\n@\"reflect/types.type:pointer:named:error\" = internal constant { i8, i16, ptr } { i8 21, i16 0, ptr @\"reflect/types.type:named:error\" }, align 4\n@\"reflect/types.type:pointer:named:reflect.rawType\" = internal constant { ptr, i8, i16, ptr } { ptr null, i8 21, i16 0, ptr null }, align 4\n@\"reflect/methods.Implements(reflect.Type) bool\" = internal constant i8 0, align 1\n\n; var errorType = reflect.TypeOf((*error)(nil)).Elem()\n; func isError(typ reflect.Type) bool {\n;   return typ.Implements(errorType)\n; }\n; The type itself is stored in %typ.value, %typ.typecode just refers to the\n; type of reflect.Type. This function can be optimized because errorType is\n; known at compile time (after the interp pass has run).\ndefine i1 @main.isError(ptr %typ.typecode, ptr %typ.value, ptr %context) {\nentry:\n  %result = call i1 @\"reflect.Type.Implements$invoke\"(ptr %typ.value, ptr getelementptr inbounds ({ ptr, i8, ptr }, ptr @\"reflect/types.type:pointer:named:reflect.rawType\", i32 0, i32 1), ptr @\"reflect/types.type:named:error\", ptr %typ.typecode, ptr undef)\n  ret i1 %result\n}\n\n; This Implements method call can not be optimized because itf is not known at\n; compile time.\n; func isUnknown(typ, itf reflect.Type) bool {\n;   return typ.Implements(itf)\n; }\ndefine i1 @main.isUnknown(ptr %typ.typecode, ptr %typ.value, ptr %itf.typecode, ptr %itf.value, ptr %context) {\nentry:\n  %result = call i1 @\"reflect.Type.Implements$invoke\"(ptr %typ.value, ptr %itf.typecode, ptr %itf.value, ptr %typ.typecode, ptr undef)\n  ret i1 %result\n}\n\ndeclare i1 @\"reflect.Type.Implements$invoke\"(ptr, ptr, ptr, ptr, ptr) #0\ndeclare i1 @\"interface:{Error:func:{}{basic:string}}.$typeassert\"(ptr %0) #1\n\nattributes #0 = { \"tinygo-invoke\"=\"reflect/methods.Implements(reflect.Type) bool\" \"tinygo-methods\"=\"reflect/methods.Align() int; reflect/methods.Implements(reflect.Type) bool\" }\nattributes #1 = { \"tinygo-methods\"=\"reflect/methods.Error() string\" }\n"
  },
  {
    "path": "transform/testdata/reflect-implements.out.ll",
    "content": "target datalayout = \"e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-f80:32-n8:16:32-S128\"\ntarget triple = \"i686--linux\"\n\n@\"reflect/types.type:named:error\" = internal constant { i8, i16, ptr, ptr } { i8 52, i16 0, ptr @\"reflect/types.type:pointer:named:error\", ptr @\"reflect/types.type:interface:{Error:func:{}{basic:string}}\" }, align 4\n@\"reflect/types.type:interface:{Error:func:{}{basic:string}}\" = internal constant { i8, ptr } { i8 20, ptr @\"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}\" }, align 4\n@\"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}\" = internal constant { i8, ptr } { i8 21, ptr @\"reflect/types.type:interface:{Error:func:{}{basic:string}}\" }, align 4\n@\"reflect/types.type:pointer:named:error\" = internal constant { i8, i16, ptr } { i8 21, i16 0, ptr @\"reflect/types.type:named:error\" }, align 4\n@\"reflect/types.type:pointer:named:reflect.rawType\" = internal constant { ptr, i8, i16, ptr } { ptr null, i8 21, i16 0, ptr null }, align 4\n@\"reflect/methods.Implements(reflect.Type) bool\" = internal constant i8 0, align 1\n\ndefine i1 @main.isError(ptr %typ.typecode, ptr %typ.value, ptr %context) {\nentry:\n  %0 = call i1 @\"interface:{Error:func:{}{basic:string}}.$typeassert\"(ptr %typ.value)\n  ret i1 %0\n}\n\ndefine i1 @main.isUnknown(ptr %typ.typecode, ptr %typ.value, ptr %itf.typecode, ptr %itf.value, ptr %context) {\nentry:\n  %result = call i1 @\"reflect.Type.Implements$invoke\"(ptr %typ.value, ptr %itf.typecode, ptr %itf.value, ptr %typ.typecode, ptr undef)\n  ret i1 %result\n}\n\ndeclare i1 @\"reflect.Type.Implements$invoke\"(ptr, ptr, ptr, ptr, ptr) #0\n\ndeclare i1 @\"interface:{Error:func:{}{basic:string}}.$typeassert\"(ptr) #1\n\nattributes #0 = { \"tinygo-invoke\"=\"reflect/methods.Implements(reflect.Type) bool\" \"tinygo-methods\"=\"reflect/methods.Align() int; reflect/methods.Implements(reflect.Type) bool\" }\nattributes #1 = { \"tinygo-methods\"=\"reflect/methods.Error() string\" }\n"
  },
  {
    "path": "transform/testdata/reflect.go",
    "content": "package main\n\n// This file tests the type codes assigned by the reflect lowering pass.\n// This test is not complete, most importantly, sidetables are not currently\n// being tested.\n\nimport (\n\t\"reflect\"\n\t\"unsafe\"\n)\n\nconst (\n\t// See the top of src/reflect/type.go\n\tprefixChan      = 0b0001\n\tprefixInterface = 0b0011\n\tprefixPtr       = 0b0101\n\tprefixSlice     = 0b0111\n\tprefixArray     = 0b1001\n\tprefixFunc      = 0b1011\n\tprefixMap       = 0b1101\n\tprefixStruct    = 0b1111\n)\n\nfunc main() {\n\t// Check for some basic types.\n\tassertType(3, uintptr(reflect.Int)<<1)\n\tassertType(uint8(3), uintptr(reflect.Uint8)<<1)\n\tassertType(byte(3), uintptr(reflect.Uint8)<<1)\n\tassertType(int64(3), uintptr(reflect.Int64)<<1)\n\tassertType(\"\", uintptr(reflect.String)<<1)\n\tassertType(3.5, uintptr(reflect.Float64)<<1)\n\tassertType(unsafe.Pointer(nil), uintptr(reflect.UnsafePointer)<<1)\n\n\t// Check for named types: they are given names in order.\n\t// They are sorted in reverse, for no good reason.\n\tconst intNum = uintptr(reflect.Int) << 1\n\tassertType(namedInt1(0), (3<<6)|intNum)\n\tassertType(namedInt2(0), (2<<6)|intNum)\n\tassertType(namedInt3(0), (1<<6)|intNum)\n\n\t// Check for some \"prefix-style\" types.\n\tassertType(make(chan int), (intNum<<5)|prefixChan)\n\tassertType(new(int), (intNum<<5)|prefixPtr)\n\tassertType([]int{}, (intNum<<5)|prefixSlice)\n}\n\ntype (\n\tnamedInt1 int\n\tnamedInt2 int\n\tnamedInt3 int\n)\n\n// Pseudo call that is being checked by the code in reflect_test.go.\n// After reflect lowering, the type code as part of the interface should match\n// the asserted type code.\nfunc assertType(itf interface{}, assertedTypeCode uintptr)\n"
  },
  {
    "path": "transform/testdata/stacksize.ll",
    "content": "target datalayout = \"e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64\"\ntarget triple = \"armv7m-none-eabi\"\n\ndeclare i32 @\"internal/task.getGoroutineStackSize\"(i32, ptr, ptr)\n\ndeclare void @\"runtime.run$1$gowrapper\"(ptr)\n\ndeclare void @\"internal/task.start\"(i32, ptr, i32)\n\ndefine void @Reset_Handler() {\nentry:\n  %stacksize = call i32 @\"internal/task.getGoroutineStackSize\"(i32 ptrtoint (ptr @\"runtime.run$1$gowrapper\" to i32), ptr undef, ptr undef)\n  call void @\"internal/task.start\"(i32 ptrtoint (ptr @\"runtime.run$1$gowrapper\" to i32), ptr undef, i32 %stacksize)\n  ret void\n}\n"
  },
  {
    "path": "transform/testdata/stacksize.out.ll",
    "content": "target datalayout = \"e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64\"\ntarget triple = \"armv7m-none-eabi\"\n\n@\"internal/task.stackSizes\" = global [1 x i32] [i32 1024], section \".tinygo_stacksizes\", align 4\n@llvm.used = appending global [2 x ptr] [ptr @\"internal/task.stackSizes\", ptr @\"runtime.run$1$gowrapper\"]\n\ndeclare i32 @\"internal/task.getGoroutineStackSize\"(i32, ptr, ptr)\n\ndeclare void @\"runtime.run$1$gowrapper\"(ptr)\n\ndeclare void @\"internal/task.start\"(i32, ptr, i32)\n\ndefine void @Reset_Handler() {\nentry:\n  %stacksize1 = load i32, ptr @\"internal/task.stackSizes\", align 4\n  call void @\"internal/task.start\"(i32 ptrtoint (ptr @\"runtime.run$1$gowrapper\" to i32), ptr undef, i32 %stacksize1)\n  ret void\n}\n"
  },
  {
    "path": "transform/testdata/stringequal.ll",
    "content": "target datalayout = \"e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64\"\ntarget triple = \"armv7m-none-eabi\"\n\n@zeroString = constant [0 x i8] zeroinitializer\n\ndeclare i1 @runtime.stringEqual(ptr, i32, ptr, i32, ptr)\n\ndefine i1 @main.stringCompareEqualConstantZero(ptr %s1.data, i32 %s1.len, ptr %context) {\nentry:\n  %0 = call i1 @runtime.stringEqual(ptr %s1.data, i32 %s1.len, ptr @zeroString, i32 0, ptr undef)\n  ret i1 %0\n}\n\ndefine i1 @main.stringCompareUnequalConstantZero(ptr %s1.data, i32 %s1.len, ptr %context) {\nentry:\n  %0 = call i1 @runtime.stringEqual(ptr %s1.data, i32 %s1.len, ptr @zeroString, i32 0, ptr undef)\n  %1 = xor i1 %0, true\n  ret i1 %1\n}\n"
  },
  {
    "path": "transform/testdata/stringequal.out.ll",
    "content": "target datalayout = \"e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64\"\ntarget triple = \"armv7m-none-eabi\"\n\n@zeroString = constant [0 x i8] zeroinitializer\n\ndeclare i1 @runtime.stringEqual(ptr, i32, ptr, i32, ptr)\n\ndefine i1 @main.stringCompareEqualConstantZero(ptr %s1.data, i32 %s1.len, ptr %context) {\nentry:\n  %0 = icmp eq i32 %s1.len, 0\n  ret i1 %0\n}\n\ndefine i1 @main.stringCompareUnequalConstantZero(ptr %s1.data, i32 %s1.len, ptr %context) {\nentry:\n  %0 = icmp eq i32 %s1.len, 0\n  %1 = xor i1 %0, true\n  ret i1 %1\n}\n"
  },
  {
    "path": "transform/testdata/stringtobytes.ll",
    "content": "target datalayout = \"e-m:e-i64:64-f80:128-n8:16:32:64-S128\"\ntarget triple = \"x86_64--linux\"\n\n@str = constant [6 x i8] c\"foobar\"\n\ndeclare { ptr, i64, i64 } @runtime.stringToBytes(ptr, i64)\n\ndeclare void @printByte(i8)\n\ndeclare void @printSlice(ptr nocapture readonly, i64, i64)\n\ndeclare void @writeToSlice(ptr nocapture, i64, i64)\n\n; Test that runtime.stringToBytes can be fully optimized away.\ndefine void @testReadOnly() {\nentry:\n  %0 = call fastcc { ptr, i64, i64 } @runtime.stringToBytes(ptr @str, i64 6)\n  %1 = extractvalue { ptr, i64, i64 } %0, 0\n  %2 = extractvalue { ptr, i64, i64 } %0, 1\n  %3 = extractvalue { ptr, i64, i64 } %0, 2\n  call fastcc void @printSlice(ptr %1, i64 %2, i64 %3)\n\n  ; print(slice[0])\n  %indexaddr.ptr1 = extractvalue { ptr, i64, i64 } %0, 0\n  %4 = getelementptr inbounds i8, ptr %indexaddr.ptr1, i64 0\n  %5 = load i8, ptr %4, align 1\n  call fastcc void @printByte(i8 %5)\n  ret void\n}\n\n; Test that even though the slice is written to, some values can be propagated.\ndefine void @testReadWrite() {\nentry:\n  %0 = call fastcc { ptr, i64, i64 } @runtime.stringToBytes(ptr @str, i64 6)\n  %1 = extractvalue { ptr, i64, i64 } %0, 0\n  %2 = extractvalue { ptr, i64, i64 } %0, 1\n  %3 = extractvalue { ptr, i64, i64 } %0, 2\n  call fastcc void @writeToSlice(ptr %1, i64 %2, i64 %3)\n  ret void\n}\n\n; Test that pointer values are never propagated if there is even a single write\n; to the pointer value (but len/cap values still can be).\ndefine void @testReadSome() {\nentry:\n  %s = call fastcc { ptr, i64, i64 } @runtime.stringToBytes(ptr @str, i64 6)\n  %s.ptr = extractvalue { ptr, i64, i64 } %s, 0\n  %s.len = extractvalue { ptr, i64, i64 } %s, 1\n  %s.cap = extractvalue { ptr, i64, i64 } %s, 2\n  call fastcc void @writeToSlice(ptr %s.ptr, i64 %s.len, i64 %s.cap)\n  %s.ptr2 = extractvalue { ptr, i64, i64 } %s, 0\n  %s.len2 = extractvalue { ptr, i64, i64 } %s, 1\n  %s.cap2 = extractvalue { ptr, i64, i64 } %s, 2\n  call fastcc void @printSlice(ptr %s.ptr2, i64 %s.len2, i64 %s.cap2)\n  ret void\n}\n"
  },
  {
    "path": "transform/testdata/stringtobytes.out.ll",
    "content": "target datalayout = \"e-m:e-i64:64-f80:128-n8:16:32:64-S128\"\ntarget triple = \"x86_64--linux\"\n\n@str = constant [6 x i8] c\"foobar\"\n\ndeclare { ptr, i64, i64 } @runtime.stringToBytes(ptr, i64)\n\ndeclare void @printByte(i8)\n\ndeclare void @printSlice(ptr nocapture readonly, i64, i64)\n\ndeclare void @writeToSlice(ptr nocapture, i64, i64)\n\ndefine void @testReadOnly() {\nentry:\n  call fastcc void @printSlice(ptr @str, i64 6, i64 6)\n  %0 = getelementptr inbounds i8, ptr @str, i64 0\n  %1 = load i8, ptr %0, align 1\n  call fastcc void @printByte(i8 %1)\n  ret void\n}\n\ndefine void @testReadWrite() {\nentry:\n  %0 = call fastcc { ptr, i64, i64 } @runtime.stringToBytes(ptr @str, i64 6)\n  %1 = extractvalue { ptr, i64, i64 } %0, 0\n  call fastcc void @writeToSlice(ptr %1, i64 6, i64 6)\n  ret void\n}\n\ndefine void @testReadSome() {\nentry:\n  %s = call fastcc { ptr, i64, i64 } @runtime.stringToBytes(ptr @str, i64 6)\n  %s.ptr = extractvalue { ptr, i64, i64 } %s, 0\n  call fastcc void @writeToSlice(ptr %s.ptr, i64 6, i64 6)\n  %s.ptr2 = extractvalue { ptr, i64, i64 } %s, 0\n  call fastcc void @printSlice(ptr %s.ptr2, i64 6, i64 6)\n  ret void\n}\n"
  },
  {
    "path": "transform/transform.go",
    "content": "// Package transform contains transformation passes for the TinyGo compiler.\n// These transformation passes may be optimization passes or lowering passes.\n//\n// Optimization passes transform the IR in such a way that they increase the\n// performance of the generated code and/or help the LLVM optimizer better do\n// its job by simplifying the IR. This usually means that certain\n// TinyGo-specific runtime calls are removed or replaced with something simpler\n// if that is a valid operation.\n//\n// Lowering passes are usually required to run. One example is the interface\n// lowering pass, which replaces stub runtime calls to get an interface method\n// with the method implementation (either a direct call or a thunk).\npackage transform\n\nimport (\n\t\"github.com/tinygo-org/tinygo/compileopts\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// AddStandardAttributes is a helper function to add standard function\n// attributes to a function. For example, it adds optsize when requested from\n// the -opt= compiler flag.\nfunc AddStandardAttributes(fn llvm.Value, config *compileopts.Config) {\n\tctx := fn.Type().Context()\n\t_, _, sizeLevel := config.OptLevel()\n\tif sizeLevel >= 1 {\n\t\tfn.AddFunctionAttr(ctx.CreateEnumAttribute(llvm.AttributeKindID(\"optsize\"), 0))\n\t}\n\tif sizeLevel >= 2 {\n\t\tfn.AddFunctionAttr(ctx.CreateEnumAttribute(llvm.AttributeKindID(\"minsize\"), 0))\n\t}\n\tif config.CPU() != \"\" {\n\t\tfn.AddFunctionAttr(ctx.CreateStringAttribute(\"target-cpu\", config.CPU()))\n\t}\n\tif config.Features() != \"\" {\n\t\tfn.AddFunctionAttr(ctx.CreateStringAttribute(\"target-features\", config.Features()))\n\t}\n}\n"
  },
  {
    "path": "transform/transform_test.go",
    "content": "package transform_test\n\n// This file defines some helper functions for testing transforms.\n\nimport (\n\t\"flag\"\n\t\"go/token\"\n\t\"go/types\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/tinygo-org/tinygo/compileopts\"\n\t\"github.com/tinygo-org/tinygo/compiler\"\n\t\"github.com/tinygo-org/tinygo/loader\"\n\t\"tinygo.org/x/go-llvm\"\n)\n\nvar update = flag.Bool(\"update\", false, \"update transform package tests\")\n\nvar defaultTestConfig = &compileopts.Config{\n\tTarget:  &compileopts.TargetSpec{},\n\tOptions: &compileopts.Options{Opt: \"2\"},\n}\n\n// testTransform runs a transformation pass on an input file (pathPrefix+\".ll\")\n// and checks whether it matches the expected output (pathPrefix+\".out.ll\"). The\n// output is compared with a fuzzy match that ignores some irrelevant lines such\n// as empty lines.\nfunc testTransform(t *testing.T, pathPrefix string, transform func(mod llvm.Module)) {\n\t// Read the input IR.\n\tctx := llvm.NewContext()\n\tdefer ctx.Dispose()\n\tbuf, err := llvm.NewMemoryBufferFromFile(pathPrefix + \".ll\")\n\tos.Stat(pathPrefix + \".ll\") // make sure this file is tracked by `go test` caching\n\tif err != nil {\n\t\tt.Fatalf(\"could not read file %s: %v\", pathPrefix+\".ll\", err)\n\t}\n\tmod, err := ctx.ParseIR(buf)\n\tif err != nil {\n\t\tt.Fatalf(\"could not load module:\\n%v\", err)\n\t}\n\tdefer mod.Dispose()\n\n\t// Perform the transform.\n\ttransform(mod)\n\n\t// Check for any incorrect IR.\n\terr = llvm.VerifyModule(mod, llvm.PrintMessageAction)\n\tif err != nil {\n\t\tt.Fatal(\"IR verification failed\")\n\t}\n\n\t// Get the output from the test and filter some irrelevant lines.\n\tactual := mod.String()\n\tactual = actual[strings.Index(actual, \"\\ntarget datalayout = \")+1:]\n\n\tif *update {\n\t\terr := os.WriteFile(pathPrefix+\".out.ll\", []byte(actual), 0666)\n\t\tif err != nil {\n\t\t\tt.Error(\"failed to write out new output:\", err)\n\t\t}\n\t} else {\n\t\t// Read the expected output IR.\n\t\tout, err := os.ReadFile(pathPrefix + \".out.ll\")\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"could not read output file %s: %v\", pathPrefix+\".out.ll\", err)\n\t\t}\n\n\t\t// See whether the transform output matches with the expected output IR.\n\t\texpected := string(out)\n\t\tif !fuzzyEqualIR(expected, actual) {\n\t\t\tt.Logf(\"output does not match expected output:\\n%s\", actual)\n\t\t\tt.Fail()\n\t\t}\n\t}\n}\n\n// fuzzyEqualIR returns true if the two LLVM IR strings passed in are roughly\n// equal. That means, only relevant lines are compared (excluding comments\n// etc.).\nfunc fuzzyEqualIR(s1, s2 string) bool {\n\tlines1 := filterIrrelevantIRLines(strings.Split(s1, \"\\n\"))\n\tlines2 := filterIrrelevantIRLines(strings.Split(s2, \"\\n\"))\n\tif len(lines1) != len(lines2) {\n\t\treturn false\n\t}\n\tfor i, line1 := range lines1 {\n\t\tline2 := lines2[i]\n\t\tif line1 != line2 {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\n// filterIrrelevantIRLines removes lines from the input slice of strings that\n// are not relevant in comparing IR. For example, empty lines and comments are\n// stripped out.\nfunc filterIrrelevantIRLines(lines []string) []string {\n\tvar out []string\n\tfor _, line := range lines {\n\t\tline = strings.Split(line, \";\")[0]    // strip out comments/info\n\t\tline = strings.TrimRight(line, \"\\r \") // drop '\\r' on Windows and remove trailing spaces from comments\n\t\tif line == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tif strings.HasPrefix(line, \"source_filename = \") {\n\t\t\tcontinue\n\t\t}\n\t\tout = append(out, line)\n\t}\n\treturn out\n}\n\n// compileGoFileForTesting compiles the given Go file to run tests against.\n// Only the given Go file is compiled (no dependencies) and no optimizations are\n// run.\n// If there are any errors, they are reported via the *testing.T instance.\nfunc compileGoFileForTesting(t *testing.T, filename string) llvm.Module {\n\ttarget, err := compileopts.LoadTarget(&compileopts.Options{GOOS: \"linux\", GOARCH: \"386\"})\n\tif err != nil {\n\t\tt.Fatal(\"failed to load target:\", err)\n\t}\n\tconfig := &compileopts.Config{\n\t\tOptions: &compileopts.Options{},\n\t\tTarget:  target,\n\t}\n\tcompilerConfig := &compiler.Config{\n\t\tTriple:             config.Triple(),\n\t\tGOOS:               config.GOOS(),\n\t\tGOARCH:             config.GOARCH(),\n\t\tCodeModel:          config.CodeModel(),\n\t\tRelocationModel:    config.RelocationModel(),\n\t\tScheduler:          config.Scheduler(),\n\t\tAutomaticStackSize: config.AutomaticStackSize(),\n\t\tDebug:              true,\n\t\tPanicStrategy:      config.PanicStrategy(),\n\t}\n\tmachine, err := compiler.NewTargetMachine(compilerConfig)\n\tif err != nil {\n\t\tt.Fatal(\"failed to create target machine:\", err)\n\t}\n\tdefer machine.Dispose()\n\n\t// Load entire program AST into memory.\n\tlprogram, err := loader.Load(config, filename, types.Config{\n\t\tSizes: compiler.Sizes(machine),\n\t})\n\tif err != nil {\n\t\tt.Fatal(\"failed to create target machine:\", err)\n\t}\n\terr = lprogram.Parse()\n\tif err != nil {\n\t\tt.Fatal(\"could not parse\", err)\n\t}\n\n\t// Compile AST to IR.\n\tprogram := lprogram.LoadSSA()\n\tpkg := lprogram.MainPkg()\n\tmod, errs := compiler.CompilePackage(filename, pkg, program.Package(pkg.Pkg), machine, compilerConfig, false)\n\tif errs != nil {\n\t\tfor _, err := range errs {\n\t\t\tt.Error(err)\n\t\t}\n\t\tt.FailNow()\n\t}\n\treturn mod\n}\n\n// getPosition returns the position information for the given value, as far as\n// it is available.\nfunc getPosition(val llvm.Value) token.Position {\n\tif !val.IsAInstruction().IsNil() {\n\t\tloc := val.InstructionDebugLoc()\n\t\tif loc.IsNil() {\n\t\t\treturn token.Position{}\n\t\t}\n\t\tfile := loc.LocationScope().ScopeFile()\n\t\treturn token.Position{\n\t\t\tFilename: filepath.Join(file.FileDirectory(), file.FileFilename()),\n\t\t\tLine:     int(loc.LocationLine()),\n\t\t\tColumn:   int(loc.LocationColumn()),\n\t\t}\n\t} else if !val.IsAFunction().IsNil() {\n\t\tloc := val.Subprogram()\n\t\tif loc.IsNil() {\n\t\t\treturn token.Position{}\n\t\t}\n\t\tfile := loc.ScopeFile()\n\t\treturn token.Position{\n\t\t\tFilename: filepath.Join(file.FileDirectory(), file.FileFilename()),\n\t\t\tLine:     int(loc.SubprogramLine()),\n\t\t}\n\t} else {\n\t\treturn token.Position{}\n\t}\n}\n"
  },
  {
    "path": "transform/util.go",
    "content": "package transform\n\n// This file contains utilities used across transforms.\n\nimport (\n\t\"tinygo.org/x/go-llvm\"\n)\n\n// Check whether all uses of this param as parameter to the call have the given\n// flag. In most cases, there will only be one use but a function could take the\n// same parameter twice, in which case both must have the flag.\n// A flag can be any enum flag, like \"readonly\".\nfunc hasFlag(call, param llvm.Value, kind string) bool {\n\tfn := call.CalledValue()\n\tif fn.IsAFunction().IsNil() {\n\t\t// This is not a function but something else, like a function pointer.\n\t\treturn false\n\t}\n\tkindID := llvm.AttributeKindID(kind)\n\tfor i := 0; i < fn.ParamsCount(); i++ {\n\t\tif call.Operand(i) != param {\n\t\t\t// This is not the parameter we're checking.\n\t\t\tcontinue\n\t\t}\n\t\tindex := i + 1 // param attributes start at 1\n\t\tattr := fn.GetEnumAttributeAtIndex(index, kindID)\n\t\tif attr.IsNil() {\n\t\t\t// At least one parameter doesn't have the flag (there may be\n\t\t\t// multiple).\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// isReadOnly returns true if the given value (which must be of pointer type) is\n// never stored to, and false if this cannot be proven.\nfunc isReadOnly(value llvm.Value) bool {\n\tuses := getUses(value)\n\tfor _, use := range uses {\n\t\tswitch {\n\t\tcase !use.IsAGetElementPtrInst().IsNil():\n\t\t\tif !isReadOnly(use) {\n\t\t\t\treturn false\n\t\t\t}\n\t\tcase !use.IsACallInst().IsNil():\n\t\t\tif !hasFlag(use, value, \"readonly\") {\n\t\t\t\treturn false\n\t\t\t}\n\t\tcase !use.IsALoadInst().IsNil():\n\t\t\t// Loads are read-only.\n\t\tdefault:\n\t\t\t// Unknown instruction, might not be readonly.\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n"
  },
  {
    "path": "util_unix.go",
    "content": "//go:build !windows\n\npackage main\n\n// This file contains utility functions for Unix-like systems (e.g. Linux).\n\nimport (\n\t\"os/exec\"\n\t\"syscall\"\n)\n\n// setCommandAsDaemon makes sure this command does not receive signals sent to\n// the parent.\nfunc setCommandAsDaemon(daemon *exec.Cmd) {\n\t// https://stackoverflow.com/a/35435038/559350\n\tdaemon.SysProcAttr = &syscall.SysProcAttr{\n\t\tSetpgid: true,\n\t\tPgid:    0,\n\t}\n}\n"
  },
  {
    "path": "util_windows.go",
    "content": "package main\n\n// This file contains utility functions for Windows.\n\nimport (\n\t\"os/exec\"\n\t\"syscall\"\n\n\t\"golang.org/x/sys/windows\"\n)\n\n// setCommandAsDaemon makes sure this command does not receive signals sent to\n// the parent.\nfunc setCommandAsDaemon(daemon *exec.Cmd) {\n\tdaemon.SysProcAttr = &syscall.SysProcAttr{\n\t\tCreationFlags: windows.DETACHED_PROCESS,\n\t}\n}\n"
  }
]